/*-------------------------------------------------------------------- * The MB-system: fbtinfo.c 7/22/2014 * $Id: $ * * Copyright (c) 2014-2014 by * David W. Caress (caress@mbari.org) * Monterey Bay Aquarium Research Institute * Moss Landing, CA 95039 * and Dale N. Chayes (dale@ldeo.columbia.edu) * Lamont-Doherty Earth Observatory * Palisades, NY 10964 * * This file contains source code modified from source files * distributed as part of MB-System. In contrast to the GPL-licensed * MB-System distributions, the code contained here is licensed * under the Lesser GNU Public license, or LGPL. This means that * compiled versions of these functions, or functions derived from * modifications to this code, may be linked with commercial * applications without imposing any restriction on the sale and * and distribution of those applications. * * The full LGPL text may be accessed at http://www.gnu.org/ * * The release of this code under the LGPL does not change the * the GPL licensing of any code contained in the regular * MB-System distribution. * * The source code provided here does not come with any warranties, * nor is it guarenteed to work on your computer or to do * anything useful. The user assumes full responsibility for * the use of this software. In particular, David W. Caress, * Dale N. Chayes, the Lamont-Doherty Earth Observatory of * Columbia University, the Monterey Bay Aquarium Research Institute, * or any other individuals or organizations involved in the * design and maintenance of the MB-System software package * and derived distributions are NOT responsible for any * damage that may follow from correct or incorrect use of this * source code. Moreover, it should be noted that the source * code provided here has NOT been tested after modification * from the related functions that are part of MB-System. * * To access MB-System documentation or source code releases see: * http://www.mbari.org/data/mbsystem * http://www.ldeo.columbia.edu/MB-System * *-------------------------------------------------------------------- * * The program fbtinfo reads an MB-System "fbt" (fast bathymetry) file * and outputs some basic statistics to stdout. * This is intended as an example of using the LGPL licensed mblgpl_fbt * library to read swath bathymetry stored in "fbt" files as part of * the MB-System processing environment. * * The header file mblgpl_fbt.h contains structure and macro definitions * required for this source to compile. * * Author: D. W. Caress * Date: July 22, 2014 * Revised: November 30, 2014 * *-------------------------------------------------------------------- */ /* standard include files */ #include #include #include #include #include /* MBLGPL include files */ #include "mblgpl_fbt.h" static char version_id[] = "$Id: $"; /*--------------------------------------------------------------------*/ int main (int argc, char **argv) { char program_name[] = "fbtinfo"; char help_message[] = "The program fbtinfo reads an MB-System fbt (fast bathymetry) file" "and outputs some basic statistics to stdout."; char usage_message[] = "fbtinfo -Ifbtfile [-V -H]"; extern char *optarg; int errflg = 0; int c; int help = 0; int flag = 0; /* MBLGPL status variables */ int status = MBLGPL_SUCCESS; int verbose = 0; int error = MBLGPL_ERROR_NO_ERROR; /* MBLGPL read parameters */ char fbtfile[1024]; FILE *fp = NULL; FILE *stream = NULL; struct mblgpl_fbt_struct *ping; int printcomments = MBLGPL_NO; int done; int lonflip = 0; int lonflip_set = MBLGPL_NO; int time_i[7]; int time_j[5]; double mtodeglon; double mtodeglat; double x, y; double last_longitude = 0.0; double last_latitude = 0.0; double ss_scale; double bath; double ss; /* limit variables */ int beams_bath_max = 0; int beams_amp_max = 0; int pixels_ss_max = 0; double lonmin = 0.0; double lonmax = 0.0; double latmin = 0.0; double latmax = 0.0; double sdpmin = 0.0; double sdpmax = 0.0; double altmin = 0.0; double altmax = 0.0; double bathmin = 0.0; double bathmax = 0.0; double ampmin = 0.0; double ampmax = 0.0; double ssmin = 0.0; double ssmax = 0.0; double bathbeg = 0.0; double bathend = 0.0; double lonbeg = 0.0; double latbeg = 0.0; double lonend = 0.0; double latend = 0.0; double spdbeg = 0.0; double hdgbeg = 0.0; double sdpbeg = 0.0; double altbeg = 0.0; double spdend = 0.0; double hdgend = 0.0; double sdpend = 0.0; double altend = 0.0; double timbeg = 0.0; double timend = 0.0; int timbeg_i[7]; int timend_i[7]; int timbeg_j[5]; int timend_j[5]; double distot = 0.0; double timtot = 0.0; double spdavg = 0.0; int irec = 0; int ntdbeams = 0; int ngdbeams = 0; int nzdbeams = 0; int nfdbeams = 0; int ntabeams = 0; int ngabeams = 0; int nzabeams = 0; int nfabeams = 0; int ntsbeams = 0; int ngsbeams = 0; int nzsbeams = 0; int nfsbeams = 0; double ngd_percent; double nzd_percent; double nfd_percent; double nga_percent; double nza_percent; double nfa_percent; double ngs_percent; double nzs_percent; double nfs_percent; int beginnav = MBLGPL_NO; int beginsdp = MBLGPL_NO; int beginalt = MBLGPL_NO; int beginbath = MBLGPL_NO; int beginamp = MBLGPL_NO; int beginss = MBLGPL_NO; int i; /* set default input to stdin */ memset(fbtfile, 0, sizeof(fbtfile)); /* process argument list */ while ((c = getopt(argc, argv, "VvHhCcI:i:")) != -1) switch (c) { case 'C': case 'c': printcomments = MBLGPL_YES; break; case 'H': case 'h': help++; break; case 'I': case 'i': sscanf (optarg,"%s", fbtfile); flag++; break; case 'V': case 'v': verbose++; break; case '?': errflg++; } /* set output stream */ if (verbose <= 1) stream = stdout; else stream = stderr; /* if error flagged then print it and exit */ if (errflg) { fprintf(stream,"usage: %s\n", usage_message); fprintf(stream,"\nProgram <%s> Terminated\n", program_name); error = MBLGPL_ERROR_BAD_USAGE; exit(error); } /* print starting message */ if (verbose == 1 || help) { fprintf(stream,"\nProgram %s\n",program_name); fprintf(stream,"Version %s\n",version_id); } /* print starting debug statements */ if (verbose >= 2) { fprintf(stream,"\ndbg2 Program <%s>\n",program_name); fprintf(stream,"dbg2 Version %s\n",version_id); fprintf(stream,"dbg2 Control Parameters:\n"); fprintf(stream,"dbg2 verbose: %d\n",verbose); fprintf(stream,"dbg2 help: %d\n",help); fprintf(stream,"dbg2 file: %s\n",fbtfile); } /* if help desired then print it and exit */ if (help) { fprintf(stream,"\n%s\n",help_message); fprintf(stream,"\nusage: %s\n", usage_message); exit(error); } /* set program status */ status = MBLGPL_SUCCESS; /* allocate and initialize the storage for fbt swath data */ status = mblgpl_fbt_alloc(verbose, &ping, &error); if (status != MBLGPL_SUCCESS) { fprintf(stream, "Error allocating memory\n"); fprintf(stream,"\nProgram <%s> Terminated\n", program_name); exit(error); } /* open the fbt file for reading */ if ((fp = fopen(fbtfile, "r")) == NULL) { fprintf(stream, "Error opening fbt file: %s\n", fbtfile); fprintf(stream,"\nProgram <%s> Terminated\n", program_name); exit(error); } /* prepare to print out comments */ if (printcomments == MBLGPL_YES) fprintf(stream, "\nComments:\n"); /* loop over reading through the file */ done = MBLGPL_NO; while (done == MBLGPL_NO) { /* read the next ping */ status = mblgpl_read_fbt(verbose, fp, ping, &error); /* process a successful read of comment */ if (status == MBLGPL_YES && ping->kind == MBLGPL_DATA_COMMENT) { if (printcomments == MBLGPL_YES) fprintf(stream, "%s\n", ping->comment); } /* reset a nonfatal error */ else if (error < 0) { error = MBLGPL_ERROR_NO_ERROR; status = MBLGPL_SUCCESS; } /* done when end of file reached */ else if (error > 0) { done = MBLGPL_YES; error = MBLGPL_ERROR_NO_ERROR; status = MBLGPL_SUCCESS; } /* process a successful read of survey data */ else if (status == MBLGPL_YES && ping->kind == MBLGPL_DATA_DATA) { /* increment counters */ irec++; // fprintf(stream, "ping: time_d:%f nav:%f %f %f %f number of beams:%d\n", // ping->time_d, ping->longitude, ping->latitude, ping->sonardepth, // ping->heading, ping->beams_bath); /* take note of min and maxes */ if (error == MBLGPL_ERROR_NO_ERROR) { /* update data counts */ ntdbeams += ping->beams_bath; ntabeams += ping->beams_amp; ntsbeams += ping->pixels_ss; /* get time_i and time_j from time_d */ mblgpl_get_date(verbose, ping->time_d, time_i); mblgpl_get_jtime(verbose, time_i, time_j); /* set lonflip if needed */ if (lonflip_set == MBLGPL_NO && (ping->longitude != 0.0 || ping->latitude != 0.0)) { lonflip_set = MBLGPL_YES; if (ping->longitude < -270.0) lonflip = 0; else if (ping->longitude >= -270.0 && ping->longitude < -90.0) lonflip = -1; else if (ping->longitude >= -90.0 && ping->longitude < 90.0) lonflip = 0; else if (ping->longitude >= 90.0 && ping->longitude < 270.0) lonflip = 1; else if (ping->longitude >= 270.0) lonflip = 0; } /* apply lonflip to navigation */ if (lonflip_set == MBLGPL_YES) { if (lonflip == -1) { if (ping->longitude > 0.0) ping->longitude -= 360.0; } else if (lonflip == 1) { if (ping->longitude < 0.0) ping->longitude += 360.0; } else if (lonflip == 0) { if (ping->longitude < -180.0) ping->longitude += 360.0; if (ping->longitude > 180.0) ping->longitude -= 360.0; } } /* calculate distance */ if (irec > 1) { mblgpl_coor_scale(verbose, ping->latitude, &mtodeglon, &mtodeglat); x = (ping->longitude - last_longitude) / mtodeglon; y = (ping->latitude - last_latitude) / mtodeglat; distot += sqrt(x * x + y * y) / 1000.0; } last_longitude = ping->longitude; last_latitude = ping->latitude; /* get max numbers of beams and pixels */ beams_bath_max = MAX(beams_bath_max, ping->beams_bath); beams_amp_max = MAX(beams_amp_max, ping->beams_amp); pixels_ss_max = MAX(pixels_ss_max, ping->pixels_ss); /* get beginning values */ if (irec == 1) { if (ping->beams_bath > 0) { if (mblgpl_beam_ok(ping->beamflag[ping->beams_bath/2])) bathbeg = ping->bath[ping->beams_bath/2]; else bathbeg = ping->altitude + ping->sonardepth; } lonbeg = ping->longitude; latbeg = ping->latitude; timbeg = ping->time_d; for (i=0;i<7;i++) timbeg_i[i] = time_i[i]; spdbeg = ping->speed; hdgbeg = ping->heading; sdpbeg = ping->sonardepth; altbeg = ping->altitude; } else if (lonbeg == 0.0 && latbeg == 0.0 && ping->longitude != 0.0 && ping->latitude != 0.0) { lonbeg = ping->longitude; if (ping->beams_bath > 0) { if (mblgpl_beam_ok(ping->beamflag[ping->beams_bath/2])) bathbeg = ping->bath[ping->beams_bath/2]; else bathbeg = ping->altitude + ping->sonardepth; } latbeg = ping->latitude; if (spdbeg == 0.0 && ping->speed != 0.0) spdbeg = ping->speed; if (hdgbeg == 0.0 && ping->heading != 0.0) hdgbeg = ping->heading; if (sdpbeg == 0.0 && ping->sonardepth != 0.0) sdpbeg = ping->sonardepth; if (altbeg == 0.0 && ping->altitude != 0.0) altbeg = ping->altitude; } /* reset ending values each time */ if (ping->beams_bath > 0) { if (mblgpl_beam_ok(ping->beamflag[ping->beams_bath/2])) bathend = ping->bath[ping->beams_bath/2]; else bathend = ping->altitude + ping->sonardepth; } lonend = ping->longitude; latend = ping->latitude; spdend = ping->speed; hdgend = ping->heading; sdpend = ping->sonardepth; altend = ping->altitude; timend = ping->time_d; for (i=0;i<7;i++) timend_i[i] = time_i[i]; /* get starting mins and maxs */ if (beginnav == MBLGPL_NO) { lonmin = ping->longitude; lonmax = ping->longitude; latmin = ping->latitude; latmax = ping->latitude; beginnav = MBLGPL_YES; } if (beginsdp == MBLGPL_NO && ping->sonardepth > 0.0) { sdpmin = ping->sonardepth; sdpmax = ping->sonardepth; beginsdp = MBLGPL_YES; } if (beginalt == MBLGPL_NO && ping->altitude > 0.0) { altmin = ping->altitude; altmax = ping->altitude; beginalt = MBLGPL_YES; } if (beginbath == MBLGPL_NO && ping->beams_bath > 0) for (i=0;ibeams_bath;i++) if (mblgpl_beam_ok(ping->beamflag[i])) { bath = ping->depth_scale * ping->bath[i] + ping->sonardepth; bathmin = bath; bathmax = bath; beginbath = MBLGPL_YES; } if (beginamp == MBLGPL_NO && ping->beams_amp > 0) for (i=0;ibeams_amp;i++) if (mblgpl_beam_ok(ping->beamflag[i])) { ampmin = ping->amp[i]; ampmax = ping->amp[i]; beginamp = MBLGPL_YES; } ss_scale = pow(2.0, (double)(ping->ss_scalepower)); if (beginss == MBLGPL_NO && ping->pixels_ss > 0) for (i=0;ipixels_ss;i++) if (ping->ss[i] > MBLGPL_SIDESCAN_NULL) { ss = ss_scale * ping->ss[i]; ssmin = ss; ssmax = ss; beginss = MBLGPL_YES; } /* get mins and maxs */ if (beginnav == MBLGPL_YES) { lonmin = MIN(lonmin, ping->longitude); lonmax = MAX(lonmax, ping->longitude); latmin = MIN(latmin, ping->latitude); latmax = MAX(latmax, ping->latitude); } if (beginsdp == MBLGPL_YES) { sdpmin = MIN(sdpmin, ping->sonardepth); sdpmax = MAX(sdpmax, ping->sonardepth); } if (beginalt == MBLGPL_YES) { altmin = MIN(altmin, ping->altitude); altmax = MAX(altmax, ping->altitude); } for (i=0;ibeams_bath;i++) { if (mblgpl_beam_ok(ping->beamflag[i])) { bath = ping->depth_scale * ping->bath[i] + ping->sonardepth; bathmin = MIN(bathmin, bath); bathmax = MAX(bathmax, bath); ngdbeams++; } else if (ping->beamflag[i] == MBLGPL_FLAG_NULL) nzdbeams++; else nfdbeams++; } for (i=0;ibeams_amp;i++) { if (mblgpl_beam_ok(ping->beamflag[i])) { ampmin = MIN(ampmin, ping->amp[i]); ampmax = MAX(ampmax, ping->amp[i]); ngabeams++; } else if (ping->beamflag[i] == MBLGPL_FLAG_NULL) nzabeams++; else nfabeams++; } for (i=0;ipixels_ss;i++) { if (ping->ss[i] > MBLGPL_SIDESCAN_NULL) { ss = ss_scale * ping->ss[i]; ssmin = MIN(ssmin, ss); ssmax = MAX(ssmax, ss); ngsbeams++; } else if (ping->ss[i] == 0.0) nzsbeams++; else nfsbeams++; } } } /* end processing good survey ping */ } /* end reading loop */ /* calculate percentages of data */ if (ntdbeams > 0) { ngd_percent = 100.0*ngdbeams/ntdbeams; nzd_percent = 100.0*nzdbeams/ntdbeams; nfd_percent = 100.0*nfdbeams/ntdbeams; } else { ngd_percent = 0.0; nzd_percent = 0.0; nfd_percent = 0.0; } if (ntabeams > 0) { nga_percent = 100.0*ngabeams/ntabeams; nza_percent = 100.0*nzabeams/ntabeams; nfa_percent = 100.0*nfabeams/ntabeams; } else { nga_percent = 0.0; nza_percent = 0.0; nfa_percent = 0.0; } if (ntsbeams > 0) { ngs_percent = 100.0*ngsbeams/ntsbeams; nzs_percent = 100.0*nzsbeams/ntsbeams; nfs_percent = 100.0*nfsbeams/ntsbeams; } else { ngs_percent = 0.0; nzs_percent = 0.0; nfs_percent = 0.0; } /* now print out the results */ timtot = (timend - timbeg)/3600.0; if (timtot > 0.0) spdavg = distot/timtot; mblgpl_get_jtime(verbose,timbeg_i,timbeg_j); mblgpl_get_jtime(verbose,timend_i,timend_j); fprintf(stream,"\nMB-System fbt file: %s\n",fbtfile); fprintf(stream,"\nData Totals:\n"); fprintf(stream,"Number of Records: %8d\n",irec); fprintf(stream,"Bathymetry Data (%d beams):\n",beams_bath_max); fprintf(stream," Number of Beams: %8d\n", ntdbeams); fprintf(stream," Number of Good Beams: %8d %5.2f%%\n",ngdbeams, ngd_percent); fprintf(stream," Number of Zero Beams: %8d %5.2f%%\n",nzdbeams, nzd_percent); fprintf(stream," Number of Flagged Beams: %8d %5.2f%%\n",nfdbeams, nfd_percent); fprintf(stream,"Amplitude Data (%d beams):\n",beams_amp_max); fprintf(stream," Number of Beams: %8d\n",ntabeams); fprintf(stream," Number of Good Beams: %8d %5.2f%%\n",ngabeams, nga_percent); fprintf(stream," Number of Zero Beams: %8d %5.2f%%\n",nzabeams, nza_percent); fprintf(stream," Number of Flagged Beams: %8d %5.2f%%\n",nfabeams, nfa_percent); fprintf(stream,"Sidescan Data (%d pixels):\n",pixels_ss_max); fprintf(stream," Number of Pixels: %8d\n",ntsbeams); fprintf(stream," Number of Good Pixels: %8d %5.2f%%\n",ngsbeams, ngs_percent); fprintf(stream," Number of Zero Pixels: %8d %5.2f%%\n",nzsbeams, nzs_percent); fprintf(stream," Number of Flagged Pixels:%8d %5.2f%%\n",nfsbeams, nfs_percent); fprintf(stream,"\nNavigation Totals:\n"); fprintf(stream,"Total Time: %10.4f hours\n",timtot); fprintf(stream,"Total Track Length: %10.4f km\n",distot); fprintf(stream,"Average Speed: %10.4f km/hr (%7.4f knots)\n",spdavg,spdavg/1.85); fprintf(stream,"\nStart of Data:\n"); fprintf(stream,"Time: %2.2d %2.2d %4.4d %2.2d:%2.2d:%2.2d.%6.6d JD%d (%4.4d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2d.%6.6d)\n", timbeg_i[1],timbeg_i[2],timbeg_i[0],timbeg_i[3], timbeg_i[4],timbeg_i[5],timbeg_i[6],timbeg_j[1], timbeg_i[0],timbeg_i[1],timbeg_i[2],timbeg_i[3],timbeg_i[4],timbeg_i[5],timbeg_i[6]); fprintf(stream,"Lon: %15.9f Lat: %15.9f Depth: %10.4f meters\n",lonbeg,latbeg,bathbeg); fprintf(stream,"Speed: %7.4f km/hr (%7.4f knots) Heading:%9.4f degrees\n",spdbeg,spdbeg/1.85,hdgbeg); fprintf(stream,"Sonar Depth:%10.4f m Sonar Altitude:%10.4f m\n",sdpbeg,altbeg); fprintf(stream,"\nEnd of Data:\n"); fprintf(stream,"Time: %2.2d %2.2d %4.4d %2.2d:%2.2d:%2.2d.%6.6d JD%d (%4.4d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2d.%6.6d)\n", timend_i[1],timend_i[2],timend_i[0],timend_i[3], timend_i[4],timend_i[5],timend_i[6],timend_j[1], timend_i[0],timend_i[1],timend_i[2],timend_i[3],timend_i[4],timend_i[5],timend_i[6]); fprintf(stream,"Lon: %15.9f Lat: %15.9f Depth: %10.4f meters\n",lonend,latend,bathend); fprintf(stream,"Speed: %7.4f km/hr (%7.4f knots) Heading:%9.4f degrees\n", spdend,spdend/1.85,hdgend); fprintf(stream,"Sonar Depth:%10.4f m Sonar Altitude:%10.4f m\n", sdpend,altend); fprintf(stream,"\nLimits:\n"); fprintf(stream,"Minimum Longitude: %15.9f Maximum Longitude: %15.9f\n",lonmin,lonmax); fprintf(stream,"Minimum Latitude: %15.9f Maximum Latitude: %15.9f\n",latmin,latmax); fprintf(stream,"Minimum Sonar Depth: %10.4f Maximum Sonar Depth: %10.4f\n",sdpmin,sdpmax); fprintf(stream,"Minimum Altitude: %10.4f Maximum Altitude: %10.4f\n",altmin,altmax); if (ngdbeams > 0 || verbose >= 1) fprintf(stream,"Minimum Depth: %10.4f Maximum Depth: %10.4f\n", bathmin,bathmax); if (ngabeams > 0 || verbose >= 1) fprintf(stream,"Minimum Amplitude: %10.4f Maximum Amplitude: %10.4f\n", ampmin,ampmax); if (ngsbeams > 0 || verbose >= 1) fprintf(stream,"Minimum Sidescan: %10.4f Maximum Sidescan: %10.4f\n", ssmin,ssmax); /* deallocate the storage for fbt swath data */ status = mblgpl_fbt_deall(verbose, &ping, &error); if (status != MBLGPL_SUCCESS) { fprintf(stream, "Error deallocating memory\n"); fprintf(stream,"\nProgram <%s> Terminated\n", program_name); exit(error); } /* print output debug statements */ if (verbose >= 2) { fprintf(stream,"\ndbg2 Program <%s> completed\n", program_name); fprintf(stream,"dbg2 Ending status:\n"); fprintf(stream,"dbg2 status: %d\n",status); } /* end it all */ exit(error); } /*--------------------------------------------------------------------*/