OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
DDProcess.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * NAME: DDProcess.cpp
4  *
5  * DESCRIPTION: Process granule using selected algorithm.
6  *
7  * Created on: Aug 25, 2020
8  * Author: Sam Anderson
9  *
10  *******************************************************************************/
11 
12 #include <pugixml.hpp>
13 
14 #include <DDataset.hpp>
15 #include <DDProcess.h>
16 #include <DDSensor.h>
17 #include <DDOptions.h>
18 #include <DDAncillary.h>
19 #include "darktarget/DtAlgorithm.h"
20 #include "deepblue/DbAlgorithm.h"
21 
22 using namespace std;
23 using namespace pugi;
24 
25 const vector<string> DDProcess::out_groups = { "geolocation", "ancillary",
26  "observations", "geophysical_data", "statistics" };
27 
28 const map<string,dtype> DDProcess::input_names = {
29  {"cloud_mask", dtype::UBYTE},
30  {"land_water", dtype::UBYTE},
31  {"relative_azimuth", dtype::FLOAT},
32  {"solar_zenith", dtype::FLOAT},
33  {"sensor_zenith", dtype::FLOAT},
34  {"scattering_angle", dtype::FLOAT},
35  {"elevation", dtype::FLOAT},
36  {"wind_speed", dtype::FLOAT},
37  {"wind_direction", dtype::FLOAT},
38  {"water_vapor", dtype::FLOAT},
39  {"ozone", dtype::FLOAT},
40  {"surface_pressure", dtype::FLOAT},
41  {"chlorophyll", dtype::FLOAT},
42 };
43 
44 const map<string,dtype> DDProcess::dtdb_names = {
45  {"quality_flag", dtype::SHORT},
46  {"aerosol_type", dtype::SHORT},
47  {"l2_flags", dtype::UINT},
48  {"fmf_550", dtype::FLOAT},
49  {"angstrom", dtype::FLOAT},
50  {"ndvi", dtype::FLOAT},
51  {"residual_error", dtype::FLOAT},
52 };
53 
54 const map<string,rhot_band> DDProcess::rhot_band_names = {
55  {"rhot_410", rhot_band::W410}, // m01
56  {"rhot_445", rhot_band::W445}, // m02
57  {"rhot_490", rhot_band::W490}, // m03
58  {"rhot_550", rhot_band::W550}, // m04
59  {"rhot_670", rhot_band::W670}, // m05
60  {"rhot_865", rhot_band::W865}, // m07
61  {"rhot_1240", rhot_band::W1240}, // m08
62  {"rhot_1380", rhot_band::W1380}, // m09
63  {"rhot_1610", rhot_band::W1610}, // m10
64  {"rhot_2250", rhot_band::W2250}, // m11
65 };
66 
67 const map<string,aot_band> DDProcess::aot_band_names = {
68  {"aot_410", aot_band::W410}, // m01
69  {"aot_490", aot_band::W490}, // m03
70  {"aot_550", aot_band::W550}, // m04
71  {"aot_670", aot_band::W670}, // m05
72  {"aot_865", aot_band::W865}, // m07
73  {"aot_1240", aot_band::W1240}, // m08
74  {"aot_1610", aot_band::W1610}, // m10
75  {"aot_2250", aot_band::W2250}, // m11
76 };
77 
78 const map<string,srf_band> DDProcess::srf_band_names = {
79  {"surface_410", srf_band::W410}, // m01
80  {"surface_490", srf_band::W490}, // m03
81  {"surface_670", srf_band::W670}, // m05
82  {"surface_2250", srf_band::W2250}, // m11
83 };
84 
85 /**************************************************************************
86  * NAME: DDProcess()
87  *
88  * DESCRIPTION: Class Constructor
89  *
90  *************************************************************************/
92 {
93  lines_ = 0.0;
94  pixels_ = 0.0;
95  alg_ = algorithm::NOTHING;
96  instrument_ = SENSOR::NOTHING;
97  psensor_ = nullptr;
98  pancillary_ = nullptr;
99  pl_ = nullptr;
100  po_ = nullptr;
101  bday_ = true;
102  lprw_ = 1;
103  bglintmask_=true;
104  bcloudmask_=true;
105  bgascorrect_=true;
106 }
107 
108 /**************************************************************************
109  * NAME: ~DDProcess()
110  *
111  * DESCRIPTION: Class Destructor
112  *
113  *************************************************************************/
115 {
116  if (psensor_ != 0) {
117  delete psensor_;
118  psensor_ = 0L;
119  }
120  if (pancillary_ != 0) {
121  delete pancillary_;
122  pancillary_ = 0L;
123  }
124 }
125 
126 /**************************************************************************
127  * NAME: initialize()
128  *
129  * DESCRIPTION: Initializes data and object classes for granule
130  *
131  *************************************************************************/
133 {
134  int status = DTDB_SUCCESS;
135 
136  string salg = get_option(ALGORITHM);
137  if (salg == "darktarget") {
138  std::cerr << "DDProcess:: Algorithm Dark Target" << std::endl;
139  alg_ = algorithm::DARKTARGET;
140  } else if (salg == "deepblue") {
141  std::cerr << "DDProcess:: Algorithm Deep Blue" << std::endl;
142  alg_ = algorithm::DEEPBLUE;
143  } else {
144  std::cerr << "DDProcess:: Invalid algorithm, exiting ..." << std::endl;
145  return DTDB_FAIL;
146  }
147  status = query_granule();
148  if (status != DTDB_SUCCESS) {
149  cerr << "DDProcess:: Query granule failure" << endl;
150  return DTDB_FAIL;
151  } else if (!bday_) {
152  cerr << "DDProcess:: Night granule detected" << endl;
153  return DTDB_FAIL;
154  }
155  switch (instrument_) {
156  case SENSOR::POCI:
157  psensor_ = new POCI();
158  break;
159  case SENSOR::VIIRS:
160  psensor_ = new VIIRS();
161  break;
162  case SENSOR::NOTHING:
163  default:
164  cerr << "DDProcess:: Invalid sensor" << endl;
165  return DTDB_FAIL;
166  break;
167  }
168  pancillary_ = new DDAncillary();
169  if (alg_== algorithm::DARKTARGET) {
170  pl_ = new DtAlgLand();
171  po_ = new DtAlgOcean();
172  } else if (alg_== algorithm::DEEPBLUE) {
173  pl_ = new DbAlgLand();
174  po_ = new DbAlgOcean();
175  }
176  lprw_ = (size_t) get_option_int(INPUT_LINES_PER_RW);
177  lprw_ = (lprw_<3) ? 3 : lprw_;
178 
179  vector<string> products = pl_->get_products();
180  out_products.insert(out_products.end(), products.begin(), products.end());
181  products = po_->get_products();
182  out_products.insert(out_products.end(), products.begin(), products.end());
183 
184  return status;
185 }
186 
187 /**************************************************************************
188  * NAME: query_granule()
189  *
190  * DESCRIPTION: Read granule data essential for initialization
191  *
192  *************************************************************************/
194 {
195  int status = DTDB_SUCCESS;
196  string filepath = get_option(INPUT_L1B);
197 
198  if (!filepath.empty()) {
199  NcFile* nc_input;
200  try {
201  nc_input = new NcFile(filepath, NcFile::read );
202  }
203  catch( NcException& e) {
204  e.what();
205  cout << "DDProcess:: Failure opening L1B file" << endl;
206  return DTDB_FAIL;
207  }
208  string str;
209  multimap <string, NcGroupAtt> attributes = nc_input->getAtts(NcGroup::Current);
210  multimap <string, NcGroupAtt>::iterator it;
211  if ((it = attributes.find("instrument")) != attributes.end()) {
212  (it->second).getValues(str);
213  }
214  if (str.find("OCI") != string::npos) {
215  instrument_ = SENSOR::POCI;
216  } else if (str.find("VIIRS") != string::npos) {
217  instrument_ = SENSOR::VIIRS;
218  } else {
219  cout << "DDProcess:: Instrument not supported" << endl;
220  return DTDB_FAIL;
221  }
222  switch (instrument_) {
223  case SENSOR::VIIRS:
224  if ((it = attributes.find("DayNightFlag")) != attributes.end()) {
225  (it->second).getValues(str);
226  } else if((it = attributes.find("day_night_flag")) != attributes.end()) {
227  (it->second).getValues(str);
228  }
229  if (str != "Night") {
230  bday_ = true;
231  } else {
232  bday_ = false;
233  }
234  lines_ = nc_input->getDim("number_of_lines").getSize();
235  pixels_ = nc_input->getDim("number_of_pixels").getSize();
236  title_ = "VIIRS Level-2 Data";
237  break;
238  case SENSOR::POCI:
239  bday_ = true;
240  lines_ = nc_input->getDim("number_of_scans").getSize();
241  pixels_ = nc_input->getDim("ccd_pixels").getSize();
242  title_ = "OCI Level-2 Data";
243  break;
244  default:
245  cout << "DDProcess:: Failure reading dimensions" << endl;
246  return DTDB_FAIL;
247  }
248  delete nc_input;
249  } else {
250  cout << "Invalid L1B filename ..." << endl;
251  status = DTDB_FAIL;
252  }
253  return status;
254 }
255 
256 /**************************************************************************
257  * NAME: process()
258  *
259  * DESCRIPTION: Processes data and produces output values for granule
260  *
261  *************************************************************************/
263 {
264  int status = DTDB_SUCCESS;
265 
266  map<string,ddata*> imap = psensor_->create( {0, 0}, {lines_, pixels_} );
267  if (static_cast<ddval<int>*>(imap["status"])->val != DTDB_SUCCESS) {
268  cerr << "DDProcess:: Create sensor failure at line " << endl;
269  return DTDB_FAIL;
270  }
271 
272  ddstr* dstr = new ddstr(title_);
273  imap.insert({"title", dstr});
274  ddma<unsigned char,2>* plw = static_cast<ddma<unsigned char,2>*>(imap["land_water"]);
275  string parfilepath = get_option(INPUT_PAR);
276  dstr = new ddstr(parfilepath);
277  imap.insert({"config_file", dstr});
279  imap.insert({"bgascorrect", bval});
280  bgascorrect_ = bval->val;
282  imap.insert({"bglintmask", bval});
283  bglintmask_ = bval->val;
285  imap.insert({"bcloudmask", bval});
286  bcloudmask_ = bval->val;
287 
288  status = pancillary_->initialize( (static_cast<ddval<int>*>(imap["start_hour"]))->val,
289  (static_cast<ddval<int>*>(imap["start_minute"]))->val);
290  if (status != DTDB_SUCCESS) {
291  cerr << "DDProcess:: Ancillary initialization failure" << endl;
292  return status;
293  }
294  cerr << "DDProcess:: Initializing Land Process" << endl;
295  status = pl_->initialize(imap);
296  if (status != DTDB_SUCCESS) {
297  cerr << "DDProcess:: Land initialization failure" << endl;
298  return status;
299  }
300  cerr << "DDProcess:: Initializing Ocean Process" << endl;
301  status = po_->initialize(imap);
302  if (status != DTDB_SUCCESS) {
303  cerr << "DDProcess:: Ocean initialization failure" << endl;
304  return status;
305  }
306 
307  cerr << "DDProcess:: Processing Granule" << endl;
308  status = create_nc4(imap);
309  if (status != DTDB_SUCCESS) {
310  cerr << "DDProcess:: Output file creation failure" << endl;
311  return status;
312  }
313 
314  for (auto &it : imap) {
315  string name = (string) it.first;
316  if (name != "land_water") {
317  delete imap[name];
318  }
319  }
320 
321  map<string, ddma<float, 2>*> flmap;
322  map<string, ddma<unsigned int, 2>*> uimap;
323  map<string, ddma<short, 2>*> shmap;
324  map<string, ddma<unsigned char, 2>*> ubmap;
325  map<string, ddata*> smap;
326  map<string, ddata*> amap;
327  map<string, ddata*> pmap;
328 
329  for (auto &it : dtdb_names) {
330  string name = (string) it.first;
331  if ( it.second == dtype::FLOAT ) {
332  ddma<float, 2>* ddfl =
333  new ddma<float, 2>(dtype::FLOAT, {0,0}, {lprw_, pixels_});
334  flmap.insert({ name, ddfl });
335  } else if ( it.second == dtype::UINT) {
336  ddma<unsigned int, 2>* ddin =
337  new ddma<unsigned int, 2>(dtype::UINT, {0,0}, {lprw_, pixels_});
338  uimap.insert({ name, ddin });
339  } else if ( it.second == dtype::SHORT ) {
340  ddma<short, 2>* ddsh =
341  new ddma<short, 2>(dtype::SHORT, {0,0}, {lprw_, pixels_});
342  shmap.insert({ name, ddsh });
343  } else if ( it.second == dtype::UBYTE ) {
344  ddma<unsigned char, 2>* ddub =
345  new ddma<unsigned char, 2>(dtype::UBYTE, {0,0}, {lprw_, pixels_});
346  ubmap.insert({ name, ddub });
347  }
348  }
349  ddma<unsigned char, 2>* ddcm =
350  new ddma<unsigned char, 2>(dtype::UBYTE, {0,0}, {lprw_, pixels_});
351  ubmap.insert({ "cloud_mask", ddcm });
352 
353  for (auto &it : rhot_band_names) {
354  string name = (string) it.first;
355  ddma<float, 2>* ddfl =
356  new ddma<float, 2>(dtype::FLOAT, {0,0}, {lprw_, pixels_});
357  string oname = "rhot_" + name.substr(1);
358  flmap.insert({ oname, ddfl });
359  }
360  for (auto &it : aot_band_names) {
361  string name = (string) it.first;
362  ddma<float, 2>* ddfl =
363  new ddma<float, 2>(dtype::FLOAT, {0,0}, {lprw_, pixels_});
364  flmap.insert({ name, ddfl });
365  }
366  for (auto &it : srf_band_names) {
367  string name = (string) it.first;
368  ddma<float, 2>* ddfl =
369  new ddma<float, 2>(dtype::FLOAT, {0,0}, {lprw_, pixels_});
370  flmap.insert({ name, ddfl });
371  }
372  ddma<unsigned char, 2>* ddlw =
373  new ddma<unsigned char, 2>(dtype::UBYTE, {0,0}, {lprw_, pixels_});
374 
375 // for special aot_380
376  ddma<float, 2>* ddfl =
377  new ddma<float, 2>(dtype::FLOAT, {0,0}, {lprw_, pixels_});
378  flmap.insert({ "aot_380", ddfl });
379 
380  size_t cline = 0;
381  while ( cline < lines_ ) {
382  imap.clear();
383  size_t sy = cline;
384  size_t cy = lprw_;
385  size_t left = lines_-cline;
386  if (left < lprw_) {
387  cy = left;
388  }
389  for (auto &it : smap) {
390  delete smap[(string) it.first];
391  }
392  smap.clear();
393  smap = psensor_->read( {sy, 0}, {cy, pixels_} );
394  if (static_cast<ddval<int>*>(smap["status"])->val != DTDB_SUCCESS) {
395  cerr << "DDProcess:: Read sensor failure at line " << sy << endl;
396  }
397  delete smap["status"];
398  smap.erase("status");
399  imap.insert(smap.begin(), smap.end());
400  for (auto &it : amap) {
401  delete amap[(string) it.first];
402  }
403  amap.clear();
404  amap = pancillary_->read(imap);
405  if (static_cast<ddval<int>*>(amap["status"])->val != DTDB_SUCCESS) {
406  cerr << "DDProcess:: Read ancillary failure at line " << sy << endl;
407  }
408  delete amap["status"];
409  amap.erase("status");
410  imap.insert(amap.begin(), amap.end());
411  for ( size_t iy = 0; iy < cy; iy++ ) {
412  for ( size_t ix = 0; ix < pixels_; ix++ ) {
413  if (ix==5 && iy+sy==1714) {
414 // bool testmode = true;
415  }
416  if (plw->pts[sy+iy][ix] == 0) {
417  pmap = po_->process({iy,ix}, {cy,pixels_}, imap);
418  ddlw->pts[iy][ix] = 0;
419  if (static_cast<ddval<int>*>(pmap["status"])->val != DTDB_SUCCESS) {
420  cerr << "DDProcess:: Ocean process failure at line " << iy+sy << " pixel " << ix << endl;
421  }
422  } else if (plw->pts[sy+iy][ix] == 1) {
423  pmap = pl_->process({iy,ix}, {cy,pixels_}, imap);
424  ddlw->pts[iy][ix] = 1;
425  if (static_cast<ddval<int>*>(pmap["status"])->val != DTDB_SUCCESS) {
426  cerr << "DDProcess:: Land process failure at line " << iy+sy << " pixel " << ix << endl;
427  }
428  }
429  for (auto &it : flmap) {
430  string name = (string) it.first;
431  if (pmap.find(name) != pmap.end()) {
432  flmap[name]->pts[iy][ix] =
433  (static_cast<ddval<float>*>(pmap[name]))->val;
434  }
435  }
436  for (auto &it : uimap) {
437  string name = (string) it.first;
438  if (pmap.find(name) != pmap.end()) {
439  uimap[name]->pts[iy][ix] =
440  (static_cast<ddval<unsigned int>*>(pmap[name]))->val;
441  }
442  }
443  for (auto &it : shmap) {
444  string name = (string) it.first;
445  if (pmap.find(name) != pmap.end()) {
446  shmap[name]->pts[iy][ix] =
447  (static_cast<ddval<short>*>(pmap[name]))->val;
448  }
449  }
450  for (auto &it : ubmap) {
451  string name = (string) it.first;
452  if (pmap.find(name) != pmap.end()) {
453  ubmap[name]->pts[iy][ix] =
454  (static_cast<ddval<short>*>(pmap[name]))->val;
455  }
456  }
457  if (pmap.find("cloud_mask") != pmap.end()) {
458  ubmap["cloud_mask"]->pts[iy][ix] =
459  (static_cast<ddval<unsigned char>*>(pmap["cloud_mask"]))->val;
460  }
461  for (auto &it : pmap) {
462  delete pmap[(string) it.first];
463  }
464  pmap.clear();
465  }
466  }
467  delete amap["cloud_mask"];
468  amap.erase("cloud_mask");
469  imap.erase("cloud_mask");
470  for (auto &it : flmap) {
471  string name = (string) it.first;
472  flmap[name]->start = {cline, 0};
473  flmap[name]->count = {cy,pixels_};
474  imap.insert({name, flmap[name]});
475  }
476  for (auto &it : uimap) {
477  string name = (string) it.first;
478  uimap[name]->start = {cline, 0};
479  uimap[name]->count = {cy,pixels_};
480  imap.insert({name, uimap[name]});
481  }
482  for (auto &it : shmap) {
483  string name = (string) it.first;
484  shmap[name]->start = {cline, 0};
485  shmap[name]->count = {cy,pixels_};
486  imap.insert({name, shmap[name]});
487  }
488  for (auto &it : ubmap) {
489  string name = (string) it.first;
490  ubmap[name]->start = {cline, 0};
491  ubmap[name]->count = {cy,pixels_};
492  imap.insert({name, ubmap[name]});
493  }
494  ddlw->start = {cline,0};
495  ddlw->count = {cy,pixels_};
496  imap.insert({"land_water", ddlw});
497  cerr << ".";
498  status = write_nc4( imap );
499  cline += lprw_;
500  }
501  for (auto &it : imap) {
502  delete imap[(string) it.first];
503  }
504  imap.clear();
505 
506  delete plw;
507  delete pl_;
508  delete po_;
509 
510  cerr << " DONE! " << endl;
511 
512  if (get_bool(BOOL_STATISTICS)) {
513  vector<string> dnames = {"fmf_550","angstrom","aot_410","aot_490",\
514  "aot_550","aot_670","aot_865","aot_1240","aot_1610","aot_2250"};
515  size_t window = 8;
516 
517  cerr << "DDProcess:: Generating statistics on decimated samples" << endl;
518  status = write_decimated(dnames, window);
519  if (status != DTDB_SUCCESS) {
520  cerr << "DDProcess:: Write decimated statistics failure" << endl;
521  }
522  cerr << "ALL DONE! " << endl;
523  }
524 
525  return status;
526 }
527 
528 /**************************************************************************
529  * NAME: create_nc4()
530  *
531  * DESCRIPTION: Create NetCDF4 product file
532  *
533  *************************************************************************/
534 int DDProcess::create_nc4( map<string, ddata*> imap )
535 {
536  int status = DTDB_SUCCESS;
537  map<string, ddata*> omap;
538 
539  bool bshort = (bool) get_bool(BOOL_SHORT_FORMAT);
540 
541  vector<size_t> sdims, cdims;
542  sdims = {0,0};
543  cdims = {lines_, pixels_};
544 
545  for (auto &it : DDProcess::input_names) {
546  string name = (string) it.first;
547  ddata* odat = new ddata(it.second, sdims, cdims, nullptr);
548  omap.insert({name, odat});
549  }
550  for (auto &it : DDProcess::dtdb_names) {
551  string name = (string) it.first;
552  auto rslt = find(out_products.begin(), out_products.end(), name);
553  if( !get_bool(name) || (rslt == out_products.end())) {
554  continue;
555  }
556  ddata* odat = new ddata(it.second, sdims, cdims, nullptr);
557  omap.insert({name, odat});
558  }
559  for (auto &it : DDProcess::rhot_band_names) {
560  string name = (string) it.first;
561  ddata* odat = new ddata(dtype::FLOAT, sdims, cdims, nullptr);
562  omap.insert({name, odat});
563  }
564  for (auto &it : DDProcess::aot_band_names) {
565  string name = (string) it.first;
566  auto rslt = find(out_products.begin(), out_products.end(), name);
567  if( !get_bool(name) || (rslt == out_products.end())) {
568  continue;
569  }
570  ddata* odat = new ddata(dtype::FLOAT, sdims, cdims, nullptr);
571  omap.insert({name, odat});
572  }
573  for (auto &it : DDProcess::srf_band_names) {
574  string name = (string) it.first;
575  auto rslt = find(out_products.begin(), out_products.end(), name);
576  if( !get_bool(name) || (rslt == out_products.end())) {
577  continue;
578  }
579  ddata* odat = new ddata(dtype::FLOAT, sdims, cdims, nullptr);
580  omap.insert({name, odat});
581  }
582 
583 // for special aot_380
584  auto rslt = find(out_products.begin(), out_products.end(), "aot_380");
585  if( get_bool("aot_380") && (rslt != out_products.end())) {
586  ddata* odat = new ddata(dtype::FLOAT, sdims, cdims, nullptr);
587  omap.insert({"aot_380", odat});
588  }
589 
590 // Create output file
591  string output_filepath = get_option(OUTPUT_NC4);
592  if (output_filepath.empty()) {
593  cerr << "\nDDProcess:: Failure locating output file path.\n" << endl;
594  return DTDB_FAIL;
595  }
596  NcFile* nc_output;
597  try {
598  nc_output = new NcFile( output_filepath, NcFile::replace );
599  }
600  catch( NcException& e) {
601  e.what();
602  cerr << "\nDDProcess:: Failure creating product file: " + output_filepath + "\n" << endl;
603  return DTDB_FAIL;
604  }
605  try {
606  string xfilepath = get_option(PRODUCT_XML);
607  xml_document doc;
608  xml_parse_result result = doc.load_file(xfilepath.c_str());
609  if ( result.status != status_ok ) {
610  cerr << "DDProcess:: Failure opening XML product configuration file " +
611  xfilepath << endl;
612  return DTDB_FAIL;
613  }
614  xml_node products = doc.child("products");
615 
616  for (xml_node gatt: products.children()) {
617  string sname = string(gatt.name());
618  if (sname == "group" || sname == "metadata") {
619  continue;
620  }
621  nc_output->putAtt(sname, gatt.child_value());
622  }
623 
624  for (xml_node meta: products.children("metadata"))
625  {
626  string mname = meta.attribute("name").value();
627  if (imap.find(mname) != imap.end()) {
628  ddata* dsp = imap[mname];
629  dsp->putAtt(nc_output, mname);
630  }
631  }
632 
633  NcDim lines_dim = nc_output->addDim( "number_of_lines", lines_ );
634  NcDim pixels_dim = nc_output->addDim( "pixels_per_line", pixels_ );
635  NcDim all_bands_dim = nc_output->addDim( "number_of_bands", NTWL );
636  dmap_.insert({lines_dim.getSize(), lines_dim});
637  dmap_.insert({pixels_dim.getSize(), pixels_dim});
638  dmap_.insert({all_bands_dim.getSize(), all_bands_dim});
639  vector<NcDim> pdims;
640 
641  for (xml_node group: products.children("group"))
642  {
643  string gname = group.attribute("name").value();
644  if (!get_bool(gname)) {
645  continue;
646  }
647  bool boutput = false;
648  for(string str : out_groups) {
649  if (str == gname) boutput = true;
650  }
651  NcGroup grp = nc_output->addGroup(gname);
652  for (xml_node product: group.children("product")) {
653  string pname = product.attribute("name").value();
654  auto rslt = find(out_products.begin(), out_products.end(), pname);
655  if(gname==BOOL_DATA && (!get_bool(pname) || (rslt == out_products.end()))) {
656  continue;
657  }
658  ddata* dsp;
659  if (omap.find(pname) != omap.end()) {
660  dsp = omap[pname];
661  } else if (imap.find(pname) != imap.end()) {
662  dsp = imap[pname];
663  } else {
664  cout << " --" << pname << " not found" << endl;
665  continue;
666  }
667  bool bnotshort = (gname == "sensor_band_parameters" ||
668  gname == "scan_line_attributes" ||
669  gname == "navigation_data");
670  if (!bnotshort) {
671  dsp->setFormat(bshort);
672  }
673  pdims.clear();
674  for (size_t i=0; i<dsp->count.size(); i++) {
675  NcDim tdim = dmap_[dsp->count[i]];
676  pdims.push_back(tdim);
677  }
678  NcVar var;
679  if(bshort && dsp->type==dtype::FLOAT &&
680  dsp->count.size()==2 && !bnotshort) {
681  var = grp.addVar(pname, NcType(NC_SHORT), pdims);
682  } else {
683  var = grp.addVar(pname, NcType((nc_type)dsp->type), pdims);
684  }
685  vector<size_t> chunksizes = {lprw_, pixels_};
686  var.setCompression(bShuffleFilter, bDeflateFilter, deflateLevel);
687  var.setChunking(var.nc_CHUNKED, chunksizes);
688 
689  float vmax,vmin;
690  for (xml_node patt: product.children()) {
691  string attr_name = string(patt.name());
692  if (attr_name == "type") {
693  continue;
694  }
695  if (attr_name == "_FillValue") {
696  string pval_str = string(patt.child_value());
697  dsp->setFill(var, pval_str);
698  } else if (attr_name == "valid_min") {
699  vmin = boost::lexical_cast<float> (patt.child_value());
700  dsp->putAtt(var, "valid_min", patt.child_value());
701  } else if (attr_name == "valid_max") {
702  vmax = boost::lexical_cast<float> (patt.child_value());
703  dsp->putAtt(var, "valid_max", patt.child_value());
704  } else if (attr_name == "valid_logmin" ) {
705  if (!bcloudmask_) {
706  vmin = boost::lexical_cast<float> (patt.child_value());
707  dsp->putAtt(var, "valid_min", patt.child_value());
708  }
709  } else if (attr_name == "valid_logmax" ) {
710  if (!bcloudmask_) {
711  vmax = boost::lexical_cast<float> (patt.child_value());
712  dsp->putAtt(var, "valid_max", patt.child_value());
713  }
714  } else {
715  var.putAtt(attr_name, patt.child_value());
716  }
717  }
718  if(bshort && dsp->type==dtype::FLOAT &&
719  dsp->count.size()==2 && !bnotshort) {
720  float scale = (vmax-vmin)/2.0/MAX_SHORT;
721  float offset = (vmax+vmin)/2.0;
722  var.putAtt("scale_factor", ncFloat, scale);
723  var.putAtt("add_offset", ncFloat, offset);
724  var.putAtt("valid_min", ncShort, -MAX_SHORT);
725  var.putAtt("valid_max", ncShort, MAX_SHORT);
726  }
727  if (!boutput) {
728  dsp->putVar(var);
729  }
730  }
731  }
732  }
733  catch( NcException& e) {
734  e.what();
735  cerr << "\nDDProcess:: Failure initializing product file: " +
736  output_filepath + "\n" << endl;
737  status = DTDB_FAIL;
738  }
739 
740  for (auto &it : omap) {
741  delete omap[(string) it.first];
742  }
743  omap.clear();
744  dmap_.clear();
745 
746  delete nc_output;
747 
748  return status;
749 }
750 
751 /**************************************************************************
752  * NAME: write_nc4()
753  *
754  * DESCRIPTION: Write a single line to output file.
755  *
756  *************************************************************************/
757 int DDProcess::write_nc4( map<string, ddata*> omap )
758 {
759  int status = DTDB_SUCCESS;
760 
761  bool bshort = (bool) get_bool(BOOL_SHORT_FORMAT);
762 
763  string output_filepath = get_option(OUTPUT_NC4);
764  if (output_filepath.empty()) {
765  cerr << "\nDDProcess:: Failure locating output file path.\n" << endl;
766  return DTDB_FAIL;
767  }
768  NcFile* nc_output;
769  try {
770  nc_output = new NcFile( output_filepath, NcFile::write );
771  }
772  catch( NcException& e) {
773  e.what();
774  cerr << "\nDDProcess:: Failure writing to product file: " +
775  output_filepath + "\n" << endl;
776  return DTDB_FAIL;
777  }
778 
779  string xfilepath = get_option(PRODUCT_XML);
780  xml_document doc;
781  xml_parse_result result = doc.load_file(xfilepath.c_str());
782  if ( result.status != status_ok ) {
783  cerr << "DDProcess:: Failure opening XML product configuration file " +
784  xfilepath << endl;
785  return DTDB_FAIL;
786  }
787  xml_node products = doc.child("products");
788 
789  for (string gname : out_groups) {
790  try {
791  if (!get_bool(gname)) {
792  continue;
793  }
794  xml_node group =
795  products.find_child_by_attribute("group", "name", gname.c_str());
796  string xname = group.attribute("name").value();
797  NcGroup grp = nc_output->getGroup(gname);
798  for (xml_node product: group.children("product")) {
799  string pname = product.attribute("name").value();
800  auto rslt = find(out_products.begin(), out_products.end(), pname);
801  if(gname==BOOL_DATA && (!get_bool(pname) || (rslt == out_products.end()))) {
802  continue;
803  }
804  if (omap.find(pname) != omap.end()) {
805  ddata* dsp = omap[pname];
806  if (!(pname=="latitude" || pname=="longitude")) {
807  dsp->setFormat(bshort);
808  }
809  NcVar var = grp.getVar(pname);
810  if (!var.isNull()) {
811  dsp->putVar(var);
812  }
813  }
814  }
815  }
816  catch( NcException& e) {
817  e.what();
818  cerr << "\nDDProcess:: Failure writing line " + output_filepath + "\n" << endl;
819  status = DTDB_FAIL;
820  }
821  }
822  delete nc_output;
823 
824  return status;
825 }
826 
827 /**************************************************************************
828  * NAME: write_decimated()
829  *
830  * DESCRIPTION: Compute and write decimated data sets.
831  *
832  *************************************************************************/
833 int DDProcess::write_decimated(vector<string> names, size_t& nwin)
834 {
835  int status = DTDB_SUCCESS;
836 
837  string filepath = get_option(OUTPUT_NC4);
838 
839  if (filepath.empty()) {
840  cout << "DDAlgorithm:: Missing L2 file name for decimation" << endl;
841  status = DTDB_FAIL;
842  return status;
843  }
844  NcFile* nc_output;
845  try {
846  nc_output = new NcFile(filepath, NcFile::write);
847  }
848  catch( NcException& e) {
849  e.what();
850  cout << "DDAlgorithm:: Failure opening L2 file for decimation" << endl;
851  return DTDB_FAIL;
852  }
853  size_t lines = nc_output->getDim("number_of_lines").getSize();
854  size_t pixels = nc_output->getDim("pixels_per_line").getSize();
855  vector<size_t> startp = {0,0};
856  vector<size_t> countp = {lines, pixels};
857  size_t dlines = lines/nwin+1;
858  size_t dpixels = pixels/nwin+1;
859  vector<size_t> startd = {0,0,0};
860  vector<size_t> countd = {3, dlines, dpixels};
861 
862  NcGroup dgrp = nc_output->addGroup("statistics");
863  NcDim sets_dim = nc_output->addDim( "number_of_views", countd[0] );
864  NcDim lines_dim = nc_output->addDim( "number_of_decimated_lines", countd[1] );
865  NcDim samples_dim = nc_output->addDim( "Decimated_samples_per_line", countd[2] );
866  vector<NcDim> dimsd = {sets_dim, lines_dim, samples_dim};
867  ddma<float,3>* ddec = new ddma<float,3>(dtype::FLOAT, startd, countd);
868 
869  for (auto &it : names) {
870  string name = (string) it;
871  NcGroup pgrp = nc_output->getGroup("geophysical_data");
872  ddma<float,2>* ddat =
873  new ddma<float,2>(pgrp, name, dtype::FLOAT, startp, countp);
874  if (ddat->ptr == nullptr) {
875  delete ddat;
876  continue;
877  }
878 
879  fill(ddec->pts.origin(), ddec->pts.origin()+ddec->pts.num_elements(),0);
880  string strdec = name +"_"+ to_string(nwin) +"x"+ to_string(nwin);
881  NcVar vard = dgrp.addVar(strdec, NcType(NC_FLOAT), dimsd);
882  if (vard.isNull()) {
883  cout << "DDProcess::write_decimated() Failure to create netcdf vars" << endl;
884  return DTDB_FAIL;
885  }
886  string lname = strdec + " Mean, Standard deviation, and sample counts on grid decimated by " + to_string(nwin);
887  vard.putAtt("long_name", lname);
888  ddec->setFill(vard, to_string(DFILL_FLOAT));
889  vector<size_t> chunksizes = {countd[0], countd[1], countd[2]};
890  vard.setCompression(bShuffleFilter, bDeflateFilter, deflateLevel);
891  vard.setChunking(vard.nc_CHUNKED, chunksizes);
892 
893  for (size_t j=0; j<lines; j++) {
894  for (size_t i=0; i<pixels; i++) {
895  if (ddat->pts[j][i] < DFILL_TEST) continue;
896  size_t iidx = i/nwin;
897  size_t jidx = j/nwin;
898  ddec->pts[0][jidx][iidx] += ddat->pts[j][i];
899  ddec->pts[2][jidx][iidx]++;
900  }
901  }
902  for (size_t j=0; j<dlines; j++) {
903  for (size_t i=0; i<dpixels; i++) {
904  if (ddec->pts[2][j][i] >9) {
905  ddec->pts[0][j][i] /= ddec->pts[2][j][i];
906  } else {
907  ddec->pts[0][j][i] = DFILL_FLOAT;
908  }
909  }
910  }
911  for (size_t j=0; j<lines; j++) {
912  for (size_t i=0; i<pixels; i++) {
913  if (ddat->pts[j][i] < DFILL_TEST) continue;
914  size_t iidx = i/nwin;
915  size_t jidx = j/nwin;
916  ddec->pts[1][jidx][iidx] +=
917  pow(ddat->pts[j][i]-ddec->pts[0][jidx][iidx],2.0);
918  }
919  }
920  for (size_t j=0; j<dlines; j++) {
921  for (size_t i=0; i<dpixels; i++) {
922  if (ddec->pts[2][j][i] >9) {
923  ddec->pts[1][j][i] /= (ddec->pts[2][j][i]-1);
924  ddec->pts[1][j][i] = sqrt(ddec->pts[1][j][i]);
925  } else {
926  ddec->pts[1][j][i] = DFILL_FLOAT;
927  }
928  }
929  }
930  ddec->putVar(vard);
931 
932  delete ddat;
933  }
934  delete ddec;
935  delete nc_output;
936 
937  return status;
938 };
939 
940 
constexpr short MAX_SHORT
Definition: DDataset.hpp:29
const string ALGORITHM
Definition: DDOptions.cpp:193
virtual int process()
Definition: DDProcess.cpp:262
@ SHORT
signed 2 byte integer
int j
Definition: decode_rs.h:73
void putAtt(NcFile *ncfile, string name)
Definition: DDataset.hpp:93
int initialize()
Definition: DDProcess.cpp:132
int status
Definition: l1_czcs_hdf.c:32
#define L(lambda, T)
Definition: PreprocessP.h:185
void putVar(NcVar &var)
Definition: DDataset.hpp:221
int query_granule()
Definition: DDProcess.cpp:193
@ UBYTE
unsigned 1 byte int
dtype type
Definition: DDataset.hpp:60
constexpr float DFILL_TEST
Definition: DDataset.hpp:26
bool bcloudmask_
Definition: DDProcess.h:128
map< int, NcDim > dmap_
Definition: DDProcess.h:163
const string BOOL_MASK_CLOUD
Definition: DDOptions.cpp:166
boost::multi_array< T, ndim > pts
Definition: DDataset.hpp:324
virtual ~DDProcess()
Definition: DDProcess.cpp:114
@ FLOAT
single precision floating point number
string get_option(const string &name)
Definition: DDOptions.cpp:211
void setFill(NcVar &var, string sval)
Definition: DDataset.hpp:175
@ string
const string BOOL_STATISTICS
Definition: DDOptions.cpp:162
character(len=1000) if
Definition: names.f90:13
const string INPUT_L1B
Definition: DDOptions.cpp:40
const string INPUT_PAR
Definition: DDOptions.cpp:37
int get_bool(const string &name)
Definition: DDOptions.cpp:231
int get_option_int(const string &name)
Definition: DDOptions.cpp:223
static const map< string, srf_band > srf_band_names
Definition: DDProcess.h:158
static const map< string, dtype > input_names
Definition: DDProcess.h:175
const string INPUT_LINES_PER_RW
Definition: DDOptions.cpp:35
const string OUTPUT_NC4
Definition: DDOptions.cpp:49
static const map< string, aot_band > aot_band_names
Definition: DDProcess.h:157
constexpr float DFILL_FLOAT
Definition: DDataset.hpp:25
string filepath
Definition: color_dtdb.py:207
int create_nc4(map< string, ddata * > imap)
Definition: DDProcess.cpp:534
size_t pixels_
Definition: DDProcess.h:133
const char * str
Definition: l1c_msi.cpp:35
Definition: names.f90:1
int write_decimated(vector< string > names, size_t &nwin)
Definition: DDProcess.cpp:833
@ UINT
unsigned 4-byte int
const string PRODUCT_XML
Definition: DDOptions.cpp:38
const bool bDeflateFilter
void setFormat(bool bshrt)
Definition: DDataset.hpp:91
vector< size_t > count
Definition: DDataset.hpp:62
a context in which it is NOT documented to do so subscript which cannot be easily calculated when extracting TONS attitude data from the Terra L0 files Corrected several defects in extraction of entrained ephemeris and and as HDF file for both the L1A and Geolocation products
Definition: HISTORY.txt:67
#define bool
Definition: usrmac.h:88
size_t lines_
Definition: DDProcess.h:132
const bool bShuffleFilter
l2prod offset
static const map< string, dtype > dtdb_names
Definition: DDProcess.h:176
const string BOOL_SHORT_FORMAT
Definition: DDOptions.cpp:167
const void * ptr
Definition: DDataset.hpp:64
const string BOOL_DATA
Definition: DDOptions.cpp:157
const int deflateLevel
vector< size_t > start
Definition: DDataset.hpp:61
size_t lprw_
Definition: DDProcess.h:134
int i
Definition: decode_rs.h:71
int write_nc4(map< string, ddata * > omap)
Definition: DDProcess.cpp:757
msiBandIdx val
Definition: l1c_msi.cpp:34
static const map< string, rhot_band > rhot_band_names
Definition: DDProcess.h:156
HISTORY txt for MOD_PR01(step one of PGE01) History follows the following convention needed due to new Aqua ReprocessingActual and the expected LUT revision number from PCF Changed to use PGE version for ProductionHistory Added Archive including ProcessingEnvironment Corrected handling of bad to resovle GSFcd02514 Changed to check staged LUT revision number versus the expected LUT revision number from thereby resolving defect report MODxl02056 This change also avoids the memory access violation reported in MODur00039 Changed the way output arrays were initialized with fill to be more but placed into the L1A output product and thought of as valid packets These packets had an invalid frame count in them and since only the last valid packet of any specific type gets it frame count data written to the output product
Definition: HISTORY.txt:176
vector< string > out_products
Definition: DDProcess.h:173
const string BOOL_GAS_CORRECTION
Definition: DDOptions.cpp:164
static const vector< string > out_groups
Definition: DDProcess.h:174
const string BOOL_MASK_GLINT
Definition: DDOptions.cpp:165
a context in which it is NOT documented to do so subscript which cannot be easily calculated when extracting TONS attitude data from the Terra L0 files Corrected several defects in extraction of entrained ephemeris and and as HDF file attributes
Definition: HISTORY.txt:65