int read_hdrfile(char *infile) { SEASAT_header_ext *hdr; FILE *fp = fopen(infile,"r"); int val, i, end_line; double dtmp, t, t1; int clock_drift_hist[MAX_CLOCK_DRIFT]; int clock_drift_median; double clock_shift; if (fp==NULL) {printf("ERROR: can't open %s header file\n",infile); return(1); } hdr = (SEASAT_header_ext *) malloc(sizeof(SEASAT_header_ext)); for (i=0; i<start_line; i++) { val = get_values(fp, hdr); if (val!=20) {printf("ERROR: unable to read to specified start line in header file\n"); exit(1);} } station_code = hdr->station_code; start_year = 1970 + hdr->lsd_year; start_date = hdr->day_of_year; start_sec = (double) hdr->msec / 1000.0; s_date.year = 1970 + hdr->lsd_year; s_date.jd = hdr->day_of_year; dtmp = (double) hdr->msec / 1000.0; date_sec2hms(dtmp,&s_time); if (USE_CLOCK_DRIFT==1) { for (i=0; i<MAX_CLOCK_DRIFT; i++) clock_drift_hist[i] = 0; end_line = start_line + npatches*patch_size; for (i = start_line; i<end_line; i++) { val = get_values(fp, hdr); if (val!=20) {printf("ERROR: unable to read to specified end line in header file\n"); exit(1);} clock_drift_hist[hdr->clock_drift]++; } printf("APPLYING CLOCK DRIFT TO IMAGE TIMING.\n"); clock_drift_median = get_median(clock_drift_hist,MAX_CLOCK_DRIFT); printf("\tclock_drift_median = %li \n",clock_drift_median); clock_shift = (double) clock_drift_median / 1000.0; start_sec += clock_shift; if (start_sec > 86400.0) {start_sec -= 86400.0; start_date += 1;} dtmp = date_hms2sec(&s_time)+clock_shift; if (dtmp > 86400.0) { s_date.jd+=1; dtmp-=86400.0;} date_sec2hms(dtmp,&s_time); } printf("Found start time: %i %i %lf\n",start_year, start_date, start_sec); fclose(fp); }
/*************************************************************** * Get_timeDelta: * Return the time difference, in seconds, between the start * of the state vectors (in the PPDR) and the start of the image * (as described in the DSSR). Write this time to the given * meta_parameters->state_vectors structure.*/ double get_timeDelta(ceos_description *ceos,struct pos_data_rec *ppdr,meta_parameters *meta) { ymd_date imgDate; julian_date imgJD,stJD; hms_time imgTime,stTime; double imgSec,stSec;/*Seconds since 1900 for start of image and start of state vectors*/ /*Read time of *start* of state vectors*/ stJD.year = (int) ppdr->year; stJD.jd = (int) ppdr->gmt_day; date_sec2hms(ppdr->gmt_sec,&stTime); stSec=date2sec(&stJD,&stTime); /*Compute the *scene* start time from the CEOS DSSR: */ /* begin with scene center time */ if (ceos->facility == BEIJING) date_dssr2time(ceos->dssr.inp_sctim,&imgDate,&imgTime); else date_dssr2date(ceos->dssr.inp_sctim,&imgDate,&imgTime); date_ymd2jd(&imgDate,&imgJD); imgSec=date2sec(&imgJD,&imgTime); if (ceos->processor==FOCUS && ceos->product==CCSD) { /* do nothing-- dssr "inp_sctim" already gives scene start time */ } else if (0!=strcmp(ceos->dssr.az_time_first,"")) { /* e.g., ESA data. "az_time_first" field gives start of image */ date_dssr2time(ceos->dssr.az_time_first,&imgDate,&imgTime); imgSec=date2sec(&imgJD,&imgTime); } else if (ceos->facility==EOC) { imgSec-=ceos->dssr.sc_lin*fabs(meta->sar->azimuth_time_per_pixel); } else {/*Convert scene center time to scene *start* time, by subtracting off the center line # * the time/line */ imgSec-=ceos->dssr.sc_lin*fabs(meta->sar->azimuth_time_per_pixel); } /* // Complex ALOS data have an additional 1 sec shift // Still under investigation: Need word from DQ on this if (ceos->facility==EOC && ceos->product==SLC) imgSec -= 1.0; */ /*Convert scene center # of seconds back to date/time*/ sec2date(imgSec,&imgJD,&imgTime); /*Write image time to meta->state_vectors structure*/ meta->state_vectors->year = (int) imgJD.year; meta->state_vectors->julDay = (int) imgJD.jd; meta->state_vectors->second = date_hms2sec(&imgTime); /*Return the time between state vector start and image start*/ return stSec-imgSec; }
/*Compute the date corresponding to this number of seconds since midnight, Jan 1, 1900. This is sub-millisecond accurate; but ignores leap seconds. */ void sec2date(double secs,julian_date *date,hms_time *time) { int year=1900; while (secs>=date_getDaysInYear(year)*DAY2SEC) secs-=date_getDaysInYear(year++)*DAY2SEC; date->year=year; date->jd=1+(int)(secs/DAY2SEC); secs-=(date->jd-1)*DAY2SEC; date_sec2hms(secs,time); }
// Compute date corresponding to seconds since midnight, Jan 1, 1985. void seconds2date(double seconds, ymd_date *date, hms_time *time) { julian_date jd; int year = 1985; double secs = seconds; while (secs >= date_getDaysInYear(year)*DAY2SEC) secs -= date_getDaysInYear(year++)*DAY2SEC; jd.year = year; jd.jd = 1 + (int)(secs/DAY2SEC); secs -= (jd.jd - 1)*DAY2SEC; date_sec2hms(secs, time); date_jd2ymd(&jd, date); }
static void rgps2iso_date(int year, double day, char *isoStr) { julian_date jd; hms_time time; ymd_date date; jd.year = year; jd.jd = (int) day; date_jd2ymd(&jd, &date); double sec = 86400 * (day - jd.jd); date_sec2hms(sec, &time); sprintf(isoStr, "%4d-%02d-%02dT%02d:%02d:%09.6lfZ", date.year, date.month, date.day, time.hour, time.min, time.sec); }
static void dateTimeStamp(meta_parameters *meta, int line, iso_dateTime *dateTime) { julian_date jd; hms_time hms; ymd_date ymd; jd.year = meta->state_vectors->year; jd.jd = meta->state_vectors->julDay; date_sec2hms(meta->state_vectors->second, &hms); date_jd2ymd(&jd, &ymd); double imgSec = line*meta->sar->azimuth_time_per_pixel; add_time(imgSec, &ymd, &hms); dateTime->year = ymd.year; dateTime->month = ymd.month; dateTime->day = ymd.day; dateTime->hour = hms.hour; dateTime->min = hms.min; dateTime->second = hms.sec; }
/******************************************************* * meta_get_dop: * Converts a line, sample pair to the doppler value at * that location. Returns Hz. Only works for SR & GR. */ double meta_get_dop(meta_parameters *meta,double yLine, double xSample) { assert (meta->sar); // && (meta->sar->image_type == 'S' // || meta->sar->image_type == 'G')); yLine += meta->general->start_line; xSample += meta->general->start_sample; if (meta->doppler && meta->doppler->tsx) { int ii; julian_date imgStartDate, imgDopplerDate; hms_time imgStartTime, imgDopplerTime; double time, refTime, *coeff; imgStartDate.year = meta->state_vectors->year; imgStartDate.jd = meta->state_vectors->julDay; date_sec2hms(meta->state_vectors->second, &imgStartTime); imgDopplerDate.year = meta->doppler->tsx->year; imgDopplerDate.jd = meta->doppler->tsx->julDay; date_sec2hms(meta->doppler->tsx->second, &imgDopplerTime); double imgAzimuthTime = date2sec(&imgStartDate, &imgStartTime) + yLine * meta->sar->range_time_per_pixel; double dopAzimuthStart = date2sec(&imgDopplerDate, &imgDopplerTime); for (ii=0; ii<meta->doppler->tsx->doppler_count; ii++) { time = dopAzimuthStart + meta->doppler->tsx->dop[ii].time; if (time > imgAzimuthTime) break; } int max = ii; int min = ii - 1; double dopAzimuthMin = dopAzimuthStart + meta->doppler->tsx->dop[min].time; double dopRangeTimeMin = meta->doppler->tsx->dop[min].first_range_time + xSample * meta->sar->azimuth_time_per_pixel; refTime = meta->doppler->tsx->dop[min].reference_time; coeff = (double *) MALLOC(sizeof(double)* meta->doppler->tsx->dop[min].poly_degree); double dopplerMin = 0.0; for (ii=0; ii<=meta->doppler->tsx->dop[min].poly_degree; ii++) { coeff[ii] = meta->doppler->tsx->dop[min].coefficient[ii]; dopplerMin += coeff[ii] * pow(dopRangeTimeMin - refTime, ii); } FREE(coeff); double dopAzimuthMax = dopAzimuthStart + meta->doppler->tsx->dop[max].time; refTime = meta->doppler->tsx->dop[min].reference_time; coeff = (double *) MALLOC(sizeof(double)* meta->doppler->tsx->dop[max].poly_degree); double dopplerMax = 0.0; for (ii=0; ii<=meta->doppler->tsx->dop[max].poly_degree; ii++) { coeff[ii] = meta->doppler->tsx->dop[max].coefficient[ii]; dopplerMax += coeff[ii] * pow(dopRangeTimeMin - refTime, ii); } FREE(coeff); return dopplerMin + (dopplerMax - dopplerMin) / (dopAzimuthMax - dopAzimuthMin) * (imgAzimuthTime - dopAzimuthMin); } else if (meta->doppler && meta->doppler->r2) { int ii; double doppler = 0.0; radarsat2_doppler_params *r2 = meta->doppler->r2; double slant_time = r2->time_first_sample + xSample * meta->sar->range_time_per_pixel; for (ii=0; ii<r2->doppler_count; ++ii) doppler += r2->centroid[ii] * pow((slant_time - r2->ref_time_centroid), ii); return doppler; } else return meta->sar->range_doppler_coefficients[0]+ meta->sar->range_doppler_coefficients[1]*xSample+ meta->sar->range_doppler_coefficients[2]*xSample*xSample+ meta->sar->azimuth_doppler_coefficients[1]*yLine+ meta->sar->azimuth_doppler_coefficients[2]*yLine*yLine; }
meta_parameters* airsar2meta(airsar_header *header, airsar_param_header *params, airsar_dem_header *dem) { meta_parameters *meta; hms_time hms; // Allocate memory for metadata structure meta = raw_init(); // General block sprintf(meta->general->basename, "%s", params->site_name); sprintf(meta->general->sensor, "AIRSAR"); strcpy(meta->general->sensor_name, "SAR"); if (strlen(header->processor)>0) { header->processor[4] = '\0'; strcpy(meta->general->processor, "JPL version "); strcat(meta->general->processor, header->processor); } else { strcpy(meta->general->processor, MAGIC_UNSET_STRING); } // FIXME: various data types - InSAR vs. polarimetric date_sec2hms(params->acquisition_seconds, &hms); sprintf(meta->general->acquisition_date, "%s %d:%d:%.3lf", params->acquisition_date, hms.hour, hms.min, hms.sec); meta->general->orbit = params->cct_id; // close enough // no frame number // FIXME: decide how to separate interferometric/polarimetric data meta->general->band_count = 1; meta->general->line_count = header->line_count; //header->line_count - header->first_data_offset / header->sample_count; meta->general->sample_count = header->sample_count; meta->general->start_line = 0; meta->general->start_sample = 0; meta->general->x_pixel_size = header->x_pixel_size; meta->general->y_pixel_size = header->y_pixel_size; meta->general->center_latitude = params->center_lat; meta->general->center_longitude = params->center_lon; meta->general->re_major = 6378137.0; // WGS84 meta->general->re_minor = 6356752.314; // WGS84 // no information on bit error rate, missing lines and no data // SAR block meta->sar = meta_sar_init(); // The CCT type 'CM' stands for 'Compressed Stokes Matrix' which implies // that you have fully polarimetric data if (strncmp_case(params->cct_type, "CM", 2) == 0) { meta->general->image_data_type = POLARIMETRIC_IMAGE; meta->general->radiometry = r_SIGMA; strcpy(meta->sar->polarization, "QUAD-POL"); meta->general->band_count = 8; } if (strncmp_case(header->range_projection, "GROUND", 6) == 0) meta->sar->image_type = 'G'; // no information on look direction if (params->deskewed == 1) meta->sar->deskewed = 1; else if (params->deskewed == 2) meta->sar->deskewed = 0; meta->sar->original_line_count = header->line_count; meta->sar->original_sample_count = header->sample_count; meta->sar->line_increment = 1; meta->sar->sample_increment = 1; // no information on azimuth and range time per pixel // no information on slant and time shift meta->sar->slant_range_first_pixel = params->near_slant_range; meta->sar->wavelength = params->wavelength; meta->sar->prf = params->prf; // no information on earth radius and satellite height // no time information // no Doppler information meta->sar->azimuth_processing_bandwidth = params->chirp_bandwidth; // no chirp rate information meta->sar->pulse_duration = params->pulse_length; meta->sar->range_sampling_rate = params->range_sampling_rate; // FIXME: check polarizations for interferometric/polarimetric data // FIXME: multilook flag depends on data type // AirSAR block meta->airsar = meta_airsar_init(); meta->airsar->scale_factor = 1.0; // Bruce Chapman said so. meta->airsar->gps_altitude = params->gps_altitude; if (dem) { meta->airsar->lat_peg_point = dem->lat_peg_point; meta->airsar->lon_peg_point = dem->lon_peg_point; meta->airsar->head_peg_point = dem->head_peg_point; meta->airsar->along_track_offset = dem->along_track_offset; meta->airsar->cross_track_offset = dem->cross_track_offset; } else { meta->airsar->lat_peg_point = params->lat_peg_point; meta->airsar->lon_peg_point = params->lon_peg_point; meta->airsar->head_peg_point = params->head_peg_point; meta->airsar->along_track_offset = params->along_track_offset; meta->airsar->cross_track_offset = params->cross_track_offset; } // The DEM header of Rick's prime test data did not have a valid peg point. // Without that the other numbers (along-track and cross-track offsets // as well as corner coordinates) don't make sense. // Will take the numbers out of the parameter header. Seems to work fine // with the prime test data set. Extract only elevation offset and increment // out of the DEM header if (dem) { meta->airsar->elevation_increment = dem->elevation_increment; meta->airsar->elevation_offset = dem->elevation_offset; } // Location block meta->location = meta_location_init(); if (dem) { meta->location->lat_start_near_range = dem->corner1_lat; meta->location->lon_start_near_range = dem->corner1_lon; meta->location->lat_start_far_range = dem->corner2_lat; meta->location->lon_start_far_range = dem->corner2_lon; meta->location->lat_end_near_range = dem->corner4_lat; meta->location->lon_end_near_range = dem->corner4_lon; meta->location->lat_end_far_range = dem->corner3_lat; meta->location->lon_end_far_range = dem->corner3_lon; } return meta; }
/*************************************************************** * Ceos_init_stVec: * Reads state vectors from given CEOS file, writing them in the * appropriate format to SAR parameters structure.*/ void ceos_init_stVec(const char *fName, ceos_description *ceos, meta_parameters *meta) { struct pos_data_rec ppdr; /*Fetch platform position data record.*/ get_ppdr(fName,&ppdr); // Read the state vectors from the leader data file, adjust coordinate system, etc. // and write them to the SAR parameters structures ceos_read_stVecs(fName, ceos, meta); // For ALOS Palsar orbits only // Don't propagate but select nine state vectors around the center for the // higher order interpolation scheme if (ceos->processor == ALOS_PROC) { // Determine closest state vector int ii, min; double diff = 99999999; for (ii=0; ii<meta->state_vectors->vector_count; ii++) { if (fabs(meta->state_vectors->vecs[ii].time) < diff) { diff = fabs(meta->state_vectors->vecs[ii].time); min = ii; } } // Populate a new state vector ymd_date img_ymd; julian_date img_jd; hms_time img_time; img_jd.year = meta->state_vectors->year; img_jd.jd = meta->state_vectors->julDay; date_sec2hms(meta->state_vectors->second,&img_time); date_jd2ymd(&img_jd, &img_ymd); add_time((min-4)*60, &img_ymd, &img_time); date_ymd2jd(&img_ymd, &img_jd); meta_state_vectors *new_st = meta_state_vectors_init(9); new_st->year = img_jd.year; new_st->julDay = img_jd.jd; new_st->second = date_hms2sec(&img_time); for (ii=0; ii<9; ii++) new_st->vecs[ii] = meta->state_vectors->vecs[ii+min-4]; FREE(meta->state_vectors); meta->state_vectors = new_st; // Time shift should definitely set in the code that is calling this function // meta->sar->time_shift = 0.0; } // Propagate three state vectors for regular frames else if (ceos->processor != PREC && ceos->processor != unknownProcessor) { int vector_count=3; double data_int = meta->sar->original_line_count / 2 * fabs(meta->sar->azimuth_time_per_pixel); meta->state_vectors->vecs[0].time = get_timeDelta(ceos, &ppdr, meta); if (ceos->processor != PREC && data_int < 360.0) { while (fabs(data_int) > 15.0) { data_int /= 2; vector_count = vector_count*2-1; } // propagate three state vectors: start, center, end propagate_state(meta, vector_count, data_int); } } }