//------------------------------------------------------------------------- // NavigationSyncer constructor using nav file and lev1 file to set up //------------------------------------------------------------------------- NavigationSyncer::NavigationSyncer(std::string navfilename, std::string lev1filename) { //Set to NULL here anyway just to be safe - they should all be none-null by the end of this function nscans=0; time=NULL; navfile=NULL; hdrsync=0; framerate=0; NOSYNCINHDR=-999; lev1firstscanmaxexpectedsize=30; //30 seconds if(navfilename.compare("NULL")!=0) { //Create a new Specim nav file object navfile=new SpecimFileChooser(navfilename); //Read in the nav file to get the time syncs navfile->Reader(); } //Need to read in the level1 file hdr info to get nscans BinFile bilin(lev1filename); //Get the number of scan lines nscans=StringToUINT(bilin.FromHeader("lines")); DEBUGPRINT("Number of scans: "<<nscans) //Get the NavSync timing from the hdr try { hdrsync=StringToUINT(TrimWhitespace(bilin.FromHeader("NavSync Timing",1,"true")))/1000.0; } catch(std::string e) { if(e.compare(0,bilin.MissingHeaderItemError().length(),bilin.MissingHeaderItemError())==0) { //Set to a value that means "no value in header" hdrsync=NOSYNCINHDR; } else { throw e; } } DEBUGPRINT("Sync from header:"<<hdrsync) //Get the acquisition date of the data acquisitiondate=bilin.FromHeader("acquisition date"); //Remove the start of the date string acquisitiondate=TrimWhitespace(acquisitiondate.substr(acquisitiondate.find_first_of(':')+1)); //Get the date format string for leap seconds dateformat=bilin.FromHeader("acquisition date"); size_t startofdateformat=dateformat.find_first_of("DATE(")+5; size_t lengthofdateformat=dateformat.find_first_of("):")-startofdateformat; dateformat=dateformat.substr(startofdateformat,lengthofdateformat); DEBUGPRINT("Date: "<<acquisitiondate) //Get the start and stop times from the header to use in case no sync messages //found in the specim nav file gpsstarttime=bilin.FromHeader("GPS Start Time"); gpsstarttime=RemoveAllBut(gpsstarttime,"1234567890.:"); gpsstarttime=TrimWhitespace(ReplaceAllWith(&gpsstarttime,':',' ')); gpsstoptime=bilin.FromHeader("GPS Stop Time"); gpsstoptime=RemoveAllBut(gpsstoptime,"1234567890.:"); gpsstoptime=TrimWhitespace(ReplaceAllWith(&gpsstoptime,':',' ')); //Get the frame rate from the hdr framerate=StringToDouble(bilin.FromHeader("fps")); DEBUGPRINT("Frame rate from header:"<<framerate) if((framerate <= 0)||(framerate>100000)) { throw "Frame rate (fps) in hdr file seems erroneous - will only process for frame rates >0 and <100000."; } //Get the Processed_crop_start from the header file - this tells us if //nav for the full line or crop of the line is required std::string cropstart=bilin.FromHeader("y start"); if(cropstart.compare("")==0) { Logger::Warning("No y start found in level 1 header, if data was cropped in previous stages navigation may be wrongly synced."); //Set the time offset to 0 croptimeoffset=0; } else { //Convert to a double croptimeoffset=StringToDouble(cropstart); //Get the number of dropped scans that occurred in the crop prior to y start (if y start = 0 so will this) std::string prevdropscans=bilin.FromHeader("dropped scans before y start"); if(prevdropscans.compare("")==0) { Logger::Warning("No 'dropped scans before y start' found in level 1 header, if y start is non-zero navigation may be wrongly synced."); //Set the time offset to 0 prevdropscans="0"; } double previousdroppedscans=StringToDouble(prevdropscans); //Convert the sum of the frames (cropstart and prevdropscans) to a time offset to add onto start time croptimeoffset=(croptimeoffset + previousdroppedscans)/framerate; Logger::Log("Using cropped level-1 data - will add a time offset relating to number of lines cropped (y start + dropped scans values in hdr): "+ToString(croptimeoffset)); } //Close the level 1 file bilin.Close(); //Create the scan time array time=new double[nscans]; //Get the number of leap seconds for the data LeapSecond leap; leapseconds=leap.GetLeapSeconds(acquisitiondate,dateformat); DEBUGPRINT("Using leap seconds of:"<<leapseconds); }
double interg(double xlat, double xlon, GRID_HEADER vec_hdr[50], FILE* vec_ifp[50], int kk) { /******************************************************************************* * Interpolates a value from the kk-th numbered geoid model grid. * As the gridded data are all direct-access files, * only the nearest points (1 thru 9, * depending on the point's location relative to corners and edges) * are read into RAM for each point's interpolation. * * The size/spacing/etc of the data file's grid * are defined by the common statement, and the variable kk. * Caveats: * 1) It is assumed that xlat/xlon fall in the region of the kth grid * in - xlat : latitude position, decimal degrees, North * in - xlon : longitude position, decimal degrees, West * in - vec_hdr : vector of header records, as read from grid files * in - vec_ifp : vector of input files, pointing to grid files * in - kk : number (0 offset) of grid file to use * out- val : the interpolated value * ret- : the interpolated value * *******************************************************************************/ FILE* infile; BUFFER buffer; // alias for type (*void) for binary grid read // Grid header elements for file kk double latMin; double lonMin; double latDelta; double lonDelta; long latRowNum; long lonColNum; long iKind; double latMax; // calcd from header data double lonMax; // calcd from header data double val; // return value long irec; // binary data file element // double xx; // double yy; double row_counter; double col_counter; int irown; int icoln; double irown_lat; double icoln_lon; float f1; // Define some necessary parameters // These header data elements are read in the main driver file, // are in a common block, and are already checked for endian condition latMin = vec_hdr[kk].lat_min; lonMin = vec_hdr[kk].lon_min; latDelta = vec_hdr[kk].lat_delta; lonDelta = vec_hdr[kk].lon_delta; latRowNum = vec_hdr[kk].lat_num; lonColNum = vec_hdr[kk].lon_num; iKind = vec_hdr[kk].ikind; latMax = latMin + latDelta * (latRowNum - 1); lonMax = lonMin + lonDelta * (lonColNum - 1); infile = vec_ifp[kk]; // ----------------------------------------------------- // A little check for safety's sake // Verify point is within grid file bounds // ----------------------------------------------------- if (xlat < latMin) { fprintf(stderr, "Error: Latitude below minimum bound\n"); fprintf(stderr, " Lat = %lf latMin = %lf\n", xlat, latMin); abort(); } if (xlat > (latMin + latDelta * latRowNum) ) { fprintf(stderr, "Error: Latitude above maximum bound"); fprintf(stderr, " Lat = %lf latMax = %lf\n", xlat, latMax); abort(); } if (xlon < lonMin) { fprintf(stderr, "Error: Longitude below minimum bound"); fprintf(stderr, " Lon = %lf lonMin = %lf\n", xlon, lonMin); abort(); } if (xlon > (lonMin + lonDelta * lonColNum) ) { fprintf(stderr,"Error: Longitude above maximum bound"); fprintf(stderr, " Lon = %lf lonMax = %lf\n", xlon, lonMax); abort(); } // -------------------------------------------------------------------- // Find the row/col of the nearest grid node to the lat/lon point // This grid node is southwest from the lat/lon point // (row_counter,col_counter) = exact (lat,lon) grid coord location (float) // (irown,icoln) = reference node (to sw) grid coord loc'n (int) // -------------------------------------------------------------------- row_counter = ((xlat-latMin) / latDelta); // +1 =fortran index corr'n col_counter = ((xlon-lonMin) / lonDelta); // +1 =fortran index corr'n irown = (int)floor(row_counter); // reference row, just south from latdd icoln = (int)floor(col_counter); // reference col, just west from londd // Find the latitude and longitude of the nearest grid point irown_lat = latMin + latDelta*(irown); // lat just south(up) from latdd icoln_lon = lonMin + lonDelta*(icoln); // lon just west(left) from londd // Find the latitude and longitude of the reference node // not needed to find value at a node // yy = (row_counter - row) + 2.0; // 2 := 4x4 spline window // xx = (col_counter - col) + 2.0; // ----------------------------------------------------- // First things first -- // If we're sitting right on or near (0.36 arcsec) // a grid node, just assign the value and return // (1.0e-4 * 3600) = 0.36 arcsec // // read(lin(kk),rec=irec)f1 // // read big endian values and convert to little endian // if(reverse_bytes(kk)) f1=frev4(f1) // val = f1 // return // ----------------------------------------------------- if(fabs(xlat - irown_lat) <= 1.0e-4 && fabs(xlon - icoln_lon) <= 1.0e-4) { // linear array matrix math: // 44L gets past the header // irown*lonColNum gets to the row // icoln gets the data from the specific column irec = 44L + (long)(4*( (irown)*lonColNum + (icoln) )); fseek(infile, irec, SEEK_SET); fread((char*)&buffer, (sizeof(float)), 1, infile); f1 = buffer.ff; // Check endian condition if (iKind != 1) { f1 = flip_endian_f( f1 ); } return( f1 ); } // ----------------------------------------------------- // Not on a node, so interpolate // 1) 6x6 spline grid // 2) 4x4 spline grid // 3) bilinear // ----------------------------------------------------- if( irown >= 3 && irown < (latRowNum - 2) && icoln >= 3 && icoln < (lonColNum - 2) ) { val = spline6(xlat, xlon, vec_ifp, vec_hdr, kk); } else if( irown >= 2 && irown < (latRowNum - 1) && icoln >= 2 && icoln < (lonColNum - 1) ) { val = spline4(xlat, xlon, vec_ifp, vec_hdr, kk); } else { val = bilin( xlat, xlon, vec_ifp, vec_hdr, kk); } return( val ); }//~interg