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 #include "l12_proto.h"
24 
25 
26 using namespace std;
27 
29 
30 void l3gen_usage(char *prog) {
31  l2gen_usage("l3gen");
32 }
33 
34 void load_l3file_handle(int sensorID, int filenum, filehandle *file) {
35  strcpy(file->name, (const char *) input->ofile[filenum]);
36  strcpy(file->l2prod, (const char *) input->l2prod[filenum]);
37  strcpy(file->def_l2prod, input->def_l2prod[filenum]);
38 
39  file->format = FT_L3BIN;
40  file->mode = WRITE;
41  file->sensorID = sensorID;
42 
43  file->tot_prod = prodlist(file->sensorID, l1_input->evalmask, file->l2prod,
44  file->def_l2prod, file->l2_prod_names);
45 }
46 
47 void load_input_filehandle(filehandle *l1file) {
48  int32 sensorID = l1file->sensorID;
49  int32 evalmask = l1_input->evalmask;
50 
51  l1file->nbands = rdsensorinfo(sensorID, evalmask, NULL, NULL);
52  l1file->nbandsir = rdsensorinfo(sensorID, evalmask, "NbandsIR", NULL);
53  l1file->ndets = 1;
54 
55  rdsensorinfo(sensorID, evalmask, "Bindx", (void **) &l1file->bindx);
56  rdsensorinfo(sensorID, evalmask, "Lambda", (void **) &l1file->iwave);
57  rdsensorinfo(sensorID, evalmask, "fwave", (void **) &l1file->fwave);
58  rdsensorinfo(sensorID, evalmask, "Fobar", (void **) &l1file->Fobar);
59  rdsensorinfo(sensorID, evalmask, "Tau_r", (void **) &l1file->Tau_r);
60  rdsensorinfo(sensorID, evalmask, "k_oz", (void **) &l1file->k_oz);
61  rdsensorinfo(sensorID, evalmask, "k_no2", (void **) &l1file->k_no2);
62  rdsensorinfo(sensorID, evalmask, "aw", (void **) &l1file->aw);
63  rdsensorinfo(sensorID, evalmask, "bbw", (void **) &l1file->bbw);
64 
65  bindex_set(l1file->iwave, l1file->nbands + l1file->nbandsir, BANDW);
66 
67  if ((l1file->Fonom = (float*) calloc(l1file->nbands, sizeof (float))) == NULL) {
68  printf("-E- (%s, %d) Cannot allocate space for l1file->Fonom\n", __FILE__, __LINE__);
69  exit(EXIT_FAILURE);
70  }
71  int i;
72  for (i = 0; i < l1file->nbands; i++) {
73  if (l1_input->outband_opt >= 2) {
74  get_f0_thuillier_ext(l1file->iwave[i], BANDW, l1file->Fonom + i);
75  } else {
76  l1file->Fonom[i] = l1file->Fobar[i];
77  }
78  }
79 
80 }
81 
82 void load_l12(l2str *l2rec) {
83  int32 iw;
84 
85  l1str* l1rec = l2rec->l1rec;
86  filehandle* l1file = l1rec->l1file;
87  int32 nbands = l1file->nbands;
88 
89  //memset(l1rec->data, 0, l1rec->length);
90  //memset(l2rec->data, 0, l2rec->length);
91 
92  for (iw = 0; iw < nbands; iw++) {
93  l1rec->Fo[iw] = l1file->Fobar[iw]; // for the moment
94  }
95 
96  l1rec->tilt = 0.0;
97  l1rec->mside = 0;
98  l1rec->detnum = 0;
99 
100  int ip;
101  for (ip = 0; ip < l1rec->npix; ip++) {
102  l1rec->pixnum[ip] = 0;
103  l1rec->alpha[ip] = 0.0;
104  l1rec->flags[ip] = 0;
105  l1rec->mask[ip] = 0;
106  }
107 
108 }
109 
110 // --------------------------------------------------------------------
111 // main
112 // --------------------------------------------------------------------
113 
114 int main(int argc, char* argv[]) {
115  static l1str *l1rec; // generic level-1b scan structure
116  static l2str *l2rec; // generic level-2 scan structure
117  static filehandle ifile; // input file handle
118  static filehandle ofile; // output file handle
119  int iprod;
120 
121  char *ptime = ydhmsf(now(), 'G');
122  double start_time = now();
123 
124  int16 year, day;
125  int32_t syear;
126  int32_t sday;
127  double dsec;
128  double mtime;
129 
130  char soft_id[200];
131  float gmt;
132  float solz;
133  float sola;
134  char buf[FILENAME_MAX];
135 
136  int i;
137  int ip;
138  int offset;
139  int64_t bin_num;
140  int nobs;
141  int nscenes;
142  int nwrite;
143  static bool atLeastOne = false;
144  int mainReturnCode = EXIT_SUCCESS;
145 
146  char units_string[MD_ATTRSZ];
147 
148  if (argc == 1) {
149  l3gen_usage(argv[0]);
150  return EXIT_SUCCESS;
151  }
152 
153  // see if help on command line
154  for (i = 0; i < argc; i++) {
155  if ((strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "-help") == 0)) {
156  l3gen_usage(argv[0]);
157  return EXIT_SUCCESS;
158  }
159  }
160 
161  setvbuf(stdout, NULL, _IOLBF, 0);
162  setvbuf(stderr, NULL, _IOLBF, 0);
163 
164  // Initialize file handles
166 
167  // cdata_();
170 
171  // Parse input parameters
172  if (msl12_input(argc, argv, "l3gen", &ifile) != 0) {
173  printf("-E- %s: Error parsing input parameters.\n", argv[0]);
174  exit(1);
175  }
176 
178 
179  char proc_con[2048];
180  strcpy(proc_con, basename(argv[0]));
181  for (i = 1; i < argc; i++) {
182  strcat(proc_con, " ");
183  strcat(proc_con, argv[i]);
184  }
185 
186  // Transfer input info to file handles
187  load_l3file_handle(ifile.sensorID, 0, &ofile);
188 
189  // Build output product list
190 
191  cout << endl << "The following products will be included in " << ofile.name
192  << endl;
193  int32 nprods_out = ofile.tot_prod;
194  char prodlist_out[L1_PRODSTRLEN] = "";
195  for (iprod = 0; iprod < ofile.tot_prod; iprod++) {
196  cout << iprod + 1 << " " << ofile.l2_prod_names[iprod] << endl;
197  strcat(prodlist_out, ofile.l2_prod_names[iprod]);
198  if (iprod < ofile.tot_prod - 1)
199  strcat(prodlist_out, ",");
200  }
201 
202  // Open input binfile and get full input product list
203 
204  static Hdf::hdf_bin *input_binfile;
205  const char *inputfile;
206 
207  inputfile = input->ifile[0];
208  input_binfile = Hdf::openBinObject(inputfile);
209 
210  int len = input_binfile->query();
211  char *fullprodlist = (char *) malloc(len);
212  input_binfile->query(fullprodlist);
213  int nrows = input_binfile->nrows;
214 
215  // Get input bin dimension
216  int32 npix = NBINREAD;
217 
218  // Get mean time
219  mtime = (input_binfile->meta_l3b.startTime + input_binfile->meta_l3b.endTime) / 2.0;
220 
221  unix2yds(mtime, &year, &day, &dsec);
222  //yes, silly, but easier than fixing the various routines that need either a 16 or 32bit int for year/day
223  syear = year;
224  sday = day;
225 
226  // Allocate memory for L1 and L2 scan data (the L2 record shares
227  // space with the L1 record, hence we need to allocate both)
228  l1rec = (l1str*) malloc(sizeof (l1str));
229  l2rec = (l2str*) malloc(sizeof (l2str));
230 
231  ifile.npix = npix;
232  ifile.nscan = 1;
233  if (alloc_l1(&ifile, l1rec) == 0) {
234  printf("-E- %s: Unable to allocate L1 record.\n", argv[0]);
235  exit(1);
236  }
237  if (alloc_l2(l1rec, l2rec) == 0) {
238  printf("-E- %s: Unable to allocate L2 record.\n", argv[0]);
239  exit(1);
240  }
241 
242  // Add meta-data to L1 and L2 structures - use a single pixel just to get things
243  // started - load_l12 will be called for each bin row with an appropriate # of pixels
244  load_l12(l2rec);
245 
246  // Build input product request list
247 
248  int32 n_vvv = MIN(windex(700., ifile.fwave, ifile.nbands) + 1, ifile.nbands);
249  char prodstr[L1_PRODSTRLEN] = "";
250 
251  // what we have
252 
253  char **prodlist_in;
254  int32 nprods_in = input_binfile->query(&prodlist_in);
255 
256  // what we want
257 
258  char prodlist_wt[L1_MAXPROD][32];
259  int32 nprods_wt = prodlist(ifile.sensorID, l1_input->evalmask,
260  "Rrs_vvv nLw_vvv Rrs_vc_vvv solz sola senz sena relaz", "",
261  prodlist_wt);
262 
263  enum geo_order {
264  SOLZ, SOLA, SENZ, SENA, RELAZ
265  };
266 
267  // what we have that we want
268 
269  int32 *rrs_bindex;
270  int32 *rrs_windex;
271  int32 n_rrs = 0;
272  int32 *nlw_bindex;
273  int32 *nlw_windex;
274  int32 n_nlw = 0;
275  int32 geo_bindex[5];
276  int32 geo_windex[5];
277  int32 n_geo = 0;
278  int32 have_solz = 0;
279  int32 have_sola = 0;
280  int32 have_sena = 0;
281  int32 have_relaz = 0;
282 
283  if ((rrs_bindex = (int32 *) malloc(ifile.nbands * sizeof (int32))) == NULL) {
284  printf("-E- %s: Error allocating memory to the input data array.\n",
285  argv[0]);
286  exit(FATAL_ERROR);
287  }
288  if ((rrs_windex = (int32 *) malloc(ifile.nbands * sizeof (int32))) == NULL) {
289  printf("-E- %s: Error allocating memory to the input data array.\n",
290  argv[0]);
291  exit(FATAL_ERROR);
292  }
293  if ((nlw_bindex = (int32 *) malloc(ifile.nbands * sizeof (int32))) == NULL) {
294  printf("-E- %s: Error allocating memory to the input data array.\n",
295  argv[0]);
296  exit(FATAL_ERROR);
297  }
298  if ((nlw_windex = (int32 *) malloc(ifile.nbands * sizeof (int32))) == NULL) {
299  printf("-E- %s: Error allocating memory to the input data array.\n",
300  argv[0]);
301  exit(FATAL_ERROR);
302  }
303 
304  cout << endl << "Checking input for desired products: " << endl;
305  iprod = 0;
306  for (int32 iwant = 0; iwant < nprods_wt; iwant++) {
307  for (int32 ihave = 0; ihave < nprods_in; ihave++) {
308  if (strcmp(prodlist_in[ihave], prodlist_wt[iwant]) == 0) {
309  strcat(prodstr, prodlist_in[ihave]);
310  strcat(prodstr, ",");
311  cout << "found " << prodlist_wt[iwant] << endl;
312  if (iwant < n_vvv) {
313  rrs_bindex[n_rrs] = iprod; // posiiton in bin read
314  rrs_windex[n_rrs] = iwant; // position in sensor wavelengths
315  n_rrs++;
316  iprod++;
317  } else if (iwant < n_vvv * 2) {
318  nlw_bindex[n_nlw] = iprod; // positon in bin read
319  nlw_windex[n_nlw] = iwant - n_vvv; // position in sensor wavelengths
320  n_nlw++;
321  iprod++;
322  } else if (iwant < n_vvv * 3) { // Rrs_vc products overwriting Rrs
323  rrs_bindex[n_rrs] = iprod; // posiiton in bin read
324  rrs_windex[n_rrs] = iwant - 2 * n_vvv; // position in sensor wavelengths
325  n_rrs++;
326  iprod++;
327  } else {
328  geo_bindex[n_geo] = iprod;
329  geo_windex[n_geo] = iwant - 3 * n_vvv;
330  switch (geo_windex[n_geo]) {
331  case SOLZ:
332  have_solz = 1;
333  break;
334  case SOLA:
335  have_sola = 1;
336  break;
337  case SENA:
338  have_sena = 1;
339  break;
340  case RELAZ:
341  have_relaz = 1;
342  break;
343  }
344  n_geo++;
345  iprod++;
346  }
347  break;
348  }
349  }
350  }
351  nprods_in = iprod;
352 
353  // remove trailing comma
354  len = strlen(prodstr);
355  prodstr[len - 1] = '\0';
356 
357  // Allocate data arrays and bin list and masking flag
358  float **outData;
359  float **tmpData;
360  float **inData;
361  if ((inData = (float **) malloc(nprods_in * sizeof (float *))) == NULL) {
362  printf("-E- %s: Error allocating memory to the input data array.\n",
363  argv[0]);
364  exit(FATAL_ERROR);
365  }
366  if ((outData = (float **) malloc(nprods_out * sizeof (float *))) == NULL) {
367  printf("-E- %s: Error allocating memory to the output data array.\n",
368  argv[0]);
369  exit(FATAL_ERROR);
370  }
371  if ((tmpData = (float **) malloc(nprods_out * sizeof (float *))) == NULL) {
372  printf("-E- %s: Error allocating memory to the temp data array.\n",
373  argv[0]);
374  exit(FATAL_ERROR);
375  }
376  for (i = 0; i < nprods_in; i++) {
377  if ((inData[i] = (float *) calloc(2 * npix, sizeof (float))) == NULL) {
378  printf("-E- %s: Error allocating memory to the output data array.\n",
379  argv[0]);
380  exit(FATAL_ERROR);
381  }
382  }
383  for (i = 0; i < nprods_out; i++) {
384  if ((outData[i] = (float *) calloc(2 * npix, sizeof (float))) == NULL) {
385  printf(
386  "-E- %s: Error allocating memory to the output data array.\n",
387  argv[0]);
388  exit(FATAL_ERROR);
389  }
390  if ((tmpData[i] = (float *) calloc(npix, sizeof (float))) == NULL) {
391  printf(
392  "-E- %s: Error allocating memory to the output data array.\n",
393  argv[0]);
394  exit(FATAL_ERROR);
395  }
396  }
397  char *outMask = (char *) calloc(npix, sizeof (char));
398 
399  // set up the bin file reading for the products we need
400  input_binfile->read(prodstr);
401 
402  /* Create output file */
403  /* ------------------ */
404  Hdf::hdf_bin *output_binfile;
405 
406  /*
407  * If the input structure does not set the output format,
408  * make the output format match the input L3 format
409  */
410  if (getFileFormatName(input->oformat) == NULL) {
411  if (input_binfile->isHDF5) {
412  strcpy(input->oformat, "HDF5");
413  } else if (input_binfile->isCDF4) {
414  strcpy(input->oformat, "netCDF4");
415  } else {
416  strcpy(input->oformat, "HDF4");
417  }
418  }
419 
420  if (strcmp(input->oformat, "HDF4") == 0) {
421  output_binfile = new Hdf::hdf4_bin;
422  output_binfile->hasNoext = true;
423  }
424  if (strcmp(input->oformat, "HDF5") == 0)
425  output_binfile = new Hdf::hdf5_bin;
426  if (strcmp(input->oformat, "netCDF4") == 0)
427  output_binfile = new Hdf::cdf4_bin;
428 
429  output_binfile->deflate = input->deflate;
430 
431  strcpy(output_binfile->meta_l3b.product_name, ofile.name);
432  strncpy(output_binfile->meta_l3b.ptime, ptime, 16);
433  strcpy(output_binfile->meta_l3b.proc_con, proc_con);
434  strcpy(output_binfile->meta_l3b.input_parms, l1_input->input_parms);
435 
436  char* tmpProdNames[ofile.tot_prod];
437  for (int i = 0; i < ofile.tot_prod; i++) {
438  tmpProdNames[i] = ofile.l2_prod_names[i];
439  }
440  output_binfile->setProductList(ofile.tot_prod, tmpProdNames);
441  output_binfile->create(ofile.name, input_binfile->nrows);
442 
443  // Begin processing
444  for (int32 iscan = 0; iscan < nrows; iscan++) {
445  if (iscan % 50 == 0) {
446  int secs = (int) now() - start_time;
447  cout << "Reading row " << iscan << " of " << nrows << " after " << secs << " seconds" << endl;
448  }
449  // Read the inputs
450  // Get basebin and numbin for this input row
451  int64_t basebin = input_binfile->get_basebin(iscan);
452  input_binfile->readBinIndex(iscan);
453  int ext = input_binfile->get_ext();
454  int64_t beg = input_binfile->get_beg();
455  // if the row has no filled bins, skip it
456  if (beg == 0)
457  continue;
458 
459  input_binfile->readBinList(ext);
460 
461  // fill the input data array with the necessary input data
462  i = 0;
463  for (int j = 0; j < input_binfile->nprod(); j++) {
464 
465  if (input_binfile->active_data_prod[j] == true) {
466  input_binfile->get_prodname(j, buf);
467  if (strcmp(prodlist_in[j], buf) == 0) {
468  input_binfile->readSums(inData[i], ext, j);
469  i++;
470  }
471  }
472  }
473  if (input_binfile->isHDF5 || input_binfile->isCDF4)
474  input_binfile->setDataPtr(ext);
475 
476 
477  // Stuff the L2 record
478  // only process as many pixels as the row as filled bins
479  l1rec->npix = ext;
480  ifile.npix = ext;
481  ifile.epix = ext - 1;
482  ifile.terrain_corrected = 1;
483 
484  memset(outMask, '\0', npix);
485  init_l1(l1rec);
486  init_l2(l2rec, ifile.nbands);
487 
488  load_l12(l2rec);
489 
490  l1rec->iscan = iscan;
491  l1rec->scantime = mtime;
492 
493  // Fill in the l1/2 structures with data from input bin file
494  // nLw, Rrs, geometries - if available.
495  for (ip = 0; ip < ext; ip++) {
496  float weight = input_binfile->get_weights(ip);
497  int32 ipw;
498  float lat;
499  float lon;
500  float flat, flon;
501 
502  bin_num = input_binfile->get_bin_num(ip);
503  input_binfile->bin2latlon(bin_num, lat, lon);
504  l1rec->lon[ip] = lon;
505  l1rec->lat[ip] = lat;
506  l1rec->nobs[ip] = input_binfile->get_nobs(ip);
507  for (int32 iw = 0; iw < n_nlw; iw++) {
508  ipw = ip * ifile.nbands + nlw_windex[iw];
509  l2rec->nLw[ipw] = inData[nlw_bindex[iw]][2 * ip] / weight;
510  l2rec->Rrs[ipw] = MAX(l2rec->nLw[ipw] / ifile.Fonom[iw], BAD_FLT);
511  }
512  for (int32 iw = 0; iw < n_rrs; iw++) {
513  ipw = ip * ifile.nbands + rrs_windex[iw];
514  l2rec->Rrs[ipw] = inData[rrs_bindex[iw]][2 * ip] / weight;
515  l2rec->nLw[ipw] = MAX(l2rec->Rrs[ipw] * ifile.Fonom[iw], BAD_FLT);
516  }
517  l1rec->solz[ip] = 0.0;
518  l1rec->sola[ip] = 0.0;
519  l1rec->senz[ip] = 0.0;
520  l1rec->sena[ip] = 90.0;
521  l1rec->delphi[ip] = 90.0;
522 
523  for (int32 iw = 0; iw < n_geo; iw++) {
524  switch (geo_windex[iw]) {
525  case SOLZ:
526  l1rec->solz[ip] = inData[geo_bindex[iw]][2 * ip] / weight;
527  break;
528  case SOLA:
529  l1rec->sola[ip] = inData[geo_bindex[iw]][2 * ip] / weight;
530  break;
531  case SENZ:
532  l1rec->senz[ip] = inData[geo_bindex[iw]][2 * ip] / weight;
533  break;
534  case SENA:
535  l1rec->sena[ip] = inData[geo_bindex[iw]][2 * ip] / weight;
536  break;
537  case RELAZ:
538  l1rec->delphi[ip] = inData[geo_bindex[iw]][2 * ip] / weight;
539  break;
540  }
541  }
542  if (!have_solz) {
543  // assume noon orbit
544  flon = l1rec->lon[ip];
545  flat = l1rec->lat[ip];
546  gmt = 12 - lon / 15;
547  sunangs_(&syear, &sday, &gmt, &flon, &flat, &solz, &sola);
548  l1rec->solz[ip] = solz;
549  l1rec->sola[ip] = sola;
550  }
551  if (have_sola && have_sena && !have_relaz) {
552  l1rec->delphi[ip] = l1rec->sena[ip] - 180.0 - l1rec->sola[ip];
553  if (l1rec->delphi[ip] < -180)
554  l1rec->delphi[ip] += 360.0;
555  } else if (!have_sola && !have_sena && have_relaz) {
556  l1rec->sena[ip] = 90.0;
557  l1rec->sola[ip] = l1rec->sena[ip] - 180.0
558  - l1rec->delphi[ip];
559  if (l1rec->sola[ip] < -180)
560  l1rec->sola[ip] += 360.0;
561  }
562  }
563 
564  // Add ancillary, Rayleigh, etc.
565  loadl1(&ifile, l1rec);
566 
567  // clear out the masks
568  for (ip = 0; ip < ext; ip++)
569  l1rec->mask[ip] = 0;
570 
571  // Add a default chl
572 
573  for (ip = 0; ip < ext; ip++)
574  l2rec->chl[ip] = get_default_chl(l2rec, &l2rec->Rrs[ip * ifile.nbands]);
575 
576  // Add default inherent optical properties
577 
578  if (input->iop_opt > 0 && (input->proc_ocean != 0))
579  get_iops(l2rec, input->iop_opt);
580 
581  // Compute output products and store in temporary buffer
582 
583  for (iprod = 0; iprod < nprods_out; iprod++) {
584 
585  // get the product index record
586  for (i = 0; i < ext; i++)
587  tmpData[iprod][i] = BAD_FLT;
588 
589  l2prodstr *p;
590 
591  if ((p = get_l2prod_index(ofile.l2_prod_names[iprod],
592  ifile.sensorID, ifile.nbands + ifile.nbandsir, ext,
593  ifile.nscan, ifile.iwave)) == NULL) {
594  printf("-E- %s line %d: product index failure.\n", __FILE__,
595  __LINE__);
596  exit(1);
597  };
598 
599  // Compute or extract the product & copy to output buffer
600 
601  VOIDP pbuf = prodgen(p, l2rec);
602 
603  // build the units attribute string
604 
605  productInfo_t *p_info;
606  p_info = allocateProductInfo();
607 
608  if (!findProductInfo(ofile.l2_prod_names[iprod], ifile.sensorID, p_info)) {
609  printf("-E- product %s not found in XML product table\n",
610  ofile.l2_prod_names[iprod]);
611  exit(EXIT_FAILURE);
612  }
613 
614  if (iprod == 0){
615  strcpy(units_string,getProductNameFull(p_info));
616  strcat(units_string,":");
617  strcat(units_string,p->units);
618  }
619  else {
620  strcat(units_string,getProductNameFull(p_info));
621  strcat(units_string,":");
622  strcat(units_string,p->units);
623  }
624  if (iprod < nprods_out -1)
625  strcat(units_string,",");
626 
627  freeProductInfo(p_info);
628 
629  memcpy(tmpData[iprod], (float *) pbuf,
630  ext * sizeof (float));
631 
632  // Check flags and set masking
633 
634  for (ip = 0; ip < ext; ip++) {
635  if ((tmpData[iprod][ip] == BAD_FLT)
636  || (l1rec->flags[ip] & FLAGMASK) != 0) {
637  outMask[ip] = 1;
638  }
639  }
640 
641  }
642 
643  /* Write output */
644  /* ------------ */
645  output_binfile->clear_binlist();
646  nwrite = 0;
647 
648  for (ip = 0; ip < ext; ip++) {
649  if (!outMask[ip]) {
650  atLeastOne = true;
651  bin_num = input_binfile->get_bin_num(ip);
652  offset = bin_num - basebin;
653  output_binfile->set_bin_num(offset, bin_num);
654  nobs = input_binfile->get_nobs(ip);
655  output_binfile->inc_nobs(offset, nobs);
656  nscenes = input_binfile->get_nscenes(ip);
657  output_binfile->inc_nscenes(offset, nscenes);
658  output_binfile->set_weights(offset, 1);
659 
660  /* Loop over data products */
661  /* ----------------------- */
662  for (iprod = 0; iprod < nprods_out; iprod++) {
663  outData[iprod][2 * nwrite] = tmpData[iprod][ip];
664 
665  } /* iprod loop */
666  if (nwrite != offset)
667  output_binfile->copy_binlist(offset, nwrite);
668 
669  nwrite++;
670  }
671  } /* ip loop */
672 
673 
674  /* Write BinList & Data Products */
675  /* ----------------------------- */
676  if (nwrite > 0) {
677  output_binfile->writeBinList(nwrite);
678  for (iprod = 0; iprod < nprods_out; iprod++) {
679  strcpy(buf, ofile.l2_prod_names[iprod]);
680  output_binfile->writeSums(outData[iprod], nwrite, buf);
681  }
682 
683  if (strcmp(input->oformat, "HDF5") == 0
684  || strcmp(input->oformat, "netCDF4") == 0)
685  output_binfile->incNumRec(nwrite);
686  }
687  }
688 
689  output_binfile->copymeta(1, &input_binfile);
690  if (strcmp(input->oformat, "netCDF4")) {
691  strcpy(output_binfile->meta_l3b.sensor, sensorId2InstrumentName(ifile.sensorID));
692  } else {
693  strcpy(output_binfile->meta_l3b.sensor_name, sensorId2SensorName(ifile.sensorID));
694  }
695  strcpy(output_binfile->meta_l3b.mission, sensorId2PlatformName(ifile.sensorID));
696  strcpy(output_binfile->meta_l3b.infiles, basename((char *) input->ifile[0]));
697  strcpy(output_binfile->meta_l3b.soft_name, "l3gen");
698  sprintf(soft_id, "%d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, GITSHA);
699  strcpy(output_binfile->meta_l3b.soft_ver, soft_id);
700  if (strcmp(input->oformat, "netCDF4") == 0) {
701  ptime = unix2isodate(now(), 'G');
702  strcpy(output_binfile->meta_l3b.ptime, ptime);
703  } else {
704  strcpy(output_binfile->meta_l3b.ptime, ptime);
705 
706  }
707  strcpy(output_binfile->meta_l3b.proc_con, proc_con);
708  //update units attribute to match the output products
709  strcpy(output_binfile->meta_l3b.units,units_string);
710  // Some missions have suites with DOIs and keywords...
711 
712  strcpy(output_binfile->meta_l3b.doi, input->doi);
713  //if suite is somehow NOT set, clear it out as it's better than lying
714  // since we copy from the source
715  strcpy(output_binfile->meta_l3b.keywords, "");
716  if (input->suite[0]) {
717  const char* keywordStr = getGCMDKeywords(input->suite);
718  if (keywordStr) {
719  strcpy(output_binfile->meta_l3b.keywords, keywordStr);
720  }
721  }
722 
723  // Close files and free memory
724  if (atLeastOne == false) {
725  cout << "No valid bins to output!" << endl << "...seems a selected product may have resulted in 100% PRODFAIL..." << endl;
726  mainReturnCode = 110; // no bins filled
727  }
728  output_binfile->close();
729  delete(output_binfile);
730  input_binfile->close();
731  delete(input_binfile);
732 
733  free(fullprodlist);
734 
735  for (i = 0; i < nprods_in; i++)
736  free(inData[i]);
737  free(inData);
738 
739  free(outMask);
740 
741  for (i = 0; i < nprods_out; i++) {
742  free(outData[i]);
743  free(tmpData[i]);
744  }
745  free(outData);
746  free(tmpData);
747 
748  free_l1(l1rec);
749  free_l2(l2rec);
750  free(l1rec);
751  free(l2rec);
752  // free input internals
753  for(i=0;i<input->fctl.nfilt; i++)
754  free(input->fctl.f[i].kernel);
755  free(input->gsm_aphs);
756  free(input->gsm_aphw);
757  free(input->giop_wave);
758  free(input->giop_rrs_unc);
759  free(input->taua);
760  free(input->vcal_nLw);
761  free(input->vcal_Lw);
762  free(input);
763 
764  free(rrs_bindex);
765  free(rrs_windex);
766  free(nlw_bindex);
767  free(nlw_windex);
768 
769  cout << "Processing Complete at " << ptime << endl << endl;
770 
771  return (mainReturnCode);
772 }
773 
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:25
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:4359
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:34
virtual int create(const char *l3b_filename, int32_t nrows)=0
int32 nrows
char input_parms[LG_ATTRSZ]
Definition: meta_l3b.h:36
const char * sensorId2PlatformName(int sensorId)
Definition: sensorInfo.c:301
#define GITSHA
Definition: version.h:4
#define VERSION_PATCH
Definition: version.h:3
int syear
Definition: l1_czcs_hdf.c:15
void msl12_input_init()
Definition: msl12_input.c:495
virtual int close()=0
void load_input_filehandle(filehandle *l1file)
Definition: main_l3gen.cpp:47
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 L2GEN_PRODUCT_FILES in CMakeLists txt Add an entry to the output routine to call your function edit prodgen c edit function prodgen() case CAT_myprod pbuf
bool active_data_prod[MAXNVDATA]
Definition: hdf_bin.h:123
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:4414
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
instr * input
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:129
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 *)
Definition: sunangs.c:25
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:121
virtual int32_t nprod()
Definition: hdf_bin.h:110
void get_iops(l2str *l2rec, int32_t iop_opt)
Definition: convl12.c:118
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:133
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:127
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:114
virtual int setDataPtr(int nbins_to_read)=0
void free_l1(l1str *l1rec)
Definition: alloc_l1.c:7
#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
#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:679
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:82
char * getProductNameFull(productInfo_t *info)
int32_t nbands
const char * sensorId2SensorName(int sensorId)
Definition: sensorInfo.c:273
#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:101
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
const char * sensorId2InstrumentName(int sensorId)
Definition: sensorInfo.c:287
bool isHDF5
Definition: hdf_bin.h:126
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:30
int16_t * nscenes
Definition: l2bin.cpp:80
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:18
int32_t rdsensorinfo(int32_t, int32_t, const char *, void **)
Definition: rdsensorinfo.c:69
#define BANDW
Definition: l1.h:53
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:36
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:91
virtual int inc_nscenes(int offset, int nscenes)=0
Hdf::binListStruct blstr
Definition: main_l3gen.cpp:28
char soft_name[SM_ATTRSZ]
Definition: meta_l3b.h:32
int npix
Definition: get_cmp.c:28
uint32_t deflate
Definition: hdf_bin.h:131
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:109