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