OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l1_viirs_nc.c
Go to the documentation of this file.
1 /* ============================================================================ */
2 /* module l1_viirs_nc.c - functions to read VIIRS L1A for MSL12 */
3 /* Written By: Joel M. Gales GSFC Futuretech, Sep. 2011. */
4 /* */
5 /* ============================================================================ */
6 
7 // #include <stdbool.h>
8 #include <nc4utils.h>
9 #include "libnav.h"
10 #include "calibrate_viirs.h"
12 #include <productInfo.h>
13 #include <libnav.h>
14 #include "l1.h"
15 #include "l2_flags.h"
16 
17 #define MBAND_NUM_DETECTORS 16
18 
19 static int32_t prevScan = -1;
20 
21 static int scanLineGrp;
22 static int scanStartTimeId;
23 static int HAMSideId;
24 
25 static int geoFileId;
26 static int geoNavigationGrp;
27 static int geoGeolocationGrp;
28 static int geoScanLineGrp;
29 static int lonId, latId, senzId, senaId, solzId, solaId, angId, posId, velId, scanQualityId, pixelQualityId;
30 
31 static double ***f_cal_corr = NULL; /* f table correction [band][det][ms] */
32 
33 static float *Fobar; // reflectance to radiance conversion factors
34 static int extract_pixel_start = 0;
35 static int extract_pixel_stop = 0;
36 
37 static short *tmpShort;
38 static unsigned char *tmpByte;
39 static int nscan, nline, npix;
40 
41 static double starttime;
42 static double lastvalidtime;
43 static int lastvalidscan = 0;
44 static double time_interval;
45 
46 static float latGeoFillValue = -999.9;
47 static float lonGeoFillValue = -999.9;
48 static short senzGeoFillValue = -32768;
49 static short senaGeoFillValue = -32768;
50 static short solzGeoFillValue = -32768;
51 static short solaGeoFillValue = -32768;
52 
53 static float latL2FillValue = -999.0;
54 static float lonL2FillValue = -999.0;
55 static float senzL2FillValue = -32767;
56 static float senaL2FillValue = -32767;
57 static float solzL2FillValue = -32767;
58 static float solaL2FillValue = -32767;
59 
60 static double scan_start_tai = -999;
61 
62 int openl1_viirs_nc(filehandle * file) {
63  char *fltime;
64 
65  size_t tmpSize;
66  int fileID, dimid, status;
67  size_t att_len; // Change to size_t JMG 08/12/13
68  int orbit_number;
69 
70  // Open the netcdf4 input file
71  status = nc_open(file->name, NC_NOWRITE, &fileID);
72  if (status != NC_NOERR) {
73  fprintf(stderr, "-E- %s line %d: nc_open(%s) failed.\n",
74  __FILE__, __LINE__, file->name);
75  return (1);
76  }
77 
78  // Get pixel and scan dimensions
79  status = nc_get_att_int(fileID, NC_GLOBAL, "number_of_filled_scans", &nscan);
80  check_err(status, __LINE__, __FILE__);
81  nline = nscan * MBAND_NUM_DETECTORS;
82 
83  status = nc_inq_dimid(fileID, "Mband_pixels", &dimid);
84  check_err(status, __LINE__, __FILE__);
85  status = nc_inq_dimlen(fileID, dimid, &tmpSize);
86  check_err(status, __LINE__, __FILE__);
87  npix = tmpSize;
88 
89  nc_type vr_type; /* attribute type */
90  size_t vr_len; /* attribute length */
91  if ((nc_inq_att(fileID, NC_GLOBAL, "extract_pixel_start", &vr_type, &vr_len) == NC_NOERR)) {
92  status = nc_get_att_int(fileID, NC_GLOBAL, "extract_pixel_start", &extract_pixel_start);
93  check_err(status, __LINE__, __FILE__);
94  extract_pixel_start--; // Attribute is one-based
95  status = nc_get_att_int(fileID, NC_GLOBAL, "extract_pixel_stop", &extract_pixel_stop);
96  check_err(status, __LINE__, __FILE__);
97  extract_pixel_stop--; // Attribute is one-based
98  if (npix != (extract_pixel_stop - extract_pixel_start + 1)) {
99  printf("-E- Problem with the extracted L1A file pixel dimension.\n");
100  printf(" npix(%d), extract_pixel_stop(%d), extract_pixel_start(%d) do not work together.\n",
101  npix, extract_pixel_stop, extract_pixel_start);
102  exit(EXIT_FAILURE);
103  }
104  }
105 
106  if (want_verbose) {
107  printf("VIIRS L1A Npix :%d Nlines:%d\n", npix, nline);
108  } // want_verbose
109 
110  // get start and end time
111  status = nc_inq_attlen(fileID, NC_GLOBAL, "time_coverage_start", &att_len);
112  check_err(status, __LINE__, __FILE__);
113 
114  /* allocate required space before retrieving values */
115  fltime = (char *) malloc(att_len + 1); /* + 1 for trailing null */
116 
117  /* get attribute values */
118  status = nc_get_att_text(fileID, NC_GLOBAL, "time_coverage_start", fltime);
119  check_err(status, __LINE__, __FILE__);
120  fltime[att_len] = '\0';
121 
122  starttime = lastvalidtime = isodate2unix(fltime);
123  lastvalidscan = 0;
124  free(fltime);
125 
126  status = nc_inq_attlen(fileID, NC_GLOBAL, "time_coverage_end", &att_len);
127  check_err(status, __LINE__, __FILE__);
128 
129  /* allocate required space before retrieving values */
130  fltime = (char *) malloc(att_len + 1); /* + 1 for trailing null */
131 
132  /* get attribute values */
133  status = nc_get_att_text(fileID, NC_GLOBAL, "time_coverage_end", fltime);
134  check_err(status, __LINE__, __FILE__);
135  fltime[att_len] = '\0';
136 
137  double stoptime = isodate2unix(fltime);
138  free(fltime);
139 
140  time_interval = (stoptime - starttime) / (nscan - 1); /* in sec */
141 
142  if ((nc_inq_att(fileID, NC_GLOBAL, "orbit_number", &vr_type, &vr_len) == NC_NOERR)) {
143  status = nc_get_att_int(fileID, NC_GLOBAL, "orbit_number", &orbit_number);
144  check_err(status, __LINE__, __FILE__);
145  } else {
146  status = nc_get_att_int(fileID, NC_GLOBAL, "OrbitNumber", &orbit_number);
147  check_err(status, __LINE__, __FILE__);
148  }
149 
150  file->sd_id = fileID;
151  file->nbands = 10;
152  file->npix = npix;
153  file->nscan = nline;
154  file->ndets = MBAND_NUM_DETECTORS;
155  file->terrain_corrected = 1; // presumed.
156  file->orbit_number = orbit_number;
157  strcpy(file->spatialResolution, "750 m");
158 
159  rdsensorinfo(file->sensorID, l1_input->evalmask,
160  "Fobar", (void **) &Fobar);
161 
162  if (want_verbose)
163  printf("file->nbands = %d\n", (int) file->nbands);
164 
165  status = nc_inq_ncid(file->sd_id, "scan_line_attributes", &scanLineGrp);
166  check_err(status, __LINE__, __FILE__);
167 
168  // get tai93
169  status = nc_inq_varid(scanLineGrp, "scan_start_time", &scanStartTimeId);
170  check_err(status, __LINE__, __FILE__);
171 
172  // get mirror side
173  status = nc_inq_varid(scanLineGrp, "HAM_side", &HAMSideId);
174  check_err(status, __LINE__, __FILE__);
175 
176  // Setup geofile pointers
177  if (file->geofile && file->geofile[0]) {
178 
179  status = nc_open(file->geofile, NC_NOWRITE, &geoFileId);
180  if (status != NC_NOERR) {
181  printf("-E- Could not open GEO file \"%s\"\n", file->geofile);
182  exit(EXIT_FAILURE);
183  }
184 
185  status = nc_inq_grp_ncid(geoFileId, "geolocation_data", &geoGeolocationGrp);
186  check_err(status, __LINE__, __FILE__);
187  status = nc_inq_varid(geoGeolocationGrp, "longitude", &lonId);
188  check_err(status, __LINE__, __FILE__);
189  status = nc_inq_var_fill(geoGeolocationGrp, lonId, NULL, &lonGeoFillValue);
190  check_err(status, __LINE__, __FILE__);
191  status = nc_inq_varid(geoGeolocationGrp, "latitude", &latId);
192  check_err(status, __LINE__, __FILE__);
193  status = nc_inq_var_fill(geoGeolocationGrp, latId, NULL, &latGeoFillValue);
194  check_err(status, __LINE__, __FILE__);
195  status = nc_inq_varid(geoGeolocationGrp, "sensor_zenith", &senzId);
196  check_err(status, __LINE__, __FILE__);
197  status = nc_inq_var_fill(geoGeolocationGrp, senzId, NULL, &senzGeoFillValue);
198  check_err(status, __LINE__, __FILE__);
199  status = nc_inq_varid(geoGeolocationGrp, "sensor_azimuth", &senaId);
200  check_err(status, __LINE__, __FILE__);
201  status = nc_inq_var_fill(geoGeolocationGrp, senaId, NULL, &senaGeoFillValue);
202  check_err(status, __LINE__, __FILE__);
203  status = nc_inq_varid(geoGeolocationGrp, "solar_zenith", &solzId);
204  check_err(status, __LINE__, __FILE__);
205  status = nc_inq_var_fill(geoGeolocationGrp, solzId, NULL, &solzGeoFillValue);
206  check_err(status, __LINE__, __FILE__);
207  status = nc_inq_varid(geoGeolocationGrp, "solar_azimuth", &solaId);
208  check_err(status, __LINE__, __FILE__);
209  status = nc_inq_var_fill(geoGeolocationGrp, solaId, NULL, &solaGeoFillValue);
210  check_err(status, __LINE__, __FILE__);
211  status = nc_inq_varid(geoGeolocationGrp, "quality_flag", &pixelQualityId);
212  check_err(status, __LINE__, __FILE__);
213 
214  status = nc_inq_grp_ncid(geoFileId, "navigation_data", &geoNavigationGrp);
215  check_err(status, __LINE__, __FILE__);
216  status = nc_inq_varid(geoNavigationGrp, "att_ang_mid", &angId);
217  check_err(status, __LINE__, __FILE__);
218  status = nc_inq_varid(geoNavigationGrp, "orb_pos_ev_mid", &posId);
219  check_err(status, __LINE__, __FILE__);
220  status = nc_inq_varid(geoNavigationGrp, "orb_vel_ev_mid", &velId);
221  check_err(status, __LINE__, __FILE__);
222 
223  status = nc_inq_grp_ncid(geoFileId, "scan_line_attributes", &geoScanLineGrp);
224  check_err(status, __LINE__, __FILE__);
225  status = nc_inq_varid(geoScanLineGrp, "scan_quality", &scanQualityId);
226  check_err(status, __LINE__, __FILE__);
227  } // geofile
228 
229  // Setup the fill values for the geo products
230  productInfo_t* info = allocateProductInfo();
231  status = findProductInfo("lat", VIIRSN, info);
232  if (status)
233  latL2FillValue = info->fillValue;
234  status = findProductInfo("lon", VIIRSN, info);
235  if (status)
236  lonL2FillValue = info->fillValue;
237  status = findProductInfo("sena", VIIRSN, info);
238  if (status)
239  senaL2FillValue = info->fillValue;
240  status = findProductInfo("senz", VIIRSN, info);
241  if (status)
242  senzL2FillValue = info->fillValue;
243  status = findProductInfo("sola", VIIRSN, info);
244  if (status)
245  solaL2FillValue = info->fillValue;
246  status = findProductInfo("solz", VIIRSN, info);
247  if (status)
248  solzL2FillValue = info->fillValue;
249  freeProductInfo(info);
250 
251  return (LIFE_IS_GOOD);
252 }
253 
254 int readl1_viirs_nc(filehandle *file, int32_t line, l1str *l1rec) {
255  static int firstCall = 1;
256 
257  int32_t ip, ib, ipb;
258  int i;
259  double f_corr;
260 
261  int status; //, ncid, varid;
262  size_t start[] = { 0, 0, 0 };
263  size_t count[] = { 1, 1, 1 };
264 
265  int32_t scan = line / MBAND_NUM_DETECTORS;
266 
267  for (ip = 0; ip < npix; ip++) {
268  l1rec->pixnum[ip] = ip + extract_pixel_start;
269  }
270 
271  if (firstCall) {
272  firstCall = 0;
273 
274  // init calibration only if a geo file was given
275  if (file->geofile && file->geofile[0]) {
276 
277  /*----- Calibration LUT -----*/
278  if (l1_input->calfile[0]) {
279  double grantime = starttime + 378691200.0; // unix (1970) -> UTC58
280  grantime *= 1000000.0; // convert to IET
281  load_fcal_lut(l1_input->calfile, (int64_t) grantime, &f_cal_corr);
282  }
283 
284  // Initialize L1A calibration
285  VcstViirsCal_initialize(file->name, l1_input->viirscalparfile);
286 
287  tmpShort = (short *) malloc(npix * sizeof(short));
288  tmpByte = (unsigned char *) malloc(npix);
289  }
290  }
291 
292  // l1rec->sensorID = file->sensorID;
293  l1rec->npix = file->npix;
294 
295  // set time for this scan - if scan_start_time value not properly set, estimate from scene start time.
296  if (scan != prevScan) {
297  start[0] = scan;
298  status = nc_get_var1_double(scanLineGrp, scanStartTimeId, start, &scan_start_tai);
299  check_err(status, __LINE__, __FILE__);
300  }
301 
302  if (scan_start_tai > 0) {
303  lastvalidtime = tai93_to_unix(scan_start_tai);
304  lastvalidscan = line;
305  l1rec->scantime = lastvalidtime;
306  } else {
307  l1rec->scantime = lastvalidtime + (time_interval * (line - lastvalidscan));
308  }
309 
310  //------------------------------------
311  // if there is no geo file just return
312  // This is used for l1info with only a L1A file and no GEO
313  //-------------------------------------
314  if (!file->geofile || !file->geofile[0]) {
315  return 0;
316  }
317 
318  // first check the scan quality flag
319  // 1 SCE_side_A_B
320  // 2 SCE_side_invalid
321  // 4 Sector_rotation
322  // 8 Encoder_degraded
323  // 16 SAA
324  // 32 Solar_eclipse
325  // 64 Lunar_eclipse
326  // 128 HAM_side
327  //
328  // Sector_rotation
329  short scanQualityWarnMask = 2 | 8 | 128;
330  short scanQualityFailMask = 4;
331  static short scanQualityFlag = 0;
332 
333  if (scan != prevScan) {
334  start[0] = scan;
335  status = nc_get_var1_short(geoScanLineGrp, scanQualityId, start, &scanQualityFlag);
336  check_err(status, __LINE__, __FILE__);
337  }
338  if (scanQualityFlag & scanQualityFailMask) {
339  for (ip = 0; ip < npix; ip++)
340  l1rec->flags[ip] |= NAVFAIL;
341  return 0;
342  }
343  if (scanQualityFlag & scanQualityWarnMask) {
344  for (ip = 0; ip < npix; ip++)
345  l1rec->flags[ip] |= NAVWARN;
346  }
347 
348  static unsigned char HAMSideVal = 0;
349  if (scan != prevScan) {
350  start[0] = scan;
351  status = nc_get_var1_uchar(scanLineGrp, HAMSideId, start, &HAMSideVal);
352  check_err(status, __LINE__, __FILE__);
353  }
354  l1rec->mside = HAMSideVal;
355 
356  // set up to read all pixels of the line.
357  start[0] = line;
358  start[1] = 0;
359  count[0] = 1;
360  count[1] = npix; // read all pixels
361 
362  status = nc_get_vara_float(geoGeolocationGrp, latId, start, count, l1rec->lat);
363  check_err(status, __LINE__, __FILE__);
364  for (i = 0; i < npix; i++)
365  if (l1rec->lat[i] == latGeoFillValue)
366  l1rec->lat[i] = latL2FillValue;
367 
368  status = nc_get_vara_float(geoGeolocationGrp, lonId, start, count, l1rec->lon);
369  check_err(status, __LINE__, __FILE__);
370  for (i = 0; i < npix; i++)
371  if (l1rec->lon[i] == lonGeoFillValue)
372  l1rec->lon[i] = lonL2FillValue;
373 
374  status = nc_get_vara_short(geoGeolocationGrp, solzId, start, count, tmpShort);
375  check_err(status, __LINE__, __FILE__);
376  for (i = 0; i < npix; i++)
377  if (tmpShort[i] == solzGeoFillValue)
378  l1rec->solz[i] = solzL2FillValue;
379  else
380  l1rec->solz[i] = tmpShort[i] * 0.01;
381 
382  status = nc_get_vara_short(geoGeolocationGrp, solaId, start, count, tmpShort);
383  check_err(status, __LINE__, __FILE__);
384  for (i = 0; i < npix; i++)
385  if (tmpShort[i] == solaGeoFillValue)
386  l1rec->sola[i] = solaL2FillValue;
387  else
388  l1rec->sola[i] = tmpShort[i] * 0.01;
389 
390  status = nc_get_vara_short(geoGeolocationGrp, senzId, start, count, tmpShort);
391  check_err(status, __LINE__, __FILE__);
392  for (i = 0; i < npix; i++)
393  if (tmpShort[i] == senzGeoFillValue)
394  l1rec->senz[i] = senzL2FillValue;
395  else
396  l1rec->senz[i] = tmpShort[i] * 0.01;
397 
398  status = nc_get_vara_short(geoGeolocationGrp, senaId, start, count, tmpShort);
399  check_err(status, __LINE__, __FILE__);
400  for (i = 0; i < npix; i++)
401  if (tmpShort[i] == senaGeoFillValue)
402  l1rec->sena[i] = senaL2FillValue;
403  else
404  l1rec->sena[i] = tmpShort[i] * 0.01;
405 
406  /* Load Angles */
407  float ang[3]; // degrees
408  float pos[3]; // km
409  float vel[3]; // km/sec
410  size_t s3[] = { scan, 0 };
411  size_t c3[] = { 1, 3 };
412  status = nc_get_vara_float(geoNavigationGrp, angId, s3, c3, ang);
413  check_err(status, __LINE__, __FILE__);
414  status = nc_get_vara_float(geoNavigationGrp, posId, s3, c3, pos);
415  check_err(status, __LINE__, __FILE__);
416  status = nc_get_vara_float(geoNavigationGrp, velId, s3, c3, vel);
417  check_err(status, __LINE__, __FILE__);
418  for (i = 0; i < 3; i++) {
419  pos[i] /= 1000.; // m -> km
420  vel[i] /= 1000.; // m/s -> km/s
421  }
422 
423  /* Compute polarization rotation angles */
424  float sen_mat[3][3], coeff[10];
425  double mnorm[3];
426  ocorient_(pos, vel, ang, sen_mat, coeff);
427  for (i = 0; i < 3; i++)
428  mnorm[i] = sen_mat[i][0];
429  compute_alpha(l1rec->lon, l1rec->lat,
430  l1rec->senz, l1rec->sena,
431  mnorm, l1rec->npix, l1rec->alpha);
432 
433  /* Check pixel values */
434  status = nc_get_vara_uchar(geoGeolocationGrp, pixelQualityId, start, count, tmpByte);
435  check_err(status, __LINE__, __FILE__);
436  // 1 Input_invalid
437  // 2 Pointing_bad
438  // 4 Terrain_bad
439  unsigned char qualityFailMask = 1 | 2;
440  unsigned char qualityWarnMask = 4;
441  for (i = 0; i < npix; i++) {
442  if (tmpByte[i] & qualityFailMask)
443  l1rec->flags[i] |= NAVFAIL;
444  if (tmpByte[i] & qualityWarnMask)
445  l1rec->flags[i] |= NAVWARN;
446  }
447 
448  /* Earth-sun distance correction for this scan */
449  static double esdist = -999.9;
450  if (scan != prevScan) {
451  int16_t year, day;
452  double dsec;
453  unix2yds(l1rec->scantime, &year, &day, &dsec);
454  int32_t yr = (int32_t) year;
455  int32_t dy = (int32_t) day;
456  int32_t msec = (int32_t) (dsec * 1000.0);
457  esdist = esdist_(&yr, &dy, &msec);
458  }
459  l1rec->fsol = pow(1.0 / esdist, 2);
460 
461  int nbands = 16; //, nRSBbands = 10, nCIRbands = 1, nTEBbands = 5;
462 
463  // read in calibrated L1B data
464  static float *l1bptrs[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
465  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
466 
467  static char *bandType[16] = {"RSB", "RSB", "RSB", "RSB", "RSB", "RSB",
468  "RSB", "RSB", "CIR", "RSB", "RSB", "TEB",
469  "TEB", "TEB", "TEB", "TEB"};
470 
471  // Note: l1bptrs arrays are 3200 pixels wide
472  int oldVerbose = want_verbose;
473  want_verbose = 0;
475  want_verbose = oldVerbose;
476 
477  l1rec->detnum = line % file->ndets;
478 
479  int irsb = 0, iteb = 0;
480  int l1bptrs_scan_idx;
481  for (ib = 0; ib < nbands; ib++) {
482 
483  /* get specific f table cal correction */
484  f_corr = (f_cal_corr == NULL) ? 1.0
485  : f_cal_corr[ib][l1rec->detnum][l1rec->mside];
486 
487  if (strcmp(bandType[ib], "TEB") == 0) {
488 
489  for (ip = 0; ip < npix; ip++) {
490  ipb = ip * NBANDSIR + iteb;
491  l1rec->Ltir[ipb] = 0;
492 
493  l1bptrs_scan_idx = l1rec->detnum * 3200 + ip + extract_pixel_start;
494 
495  if (l1bptrs[ib][l1bptrs_scan_idx] != -32767) {
496  l1rec->Ltir[ipb] = l1bptrs[ib][l1bptrs_scan_idx] / 10.0;
497 
498  /* Apply F-factor */
499  l1rec->Ltir[ipb] *= f_corr;
500  }
501 
502  }
503  iteb++;
504 
505  } else if (strcmp(bandType[ib], "CIR") == 0) {
506 
507  for (ip = 0; ip < npix; ip++) {
508 
509  l1bptrs_scan_idx = l1rec->detnum * 3200 + ip + extract_pixel_start;
510 
511  if (l1bptrs[ib][l1bptrs_scan_idx] != -32767) {
512  l1rec->rho_cirrus[ip] = l1bptrs[ib][l1bptrs_scan_idx];
513 
514  /* Normalize reflectance by solar zenith angle */
515  l1rec->rho_cirrus[ip] /= cos(l1rec->solz[ip] / RADEG);
516 
517  /* Apply F-factor */
518  l1rec->rho_cirrus[ip] *= f_corr;
519  }
520 
521  }
522 
523  } else if (strcmp(bandType[ib], "RSB") == 0) {
524 
525  l1rec->Fo[irsb] = Fobar[irsb] * l1rec->fsol;
526 
527  // copy to Lt record.
528  for (ip = 0; ip < npix; ip++) {
529  ipb = ip * l1rec->l1file->nbands + irsb;
530 
531  l1bptrs_scan_idx = l1rec->detnum * 3200 + ip + extract_pixel_start;
532 
533  if (l1bptrs[ib][l1bptrs_scan_idx] != -32767) {
534  l1rec->Lt[ipb] = l1bptrs[ib][l1bptrs_scan_idx];
535 
536  /* convert from reflectance to radiance */
537  l1rec->Lt[ipb] *= l1rec->Fo[irsb] / PI;
538 
539  /* Apply F-factor */
540  l1rec->Lt[ipb] *= f_corr;
541  }
542 
543  }
544  irsb++;
545  } // if RSB
546 
547  } // for ib
548 
549  radiance2bt(l1rec, -1); // calculate brightness temperature
550 
551  for (ip = 0; ip < npix; ip++) {
552  flag_bowtie_deleted(l1rec, ip, extract_pixel_start);
553  }
554 
555  prevScan = scan;
556  return (LIFE_IS_GOOD);
557 }
558 
559 int readl1_lonlat_viirs_nc(filehandle *file, int32_t line, l1str *l1rec) {
560  int32_t ip;
561  int status;
562  size_t start[] = { 0, 0, 0 };
563  size_t count[] = { 1, 1, 1 };
564 
565  int32_t scan = line / MBAND_NUM_DETECTORS;
566 
567  if (!file->geofile || !file->geofile[0]) {
568  printf("-E- Geolocation file needs to be set\n");
569  exit(EXIT_FAILURE);
570  }
571 
572  // l1rec->sensorID = file->sensorID;
573  l1rec->npix = file->npix;
574 
575  // set time for this scan - if scan_start_time value not properly set, estimate from scene start time.
576  if (scan != prevScan) {
577  start[0] = scan;
578  status = nc_get_var1_double(scanLineGrp, scanStartTimeId, start, &scan_start_tai);
579  check_err(status, __LINE__, __FILE__);
580  }
581 
582  if (scan_start_tai > 0) {
583  lastvalidtime = tai93_to_unix(scan_start_tai);
584  lastvalidscan = line;
585  l1rec->scantime = lastvalidtime;
586  } else {
587  l1rec->scantime = lastvalidtime + (time_interval * (line - lastvalidscan));
588  }
589 
590  // set up to read all pixels of the line.
591  start[0] = line;
592  start[1] = 0;
593  count[0] = 1;
594  count[1] = npix; // read all pixels
595 
596  status = nc_get_vara_float(geoGeolocationGrp, latId, start, count, l1rec->lat);
597  check_err(status, __LINE__, __FILE__);
598 
599  status = nc_get_vara_float(geoGeolocationGrp, lonId, start, count, l1rec->lon);
600  check_err(status, __LINE__, __FILE__);
601 
602  prevScan = scan;
603 
604  for (ip = 0; ip < npix; ip++) {
605  // convert the fill values to the proper value
606  if (l1rec->lat[ip] == latGeoFillValue)
607  l1rec->lat[ip] = latL2FillValue;
608  if (l1rec->lon[ip] == lonGeoFillValue)
609  l1rec->lon[ip] = lonL2FillValue;
610  }
611 
612  return (LIFE_IS_GOOD);
613 }
614 
615 int closel1_viirs_nc(filehandle *file) {
616  int status;
617 
618  status = nc_close(file->sd_id);
619  check_err(status, __LINE__, __FILE__);
620 
621  if (file->geofile && file->geofile[0]) {
622  status = nc_close(geoFileId);
623  check_err(status, __LINE__, __FILE__);
624 
625  free(tmpShort);
626  free(tmpByte);
627  }
628 
629  return (LIFE_IS_GOOD);
630 }
631 
void freeProductInfo(productInfo_t *info)
int32_t day
int status
Definition: l1_czcs_hdf.c:32
void check_err(const int stat, const int line, const char *file)
Definition: nc4utils.c:35
int openl1_viirs_nc(filehandle *file)
Definition: l1_viirs_nc.c:62
double mnorm[3]
#define NBANDSIR
Definition: filehandle.h:23
void VcstViirsCal_calibrateMOD(int iScan, int nbands, float **l1bptrs)
int16_t fileID
#define NULL
Definition: decode_rs.h:63
MOD_PR01 Production producing one five minute granule of output data in each run It can be configured to produce as many as three five minute granules per run Each execution with one construction record and one date file for each dataset In normal these are created by which splits them out of the hour datasets For LANCE they are created by which merges all session MODIS L0 datasets overlapping the requested time and extracts from the merged data those packets which fall within that time period Each scan of data is stored in the L1A granule that covers the start time of that scan
Definition: MOD_PR01_pr.txt:19
void ocorient_(float *pos, float *vel, float *att, float(*)[3], float *coef)
read l1rec
#define VIIRSN
Definition: sensorDefs.h:23
float32 * pos
Definition: l1_czcs_hdf.c:35
int32 * msec
Definition: l1_czcs_hdf.c:31
double esdist_(int32_t *year, int32_t *day, int32_t *msec)
int32 nscan
Definition: l1_czcs_hdf.c:19
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude resolving resolving GSFcd00179 Corrected handling of fill values for[Sensor|Solar][Zenith|Azimuth] resolving MODxl01751 Changed to validate LUT version against a value retrieved from the resolving MODxl02056 Changed to calculate Solar Diffuser angles without adjustment for estimated post launch changes in the MODIS orientation relative to incidentally resolving defects MODxl01766 Also resolves MODxl01947 Changed to ignore fill values in SCI_ABNORM and SCI_STATE rather than treating them as resolving MODxl01780 Changed to use spacecraft ancillary data to recognise when the mirror encoder data is being set by side A or side B and to change calculations accordingly This removes the need for seperate LUTs for Side A and Side B data it makes the new LUTs incompatible with older versions of the and vice versa Also resolves MODxl01685 A more robust GRing algorithm is being which will create a non default GRing anytime there s even a single geolocated pixel in a granule Removed obsolete messages from seed file
Definition: HISTORY.txt:413
character(len=1000) if
Definition: names.f90:13
#define LIFE_IS_GOOD
Definition: passthebuck.h:4
#define PI
Definition: l3_get_org.c:6
int closel1_viirs_nc(filehandle *file)
Definition: l1_viirs_nc.c:615
void compute_alpha(float lon[], float lat[], float senz[], float sena[], double mnorm[3], int npix, float alpha[])
Definition: compute_alpha.c:8
productInfo_t * allocateProductInfo()
double tai93_to_unix(double tai93)
Definition: yds2tai.c:16
l1_input_t * l1_input
Definition: l1_options.c:9
int want_verbose
void unix2yds(double usec, short *year, short *day, double *secs)
#define RADEG
Definition: czcs_ctl_pt.c:5
int findProductInfo(const char *productName, int sensorId, productInfo_t *info)
int load_fcal_lut(char *calfile, int64_t UTC58usec, double ****ftable)
int32_t nbands
void radiance2bt(l1str *l1rec, int resolution)
Definition: brightness.c:170
#define MBAND_NUM_DETECTORS
Definition: l1_viirs_nc.c:17
int readl1_viirs_nc(filehandle *file, int32_t line, l1str *l1rec)
Definition: l1_viirs_nc.c:254
real *8 function esdist(iyr, iday, msec)
Definition: esdist.f:3
int32_t rdsensorinfo(int32_t, int32_t, const char *, void **)
Definition: rdsensorinfo.c:69
void VcstViirsCal_initialize(char *l1aFilename, char *l1aCalParFilename)
int readl1_lonlat_viirs_nc(filehandle *file, int32_t line, l1str *l1rec)
Definition: l1_viirs_nc.c:559
int i
Definition: decode_rs.h:71
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
void flag_bowtie_deleted(l1str *l1rec, size_t ipix, int extract_offset)
Definition: l1b_viirs_nc.c:881
int npix
Definition: get_cmp.c:27
double isodate2unix(const char *isodate)
Definition: unix2isodate.c:61
int count
Definition: decode_rs.h:79