OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l2qc_viirs.cpp
Go to the documentation of this file.
1 // procedure to perform quality control on a VIIRS Level-2 file
2 // includes:
3 // - metadata format check
4 // - start/end time output
5 
6 // Arguments
7 //
8 // Name Type I/O Description
9 // ---- ---- --- -----------
10 // ifile string I VIIRS packet file name
11 // cfile string I metadata configuration file (template)
12 // ofile string O quality check output file
13 
14 // Liang Hong, Dec. 8, 2017 V0.2
15 // Liang Hong, Sep. 21, 2018 V0.21
16 // Sean Bailey, Nov. 1, 2019 V0.22 - support new filename convention
17 // Liang Hong, Oct. 31, 2022 V0.33, fixed a bug in checking and displaying missing global att.
18 
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <libgen.h>
23 #include <string.h>
24 #include <string>
25 #include <regex>
26 #include <math.h>
27 #include "netcdf.h"
28 #include <stdbool.h>
29 #include "l2qc_viirs.h"
30 
31 #define VERSION "0.33"
32 
33 #define MAX_ATT_NUM 500
34 #define MAX_ATT_LEN 256
35 #define MAX_ERR_LEN 100
36 
37 using namespace std;
38 
40 
41 
42 // The main function that checks if two given strings match. The first
43 // string may contain wildcard characters
44 
45 bool match(char *first, char * second) {
46  // If we reach at the end of both strings, we are done
47  if (*first == '\0' && *second == '\0')
48  return true;
49 
50  // Make sure that the characters after '*' are present in second string.
51  // This function assumes that the first string will not contain two
52  // consecutive '*'
53  if (*first == '*' && *(first + 1) != '\0' && *second == '\0')
54  return false;
55 
56  // If the first string contains '?', or current characters of both
57  // strings match
58  if (*first == '?' || *first == *second)
59  return match(first + 1, second + 1);
60 
61  // If there is *, then there are two possibilities
62  // a) We consider current character of second string
63  // b) We ignore current character of second string.
64  if (*first == '*')
65  return match(first + 1, second) || match(first, second + 1);
66  return false;
67 }
68 
69 static void replacestr(char *line, const char *search, const char *replace) {
70  char *sp;
71 
72  if ((sp = strstr(line, search)) == NULL) {
73  return;
74  }
75  int search_len = strlen(search);
76  int replace_len = strlen(replace);
77  int tail_len = strlen(sp + search_len);
78 
79  memmove(sp + replace_len, sp + search_len, tail_len + 1);
80  memcpy(sp, replace, replace_len);
81 
82  replacestr(line, search, replace);
83 }
84 
85 int ValidBoundary(const char *strMinMax, float *datamin, float *datamax) {
86  const char *ptr;
87  char strBoundary[100];
88  int index;
89  int ch = '/';
90 
91  // find the min/max value separator "/"
92  if ((ptr = strchr(strMinMax, ch)) == NULL) {
93  return false;
94  }
95  index = ptr - strMinMax;
96 
97  // find lower boundary
98  memset(strBoundary, '\0', sizeof (strBoundary));
99  strncpy(strBoundary, strMinMax, index);
100  *datamin = atof(strBoundary);
101 
102 
103  // find upper boundary
104  memset(strBoundary, '\0', sizeof (strBoundary));
105  strcpy(strBoundary, ptr + 1);
106  *datamax = atof(strBoundary);
107 
108  return true;
109 }
110 
111 int main(int argc, char *argv[]) {
112  printf("l2qc_viirs Version: %s (%s %s)\n", VERSION, __DATE__, __TIME__);
113 
114  char *str_L2file = NULL; // VIIRS L2 file
115  char *str_rfile = NULL; // report text file
116  char *str_cfile = NULL; // configuration text file
117  int bReportFile = 0;
118  int i, j, iMetaTplt;
119  int status; /* error status */
120  int ncid; /* netCDF ID */
121  int natts; // # of attributes found in Meta data
122  int grp0id, grp1id;
123  char att_text[MAX_ATT_LEN + 1];
124  float att_float;
125  double att_double;
126  long att_long;
127  char attname[NC_MAX_NAME + 1];
128  float datamin, datamax;
129  nc_type xtypep;
130  char strTimeStamp[16] = "[l2timestring]";
131  char strTimeString0[15] = "[timestring0]Z";
132  char strL2ProdString[12] = "[L2Product]";
133  int nMissingMetaData = 0;
134  int nWrongMetaData = 0;
135  int nErr = 0;
136  int nFlagged = 0;
137  char strFlagged[1000] = "L2Flags_set=";
138  int nattsp;
139  int il2_Tplt_global_att = 0; // Template global attribute index
140  int il2_Tplt_processing_control = 0; // Template processing control index
141 
142  char *l2_Tplt_global_att_name[MAX_ATT_NUM];
143  char *l2_Tplt_global_att_val[MAX_ATT_NUM];
144  char *l2_Tplt_processing_control_g1[MAX_ATT_NUM]; // processing control group 1
145  char *l2_Tplt_processing_control_name[MAX_ATT_NUM]; // processing control attribute name
146  char *l2_Tplt_processing_control_val[MAX_ATT_NUM];
147 
148 
149  char *errstr = (char*) malloc(10000 * MAX_ERR_LEN); // string array to store errors
150  char strTplt2replace[2] = "|"; // server database won't take '|', using ',' instead
151  char strDB2accept[2] = ",";
152 
154 
156  if (argc == 1) {
158  exit(1);
159  }
160  l2qcviirs_read_options(optionList, argc, argv);
161 
162  str_L2file = clo_getString(optionList, "ifile");
163  str_cfile = clo_getString(optionList, "cfile");
164  str_rfile = clo_getString(optionList, "ofile");
165  if (str_rfile != NULL) {
166  bReportFile = 1;
167  }
168 
169  string str_L2basename = basename(str_L2file);
170  char str_L2_product[10] = "All";
171 
172  regex OC ("(.*)(OC)(.*)");
173  regex IOP ("(.*)(IOP)(.*)");
174  regex SST ("(.*)(SST)(.*)");
175  regex SST3 ("(.*)(SST3)(.*)");
176  if (regex_match(str_L2basename,OC)){
177  strcpy(str_L2_product, "OC");
178  } else if (regex_match(str_L2basename,IOP)) {
179  strcpy(str_L2_product, "IOP");
180  } else if (regex_match(str_L2basename,SST3)) {
181  strcpy(str_L2_product, "SST3");
182  } else if (regex_match(str_L2basename,SST)) {
183  strcpy(str_L2_product, "SST");
184  }
185 
186  FILE *outfile;
187 
188  // read configuration file
189  FILE *configfile = fopen(str_cfile, "r");
190  if (!configfile) {
191  printf("Could not open configuration file. Exiting application.\n");
192  return 1;
193  }
194 
195  // read in the whole configuration text file as a string
196  char *file_contents;
197  long input_file_size;
198  fseek(configfile, 0, SEEK_END);
199  input_file_size = ftell(configfile);
200  rewind(configfile);
201  file_contents = (char*) calloc(input_file_size+50,1);
202  fread(file_contents, sizeof (char), input_file_size, configfile);
203  fclose(configfile);
204 
205  // parse the configuration file content string
206  char *line;
207  line = strtok(file_contents, "\n");
208 
209  int nAttributes_global=0;
210  int nAttributes_processing_control=0;
211 
212  while (line != NULL) {
213  if (match((char*) "#*", line)) {
214  // comment line
215  line = strtok(NULL, "\n");
216  continue;
217  } else if (match((char*) "[*]processing_control*", line)) {
218  // processing control group
219  // e.g. [OC,IOP,SST,SST3]processing_control.flag_percentages.NAVFAIL=0/0
220 
221  // if currently opened L2 product is in [], store attribute; otherwise, skip this line
222  char *tmpstrRBracket; // find the first right bracket in line
223  char *tmpstrL2product; // find first L2 product info in the list
224  char *tmpstrEqual; // find the first equal sign
225  tmpstrRBracket = strstr(line,"]");
226  tmpstrL2product = strstr(line,str_L2_product);
227  tmpstrEqual = strstr(line,"=");
228  if (tmpstrL2product!=NULL) {
229  if (tmpstrL2product<tmpstrRBracket) {
230  line = tmpstrRBracket + 1;
231  replacestr(line, "processing_control.", ""); // line = flag_percentages.NAVFAIL=0/0
232  char *strDot; // find first "." in the line
233  strDot = strstr(line, ".");
234  l2_Tplt_processing_control_g1[il2_Tplt_processing_control] = (char*) calloc(MAX_ATT_LEN,1);
235  strncpy(l2_Tplt_processing_control_g1[il2_Tplt_processing_control], line, strDot-tmpstrRBracket-1);
236  tmpstrEqual = strstr(line,"=");
237  l2_Tplt_processing_control_name[il2_Tplt_processing_control] = (char*) calloc(MAX_ATT_LEN,1);
238  strncpy(l2_Tplt_processing_control_name[il2_Tplt_processing_control], strDot+1, tmpstrEqual-strDot-1);
239  l2_Tplt_processing_control_val[il2_Tplt_processing_control] = (char*) calloc(MAX_ATT_LEN,1);
240  strcpy(l2_Tplt_processing_control_val[il2_Tplt_processing_control], tmpstrEqual+1);
241  il2_Tplt_processing_control++;
242  line = NULL;
243  }
244  }
245 
246  } else {
247  // global attribute
248  // e.g. [OC,IOP,SST,SST3]orbit_number=1/4294967295
249 
250  char *tmpstrRBracket; // find the first right bracket in line
251  char *tmpstrL2product; // find first L2 product info in the list
252  char *tmpstrEqual; // find the first equal sign
253  tmpstrRBracket = strstr(line,"]");
254  tmpstrL2product = strstr(line,str_L2_product);
255  tmpstrEqual = strstr(line,"=");
256  if (tmpstrL2product!=NULL) {
257  if (tmpstrL2product<tmpstrRBracket) {
258  l2_Tplt_global_att_name[il2_Tplt_global_att] = (char*) calloc(MAX_ATT_LEN,1);
259  strncpy(l2_Tplt_global_att_name[il2_Tplt_global_att], tmpstrRBracket+1, tmpstrEqual-tmpstrRBracket-1);
260  l2_Tplt_global_att_val[il2_Tplt_global_att] = (char*) calloc(MAX_ATT_LEN,1);
261  strcpy(l2_Tplt_global_att_val[il2_Tplt_global_att], tmpstrEqual+1);
262  il2_Tplt_global_att++;
263  }
264  }
265  }
266  if (line){
267  line = strtok(NULL, "\n");
268  }
269  }
270 
271  // update number of all attributes to check in the tempalte that applies to this L2 Product
272  nAttributes_global = il2_Tplt_global_att;
273  nAttributes_processing_control = il2_Tplt_processing_control;
274 
275  // open L2 netcdf file
276  status = nc_open(str_L2file, NC_NOWRITE, &ncid);
277  if (status != NC_NOERR) {
278  printf("Unable to open input VIIRS L2 file.\n");
279  return 1;
280  }
281 
282  // open report file
283  if (bReportFile) {
284  outfile = fopen(str_rfile, "a+");
285  if (outfile == NULL) {
286  printf("Unable to open output report file.\n");
287  return 1;
288  }
289  fprintf(outfile, "basename=%s\n", str_L2basename.c_str());
290  }
291 
292  // Check meta data format
293  status = nc_inq_natts(ncid, &natts);
294 
295  int meta_global_idx[nAttributes_global]; // global attributes
296  for (i = 0; i < nAttributes_global; i++) {
297  // for each item in metadata template
298  // default = 0: missing metadata in file
299  // -1: found matching item in file
300  // 1: found item in file, but not matching
301  // 2: wrong format or data range in file
302  meta_global_idx[i] = 0;
303  }
304 
305 // int meta_processing_control_idx[nAttributes_processing_control]; // processing control group
306 // for (i = 0; i < nAttributes_processing_control; i++) {
307 // // for each item in metadata template
308 // // default = 0: missing metadata in file
309 // // -1: found matching item in file
310 // // 1: found item in file, but not matching
311 // // 2: wrong format or data range in file
312 // meta_processing_control_idx[i] = 0;
313 // }
314 
315  // Check processing control groups
316  status = nc_inq_ncid(ncid, "processing_control", &grp0id);
317  for (int ipc = 0; ipc < nAttributes_processing_control; ipc++) {
318  status = nc_inq_ncid(grp0id, l2_Tplt_processing_control_g1[ipc], &grp1id);
319  status = nc_inq_natts(grp1id, &nattsp);
320  for (i = 0; i < nattsp; i++) {
321  status = nc_inq_attname(grp1id, NC_GLOBAL, i, attname);
322  status = nc_get_att_float(grp1id, NC_GLOBAL, attname, &att_float);
323  if (strcmp(attname, l2_Tplt_processing_control_name[ipc]) == 0) {
324  if (ValidBoundary(l2_Tplt_processing_control_val[ipc], &datamin, &datamax)) {
325  if ((att_float < datamin) || (att_float > datamax)) {
326  if (nFlagged > 0)
327  strcat(strFlagged, ",");
328  strcat(strFlagged, attname);
329  nFlagged++;
330  }
331  }
332  }
333  }
334  }
335 
336  // read global attributes from L2 file
337  for (i = 0; i < natts; i++) {
338  // read each of the metadata attributes in L2 file and compare with the template
339  // to check missing, un-matched and extra items.
340  status = nc_inq_attname(ncid, NC_GLOBAL, i, attname);
341  status = nc_inq_atttype(ncid, NC_GLOBAL, attname, &xtypep);
342  // read metadata template value
343  iMetaTplt = -1;
344  char strValTplt[MAX_ATT_LEN + 1], strNameTplt[MAX_ATT_LEN + 1];
345 
346  // find metadata item in the template, output the index
347  // otherwise, skip this attribute
348  for (j = 0; j < nAttributes_global; j++) {
349  strcpy(strNameTplt, l2_Tplt_global_att_name[j]);
350  if (match(strNameTplt, attname)) {
351  iMetaTplt = j;
352  break;
353  }
354  }
355  if (iMetaTplt < 0) continue;
356 
357  strcpy(strValTplt, l2_Tplt_global_att_val[iMetaTplt]);
358 
359  switch (xtypep) {
360  case NC_BYTE:
361  //printf("NC_BYTE\n");
362  break;
363  case NC_CHAR:
364  //printf("NC_CHAR\n");
365  status = nc_get_att_text(ncid, NC_GLOBAL, attname, att_text);
366  char strTmpstring[100];
367  char *strDot; // find first "." in file name, e.g. V2015363144800_S20151229130521.L2_SNPP_OC.nc
368  strDot = strstr(basename(str_L2file), ".");
369  strncpy(strTmpstring, basename(str_L2file)+1,strDot-basename(str_L2file)-1);
370  replacestr(strValTplt, strTimeStamp, strTmpstring);
371  // replace [L2Product] with OC or IOP...
372  replacestr(strValTplt, strL2ProdString, str_L2_product);
373  if (match(strValTplt, strTimeString0)) {
374  int iyr, mm, dd, ih, mn, sec, msec;
375  bool bPassCheck = true;
376  sscanf(att_text, "%d-%d-%dT%d:%d:%d.%dZ", &iyr, &mm, &dd, &ih, &mn, &sec, &msec);
377  if ((iyr < 2000) || (iyr > 3000)) bPassCheck = false;
378  if ((mm < 1) || (mm > 12)) bPassCheck = false;
379  if ((dd < 1) || (dd > 31)) bPassCheck = false;
380  if ((ih < 0) || (ih > 24)) bPassCheck = false;
381  if ((mn < 0) || (mn > 60)) bPassCheck = false;
382  if ((sec < 0) || (sec > 60)) bPassCheck = false;
383  if ((msec < 0) || (msec > 999)) bPassCheck = false;
384  if (!bPassCheck) {
385  meta_global_idx[iMetaTplt] = 2;
386  nWrongMetaData++;
387  char tmpstr[500];
388  sprintf(tmpstr, "var[%d]: %s = %s [Invalid time string]", i, attname, att_text);
389  replacestr(tmpstr, strTplt2replace, strDB2accept); // replace "|" with "," for database table "file_data" compatibility
390  strncpy(&errstr[nErr * MAX_ERR_LEN], tmpstr, MAX_ERR_LEN);
391  printf("%s\n", tmpstr);
392  nErr++;
393  break;
394  }
395  } else if (strstr(strValTplt, "|") != NULL) {
396  if (strstr(strValTplt, att_text) == NULL) {
397  meta_global_idx[iMetaTplt] = 1;
398  nWrongMetaData++;
399  char tmpstr[500];
400  sprintf(tmpstr, "%s not matching: Template val = %s; att_text = %s", attname, strValTplt, att_text);
401  replacestr(tmpstr, strTplt2replace, strDB2accept); // replace "|" with "," for database table "file_data" compatibility
402  strncpy(&errstr[nErr * MAX_ERR_LEN], tmpstr, MAX_ERR_LEN);
403  printf("%s\n", tmpstr);
404  nErr++;
405  break;
406  }
407  } else if (!match(strValTplt, att_text)) {
408  meta_global_idx[iMetaTplt] = 1;
409  nWrongMetaData++;
410  char tmpstr[500];
411  sprintf(tmpstr, "%s not matching: Template val = %s; att_text = %s", attname, strValTplt, att_text);
412  replacestr(tmpstr, strTplt2replace, strDB2accept); // replace "|" with "," for database table "file_data" compatibility
413  strncpy(&errstr[nErr * MAX_ERR_LEN], tmpstr, MAX_ERR_LEN);
414  printf("%s\n", tmpstr);
415  nErr++;
416  break;
417  }
418 
419  meta_global_idx[iMetaTplt] = -1; // means passing check
420  break;
421  case NC_SHORT:
422  //printf("NC_SHORT\n");
423  break;
424  case NC_LONG:
425  //printf("NC_LONG\n");
426  status = nc_get_att_long(ncid, NC_GLOBAL, attname, &att_long);
427 
428  // Check attribute data value to see if it is within boundary
429  if (ValidBoundary(strValTplt, &datamin, &datamax)) {
430  if ((att_long >= datamin) && (att_long <= datamax)) {
431  meta_global_idx[iMetaTplt] = -1;
432  } else {
433  meta_global_idx[iMetaTplt] = 2;
434  nWrongMetaData++;
435  char tmpstr[500];
436  sprintf(tmpstr, "%s: data not in correct range", attname);
437  replacestr(tmpstr, strTplt2replace, strDB2accept); // replace "|" with "," for database table "file_data" compatibility
438  strncpy(&errstr[nErr * MAX_ERR_LEN], tmpstr, MAX_ERR_LEN);
439  printf("%s\n", tmpstr);
440  nErr++;
441  break;
442  }
443  } else
444  meta_global_idx[iMetaTplt] = -1;
445 
446  break;
447  case NC_FLOAT:
448  //printf("NC_FLOAT\n");
449  status = nc_get_att_float(ncid, NC_GLOBAL, attname, &att_float);
450 
451  // Check attribute data value to see if it is within boundary
452  if (ValidBoundary(strValTplt, &datamin, &datamax)) {
453  if ((att_float >= datamin) && (att_float <= datamax)) {
454  meta_global_idx[iMetaTplt] = -1;
455  } else {
456  meta_global_idx[iMetaTplt] = 2;
457  nWrongMetaData++;
458  char tmpstr[500];
459  sprintf(tmpstr, "%s: data not in correct range", attname);
460  replacestr(tmpstr, strTplt2replace, strDB2accept); // replace "|" with "," for database table "file_data" compatibility
461  strncpy(&errstr[nErr * MAX_ERR_LEN], tmpstr, MAX_ERR_LEN);
462  printf("%s\n", tmpstr);
463  nErr++;
464  break;
465  }
466  } else
467  meta_global_idx[iMetaTplt] = -1;
468 
469  break;
470  case NC_DOUBLE:
471  //printf("NC_DOUBLE\n");
472  status = nc_get_att_double(ncid, NC_GLOBAL, attname, &att_double);
473 
474  // Check attribute data value to see if it is within boundary
475  if (ValidBoundary(strValTplt, &datamin, &datamax)) {
476  if ((att_double >= datamin) && (att_double <= datamax)) {
477  meta_global_idx[iMetaTplt] = -1;
478  } else {
479  meta_global_idx[iMetaTplt] = 2;
480  nWrongMetaData++;
481  char tmpstr[500];
482  sprintf(tmpstr, "%s: data not in correct range", attname);
483  replacestr(tmpstr, strTplt2replace, strDB2accept); // replace "|" with "," for database table "file_data" compatibility
484  strncpy(&errstr[nErr * MAX_ERR_LEN], tmpstr, MAX_ERR_LEN);
485  printf("%s\n", tmpstr);
486  nErr++;
487  break;
488  }
489  } else
490  meta_global_idx[iMetaTplt] = -1;
491  break;
492  case NC_STRING:
493  //printf("NC_STRING\n");
494  //status = nc_get_att_text(ncid, NC_GLOBAL, attname, att_text);
495  break;
496  default:
497  char tmpstr[500];
498  sprintf(tmpstr, "Attribute [%d] data type not found in template!", i);
499  replacestr(tmpstr, strTplt2replace, strDB2accept); // replace "|" with "," for database table "file_data" compatibility
500  strncpy(&errstr[nErr * MAX_ERR_LEN], tmpstr, MAX_ERR_LEN);
501  printf("%s\n", tmpstr);
502  nErr++;
503  }
504 
505  if (meta_global_idx[iMetaTplt] != -1) printf("not passing check!\n");
506 
507  if (strcmp(attname, "time_coverage_start") == 0) {
508  printf("start_time=%s\n", att_text);
509  if (bReportFile) fprintf(outfile, "start_time=%s\n", att_text);
510  }
511  if (strcmp(attname, "time_coverage_end") == 0) {
512  printf("stop_time=%s\n", att_text);
513  if (bReportFile) fprintf(outfile, "stop_time=%s\n", att_text);
514  }
515  if (strcmp(attname, "processing_version") == 0) {
516  printf("processing_version=%s\n", att_text);
517  if (bReportFile) fprintf(outfile, "processing_version=%s\n", att_text);
518  }
519  if (strcmp(attname, "day_night_flag") == 0) {
520  printf("day_night_flag=%s\n", att_text);
521  if (bReportFile) fprintf(outfile, "day_night_flag=%s\n", att_text);
522  }
523  }
524 
525  for (i = 0; i < nAttributes_global; i++) {
526  if (meta_global_idx[i] == 0) {
527  nMissingMetaData++;
528  printf("L2 file missing att[%d] %s\n", i, l2_Tplt_global_att_name[i]);
529  }
530  }
531 
532  if ((nMissingMetaData == 0) && (nWrongMetaData == 0)) printf("No error found in Metadata.\n");
533 
534  if (nFlagged < 1)
535  printf("No flags for attention in Metadata.\n");
536  else if (nFlagged == 1)
537  printf("1 flag for attention in Metadata.\n");
538  else
539  printf("%d flags for attention in Metadata.\n", nFlagged);
540 
541  // output report file
542  if (bReportFile) {
543  fprintf(outfile, "errors=%d\n", nErr);
544  for (i = 0; i < nErr; i++) {
545  fprintf(outfile, "err_%d=%.*s\n", i + 1, MAX_ERR_LEN, errstr + i * MAX_ERR_LEN);
546  }
547  if (nFlagged > 0) fprintf(outfile, "%s\n", strFlagged);
548  fclose(outfile);
549  }
550 
551  status = nc_close(ncid);
552 
553  free(errstr);
554  for (i = 0; i < nAttributes_global; i++) free(l2_Tplt_global_att_name[i]);
555  for (i = 0; i < nAttributes_global; i++) free(l2_Tplt_global_att_val[i]);
556  for (i = 0; i < nAttributes_processing_control; i++) free(l2_Tplt_processing_control_name[i]);
557  for (i = 0; i < nAttributes_processing_control; i++) free(l2_Tplt_processing_control_val[i]);
558 
560  return nMissingMetaData+nWrongMetaData+nFlagged+nErr;
561 }
562 
563 
564 
an array had not been initialized Several spelling and grammar corrections were which is read from the appropriate MCF the above metadata values were hard coded A problem calculating the average background DN for SWIR bands when the moon is in the space view port was corrected The new algorithm used to calculate the average background DN for all reflective bands when the moon is in the space view port is now the same as the algorithm employed by the thermal bands For non SWIR changes in the averages are typically less than Also for non SWIR the black body DNs remain a backup in case the SV DNs are not available For SWIR the changes in computed averages were larger because the old which used the black body suffered from contamination by the micron leak As a consequence of the if SV DNs are not available for the SWIR the EV pixels will not be the granule time is used to identify the appropriate tables within the set given for one LUT the first two or last two tables respectively will be used for the interpolation If there is only one LUT in the set of it will be treated as a constant LUT The manner in which Earth View data is checked for saturation was changed Previously the raw Earth View DNs and Space View DNs were checked against the lookup table values contained in the table dn_sat The change made is to check the raw Earth and Space View DNs to be sure they are less than the maximum saturation value and to check the Space View subtracted Earth View dns against a set of values contained in the new lookup table dn_sat_ev The metadata configuration and ASSOCIATEDINSTRUMENTSHORTNAME from the MOD02HKM product The same metatdata with extensions and were removed from the MOD021KM and MOD02OBC products ASSOCIATEDSENSORSHORTNAME was set to MODIS in all products These changes are reflected in new File Specification which users may consult for exact the pow functions were eliminated in Emissive_Cal and Emissive bands replaced by more efficient code Other calculations throughout the code were also made more efficient Aside from a few round off there was no difference to the product The CPU time decreased by about for a day case and for a night case A minor bug in calculating the uncertainty index for emissive bands was corrected The frame index(0-based) was previously being used the frame number(1-based) should have been used. There were only a few minor changes to the uncertainty index(maximum of 1 digit). 3. Some inefficient arrays(Sigma_RVS_norm_sq) were eliminated and some code lines in Preprocess_L1A_Data were moved into Process_OBCEng_Emiss. There were no changes to the product. Required RAM was reduced by 20 MB. Now
int j
Definition: decode_rs.h:73
int l2qcviirs_read_options(clo_optionList_t *list, int argc, char *argv[])
char * clo_getString(clo_optionList_t *list, const char *key)
Definition: clo.c:1357
int status
Definition: l1_czcs_hdf.c:32
#define NULL
Definition: decode_rs.h:63
int32 * msec
Definition: l1_czcs_hdf.c:31
int main(int argc, char *argv[])
Definition: l2qc_viirs.cpp:111
subroutine search(dflag, xbar, x, n, i)
clo_optionList_t * clo_createList()
Definition: clo.c:532
void clo_printUsage(clo_optionList_t *list)
Definition: clo.c:1988
#define MAX_ATT_NUM
Definition: l2qc_viirs.cpp:33
int32_t ih
Definition: atrem_corl1.h:161
#define MAX_ERR_LEN
Definition: l2qc_viirs.cpp:35
#define VERSION
Definition: l2qc_viirs.cpp:31
bool match(char *first, char *second)
Definition: l2qc_viirs.cpp:45
#define basename(s)
Definition: l0chunk_modis.c:29
#define SST
PARAM_TYPE_NONE Default value No parameter is buried in the product name name_prefix is case insensitive string compared to the product name PARAM_TYPE_VIS_WAVE The visible wavelength bands from the sensor are buried in the product name The product name is compared by appending and name_suffix ie aph_412_giop where prod_ix will be set to PARAM_TYPE_IR_WAVE same search method as PARAM_TYPE_VIS_WAVE except only wavelength above are looped through but prod_ix is still based ie aph_2_giop for the second and prod_ix set to PARAM_TYPE_INT name_prefix is compared with the beginning of the product name If name_suffix is not empty the it must match the end of the product name The characters right after the prefix are read as an integer and prod_ix is set to that number strncpy(l2prod->name_prefix, "myprod", UNITLEN)
clo_optionList_t * optionList
Definition: l2qc_viirs.cpp:39
void clo_deleteList(clo_optionList_t *list)
Definition: clo.c:875
int ValidBoundary(const char *strMinMax, float *datamin, float *datamax)
Definition: l2qc_viirs.cpp:85
int l2qcviirs_init_options(clo_optionList_t *list, const char *softwareVersion)
#define MAX_ATT_LEN
Definition: l2qc_viirs.cpp:34
int i
Definition: decode_rs.h:71
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int32_t iyr
Definition: atrem_corl1.h:161