NASA Logo
Ocean Color Science Software

ocssw V2022
l1_viirs_h5.c
Go to the documentation of this file.
1 /* ========================================================================= */
2 /* module l1_viirs_h5.c - functions to read VIIRS L1B for MSL12 */
3 /* */
4 /* Written By: W. Robinson, SAIC, Feb, 2009 based on l1_modis_hdf.c */
5 /* W. Robinson, SAIC, 13 Nov 2012 add reading of height from the GEO file */
6 /* W. Robinson, SAIC, 9 Apr 2013 add capability to process */
7 /* time-aggregated files */
8 /* W. Robinson, SAIC, 5 Jun 2014 fix mirror normal used in polarization calc */
9 /* */
10 /* ========================================================================= */
11 
12 #include "libnav.h"
13 #include "l1_viirs_h5.h"
14 #include "l1.h"
15 #include <string.h>
16 #include <unistd.h>
17 #include <sys/types.h>
18 #include <dirent.h>
19 #include <libgen.h>
20 #include <ctype.h>
21 
22 
23 #define MAXBANDS 16
24 #define STDMAXSCANS 48 /* for std granule - max # scans */
25 #define NDET 16
26 #define N_MS 2
27 #define NAGGPX 3200
28 #define NUMERATOR 0
29 #define DENOMINATOR 1
30 #define near( x, y ) ( fabsf( x - y ) < 0.001 )
31 
32 /* define fill condition values */
33 #define NA_FLOAT32_FILL -999.9f /* Algorithm Exclusions */
34 #define NA_UINT16_FILL 65535
35 #define MISS_FLOAT32_FILL -999.8f /* Missing at Time of Processing */
36 #define MISS_UINT16_FILL 65534
37 #define ONBOARD_PT_FLOAT32_FILL -999.7f /* Onboard Pixel Trimi (bow tie) */
38 #define ONBOARD_PT_UINT16_FILL 65533
39 #define ONGROUND_PT_FLOAT32_FILL -999.6f /* On-ground Pixel Trim */
40 #define ONGROUND_PT_UINT16_FILL 65532
41 #define ERR_FLOAT32_FILL -999.5f /* Cannot Calculate */
42 #define ERR_UINT16_FILL 65531
43 #define ELINT_FLOAT32_FILL -999.4f /* Ellipsoid Intersection Failed */
44 #define ELINT_UINT16_FILL 65530
45 #define VDNE_FLOAT32_FILL -999.3f /* Value Does Not Exist */
46 #define VDNE_UINT16_FILL 65529
47 #define SOUB_FLOAT32_FILL -999.2f /* Scaling Out Of Bounds */
48 #define SOUB_UINT16_FILL 65528
49 
50 int gen_sdr_suite(char *);
51 int set_f_cal_corr(h5io_str *, filehandle *, int64_t);
52 int rd_vir_f_tbl(char *, int64_t, int);
53 
54 /* all the band file names, file IDs for geo and bands and needed
55  group and dataset ids */
56 static char vfnames[MAXBANDS][FILENAME_MAX];
57 static h5io_str geo_fid, sdr_fid[MAXBANDS];
58 static h5io_str geo_dat_id[7], bnd_dat_id[2][MAXBANDS];
59 static char sdr_band_typ[MAXBANDS]; /* 0 if scaled, 1 if float */
60 static unsigned short *scl_rad; /* storage for the scaled radiance values */
61 static float *scale, *offset; /* scaling factors */
62 static float *flt_rad; /* for float radiance read from file */
63 static int64_t *u58_scn_st, u58_gran_st, u58_gran_en;
64 static float *Fobar;
65 static unsigned char *viirs_qual2; /* storage for the SDR scan quality info */
66 /*
67  * the 2 ..._map items track the locations of scans that have real data in
68  * them, to account for the scans in the datasets that don't have instrument
69  * data in them and get concatenated together in an time aggregate
70  * the gran_map tells what granule the scan is in.
71  */
72 static int *gran_map; /* granule assoc to a scan */
73 static int *scan_map; /* real dataset scan location */
74 /* from the QF2_SCAN_SDR, get mirror side
75  from here too */
76 static float *pos, *vel, *att; /* position, velocity, sensor attitude */
77 static int16_t scn_fmt; /* local scan format store */
78 static int16_t margin[2]; /* margin storage */
79 
80 #define VSWIR 0
81 #define THERM 1
82 #define CIRRUS 2
83 static int32_t btype[] = {0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 1, 1, 1, 1};
84 static int32_t ivswir = 0;
85 static int32_t itherm = 0;
86 static double f_cal_corr[MAXBANDS * NDET * N_MS]; /* f table correction */
87 
88 void fix_viirs_filename(char* name) {
89  char tmp[FILENAME_MAX];
90  char dir[FILENAME_MAX];
91  char base[FILENAME_MAX];
92 
93  // see if file exists
94  if( access(name, R_OK ) == 0 ) {
95  return;
96  }
97 
98  // see if we can find a file that matches the first 44 char of the file name
99  // This will happen if the creation time is the last part of the filename.
100  strcpy(tmp, name);
101  strcpy(base, basename(tmp));
102  strcpy(tmp, name);
103  strcpy(dir, dirname(tmp));
104 
105  DIR *dp;
106  struct dirent *entry;
107  if((dp = opendir(dir)) == NULL) {
108  fprintf(stderr, "%s:%d - cannot open directory: %s\n", __FILE__, __LINE__, dir);
109  exit(EXIT_FAILURE);
110  }
111 
112  int fileFound = 0;
113  while((entry = readdir(dp)) != NULL) {
114  if(strncmp(entry->d_name, base, 44) == 0){
115  fileFound = 1;
116  sprintf(name, "%s/%s", dir, entry->d_name);
117  break;
118  }
119  }
120  closedir(dp);
121 
122  if(!fileFound) {
123  fprintf(stderr, "%s:%d - valid VIIRS file not found: %s\n", __FILE__, __LINE__, name);
124  exit(EXIT_FAILURE);
125  }
126 
127 }
128 
129 int gen_sdr_suite(char *in_file)
130 /*******************************************************************
131 
132  gen_sdr_suite
133 
134  purpose: check the initial L1b sdr name to conform to VIIRS format and
135  generate the full SDR name suite from that 1 name
136 
137  Returns type: int - description
138 
139  Parameters: (in calling order)
140  Type Name I/O Description
141  ---- ---- --- -----------
142  char * in_file I input VIIRS file with path
143 
144  Modification history:
145  Programmer Date Description of change
146  ---------- ---- ---------------------
147  W. Robinson 9-Feb-2009 Original development
148  W. Robinson, SAIC 6Aug2010 add ability to read suite from text file
149 
150  *******************************************************************/ {
151  char *path, temp[FILENAME_MAX], base[FILENAME_MAX];
152  int i, j;
153  h5io_str h5fid;
154  FILE *fp;
155 
156  /*
157  * if the file is a text file with names (not hdf 5) extract file names
158  */
159  if (h5io_openr(in_file, 0, &h5fid) != 0) {
160  if ((fp = fopen(in_file, "r")) == NULL) {
161  fprintf(stderr, "-E- %s, %d: input file %s open problem.\n",
162  __FILE__, __LINE__, in_file);
163  return 1;
164  }
165  /*
166  * get the file names of needed bands
167  */
168  for (i = 0, j = 1; i < MAXBANDS; i++, j++) {
169  if (fscanf(fp, "%s", vfnames[i]) != 1) {
170  fprintf(stderr,
171  "-E- %s, %d: Failed to read VIIRS input file # %d from list file: %s/n",
172  __FILE__, __LINE__, i, in_file);
173  return 1;
174  }
175  }
176  fclose(fp);
177  } else {
178  h5io_close(&h5fid);
179  /*
180  * Although standard VIIRS file names have much more, just accept
181  * SDR files with the base starting with SVMxx (xx is band #)
182  */
183  strcpy(temp, in_file);
184  strcpy(base, basename(temp));
185  strcpy(temp, in_file);
186  path = dirname(in_file);
187  /* */
188  if (strncmp(base, "SVM", 3) != 0) {
189  fprintf(stderr,
190  "-E- %s, %d: Improper VIIRS file format for file base:\n",
191  __FILE__, __LINE__);
192  fprintf(stderr, "%s\n", base);
193  return 1;
194  }
195  if (!(isdigit(*(base + 3))) || !(isdigit(*(base + 4)))) {
196  fprintf(stderr,
197  "-E- %s, %d: Improper VIIRS file format for file base:\n",
198  __FILE__, __LINE__);
199  fprintf(stderr, "%s\n", base);
200  return 1;
201  }
202  for (i = 0, j = 1; i < MAXBANDS; i++, j++) {
203  sprintf(vfnames[i], "%s/SVM%2.2d%s", path, j, base + 5);
204  fix_viirs_filename(vfnames[i]);
205  if (want_verbose)
206  printf("VIIRS filename for M%2.2d: %s\n", j, vfnames[i]);
207  }
208  }
209  return (LIFE_IS_GOOD);
210 }
211 
212 /* ------------------------------------------------------------------------
213  set_f_cal_corr
214 
215  purpose: create the array of f table corrections to apply to the radiances
216  using the input cal table and the SDR indicated cal table
217 
218  Parameters: (in calling order)
219  Type Name I/O Description
220  ---- ---- --- -----------
221  h5io_str * g_id I group id of the area with
222  the granule metadata
223  (specifically the tables used)
224  filehandle * file I input L1 file info, including
225  processing options
226  int64_t u58_time I start time of the granule in
227  IET units
228 
229  (the array of f table corrections, f_cal_corr is shared in the
230  l1_viirs_h5.c routine)
231 
232  Modification history:
233  Programmer Date Description of change
234  ---------- ---- ---------------------
235  W. Robinson, SAIC 11 Sep 2012 add the ability to process pseudo-L1A
236  SDR files
237 
238  ------------------------------------------------------------------------*/
239 int set_f_cal_corr(h5io_str *g_id, filehandle *file, int64_t u58_time) {
240  char *in_calfile, sdr_cal_fil[FILENAME_MAX], *csave = NULL;
241  char *aux_arr, *fildir;
242  int ncorr, icorr, f_ndim, f_dim_siz[20], f_sto_len, i;
243  H5T_class_t f_class;
244  hid_t f_native_typ;
245  /*
246  * the f_cal_corr is used always to add any radiance correction.
247  * These values are only non-unity if a cal table is specified
248  *
249  * set up default unity table
250  */
251  ncorr = N_MS * NDET * MAXBANDS;
252  for (icorr = 0; icorr < ncorr; icorr++)
253  *(f_cal_corr + icorr) = 1.;
254 
255  in_calfile = l1_input->calfile;
256  /*
257  * If no cal table is specified, it is done
258  */
259  if (want_verbose)
260  printf("\nVIIRS calibration starting\n");
261  if (*in_calfile == 0) {
262  if (want_verbose)
263  printf("No cal file supplied, calibration remains unchanged\n");
264  return 0;
265  }
266  if (want_verbose)
267  printf("Input calibration from file: %s\n", in_calfile);
268  /*
269  * The numerator of the f table correction comes from the input cal file, but
270  * is one if the table is 'Unity'
271  * otherwise, make the numerator of the correction from the specified f table
272  * If any cal file is specified, it will back out the existing cal and use
273  * the new cal. If the existing cal was 'Unity' it will not have to back
274  * out the cal.
275  */
276  if (strstr(in_calfile, "Unity") == NULL) {
277  if (rd_vir_f_tbl(in_calfile, u58_time, NUMERATOR) != 0) {
278  printf("%s, %d - E - failed to retrieve input F table values\n",
279  __FILE__, __LINE__);
280  return 1;
281  }
282  } else if (want_verbose)
283  printf("Input calibration is from the unity F table, Using unity\n");
284  /*
285  * any cal other than unity in the SDR is removed by placing it into the
286  * denominator of the correction array
287  */
288  /*
289  * get some info on the attribute
290  */
291  if (h5io_info(g_id, "N_Aux_Filename", &f_class, &f_native_typ, &f_ndim,
292  f_dim_siz, &f_sto_len) != 0) {
293  printf("%s, %d - E - could not get info on N_Aux_Filename\n", __FILE__,
294  __LINE__);
295  return 1;
296  }
297  /*
298  * allocate space for the times
299  */
300  if ((aux_arr = (char *) malloc(f_sto_len * f_dim_siz[0] * sizeof (char)))
301  == NULL) {
302  printf("%s, %d - E - unable to allocate aux filename list array\n",
303  __FILE__, __LINE__);
304  return 1;
305  }
306  /*
307  * read the attribute
308  */
309  if (h5io_rd_attr(g_id, "N_Aux_Filename", aux_arr) != 0) {
310  printf("%s, %d - failed to read the N_Aux_Filename attribute\n",
311  __FILE__, __LINE__);
312  return 1;
313  }
314  /*
315  * find the F LUT in the strings
316  */
317  for (i = 0; i < f_dim_siz[0]; i++) {
318  /* printf( "# %3d: %s\n", i, ( aux_arr + i * f_sto_len ) ); */
319  if (strstr((aux_arr + i * f_sto_len), "VIIRS-SDR-F-LUT_npp") != NULL)
320  csave = (aux_arr + i * f_sto_len);
321  }
322  if (csave == NULL) {
323  /*
324  * there can be another, dynamic F-LUT now. If it is found, we cannot
325  * deal with that now. Advise user to NOT use a F-LUT to calibrate with
326  */
327  printf("%s ,%d: I: No F-LUT found, Looking for F-PREDICTED-LUT\n",
328  __FILE__, __LINE__);
329  for (i = 0; i < f_dim_siz[0]; i++) {
330  /*printf( "# %3d: %s\n", i, ( aux_arr + i * f_sto_len ) ); */
331  if (strstr((aux_arr + i * f_sto_len),
332  "VIIRS-SDR-F-PREDICTED-LUT_npp") != NULL)
333  csave = (aux_arr + i * f_sto_len);
334  }
335  if (csave == NULL) {
336  printf(
337  "%s, %d E - failed to find the F LUT name in N_Aux_Filename\n",
338  __FILE__, __LINE__);
339  return 1;
340  } else {
341  printf(
342  "%s, %d - A F-PREDICTED-LUT was found, but code is not set-up\n",
343  __FILE__, __LINE__);
344  printf(
345  " to handle this kind of LUT. Set 'calfile=' in par file\n");
346  printf(" to leave cal unchanged\n");
347  return 1;
348  }
349  }
350  if (want_verbose)
351  printf("\n\nThe F LUT found in the SDR is: %s\n", csave);
352  /*
353  * look for a Unity file
354  */
355  if (strstr(csave, "Unity") != NULL) {
356  if (want_verbose)
357  printf("Found a unity F table designation in the SDR\n");
358  } else {
359  /*
360  * the name of the file should be what was found with a .h5 after it
361  * in path $OCVARROOT/viirsn/cal/EVAL/
362  */
363  if ((fildir = getenv("OCVARROOT")) == NULL) {
364  printf("-E- %s, %d: OCVARROOT env variable undefined.\n", __FILE__,
365  __LINE__);
366  exit(1);
367  }
368  strcpy(sdr_cal_fil, fildir);
369  strcat(sdr_cal_fil, "/viirsn/cal/EVAL/");
370  strcat(sdr_cal_fil, csave);
371  strcat(sdr_cal_fil, ".h5");
372  printf("F Lut file name derived from the SDR is: %s\n", sdr_cal_fil);
373  /*
374  * Only for non-unity table, read the f table values into the correction
375  * array denominator
376  */
377  if (rd_vir_f_tbl(sdr_cal_fil, u58_time, DENOMINATOR) != 0) {
378  printf("-E- %s, %d: Failed to retrieve SDR F table values\n",
379  __FILE__, __LINE__);
380  return 1;
381  }
382  }
383  /*
384  * The corrections are all set to be applied
385  */
386  if (want_verbose)
387  printf("Completed calibration using F LUT file(s)\n\n");
388  free(aux_arr);
389  return 0;
390 }
391 
392 /* ------------------------------------------------------------------------
393 
394  rd_vir_f_tbl
395 
396  purpose: read F table lut high gain corrections and apply them to the
397  correction array for the specified time of the viirs granule
398 
399  Parameters: (in calling order)
400  Type Name I/O Description
401  ---- ---- --- -----------
402  char * file I F LUT table file name
403  int64_t u58_time I Granule time
404  int corr_loc I either NUMERATOR or DENOMINATOR
405  to apply f table values to the
406  proper part of the correction
407  array
408 
409  Modification history:
410  Programmer Date Description of change
411  ---------- ---- ---------------------
412  W. Robinson, SAIC 11 Sep 2012 Original development
413  W. Robinson, SAIC 16 Nov 2012 mod to extrapolate using end 2 points
414 
415  ------------------------------------------------------------------------*/
416 int rd_vir_f_tbl(char *file, int64_t u58_time, int corr_loc) {
417  /* f_lut_sel [ # ms, # det, # bands, # times ] (ms fastest) */
418  double f_lut_sel[2 * 16 * 16 * 2];
419  int64_t *tarr, del, dist, u58_t1, u58_t2;
420  int start[5], count[5];
421  H5T_class_t f_class;
422  hid_t f_native_typ;
423  h5io_str h5fid, dsid;
424  int f_ndim, f_dim_siz[20], f_sto_len, ntime, itim1, ncorr, i;
425  float fact;
426  /*
427  * open the LUT file and get the times available
428  */
429  if (want_verbose)
430  printf("Reading in F LUT: %s\n", file);
431  if (h5io_openr(file, 0, &h5fid) != 0) {
432  printf("- E - %s, %d: Unable to open the F LUT file: %s\n", __FILE__,
433  __LINE__, file);
434  return 1;
435  }
436  /*
437  * get the info on the times
438  */
439  if (h5io_set_ds(&h5fid, "Beginning_Time_IET", &dsid) != 0) {
440  printf("- E - %s, %d: Unable to set dataset Beginning_Time_IET\n",
441  __FILE__, __LINE__);
442  return 1;
443  }
444  if (h5io_info(&dsid, NULL, &f_class, &f_native_typ, &f_ndim, f_dim_siz,
445  &f_sto_len) != 0) {
446  printf("- E - %s, %d: Unable to get info on Beginning_Time_IET\n",
447  __FILE__, __LINE__);
448  return 1;
449  }
450  ntime = f_dim_siz[0];
451  /*
452  * allocate time array and read it
453  */
454  if ((tarr = (int64_t *) malloc(ntime * sizeof (int64_t))) == NULL) {
455  printf("- E - %s, %d: Unable to allocate time storage\n", __FILE__,
456  __LINE__);
457  return 1;
458  }
459  if (h5io_rd_ds(&dsid, (void *) tarr) != 0) {
460  printf("- E - %s, %d: Unable to read Beginning_Time_IET\n", __FILE__,
461  __LINE__);
462  return 1;
463  }
464  h5io_close(&dsid);
465  /*
466  * find the 2 times to interpolate between / extrapolate beyond
467  */
468  if (want_verbose)
469  printf("Granule time is: %ld\n", (long) u58_time);
470  if (u58_time < tarr[0]) {
471  printf(
472  "\n\n\n- W - %s, %d: WARNING, granule time below times in the F table\n",
473  __FILE__, __LINE__);
474  itim1 = 0;
475  printf("granule time of %ld is below table start time of %ld\n",
476  (long) u58_time, (long) tarr[0]);
477  } else if (u58_time > *(tarr + ntime - 1)) {
478  printf(
479  "\n\n\n- W - %s, %d: WARNING, granule time higher than times in the F table\n",
480  __FILE__, __LINE__);
481  itim1 = ntime - 2;
482  printf("granule time of %ld is above table end time of %ld\n", (long) u58_time,
483  (long) tarr[ntime - 1]);
484  } else {
485  for (itim1 = 0; itim1 < ntime; itim1++)
486  if (*(tarr + itim1 + 1) > u58_time)
487  break;
488  }
489  /*
490  * get the 2 times
491  */
492  u58_t1 = *(tarr + itim1);
493  u58_t2 = *(tarr + itim1 + 1);
494  if (want_verbose)
495  printf("itim1: %d, t1: %ld, t2: %ld\n", itim1, (long) u58_t1, (long) u58_t2);
496  free(tarr);
497  /*
498  * flut is 2 ms, 3 gain, 32 det, 22 bands, # times, check this
499  */
500  if (h5io_set_ds(&h5fid, "VIIRS-SDR-F-LUT", &dsid) != 0) {
501  printf("- E - %s, %d: Unable to set dataset VIIRS-SDR-F-LUT\n",
502  __FILE__, __LINE__);
503  return 1;
504  }
505  if (h5io_info(&dsid, NULL, &f_class, &f_native_typ, &f_ndim, f_dim_siz,
506  &f_sto_len) != 0) {
507  printf("- E - %s, %d: Unable to get info on dataset VIIRS-SDR-F-LUT\n",
508  __FILE__, __LINE__);
509  return 1;
510  }
511  if (f_ndim != 5) {
512  printf("- E - %s, %d: # dimensions of LUT dataset is not 5\n", __FILE__,
513  __LINE__);
514  return 1;
515  }
516  if ((f_dim_siz[0] != ntime) || (f_dim_siz[1] != 22) || (f_dim_siz[2] != 32)
517  || (f_dim_siz[3] != 3) || (f_dim_siz[4] != 2)) {
518  printf("- E - %s, %d: LUT dataset dimension sizes are unexpected\n",
519  __FILE__, __LINE__);
520  return 1;
521  }
522  /*
523  * read the selected part of the whole lut: both mirror sides,
524  * 1st 16 of 32 detectors, M bands at index 5 - 20, and the 2 times
525  * starting at itim1
526  */
527  start[0] = itim1;
528  start[1] = 5;
529  start[2] = 0;
530  start[3] = 0;
531  start[4] = 0;
532  count[0] = 2;
533  count[1] = 16;
534  count[2] = 16;
535  count[3] = 1;
536  count[4] = 2;
537  if (h5io_rd_ds_slice(&dsid, start, count, (void *) f_lut_sel) != 0) {
538  printf("- E - %s, %d: Unable to read the VIIRS-SDR-F-LUT dataset\n",
539  __FILE__, __LINE__);
540  return 1;
541  }
542  /*
543  * interpolate/extrapolate and apply
544  */
545  ncorr = N_MS * NDET * MAXBANDS;
546  del = u58_t2 - u58_t1;
547  dist = u58_time - u58_t1;
548  fact = (float) dist / (float) del;
549  if (want_verbose)
550  printf("Interp factor from t2: %f\n", fact);
551 
552  if (corr_loc == NUMERATOR)
553  for (i = 0; i < ncorr; i++)
554  *(f_cal_corr + i) *= *(f_lut_sel + i) * (1. - fact)
555  + *(f_lut_sel + i + ncorr) * fact;
556  else
557  for (i = 0; i < ncorr; i++)
558  *(f_cal_corr + i) /= *(f_lut_sel + i) * (1. - fact)
559  + *(f_lut_sel + i + ncorr) * fact;
560  /*
561  * de-allocate space for arrays and close the LUT file
562  */
563  h5io_close(&dsid);
564  h5io_close(&h5fid);
565 
566  return 0;
567 }
568 
577 int h5ReadAttrInt32(h5io_str *id, char *attr_name, int32_t *val) {
578  hid_t *base_grp, spaceid, attr_id;
579 
580  base_grp = (id->type == H5IO_TYP_DAT_ID) ?
581  &(id->dat_id) : &(id->grp_id);
582  if ((attr_id = H5Aopen_name(*base_grp, attr_name)) < 0)
583  return 1;
584 
585  if ((spaceid = H5Aget_space(attr_id)) < 0)
586  return 1;
587 
588  if(H5Sget_simple_extent_npoints(spaceid) != 1) {
589  printf("%s: # of elements of attribute: %s has to be 1\n", __FILE__, attr_name);
590  return 1;
591  }
592 
593  if (H5Aread(attr_id, H5T_NATIVE_INT, val) < 0)
594  return 1;
595 
596  /*
597  * close the allocated spaces before leaving
598  */
599  if (H5Sclose(spaceid) < 0)
600  return 1;
601  if (H5Aclose(attr_id) < 0)
602  return 1;
603  return 0;
604 }
605 
606 /* ------------------------------------------------------------------------
607  openl1_viirs_h5
608 
609  purpose: opens a VIIRS L1B file for reading.
610 
611  Parameters: (in calling order)
612  Type Name I/O Description
613  ---- ---- --- -----------
614  filehandle * file I input file information
615 
616  Modification history:
617  Programmer Date Description of change
618  ---------- ---- ---------------------
619  W. Robinson, SAIC, 10 Feb, 2009 Original development
620 
621  ------------------------------------------------------------------------*/
622 int openl1_viirs_h5(filehandle * file) {
623  int npix, nscan, ibnd, jbnd, ids, i, igran;
624  int *nscan_inst; /* # instrument scans per granule */
625  int *nscan_stat; /* same as nscan_inst, but for dark bands (turned */
626  /* off at night), valued at -993 */
627  int nscan_sto; /* # scans in files storage, can be > nscan_inst_tot */
628  int nscan_inst_tot; /* total # instrument scans in this file */
629  int nscan_per_gran;
630  h5io_str g_id, id_tmp;
631  char g_path[100], geo_all_data_gnam[200], *band_dark, **grp_obj_nm;
632  char *geo_name[] = {"Latitude", "Longitude", "SatelliteAzimuthAngle",
633  "SatelliteZenithAngle", "SolarAzimuthAngle", "SolarZenithAngle",
634  "Height"};
635  float *rad_fact;
636  H5T_class_t h5_class;
637  hid_t h5_native_typ;
638  int ndim, dim_siz[4], sto_len, n_obj, *grp_obj_typ;
639  int terr_corr;
640  unsigned char *cmp_vq2;
641  int16_t ua_scn_fmt, ua_ndets, ua_margin[2];
642  int32_t ua_npix, ua_nlin, attr_exist;
643  int32_t qual2_found = 0, ngran, dgran, iscan, dk;
644  /* dgran will be used for checking the match in different files */
645  int64_t u58_gran;
646  /*
647  * get the names of the suite of VIIRS file names from the input name
648  */
649  if (gen_sdr_suite(file->name) != 0)
650  return 1;
651 
652  // try a reasonable geo file if one is not given
653  if(file->geofile[0] == 0) {
654  strcpy(file->geofile, file->name);
655  file->geofile[0] = 'G';
656  file->geofile[1] = 'M';
657  file->geofile[2] = 'T';
658  file->geofile[3] = 'C';
659  file->geofile[4] = 'O';
660  fix_viirs_filename(file->geofile);
661  }
662 
663  /* Open the HDF input file */
664  /*
665  * for all the SDR band files, open and get, check size and set
666  * up for later dataset access
667  */
668  for (ibnd = 0, jbnd = 1; ibnd < MAXBANDS; ibnd++, jbnd++) {
669  /* open */
670  if (h5io_openr(vfnames[ibnd], 0, (sdr_fid + ibnd)) != 0) {
671  fprintf(stderr, "-E- %s Line %d: Failure to open %s\n", __FILE__,
672  __LINE__, vfnames[ibnd]);
673  return 1;
674  }
675  /*
676  * Determine the # of granules in this file
677  */
678  sprintf(g_path, "Data_Products/VIIRS-M%d-SDR/VIIRS-M%d-SDR_Aggr", jbnd,
679  jbnd);
680  if (h5io_set_ds((sdr_fid + ibnd), g_path, &g_id) != 0) {
681  fprintf(stderr,
682  "-E- %s, %d: Failure to set aggregation dataset, band %d:\n",
683  __FILE__, __LINE__, ibnd);
684  fprintf(stderr, "name: %s\n", vfnames[ibnd]);
685  return 1;
686  }
687  if (h5ReadAttrInt32(&g_id, "AggregateNumberGranules", (void *) &dgran)
688  != 0) {
689  fprintf(stderr,
690  "-E- %s, %d: Unable to read the AggregateNumberGranules attribute\n",
691  __FILE__, __LINE__);
692  fprintf(stderr, "band %d\n, name: %s\n", ibnd, vfnames[ibnd]);
693  return 1;
694  }
695  if (h5io_close(&g_id) != 0) {
696  fprintf(stderr, "-E- %s Line %d: Unable to close granule, ds %d\n",
697  __FILE__, __LINE__, ibnd);
698  return 1;
699  }
700  /*
701  * set up the scan and granule maps and check # granules among band files
702  */
703  if (ibnd == 0) {
704  ngran = dgran;
705  /*
706  * With ngran determined, allocate granule-dependent arrays
707  */
708  if ((scale = (float *) malloc(MAXBANDS * ngran * sizeof (float)))
709  == NULL) {
710  fprintf(stderr,
711  "-E- %s, %d: failure to allocate scale storage\n",
712  __FILE__, __LINE__);
713  return 1;
714  }
715  if ((offset = (float *) malloc(MAXBANDS * ngran * sizeof (float)))
716  == NULL) {
717  fprintf(stderr,
718  "-E- %s, %d: failure to allocate offset storage\n",
719  __FILE__, __LINE__);
720  return 1;
721  }
722  if ((nscan_inst = (int *) malloc(ngran * sizeof (int))) == NULL) {
723  fprintf(stderr,
724  "-E- %s, %d: failure to allocate nscan_inst storage\n",
725  __FILE__, __LINE__);
726  return 1;
727  }
728  if ((nscan_stat = (int *) malloc(ngran * sizeof (int))) == NULL) {
729  fprintf(stderr,
730  "-E- %s, %d: failure to allocate nscan_stat storage\n",
731  __FILE__, __LINE__);
732  return 1;
733  }
734  if ((band_dark = (char *) calloc(ngran * MAXBANDS, sizeof (char)))
735  == NULL) {
736  fprintf(stderr,
737  "-E- %s, %d: failure to allocate band_dark storage\n",
738  __FILE__, __LINE__);
739  return 1;
740  }
741  if ((rad_fact = (float *) malloc(ngran * 2 * sizeof (float))) == NULL) {
742  fprintf(stderr,
743  "-E- %s, %d: failure to allocate rad_fact storage\n",
744  __FILE__, __LINE__);
745  return 1;
746  }
747  } else {
748  if (dgran != ngran) {
749  fprintf(stderr,
750  "-E- %s, %d: Mismatch in AggregateNumberOfGranules\n",
751  __FILE__, __LINE__);
752  fprintf(stderr, "band %d\n, name: %s\n", ibnd, vfnames[ibnd]);
753  return 1;
754  }
755  }
756  iscan = 0;
757  /*
758  * Get the # scans from the granule area for all granules
759  */
760  nscan_inst_tot = 0;
761  for (igran = 0; igran < ngran; igran++) {
762  sprintf(g_path, "Data_Products/VIIRS-M%d-SDR/VIIRS-M%d-SDR_Gran_%d",
763  jbnd, jbnd, igran);
764  if (h5io_set_ds((sdr_fid + ibnd), g_path, &g_id) != 0) {
765  fprintf(stderr,
766  "-E- %s Line %d: Failure to set granule dataset, ds %d:\n",
767  __FILE__, __LINE__, ibnd);
768  fprintf(stderr, "name: %s", vfnames[ibnd]);
769  return 1;
770  }
771 
772  if (h5io_rd_attr(&g_id, "N_Number_Of_Scans",
773  (void *) (nscan_inst + igran)) != 0) {
774  fprintf(stderr,
775  "-E- %s Line %d: Unable to read the N_Number_Of_Scans ds attr, ds %d:\n",
776  __FILE__, __LINE__, ibnd);
777  fprintf(stderr, "name: %s", vfnames[ibnd]);
778  return 1;
779  }
780  if (nscan_inst[igran] <= 0) {
781  fprintf(stderr,
782  "-E- %s, %d: N_Number_Of_Scans[%d]: %d invalid\n",
783  __FILE__, __LINE__, igran, nscan_inst[igran]);
784  return 1;
785  }
786  /* accumulate grand total of scans and set map info */
787  nscan_inst_tot += nscan_inst[igran];
788 
789  /* With the # scans and # granules, set up the gran_map and scan_map */
790  if ((igran == 0) && (ibnd == 0)) {
791  /* this will insure that simulated granules (with no # scan limit)
792  or std format granules ( with STDMAXSCANS at most scans)
793  will get sufficient storage allocated */
794  nscan_per_gran =
795  (nscan_inst[0] > STDMAXSCANS) ?
796  nscan_inst[0] : STDMAXSCANS;
797 
798  if ((gran_map = (int *) malloc(
799  ngran * nscan_per_gran * sizeof (int))) == NULL) {
800  fprintf(stderr,
801  "-E- %s, %d: failure to allocate gran_map storage\n",
802  __FILE__, __LINE__);
803  return 1;
804  }
805  if ((scan_map = (int *) malloc(
806  ngran * nscan_per_gran * sizeof (int))) == NULL) {
807  fprintf(stderr,
808  "-E- %s, %d: failure to allocate scan_map storage\n",
809  __FILE__, __LINE__);
810  return 1;
811  }
812  for (i = 0; i < ngran * nscan_per_gran; i++) {
813  gran_map[i] = -1;
814  scan_map[i] = -1;
815  }
816  }
817  for (i = 0; i < nscan_inst[igran]; i++) {
818  scan_map[iscan] = igran * nscan_per_gran + i;
819  gran_map[iscan++] = igran;
820  }
821  /*
822  * Get the start and end time (in IET to match scan times)
823  */
824  if (h5io_rd_attr(&g_id, "N_Beginning_Time_IET", (void *) &u58_gran)
825  != 0) {
826  fprintf(stderr,
827  "-E- %s Line %d: Unable to read the N_Beginning_Time_IET ds attr, ds %d:\n",
828  __FILE__, __LINE__, ibnd);
829  fprintf(stderr, "name: %s", vfnames[ibnd]);
830  return 1;
831  }
832  if (igran == 0)
833  u58_gran_st = u58_gran;
834  else if ((u58_gran > 0) && (u58_gran < u58_gran_st))
835  u58_gran_st = u58_gran;
836 
837  if (h5io_rd_attr(&g_id, "N_Ending_Time_IET", (void *) &u58_gran)
838  != 0) {
839  fprintf(stderr,
840  "-E- %s Line %d: Unable to read the N_Ending_Time_IET ds attr, ds %d:\n",
841  __FILE__, __LINE__, ibnd);
842  fprintf(stderr, "name: %s", vfnames[ibnd]);
843  return 1;
844  }
845  if (igran == 0)
846  u58_gran_en = u58_gran;
847  else if (u58_gran > u58_gran_en)
848  u58_gran_en = u58_gran;
849  /*
850  * we need one of the 'GranX' datasets open to set up the
851  * calibration (calfile=<name>)
852  *
853  * NOTE that a granule-specific or line-by-line cal may get switched
854  * to if needed - this makes cal based on just start time
855  */
856  if ((ibnd == 0) && (igran == ngran - 1))
857  if (set_f_cal_corr(&g_id, file, u58_gran_st) != 0)
858  return 1;
859 
860  if (h5io_close(&g_id) != 0) {
861  fprintf(stderr,
862  "-E- %s Line %d: Unable to close granule, ds %d\n",
863  __FILE__, __LINE__, ibnd);
864  return 1;
865  }
866  }
867 
868  /* Get the nscan_stat = NumberOfScans (from the All Data area) each time */
869  sprintf(g_path, "All_Data/VIIRS-M%d-SDR_All/NumberOfScans", jbnd);
870  if (h5io_grab_ds((sdr_fid + ibnd), g_path, (void *) nscan_stat) != 0) {
871  fprintf(stderr,
872  "-E- %s, %d: Unable to read the # scans from NumberOfScans, band %d\n",
873  __FILE__, __LINE__, ibnd);
874  return 1;
875  }
876  for (igran = 0; igran < ngran; igran++) {
877  /* note the dark bands */
878  if (nscan_stat[igran] == -993) {
879  *(band_dark + ibnd + MAXBANDS * igran) = 1;
880  } else {
881  if (nscan_stat[igran] != nscan_inst[igran]) {
882  fprintf(stderr,
883  "-E- %s, %d: dataset #scans: %d not = to granule # scans: %d \n",
884  __FILE__, __LINE__, nscan_stat[igran],
885  nscan_inst[igran]);
886  fprintf(stderr, "band: %d, granule: %d\n", ibnd, igran);
887  return 1;
888  }
889  }
890  }
891  /*
892  * for the first band, get the count of scans in the actual
893  * datasets (we'll get that from the 'Radiance' dataset).
894  * This is informational only (the operational VIIRS SDRs
895  * have 48 scans of data space even if the # scans in the
896  * attributes is 47 - care must be taken due to this choice)
897  *
898  * Also, set up storage for the quality 2
899  */
900  if (ibnd == 0) {
901  sprintf(g_path, "All_Data/VIIRS-M%d-SDR_All/Radiance", jbnd);
902  if (h5io_set_ds((sdr_fid + ibnd), g_path, &g_id) != 0) {
903  fprintf(stderr,
904  "-E- %s Line %d: Getting nscan_sto, Unable to open path\n",
905  __FILE__, __LINE__);
906  return 1;
907  }
908  if (h5io_info(&g_id, NULL, &h5_class, &h5_native_typ, &ndim,
909  dim_siz, &sto_len) != 0) {
910  fprintf(stderr,
911  "-E- %s Line %d: Getting nscan_sto, Unable to read dataset\n",
912  __FILE__, __LINE__);
913  return 1;
914  }
915  nscan_sto = dim_siz[0] / NDET;
916  if (h5io_close(&g_id) != 0) {
917  fprintf(stderr,
918  "-E- %s Line %d: Getting nscan_sto, Unable to close path\n",
919  __FILE__, __LINE__);
920  return 1;
921  }
922  if (want_verbose)
923  printf("%s: total # inst scans: %d, dataset scans: %d\n",
924  __FILE__, nscan_inst_tot, nscan_sto);
925  if (nscan_sto < nscan_inst_tot) {
926  fprintf(stderr, "-E- %s,%d: # aggregate scans < inst scans\n",
927  __FILE__, __LINE__);
928  }
929  /*
930  */
931  if ((viirs_qual2 = malloc(nscan_sto * sizeof (unsigned char)))
932  == NULL) {
933  fprintf(stderr,
934  "-E- %s Line %d: mem allocation error for viirs_qual2\n",
935  __FILE__, __LINE__);
936  return 1;
937  }
938  if ((cmp_vq2 = malloc(nscan_sto * sizeof (unsigned char))) == NULL) {
939  fprintf(stderr,
940  "-E- %s Line %d: mem allocation error for cmp_vq2\n",
941  __FILE__, __LINE__);
942  return 1;
943  }
944  }
945  /*
946  * get the quality 2 data
947  */
948  sprintf(g_path, "All_Data/VIIRS-M%d-SDR_All/QF2_SCAN_SDR", jbnd);
949  if (h5io_grab_ds((sdr_fid + ibnd), g_path, (void *) cmp_vq2) != 0) {
950  fprintf(stderr,
951  "-E- %s, %d: Unable to get QF2 for path %s, band %d\n",
952  __FILE__, __LINE__, g_path, ibnd);
953  return 1;
954  }
955  /*
956  * check # scan, ... consistency between datastes
957  */
958  if (ibnd == 0)
959  nscan = nscan_inst_tot;
960  else {
961  if (nscan_inst_tot != nscan) {
962  fprintf(stderr,
963  "-E- %s, %d: # inst scans: %d in band file: %s",
964  __FILE__, __LINE__, nscan_inst_tot, vfnames[ibnd]);
965  fprintf(stderr,
966  "is not the same as initially established (scans: %d)\n",
967  nscan);
968  return 1;
969  }
970  }
971  /*
972  * collect the quality 2 and check it for the non-dark bands
973  * and report if there is a lunar incursion
974  */
975  dk = 0;
976  for (i = 0; i < ngran; i++) {
977  if (*(band_dark + ibnd + MAXBANDS * i) == 1) {
978  dk = 1;
979  break;
980  }
981  }
982  if (dk == 0) {
983  if (qual2_found == 0) {
984  memcpy(viirs_qual2, cmp_vq2, nscan_sto);
985  qual2_found = 1;
986  for (i = 0; i < nscan_inst_tot; i++) {
987  if ((*(viirs_qual2 + scan_map[i]) & 2) != 0) {
988  file->sv_with_moon = 1;
989  printf("VIIRS_SV_LUNAR_INCURSION detected\n");
990  break;
991  }
992  }
993  } else {
994  /* check the quality 2 for consistency */
995  for (i = 0; i < nscan_inst_tot; i++) {
996  if (*(viirs_qual2 + scan_map[i])
997  != *(cmp_vq2 + scan_map[i])) {
998  fprintf(stderr,
999  "-E- %s Line %d: QF2_SCAN_SDR mismatch, val# %d, bnd %d\n",
1000  __FILE__, __LINE__, i, ibnd);
1001  return 1;
1002  }
1003  }
1004  }
1005  }
1006  /*
1007  * for non-aggregated files, see if extra info is there, and record
1008  * unaggregated file info
1009  */
1010  if ((attr_exist = h5io_attr_exist((sdr_fid + ibnd), "Data Scan Format"))
1011  == -1) {
1012  fprintf(stderr,
1013  "-E- %s Line %d: failure while checking for attr Data Scan Format, band: %d\n",
1014  __FILE__, __LINE__, ibnd);
1015  return 1;
1016  } else {
1017  if (attr_exist == 1) {
1018  /* a std aggregated file, no extra attributes */
1019  ua_npix = NAGGPX;
1020  ua_scn_fmt = 0;
1021  ua_nlin = nscan * NDET;
1022  ua_ndets = NDET;
1023  ua_margin[0] = 0;
1024  ua_margin[1] = 0;
1025  } else {
1026  /* read the unaggregated information */
1027  if (h5io_rd_attr((sdr_fid + ibnd), "Data Scan Format",
1028  (void *) &ua_scn_fmt) != 0) {
1029  fprintf(stderr,
1030  "-E- %s Line %d: Unable to read the Data Scan Format attr, ds %d: name: %s\n",
1031  __FILE__, __LINE__, ibnd, vfnames[ibnd]);
1032  return 1;
1033  }
1034  if (h5io_rd_attr((sdr_fid + ibnd), "Scan Margin (track, scan)",
1035  (void *) ua_margin) != 0) {
1036  fprintf(stderr,
1037  "-E- %s Line %d: Unable to read the Scan Margin attr, ds %d: name: %s\n",
1038  __FILE__, __LINE__, ibnd, vfnames[ibnd]);
1039  return 1;
1040  }
1041  if (h5io_rd_attr((sdr_fid + ibnd), "Pixels per Scan Line",
1042  (void *) &ua_npix) != 0) {
1043  fprintf(stderr,
1044  "-E- %s Line %d: Unable to read the Pixels per Scan Line attr, ds %d: name: %s\n",
1045  __FILE__, __LINE__, ibnd, vfnames[ibnd]);
1046  return 1;
1047  }
1048  if (h5io_rd_attr((sdr_fid + ibnd), "Number of Scan Lines",
1049  (void *) &ua_nlin) != 0) {
1050  fprintf(stderr,
1051  "-E- %s Line %d: Unable to read the Number of Scan Lines attr, ds %d: name: %s\n",
1052  __FILE__, __LINE__, ibnd, vfnames[ibnd]);
1053  return 1;
1054  }
1055  if (h5io_rd_attr((sdr_fid + ibnd),
1056  "Number of Detectors per Scan", (void *) &ua_ndets)
1057  != 0) {
1058  fprintf(stderr,
1059  "-E- %s Line %d: Unable to read the Number of Detectors per Scan attr, ds %d: name: %s\n",
1060  __FILE__, __LINE__, ibnd, vfnames[ibnd]);
1061  return 1;
1062  }
1063  }
1064  }
1065  /*
1066  * check unaggregated file info between files
1067  */
1068  if (ibnd == 0) {
1069  margin[0] = ua_margin[0];
1070  margin[1] = ua_margin[1];
1071  file->npix = ua_npix;
1072  npix = ua_npix;
1073  file->ndets = ua_ndets;
1074  file->nscan = ua_nlin;
1075  scn_fmt = ua_scn_fmt;
1076  file->sd_id = 0; /* this appears to not be needed */
1077  } else {
1078  if ((margin[0] != ua_margin[0]) || (margin[1] != ua_margin[1])) {
1079  fprintf(stderr,
1080  "-E- %s Line %d: margin mismatch on band: %d name: %s\n",
1081  __FILE__, __LINE__, ibnd, vfnames[ibnd]);
1082  return 1;
1083  }
1084  if (file->npix != ua_npix) {
1085  fprintf(stderr,
1086  "-E- %s Line %d: ua npix mismatch on band: %d name: %s\n",
1087  __FILE__, __LINE__, ibnd, vfnames[ibnd]);
1088  return 1;
1089  }
1090  if (file->ndets != ua_ndets) {
1091  fprintf(stderr,
1092  "-E- %s Line %d: ua ndets mismatch on band: %d name: %s\n",
1093  __FILE__, __LINE__, ibnd, vfnames[ibnd]);
1094  return 1;
1095  }
1096  if (file->nscan != nscan * ua_ndets) {
1097  fprintf(stderr,
1098  "-E- %s Line %d: ua # lines mismatch on band: %d name: %s\n",
1099  __FILE__, __LINE__, ibnd, vfnames[ibnd]);
1100  return 1;
1101  }
1102  if (scn_fmt != ua_scn_fmt) {
1103  fprintf(stderr,
1104  "-E- %s Line %d: ua scan format mismatch on band: %d name: %s\n",
1105  __FILE__, __LINE__, ibnd, vfnames[ibnd]);
1106  return 1;
1107  }
1108  }
1109 
1110  /* set up the datasets to read from this file, a line at a time */
1111  /* The RadianceFactors have been moved out of this, so for now, only
1112  1 dataset is set up this way, but in the future, this method may
1113  be of use so keep it */
1114  for (ids = 0; ids < 1; ids++) {
1115  if (btype[ibnd] == VSWIR || btype[ibnd] == CIRRUS)
1116  sprintf(g_path, "All_Data/VIIRS-M%d-SDR_All/%s", jbnd,
1117  "Reflectance");
1118  else
1119  sprintf(g_path, "All_Data/VIIRS-M%d-SDR_All/%s", jbnd,
1120  "Radiance");
1121 
1122  if (h5io_set_ds((sdr_fid + ibnd), g_path, &(bnd_dat_id[ids][ibnd]))
1123  != 0) {
1124  fprintf(stderr,
1125  "-E- %s Line %d: Error setting dataset, band %d, ds %d\n",
1126  __FILE__, __LINE__, ibnd, ids);
1127  return 1;
1128  }
1129  /*
1130  * for the radiance, determine if it is scaled by finding data class
1131  */
1132  if (ids == 0) {
1133  if (h5io_info(&(bnd_dat_id[ids][ibnd]), NULL, &h5_class,
1134  &h5_native_typ, &ndim, dim_siz, &sto_len) != 0) {
1135  fprintf(stderr,
1136  "-E- %s Line %d: Error accessing radiance dataset info, band %d\n",
1137  __FILE__, __LINE__, ibnd);
1138  return 1;
1139  }
1140  if (h5_class == H5T_INTEGER)
1141  *(sdr_band_typ + ibnd) = 0;
1142  else
1143  *(sdr_band_typ + ibnd) = 1;
1144  }
1145  }
1146  /*
1147  * set scale and offset for band rads here, 0 if unscaled
1148  */
1149  if (*(sdr_band_typ + ibnd) == 0) {
1150  if (btype[ibnd] == VSWIR || btype[ibnd] == CIRRUS)
1151  sprintf(g_path, "All_Data/VIIRS-M%d-SDR_All/ReflectanceFactors",
1152  jbnd);
1153  else
1154  sprintf(g_path, "All_Data/VIIRS-M%d-SDR_All/RadianceFactors",
1155  jbnd);
1156 
1157  if (h5io_grab_ds((sdr_fid + ibnd), g_path, (void *) rad_fact)
1158  != 0) {
1159  fprintf(stderr,
1160  "-E- %s Line %d: Unable to read the rad fact, ds %d\n",
1161  __FILE__, __LINE__, ibnd);
1162  return 1;
1163  }
1164  for (igran = 0; igran < ngran; igran++) {
1165  *(scale + ibnd + MAXBANDS * igran) = rad_fact[igran * 2];
1166  *(offset + ibnd + MAXBANDS * igran) = rad_fact[1 + igran * 2];
1167  }
1168  } else {
1169  for (igran = 0; igran < ngran; igran++) {
1170  *(scale + ibnd + MAXBANDS * igran) = 1.;
1171  *(offset + ibnd + MAXBANDS * igran) = 0.;
1172  }
1173  }
1174  } /***** end of band-specific initial set-up *****/
1175  free(cmp_vq2);
1176  /*
1177  * quality 2 needs to be collected to get the mirror sides.
1178  * if not collected, there is trouble
1179  */
1180  if (qual2_found == 0) {
1181  fprintf(stderr,
1182  "-E- %s Line %d: All M bands contain no data (NumberOfScans undefined for all bands)\n",
1183  __FILE__, __LINE__);
1184  return 1;
1185  }
1186 
1187  /* Open the geolocation file */
1188  if (h5io_openr(file->geofile, 0, &geo_fid) != 0) {
1189  fprintf(stderr,
1190  "-E- %s Line %d: Unable to open the geolocation file: %s\n",
1191  __FILE__, __LINE__, file->geofile);
1192  return 1;
1193  }
1194  /*
1195  * Determine if this is a terrain-corrected or uncorrected geolocation
1196  * VIIRS-MOD-GEO - un-corrected, VIIRS-MOD-GEO-TC - corrected
1197  */
1198  if (h5io_set_grp(&geo_fid, "Data_Products", &id_tmp) != 0) {
1199  fprintf(stderr,
1200  "-E- %s, %d: Failure to set geolocation Data_Products group\n",
1201  __FILE__, __LINE__);
1202  fprintf(stderr, "name: %s\n", file->geofile);
1203  return 1;
1204  }
1205  if (h5io_grp_contents(&id_tmp, &n_obj, &grp_obj_nm, &grp_obj_typ) != 0) {
1206  fprintf(stderr,
1207  "-E- %s Line %d: failed to get group Data_Products contents\n",
1208  __FILE__, __LINE__);
1209  return 1;
1210  }
1211  if (strcmp(grp_obj_nm[0], "VIIRS-MOD-GEO-TC") == 0) {
1212  terr_corr = 1;
1213  if (want_verbose)
1214  fprintf(stderr, "-I- %s , %d: Geolocation is Terrain Corrected\n",
1215  __FILE__, __LINE__);
1216  } else if (strcmp(grp_obj_nm[0], "VIIRS-MOD-GEO") == 0) {
1217  terr_corr = 0;
1218  if (want_verbose)
1219  fprintf(stderr, "-I- %s , %d: Geolocation is NOT Terrain Corrected\n",
1220  __FILE__, __LINE__);
1221  } else {
1222  fprintf(stderr, "-E- %s, %d: Geo Data_Products has unknown sub-group\n",
1223  __FILE__, __LINE__);
1224  fprintf(stderr, "= %s\n", grp_obj_nm[0]);
1225  return 1;
1226  }
1227  if (h5io_close(&id_tmp) != 0) {
1228  fprintf(stderr, "-E- %s, %d: failed to close group Data_Products\n",
1229  __FILE__, __LINE__);
1230  return 1;
1231  }
1232  file->terrain_corrected = terr_corr;
1233  /*
1234  * Check geolocation file # granules to match the band files
1235  */
1236  if (terr_corr == 1)
1237  sprintf(g_path, "Data_Products/VIIRS-MOD-GEO-TC/VIIRS-MOD-GEO-TC_Aggr");
1238  else
1239  sprintf(g_path, "Data_Products/VIIRS-MOD-GEO/VIIRS-MOD-GEO_Aggr");
1240 
1241  if (h5io_set_ds(&geo_fid, g_path, &g_id) != 0) {
1242  fprintf(stderr,
1243  "-E- %s, %d: Failure to set geolocation aggregation dataset\n",
1244  __FILE__, __LINE__);
1245  fprintf(stderr, "name: %s\n", file->geofile);
1246  return 1;
1247  }
1248  if (h5ReadAttrInt32(&g_id, "AggregateNumberGranules", (void *) &dgran) != 0) {
1249  fprintf(stderr,
1250  "-E- %s, %d: Unable to read the AggregateNumberGranules attribute\n",
1251  __FILE__, __LINE__);
1252  fprintf(stderr, "name: %s\n", file->geofile);
1253  return 1;
1254  }
1255  if (h5io_close(&g_id) != 0) {
1256  fprintf(stderr, "-E- %s, %d: Unable to close geofile granule\n",
1257  __FILE__, __LINE__);
1258  return 1;
1259  }
1260 
1261  if (dgran != ngran) {
1262  fprintf(stderr,
1263  "-E- %s, %d: Mismatch found in # granules in geofile vs band files\n",
1264  __FILE__, __LINE__);
1265  fprintf(stderr, " geofile: %d, band files: %d\n", dgran, ngran);
1266  return 1;
1267  }
1268  /*
1269  * get the group name under 'All_Data' from this geo file
1270  * for a geo file, it can be either VIIRS-MOD-GEO for elipsoid nav
1271  * or VIIRS-MOD-GEO-TC for terrain corrected
1272  */
1273  if (h5io_set_grp(&geo_fid, "All_Data", &id_tmp) != 0) {
1274  fprintf(stderr, "-E- %s Line %d: Unable to open group All_Data\n",
1275  __FILE__, __LINE__);
1276  return 1;
1277  }
1278  if (h5io_grp_contents(&id_tmp, &n_obj, &grp_obj_nm, &grp_obj_typ) != 0) {
1279  fprintf(stderr,
1280  "-E- %s Line %d: failed to get group All_Data contents\n",
1281  __FILE__, __LINE__);
1282  return 1;
1283  }
1284  strcpy(geo_all_data_gnam, grp_obj_nm[0]);
1285  if (h5io_close(&id_tmp) != 0) {
1286  fprintf(stderr, "-E- %s Line %d: failed to close group All_Data\n",
1287  __FILE__, __LINE__);
1288  return 1;
1289  }
1290  /*
1291  * get the entire actual scan start times, position, velocity, and sensor
1292  * attitude for all frames
1293  * check/correct scan starts to be within gran t range (fixes anc
1294  * problem downstream)
1295  */
1296  u58_scn_st = (int64_t *) malloc(nscan_sto * sizeof (int64_t));
1297  sprintf(g_path, "All_Data/%s/StartTime", geo_all_data_gnam);
1298  if (h5io_grab_ds(&geo_fid, g_path, (void *) u58_scn_st) != 0) {
1299  fprintf(stderr, "-E- %s, %d: Unable to read the Geo StartTime\n",
1300  __FILE__, __LINE__);
1301  return 1;
1302  }
1303  for (i = 0; i < nscan_inst_tot; i++) {
1304  iscan = scan_map[i];
1305  if ((u58_scn_st[iscan] < u58_gran_st)
1306  || (u58_scn_st[iscan] > u58_gran_en)) {
1307  fprintf(stderr,
1308  "-W- %s Line %d: scan start time on scan %d was outside granule range - repaired.\n",
1309  __FILE__, __LINE__, i);
1310  u58_scn_st[iscan] = u58_gran_st
1311  + i * (u58_gran_en - u58_gran_st) / nscan_inst_tot;
1312  }
1313  }
1314 
1315  pos = (float *) malloc(nscan_sto * 3 * sizeof (float));
1316 
1317  sprintf(g_path, "All_Data/%s/SCPosition", geo_all_data_gnam);
1318  if (h5io_grab_ds(&geo_fid, g_path, (void *) pos) != 0) {
1319  fprintf(stderr, "-E- %s Line %d: Unable to read the SCPosition\n",
1320  __FILE__, __LINE__);
1321  return 1;
1322  }
1323 
1324  vel = (float *) malloc(nscan_sto * 3 * sizeof (float));
1325 
1326  sprintf(g_path, "All_Data/%s/SCVelocity", geo_all_data_gnam);
1327  if (h5io_grab_ds(&geo_fid, g_path, (void *) vel) != 0) {
1328  fprintf(stderr, "-E- %s Line %d: Unable to read the SCVelocity\n",
1329  __FILE__, __LINE__);
1330  return 1;
1331  }
1332 
1333  att = (float *) malloc(nscan_sto * 3 * sizeof (float));
1334  sprintf(g_path, "All_Data/%s/SCAttitude", geo_all_data_gnam);
1335 
1336  if (h5io_grab_ds(&geo_fid, g_path, (void *) att) != 0) {
1337  fprintf(stderr, "-E- %s Line %d: Unable to read the SCAttitude\n",
1338  __FILE__, __LINE__);
1339  return 1;
1340  }
1341  /*
1342  * set to the geolocation datasets for the lat, lon, and view angles
1343  */
1344  for (ids = 0; ids < 7; ids++) {
1345  sprintf(g_path, "All_Data/%s/%s", geo_all_data_gnam, geo_name[ids]);
1346  if (h5io_set_ds(&geo_fid, g_path, (geo_dat_id + ids)) != 0) {
1347  fprintf(stderr,
1348  "-E- %s Line %d: Unable to set ds # %d in geolocation file\n",
1349  __FILE__, __LINE__, ids);
1350  return 1;
1351  }
1352  }
1353  /*
1354  * On to set-up of any initial storage or factors that can be done
1355  */
1356  if ((scl_rad = (unsigned short *) malloc(npix * sizeof (unsigned short)))
1357  == NULL) {
1358  fprintf(stderr, "-E- %s Line %d: scl_rad allocate failed\n", __FILE__,
1359  __LINE__);
1360  return 1;
1361  }
1362 
1363  if ((flt_rad = (float *) malloc(npix * sizeof (float))) == NULL) {
1364  fprintf(stderr, "-E- %s Line %d: flt_rad allocate failed\n", __FILE__,
1365  __LINE__);
1366  return 1;
1367  }
1368  /*
1369  * get the Fobar here to set up Fo
1370  */
1371  rdsensorinfo(file->sensorID, l1_input->evalmask, "Fobar", (void **) &Fobar);
1372  /*
1373  * finally, free locally used space
1374  */
1375  free(nscan_inst);
1376  free(nscan_stat);
1377  free(band_dark);
1378  free(rad_fact);
1379 
1380  return (LIFE_IS_GOOD);
1381 }
1382 
1383 /* ------------------------------------------------------------------------
1384  readl1_viirs_h5
1385 
1386  purpose: reads 1 line (scan) from a VIIRS L1B file and load l1rec.
1387 
1388  Parameters: (in calling order)
1389  Type Name I/O Description
1390  ---- ---- --- -----------
1391  filehandle * file I input file information
1392  int32 dline I scan line to read, 0 origin
1393  l1str * l1rec I/O data for that line
1394  int lonlat I signal to read only lon and lat
1395 
1396  Modification history:
1397  Programmer Date Description of change
1398  ---------- ---- ---------------------
1399  W. Robinson, SAIC, Feb, 2009 Original development
1400  W. Robinson, SAIC, 10 sep 2012 use moon in space view to flag affected
1401  scans with nav failure
1402 
1403  ------------------------------------------------------------------------*/
1404 int readl1_viirs_h5(filehandle * file, int32_t dline, l1str * l1rec, int lonlat) {
1405  static int32_t firstcall = 1, lastframe = -1;
1406  static double fsol;
1407  int start[2], count[2];
1408  int32_t i, ibnd, ipix, moon_affected;
1409  float *iptr, pos1[3], vel1[3], att1[3], sen_mat[3][3], coeff[10], rval;
1410  short year, day;
1411  double dsec, esdist, f_corr;
1412  static double mnorm[3];
1413  static int mside;
1414 
1415  int32_t detnum, igran, dscan, ascan, aline;
1416  int32_t nbands = (int32_t) file->nbands;
1417 
1418  l1rec->npix = file->npix;
1419  // if (firstcall)
1420  // cdata_();
1421  /*
1422  * get proper line in data and detector #
1423  */
1424  dscan = dline / file->ndets;
1425  detnum = (dline % (NDET + 2 * margin[0])) - margin[0];
1426  ascan = scan_map[dscan]; /* scan and line in the datasets */
1427  aline = ascan * (NDET + 2 * margin[0]) + detnum;
1428  igran = gran_map[dscan];
1429  /*
1430  * load scan start time
1431  */
1432  if (detnum < 0) /* can't have a detector outside instrument's existing ones */
1433  detnum = 0;
1434  if (detnum > NDET - 1)
1435  detnum = NDET - 1;
1436  double tai58 = u58_scn_st[ascan] / 1000000.0;
1437  l1rec->scantime = tai58_to_unix(tai58);
1438  unix2yds(l1rec->scantime, &year, &day, &dsec);
1439 
1440  /*
1441  * get the location and view information from the geo file
1442  */
1443  for (ibnd = 0; ibnd < 7; ibnd++) {
1444 
1445  // when lonlat is on and ibnd is not 0, 1 and 5, skip the iteration
1446  // lonlat mode only needs lon, lat and solar zenith
1447  if (lonlat && (ibnd != 0) && (ibnd != 1) && (ibnd != 5))
1448  continue;
1449 
1450  switch (ibnd) {
1451  case 0:
1452  iptr = l1rec->lat;
1453  break;
1454  case 1:
1455  iptr = l1rec->lon;
1456  break;
1457  case 2:
1458  iptr = l1rec->sena;
1459  break;
1460  case 3:
1461  iptr = l1rec->senz;
1462  break;
1463  case 4:
1464  iptr = l1rec->sola;
1465  break;
1466  case 5:
1467  iptr = l1rec->solz;
1468  break;
1469  case 6:
1470  iptr = l1rec->height;
1471  break;
1472  }
1473 
1474  count[0] = 1;
1475  count[1] = l1rec->npix;
1476  start[0] = aline;
1477  start[1] = 0;
1478  if (h5io_rd_ds_slice(&(geo_dat_id[ibnd]), start, count, (void *) iptr)
1479  != 0) {
1480  fprintf(stderr,
1481  "-E- %s, %d: Failed read to geo line %d of band %d\n",
1482  __FILE__, __LINE__, aline, ibnd);
1483  return 1;
1484  }
1485  }
1486 
1487  // stop if lonlat only
1488  if (lonlat)
1489  return LIFE_IS_GOOD;
1490 
1491  if (ascan != lastframe) {
1492  /*
1493  * Get mirror side (0=A,1=B) from the low bit of the QF2_SCAN_SDR file
1494  */
1495  mside = ((*(viirs_qual2 + ascan) & 1) == 1) ? 1 : 0;
1496  /*
1497  * convert the (pos, vel, att) from (m, m/s, arcsec) to (km, km/s, deg)
1498  * and compute the sensor attitude in ECF
1499  */
1500  for (i = 0; i < 3; i++) {
1501  pos1[i] = *(pos + i + ascan * 3) / 1000.;
1502  vel1[i] = *(vel + i + ascan * 3) / 1000.;
1503  att1[i] = *(att + i + ascan * 3) / 3600.;
1504  }
1505  ocorient_(pos1, vel1, att1, sen_mat, coeff);
1506  /*
1507  * extract the 'mirror normal' - WDR reverse sen_mat ixdexes used
1508  */
1509  for (i = 0; i < 3; i++)
1510  mnorm[i] = sen_mat[i][0];
1511 
1512  lastframe = ascan;
1513  }
1514  l1rec->mside = (int32_t) mside;
1515 
1516  /* get earth-sun distance correction for this frame */
1517  int32_t msec32 = (int32_t) (dsec * 1.e3);
1518  int32_t yr = (int32_t) year;
1519  int32_t dy = (int32_t) day;
1520 
1521  esdist = esdist_(&yr, &dy, &msec32);
1522  fsol = pow(1.0 / esdist, 2);
1523 
1524  /* Compute polarization frame rotation angles */
1525  compute_alpha(l1rec->lon, l1rec->lat, l1rec->senz, l1rec->sena, mnorm,
1526  l1rec->npix, l1rec->alpha);
1527 
1528  for (ipix = 0; ipix < l1rec->npix; ipix++)
1529  *(l1rec->pixnum + ipix) = ipix;
1530  /*
1531  * it is possible that some flags can be set using the quality
1532  * info in the files (maybe) may be able to add this later
1533  * hilt, navfail done in modis io
1534  */
1535  /*
1536  * get the radiance information from band files and un-scale it if necessary
1537  * check values against the fill values for VIIRS
1538  * also make into Mw / cm^2 sr sec from W / m^2...
1539  *
1540  * The refl bands go to nbands, after that, the IR get stored in Ltir
1541  */
1542  count[0] = 1;
1543  count[1] = l1rec->npix;
1544  start[1] = 0;
1545  ivswir = 0;
1546  itherm = 0;
1547  for (ibnd = 0; ibnd < MAXBANDS; ibnd++) {
1548  start[0] = aline;
1549 
1550  if (btype[ibnd] == VSWIR)
1551  l1rec->Fo[ivswir] = Fobar[ivswir] * fsol;
1552  /* find if the line is moon affected */
1553  moon_affected = ((*(viirs_qual2 + ascan) & 2) != 0) ? 1 : 0;
1554  /* get specific f table cal correction */
1555  f_corr = *(f_cal_corr + mside + N_MS * (detnum + NDET * ibnd));
1556 
1557  if (sdr_band_typ[ibnd] == 0) {
1558  /* re-scale */
1559  if (h5io_rd_ds_slice(&(bnd_dat_id[0][ibnd]), start, count,
1560  (void *) scl_rad) != 0) {
1561  fprintf(stderr,
1562  "-E- %s, %d: Failed to read line %d of band %d\n",
1563  __FILE__, __LINE__, aline, ibnd);
1564  return 1;
1565  }
1566  for (ipix = 0; ipix < l1rec->npix; ipix++) {
1567  /*
1568  * for vis bands in the dark, just set value = 0
1569  */
1570  if ((btype[ibnd] == VSWIR)
1571  && (*(l1rec->solz + ipix) > SOLZNIGHT)) {
1572  *(l1rec->Lt + nbands * ipix + ivswir) = 0.;
1573  continue;
1574  }
1575  /*
1576  * bad geo info will trigger nav fail flag
1577  */
1578  if ((*(l1rec->lat + ipix) < -90.)
1579  || (*(l1rec->lat + ipix) > 90.)
1580  || (*(l1rec->lon + ipix) < -180.)
1581  || (*(l1rec->lon + ipix) > 180.)) {
1582  if (btype[ibnd] == VSWIR) {
1583  *(l1rec->Lt + nbands * ipix + ivswir) = 0.;
1584  l1rec->navfail[ipix] = 1;
1585  } else if (btype[ibnd] == THERM)
1586  *(l1rec->Ltir + NBANDSIR * ipix + itherm) = 0.;
1587  else if (btype[ibnd] == CIRRUS)
1588  l1rec->rho_cirrus[ipix] = BAD_FLT;
1589  continue;
1590  }
1591  /*
1592  * moon in space view will set the nav warn flag
1593  */
1594  if (moon_affected == 1)
1595  l1rec->navwarn[ipix] = 1;
1596 
1597  /*
1598  * check data flag values
1599  */
1600  switch (*(scl_rad + ipix)) {
1601  case SOUB_UINT16_FILL:
1602  if (btype[ibnd] == VSWIR) {
1603  *(l1rec->Lt + nbands * ipix + ivswir) = 1000.;
1604  l1rec->hilt[ipix] = 1;
1605  } else if (btype[ibnd] == THERM) {
1606  *(l1rec->Ltir + NBANDSIR * ipix + itherm) = 0.;
1607  } else if (btype[ibnd] == CIRRUS) {
1608  l1rec->rho_cirrus[ipix] = BAD_FLT;
1609  }
1610  break;
1611  case NA_UINT16_FILL:
1612  case MISS_UINT16_FILL:
1615  case ERR_UINT16_FILL:
1616  case VDNE_UINT16_FILL:
1617  if (btype[ibnd] == VSWIR) {
1618  *(l1rec->Lt + nbands * ipix + ivswir) = BAD_FLT;
1619  } else if (btype[ibnd] == THERM) {
1620  *(l1rec->Ltir + NBANDSIR * ipix + itherm) = 0.;
1621  } else if (btype[ibnd] == CIRRUS) {
1622  l1rec->rho_cirrus[ipix] = BAD_FLT;
1623  }
1624  break;
1625  case ELINT_UINT16_FILL:
1626  if (btype[ibnd] == VSWIR) {
1627  *(l1rec->Lt + nbands * ipix + ivswir) = 0.;
1628  l1rec->navfail[ipix] = 1;
1629  } else if (btype[ibnd] == THERM)
1630  *(l1rec->Ltir + NBANDSIR * ipix + itherm) = 0.;
1631  else if (btype[ibnd] == CIRRUS)
1632  l1rec->rho_cirrus[ipix] = BAD_FLT;
1633  break;
1634  default:
1635  if (btype[ibnd] == VSWIR)
1636  *(l1rec->Lt + nbands * ipix + ivswir) = (*(scl_rad
1637  + ipix) * *(scale + ibnd + MAXBANDS * igran)
1638  + *(offset + ibnd + MAXBANDS * igran))
1639  * l1rec->Fo[ivswir] * f_corr
1640  * cos(l1rec->solz[ipix] / RADEG) / PI;
1641  else if (btype[ibnd] == THERM)
1642  *(l1rec->Ltir + NBANDSIR * ipix + itherm) = 0.1
1643  * (*(scl_rad + ipix)
1644  * *(scale + ibnd + MAXBANDS * igran)
1645  + *(offset + ibnd + MAXBANDS * igran))
1646  * f_corr;
1647  else if (btype[ibnd] == CIRRUS)
1648  l1rec->rho_cirrus[ipix] = (*(scl_rad + ipix)
1649  * *(scale + ibnd + MAXBANDS * igran)
1650  + *(offset + ibnd + MAXBANDS * igran)) * f_corr;
1651  break;
1652  }
1653  }
1654  } else /* SDR band data in float form */ {
1655  if (h5io_rd_ds_slice(&(bnd_dat_id[0][ibnd]), start, count,
1656  (void *) flt_rad) != 0) {
1657  fprintf(stderr,
1658  "-E- %s, %d: Failed to read scan %d of band %d\n",
1659  __FILE__, __LINE__, aline, ibnd);
1660  return 1;
1661  }
1662  for (ipix = 0; ipix < l1rec->npix; ipix++) {
1663  if ((btype[ibnd] == VSWIR)
1664  && (*(l1rec->solz + ipix) > SOLZNIGHT)) {
1665  *(l1rec->Lt + nbands * ipix + ivswir) = 0.;
1666  continue;
1667  }
1668  /*
1669  * bad geo info will trigger nav fail flag
1670  */
1671  if ((*(l1rec->lat + ipix) < -90.)
1672  || (*(l1rec->lat + ipix) > 90.)
1673  || (*(l1rec->lon + ipix) < -180.)
1674  || (*(l1rec->lon + ipix) > 180.)) {
1675  if (btype[ibnd] == VSWIR) {
1676  *(l1rec->Lt + nbands * ipix + ivswir) = 0.;
1677  l1rec->navfail[ipix] = 1;
1678  } else if (btype[ibnd] == THERM)
1679  *(l1rec->Ltir + NBANDSIR * ipix + itherm) = 0.;
1680  else if (btype[ibnd] == CIRRUS)
1681  l1rec->rho_cirrus[ipix] = BAD_FLT;
1682  continue;
1683  }
1684  /*
1685  * moon in space view will set the nav warn flag
1686  */
1687  if (moon_affected == 1)
1688  l1rec->navwarn[ipix] = 1;
1689 
1690  rval = *(flt_rad + ipix);
1691  if (near(rval, SOUB_FLOAT32_FILL)) {
1692  if (btype[ibnd] == VSWIR) {
1693  *(l1rec->Lt + nbands * ipix + ivswir) = 1000.;
1694  l1rec->hilt[ipix] = 1;
1695  } else if (btype[ibnd] == THERM) {
1696  *(l1rec->Ltir + NBANDSIR * ipix + itherm) = 0.;
1697  } else if (btype[ibnd] == CIRRUS) {
1698  l1rec->rho_cirrus[ipix] = BAD_FLT;
1699  }
1700  } else if (near(rval, (float)NA_FLOAT32_FILL)
1701  || near(rval, MISS_FLOAT32_FILL)
1702  || near(rval, ONBOARD_PT_FLOAT32_FILL)
1703  || near(rval, ONGROUND_PT_FLOAT32_FILL)
1704  || near(rval, ERR_FLOAT32_FILL)
1705  || near(rval, VDNE_FLOAT32_FILL)) {
1706  if (btype[ibnd] == VSWIR) {
1707  *(l1rec->Lt + nbands * ipix + ivswir) = BAD_FLT;
1708  } else if (btype[ibnd] == THERM) {
1709  *(l1rec->Ltir + NBANDSIR * ipix + itherm) = 0.;
1710  } else if (btype[ibnd] == CIRRUS) {
1711  l1rec->rho_cirrus[ipix] = BAD_FLT;
1712  }
1713  } else if (near(rval, ELINT_FLOAT32_FILL)) {
1714  if (btype[ibnd] == VSWIR) {
1715  *(l1rec->Lt + nbands * ipix + ivswir) = 0.;
1716  l1rec->navfail[ipix] = 1;
1717  } else if (btype[ibnd] == THERM)
1718  *(l1rec->Ltir + NBANDSIR * ipix + itherm) = 0.;
1719  else if (btype[ibnd] == CIRRUS)
1720  l1rec->rho_cirrus[ipix] = BAD_FLT;
1721  } else if (btype[ibnd] == VSWIR)
1722  *(l1rec->Lt + nbands * ipix + ivswir) = rval * f_corr
1723  * l1rec->Fo[ivswir]
1724  * cos(l1rec->solz[ipix] / RADEG) / PI;
1725  else if (btype[ibnd] == THERM)
1726  *(l1rec->Ltir + NBANDSIR * ipix + itherm) = 0.1 * rval
1727  * f_corr;
1728  else if (btype[ibnd] == CIRRUS)
1729  l1rec->rho_cirrus[ipix] = rval * f_corr;
1730  }
1731  }
1732  switch (btype[ibnd]) {
1733  case VSWIR:
1734  ivswir++;
1735  break;
1736  case THERM:
1737  itherm++;
1738  break;
1739  }
1740  }
1741  l1rec->detnum = (int32_t) detnum;
1742  l1rec->margin_s = margin[1];
1743  l1rec->scn_fmt = scn_fmt;
1744 
1745  /* Convert IR bands to brightness temperature */
1746  radiance2bt(l1rec, 1000);
1747  // flag bowtie deleted pixels
1748  for (ipix = 0; ipix < l1rec->npix; ipix++)
1749  flag_bowtie_deleted(l1rec, ipix, 0);
1750 
1751  return (LIFE_IS_GOOD);
1752 }
1753 
1754 int closel1_viirs_h5(filehandle * file)
1755 /* ------------------------------------------------------------------------
1756  close1_viirs_h5
1757 
1758  purpose: Close all the ids for the band and geolocation file(s)
1759 
1760  Parameters: (in calling order)
1761  Type Name I/O Description
1762  ---- ---- --- -----------
1763  filehandle * file I input file information
1764 
1765  Modification history:
1766  Programmer Date Description of change
1767  ---------- ---- ---------------------
1768  W. Robinson, SAIC, 11 Feb, 2009 Original development
1769 
1770  ------------------------------------------------------------------------*/ {
1771  int ict;
1772  /*
1773  * first close the band dataset ids and file ids
1774  * (may need extra loop for mult datasets in each band)
1775  */
1776  for (ict = 0; ict < MAXBANDS; ict++) {
1777  if (h5io_close(&(bnd_dat_id[0][ict])) != 0) {
1778  fprintf(stderr,
1779  "-E- %s Line %d: Failed to close band data id #%d\n",
1780  __FILE__, __LINE__, ict);
1781  return 1;
1782  }
1783 
1784  if (h5io_close(&(sdr_fid[ict])) != 0) {
1785  fprintf(stderr, "-E- %s Line %d: Failed to close band file %s\n",
1786  __FILE__, __LINE__, vfnames[ict]);
1787  return 1;
1788  }
1789  }
1790  /*
1791  * close the geolocation data ids and file id
1792  */
1793  for (ict = 0; ict < 7; ict++) {
1794  if (h5io_close(&(geo_dat_id[ict])) != 0) {
1795  fprintf(stderr,
1796  "-E- %s Line %d: Failed to close geo data id #%d\n",
1797  __FILE__, __LINE__, ict);
1798  return 1;
1799  }
1800  }
1801 
1802  if (h5io_close(&geo_fid) != 0) {
1803  fprintf(stderr, "-E- %s Line %d: Failed to close geo data file %s\n",
1804  __FILE__, __LINE__, file->geofile);
1805  return 1;
1806  }
1807  /*
1808  * Free allocated space for the work and exit
1809  */
1810  free(u58_scn_st);
1811  free(scl_rad);
1812  free(flt_rad);
1813  free(pos);
1814  free(vel);
1815  free(att);
1816  free(scale);
1817  free(offset);
1818  free(gran_map);
1819  free(scan_map);
1820 
1821  return (LIFE_IS_GOOD);
1822 }
int j
Definition: decode_rs.h:73
int32_t day
#define NA_FLOAT32_FILL
Definition: l1_viirs_h5.c:33
int h5io_openr(char *file, int opt, h5io_str *id)
Definition: h5io.c:4
int h5io_attr_exist(h5io_str *id, char *attr_name)
Definition: h5io.c:1451
double mnorm[3]
#define NBANDSIR
Definition: filehandle.h:23
#define VSWIR
Definition: l1_viirs_h5.c:80
#define NULL
Definition: decode_rs.h:63
#define SOUB_UINT16_FILL
Definition: l1_viirs_h5.c:48
#define ONBOARD_PT_FLOAT32_FILL
Definition: l1_viirs_h5.c:37
void ocorient_(float *pos, float *vel, float *att, float(*)[3], float *coef)
#define ERR_UINT16_FILL
Definition: l1_viirs_h5.c:42
read l1rec
int h5io_info(h5io_str *id, char *attr_name, H5T_class_t *class, hid_t *native_typ, int *ndim, int *dim_siz, int *sto_len)
Definition: h5io.c:173
int gen_sdr_suite(char *)
Definition: l1_viirs_h5.c:129
float32 base
Definition: maplists.h:106
int rd_vir_f_tbl(char *, int64_t, int)
Definition: l1_viirs_h5.c:416
#define NDET
Definition: l1_viirs_h5.c:25
float32 * pos
Definition: l1_czcs_hdf.c:35
double esdist_(int32_t *year, int32_t *day, int32_t *msec)
int h5io_close(h5io_str *id)
Definition: h5io.c:115
int h5ReadAttrInt32(h5io_str *id, char *attr_name, int32_t *val)
Definition: l1_viirs_h5.c:577
#define NAGGPX
Definition: l1_viirs_h5.c:27
int32 nscan
Definition: l1_czcs_hdf.c:19
#define NA_UINT16_FILL
Definition: l1_viirs_h5.c:34
#define ONBOARD_PT_UINT16_FILL
Definition: l1_viirs_h5.c:38
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
#define DENOMINATOR
Definition: l1_viirs_h5.c:29
int h5io_set_grp(h5io_str *id, char *path_name, h5io_str *grp_id)
Definition: h5io.c:369
#define NUMERATOR
Definition: l1_viirs_h5.c:28
#define LIFE_IS_GOOD
Definition: passthebuck.h:4
int h5io_set_ds(h5io_str *id, char *path_name, h5io_str *ds_id)
Definition: h5io.c:324
#define PI
Definition: l3_get_org.c:6
#define ONGROUND_PT_FLOAT32_FILL
Definition: l1_viirs_h5.c:39
#define STDMAXSCANS
Definition: l1_viirs_h5.c:24
void compute_alpha(float lon[], float lat[], float senz[], float sena[], double mnorm[3], int npix, float alpha[])
Definition: compute_alpha.c:8
#define isdigit(c)
void fix_viirs_filename(char *name)
Definition: l1_viirs_h5.c:88
#define SOUB_FLOAT32_FILL
Definition: l1_viirs_h5.c:47
int32_t mside
data_t tmp
Definition: decode_rs.h:74
subroutine lonlat(alon, alat, xlon, ylat)
Definition: lonlat.f:2
int h5io_rd_ds_slice(h5io_str *ds_id, int *start, int *count, void *data)
Definition: h5io.c:602
int h5io_rd_attr(h5io_str *id, char *attr_name, void *data)
Definition: h5io.c:412
string path
Definition: color_dtdb.py:221
#define VDNE_UINT16_FILL
Definition: l1_viirs_h5.c:46
int set_f_cal_corr(h5io_str *, filehandle *, int64_t)
Definition: l1_viirs_h5.c:239
int h5io_grp_contents(h5io_str *id, int *n_obj, char ***o_names, int **types)
Definition: h5io.c:1506
#define VDNE_FLOAT32_FILL
Definition: l1_viirs_h5.c:45
l1_input_t * l1_input
Definition: l1_options.c:9
#define THERM
Definition: l1_viirs_h5.c:81
subroutine fact
Definition: tmd.lp.f:1161
int want_verbose
float dp[MODELMAX]
void unix2yds(double usec, short *year, short *day, double *secs)
#define MAXBANDS
Definition: l1_viirs_h5.c:23
int openl1_viirs_h5(filehandle *file)
Definition: l1_viirs_h5.c:622
#define near(x, y)
Definition: l1_viirs_h5.c:30
#define H5IO_TYP_DAT_ID
Definition: h5io.h:33
#define RADEG
Definition: czcs_ctl_pt.c:5
#define basename(s)
Definition: l0chunk_modis.c:29
#define SOLZNIGHT
Definition: l1.h:58
#define ERR_FLOAT32_FILL
Definition: l1_viirs_h5.c:41
#define BAD_FLT
Definition: jplaeriallib.h:19
#define N_MS
Definition: l1_viirs_h5.c:26
int h5io_grab_ds(h5io_str *id, char *path_name, void *data)
Definition: h5io.c:1347
#define ELINT_UINT16_FILL
Definition: l1_viirs_h5.c:44
int32_t nbands
double tai58_to_unix(double tai58)
Definition: yds2tai.c:29
void radiance2bt(l1str *l1rec, int resolution)
Definition: brightness.c:170
int32_t iscan
int readl1_viirs_h5(filehandle *file, int32_t dline, l1str *l1rec, int lonlat)
Definition: l1_viirs_h5.c:1404
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
int closel1_viirs_h5(filehandle *file)
Definition: l1_viirs_h5.c:1754
#define CIRRUS
Definition: l1_viirs_h5.c:82
#define ONGROUND_PT_UINT16_FILL
Definition: l1_viirs_h5.c:40
l2prod offset
#define MISS_FLOAT32_FILL
Definition: l1_viirs_h5.c:35
int h5io_rd_ds(h5io_str *ds_id, void *data)
Definition: h5io.c:505
int i
Definition: decode_rs.h:71
#define MISS_UINT16_FILL
Definition: l1_viirs_h5.c:36
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
#define ELINT_FLOAT32_FILL
Definition: l1_viirs_h5.c:43
void flag_bowtie_deleted(l1str *l1rec, size_t ipix, int extract_offset)
Definition: l1_viirs_l1b.c:876
int npix
Definition: get_cmp.c:28
int count
Definition: decode_rs.h:79