OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
main_l3gen.cpp
Go to the documentation of this file.
1 // =====================================================================
2 // l3gen - level-3 to level-3 ocean algorithm processor
3 // B. Franz, NASA/OBPG, August 2008
4 //
5 // Modification History
6 // --------------------
7 // Use hdf_bin class rather than hdf4_bin class
8 // J. Gales Futuretech 07/18/11
9 // =====================================================================
10 
11 #include <stdio.h>
12 #include <math.h>
13 #include <iostream>
14 #include <sstream>
15 #include <list>
16 #include "netcdf.h"
17 #include "hdf_bin.h"
18 #include "version.h"
19 
20 #define NBINREAD MAXPIX
21 #define FLAGMASK PRODFAIL
22 
23 extern "C" {
24 #include "l12_proto.h"
25 }
26 
27 using namespace std;
28 
30 
31 void l3gen_usage(char *prog) {
32  l2gen_usage("l3gen");
33 }
34 
35 void load_l3file_handle(int sensorID, int filenum, filehandle *file) {
36  strcpy(file->name, (const char *) input->ofile[filenum]);
37  strcpy(file->l2prod, (const char *) input->l2prod[filenum]);
38  strcpy(file->def_l2prod, input->def_l2prod[filenum]);
39 
40  file->format = FT_L3BIN;
41  file->mode = WRITE;
42  file->sensorID = sensorID;
43 
44  file->tot_prod = prodlist(file->sensorID, l1_input->evalmask, file->l2prod,
45  file->def_l2prod, file->l2_prod_names);
46 }
47 
48 void load_input_filehandle(filehandle *l1file) {
49  int32 sensorID = l1file->sensorID;
50  int32 evalmask = l1_input->evalmask;
51 
52  l1file->nbands = rdsensorinfo(sensorID, evalmask, NULL, NULL);
53  l1file->nbandsir = rdsensorinfo(sensorID, evalmask, "NbandsIR", NULL);
54  l1file->ndets = 1;
55 
56  rdsensorinfo(sensorID, evalmask, "Bindx", (void **) &l1file->bindx);
57  rdsensorinfo(sensorID, evalmask, "Lambda", (void **) &l1file->iwave);
58  rdsensorinfo(sensorID, evalmask, "fwave", (void **) &l1file->fwave);
59  rdsensorinfo(sensorID, evalmask, "Fobar", (void **) &l1file->Fobar);
60  rdsensorinfo(sensorID, evalmask, "Tau_r", (void **) &l1file->Tau_r);
61  rdsensorinfo(sensorID, evalmask, "k_oz", (void **) &l1file->k_oz);
62  rdsensorinfo(sensorID, evalmask, "k_no2", (void **) &l1file->k_no2);
63  rdsensorinfo(sensorID, evalmask, "aw", (void **) &l1file->aw);
64  rdsensorinfo(sensorID, evalmask, "bbw", (void **) &l1file->bbw);
65 
66  bindex_set(l1file->iwave, l1file->nbands + l1file->nbandsir, BANDW);
67 
68  if ((l1file->Fonom = (float*) calloc(l1file->nbands, sizeof (float))) == NULL) {
69  printf("-E- (%s, %d) Cannot allocate space for l1file->Fonom\n", __FILE__, __LINE__);
70  exit(EXIT_FAILURE);
71  }
72  int i;
73  for (i = 0; i < l1file->nbands; i++) {
74  if (l1_input->outband_opt >= 2) {
75  get_f0_thuillier_ext(l1file->iwave[i], BANDW, l1file->Fonom + i);
76  } else {
77  l1file->Fonom[i] = l1file->Fobar[i];
78  }
79  }
80 
81 }
82 
83 void load_l12(l2str *l2rec) {
84  int32 iw;
85 
86  l1str* l1rec = l2rec->l1rec;
87  filehandle* l1file = l1rec->l1file;
88  int32 nbands = l1file->nbands;
89 
90  //memset(l1rec->data, 0, l1rec->length);
91  //memset(l2rec->data, 0, l2rec->length);
92 
93  for (iw = 0; iw < nbands; iw++) {
94  l1rec->Fo[iw] = l1file->Fobar[iw]; // for the moment
95  }
96 
97  l1rec->tilt = 0.0;
98  l1rec->mside = 0;
99  l1rec->detnum = 0;
100 
101  int ip;
102  for (ip = 0; ip < l1rec->npix; ip++) {
103  l1rec->pixnum[ip] = 0;
104  l1rec->alpha[ip] = 0.0;
105  l1rec->flags[ip] = 0;
106  l1rec->mask[ip] = 0;
107  }
108 
109 }
110 
111 instr *input; // input parameters structure
112 
113 // --------------------------------------------------------------------
114 // main
115 // --------------------------------------------------------------------
116 
117 int main(int argc, char* argv[]) {
118  static l1str *l1rec; // generic level-1b scan structure
119  static l2str *l2rec; // generic level-2 scan structure
120  static filehandle ifile; // input file handle
121  static filehandle ofile; // output file handle
122  int iprod;
123 
124  char *ptime = ydhmsf(now(), 'G');
125  double start_time = now();
126 
127  int16 year, day;
128  int32_t syear;
129  int32_t sday;
130  double dsec;
131  double mtime;
132 
133  char soft_id[200];
134  float gmt;
135  float solz;
136  float sola;
137  char buf[FILENAME_MAX];
138 
139  int i;
140  int ip;
141  int offset;
142  int64_t bin_num;
143  int nobs;
144  int nscenes;
145  int nwrite;
146  static bool atLeastOne = false;
147  int mainReturnCode = EXIT_SUCCESS;
148 
149  char units_string[MD_ATTRSZ];
150 
151  if (argc == 1) {
152  l3gen_usage(argv[0]);
153  return EXIT_SUCCESS;
154  }
155 
156  // see if help on command line
157  for (i = 0; i < argc; i++) {
158  if ((strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "-help") == 0)) {
159  l3gen_usage(argv[0]);
160  return EXIT_SUCCESS;
161  }
162  }
163 
164  setvbuf(stdout, NULL, _IOLBF, 0);
165  setvbuf(stderr, NULL, _IOLBF, 0);
166 
167  // Initialize file handles
169 
170  cdata_();
173 
174  // Parse input parameters
175  if (msl12_input(argc, argv, "l3gen", &ifile) != 0) {
176  printf("-E- %s: Error parsing input parameters.\n", argv[0]);
177  exit(1);
178  }
179 
181 
182  char proc_con[2048];
183  strcpy(proc_con, basename(argv[0]));
184  for (i = 1; i < argc; i++) {
185  strcat(proc_con, " ");
186  strcat(proc_con, argv[i]);
187  }
188 
189  // Transfer input info to file handles
190  load_l3file_handle(ifile.sensorID, 0, &ofile);
191 
192  // Build output product list
193 
194  cout << endl << "The following products will be included in " << ofile.name
195  << endl;
196  int32 nprods_out = ofile.tot_prod;
197  char prodlist_out[L1_PRODSTRLEN] = "";
198  for (iprod = 0; iprod < ofile.tot_prod; iprod++) {
199  cout << iprod + 1 << " " << ofile.l2_prod_names[iprod] << endl;
200  strcat(prodlist_out, ofile.l2_prod_names[iprod]);
201  if (iprod < ofile.tot_prod - 1)
202  strcat(prodlist_out, ",");
203  }
204 
205  // Open input binfile and get full input product list
206 
207  static Hdf::hdf_bin *input_binfile;
208  const char *inputfile;
209 
210  inputfile = input->ifile[0];
211  input_binfile = Hdf::openBinObject(inputfile);
212 
213  int len = input_binfile->query();
214  char *fullprodlist = (char *) malloc(len);
215  input_binfile->query(fullprodlist);
216  int nrows = input_binfile->nrows;
217 
218  // Get input bin dimension
219  int32 npix = NBINREAD;
220 
221  // Get mean time
222  mtime = (input_binfile->meta_l3b.startTime + input_binfile->meta_l3b.endTime) / 2.0;
223 
224  unix2yds(mtime, &year, &day, &dsec);
225  //yes, silly, but easier than fixing the various routines that need either a 16 or 32bit int for year/day
226  syear = year;
227  sday = day;
228 
229  // Allocate memory for L1 and L2 scan data (the L2 record shares
230  // space with the L1 record, hence we need to allocate both)
231  l1rec = (l1str*) malloc(sizeof (l1str));
232  l2rec = (l2str*) malloc(sizeof (l2str));
233 
234  ifile.npix = npix;
235  ifile.nscan = 1;
236  if (alloc_l1(&ifile, l1rec) == 0) {
237  printf("-E- %s: Unable to allocate L1 record.\n", argv[0]);
238  exit(1);
239  }
240  if (alloc_l2(l1rec, l2rec) == 0) {
241  printf("-E- %s: Unable to allocate L2 record.\n", argv[0]);
242  exit(1);
243  }
244 
245  // Add meta-data to L1 and L2 structures - use a single pixel just to get things
246  // started - load_l12 will be called for each bin row with an appropriate # of pixels
247  load_l12(l2rec);
248 
249  // Build input product request list
250 
251  int32 n_vvv = MIN(windex(700., ifile.fwave, ifile.nbands) + 1, ifile.nbands);
252  char prodstr[L1_PRODSTRLEN] = "";
253 
254  // what we have
255 
256  char **prodlist_in;
257  int32 nprods_in = input_binfile->query(&prodlist_in);
258 
259  // what we want
260 
261  char prodlist_wt[L1_MAXPROD][32];
262  int32 nprods_wt = prodlist(ifile.sensorID, l1_input->evalmask,
263  "Rrs_vvv nLw_vvv Rrs_vc_vvv solz sola senz sena relaz", "",
264  prodlist_wt);
265 
266  enum geo_order {
267  SOLZ, SOLA, SENZ, SENA, RELAZ
268  };
269 
270  // what we have that we want
271 
272  int32 *rrs_bindex;
273  int32 *rrs_windex;
274  int32 n_rrs = 0;
275  int32 *nlw_bindex;
276  int32 *nlw_windex;
277  int32 n_nlw = 0;
278  int32 geo_bindex[5];
279  int32 geo_windex[5];
280  int32 n_geo = 0;
281  int32 have_solz = 0;
282  int32 have_sola = 0;
283  int32 have_sena = 0;
284  int32 have_relaz = 0;
285 
286  if ((rrs_bindex = (int32 *) malloc(ifile.nbands * sizeof (int32))) == NULL) {
287  printf("-E- %s: Error allocating memory to the input data array.\n",
288  argv[0]);
289  exit(FATAL_ERROR);
290  }
291  if ((rrs_windex = (int32 *) malloc(ifile.nbands * sizeof (int32))) == NULL) {
292  printf("-E- %s: Error allocating memory to the input data array.\n",
293  argv[0]);
294  exit(FATAL_ERROR);
295  }
296  if ((nlw_bindex = (int32 *) malloc(ifile.nbands * sizeof (int32))) == NULL) {
297  printf("-E- %s: Error allocating memory to the input data array.\n",
298  argv[0]);
299  exit(FATAL_ERROR);
300  }
301  if ((nlw_windex = (int32 *) malloc(ifile.nbands * sizeof (int32))) == NULL) {
302  printf("-E- %s: Error allocating memory to the input data array.\n",
303  argv[0]);
304  exit(FATAL_ERROR);
305  }
306 
307  cout << endl << "Checking input for desired products: " << endl;
308  iprod = 0;
309  for (int32 iwant = 0; iwant < nprods_wt; iwant++) {
310  for (int32 ihave = 0; ihave < nprods_in; ihave++) {
311  if (strcmp(prodlist_in[ihave], prodlist_wt[iwant]) == 0) {
312  strcat(prodstr, prodlist_in[ihave]);
313  strcat(prodstr, ",");
314  cout << "found " << prodlist_wt[iwant] << endl;
315  if (iwant < n_vvv) {
316  rrs_bindex[n_rrs] = iprod; // posiiton in bin read
317  rrs_windex[n_rrs] = iwant; // position in sensor wavelengths
318  n_rrs++;
319  iprod++;
320  } else if (iwant < n_vvv * 2) {
321  nlw_bindex[n_nlw] = iprod; // positon in bin read
322  nlw_windex[n_nlw] = iwant - n_vvv; // position in sensor wavelengths
323  n_nlw++;
324  iprod++;
325  } else if (iwant < n_vvv * 3) { // Rrs_vc products overwriting Rrs
326  rrs_bindex[n_rrs] = iprod; // posiiton in bin read
327  rrs_windex[n_rrs] = iwant - 2 * n_vvv; // position in sensor wavelengths
328  n_rrs++;
329  iprod++;
330  } else {
331  geo_bindex[n_geo] = iprod;
332  geo_windex[n_geo] = iwant - 3 * n_vvv;
333  switch (geo_windex[n_geo]) {
334  case SOLZ:
335  have_solz = 1;
336  break;
337  case SOLA:
338  have_sola = 1;
339  break;
340  case SENA:
341  have_sena = 1;
342  break;
343  case RELAZ:
344  have_relaz = 1;
345  break;
346  }
347  n_geo++;
348  iprod++;
349  }
350  break;
351  }
352  }
353  }
354  nprods_in = iprod;
355 
356  // remove trailing comma
357  len = strlen(prodstr);
358  prodstr[len - 1] = '\0';
359 
360  // Allocate data arrays and bin list and masking flag
361  float **outData;
362  float **tmpData;
363  float **inData;
364  if ((inData = (float **) malloc(nprods_in * sizeof (float *))) == NULL) {
365  printf("-E- %s: Error allocating memory to the input data array.\n",
366  argv[0]);
367  exit(FATAL_ERROR);
368  }
369  if ((outData = (float **) malloc(nprods_out * sizeof (float *))) == NULL) {
370  printf("-E- %s: Error allocating memory to the output data array.\n",
371  argv[0]);
372  exit(FATAL_ERROR);
373  }
374  if ((tmpData = (float **) malloc(nprods_out * sizeof (float *))) == NULL) {
375  printf("-E- %s: Error allocating memory to the temp data array.\n",
376  argv[0]);
377  exit(FATAL_ERROR);
378  }
379  for (i = 0; i < nprods_in; i++) {
380  if ((inData[i] = (float *) calloc(2 * npix, sizeof (float))) == NULL) {
381  printf("-E- %s: Error allocating memory to the output data array.\n",
382  argv[0]);
383  exit(FATAL_ERROR);
384  }
385  }
386  for (i = 0; i < nprods_out; i++) {
387  if ((outData[i] = (float *) calloc(2 * npix, sizeof (float))) == NULL) {
388  printf(
389  "-E- %s: Error allocating memory to the output data array.\n",
390  argv[0]);
391  exit(FATAL_ERROR);
392  }
393  if ((tmpData[i] = (float *) calloc(npix, sizeof (float))) == NULL) {
394  printf(
395  "-E- %s: Error allocating memory to the output data array.\n",
396  argv[0]);
397  exit(FATAL_ERROR);
398  }
399  }
400  char *outMask = (char *) calloc(npix, sizeof (char));
401 
402  // set up the bin file reading for the products we need
403  input_binfile->read(prodstr);
404 
405  /* Create output file */
406  /* ------------------ */
407  Hdf::hdf_bin *output_binfile;
408 
409  /*
410  * If the input structure does not set the output format,
411  * make the output format match the input L3 format
412  */
413  if (getFileFormatName(input->oformat) == NULL) {
414  if (input_binfile->isHDF5) {
415  strcpy(input->oformat, "HDF5");
416  } else if (input_binfile->isCDF4) {
417  strcpy(input->oformat, "netCDF4");
418  } else {
419  strcpy(input->oformat, "HDF4");
420  }
421  }
422 
423  if (strcmp(input->oformat, "HDF4") == 0) {
424  output_binfile = new Hdf::hdf4_bin;
425  output_binfile->hasNoext = true;
426  }
427  if (strcmp(input->oformat, "HDF5") == 0)
428  output_binfile = new Hdf::hdf5_bin;
429  if (strcmp(input->oformat, "netCDF4") == 0)
430  output_binfile = new Hdf::cdf4_bin;
431 
432  output_binfile->deflate = input->deflate;
433 
434  strcpy(output_binfile->meta_l3b.product_name, ofile.name);
435  strncpy(output_binfile->meta_l3b.ptime, ptime, 16);
436  strcpy(output_binfile->meta_l3b.proc_con, proc_con);
437  strcpy(output_binfile->meta_l3b.input_parms, l1_input->input_parms);
438 
439  char* tmpProdNames[ofile.tot_prod];
440  for (int i = 0; i < ofile.tot_prod; i++) {
441  tmpProdNames[i] = ofile.l2_prod_names[i];
442  }
443  output_binfile->setProductList(ofile.tot_prod, tmpProdNames);
444  output_binfile->create(ofile.name, input_binfile->nrows);
445 
446  // Begin processing
447  for (int32 iscan = 0; iscan < nrows; iscan++) {
448  if (iscan % 50 == 0) {
449  int secs = (int) now() - start_time;
450  cout << "Reading row " << iscan << " of " << nrows << " after " << secs << " seconds" << endl;
451  }
452  // Read the inputs
453  // Get basebin and numbin for this input row
454  int64_t basebin = input_binfile->get_basebin(iscan);
455  input_binfile->readBinIndex(iscan);
456  int ext = input_binfile->get_ext();
457  int64_t beg = input_binfile->get_beg();
458  // if the row has no filled bins, skip it
459  if (beg == 0)
460  continue;
461 
462  input_binfile->readBinList(ext);
463 
464  // fill the input data array with the necessary input data
465  i = 0;
466  for (int j = 0; j < input_binfile->nprod(); j++) {
467 
468  if (input_binfile->active_data_prod[j] == true) {
469  input_binfile->get_prodname(j, buf);
470  if (strcmp(prodlist_in[j], buf) == 0) {
471  input_binfile->readSums(inData[i], ext, j);
472  i++;
473  }
474  }
475  }
476  if (input_binfile->isHDF5 || input_binfile->isCDF4)
477  input_binfile->setDataPtr(ext);
478 
479 
480  // Stuff the L2 record
481  // only process as many pixels as the row as filled bins
482  l1rec->npix = ext;
483  ifile.npix = ext;
484  ifile.epix = ext - 1;
485  ifile.terrain_corrected = 1;
486 
487  memset(outMask, '\0', npix);
488  init_l1(l1rec);
489  init_l2(l2rec, ifile.nbands);
490 
491  load_l12(l2rec);
492 
493  l1rec->iscan = iscan;
494  l1rec->scantime = mtime;
495 
496  // Fill in the l1/2 structures with data from input bin file
497  // nLw, Rrs, geometries - if available.
498  for (ip = 0; ip < ext; ip++) {
499  float weight = input_binfile->get_weights(ip);
500  int32 ipw;
501  float lat;
502  float lon;
503  float flat, flon;
504 
505  bin_num = input_binfile->get_bin_num(ip);
506  input_binfile->bin2latlon(bin_num, lat, lon);
507  l1rec->lon[ip] = lon;
508  l1rec->lat[ip] = lat;
509  l1rec->nobs[ip] = input_binfile->get_nobs(ip);
510  for (int32 iw = 0; iw < n_nlw; iw++) {
511  ipw = ip * ifile.nbands + nlw_windex[iw];
512  l2rec->nLw[ipw] = inData[nlw_bindex[iw]][2 * ip] / weight;
513  l2rec->Rrs[ipw] = MAX(l2rec->nLw[ipw] / ifile.Fonom[iw], BAD_FLT);
514  }
515  for (int32 iw = 0; iw < n_rrs; iw++) {
516  ipw = ip * ifile.nbands + rrs_windex[iw];
517  l2rec->Rrs[ipw] = inData[rrs_bindex[iw]][2 * ip] / weight;
518  l2rec->nLw[ipw] = MAX(l2rec->Rrs[ipw] * ifile.Fonom[iw], BAD_FLT);
519  }
520  l1rec->solz[ip] = 0.0;
521  l1rec->sola[ip] = 0.0;
522  l1rec->senz[ip] = 0.0;
523  l1rec->sena[ip] = 90.0;
524  l1rec->delphi[ip] = 90.0;
525 
526  for (int32 iw = 0; iw < n_geo; iw++) {
527  switch (geo_windex[iw]) {
528  case SOLZ:
529  l1rec->solz[ip] = inData[geo_bindex[iw]][2 * ip] / weight;
530  break;
531  case SOLA:
532  l1rec->sola[ip] = inData[geo_bindex[iw]][2 * ip] / weight;
533  break;
534  case SENZ:
535  l1rec->senz[ip] = inData[geo_bindex[iw]][2 * ip] / weight;
536  break;
537  case SENA:
538  l1rec->sena[ip] = inData[geo_bindex[iw]][2 * ip] / weight;
539  break;
540  case RELAZ:
541  l1rec->delphi[ip] = inData[geo_bindex[iw]][2 * ip] / weight;
542  break;
543  }
544  }
545  if (!have_solz) {
546  // assume noon orbit
547  flon = l1rec->lon[ip];
548  flat = l1rec->lat[ip];
549  gmt = 12 - lon / 15;
550  sunangs_(&syear, &sday, &gmt, &flon, &flat, &solz, &sola);
551  l1rec->solz[ip] = solz;
552  l1rec->sola[ip] = sola;
553  }
554  if (have_sola && have_sena && !have_relaz) {
555  l1rec->delphi[ip] = l1rec->sena[ip] - 180.0 - l1rec->sola[ip];
556  if (l1rec->delphi[ip] < -180)
557  l1rec->delphi[ip] += 360.0;
558  } else if (!have_sola && !have_sena && have_relaz) {
559  l1rec->sena[ip] = 90.0;
560  l1rec->sola[ip] = l1rec->sena[ip] - 180.0
561  - l1rec->delphi[ip];
562  if (l1rec->sola[ip] < -180)
563  l1rec->sola[ip] += 360.0;
564  }
565  }
566 
567  // Add ancillary, Rayleigh, etc.
568  loadl1(&ifile, l1rec);
569 
570  // clear out the masks
571  for (ip = 0; ip < ext; ip++)
572  l1rec->mask[ip] = 0;
573 
574  // Add a default chl
575 
576  for (ip = 0; ip < ext; ip++)
577  l2rec->chl[ip] = get_default_chl(l2rec, &l2rec->Rrs[ip * ifile.nbands]);
578 
579  // Add default inherent optical properties
580 
581  if (input->iop_opt > 0 && (input->proc_ocean != 0))
582  get_iops(l2rec, input->iop_opt);
583 
584  // Compute output products and store in temporary buffer
585 
586  for (iprod = 0; iprod < nprods_out; iprod++) {
587 
588  // get the product index record
589  for (i = 0; i < ext; i++)
590  tmpData[iprod][i] = BAD_FLT;
591 
592  l2prodstr *p;
593 
594  if ((p = get_l2prod_index(ofile.l2_prod_names[iprod],
595  ifile.sensorID, ifile.nbands + ifile.nbandsir, ext,
596  ifile.nscan, ifile.iwave)) == NULL) {
597  printf("-E- %s line %d: product index failure.\n", __FILE__,
598  __LINE__);
599  exit(1);
600  };
601 
602  // Compute or extract the product & copy to output buffer
603 
604  VOIDP pbuf = prodgen(p, l2rec);
605 
606  // build the units attribute string
607 
608  productInfo_t *p_info;
609  p_info = allocateProductInfo();
610 
611  if (!findProductInfo(ofile.l2_prod_names[iprod], ifile.sensorID, p_info)) {
612  printf("-E- product %s not found in XML product table\n",
613  ofile.l2_prod_names[iprod]);
614  exit(EXIT_FAILURE);
615  }
616 
617  if (iprod == 0){
618  strcpy(units_string,getProductNameFull(p_info));
619  strcat(units_string,":");
620  strcat(units_string,p->units);
621  }
622  else {
623  strcat(units_string,getProductNameFull(p_info));
624  strcat(units_string,":");
625  strcat(units_string,p->units);
626  }
627  if (iprod < nprods_out -1)
628  strcat(units_string,",");
629 
630  freeProductInfo(p_info);
631 
632  memcpy(tmpData[iprod], (float *) pbuf,
633  ext * sizeof (float));
634 
635  // Check flags and set masking
636 
637  for (ip = 0; ip < ext; ip++) {
638  if ((tmpData[iprod][ip] == BAD_FLT)
639  || (l1rec->flags[ip] & FLAGMASK) != 0) {
640  outMask[ip] = 1;
641  }
642  }
643 
644  }
645 
646  /* Write output */
647  /* ------------ */
648  output_binfile->clear_binlist();
649  nwrite = 0;
650 
651  for (ip = 0; ip < ext; ip++) {
652  if (!outMask[ip]) {
653  atLeastOne = true;
654  bin_num = input_binfile->get_bin_num(ip);
655  offset = bin_num - basebin;
656  output_binfile->set_bin_num(offset, bin_num);
657  nobs = input_binfile->get_nobs(ip);
658  output_binfile->inc_nobs(offset, nobs);
659  nscenes = input_binfile->get_nscenes(ip);
660  output_binfile->inc_nscenes(offset, nscenes);
661  output_binfile->set_weights(offset, 1);
662 
663  /* Loop over data products */
664  /* ----------------------- */
665  for (iprod = 0; iprod < nprods_out; iprod++) {
666  outData[iprod][2 * nwrite] = tmpData[iprod][ip];
667 
668  } /* iprod loop */
669  if (nwrite != offset)
670  output_binfile->copy_binlist(offset, nwrite);
671 
672  nwrite++;
673  }
674  } /* ip loop */
675 
676 
677  /* Write BinList & Data Products */
678  /* ----------------------------- */
679  if (nwrite > 0) {
680  output_binfile->writeBinList(nwrite);
681  for (iprod = 0; iprod < nprods_out; iprod++) {
682  strcpy(buf, ofile.l2_prod_names[iprod]);
683  output_binfile->writeSums(outData[iprod], nwrite, buf);
684  }
685 
686  if (strcmp(input->oformat, "HDF5") == 0
687  || strcmp(input->oformat, "netCDF4") == 0)
688  output_binfile->incNumRec(nwrite);
689  }
690  }
691 
692  output_binfile->copymeta(1, &input_binfile);
693  if (strcmp(input->oformat, "netCDF4")) {
694  strcpy(output_binfile->meta_l3b.sensor, sensorId2InstrumentName(ifile.sensorID));
695  } else {
696  strcpy(output_binfile->meta_l3b.sensor_name, sensorId2SensorName(ifile.sensorID));
697  }
698  strcpy(output_binfile->meta_l3b.mission, sensorId2PlatformName(ifile.sensorID));
699  strcpy(output_binfile->meta_l3b.infiles, basename((char *) input->ifile[0]));
700  strcpy(output_binfile->meta_l3b.soft_name, "l3gen");
701  sprintf(soft_id, "%d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, GITSHA);
702  strcpy(output_binfile->meta_l3b.soft_ver, soft_id);
703  if (strcmp(input->oformat, "netCDF4") == 0) {
704  ptime = unix2isodate(now(), 'G');
705  strcpy(output_binfile->meta_l3b.ptime, ptime);
706  } else {
707  strcpy(output_binfile->meta_l3b.ptime, ptime);
708 
709  }
710  strcpy(output_binfile->meta_l3b.proc_con, proc_con);
711  //update units attribute to match the output products
712  strcpy(output_binfile->meta_l3b.units,units_string);
713  // Some missions have suites with DOIs and keywords...
714 
715  if (input->suite[0]) {
716  const char* doiStr = getDOI(output_binfile->meta_l3b.mission, output_binfile->meta_l3b.sensor, "L3B",
717  input->suite,
718  l1_input->pversion);
719  if (doiStr) {
720  strcpy(output_binfile->meta_l3b.doi, doiStr);
721  } else {
722  strcpy(output_binfile->meta_l3b.doi, "");
723  strcpy(output_binfile->meta_l3b.keywords, "");
724  }
725  const char* keywordStr = getGCMDKeywords(input->suite);
726  if (keywordStr) {
727  strcpy(output_binfile->meta_l3b.keywords, keywordStr);
728  } else {
729  strcpy(output_binfile->meta_l3b.doi, "");
730  strcpy(output_binfile->meta_l3b.keywords, "");
731  }
732  } else {
733  //if suite is somehow NOT set, clear it out as it's better than lying
734  // since we copy from the source
735  strcpy(output_binfile->meta_l3b.doi, "");
736  strcpy(output_binfile->meta_l3b.keywords, "");
737  }
738 
739  // Close files and free memory
740  if (atLeastOne == false) {
741  cout << "No valid bins to output!" << endl << "...seems a selected product may have resulted in 100% PRODFAIL..." << endl;
742  mainReturnCode = 110; // no bins filled
743  }
744  output_binfile->close();
745  delete(output_binfile);
746  input_binfile->close();
747  delete(input_binfile);
748 
749  free(fullprodlist);
750 
751  for (i = 0; i < nprods_in; i++)
752  free(inData[i]);
753  free(inData);
754 
755  free(outMask);
756 
757  for (i = 0; i < nprods_out; i++) {
758  free(outData[i]);
759  free(tmpData[i]);
760  }
761  free(outData);
762  free(tmpData);
763 
764  free_l1(l1rec);
765  free_l2(l2rec);
766  free(l1rec);
767  free(l2rec);
768  // free input internals
769  for(i=0;i<input->fctl.nfilt; i++)
770  free(input->fctl.f[i].kernel);
771  free(input->gsm_aphs);
772  free(input->gsm_aphw);
773  free(input->giop_wave);
774  free(input->giop_rrs_unc);
775  free(input->gain_unc);
776  free(input->taua);
777  free(input->vcal_nLw);
778  free(input->vcal_Lw);
779  free(input->lt_noise_scale);
780  free(input->bias_frac);
781  free(input);
782 
783  free(rrs_bindex);
784  free(rrs_windex);
785  free(nlw_bindex);
786  free(nlw_windex);
787 
788  cout << "Processing Complete at " << ptime << endl << endl;
789 
790  return (mainReturnCode);
791 }
792 
char * ydhmsf(double dtime, char zone)
Definition: ydhmsf.c:12
virtual int64_t get_bin_num(int kbin)=0
#define L1_MAXPROD
Definition: filehandle.h:20
virtual int get_nobs(int kbin)=0
virtual void bin2latlon(int64_t bin_num, float &lat, float &lon)
Definition: hdf_bin.h:80
int32 l1file(int32 sdfid, int32 *nsamp, int32 *nscans, int16 *dtynum)
Definition: l1stat_chk.c:586
#define MAX(A, B)
Definition: swl0_utils.h:26
integer, parameter int16
Definition: cubeio.f90:3
void bindex_set(int32_t wave[], int nwave, int dwave_vswir)
Definition: windex.c:15
char product_name[SM_ATTRSZ]
Definition: meta_l3b.h:16
#define MIN(x, y)
Definition: rice.h:169
#define EXIT_SUCCESS
Definition: GEO_basic.h:72
char units[MD_ATTRSZ]
Definition: meta_l3b.h:28
void freeProductInfo(productInfo_t *info)
int j
Definition: decode_rs.h:73
const char * getGCMDKeywords(const char *suite)
int32_t day
int msl12_input(int argc, char *argv[], const char *progName, filehandle *l1file)
Definition: msl12_input.c:4201
virtual int readSums(float *sums, int32_t nbins_to_read, int iprod)=0
void free_l2(l2str *l2rec)
Definition: alloc_l2.c:7
#define FLAGMASK
Definition: main_l3gen.cpp:21
virtual void setProductList(int numProducts, char *prodNames[])
Definition: bin_io.cpp:2807
char infiles[LG_ATTRSZ]
Definition: meta_l3b.h:38
#define VERSION_MINOR
Definition: version.h:2
#define NULL
Definition: decode_rs.h:63
void filehandle_init(filehandle *file)
char mission[SM_ATTRSZ]
Definition: meta_l3b.h:21
hdf_bin * openBinObject(const char *binFileName)
Definition: bin_io.cpp:32
read l1rec
char keywords[SM_ATTRSZ]
Definition: meta_l3b.h:55
#define NBINREAD
Definition: main_l3gen.cpp:20
void load_l3file_handle(int sensorID, int filenum, filehandle *file)
Definition: main_l3gen.cpp:35
virtual int create(const char *l3b_filename, int32_t nrows)=0
char input_parms[LG_ATTRSZ]
Definition: meta_l3b.h:36
const char * sensorId2PlatformName(int sensorId)
Definition: sensorInfo.c:226
#define GITSHA
Definition: version.h:4
float * lat
#define VERSION_PATCH
Definition: version.h:3
int syear
Definition: l1_czcs_hdf.c:15
void msl12_input_init()
Definition: msl12_input.c:485
virtual int close()=0
void load_input_filehandle(filehandle *l1file)
Definition: main_l3gen.cpp:48
bool active_data_prod[MAXNVDATA]
Definition: hdf_bin.h:121
virtual int64_t get_beg()=0
virtual int copy_binlist(int src, int dest)=0
int l2gen_usage(const char *prog)
Definition: msl12_input.c:4254
virtual int get_nscenes(int kbin)=0
int32_t nobs
Definition: atrem_cor.h:93
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 VERSION_MAJOR
Definition: version.h:1
def mtime(the_file)
Definition: ProcUtils.py:344
int sday
Definition: l1_czcs_hdf.c:15
int32_t prodlist(int32_t sensorID, int32_t evalmask, const char *inprod, const char *defprod, char outprod[L1_MAXPROD][32])
virtual int get_ext()=0
virtual int query()
Definition: bin_io.cpp:2764
bool hasNoext
Definition: hdf_bin.h:127
char sensor[SM_ATTRSZ]
Definition: meta_l3b.h:23
int alloc_l2(l1str *l1rec, l2str *l2rec)
Definition: alloc_l2.c:17
void sunangs_(int *, int *, float *, float *, float *, float *, float *)
double endTime
Definition: meta_l3b.h:40
virtual int set_weights(int offset, float weights)=0
virtual int copymeta(int32_t nfiles, Hdf::hdf_bin *input_binfile[])
Definition: bin_io.cpp:2874
productInfo_t * allocateProductInfo()
const char * getFileFormatName(const char *str)
virtual int64_t get_basebin(int irow)
Definition: hdf_bin.h:76
int32_t nrows
Definition: hdf_bin.h:119
virtual int32_t nprod()
Definition: hdf_bin.h:108
void cdata_()
void get_iops(l2str *l2rec, int32_t iop_opt)
Definition: convl12.c:113
l1_input_t * l1_input
Definition: l1_options.c:9
#define L1_PRODSTRLEN
Definition: filehandle.h:19
#define FATAL_ERROR
Definition: swl0_parms.h:5
meta_l3bType meta_l3b
Definition: hdf_bin.h:131
int32 nrows
void init_l2(l2str *l2rec, int32_t nbands)
Definition: init_l2.c:11
void unix2yds(double usec, short *year, short *day, double *secs)
bool isCDF4
Definition: hdf_bin.h:125
virtual int incNumRec(int n_write)=0
virtual int writeSums(float *sums, int32_t nbins_to_write, const char *prodname)=0
int main(int argc, char *argv[])
Definition: main_l3gen.cpp:117
virtual int setDataPtr(int nbins_to_read)=0
void free_l1(l1str *l1rec)
Definition: alloc_l1.c:6
#define basename(s)
Definition: l0chunk_modis.c:29
#define WRITE
Definition: create_Vdata.c:7
int findProductInfo(const char *productName, int sensorId, productInfo_t *info)
char doi[SM_ATTRSZ]
Definition: meta_l3b.h:54
instr * input
Definition: main_l3gen.cpp:111
const char * getDOI(const char *platform, const char *sensor, const char *level, const char *suite, const char *version)
Definition: getDOI.cpp:16
#define BAD_FLT
Definition: jplaeriallib.h:19
void init_l1(l1str *l1rec)
Definition: init_l1.c:11
float get_default_chl(l2str *l2rec, float Rrs[])
Definition: get_chl.c:392
virtual int get_prodname(int iprod, char *prodname)
Definition: bin_io.cpp:2802
char proc_con[MD_ATTRSZ]
Definition: meta_l3b.h:35
void load_l12(l2str *l2rec)
Definition: main_l3gen.cpp:83
char * getProductNameFull(productInfo_t *info)
int32_t nbands
const char * sensorId2SensorName(int sensorId)
Definition: sensorInfo.c:198
#define MD_ATTRSZ
Definition: meta_l3b.h:8
virtual int inc_nobs(int offset, int nobs)=0
double startTime
Definition: meta_l3b.h:39
int32_t iscan
char soft_ver[SM_ATTRSZ]
Definition: meta_l3b.h:33
void * prodgen(l2prodstr *p, l2str *l2rec)
Definition: prodgen.c:89
u5 which has been done in the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT production Changes from v6 which may affect scientific the sector rotation may actually occur during one of the scans earlier than the one where it is first reported As a the b1 values are about the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT to fill pixels affected by dead subframes with a special value Output the metadata of noisy and dead subframe Dead Subframe EV and Detector Quality Flag2 Removed the function call of Fill_Dead_Detector_SI to stop interpolating SI values for dead but also for all downstream products for science test only Changes from v5 which will affect scientific to conform to MODIS requirements Removed the Mixed option from the ScanType in the code because the L1A Scan Type is never Mixed Changed for ANSI C compliance and comments to better document the fact that when the HDF_EOS metadata is stricly the and products are off by and in the track respectively Corrected some misspelling of RCS swir_oob_sending_detector to the Reflective LUTs to enable the SWIR OOB correction detector so that if any of the sending detectors becomes noisy or non near by good detectors from the same sending band can be specified as the substitute in the new look up table Code change for adding an additional dimension of mirror side to the Band_21_b1 LUT to separate the coefficient of the two mirror sides for just like other thermal emissive so that the L1B code can calibrate Band scan to scan with mirror side dependency which leads better calibration result Changes which do not affect scientific when the EV data are not provided in this Crosstalk Correction will not be performed to the Band calibration data Changes which do not affect scientific and BB_500m in L1A Logic was added to turn off the or to spatial aggregation processes and the EV_250m_Aggr1km_RefSB and EV_500m_Aggr1km_RefSB fields were set to fill values when SDSs EV_250m and EV_500m are absent in L1A file Logic was added to skip the processing and turn off the output of the L1B QKM and HKM EV data when EV_250m and EV_500m are absent from L1A In this the new process avoids accessing and reading the and L1A EV skips and writing to the L1B and EV omits reading and subsampling SDSs from geolocation file and writing them to the L1B and omits writing metadata to L1B and EV and skips closing the L1A and L1B EV and SDSs Logic was added to turn off the L1B OBC output when the high resolution OBC SDSs are absent from L1A This is accomplished by skipping the openning the writing of metadata and the closing of the L1B OBC hdf which is Bit in the scan by scan bit QA has been changed Until now
Definition: HISTORY.txt:361
char * unix2isodate(double dtime, char zone)
Definition: unix2isodate.c:10
This should be set to the NetCDF standard name if exists for this product Create a function that computes your product edit get_myprod c add prototype to l12_proto h add get_myprod c to add_executable for l2gen and l3gen in CMakeLists txt Add an entry to the output routine to call your function edit prodgen c edit function prodgen() case CAT_myprod pbuf
const char * sensorId2InstrumentName(int sensorId)
Definition: sensorInfo.c:212
bool isHDF5
Definition: hdf_bin.h:124
int windex(float wave, float twave[], int ntwave)
Definition: windex.c:73
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)
void l3gen_usage(char *prog)
Definition: main_l3gen.cpp:31
int16_t * nscenes
Definition: l2bin.cpp:86
float * lon
virtual int set_bin_num(int offset, int64_t bin_num)=0
char ptime[SM_ATTRSZ]
Definition: meta_l3b.h:34
virtual int clear_binlist()=0
virtual int read(char *product_list)
Definition: bin_io.cpp:358
int32_t alloc_l1(filehandle *l1file, l1str *l1rec)
Definition: alloc_l1.c:15
int32_t rdsensorinfo(int32_t, int32_t, const char *, void **)
Definition: rdsensorinfo.c:69
#define BANDW
Definition: l1.h:52
for(i=0;i< NROOTS;i++) s[i]
Definition: decode_rs.h:85
virtual int readBinIndex(int row_num_to_read)=0
l2prod offset
virtual int readBinList(int nbins_to_read)=0
int loadl1(filehandle *l1file, l1str *l1rec)
Definition: loadl1.c:201
char sensor_name[SM_ATTRSZ]
Definition: meta_l3b.h:19
int i
Definition: decode_rs.h:71
void get_f0_thuillier_ext(int32_t wl, int32_t width, float *f0)
Definition: get_f0.c:137
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 sensorID[MAXNFILES]
Definition: l2bin.cpp:97
virtual int inc_nscenes(int offset, int nscenes)=0
Hdf::binListStruct blstr
Definition: main_l3gen.cpp:29
char soft_name[SM_ATTRSZ]
Definition: meta_l3b.h:32
int npix
Definition: get_cmp.c:27
uint32_t deflate
Definition: hdf_bin.h:129
float p[MODELMAX]
Definition: atrem_corl1.h:131
virtual float get_weights(int kbin)=0
virtual int writeBinList(int32_t nbins_to_write)=0
@ FT_L3BIN
Definition: filetype.h:24
int32_t get_l2prod_index(const l2_prod &l2, const char *prodname)
Definition: l2bin.cpp:345