void calc_minmax_polsarpro(const char *inFile, double *min, double *max) { int ii,jj; *min = 999999; *max = -999999; char *enviName = (char *) MALLOC(sizeof(char)*(strlen(inFile) + 10)); sprintf(enviName, "%s.hdr", inFile); envi_header *envi = read_envi(enviName); meta_parameters *meta = envi2meta(envi); float *data = MALLOC(sizeof(float) * meta->general->sample_count); FILE *fp = FOPEN(inFile, "rb"); asfPrintStatus("\nCalculating min and max ...\n"); for (ii=0; ii<meta->general->line_count; ++ii) { asfPercentMeter(((double)ii/(double)meta->general->line_count)); get_float_line(fp, meta, ii, data); for (jj=0; jj<meta->general->sample_count; ++jj) { ieee_big32(data[jj]); if (data[jj] < *min) *min = data[jj]; if (data[jj] > *max) *max = data[jj]; } } asfPercentMeter(1.0); FCLOSE(fp); FREE(data); meta_free(meta); FREE(envi); FREE(enviName); }
/* Calculate minimum, maximum, mean and standard deviation for a floating point image. A mask value can be defined that is excluded from this calculation. If no mask value is supposed to be used, pass the mask value as NAN. */ void calc_stats(float *data, long long pixel_count, double mask, double *min, double *max, double *mean, double *stdDev) { long long ii, pix; /* Initialize values */ *min = 99999; *max = -99999; *mean = 0.0; *stdDev = 0.0; pix = 0; asfPrintStatus("\nFinding min, max, and mean...\n"); for (ii=0; ii<pixel_count; ii++) { asfPercentMeter(((double)ii/(double)pixel_count)); if (!ISNAN(mask)) { if (data[ii] < *min && !FLOAT_EQUIVALENT(data[ii], mask)) *min = data[ii]; if (data[ii] > *max && !FLOAT_EQUIVALENT(data[ii], mask)) *max = data[ii]; if (!FLOAT_EQUIVALENT(data[ii], mask)) { *mean += data[ii]; pix++; } } else { if (data[ii] < *min) *min = data[ii]; if (data[ii] > *max) *max = data[ii]; *mean += data[ii]; ++pix; } } asfPercentMeter(1.0); *mean /= pix; asfPrintStatus("\nCalculating standard deviation...\n"); for (ii=0; ii<pixel_count; ii++) { asfPercentMeter(((double)ii/(double)pixel_count)); if (!ISNAN(mask)) { if (!FLOAT_EQUIVALENT(data[ii], mask)) *stdDev += (data[ii] - *mean) * (data[ii] - *mean); } else *stdDev += (data[ii] - *mean) * (data[ii] - *mean); } *stdDev = sqrt(*stdDev/(pix - 1)); asfPercentMeter(1.0); return; }
int get_terrasar_thumbnail_data(int thumb_size_x, int thumb_size_y, meta_parameters *meta, void *read_client_info, void *dest_void, int data_type) { ReadTerrasarClientInfo *info = (ReadTerrasarClientInfo*) read_client_info; int ii, jj; int ns = meta->general->sample_count; int sf = meta->general->line_count / thumb_size_y; if (info->multilook) sf *= meta->sar->look_count; float *dest = (float*)dest_void; // Read in the image short int *shorts = MALLOC(sizeof(short int)*ns*2); for (ii=0; ii<thumb_size_y; ii++) { int line = ii*sf; long long offset = (long long) (info->header + line*info->width); FSEEK(info->fp, offset, SEEK_SET); FREAD(shorts, sizeof(short int), ns*2, info->fp); for (jj=0; jj<thumb_size_x; jj++) dest[jj + ii*thumb_size_x] = hypot(shorts[jj*sf*2], shorts[jj*sf*2+1]); asfPercentMeter((float)ii/(thumb_size_y - 1)); } free(shorts); return TRUE; }
int get_uavsar_thumbnail_data(int thumb_size_x, int thumb_size_y, meta_parameters *meta, void *read_client_info, void *dest_void, int data_type) { ReadUavsarClientInfo *info = (ReadUavsarClientInfo*) read_client_info; int i, j; int sf = meta->general->line_count / thumb_size_y; int ns = meta->general->sample_count; // temporary storage float *buf = MALLOC(sizeof(float)*ns); if (meta->general->data_type == ASF_BYTE) { unsigned char *dest = (unsigned char*)dest_void; if (data_type == GREYSCALE_BYTE) { for (i=0; i<thumb_size_y; ++i) { get_uavsar_line(info, meta, i*sf, buf); for (j=0; j<thumb_size_x; ++j) dest[i*thumb_size_x+j] = (unsigned char)(buf[j*sf]); asfPercentMeter((float)i/(thumb_size_y-1)); } } else { assert(FALSE); } } else { float *dest = (float*)dest_void; if (data_type == GREYSCALE_FLOAT) { for (i=0; i<thumb_size_y; ++i) { get_uavsar_line(info, meta, i*sf, buf); for (j=0; j<thumb_size_x; ++j) dest[i*thumb_size_x+j] = buf[j*sf]; asfPercentMeter((float)i/(thumb_size_y-1)); } } else { assert(FALSE); } } free(buf); return TRUE; }
int get_asf_thumbnail_data(int thumb_size_x, int thumb_size_y, meta_parameters *meta, void *read_client_info, void *dest_void, int data_type) { ReadAsfClientInfo *info = (ReadAsfClientInfo*) read_client_info; int sf = meta->general->line_count / thumb_size_y; //assert(sf==meta->general->sample_count / thumb_size_x); int i,j; int nl = meta->general->line_count; int ns = meta->general->sample_count; // temporary storage float *buf = MALLOC(sizeof(float)*ns); if (meta->general->data_type == ASF_BYTE) { // BYTE case -- data file contains bytes. unsigned char *dest = (unsigned char*)dest_void; if (data_type == GREYSCALE_BYTE) { // data file contains byte data, and we are just pulling out // one band to display. int off = nl*info->band_gs; for (i=0; i<thumb_size_y; ++i) { get_asf_line(info, meta, i*sf + off, buf); for (j=0; j<thumb_size_x; ++j) dest[i*thumb_size_x+j] = (unsigned char)(buf[j*sf]); asfPercentMeter((float)i/(thumb_size_y-1)); } } else { // rgb case -- we have to read up to 3 bands from the file, // and put them together assert(data_type == RGB_BYTE); int off, k; // first set dest buffer to all zeros. This way, any bands that // aren't set up will just come out black memset(dest, 0, 3*thumb_size_x*thumb_size_y); // "tot" is to help with the PercentMeter -- the total number // of lines that we will need to read. "l" is the counter int tot = (info->band_r>=0) + (info->band_g>=0) + (info->band_b>=0); tot *= thumb_size_y; int l=0; // to do each of the bands, we read the data into a float array, // then cast (back) to byte into the interleaved "dest" array // (interleaved in the sense that we only populate every 3rd item // each time through) // red band if (info->band_r >= 0) { off = nl*info->band_r; for (i=0; i<thumb_size_y; ++i) { k=3*i*thumb_size_x; // starting point in dest array get_asf_line(info, meta, i*sf + off, buf); for (j=0; j<thumb_size_x; ++j, k += 3) dest[k] = (unsigned char)(buf[j*sf]); asfPercentMeter((float)(l++)/(tot-1)); } } // green band if (info->band_g >= 0) { off = nl*info->band_g; for (i=0; i<thumb_size_y; ++i) { k=3*i*thumb_size_x+1; get_asf_line(info, meta, i*sf + off, buf); for (j=0; j<thumb_size_x; ++j, k += 3) dest[k] = (unsigned char)(buf[j*sf]); asfPercentMeter((float)(l++)/(tot-1)); } } // blue band if (info->band_b >= 0) { off = nl*info->band_b; for (i=0; i<thumb_size_y; ++i) { k=3*i*thumb_size_x+2; get_asf_line(info, meta, i*sf + off, buf); for (j=0; j<thumb_size_x; ++j, k += 3) dest[k] = (unsigned char)(buf[j*sf]); asfPercentMeter((float)(l++)/(tot-1)); } } //assert(l==tot); if (l!=tot) printf("These are supposed to be equal: %d %d\n", l, tot); } } else { // this is the normal case -- regular old floating point data, // we just read with get_float_line and populate directly into // a floating point array float *dest = (float*)dest_void; if (data_type == GREYSCALE_FLOAT) { int off = nl*info->band_gs; for (i=0; i<thumb_size_y; ++i) { get_asf_line(info, meta, i*sf + off, buf); for (j=0; j<thumb_size_x; ++j) dest[i*thumb_size_x+j] = buf[j*sf]; asfPercentMeter((float)i/(thumb_size_y-1)); } } else if (data_type == RGB_FLOAT) { int off, k; // first set dest buffer to all zeros. This way, any bands that // aren't set up will just come out black. memset(dest, 0, 3*sizeof(float)*thumb_size_x*thumb_size_y); // "tot" is to help with the PercentMeter -- the total number // of lines that we will need to read. "l" is the counter int tot = (info->band_r>=0) + (info->band_g>=0) + (info->band_b>=0); tot *= thumb_size_y; int l=0; // to do each of the bands, we read the data into a float array, // then cast (back) to byte into the interleaved "dest" array // (interleaved in the sense that we only populate every 3rd item // each time through) // red band if (info->band_r >= 0) { off = nl*info->band_r; for (i=0; i<thumb_size_y; ++i) { k=3*i*thumb_size_x; // starting point in dest array get_asf_line(info, meta, i*sf + off, buf); for (j=0; j<thumb_size_x; ++j, k += 3) dest[k] = buf[j*sf]; asfPercentMeter((float)(l++)/(tot-1)); } } // green band if (info->band_g >= 0) { off = nl*info->band_g; for (i=0; i<thumb_size_y; ++i) { k=3*i*thumb_size_x+1; get_asf_line(info, meta, i*sf + off, buf); for (j=0; j<thumb_size_x; ++j, k += 3) dest[k] = buf[j*sf]; asfPercentMeter((float)(l++)/(tot-1)); } } // blue band if (info->band_b >= 0) { off = nl*info->band_b; for (i=0; i<thumb_size_y; ++i) { k=3*i*thumb_size_x+2; get_asf_line(info, meta, i*sf + off, buf); for (j=0; j<thumb_size_x; ++j, k += 3) dest[k] = buf[j*sf]; asfPercentMeter((float)(l++)/(tot-1)); } } //assert(l==tot); if (l!=tot) printf("These are supposed to be equal: %d %d\n", l, tot); } else { assert(FALSE); } } free(buf); return TRUE; }
/* Create histogram of the data and get the summation of the * square of (sample-mean) to use in calculation of rmse & stdev */ stat_parameters calc_hist(stat_parameters stats, char *sar_name, int band, meta_parameters *meta, double sum_of_samples, long samples_counted, int mask_flag) { FILE *fp; long start_line, start_sample, window_height, window_width; long percent_complete, line, sample, ii, band_offset; double diff_squared_sum=0.0; float *data_line; start_line = stats.upper_left_line; start_sample = stats.upper_left_samp; window_height = stats.lower_right_line - start_line; window_width = stats.lower_right_samp - start_sample; data_line = (float *)MALLOC(sizeof(float)*meta->general->sample_count); fp = FOPEN(sar_name, "r"); /* Initialize the histogram array */ for (ii=0; ii<256; ii++) stats.histogram[ii] = 0; if (meta->general->data_type != ASF_BYTE) { /* Set slope and offset, to map pixels to [0..255]. * byte = slope * in + offset * 0 = slope * min + offset * 255 = slope * max + offset * Therefore: */ stats.slope = 255.0 / (stats.max-stats.min); stats.offset = -stats.slope * stats.min; } /* Get histogram of the data. If its byte data just slap it into the * histogram; otherwise use slope & offset to scale the data */ stats.mean = sum_of_samples / (double)samples_counted; percent_complete=0; band_offset = band * meta->general->line_count; for (line=start_line+band_offset; line<start_line+window_height+band_offset; line++) { if (!quietflag) asfPercentMeter((float)(line-start_line-band_offset)/(float)(window_height-start_line)); get_float_line(fp, meta, line, data_line); for (sample=start_sample; sample<start_sample+window_width; sample++) { int bin = (meta->general->data_type == ASF_BYTE) ? (int)data_line[sample] : (int)(stats.slope*data_line[sample]+stats.offset); if (bin < 0) bin = 0; else if (bin > 255) bin = 255; if ( mask_flag && FLOAT_EQUIVALENT(data_line[sample],stats.mask) ) continue; stats.histogram[bin]++; diff_squared_sum += SQR(data_line[sample] - stats.mean); } } if (!quietflag) asfPercentMeter(1.0); FREE(data_line); FCLOSE(fp); /* Populate stats structure */ stats.rmse = sqrt( fabs( diff_squared_sum / (double)samples_counted ) ); stats.std_deviation = sqrt( fabs( diff_squared_sum / (double)(samples_counted-1) ) ); return stats; }
int main(int argc, char **argv) { double min, max; /* Minimum & maximum sample values */ double sum_of_samples=0.0; /* Sum of all samples accounted for */ double sum_of_squared_samples=0.0; /* Sum of all squared samples accounted for*/ double trim_fraction; /* Fraction used to trim the histogram */ int ii; /* Loop index */ long samples_counted=0; /* Number of all samples accounted for */ float *data_line; /* Buffer for a line of samples */ long line, sample; /* Line and sample indices */ long num_lines, num_samples; /* Number of lines and samples */ int percent_complete=0; /* Percent of data sweep completed */ int overmeta_flag=FALSE; /* If TRUE write over current .meta file */ int overstat_flag=FALSE; /* If TRUE write over current .stat file */ int nometa_flag=FALSE; /* If TRUE do not write .meta file */ int nostat_flag=FALSE; /* If TRUE do not write .stat file */ int mask_flag=FALSE; /* TRUE if user specifies a mask value */ int trim_flag=FALSE; /* If TRUE trim histogram */ double mask=NAN; /* Value to ignore while caculating stats*/ char meta_name[261]; /* Meta file name */ meta_parameters *meta; /* SAR meta data structure */ char sar_name[256]; /* SAR file name WITH extention */ FILE *sar_file; /* SAR data file pointer to take stats on*/ stat_parameters *stats; /* Statistics structure */ char stat_name[261]; /* Stats file name */ extern int currArg; /* Pre-initialized to 1 */ /* We initialize these to a magic number for checking. */ long start_line = -1; /* Window starting line. */ long start_sample = -1; /* Window starting sample. */ long window_height = -1; /* Window height in lines. */ long window_width = -1; /* Window width in samples. */ /* parse command line */ handle_license_and_version_args(argc, argv, "stats"); logflag=quietflag=FALSE; while (currArg < (argc-1)) { char *key = argv[currArg++]; if (strmatch(key,"-quiet")) { quietflag=TRUE; } else if (strmatch(key,"-log")) { CHECK_ARG(1); strcpy(logFile,GET_ARG(1)); fLog = FOPEN(logFile, "a"); logflag=TRUE; } else if (strmatch(key,"-mask")) { CHECK_ARG(1); mask = atof(GET_ARG(1)); mask_flag=TRUE; } else if (strmatch(key,"-overmeta")) { overmeta_flag=TRUE; } else if (strmatch(key,"-overstat")) { overstat_flag=TRUE; } else if (strmatch(key,"-nometa")) { nometa_flag=TRUE; } else if (strmatch(key,"-nostat")) { nostat_flag=TRUE; } else if (strmatch(key,"-startline")) { CHECK_ARG(1); nometa_flag=TRUE; /* Implied. */ start_line = atol(GET_ARG(1)); if ( start_line < 0 ) { printf("error: -startline argument must be greater than or equal to zero\n"); usage(argv[0]); } } else if (strmatch(key,"-startsample")) { CHECK_ARG(1); nometa_flag=TRUE; /* Implied. */ start_sample = atol(GET_ARG(1)); if ( start_sample < 0 ) { printf("error: -startsample argument must be greater than or equal to zero\n"); usage(argv[0]); } } else if (strmatch(key,"-width")) { CHECK_ARG(1); nometa_flag=TRUE; /* Implied. */ window_width = atol(GET_ARG(1)); if ( window_width < 0 ) { printf("error: -width argument must be greater than or equal to zero\n"); usage(argv[0]); } } else if (strmatch(key,"-height")) { CHECK_ARG(1); nometa_flag=TRUE; /* Implied. */ window_height = atol(GET_ARG(1)); if ( window_height < 0 ) { printf("error: -height argument must be greater than or equal to zero\n"); usage(argv[0]); } } else if (strmatch(key,"-trim")) { CHECK_ARG(1); trim_flag=TRUE; /* Implied. */ trim_fraction = atof(GET_ARG(1)); } else {printf( "\n**Invalid option: %s\n",argv[currArg-1]); usage(argv[0]);} } if ((argc-currArg)<1) {printf("Insufficient arguments.\n"); usage(argv[0]);} strcpy (sar_name, argv[currArg]); char *ext = findExt(sar_name); if (ext == NULL || strcmp("IMG", uc(ext)) != 0) { strcpy(sar_name, appendExt(sar_name, ".img")); } create_name(meta_name, sar_name, ".meta"); create_name(stat_name, sar_name, ".stat"); printf("\nProgram: stats\n\n"); if (logflag) { fprintf(fLog, "\nProgram: stats\n\n"); } printf("\nCalculating statistics for %s\n\n", sar_name); if (logflag) { fprintf(fLog,"\nCalculating statistics for %s\n\n", sar_name); } meta = meta_read(meta_name); num_lines = meta->general->line_count; num_samples = meta->general->sample_count; if ( start_line == -1 ) start_line = 0; if ( start_line > num_lines ) { printf("error: -startline argument is larger than index of last line in image\n"); exit(EXIT_FAILURE); } if ( start_sample == -1 ) start_sample = 0; if ( start_sample > num_samples ) { printf("error: -startsample argument is larger than index of last sample in image\n"); exit(EXIT_FAILURE); } if ( window_height == -1 ) window_height = num_lines; if ( start_line + window_height > num_lines ) { printf("warning: window specified with -startline, -height options doesn't fit in image\n"); } if ( window_width == -1 ) window_width = num_samples; if ( start_sample + window_width > num_samples ) { printf("warning: window specified with -startsample, -width options doesn't fit in image\n"); } /* Make sure we don't over write any files that we don't want to */ if (meta->stats && !overmeta_flag && !nometa_flag) { printf(" ** The meta file already has a populated statistics structure.\n" " ** If you want to run this program and replace that structure,\n" " ** then use the -overmeta option to do so. If you want to run\n" " ** this program, but don't want to replace the structure, use\n" " ** the -nometa option.\n"); if (logflag) { fprintf(fLog, " ** The meta file already has a populated statistics structure.\n" " ** If you want to run this program and replace that structure,\n" " ** then use the -overmeta option to do so. If you want to run\n" " ** this program, but don't want to replace the structure, use\n" " ** the -nometa option.\n"); } exit(EXIT_FAILURE); } if (fileExists(stat_name) && !overstat_flag && !nostat_flag) { printf(" ** The file, %s, already exists. If you want to\n" " ** overwrite it, then use the -overstat option to do so.\n" " ** If you want to run the progam but don't want to write\n" " ** over the current file, then use the -nostat option.\n", stat_name); if (logflag) { fprintf(fLog, " ** The file, %s, already exists. If you want to\n" " ** overwrite it, then use the -overstat option to do so.\n" " ** If you want to run the progam but don't want to write\n" " ** over the current file, then use the -nostat option.\n", stat_name); } exit(EXIT_FAILURE); } /* Let user know the window in which the stats will be taken */ if ((start_line!=0) || (start_sample!=0) || (window_height!=num_lines) || (window_width!=num_samples)) { if (!quietflag) { printf("Taking statistics on a window with upper left corner (%ld,%ld)\n" " and lower right corner (%ld,%ld)\n", start_sample, start_line, window_width+start_sample, window_height+start_line); } if (logflag && !quietflag) { fprintf(fLog, "Taking statistics on a window with upper left corner (%ld,%ld)\n" " and lower right corner (%ld,%ld)\n", start_sample, start_line, window_width+start_sample, window_height+start_line); } } /* Allocate line buffer */ data_line = (float *)MALLOC(sizeof(float)*num_samples); if (meta->stats) FREE(meta->stats); if (meta->general->band_count <= 0) { printf(" ** Band count in the existing data is missing or less than zero.\nDefaulting to one band.\n"); if (logflag) { fprintf(fLog, " ** Band count in the existing data is missing or less than zero.\nDefaulting to one band.\n"); } meta->general->band_count = 1; } meta->stats = meta_statistics_init(meta->general->band_count); if (!meta->stats) { printf(" ** Cannot allocate memory for statistics data structures.\n"); if (logflag) { fprintf(fLog, " ** Cannot allocate memory for statistics data structures.\n"); } exit(EXIT_FAILURE); } stats = (stat_parameters *)MALLOC(sizeof(stat_parameters) * meta->stats->band_count); if (!stats) { printf(" ** Cannot allocate memory for statistics data structures.\n"); if (logflag) { fprintf(fLog, " ** Cannot allocate memory for statistics data structures.\n"); } exit(EXIT_FAILURE); } int band; long band_offset; for (band = 0; band < meta->stats->band_count; band++) { /* Find min, max, and mean values */ if (!quietflag) printf("\n"); if (logflag && !quietflag) fprintf(fLog,"\n"); min = 100000000; max = -100000000; sum_of_samples=0.0; sum_of_squared_samples=0.0; percent_complete=0; band_offset = band * meta->general->line_count; sar_file = FOPEN(sar_name, "r"); for (line=start_line+band_offset; line<start_line+window_height+band_offset; line++) { if (!quietflag) asfPercentMeter((float)(line-start_line-band_offset)/(float)(window_height-start_line)); get_float_line(sar_file, meta, line, data_line); for (sample=start_sample; sample<start_sample+window_width; sample++) { if ( mask_flag && FLOAT_EQUIVALENT(data_line[sample],mask) ) continue; if (data_line[sample] < min) min=data_line[sample]; if (data_line[sample] > max) max=data_line[sample]; sum_of_samples += data_line[sample]; sum_of_squared_samples += SQR(data_line[sample]); samples_counted++; } } if (!quietflag) asfPercentMeter(1.0); // if (!quietflag) printf("\rFirst data sweep: 100%% complete.\n"); FCLOSE(sar_file); stats[band].min = min; stats[band].max = max; stats[band].upper_left_line = start_line; stats[band].upper_left_samp = start_sample; stats[band].lower_right_line = start_line + window_height; stats[band].lower_right_samp = start_sample + window_width; stats[band].mask = mask; stats[band] = calc_hist(stats[band], sar_name, band, meta, sum_of_samples, samples_counted, mask_flag); /* Remove outliers and trim the histogram by resetting the minimum and and maximum */ if (trim_flag) { register int sum=0, num_pixels, minDex=0, maxDex=255; double overshoot, width; num_pixels = (int)(samples_counted*trim_fraction); minDex = 0; while (sum < num_pixels) sum += stats[band].histogram[minDex++]; if (minDex-1>=0) overshoot = (double)(num_pixels-sum)/stats[band].histogram[minDex-1]; else overshoot = 0; stats[band].min = (minDex-overshoot-stats[band].offset)/stats[band].slope; sum=0; while (sum < num_pixels) sum += stats[band].histogram[maxDex--]; if (maxDex+1<256) overshoot = (double)(num_pixels-sum)/stats[band].histogram[maxDex+1]; else overshoot = 0; stats[band].max = (maxDex+1+overshoot-stats[band].offset)/stats[band].slope; /* Widening the range for better visual effect */ width = (stats[band].max-stats[band].min)*(1/(1.0-2*trim_fraction)-1); stats[band].min -= width/2; stats[band].max += width/2; /* Couple useful corrections borrowed from SARview */ if ((stats[band].max-stats[band].min) < 0.01*(max-min)) { stats[band].max = max; stats[band].min = min; } if (min == 0.0) stats[band].min=0.0; if (stats[band].min == stats[band].max) stats[band].max = stats[band].min + MICRON; stats[band].slope = 255.0/(stats[band].max-stats[band].min); stats[band].offset = -stats[band].slope*stats[band].min; stats[band] = calc_hist(stats[band], sar_name, band, meta, sum_of_samples, samples_counted, mask_flag); } } if(data_line)FREE(data_line); /* Populate meta->stats structure */ char **band_names = NULL; if (meta_is_valid_string(meta->general->bands) && strlen(meta->general->bands) && meta->general->band_count > 0) { band_names = extract_band_names(meta->general->bands, meta->general->band_count); } else { if (meta->general->band_count <= 0) meta->general->band_count = 1; band_names = (char **) MALLOC (meta->general->band_count * sizeof(char *)); int i; for (i=0; i<meta->general->band_count; i++) { band_names[i] = (char *) MALLOC (64 * sizeof(char)); sprintf(band_names[i], "%02d", i); } } int band_no; for (band_no = 0; band_no < meta->stats->band_count; band_no++) { strcpy(meta->stats->band_stats[band_no].band_id, band_names[band_no]); meta->stats->band_stats[band_no].min = stats[band_no].min; meta->stats->band_stats[band_no].max = stats[band_no].max; meta->stats->band_stats[band_no].mean = stats[band_no].mean; meta->stats->band_stats[band_no].rmse = stats[band_no].rmse; meta->stats->band_stats[band_no].std_deviation = stats[band_no].std_deviation; meta->stats->band_stats[band_no].mask = stats[band_no].mask; } if (band_names) { int i; for (i=0; i<meta->general->band_count; i++) { if (band_names[i]) FREE (band_names[i]); } FREE(band_names); } /* Print findings to the screen (and log file if applicable)*/ if (!quietflag) { printf("\n"); printf("Statistics found:\n"); if (mask_flag) { printf("Used mask %-16.11g\n",mask); } printf("Number of bands: %d\n", meta->stats->band_count); for (band=0; band<meta->stats->band_count; band++) { printf("\n\nBand name = \"%s\"\n", meta->stats->band_stats[band].band_id); printf("Minimum = %-16.11g\n",stats[band].min); printf("Maximum = %-16.11g\n",stats[band].max); printf("Mean = %-16.11g\n",stats[band].mean); printf("Root mean squared error = %-16.11g\n", stats[band].rmse); printf("Standard deviation = %-16.11g\n", stats[band].std_deviation); printf("\n"); printf("Data fit to [0..255] using equation: byte = %g * sample + %g\n", stats[band].slope, stats[band].offset); if (trim_flag) printf("Trimming fraction = %.3g\n", trim_fraction); printf("\n"); printf("Histogram:\n"); for (ii=0; ii<256; ii++) { if (ii%8 == 0) { printf("%s%3i-%3i:", (ii==0) ? "" : "\n", ii, ii+7); } printf(" %8i", stats[band].histogram[ii]); } printf("\n"); } } if (logflag && !quietflag) { fprintf(fLog,"Statistics found:\n"); if (mask_flag) { fprintf(fLog,"Used mask %-16.11g\n",mask); } fprintf(fLog,"Number of bands: %d\n", meta->stats->band_count); for (band=0; band<meta->stats->band_count; band++) { fprintf(fLog,"\n\nBand name = \"%s\"\n", meta->stats->band_stats[band].band_id); fprintf(fLog,"Minimum = %-16.11g\n",stats[band].min); fprintf(fLog,"Maximum = %-16.11g\n",stats[band].max); fprintf(fLog,"Mean = %-16.11g\n",stats[band].mean); fprintf(fLog,"Root mean squared error = %-16.11g\n", stats[band].rmse); fprintf(fLog,"Standard deviation = %-16.11g\n", stats[band].std_deviation); fprintf(fLog,"\n"); fprintf(fLog,"Data fit to [0..255] using equation: byte = %g * sample + %g\n", stats[band].slope, stats[band].offset); if (trim_flag) fprintf(fLog,"Trimming fraction = %.3g\n", trim_fraction); fprintf(fLog,"\n"); fprintf(fLog,"Histogram:\n"); for (ii=0; ii<256; ii++) { if (ii%8 == 0) { fprintf(fLog,"%s%3i-%3i:", (ii==0) ? "" : "\n", ii, ii+7); } fprintf(fLog," %8i", stats[band].histogram[ii]); } fprintf(fLog,"\n"); } } /* Write out .meta and .stat files */ if (!nometa_flag) meta_write(meta, meta_name); if (!nostat_flag) stat_write(stats, stat_name, meta->stats->band_count); /* Free the metadata structure */ meta_free(meta); /* Report */ if (!quietflag) { printf("\n"); printf("Statistics taken on image file %s.\n",sar_name); if (!nometa_flag) printf("Statistics written to the stats block in %s.\n", meta_name); if (!nostat_flag) printf("Statistics plus histogram written to %s.\n", stat_name); printf("\n"); } if (logflag && !quietflag) { fprintf(fLog,"\n"); fprintf(fLog,"Statistics taken on image file '%s'\n",sar_name); if (!nometa_flag) fprintf(fLog,"Statistics written to the stats block in %s\n", meta_name); if (!nostat_flag) fprintf(fLog,"Statistics plus histogram written to %s\n", stat_name); fprintf(fLog,"\n"); } if (fLog) FCLOSE(fLog); return 0; }
// if png_flag is true, outputs a PNG. if false, outputs a jpeg static void patchToRGBImage(char *outname, int png_flag) { update_status("Generating %s", outname); if (!quietflag) printf(" Outputting Debugging image '%s'...\n",outname); // input name is just the output name with ".img" char *polar_name = MALLOC((strlen(outname)+20)*sizeof(char)); sprintf(polar_name, "%s_polar.img", outname); // will multilook, as well as conver to polar, generates a 2-band // file (amplitude is band 1, phase is band 2) c2p(outname,polar_name,FALSE,TRUE); // prepare for RGB conversion int i,j; meta_parameters *meta = meta_read(polar_name); int nl = meta->general->line_count; int ns = meta->general->sample_count; float *amp = MALLOC(sizeof(float)*ns); float *phase = MALLOC(sizeof(float)*ns); unsigned char *red = MALLOC(sizeof(unsigned char)*ns); unsigned char *grn = MALLOC(sizeof(unsigned char)*ns); unsigned char *blu = MALLOC(sizeof(unsigned char)*ns); FILE *fp = fopenImage(polar_name, "rb"); const double TWOPI=2.*PI; const double PIOVER3=PI/3.; int n=0; // first/second passes are stats gathering asfPrintStatus("Gathering stats...\n"); double avg=0, stddev=0; for (i=0; i<nl; i+=3) { get_float_line(fp,meta,i,amp); for (j=0; j<ns; j+=3) { avg += amp[j]; ++n; } asfPercentMeter((float)i/((float)nl*2.)); } avg /= (double)n; for (i=0; i<nl; i+=3) { get_float_line(fp,meta,i,amp); for (j=0; j<ns; j+=3) { stddev += (amp[j]-avg)*(amp[j]-avg); } asfPercentMeter((float)(i+nl)/((float)nl*2.)); } asfPercentMeter(1); stddev = sqrt(stddev/(double)n); double min = avg - 2*stddev; double max = avg + 2*stddev; // open up PNG/JPEG output file FILE *ofp=NULL; struct jpeg_compress_struct cinfo; png_structp png_ptr; png_infop png_info_ptr; char *jpgname = NULL; char *pngname = NULL; if (png_flag) { asfPrintStatus("Generating debug image (PNG)...\n"); pngname = appendExt(outname, ".png"); initialize_png_file(pngname,meta,&ofp,&png_ptr,&png_info_ptr,TRUE); } else { asfPrintStatus("Generating debug image (JPEG)...\n"); jpgname = appendExt(outname, ".jpg"); initialize_jpeg_file(jpgname,meta,&ofp,&cinfo,TRUE); } // now read in the polar image, calculate RGB values, write to jpeg/png for (i=0; i<nl; ++i) { get_band_float_line(fp,meta,0,i,amp); get_band_float_line(fp,meta,1,i,phase); for (j=0; j<ns; ++j) { // scale to 2-sigma, to get brightness of the pixel unsigned char intensity; //=(unsigned char)(amp[j] * 128./(float)avg * 41./255.); if (amp[j]<=min) intensity=0; else if (amp[j]>=max) intensity=255; else intensity=(unsigned char)((amp[j]-min)/(max-min)*255.); // color of the pixel is determined by the phase unsigned char r=0,g=0,b=0; if (phase[j]<-PI) phase[j]+=TWOPI; // ensure [-PI, PI) if (phase[j]>=PI) phase[j]-=TWOPI; int range = (int)((phase[j]+PI)/PIOVER3); // will be 0-6 (and rarely 6) switch (range) { case 0: r=1; break; case 1: r=1; g=1; break; case 2: g=1; break; case 3: g=1; b=1; break; case 4: b=1; break; case 5: r=1; b=1; break; case 6: break; // left black default: printf("phase: %f, range: %d\n", phase[j], range); assert(FALSE); break; } red[j] = r*intensity; grn[j] = g*intensity; blu[j] = b*intensity; } // write the line if (png_flag) write_rgb_png_byte2byte(ofp,red,grn,blu,png_ptr,png_info_ptr,ns); else write_rgb_jpeg_byte2byte(ofp,red,grn,blu,&cinfo,ns); // keep the user interested! asfPercentMeter((float)i/((float)nl)); } asfPercentMeter(1.0); // clean up FCLOSE(fp); FREE(amp); FREE(phase); FREE(red); FREE(grn); FREE(blu); meta_free(meta); if (png_flag) finalize_png_file(ofp,png_ptr,png_info_ptr); else finalize_jpeg_file(ofp,&cinfo); FREE(jpgname); FREE(pngname); clean(polar_name); FREE(polar_name); }
void calc_minmax_median(const char *inFile, char *band, double mask, double *min, double *max) { long long ii, jj; float logeps = 10.0 * log10(EPSILON); float median, median0; meta_parameters *meta = meta_read(inFile); int band_number = (!band || strlen(band) == 0 || strcmp(band, "???") == 0) ? 0 : get_band_number(meta->general->bands, meta->general->band_count, band); long sample_count = meta->general->sample_count; long line_count = meta->general->line_count; long pixel_count = sample_count*line_count; long offset = line_count * band_number; float *data_line = MALLOC(sizeof(float) * sample_count); float *data = MALLOC(sizeof(float) * pixel_count); float *data2 = MALLOC(sizeof(float) * pixel_count); // Culling invalid pixels FILE *fp = FOPEN(inFile, "rb"); long valid_pixel_count = 0; asfPrintStatus("\nCalculating min and max using median...\n"); for (ii=0; ii<line_count; ++ii) { get_float_line(fp, meta, ii + offset, data_line); asfPercentMeter(((double)ii/(double)line_count)); for (jj=0; jj<sample_count; ++jj) { if (!FLOAT_EQUIVALENT(data_line[jj], -9999.99) || !FLOAT_EQUIVALENT(data_line[jj], logeps) || ISNAN(mask)) { data[valid_pixel_count] = data_line[jj]; valid_pixel_count++; } } } asfPercentMeter(1.0); FCLOSE(fp); FREE(data_line); // Determine initial min and max *min = INIT_MINMAX; *max = -INIT_MINMAX; float minmin = INIT_MINMAX; float maxmax = -INIT_MINMAX; for (ii=0; ii<valid_pixel_count; ++ii) { data2[ii] = data[ii]; if (data[ii] < minmin) minmin = data[ii]; if (data[ii] > maxmax) maxmax = data[ii]; } median0 = median_value(data, valid_pixel_count); // Determine minimum median = median0; *min = median0; for (ii=0; ii<3; ii++) { pixel_count = -1; for (jj=0; jj<valid_pixel_count; ++jj) if (median0 == minmin) { if (data[jj] <= median) { pixel_count++; data2[pixel_count] = data[jj]; } } else { if (data[jj] < median) { pixel_count++; data2[pixel_count] = data[jj]; } } median = median_value(data2, pixel_count); if (median == minmin) median = *min; *min = median; } // Determine maximum median = median0; *max = median0; for (ii=0; ii<3; ii++) { pixel_count = -1; for (jj=0; jj<valid_pixel_count; ++jj) if (median0 == maxmax) { if (data[jj] >= median) { pixel_count++; data2[pixel_count] = data[jj]; } } else { if (data[jj] > median) { pixel_count++; data2[pixel_count] = data[jj]; } } median = median_value(data2, pixel_count); if (median == maxmax) median = *max; *max = median; } FREE(data); FREE(data2); }
void calc_stats_rmse_from_file(const char *inFile, char *band, double mask, double *min, double *max, double *mean, double *stdDev, double *rmse, gsl_histogram **histogram) { double se; int ii,jj; *min = 999999; *max = -999999; *mean = 0.0; meta_parameters *meta = meta_read(inFile); int band_number = (!band || strlen(band) == 0 || strcmp(band, "???") == 0) ? 0 : get_band_number(meta->general->bands, meta->general->band_count, band); long offset = meta->general->line_count * band_number; float *data = MALLOC(sizeof(float) * meta->general->sample_count); // pass 1 -- calculate mean, min & max FILE *fp = FOPEN(inFile, "rb"); long long pixel_count=0; asfPrintStatus("\nCalculating min, max, and mean...\n"); for (ii=0; ii<meta->general->line_count; ++ii) { asfPercentMeter(((double)ii/(double)meta->general->line_count)); get_float_line(fp, meta, ii + offset, data); for (jj=0; jj<meta->general->sample_count; ++jj) { if (ISNAN(mask) || !FLOAT_EQUIVALENT(data[jj], mask)) { if (data[jj] < *min) *min = data[jj]; if (data[jj] > *max) *max = data[jj]; *mean += data[jj]; ++pixel_count; } } } asfPercentMeter(1.0); FCLOSE(fp); *mean /= pixel_count; // Guard against weird data if(!(*min<*max)) *max = *min + 1; // Initialize the histogram. const int num_bins = 256; gsl_histogram *hist = gsl_histogram_alloc (num_bins); gsl_histogram_set_ranges_uniform (hist, *min, *max); *stdDev = 0.0; // pass 2 -- update histogram, calculate standard deviation fp = FOPEN(inFile, "rb"); asfPrintStatus("\nCalculating standard deviation, rmse, and histogram...\n"); se = 0.0; for (ii=0; ii<meta->general->line_count; ++ii) { asfPercentMeter(((double)ii/(double)meta->general->line_count)); get_float_line(fp, meta, ii + offset, data); for (jj=0; jj<meta->general->sample_count; ++jj) { if (ISNAN(mask) || !FLOAT_EQUIVALENT(data[jj], mask)) { *stdDev += (data[jj] - *mean) * (data[jj] - *mean); gsl_histogram_increment (hist, data[jj]); se += (data[jj] - *mean) * (data[jj] - *mean); } } } asfPercentMeter(1.0); FCLOSE(fp); *stdDev = sqrt(*stdDev/(pixel_count - 1)); *rmse = sqrt(se/(pixel_count - 1)); FREE(data); *histogram = hist; }
void calc_stats_from_file_with_formula(const char *inFile, char *bands, calc_stats_formula_t formula_callback, double mask, double *min, double *max, double *mean, double *stdDev, gsl_histogram **histogram) { int ii,jj,kk; const int N=MAX_BANDS; *min = 999999; *max = -999999; *mean = 0.0; meta_parameters *meta = meta_read(inFile); int band_numbers[N]; for (ii=0; ii<N; ++ii) band_numbers[ii] = -1; int band_count = 0; if (bands) { char *s = STRDUP(bands); // a copy we can fiddle with char *q, *p = s; do { q = strchr(p, ','); if (q) *q = '\0'; if (strlen(p) > 0 && strcmp(p, "???") != 0) { band_numbers[band_count] = get_band_number(meta->general->bands, meta->general->band_count, p); //printf("%s -> %d\n", p, band_numbers[band_count]); ++band_count; } if (q) p = q+1; } while (q); FREE(s); } long band_offsets[N]; float *band_data[N]; for (ii=0; ii<N; ++ii) { if (band_numbers[ii] >= 0) { band_offsets[ii] = meta->general->line_count * band_numbers[ii]; band_data[ii] = MALLOC(sizeof(float)*meta->general->sample_count); } else { band_offsets[ii] = -1; band_data[ii] = NULL; } } // pass 1 -- calculate mean, min & max FILE *fp = FOPEN(inFile, "rb"); long long pixel_count=0; asfPrintStatus("\nCalculating min, max, and mean...\n"); for (ii=0; ii<meta->general->line_count; ++ii) { asfPercentMeter((double)ii/(double)meta->general->line_count); for (kk=0; kk<N; ++kk) { if (band_data[kk]) { assert(band_offsets[kk] >= 0); get_float_line(fp, meta, ii + band_offsets[kk], band_data[kk]); } } for (jj=0; jj<meta->general->sample_count; ++jj) { int is_masked = FALSE; if (ISNAN(mask)) { for (kk=0; kk<N; ++kk) if (band_data[kk] && FLOAT_EQUIVALENT(band_data[kk][jj], mask)) is_masked = TRUE; } if (!is_masked) { double data_arr[N]; int ll; for (ll=0, kk=0; kk<N; ++kk) if (band_data[kk]) data_arr[ll++] = band_data[kk][jj]; assert(ll==band_count); double val = formula_callback(data_arr, mask); if (val < *min) *min = val; if (val > *max) *max = val; *mean += val; ++pixel_count; } } } asfPercentMeter(1.0); FCLOSE(fp); *mean /= pixel_count; // Guard against weird data if(!(*min<*max)) *max = *min + 1; // Initialize the histogram. const int num_bins = 256; gsl_histogram *hist = gsl_histogram_alloc (num_bins); gsl_histogram_set_ranges_uniform (hist, *min, *max); *stdDev = 0.0; // pass 2 -- update histogram, calculate standard deviation fp = FOPEN(inFile, "rb"); asfPrintStatus("\nCalculating standard deviation and histogram...\n"); for (ii=0; ii<meta->general->line_count; ++ii) { asfPercentMeter((double)ii/(double)meta->general->line_count); for (kk=0; kk<N; ++kk) { if (band_data[kk]) { assert(band_offsets[kk] >= 0); get_float_line(fp, meta, ii + band_offsets[kk], band_data[kk]); } } for (jj=0; jj<meta->general->sample_count; ++jj) { int is_masked = FALSE; if (ISNAN(mask)) { for (kk=0; kk<N; ++kk) if (band_data[kk] && FLOAT_EQUIVALENT(band_data[kk][jj], mask)) is_masked = TRUE; } if (!is_masked) { double data_arr[N]; int ll; for (ll=0, kk=0; kk<N; ++kk) if (band_data[kk]) data_arr[ll++] = band_data[kk][jj]; assert(ll==band_count); double val = formula_callback(data_arr, mask); *stdDev += (val - *mean) * (val - *mean); gsl_histogram_increment (hist, val); } } } asfPercentMeter(1.0); FCLOSE(fp); *stdDev = sqrt(*stdDev/(pixel_count - 1)); for (ii=0; ii<N; ++ii) if (band_data[ii]) FREE(band_data[ii]); *histogram = hist; }
void c2p_ext(const char *inDataName, const char *inMetaName, const char *outfile, int multilook, int banded) { meta_parameters *in_meta = meta_read(inMetaName); int data_type = in_meta->general->data_type; // the old code did this, but why?? in_meta->general->data_type = meta_polar2complex(data_type); // some sanity checks switch (data_type) { case COMPLEX_BYTE: case COMPLEX_INTEGER16: case COMPLEX_INTEGER32: case COMPLEX_REAL32: case COMPLEX_REAL64: break; default: asfPrintError("c2p: %s is not a complex image.\n", inDataName); } if (in_meta->general->band_count != 1) asfPrintError("c2p: %s is not a single-band image.\n", inDataName); if (!in_meta->sar) asfPrintError("c2p: %s is missing a SAR block.\n", inDataName); asfPrintStatus("Converting complex image to amplitude/phase...\n"); int nl = in_meta->general->line_count; int ns = in_meta->general->sample_count; // process 1 line at a time when not multilooking, otherwise grab nlooks int nlooks = multilook ? in_meta->sar->look_count : 1; if (nlooks == 1 && multilook) { asfPrintStatus("Not multilooking, look_count is 1.\n"); multilook = FALSE; } if (multilook) asfPrintStatus("Multilooking with %d looks.\n", nlooks); meta_parameters *out_meta = meta_read(inMetaName); out_meta->general->data_type = meta_complex2polar(data_type); // set up input/output files FILE *fin = fopenImage(inDataName, "rb"); // we either have 1 or 2 output files, per the "banded" flag. char *outfile_img = appendExt(outfile, ".img"); char *amp_name=NULL, *phase_name=NULL; FILE *fout_banded=NULL, *fout_amp=NULL, *fout_phase=NULL; if (banded) { asfPrintStatus("Output is 2-band image: %s\n", outfile_img); fout_banded = fopenImage(outfile_img, "wb"); } else { amp_name = appendToBasename(outfile_img, "_amp"); phase_name = appendToBasename(outfile_img, "_phase"); asfPrintStatus("Output amplitude file: %s\n", amp_name); asfPrintStatus("Output phase file: %s\n", phase_name); fout_amp = fopenImage(amp_name, "wb"); fout_phase = fopenImage(phase_name, "wb"); } if (banded) assert(fout_banded && !fout_amp && !fout_phase); else assert(!fout_banded && fout_amp && fout_phase); // get the metadata band_count correct, needed in the put_* calls if (banded) { out_meta->general->band_count = 2; strcpy(out_meta->general->bands, "AMP,PHASE"); } // input buffer complexFloat *cpx = MALLOC(sizeof(complexFloat)*ns*nlooks); // output buffers float *amp = MALLOC(sizeof(float)*ns*nlooks); float *phase = MALLOC(sizeof(float)*ns*nlooks); int line_in; // line in the input image int line_out=0; // line in the output image int samp; // sample #, loop index int l; // line loop index, iterates over the lines in the block out_meta->general->line_count = (int)ceil((double)nl/(double)nlooks); for (line_in=0; line_in<nl; line_in+=nlooks) { // lc = "line count" -- how many lines to read. normally we will read // nlooks lines, but near eof we might have to read fewer int lc = nlooks; if (line_in + lc > nl) lc = nl - line_in; // read "nlooks" (or possibly fewer, if near eof) lines of data int blockSize = get_complexFloat_lines(fin,in_meta,line_in,lc,cpx); if (blockSize != lc*ns) asfPrintError("bad blockSize: bs=%d nlooks=%d ns=%d\n", blockSize, nlooks, ns); // first, compute the power/phase for (l=0; l<lc; ++l) { for (samp=0; samp<ns; ++samp) { int k = l*ns + samp; // index into the block float re = cpx[k].real; float im = cpx[k].imag; if (re != 0.0 || im != 0.0) { amp[k] = re*re + im*im; phase[k] = atan2(im, re); } else { amp[k] = phase[k] = 0.0; } } } // now multilook, if requested if (multilook) { // put the multilooked data in the first "row" of amp,phase for (samp=0; samp<ns; ++samp) { float value = 0.0; for (l=0; l<lc; ++l) value += amp[l*ns + samp]; amp[samp] = sqrt(value/(float)lc); value = 0.0; for (l=0; l<lc; ++l) value += phase[l*ns + samp]; phase[samp] = value/(float)lc; } } else { for (samp=0; samp<ns*lc; ++samp) amp[samp] = sqrt(amp[samp]); } // write out a line (multilooked) or a bunch of lines (not multi) if (multilook) { if (banded) { put_band_float_line(fout_banded, out_meta, 0, line_out, amp); put_band_float_line(fout_banded, out_meta, 1, line_out, phase); } else { put_float_line(fout_amp, out_meta, line_out, amp); put_float_line(fout_phase, out_meta, line_out, phase); } ++line_out; } else { for (l=0; l<lc; ++l) { if (banded) { put_band_float_line(fout_banded, out_meta, 0, line_in+l, amp); put_band_float_line(fout_banded, out_meta, 1, line_in+l, phase); } else { put_float_line(fout_amp, out_meta, line_in+l, amp); put_float_line(fout_phase, out_meta, line_in+l, phase); } ++line_out; } } asfPercentMeter((float)line_in/(float)(nl)); } asfPercentMeter(1.0); fclose(fin); if (fout_banded) fclose(fout_banded); if (fout_amp) fclose(fout_amp); if (fout_phase) fclose(fout_phase); if (multilook) { if (out_meta->general->line_count != line_out) asfPrintError("Line counts don't match: %d != %d\n", out_meta->general->line_count, line_out); out_meta->general->y_pixel_size *= nlooks; out_meta->sar->azimuth_time_per_pixel *= nlooks; out_meta->sar->multilook = TRUE; } else assert(line_out == nl); // write out the metadata, different whether multi-banded or not if (banded) { assert(!amp_name && !phase_name); meta_write(out_meta, outfile); } else { assert(amp_name && phase_name); out_meta->general->image_data_type = AMPLITUDE_IMAGE; meta_write(out_meta, amp_name); out_meta->general->image_data_type = PHASE_IMAGE; meta_write(out_meta, phase_name); } if (multilook) asfPrintStatus("Original line count: %d, after multilooking: %d " "(%d looks)\n", nl, line_out, nlooks); meta_free(in_meta); meta_free(out_meta); FREE(amp); FREE(phase); FREE(cpx); FREE(outfile_img); FREE(amp_name); FREE(phase_name); }
int plan(const char *satellite, const char *beam_mode, double look_angle, long startdate, long enddate, double min_lat, double max_lat, double clat, double clon, int pass_type, int zone, Poly *aoi, const char *tle_filename, PassCollection **pc_out, char **errorstring) { BeamModeInfo *bmi = get_beam_mode_info(satellite, beam_mode); if (!bmi) { *errorstring = STRDUP("Unknown satellite/beam mode combination.\n"); return -1; } // Convert the input start/end times from longdates (dates as long ints) // to seconds from some reference time. (midnight jan 1, 1900) // We add a day to the end date, so that the passed-in range is inclusive double start_secs = seconds_from_long(startdate); double end_secs = seconds_from_long(add_a_day(enddate)); sat_t sat; read_tle(tle_filename, satellite, &sat); // if the planned acquisition period is further away than this amount, // we subtract multiples of the repeat cyle time until we are within // this threshold time of this tle double tle_time = time_to_secs(sat.tle.epoch_year, sat.tle.epoch_day, sat.tle.epoch_fod); // FIXME this is alos specific FIXME!! // should really read this out of a config file... or calculate it // from the TLE info? const double repeat_days = 46; const double orbits_per_cycle = 671; // repeat time, in seconds, all time references are in seconds double repeat_cycle_time = repeat_days * 24.*60.*60.; // how many days to pad the repeat cycle time, before modding the // start/end time const double days_of_padding = 5; // this is the cutoff, double threshold = repeat_cycle_time + 24*60*60 * days_of_padding; int cycles_adjustment=0; if (start_secs-tle_time > threshold) { while (start_secs-tle_time > threshold) { start_secs -= repeat_cycle_time; end_secs -= repeat_cycle_time; ++cycles_adjustment; } } else if (tle_time-start_secs > threshold) { // planning backwards... while (tle_time-start_secs > threshold) { start_secs += repeat_cycle_time; end_secs += repeat_cycle_time; --cycles_adjustment; } } double time_adjustment = cycles_adjustment*repeat_cycle_time; if (cycles_adjustment != 0) asfPrintStatus("Adjusted start/end times %s by %d repeat cycle%s.\n", cycles_adjustment > 0 ? "forward" : "backward", cycles_adjustment > 0 ? cycles_adjustment : -cycles_adjustment, cycles_adjustment == 1 || cycles_adjustment == -1 ? "" : "s"); // no deep space orbits can be planned assert((sat.flags & DEEP_SPACE_EPHEM_FLAG) == 0); if (is_utm(zone)) { asfPrintStatus("Target: UTM zone %d\n" " (%10.2f, %10.2f) (%10.2f, %10.2f)\n" " (%10.2f, %10.2f) (%10.2f, %10.2f)\n", zone, aoi->x[0], aoi->y[0], aoi->x[1], aoi->y[1], aoi->x[2], aoi->y[2], aoi->x[3], aoi->y[3]); } else { asfPrintStatus("Target: Polar Stereo %s\n" " (%10.2f, %10.2f) (%10.2f, %10.2f)\n" " (%10.2f, %10.2f) (%10.2f, %10.2f)\n", zone>0 ? "North" : "South", aoi->x[0], aoi->y[0], aoi->x[1], aoi->y[1], aoi->x[2], aoi->y[2], aoi->x[3], aoi->y[3]); } double curr = start_secs; double incr = bmi->image_time; stateVector st = tle_propagate(&sat, start_secs-incr); double lat_prev = sat.ssplat; int i,num_found = 0; // // Calculate the number of frames to include before we hit the // area of interest. Add 1 (i.e., round up), but if user puts in // zero seconds, then we want 0 lead-up frames. PassCollection *pc = pass_collection_new(clat, clon, aoi); asfPrintStatus("Searching...\n"); while (curr < end_secs) { st = tle_propagate(&sat, curr); char dir = sat.ssplat > lat_prev ? 'A' : 'D'; if ((dir=='A' && pass_type!=DESCENDING_ONLY) || (dir=='D' && pass_type!=ASCENDING_ONLY)) { OverlapInfo *oi = overlap(curr, &st, bmi, look_angle, zone, clat, clon, aoi); if (oi) { int n=0; // Calculate the orbit number -- we have to fudge this if we // modded the start time. int orbit_num = sat.orbit + orbits_per_cycle*cycles_adjustment; // This is an alternate way of calculating the orbit number that // was being used during testing... seems to produce numbers close // to (within 1) of the number obtained by sgpsdp... //double secs_per_orbit = repeat_cycle_time / orbits_per_cycle; // ALOS was launced on 1/24/06 //double launch_secs = seconds_from_long(20060124); //double orbit_num2 = (curr - launch_secs) / secs_per_orbit; //orbit_num2 += orbits_per_cycle*cycles_adjustment; //printf("%f %f %f\n", orbit_num + sat.orbit_part, // orbit_num2, orbit_num+sat.orbit_part-orbit_num2); // UPDATE!! All this orbit number calculation business doesn't get // used for ALOS planning -- orbit number is re-calculated using // time since a refrence orbit. // See planner.c -- get_alos_orbit_number_at_time() PassInfo *pass_info = pass_info_new(orbit_num, sat.orbit_part, dir); double start_time = curr - bmi->num_buffer_frames*incr; // add on the buffer frames before the area of interest for (i=bmi->num_buffer_frames; i>0; --i) { double t = curr - i*incr; stateVector st1 = tle_propagate(&sat, t); double rclat, rclon; // viewable region center lat/lon Poly *region = get_viewable_region(&st1, bmi, look_angle, zone, clat, clon, &rclat, &rclon); if (region) { OverlapInfo *oi1 = overlap_new(0, 1000, region, zone, clat, clon, &st1, t); pass_info_add(pass_info, t+time_adjustment, oi1); if (pass_info->start_lat == -999) { // at the first valid buffer frame -- set starting latitude double start_lat, end_lat; get_latitude_range(region, zone, dir, &start_lat, &end_lat); pass_info_set_start_latitude(pass_info, start_lat); } } } // add the frames that actually image the area of interest while (curr < end_secs && oi) { pass_info_add(pass_info, curr+time_adjustment, oi); ++n; curr += incr; st = tle_propagate(&sat, curr); oi = overlap(curr, &st, bmi, look_angle, zone, clat, clon, aoi); } double end_time = curr + (bmi->num_buffer_frames-1)*incr; pass_info_set_duration(pass_info, end_time-start_time); // add on the buffer frames after the area of interest for (i=0; i<bmi->num_buffer_frames; ++i) { double t = curr + i*incr; stateVector st1 = tle_propagate(&sat, t); double rclat, rclon; // viewable region center lat/lon Poly *region = get_viewable_region(&st1, bmi, look_angle, zone, clat, clon, &rclat, &rclon); if (region) { OverlapInfo *oi1 = overlap_new(0, 1000, region, zone, clat, clon, &st1, t); pass_info_add(pass_info, t+time_adjustment, oi1); // set stopping latitude -- each frame overwrites the previous, // so the last valid frame will set the stopping latitude double start_lat, end_lat; get_latitude_range(region, zone, dir, &start_lat, &end_lat); pass_info_set_stop_latitude(pass_info, end_lat); } } // make sure we set all the required "after the fact" info // if not, then do not add the pass... must be invalid // (these used to be asserts, so it doesn't seem to ever happen) if (n>0 && pass_info->start_lat != -999 && pass_info->stop_lat != -999 && pass_info->duration != -999) { // add the pass! pass_collection_add(pc, pass_info); ++num_found; } else { asfPrintStatus("Invalid pass found. Skipped... \n" " -- number of frames: %d, dir: %c\n" " -- date: %s, orbit %d, %f\n --> (%f,%f,%f)\n", n, pass_info->dir, pass_info->start_time_as_string, pass_info->orbit, pass_info->orbit_part, pass_info->start_lat, pass_info->stop_lat, pass_info->duration); } } } curr += incr; lat_prev = sat.ssplat; //printf("Lat: %f, Orbit: %d, Orbit Part: %f\n", sat.ssplat, // (int)sat.orbit, sat.orbit_part); asfPercentMeter((curr-start_secs)/(end_secs-start_secs)); } asfPercentMeter(1.0); *pc_out = pc; return num_found; }