32 #include <sys/types.h>
42 #include <gsl/gsl_math.h>
43 #include <gsl/gsl_spline.h>
44 #include <gsl/gsl_sort.h>
45 #include <gsl/gsl_statistics.h>
52 static int geoNavigationGrp;
53 static int geoGeolocationGrp;
54 static int geoScanLineGrp;
55 static int l1aScanLineGrp;
56 static int l1aTelemetryGrp;
57 static int l1aNavigationGrp;
58 static int l1aEarthViewGrp;
59 static int lonId, latId, senzId, senaId, solzId, solaId,
60 angId, posId, velId, pixelQualityId;
61 static int scanDeltaTimeId;
64 static short *tmpShort;
65 static unsigned char *tmpByte;
66 static size_t num_scans, num_pixels, num_bands;
68 static int firstCall = 1;
70 static double lastvalidtime;
71 static int lastvalidscan = 0;
72 static double time_interval;
74 static float latGeoFillValue = -999.9;
75 static float lonGeoFillValue = -999.9;
76 static short senzGeoFillValue = -32768;
77 static short senaGeoFillValue = -32768;
78 static short solzGeoFillValue = -32768;
79 static short solaGeoFillValue = -32768;
81 static float latL2FillValue = -999.0;
82 static float lonL2FillValue = -999.0;
83 static float senzL2FillValue = -32767;
84 static float senaL2FillValue = -32767;
85 static float solzL2FillValue = -32767;
86 static float solaL2FillValue = -32767;
88 static int32_t scanDeltaTimeFillValue = -999;
89 static int32_t scanDeltaTimeValidMin = 0;
90 static int32_t scanDeltaTimeValidMax = 200000;
93 static size_t num_ccd_temps, num_tlm_blocks, num_tlm_blocks_cleansed;
94 static double **CCD_temperatures;
95 static double **CCD_temperatures_cleansed;
96 static double CCD_temperature_default = 35.0;
97 static double *tlm_delta_time_ms;
98 static double *tlm_delta_time_ms_cleansed;
99 static float fill_value_in_CCD_T;
100 static int *dn_varid;
101 static double *CCD_temperatures_this_scan;
102 static unsigned short *dn;
103 static double **bkg_avg;
105 static uint32_t darkSubtracted;
106 static uint32_t darkHeight;
109 static size_t cal_num_dates;
110 static size_t cal_num_temperatures;
111 static double *time_ref;
112 static double *temperature_ref;
119 static unsigned short **nominal_dark_counts;
122 static int *track_offset;
123 static int *ccd_offset;
125 static int reference_band;
126 static int reference_pixel;
129 static int skip_beglines;
130 static int skip_endlines;
131 static int shutter_rampdown;
132 static int default_darkrows;
133 static uint32_t firstbad;
143 double nan_wmean(
double *weights,
double *
data,
size_t n,
double fill_value);
164 int ncid_L1A, varid, dimid,
status;
168 char nc_search_string[10] =
"";
172 printf(
"Opening Hawkeye L1A file\n");
173 status = nc_open(
file->name, NC_NOWRITE, &ncid_L1A);
175 fprintf(
stderr,
"-E- Error opening L1A file \"%s\": %s\n",
183 TRY_NC(__FILE__, __LINE__, nc_inq_dimid(ncid_L1A,
"number_of_scans", &dimid));
184 nc_inq_dimlen(ncid_L1A, dimid, &num_scans);
185 TRY_NC(__FILE__, __LINE__, nc_inq_dimid(ncid_L1A,
"number_of_bands", &dimid));
186 nc_inq_dimlen(ncid_L1A, dimid, &num_bands);
187 TRY_NC(__FILE__, __LINE__, nc_inq_dimid(ncid_L1A,
"number_of_pixels", &dimid));
188 nc_inq_dimlen(ncid_L1A, dimid, &num_pixels);
189 TRY_NC(__FILE__, __LINE__, nc_inq_dimid(ncid_L1A,
"ccd_temps", &dimid));
190 nc_inq_dimlen(ncid_L1A, dimid, &num_ccd_temps);
191 TRY_NC(__FILE__, __LINE__, nc_inq_dimid(ncid_L1A,
"number_of_tlm_blocks", &dimid));
192 nc_inq_dimlen(ncid_L1A, dimid, &num_tlm_blocks);
194 printf(
"Hawkeye L1A npix = %d; nscans = %d; nbands = %d\n",
195 (
int) num_pixels, (
int) num_scans, (
int) num_bands);
207 tlm_delta_time_ms = (
double *) calloc(num_tlm_blocks,
sizeof(
double));
208 tlm_delta_time_ms_cleansed = (
double *) calloc(num_tlm_blocks,
sizeof(
double));
209 dn_varid = (
int *) calloc(num_bands,
sizeof(
int));
212 if ((nc_inq_grp_ncid(ncid_L1A,
"scan_line_attributes", &l1aScanLineGrp))
214 fprintf(
stderr,
"-E- Error finding group \"scan_line_attributes\".\n");
217 TRY_NC(__FILE__, __LINE__,
218 nc_inq_varid(l1aScanLineGrp,
"delta_time", &scanDeltaTimeId));
219 TRY_NC(__FILE__, __LINE__,
220 nc_get_att_int(l1aScanLineGrp, scanDeltaTimeId,
"_FillValue",
221 &scanDeltaTimeFillValue));
222 TRY_NC(__FILE__, __LINE__,
223 nc_get_att_int(l1aScanLineGrp, scanDeltaTimeId,
"valid_min",
224 &scanDeltaTimeValidMin));
225 TRY_NC(__FILE__, __LINE__,
226 nc_get_att_int(l1aScanLineGrp, scanDeltaTimeId,
"valid_max",
227 &scanDeltaTimeValidMax));
230 if ((nc_inq_grp_ncid(ncid_L1A,
"parameters_telemetry_data", &l1aTelemetryGrp))
232 fprintf(
stderr,
"-E- Error finding group \"parameters_telemetry_data\".\n");
235 if ((nc_inq_grp_ncid(ncid_L1A,
"navigation_data", &l1aNavigationGrp))
237 fprintf(
stderr,
"-E- Error finding group \"navigation_data\" in the L1A file.\n");
241 TRY_NC(__FILE__, __LINE__,
242 nc_inq_varid(l1aTelemetryGrp,
"CCD_temperatures", &varid));
243 TRY_NC(__FILE__, __LINE__,
244 nc_get_var_double(l1aTelemetryGrp, varid, &CCD_temperatures[0][0]));
245 if (nc_inq_var_fill(l1aTelemetryGrp, varid,
NULL, &fill_value_in_CCD_T)
247 fprintf(
stderr,
"-W- Using default fill value of -999 for CCD_temperatures.\n");
248 fill_value_in_CCD_T = -999.0;
251 TRY_NC(__FILE__, __LINE__,
252 nc_inq_varid(l1aTelemetryGrp,
"tlm_time_stamp", &varid));
253 TRY_NC(__FILE__, __LINE__,
254 nc_get_var_double(l1aTelemetryGrp, varid, &tlm_delta_time_ms[0]));
257 if (nc_get_att_uint(l1aTelemetryGrp, NC_GLOBAL,
"darkSubtracted", &darkSubtracted)
262 if (nc_get_att_uint(l1aTelemetryGrp, NC_GLOBAL,
"darkHeight", &darkHeight)
264 darkHeight = default_darkrows;
268 printf(
"Will skip first %d and last %d scans.\n",
269 (
int) skip_beglines, (
int) darkHeight);
271 firstbad = num_scans - darkHeight;
281 TRY_NC(__FILE__, __LINE__,
282 nc_inq_attlen(ncid_L1A, NC_GLOBAL,
"time_coverage_start", &att_len));
283 fltime = (
char *) malloc(att_len + 1);
284 TRY_NC(__FILE__, __LINE__,
285 nc_get_att_text(ncid_L1A, NC_GLOBAL,
"time_coverage_start", fltime));
286 fltime[att_len] =
'\0';
293 TRY_NC(__FILE__, __LINE__,
294 nc_inq_attlen(ncid_L1A, NC_GLOBAL,
"time_coverage_end", &att_len));
295 fltime = (
char *) malloc(att_len + 1);
296 TRY_NC(__FILE__, __LINE__,
297 nc_get_att_text(ncid_L1A, NC_GLOBAL,
"time_coverage_end", fltime));
298 fltime[att_len] =
'\0';
305 time_interval = (
stoptime - starttime) / (num_scans - 1);
308 if (nc_get_att_int(ncid_L1A, NC_GLOBAL,
"orbit_number", &orbit_number) != NC_NOERR)
312 if (nc_get_att_int(l1aTelemetryGrp, NC_GLOBAL,
"exposureID", &
data->exposureID) != NC_NOERR)
313 data->exposureID = 0;
314 if (nc_get_att_float(l1aNavigationGrp, NC_GLOBAL,
"time_offset", &
data->time_offset) != NC_NOERR)
315 data->time_offset = 0.;
316 if (nc_get_att_float(l1aNavigationGrp, NC_GLOBAL,
"roll_offset", &
data->roll_offset) != NC_NOERR)
317 data->roll_offset = 0.;
321 if ((nc_inq_grp_ncid(ncid_L1A,
"earth_view_data", &l1aEarthViewGrp)) != NC_NOERR) {
322 fprintf(
stderr,
"-E- Error finding group \"earth_view_data\".\n");
325 for (band_num = 0; band_num < num_bands; band_num++) {
326 sprintf(nc_search_string,
"band_%d", band_num + 1);
327 TRY_NC(__FILE__, __LINE__,
328 nc_inq_varid(l1aEarthViewGrp, nc_search_string, &dn_varid[band_num]));
331 file->sd_id = ncid_L1A;
332 file->nbands = num_bands;
333 file->npix = num_pixels;
334 file->nscan = num_scans - skip_beglines - darkHeight;
336 file->terrain_corrected = 0;
337 file->orbit_number = orbit_number;
341 "Fobar", (
void **) &Fobar);
344 if (
file->geofile &&
file->geofile[0]) {
346 printf(
"Opening Hawkeye GEO file\n");
347 status = nc_open(
file->geofile, NC_NOWRITE, &geoFileId);
349 fprintf(
stderr,
"-E- Error opening GEO file \"%s\": %s\n",
355 if ((nc_inq_grp_ncid(geoFileId,
"geolocation_data", &geoGeolocationGrp))
357 fprintf(
stderr,
"-E- Error finding group \"geolocation_data\".\n");
360 TRY_NC(__FILE__, __LINE__,
361 nc_inq_varid(geoGeolocationGrp,
"longitude", &lonId));
362 TRY_NC(__FILE__, __LINE__,
363 nc_inq_var_fill(geoGeolocationGrp, lonId,
NULL, &lonGeoFillValue));
364 TRY_NC(__FILE__, __LINE__,
365 nc_inq_varid(geoGeolocationGrp,
"latitude", &latId));
366 TRY_NC(__FILE__, __LINE__,
367 nc_inq_var_fill(geoGeolocationGrp, latId,
NULL, &latGeoFillValue));
368 TRY_NC(__FILE__, __LINE__,
369 nc_inq_varid(geoGeolocationGrp,
"sensor_zenith", &senzId));
370 TRY_NC(__FILE__, __LINE__,
371 nc_inq_var_fill(geoGeolocationGrp, senzId,
NULL, &senzGeoFillValue));
372 TRY_NC(__FILE__, __LINE__,
373 nc_inq_varid(geoGeolocationGrp,
"sensor_azimuth", &senaId));
374 TRY_NC(__FILE__, __LINE__,
375 nc_inq_var_fill(geoGeolocationGrp, senaId,
NULL, &senaGeoFillValue));
376 TRY_NC(__FILE__, __LINE__,
377 nc_inq_varid(geoGeolocationGrp,
"solar_zenith", &solzId));
378 TRY_NC(__FILE__, __LINE__,
379 nc_inq_var_fill(geoGeolocationGrp, solzId,
NULL, &solzGeoFillValue));
380 TRY_NC(__FILE__, __LINE__,
381 nc_inq_varid(geoGeolocationGrp,
"solar_azimuth", &solaId));
382 TRY_NC(__FILE__, __LINE__,
383 nc_inq_var_fill(geoGeolocationGrp, solaId,
NULL, &solaGeoFillValue));
384 TRY_NC(__FILE__, __LINE__,
385 nc_inq_varid(geoGeolocationGrp,
"quality_flag", &pixelQualityId));
387 if ((nc_inq_grp_ncid(geoFileId,
"navigation_data", &geoNavigationGrp))
389 fprintf(
stderr,
"-E- Error finding group \"navigation_data\".\n");
393 TRY_NC(__FILE__, __LINE__, nc_inq_varid(geoNavigationGrp,
"att_ang", &angId));
394 TRY_NC(__FILE__, __LINE__, nc_inq_varid(geoNavigationGrp,
"orb_pos", &posId));
395 TRY_NC(__FILE__, __LINE__, nc_inq_varid(geoNavigationGrp,
"orb_vel", &velId));
397 if ((nc_inq_grp_ncid(geoFileId,
"scan_line_attributes", &geoScanLineGrp))
399 fprintf(
stderr,
"-E- Error finding group \"scan_line_attributes\".\n");
411 latL2FillValue = info->fillValue;
414 lonL2FillValue = info->fillValue;
417 senaL2FillValue = info->fillValue;
420 senzL2FillValue = info->fillValue;
423 solaL2FillValue = info->fillValue;
426 solzL2FillValue = info->fillValue;
436 int band_num, pixel_num;
439 for (pixel_num = 0; pixel_num < num_pixels; pixel_num++)
440 for (band_num = 0; band_num < num_bands; band_num++)
441 bkg_avg[band_num][pixel_num] = nominal_dark_counts[band_num][pixel_num];
444 if (!darkSubtracted) {
448 if (num_scans == 6000) {
450 size_t begline = num_scans - darkHeight + shutter_rampdown;
451 size_t endline = num_scans - skip_endlines - 1;
452 size_t num_darklines = endline - begline + 1;
454 size_t start[] = { 0, 0 };
455 size_t count[] = { 1, 1 };
457 count[0] = num_darklines;
459 count[1] = num_pixels;
462 unsigned short **dn_dark = (
unsigned short**)
allocate2d_short(num_darklines,
464 memset((&dn_dark[0][0]), 0, num_darklines*num_pixels*
sizeof(
unsigned short));
466 for (band_num = 0; band_num < num_bands; band_num++) {
467 nc_get_vara_ushort(l1aEarthViewGrp, dn_varid[band_num],
471 for (pixel_num = 0; pixel_num < num_pixels; pixel_num++) {
472 unsigned long sum_vals = 0;
473 for (
size_t line_num = 0; line_num < num_darklines; line_num++)
474 sum_vals += dn_dark[line_num][pixel_num];
475 bkg_avg[band_num][pixel_num] = (
double) sum_vals
476 / (
double) num_darklines;
503 int16_t scan_year, scan_day;
506 size_t start[] = { 0, 0 };
507 size_t count[] = { 1, 1 };
510 int band_num, pixel_num;
511 int16_t scan_month, scan_dom;
512 double current_julian_date;
513 int32_t scan_delta_time_ms;
516 for (int32_t ip = 0; ip < num_pixels; ip++) {
517 l1rec->pixnum[ip] = ip;
525 tmpShort = (
short *) malloc(num_pixels *
sizeof(
short));
526 tmpByte = (
unsigned char *) malloc(num_pixels);
527 dn = (
unsigned short*) calloc(num_pixels,
sizeof(
unsigned short));
530 CCD_temperatures_this_scan = (
double *) calloc(num_ccd_temps,
sizeof(
double));
536 int32_t
line = oline + skip_beglines;
543 TRY_NC(__FILE__, __LINE__,
544 nc_get_vara_int(l1aScanLineGrp, scanDeltaTimeId,
start,
count,
545 &scan_delta_time_ms));
547 if ((scan_delta_time_ms == scanDeltaTimeFillValue) ||
548 (scan_delta_time_ms < scanDeltaTimeValidMin) ||
549 (scan_delta_time_ms > scanDeltaTimeValidMax)) {
550 l1rec->scantime = lastvalidtime + (time_interval * (
line - lastvalidscan));
552 lastvalidtime = starttime + scan_delta_time_ms / 1000.0;
553 lastvalidscan =
line;
554 l1rec->scantime = lastvalidtime;
560 yd2md(scan_year, scan_day, &scan_month, &scan_dom);
561 current_julian_date =
jday(scan_year, scan_month, scan_dom)
562 + (scan_sec / (24 * 3600.0)) - 0.5;
578 for (band_num = 0; band_num < num_bands; band_num++) {
582 int inputline =
line + track_offset[band_num];
583 if ((-1 < inputline) && (inputline < firstbad)) {
585 for (pixel_num = 0; pixel_num < num_pixels; pixel_num++) {
587 float inputpix = pixel_num + ccd_offset[band_num] +
589 (pixel_num - reference_pixel));
590 int ipix = floor(inputpix);
591 float fpix = inputpix - ipix;
594 if ((-1 < ipix) && (ceil(inputpix) < num_pixels)) {
595 Lt_interp = Lt[band_num][ipix] * (1 - fpix);
597 Lt_interp += Lt[band_num][ipix + 1] * fpix;
600 l1rec->Lt[pixel_num * num_bands + band_num] = (
float) Lt_interp / 10.0;
609 if (
file->geofile &&
file->geofile[0]) {
615 count[1] = num_pixels;
617 TRY_NC(__FILE__, __LINE__,
618 nc_get_vara_float(geoGeolocationGrp, latId,
start,
count,
l1rec->lat));
619 for (
i = 0;
i < num_pixels;
i++)
620 if (
l1rec->lat[
i] == latGeoFillValue)
621 l1rec->lat[
i] = latL2FillValue;
623 TRY_NC(__FILE__, __LINE__,
624 nc_get_vara_float(geoGeolocationGrp, lonId,
start,
count,
l1rec->lon));
625 for (
i = 0;
i < num_pixels;
i++)
626 if (
l1rec->lon[
i] == lonGeoFillValue)
627 l1rec->lon[
i] = lonL2FillValue;
629 TRY_NC(__FILE__, __LINE__,
630 nc_get_vara_short(geoGeolocationGrp, solzId,
start,
count, tmpShort));
631 for (
i = 0;
i < num_pixels;
i++)
632 if (tmpShort[
i] == solzGeoFillValue)
633 l1rec->solz[
i] = solzL2FillValue;
635 l1rec->solz[
i] = tmpShort[
i] * 0.01;
637 TRY_NC(__FILE__, __LINE__,
638 nc_get_vara_short(geoGeolocationGrp, solaId,
start,
count, tmpShort));
639 for (
i = 0;
i < num_pixels;
i++)
640 if (tmpShort[
i] == solaGeoFillValue)
641 l1rec->sola[
i] = solaL2FillValue;
643 l1rec->sola[
i] = tmpShort[
i] * 0.01;
645 TRY_NC(__FILE__, __LINE__,
646 nc_get_vara_short(geoGeolocationGrp, senzId,
start,
count, tmpShort));
647 for (
i = 0;
i < num_pixels;
i++)
648 if (tmpShort[
i] == senzGeoFillValue)
649 l1rec->senz[
i] = senzL2FillValue;
651 l1rec->senz[
i] = tmpShort[
i] * 0.01;
653 TRY_NC(__FILE__, __LINE__,
654 nc_get_vara_short(geoGeolocationGrp, senaId,
start,
count, tmpShort));
655 for (
i = 0;
i < num_pixels;
i++)
656 if (tmpShort[
i] == senaGeoFillValue)
657 l1rec->sena[
i] = senaL2FillValue;
659 l1rec->sena[
i] = tmpShort[
i] * 0.01;
665 size_t s3[] = {
line, 0 };
666 size_t c3[] = { 1, 3 };
668 TRY_NC(__FILE__, __LINE__, nc_get_vara_float(geoNavigationGrp, angId, s3, c3, ang));
669 TRY_NC(__FILE__, __LINE__, nc_get_vara_float(geoNavigationGrp, posId, s3, c3,
pos));
670 TRY_NC(__FILE__, __LINE__, nc_get_vara_float(geoNavigationGrp, velId, s3, c3, vel));
671 for (
i = 0;
i < 3;
i++) {
677 float sen_mat[3][3], coeff[10];
680 for (
i = 0;
i < 3;
i++)
687 TRY_NC(__FILE__, __LINE__,
688 nc_get_vara_uchar(geoGeolocationGrp, pixelQualityId,
start,
count, tmpByte));
694 for (
i = 0;
i < num_pixels;
i++) {
700 int32_t yr = (int32_t) scan_year;
701 int32_t dy = (int32_t) scan_day;
702 int32_t
msec = (int32_t) (scan_sec * 1000.0);
717 printf(
"Closing hawkeye L1A file\n");
718 TRY_NC(__FILE__, __LINE__, nc_close(
file->sd_id));
720 if (
file->geofile &&
file->geofile[0]) {
721 printf(
"Closing Hawkeye GEO file\n");
722 TRY_NC(__FILE__, __LINE__, nc_close(geoFileId));
726 if (tmpShort) free(tmpShort);
727 if (tmpByte) free(tmpByte);
728 if (CCD_temperatures_this_scan) free(CCD_temperatures_this_scan);
733 if (temperature_ref) free(temperature_ref);
734 if (time_ref) free(time_ref);
742 if (CCD_temperatures_cleansed)
free2d_double(CCD_temperatures_cleansed);
743 if (tlm_delta_time_ms) free(tlm_delta_time_ms);
744 if (tlm_delta_time_ms_cleansed) free(tlm_delta_time_ms_cleansed);
745 if (dn_varid) free(dn_varid);
748 free (
file->private_data);
766 size_t tlm_block_num, tlm_block_cleansed_num, ccd_temp_num;
767 bool *tlm_block_good;
768 double *CCD_temperatures_Dim2, *nan_mean_weights;
769 double CCD_temperature_max_deviation = 10.0;
770 double *CCD_temperature_sorted;
771 size_t *CCD_temperature_sort_index;
772 double CCD_temperature_median;
775 tlm_block_good = (
bool *) calloc(num_tlm_blocks,
sizeof(
bool));
776 CCD_temperatures_Dim2 = (
double *) calloc(num_ccd_temps,
sizeof(
double));
777 nan_mean_weights = (
double *) calloc(num_ccd_temps,
sizeof(
double));
778 CCD_temperature_sorted = (
double *) calloc(num_ccd_temps,
sizeof(
double));
779 CCD_temperature_sort_index = (
size_t *) calloc(num_ccd_temps,
sizeof(
size_t));
782 for (tlm_block_num = 0; tlm_block_num < num_tlm_blocks; tlm_block_num++) {
784 tlm_block_good[tlm_block_num] =
false;
785 for (ccd_temp_num = 0; ccd_temp_num < num_ccd_temps; ccd_temp_num++) {
786 if (CCD_temperatures[tlm_block_num][ccd_temp_num] != fill_value_in_CCD_T) {
787 tlm_block_good[tlm_block_num] =
true;
796 for (ccd_temp_num = 0; ccd_temp_num < num_ccd_temps; ccd_temp_num++) {
797 nan_mean_weights[ccd_temp_num] = 1.0;
799 tlm_block_cleansed_num = 0;
800 for (tlm_block_num = 0; tlm_block_num < num_tlm_blocks; tlm_block_num++) {
801 if (tlm_block_good[tlm_block_num]) {
804 tlm_delta_time_ms_cleansed[tlm_block_cleansed_num] =
805 tlm_delta_time_ms[tlm_block_num];
808 for (ccd_temp_num = 0; ccd_temp_num < num_ccd_temps; ccd_temp_num++) {
810 CCD_temperatures_Dim2[ccd_temp_num] =
811 CCD_temperatures[tlm_block_num][ccd_temp_num];
813 for (ccd_temp_num = 0; ccd_temp_num < num_ccd_temps; ccd_temp_num++) {
815 if (CCD_temperatures_Dim2[ccd_temp_num] == fill_value_in_CCD_T) {
816 CCD_temperatures_cleansed[tlm_block_cleansed_num][ccd_temp_num] =
817 nan_wmean(nan_mean_weights, CCD_temperatures_Dim2,
818 num_ccd_temps, (
double) fill_value_in_CCD_T);
820 CCD_temperatures_cleansed[tlm_block_cleansed_num][ccd_temp_num] =
821 CCD_temperatures_Dim2[ccd_temp_num];
824 tlm_block_cleansed_num = tlm_block_cleansed_num + 1;
832 for (tlm_block_num = 0; tlm_block_num < num_tlm_blocks; tlm_block_num++) {
833 for (ccd_temp_num = 0; ccd_temp_num < num_ccd_temps; ccd_temp_num++) {
835 CCD_temperatures_Dim2[ccd_temp_num] =
836 CCD_temperatures[tlm_block_num][ccd_temp_num];
839 gsl_sort_index(CCD_temperature_sort_index, CCD_temperatures_Dim2, 1,
841 for (ccd_temp_num = 0; ccd_temp_num < num_ccd_temps; ccd_temp_num++) {
842 CCD_temperature_sorted[ccd_temp_num] =
843 CCD_temperatures_Dim2[CCD_temperature_sort_index[ccd_temp_num]];
846 CCD_temperature_median = gsl_stats_median_from_sorted_data(CCD_temperature_sorted,
849 for (ccd_temp_num = 0; ccd_temp_num < num_ccd_temps; ccd_temp_num++) {
850 if (
fabs(CCD_temperatures_Dim2[ccd_temp_num] - CCD_temperature_median)
851 > CCD_temperature_max_deviation) {
853 "-W- In tlm block %d, CCD %d records a temperature of %f, more than %f degrees different than the median value of %f\n",
855 (
int) ccd_temp_num, CCD_temperatures_Dim2[ccd_temp_num],
856 CCD_temperature_max_deviation, CCD_temperature_median);
862 if (tlm_block_cleansed_num < 2) {
864 for (tlm_block_num = 0; tlm_block_num < num_tlm_blocks; tlm_block_num++) {
865 tlm_delta_time_ms_cleansed[tlm_block_num] = tlm_delta_time_ms[tlm_block_num];
866 for (ccd_temp_num = 0; ccd_temp_num < num_ccd_temps; ccd_temp_num++) {
867 CCD_temperatures_cleansed[tlm_block_num][ccd_temp_num] =
868 CCD_temperature_default;
871 num_tlm_blocks_cleansed = num_tlm_blocks;
873 "-W- There were fewer than 2 good tlm_blocks of CCD_temperatures, so using the default value of %f\n",
874 CCD_temperature_default);
877 num_tlm_blocks_cleansed = tlm_block_cleansed_num;
881 free(tlm_block_good);
882 free(CCD_temperatures_Dim2);
883 free(nan_mean_weights);
884 free(CCD_temperature_sorted);
885 free(CCD_temperature_sort_index);
898 int status, ncid_CAL, varid, dimid;
902 size_t cal_num_bands = 0;
903 size_t cal_num_pixels = 0;
906 printf(
"Reading Hawkeye calibration LUT\n");
907 status = nc_open(cal_path, NC_NOWRITE, &ncid_CAL);
909 fprintf(
stderr,
"-E- Error opening CAL file \"%s\": %s\n",
910 cal_path, nc_strerror(
status));
915 TRY_NC(__FILE__, __LINE__, nc_inq_dimid(ncid_CAL,
"number_of_bands", &dimid));
916 nc_inq_dimlen(ncid_CAL, dimid, &cal_num_bands);
917 TRY_NC(__FILE__, __LINE__, nc_inq_dimid(ncid_CAL,
"number_of_pixels", &dimid));
918 nc_inq_dimlen(ncid_CAL, dimid, &cal_num_pixels);
919 TRY_NC(__FILE__, __LINE__, nc_inq_dimid(ncid_CAL,
"number_of_times", &dimid));
920 nc_inq_dimlen(ncid_CAL, dimid, &cal_num_dates);
921 TRY_NC(__FILE__, __LINE__, nc_inq_dimid(ncid_CAL,
"number_of_temperatures", &dimid));
922 nc_inq_dimlen(ncid_CAL, dimid, &cal_num_temperatures);
925 if (cal_num_bands != num_bands) {
926 fprintf(
stderr,
"-E- num_bands in cal file not equal to num_bands in L1A file\n");
929 if (cal_num_pixels != num_pixels) {
931 "-E- num_pixels in cal file not equal to num_pixels in L1A file\n");
937 time_ref = (
double *) calloc(cal_num_dates,
sizeof(
double));
938 temperature_ref = (
double *) calloc(cal_num_temperatures,
sizeof(
double));
939 K1 = (
double *) calloc(num_bands,
sizeof(
double));
946 nominal_dark_counts = (
unsigned short**)
allocate2d_short(num_bands, num_pixels);
949 if ((nc_inq_grp_ncid(ncid_CAL,
"radiometric_calibration", &calGrp)) != NC_NOERR) {
950 fprintf(
stderr,
"-E- Error finding group \"radiometric_calibration\".\n");
954 TRY_NC(__FILE__, __LINE__, nc_inq_varid(calGrp,
"K1", &varid));
955 TRY_NC(__FILE__, __LINE__, nc_get_var_double(calGrp, varid,
K1));
957 TRY_NC(__FILE__, __LINE__, nc_inq_varid(calGrp,
"K2", &varid));
958 TRY_NC(__FILE__, __LINE__, nc_get_var_double(calGrp, varid, &K2[0][0][0]));
960 TRY_NC(__FILE__, __LINE__, nc_inq_varid(calGrp,
"K2t", &varid));
961 TRY_NC(__FILE__, __LINE__, nc_get_var_double(calGrp, varid, time_ref));
963 TRY_NC(__FILE__, __LINE__, nc_inq_varid(calGrp,
"K3", &varid));
964 TRY_NC(__FILE__, __LINE__, nc_get_var_double(calGrp, varid, &
K3[0][0]));
966 TRY_NC(__FILE__, __LINE__, nc_inq_varid(calGrp,
"K3T", &varid));
967 TRY_NC(__FILE__, __LINE__, nc_get_var_double(calGrp, varid, temperature_ref));
969 TRY_NC(__FILE__, __LINE__, nc_inq_varid(calGrp,
"K4", &varid));
970 TRY_NC(__FILE__, __LINE__, nc_get_var_float(calGrp, varid, &
K4[0][0]));
972 TRY_NC(__FILE__, __LINE__, nc_inq_varid(calGrp,
"K5", &varid));
973 TRY_NC(__FILE__, __LINE__, nc_get_var_double(calGrp, varid, &K5[0][0]));
977 TRY_NC(__FILE__, __LINE__, nc_inq_varid(calGrp,
"K7", &varid));
979 TRY_NC(__FILE__, __LINE__, nc_get_var_float(calGrp, varid, &K7[0][0]));
982 TRY_NC(__FILE__, __LINE__, nc_inq_varid(calGrp,
"nominal_dark_counts", &varid));
983 TRY_NC(__FILE__, __LINE__, nc_get_var_ushort(calGrp, varid, &nominal_dark_counts[0][0]));
986 if ((nc_inq_grp_ncid(ncid_CAL,
"geometric_parameters", &geoGrp)) != NC_NOERR) {
987 fprintf(
stderr,
"-E- Error finding group \"geometric_parameters\".\n");
991 track_offset = calloc(num_bands,
sizeof(
int));
992 ccd_offset = calloc(num_bands,
sizeof(
int));
993 focal_length = (
float *) calloc(num_bands,
sizeof(
float));
994 TRY_NC(__FILE__, __LINE__, nc_inq_varid(geoGrp,
"track_offset", &varid));
995 TRY_NC(__FILE__, __LINE__, nc_get_var_int(geoGrp, varid, track_offset));
996 TRY_NC(__FILE__, __LINE__, nc_inq_varid(geoGrp,
"CCD_offset", &varid));
997 TRY_NC(__FILE__, __LINE__, nc_get_var_int(geoGrp, varid, ccd_offset));
998 TRY_NC(__FILE__, __LINE__, nc_inq_varid(geoGrp,
"focal_length", &varid));
1000 TRY_NC(__FILE__, __LINE__,
1001 nc_get_att_int(geoGrp, NC_GLOBAL,
"reference_band", &reference_band));
1002 reference_band -= 1;
1003 TRY_NC(__FILE__, __LINE__,
1004 nc_get_att_int(geoGrp, NC_GLOBAL,
"reference_pixel", &reference_pixel));
1005 reference_pixel -= 1;
1007 TRY_NC(__FILE__, __LINE__,
1008 nc_get_att_int(geoGrp, NC_GLOBAL,
"skip_beglines", &skip_beglines));
1009 TRY_NC(__FILE__, __LINE__,
1010 nc_get_att_int(geoGrp, NC_GLOBAL,
"skip_endlines", &skip_endlines));
1011 TRY_NC(__FILE__, __LINE__,
1012 nc_get_att_int(geoGrp, NC_GLOBAL,
"shutter_rampdown", &shutter_rampdown));
1013 TRY_NC(__FILE__, __LINE__,
1014 nc_get_att_int(geoGrp, NC_GLOBAL,
"default_darkrows", &default_darkrows));
1017 TRY_NC(__FILE__, __LINE__, nc_close(ncid_CAL));
1030 size_t tlm_block_num, ccd_temp_num;
1031 double *CCD_temperatures_Dim1;
1034 CCD_temperatures_Dim1 = (
double *) calloc(num_tlm_blocks_cleansed,
sizeof(
double));
1036 gsl_interp_accel *acc_delta_time = gsl_interp_accel_alloc();
1037 gsl_spline *spline_delta_time = gsl_spline_alloc(gsl_interp_linear,
1038 num_tlm_blocks_cleansed);
1042 num_tlm_blocks_cleansed);
1043 for (ccd_temp_num = 0; ccd_temp_num < num_ccd_temps; ccd_temp_num++) {
1044 for (tlm_block_num = 0; tlm_block_num < num_tlm_blocks_cleansed;
1047 CCD_temperatures_Dim1[tlm_block_num] =
1048 CCD_temperatures_cleansed[tlm_block_num][ccd_temp_num];
1051 gsl_spline_init(spline_delta_time, tlm_delta_time_ms_cleansed,
1052 &CCD_temperatures_Dim1[0], num_tlm_blocks_cleansed);
1053 CCD_temperatures_this_scan[ccd_temp_num] = gsl_spline_eval(spline_delta_time,
1059 free(CCD_temperatures_Dim1);
1060 gsl_spline_free(spline_delta_time);
1061 gsl_interp_accel_free(acc_delta_time);
1072 double current_temp_C;
1074 size_t start[] = { 0, 0 };
1075 size_t count[] = { 1, 1 };
1077 int32_t band_num, pixel_num, ccd_temp_num;
1083 gsl_interp_accel *acc_T = gsl_interp_accel_alloc();
1084 gsl_interp_accel *acc_date = gsl_interp_accel_alloc();
1085 gsl_spline *spline_T = gsl_spline_alloc(gsl_interp_linear, cal_num_temperatures);
1090 K3i = (
double *) calloc(num_bands,
sizeof(
double));
1097 for (K2t_idx = 0; K2t_idx < cal_num_dates; K2t_idx++){
1099 if ((time_ref[K2t_idx] - current_julian_date) >= 0)
1107 for (band_num = 0; band_num < num_bands; band_num++) {
1108 for (pixel_num = 0; pixel_num < num_pixels; pixel_num++) {
1109 K2i[band_num][pixel_num] = K2[band_num][pixel_num][K2t_idx];
1122 for (band_num = 0; band_num < num_bands; band_num++) {
1124 ccd_temp_num = (
int) (band_num / 2);
1125 current_temp_C = CCD_temperatures_this_scan[ccd_temp_num];
1129 gsl_spline_init(spline_T, temperature_ref, &
K3[band_num][0],
1130 cal_num_temperatures);
1131 K3i[band_num] = gsl_spline_eval(spline_T, current_temp_C, acc_T);
1136 count[1] = num_pixels;
1137 for (band_num = 0; band_num < num_bands; band_num++) {
1140 int inputline =
line + track_offset[band_num];
1141 if ((-1 < inputline) && (inputline < firstbad)) {
1142 start[0] = inputline;
1143 TRY_NC(__FILE__, __LINE__,
1144 nc_get_vara_ushort(l1aEarthViewGrp, dn_varid[band_num],
1147 for (pixel_num = 0; pixel_num < num_pixels; pixel_num++) {
1149 this_dn = (
double) dn[pixel_num] - bkg_avg[band_num][pixel_num];
1155 cal_coeff = (
K1[band_num]) * (K2i[band_num][pixel_num]) * (K3i[band_num])
1156 * (
K4[band_num][pixel_num]);
1160 cal_coeff *= K7[band_num][pixel_num];
1162 Lt[band_num][pixel_num] = this_dn * cal_coeff
1163 * (1 + (K5[band_num][pixel_num]) * this_dn);
1171 gsl_spline_free(spline_T);
1172 gsl_interp_accel_free(acc_T);
1174 gsl_interp_accel_free(acc_date);
1179 size_t i, fill_count;
1183 for (
i = 0;
i < n;
i++) {
1184 if (
data[
i] == fill_value) {
1190 if (fill_count < n) {
1191 wmean = gsl_stats_wmean(weights, 1,
data, 1, n);
1208 gsl_stats_minmax(&xmin, &xmax,
x, 1,
N);