OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
DDSensor.cpp
Go to the documentation of this file.
1 /**************************************************************************
2  *
3  * NAME: DDSensor.cpp
4  *
5  * DESCRIPTION: Object class that reads in L1B radiance and geolocation data
6  * for for processing by selected algorithms.
7  *
8  * Created on: August 24, 2020
9  * Author: Sam Anderson
10  *
11  **************************************************************************/
12 
13 #include <netcdf>
14 #include <vector>
15 #include <map>
16 #include <memory>
17 #include <iostream>
18 #include <algorithm>
19 #include <ctime>
20 #include <timeutils.h>
21 #include <gsl/gsl_rng.h>
22 #include <gsl/gsl_randist.h>
23 #include <sys/time.h>
24 #include <netcdf>
25 
26 #include <DDataset.hpp>
27 #include <DDProcess.h>
28 #include <DDOptions.h>
29 #include <DDSensor.h>
30 #include "resam_viirs/RsViirs.h"
31 
32 using namespace std;
33 using namespace netCDF;
34 using namespace netCDF::exceptions;
35 
36 string nodestr [3] = {"Ascending", "Descending", "Unknown"};
37 string daynightstr[4] = {"Day", "Night", "Mixed", "Unknown"};
38 
39 map<string,float> F0 = {
40  {"rhot_410", 167.403},
41  {"rhot_445", 194.417},
42  {"rhot_490", 195.211},
43  {"rhot_550", 187.053},
44  {"rhot_670", 151.462},
45  {"rhot_865", 94.948},
46  {"rhot_1240", 44.830},
47  {"rhot_1380", 36.468},
48  {"rhot_1610", 24.439},
49  {"rhot_2250", 7.686}
50 };
51 
52 /**************************************************************************
53  * NAME: DDSensor()
54  * DESCRIPTION: Class Constructor
55  *************************************************************************/
57 {
58  brad_ = false;
59 }
60 
61 /**************************************************************************
62  * NAME: ~DDSensor()
63  * DESCRIPTION: Class Destructor
64  *************************************************************************/
66 {
67 }
68 
69 /**************************************************************************
70  * NAME: create()
71  * DESCRIPTION: Create l2 template data.
72  *************************************************************************/
73 
74 map<string,ddata*> DDSensor::create(vector<size_t> start, vector<size_t> count)
75 {
76  map<string, ddata*> omap;
77  int status = DTDB_SUCCESS;
78  ddval<int>* pstat = new ddval<int>(dtype::INT, status);
79  omap.insert({"status", pstat});
80 
81  string filepath_l1b = get_option(INPUT_L1B);
82  string filepath_geo = get_option(INPUT_GEO);
83  filepath_geo = (filepath_geo=="") ? filepath_l1b : filepath_geo;
84  map<string,ddata*> gmap = read_geo( filepath_geo, start, count );
85  if (static_cast<ddval<int>*>(gmap["status"])->val != DTDB_SUCCESS) {
86  cerr << "DDSensor:: Read GEO failure. " << endl;
87  pstat->val = DTDB_FAIL;
88  return omap;
89  }
90  delete gmap["status"];
91  gmap.erase("status");
92  omap.insert(gmap.begin(), gmap.end());
93 
94  map<string,ddata*> lmap = create_l2( gmap );
95  if (static_cast<ddval<int>*>(lmap["status"])->val != DTDB_SUCCESS) {
96  cerr << "DDSensor:: Create L2 failure. " << endl;
97  pstat->val = DTDB_FAIL;
98  return omap;
99  }
100  delete lmap["status"];
101  lmap.erase("status");
102  omap.insert(lmap.begin(), lmap.end());
103  return omap;
104 }
105 
106 /**************************************************************************
107  * NAME: read()
108  * DESCRIPTION: Read selection of l1 data.
109  *************************************************************************/
110 
111 map<string,ddata*> DDSensor::read(vector<size_t> start, vector<size_t> count)
112 {
113  map<string, ddata*> omap;
114  int status = DTDB_SUCCESS;
115  ddval<int>* pstat = new ddval<int>(dtype::INT, status);
116  omap.insert({"status", pstat});
117 
118  string filepath_l1b = get_option(INPUT_L1B);
119  string filepath_geo = get_option(INPUT_GEO);
120  filepath_geo = (filepath_geo=="") ? filepath_l1b : filepath_geo;
121 
122  map<string,ddata*> lmap = read_l1b( filepath_l1b, start, count );
123  if (static_cast<ddval<int>*>(lmap["status"])->val != DTDB_SUCCESS) {
124  cerr << "DDSensor::Error: Read L1B Failure. " << endl;
125  pstat->val = DTDB_FAIL;
126  return omap;
127  }
128  delete lmap["status"];
129  lmap.erase("status");
130  omap.insert(lmap.begin(), lmap.end());
131 
132  map<string,ddata*> gmap = read_geo( filepath_geo, start, count );
133  if (static_cast<ddval<int>*>(gmap["status"])->val != DTDB_SUCCESS) {
134  cerr << "DDSensor::Error: Read GEO Failure. " << endl;
135  pstat->val = DTDB_FAIL;
136  return omap;
137  }
138  delete gmap["status"];
139  gmap.erase("status");
140  omap.insert(gmap.begin(), gmap.end());
141 
142  // Apply solar zenith angle corrections
143  for ( size_t iy=0; iy<count[0]; iy++) {
144  for ( size_t ix=start[1]; ix<count[1]; ix++) {
145  double sza = static_cast<ddma<float,2>*>(gmap["solar_zenith"])->pts[iy][ix];
146  double cossza = cos(sza*DEGtoRAD);
147  for (auto &it : DDProcess::rhot_band_names) {
148  string name = (string) it.first;
149  float rfl = static_cast<ddma<float,2>*>(lmap[name])->pts[iy][ix];
150  if (rfl > 0) {
151  static_cast<ddma<float,2>*>(lmap[name])->pts[iy][ix] = rfl/cossza;
152  }
153  }
154  }
155  }
156  return omap;
157 }
158 
159 /**************************************************************************
160  * NAME: read_land_mask()
161  *
162  * DESCRIPTION: Read global Land/Sea mask LUT.
163  *
164  *************************************************************************/
165 map<string,ddata*> DDSensor::read_landmask( map<string,ddata*> gmap,
166  vector<size_t> start, vector<size_t> count )
167 {
168  map<string, ddata*> omap;
169  int status = DTDB_SUCCESS;
170  ddval<int>* pstat = new ddval<int>(dtype::INT, status);
171  omap.insert({"status", pstat});
172 
173  LandMaskLUT* lm_lut = new LandMaskLUT;
175  if(! filepath.empty()) {
176  NcFile* nc_input;
177  try {
178  nc_input = new NcFile(filepath, NcFile::read );
179  }
180  catch( NcException& e) {
181  e.what();
182  cerr << "DDSensor:: Failure opening Land Mask LUT file: "
183  + filepath << endl;
184  pstat->val = DTDB_FAIL;
185  return omap;
186  }
187  NcVar var = nc_input->getVar ( "lat" );
188  var.getVar( lm_lut->lat );
189  var = nc_input->getVar ( "lon" );
190  var.getVar( lm_lut->lon );
191  var = nc_input->getVar ( "watermask" );
192  var.getVar( lm_lut->watermask );
193  delete nc_input;
194  }
195  else {
196  cerr << "DDSensor:: Failure, bad Land Mask file path." << endl;
197  pstat->val = DTDB_FAIL;
198  return omap;
199  }
200 
202 
203  for ( size_t iy=start[0]; iy<count[0]; iy++) {
204  for ( size_t ix=start[1]; ix<count[1]; ix++) {
205  double lat = static_cast<ddma<float,2>*>(gmap["latitude"])->pts[iy][ix];
206  double lon = static_cast<ddma<float,2>*>(gmap["longitude"])->pts[iy][ix];
207  int iLat = (90.0+lat)*(LANDMASK_LAT-1)/180.0;
208  int iLon = (180.0+lon)*(LANDMASK_LON-1)/360.0;
209  iLat = max (iLat, 0);
210  iLat = min (iLat, LANDMASK_LAT-1);
211  iLon = max (iLon, 0);
212  iLon = min (iLon, LANDMASK_LON-1);
213  unsigned char c = (unsigned char) lm_lut->watermask[iLat][iLon];
214  dlw->pts[iy][ix] = (c < 0.5) ? 1 : 0;
215  }
216  }
217  delete lm_lut;
218 
219  omap.insert({"land_water", dlw});
220  return omap;
221 }
222 
223 /**************************************************************************
224  * NAME: random_seed()
225  *
226  * DESCRIPTION: Obtain a random seed for
227  *
228  *************************************************************************/
229 unsigned long int DDSensor::random_seed() {
230  /* Seed generator for gsl. */
231  struct timeval tv;
232  gettimeofday(&tv, nullptr);
233  return (tv.tv_sec + tv.tv_usec);
234 }
235 
236 /**************************************************************************
237  * NAME: make_noise()
238  *
239  * DESCRIPTION: Noise generator adapted from OCSSW loadl1.c
240  *
241  *************************************************************************/
242 float DDSensor::make_noise(float sigma) {
243  unsigned long randSeed = random_seed();
244  float noise;
245  gsl_rng *rng;
246  rng = gsl_rng_alloc(gsl_rng_mt19937);
247  gsl_rng_set(rng, randSeed);
248  noise = gsl_ran_gaussian(rng, sigma);
249  gsl_rng_free(rng);
250  return (noise);
251 }
252 
253 /**************************************************************************
254  * NAME: noise_model()
255  *
256  * DESCRIPTION: Virtual instrument-dependent noise model.
257  *
258  *************************************************************************/
259 float DDSensor::noise_model(float lt, int iw, float snr_mult)
260 { return 0.0; }
261 
262 /**************************************************************************
263  * NAME: read_l1b()
264  *
265  * DESCRIPTION: Virtual method.
266  *
267  *************************************************************************/
268 map<string,ddata*> DDSensor::read_l1b(const string & filepath,
269  vector<size_t> start, vector<size_t> count)
270 {
271  map<string, ddata*> omap;
272  int status = DTDB_SUCCESS;
273  ddval<int>* pstat = new ddval<int>(dtype::INT, status);
274  omap.insert({"status", pstat});
275  return omap;
276 }
277 
278 /**************************************************************************
279  * NAME: read_l1b_attributes()
280  *
281  * DESCRIPTION: Virtual method.
282  *
283  *************************************************************************/
284 map<string,ddata*> DDSensor::read_l1b_attributes(NcFile* nc_input)
285 {
286  map<string, ddata*> omap;
287  int status = DTDB_SUCCESS;
288  ddval<int>* pstat = new ddval<int>(dtype::INT, status);
289  omap.insert({"status", pstat});
290  return omap;
291 }
292 
293 /**************************************************************************
294  * NAME: create_l2()
295  *
296  * DESCRIPTION: Populate input map for generic granule data.
297  *
298  *************************************************************************/
299 map<string, ddata*> DDSensor::create_l2(map<string, ddata*> gmap)
300 {
301  map<string, ddata*> omap;
302  int status = DTDB_SUCCESS;
303  ddval<int>* pstat = new ddval<int>(dtype::INT, status);
304  omap.insert({"status", pstat});
305 
306  int spixl = get_option_int(INPUT_SPIX);
307  int epixl = get_option_int(INPUT_EPIX);
308  int sline = get_option_int(INPUT_SLINE);
309  int eline = get_option_int(INPUT_ELINE);
310 
311  time_t rawtime;
312  struct tm * timeinfo;
313  char timebuffer[80];
314  time(&rawtime);
315  timeinfo = localtime(&rawtime);
316  strftime(timebuffer, 80, "%Y-%m-%dT%H:%M:%SZ", timeinfo);
317  string date_created = string(timebuffer);
318 
319  string filepath_l1b = get_option(INPUT_L1B);
320  NcFile* nc_input = new NcFile(filepath_l1b, NcFile::read );
321  map<string,ddata*> amap = read_l1b_attributes(nc_input);
322  delete nc_input;
323  if (static_cast<ddval<int>*>(amap["status"])->val != DTDB_SUCCESS) {
324  cerr << "DDSensor::Error: Read L1B attributes failure. " << endl;
325  pstat->val = DTDB_FAIL;
326  return omap;
327  }
328  delete amap["status"];
329  amap.erase("status");
330  size_t numx = static_cast<ddval<int>*>(amap["num_pixels"])->val;
331  size_t numy = static_cast<ddval<int>*>(amap["num_lines"])->val;
332  vector<size_t> start = {0,0};
333  vector<size_t> count = {numy,numx};
334  size_t cpix = numx / 2;
335  size_t npix = numx;
336  size_t epix = (epixl < 1) ? npix-1 : epixl-1;
337  size_t spix = (spixl < 1) ? 0 : spixl-1;
338  size_t nscan = numy;
339  if (eline < 1) {
340  nscan = numy - max(sline - 1, 0);
341  } else {
342  nscan = (eline - 1) - max(sline - 1, 0);
343  }
344  size_t cscan = nscan / 2;
345  size_t line_cnt = 0;
346  vector<size_t> strt = {0};
347  vector<size_t> cntr = {nscan};
348  vector<size_t> cntc = {numx};
349 
350  map<string,ddata*> lmap = read_landmask(gmap, start, count);
351  if (static_cast<ddval<int>*>(lmap["status"])->val != DTDB_SUCCESS) {
352  cerr << "DDSensor::Error: Read landmask failure. " << endl;
353  pstat->val = DTDB_FAIL;
354  return omap;
355  }
356  delete lmap["status"];
357  lmap.erase("status");
358  omap.insert(lmap.begin(), lmap.end());
359  omap.insert(gmap.begin(), gmap.end());
360  omap.insert(amap.begin(), amap.end());
361  omap.insert({"mside", amap["mside"]});
362  ddma<int,1>* dyear = new ddma<int,1>(dtype::INT, strt, cntr);
363  omap.insert({"year", dyear});
364  ddma<int,1>* dday = new ddma<int,1>(dtype::INT, strt, cntr);
365  omap.insert({"day", dday});
366  ddma<int,1>* dmsec = new ddma<int,1>(dtype::INT, strt, cntr);
367  omap.insert({"msec", dmsec});
368  ddma<int,1>* drows = new ddma<int,1>(dtype::INT, strt, cntr);
369  omap.insert({"cntl_pt_rows", drows});
370  ddma<int,1>* dcols = new ddma<int,1>(dtype::INT, strt, cntc);
371  omap.insert({"cntl_pt_cols", dcols});
372  ddma<float,1>* dslon = new ddma<float,1>(dtype::FLOAT, strt, cntr);
373  omap.insert({"slon", dslon});
374  ddma<float,1>* dclon = new ddma<float,1>(dtype::FLOAT, strt, cntr);
375  omap.insert({"clon", dclon});
376  ddma<float,1>* delon = new ddma<float,1>(dtype::FLOAT, strt, cntr);
377  omap.insert({"elon", delon});
378  ddma<float,1>* dslat = new ddma<float,1>(dtype::FLOAT, strt, cntr);
379  omap.insert({"slat", dslat});
380  ddma<float,1>* dclat = new ddma<float,1>(dtype::FLOAT, strt, cntr);
381  omap.insert({"clat", dclat});
382  ddma<float,1>* delat = new ddma<float,1>(dtype::FLOAT, strt, cntr);
383  omap.insert({"elat", delat});
384  ddma<float,1>* dcsol_z = new ddma<float,1>(dtype::FLOAT, strt, cntr);
385  omap.insert({"csol_z", dcsol_z});
386  ddma<float,1>* dtilt = new ddma<float,1>(dtype::FLOAT, strt, cntr);
387  omap.insert({"tilt", dtilt});
388 
389  size_t pix_cnt = 0;
390  for ( size_t ix=0; ix<numx; ix++) {
391  dcols->pts[ix] = pix_cnt++;
392  }
393  for ( size_t iy=0; iy<nscan; iy++) {
394  struct tm *trec;
395  time_t utime = (time_t) static_cast<ddma<double,1>*>(amap["scan_time"])->pts[iy];
396  trec = gmtime(&utime);
397  int year = trec->tm_year + 1900;
398  int day = trec->tm_yday + 1;
399  double secs = trec->tm_hour * 3600.0 + trec->tm_min * 60. +
400  trec->tm_sec + fmod(static_cast<ddma<double,1>*>(amap["scan_time"])->pts[iy], 1.);
401  dyear->pts[iy] = (int32_t) year;
402  dday->pts[iy] = (int32_t) day;
403  dmsec->pts[iy] = (int32_t) (secs * 1.e3);
404  dslon->pts[iy] = static_cast<ddma<float,2>*>(gmap["longitude"])->pts[iy][spix];
405  dclon->pts[iy] = static_cast<ddma<float,2>*>(gmap["longitude"])->pts[iy][cpix];
406  delon->pts[iy] = static_cast<ddma<float,2>*>(gmap["longitude"])->pts[iy][epix];
407  dslat->pts[iy] = static_cast<ddma<float,2>*>(gmap["latitude"])->pts[iy][spix];
408  dclat->pts[iy] = static_cast<ddma<float,2>*>(gmap["latitude"])->pts[iy][cpix];
409  delat->pts[iy] = static_cast<ddma<float,2>*>(gmap["latitude"])->pts[iy][epix];
410  dcsol_z->pts[iy] = static_cast<ddma<float,2>*>(gmap["solar_zenith"])->pts[iy][cpix];
411  drows->pts[iy] = line_cnt++;
412  }
413 
414  double esd = esdist_(&dyear->pts[cscan], &dday->pts[cscan], &dmsec->pts[cscan]);
415  double esdist_correction = pow(1.0 / esd, 2);
416  float start_center_lon = static_cast<ddma<float,2>*>(gmap["longitude"])->pts[0][cpix];
417  float start_center_lat = static_cast<ddma<float,2>*>(gmap["latitude"])->pts[0][cpix];
418  float end_center_lon = static_cast<ddma<float,2>*>(gmap["longitude"])->pts[nscan-1][cpix];
419  float end_center_lat = static_cast<ddma<float,2>*>(gmap["latitude"])->pts[nscan-1][cpix];
420 
421  auto mm = minmax_element(static_cast<ddma<float,2>*>(gmap["latitude"])->pts.data(),
422  static_cast<ddma<float,2>*>(gmap["latitude"])->pts.data() +
423  static_cast<ddma<float,2>*>(gmap["latitude"])->pts.num_elements());
424  float geospatial_lat_max = *mm.second;
425  float geospatial_lat_min = *mm.first;
426  mm = minmax_element(static_cast<ddma<float,2>*>(gmap["longitude"])->pts.data(),
427  static_cast<ddma<float,2>*>(gmap["longitude"])->pts.data() +
428  static_cast<ddma<float,2>*>(gmap["longitude"])->pts.num_elements());
429  float geospatial_lon_max = *mm.second;
430  float geospatial_lon_min = *mm.first;
431 
432  float lastLat = start_center_lat;
433  int daynight = UNKNOWNSCENE;
434  float northern_lat = -90.0;
435  float southern_lat = +90.0;
436  float eastern_lon = +180.0;
437  float western_lon = -180.0;
438  for (size_t is=0; is<nscan; is++) {
439  for (size_t ip = spix; ip <= epix; ip++) {
440  northern_lat = max(northern_lat, (static_cast<ddma<float,2>*>(gmap["latitude"]))->pts[is][ip]);
441  southern_lat = min(southern_lat, (static_cast<ddma<float,2>*>(gmap["latitude"]))->pts[is][ip]);
442  if (daynight != DAYANDNIGHT) {
443  if (static_cast<ddma<float,2>*>(gmap["solar_zenith"])->pts[is][ip] > SOLZNIGHT) {
444  daynight = (daynight == DAYSCENE) ? DAYANDNIGHT : NIGHTSCENE;
445  } else {
446  daynight = (daynight == NIGHTSCENE) ? DAYANDNIGHT : DAYSCENE;
447  }
448  }
449  }
450  float wl = static_cast<ddma<float,2>*>(gmap["longitude"])->pts[is][spix];
451  float el = static_cast<ddma<float,2>*>(gmap["longitude"])->pts[is][epix];
452  if (static_cast<ddma<float,2>*>(gmap["latitude"])->pts[is][cpix] < lastLat) {
453  wl = static_cast<ddma<float,2>*>(gmap["longitude"])->pts[is][epix];
454  el = static_cast<ddma<float,2>*>(gmap["longitude"])->pts[is][spix];
455  }
456  western_lon = (wl > western_lon) ? wl : western_lon;
457  eastern_lon = (el < eastern_lon) ? el : eastern_lon;
458  lastLat = static_cast<ddma<float,2>*>(gmap["latitude"])->pts[is][cpix];
459  }
460 
461  string start_direction = (static_cast<ddma<float,2>*>(gmap["latitude"])->pts[1][cpix] >
462  static_cast<ddma<float,2>*>(gmap["latitude"])->pts[0][cpix]) ?
464  string end_direction = (static_cast<ddma<float,2>*>(gmap["latitude"])->pts[nscan-1][cpix] >
465  static_cast<ddma<float,2>*>(gmap["latitude"])->pts[nscan-2][cpix]) ?
467  string day_night_flag = daynightstr[daynight];
468 
469  // fill map
470  ddstr* dstr = new ddstr(date_created.c_str());
471  omap.insert({"date_created", dstr});
472  dstr = new ddstr(start_direction.c_str());
473  omap.insert({"start_direction", dstr});
474  dstr = new ddstr(end_direction.c_str());
475  omap.insert({"end_direction", dstr});
476  dstr = new ddstr(day_night_flag.c_str());
477  omap.insert({"day_night_flag", dstr});
478  ddval<double>* ddoub = new ddval<double>(dtype::DOUBLE, esdist_correction);
479  omap.insert({"earth_sun_distance_correction", ddoub});
480  ddval<float>* dflt = new ddval<float>(dtype::FLOAT, start_center_lon);
481  omap.insert({"start_center_longitude", dflt});
482  dflt = new ddval<float>(dtype::FLOAT, start_center_lat);
483  omap.insert({"start_center_latitude", dflt});
484  dflt = new ddval<float>(dtype::FLOAT, end_center_lon);
485  omap.insert({"end_center_longitude", dflt});
486  dflt = new ddval<float>(dtype::FLOAT, end_center_lat);
487  omap.insert({"end_center_latitude", dflt});
488  dflt = new ddval<float>(dtype::FLOAT, northern_lat);
489  omap.insert({"northernmost_latitude", dflt});
490  dflt = new ddval<float>(dtype::FLOAT, southern_lat);
491  omap.insert({"southernmost_latitude", dflt});
492  dflt = new ddval<float>(dtype::FLOAT, eastern_lon);
493  omap.insert({"easternmost_longitude", dflt});
494  dflt = new ddval<float>(dtype::FLOAT, western_lon);
495  omap.insert({"westernmost_longitude", dflt});
496  dflt = new ddval<float>(dtype::FLOAT, geospatial_lat_max);
497  omap.insert({"geospatial_lat_max", dflt});
498  dflt = new ddval<float>(dtype::FLOAT, geospatial_lat_min);
499  omap.insert({"geospatial_lat_min", dflt});
500  dflt = new ddval<float>(dtype::FLOAT, geospatial_lon_max);
501  omap.insert({"geospatial_lon_max", dflt});
502  dflt = new ddval<float>(dtype::FLOAT, geospatial_lon_min);
503  omap.insert({"geospatial_lon_min", dflt});
504 
505  ddma<float,1>* gringlat = new ddma<float,1>(dtype::FLOAT, {0}, {8});
506  omap.insert({"GRingPointLatitude", gringlat});
507  gringlat->pts[0] = dslat->pts[0];
508  gringlat->pts[1] = dclat->pts[0];
509  gringlat->pts[2] = delat->pts[0];
510  gringlat->pts[3] = delat->pts[cscan];
511  gringlat->pts[4] = delat->pts[nscan-1];
512  gringlat->pts[5] = dclat->pts[nscan-1];
513  gringlat->pts[6] = dslat->pts[nscan-1];
514  gringlat->pts[7] = dslat->pts[cscan];
515  ddma<float,1>* gringlon = new ddma<float,1>(dtype::FLOAT, {0}, {8});
516  omap.insert({"GRingPointLongitude", gringlon});
517  gringlon->pts[0] = dslon->pts[0];
518  gringlon->pts[1] = dclon->pts[0];
519  gringlon->pts[2] = delon->pts[0];
520  gringlon->pts[3] = delon->pts[cscan];
521  gringlon->pts[4] = delon->pts[nscan-1];
522  gringlon->pts[5] = dclon->pts[nscan-1];
523  gringlon->pts[6] = dslon->pts[nscan-1];
524  gringlon->pts[7] = dslon->pts[cscan];
525  ddma<int,1>* gringseq = new ddma<int,1>(dtype::INT, {0}, {8});
526  omap.insert({"GRingPointSequenceNo", gringseq});
527  gringseq->pts[0] = 0;
528  gringseq->pts[1] = 1;
529  gringseq->pts[2] = 2;
530  gringseq->pts[3] = 3;
531  gringseq->pts[4] = 4;
532  gringseq->pts[5] = 5;
533  gringseq->pts[6] = 6;
534  gringseq->pts[7] = 7;
535 
536  strt = {0};
537  cntr = {NTWL};
538  ddma<float,1>* ddat = new ddma<float,1>(dtype::FLOAT, strt, cntr);
539  omap.insert({"vcal_gain", ddat});
540  ddat = new ddma<float,1>(dtype::FLOAT, strt, cntr);
541  omap.insert({"vcal_offset", ddat});
542  ddat = new ddma<float,1>(dtype::FLOAT, strt, cntr);
543  omap.insert({"F0", ddat});
544 
545  fsol_ = esdist_correction;
546  for (auto &it : DDProcess::rhot_band_names) {
547  string name = (string) it.first;
548  ddat->pts[(size_t)it.second] = F0[name]*fsol_;
549  }
550 
551  return omap;
552 }
553 
554 /**************************************************************************
555  * NAME: POCI::read_geo()
556  *
557  * DESCRIPTION: Virtual function to read geolocation data.
558  *
559  *************************************************************************/
560 map<string,ddata*> DDSensor::read_geo(const string & filepath,
561  vector<size_t> start, vector<size_t> count)
562 {
563  map<string,ddata*> omap;
564  return omap;
565 }
566 
567 /**************************************************************************
568  * NAME: POCI()
569  * DESCRIPTION: Class Constructor
570  *************************************************************************/
572 {
573 }
574 
575 /**************************************************************************
576  * NAME: ~POCI()
577  * DESCRIPTION: Class Destructor
578  *************************************************************************/
580 {
581 }
582 
583 /**************************************************************************
584  * NAME: noise_model()
585  *
586  * DESCRIPTION: Virtual instrument-dependent noise model. Noise coefficients
587  * entered in order: {C0,C1} such that C0 + C1 * lt
588  *
589  *************************************************************************/
590 float POCI::noise_model(float lt, int iw, float snr_mult)
591 {
592  float sigma, noise, snr, scaled_lt;
593  float coef[9][2] = {
594  {/*412:C0,C1*/2.1525676E-4, 1.283166E-5},
595  {/*488:*/2.4496944E-4, 9.037615E-6},
596  {/*550*/2.3188611E-4, 9.68949E-6},
597  {/*670*/2.011162E-5, 8.404901E-6},
598  {/*865*/3.2728847E-5, 2.2284337E-6},
599  {/*1240*/0.07877732, 0.00049940},
600  {/*1380*/0.0, 0.0},
601  {/*1610*/0.26743281, 0.01044864},
602  {/*2250*/0.00628912, 0.00021160}
603  };
604  scaled_lt = lt;
605  noise = coef[iw][0] + coef[iw][1] * scaled_lt;
606  snr = scaled_lt * snr_mult / noise; //noise model based on
607  sigma = 1 / snr;
608 
609  return sigma;
610 }
611 
612 /**************************************************************************
613  * NAME: POCI::read_l1b()
614  *
615  * DESCRIPTION: Read granule-level PACE L1B data and compute derived status
616  * values.
617  *
618  *************************************************************************/
619 
620 map<string,ddata*> POCI::read_l1b(const string & filepath,
621  vector<size_t> start, vector<size_t> count)
622 {
623  map<string, ddata*> omap;
624  int status = DTDB_SUCCESS;
625  ddval<int>* pstat = new ddval<int>(dtype::INT, status);
626  omap.insert({"status", pstat});
627 
628  NcFile* nc_input;
629  try {
630  nc_input = new NcFile(filepath, NcFile::read );
631  }
632  catch( NcException& e) {
633  e.what();
634  cerr << "POCI:: Failure opening PACE L1B input file: " + filepath << endl;
635  pstat->val = DTDB_FAIL;
636  return omap;
637  }
638  try {
639  NcGroup nc_group = nc_input->getGroup("observation_data");
640 
641  vector<size_t> countp = {1,count[0],count[1]};
642 
643  vector<size_t> startp = {bindex(410),start[0],start[1]};
644  ddma<float,2>* dda = new ddma<float,2>(nc_group,
645  "Lt_blue", dtype::FLOAT, startp, countp);
646  omap.insert({"rhot_410", dda});
647 
648  startp = {bindex(445),start[0],start[1]};
649  dda = new ddma<float,2>(nc_group,
650  "Lt_blue", dtype::FLOAT, startp, countp);
651  omap.insert({"rhot_445", dda});
652 
653  startp = {bindex(490),start[0],start[1]};
654  dda = new ddma<float,2>(nc_group,
655  "Lt_blue", dtype::FLOAT, startp, countp);
656  omap.insert({"rhot_490", dda});
657 
658  startp = {bindex(550),start[0],start[1]};
659  dda = new ddma<float,2>(nc_group,
660  "Lt_blue", dtype::FLOAT, startp, countp);
661  omap.insert({"rhot_550", dda});
662 
663  startp = {rindex(670),start[0],start[1]};
664  dda = new ddma<float,2>(nc_group,
665  "Lt_red", dtype::FLOAT, startp, countp);
666  omap.insert({"rhot_670", dda});
667 
668  startp = {rindex(865),start[0],start[1]};
669  dda = new ddma<float,2>(nc_group,
670  "Lt_red", dtype::FLOAT, startp, countp);
671  omap.insert({"rhot_865", dda});
672 
673  startp = {PS1250,start[0],start[1]};
674  dda = new ddma<float,2>(nc_group,
675  "Lt_SWIR", dtype::FLOAT, startp, countp);
676  omap.insert({"rhot_1240", dda});
677 
678  startp = {PS1378,start[0],start[1]};
679  dda = new ddma<float,2>(nc_group,
680  "Lt_SWIR", dtype::FLOAT, startp, countp);
681  omap.insert({"rhot_1380", dda});
682 
683  startp = {PS1615,start[0],start[1]};
684  dda = new ddma<float,2>(nc_group,
685  "Lt_SWIR", dtype::FLOAT, startp, countp);
686  omap.insert({"rhot_1610", dda});
687 
688  startp = {PS2260,start[0],start[1]};
689  dda = new ddma<float,2>(nc_group,
690  "Lt_SWIR", dtype::FLOAT, startp, countp);
691  omap.insert({"rhot_2250", dda});
692 
693 // Convert to VIIRS units
694  for ( size_t iy=0; iy<count[0]; iy++) {
695  for ( size_t ix=start[1]; ix<count[1]; ix++) {
696  for (auto &it : DDProcess::rhot_band_names) {
697  const string name = (string) it.first;
698  float rfl = static_cast<ddma<float,2>*>(omap[name])->pts[iy][ix];
699  float fbar = (float) F0[name];
700  if (rfl > 0) {
701  if (brad_) {
702  static_cast<ddma<float,2>*>(omap[name])->pts[iy][ix] = M_PI*rfl/(fbar*fsol_)/10.0;
703  } else {
704  static_cast<ddma<float,2>*>(omap[name])->pts[iy][ix] = M_PI*rfl;
705  }
706  }
707  }
708  }
709  }
710  }
711  catch( NcException& e) {
712  e.what();
713  cerr << "POCI::Failure reading PACE L1B input data." << endl;
714  pstat->val = DTDB_FAIL;
715  return omap;
716  }
717  delete nc_input;
718 
719  return omap;
720 }
721 
722 /**************************************************************************
723  * POCI::read_l1b_attributes()
724  *
725  * Read granule global attributes contained in input file
726  *
727  *************************************************************************/
728 map<string,ddata*> POCI::read_l1b_attributes(NcFile* nc_input)
729 {
730  map<string, ddata*> omap;
731  int status = DTDB_SUCCESS;
732  ddval<int>* pstat = new ddval<int>(dtype::INT, status);
733  omap.insert({"status", pstat});
734 
735  multimap <string, NcGroupAtt> attributes;
736 
737  attributes = nc_input->getAtts(NcGroup::Current);
738  string tcs,tce,tstr;
739  (attributes.find("time_coverage_start")->second).getValues(tcs);
740  ddstr* dstr = new ddstr(tcs);
741  omap.insert({"time_coverage_start", dstr});
742  (attributes.find("time_coverage_end")->second).getValues(tce);
743  dstr = new ddstr(tce);
744  omap.insert({"time_coverage_end", dstr});
745  (attributes.find("instrument")->second).getValues(tstr);
746  dstr = new ddstr(tstr);
747  omap.insert({"instrument", dstr});
748  dstr = new ddstr("PACE");
749  omap.insert({"platform", dstr});
750 
751  int normLt = -1;
752  (attributes.find("normalizedLt")->second).getValues(&normLt);
753  brad_ = (normLt==0) ? true : false;
754 
755 // 2015-08-18T17:30:00.000Z
756 
757  ddval<int>* dval = new ddval<int>(dtype::INT, atoi(tcs.substr(0,4).c_str()));
758  omap.insert({"start_year", dval});
759  int start_month = atoi(tcs.substr(5,2).c_str());
760  dval = new ddval<int>(dtype::INT, start_month);
761  omap.insert({"start_month", dval});
762  dval = new ddval<int>(dtype::INT, atoi(tcs.substr(8,2).c_str()));
763  omap.insert({"start_day", dval});
764  dval = new ddval<int>(dtype::INT, atoi(tcs.substr(11,2).c_str()));
765  omap.insert({"start_hour", dval});
766  dval = new ddval<int>(dtype::INT, atoi(tce.substr(11,2).c_str()));
767  omap.insert({"end_hour", dval});
768  dval = new ddval<int>(dtype::INT, atoi(tcs.substr(14,2).c_str()));
769  omap.insert({"start_minute", dval});
770  dval = new ddval<int>(dtype::INT, atoi(tce.substr(14,2).c_str()));
771  omap.insert({"end_minute", dval});
772  dval = new ddval<int>(dtype::INT, atoi(tcs.substr(17,2).c_str()));
773  omap.insert({"start_second", dval});
774  dval = new ddval<int>(dtype::INT, atoi(tce.substr(17,2).c_str()));
775  omap.insert({"end_second", dval});
776  int season = (start_month == 12) ? 0 : start_month/3;
777  dval = new ddval<int>(dtype::INT, season);
778  omap.insert({"season", dval});
779 
780  int num;
781  (attributes.find("orbit_number")->second).getValues(&num);
782  dval = new ddval<int>(dtype::INT, num);
783  omap.insert({"orbit_number", dval});
784 
785  dval = new ddval<int>(dtype::INT, nc_input->getDim("ccd_pixels").getSize());
786  omap.insert({"num_pixels", dval});
787  dval = new ddval<int>(dtype::INT, nc_input->getDim("number_of_scans").getSize());
788  omap.insert({"num_lines", dval});
789 
790  NcGroup nc_group = nc_input->getGroup("scan_line_attributes");
791  vector<size_t> starts = {0};
792  vector<size_t> counts = {(size_t)dval->val};
793  ddma<unsigned char,1>* ddh = new ddma<unsigned char,1>(nc_group,
794  "HAM_side", dtype::UBYTE, starts, counts);
795  omap.insert({"mside", ddh});
796  ddma<double,1>* dde = new ddma<double,1>(nc_group,
797  "time", dtype::DOUBLE, starts, counts);
798  omap.insert({"scan_time", dde});
799 
800  vector<size_t> startw = {0};
801  vector<size_t> countw = {NTWL};
802  ddma<int,1>* ddw = new ddma<int,1>(dtype::INT, startw, countw);
803  omap.insert({"wavelength", ddw});
804  ddw->pts[(size_t)rhot_band::W410] = 410;
805  ddw->pts[(size_t)rhot_band::W445] = 445;
806  ddw->pts[(size_t)rhot_band::W490] = 490;
807  ddw->pts[(size_t)rhot_band::W550] = 550;
808  ddw->pts[(size_t)rhot_band::W670] = 670;
809  ddw->pts[(size_t)rhot_band::W865] = 865;
810  ddw->pts[(size_t)rhot_band::W1240] = 1240;
811  ddw->pts[(size_t)rhot_band::W1380] = 1378;
812  ddw->pts[(size_t)rhot_band::W1610] = 1615;
813  ddw->pts[(size_t)rhot_band::W2250] = 2260;
814 
815  return omap;
816 }
817 
818 /**************************************************************************
819  * POCI::read_geo()
820  *
821  * Read geolocation input file
822  *
823  *************************************************************************/
824 map<string,ddata*> POCI::read_geo(const string & filepath,
825  vector<size_t> start, vector<size_t> count)
826 {
827  map<string, ddata*> omap;
828  int status = DTDB_SUCCESS;
829  ddval<int>* pstat = new ddval<int>(dtype::INT, status);
830  omap.insert({"status", pstat});
831 
832  NcFile* nc_input;
833  try {
834  nc_input = new NcFile(filepath, NcFile::read );
835  }
836  catch( NcException& e) {
837  e.what();
838  cerr << "POCI:: Failure opening PACE L1B input file: " + filepath << endl;
839  pstat->val = DTDB_FAIL;
840  return omap;
841  }
842 
843  ddma<float,2>* ddsen;
844  ddma<float,2>* ddsol;
845  try {
846  NcGroup nc_group = nc_input->getGroup("geolocation_data");
847 
848  ddma<float,2>* dda = new ddma<float,2>(nc_group,
849  "latitude", dtype::FLOAT, start, count);
850  omap.insert({"latitude", dda});
851 
852  dda = new ddma<float,2>(nc_group,
853  "longitude", dtype::FLOAT, start, count);
854  omap.insert({"longitude", dda});
855 
856  dda = new ddma<float,2>(nc_group,
857  "height", dtype::FLOAT, start, count);
858  omap.insert({"elevation", dda});
859 
860  ddsen = new ddma<float,2>(nc_group,
861  "sensor_azimuth", dtype::FLOAT, start, count);
862  omap.insert({"sensor_azimuth", ddsen});
863 
864  dda = new ddma<float,2>(nc_group,
865  "sensor_zenith", dtype::FLOAT, start, count);
866  omap.insert({"sensor_zenith", dda});
867 
868  ddsol = new ddma<float,2>(nc_group,
869  "solar_azimuth", dtype::FLOAT, start, count);
870  omap.insert({"solar_azimuth", ddsol});
871 
872  dda = new ddma<float,2>(nc_group,
873  "solar_zenith", dtype::FLOAT, start, count);
874  omap.insert({"solar_zenith", dda});
875  }
876  catch( NcException& e) {
877  e.what();
878  cerr << "POCI::Failure reading PACE L1B input data." << endl;
879  pstat->val = DTDB_FAIL;
880  return omap;
881  }
882  delete nc_input;
883 
885  for ( size_t iy=0; iy<count[0]; iy++) {
886  for ( size_t ix=start[1]; ix<count[1]; ix++) {
887  float raa = ddsen->pts[iy][ix] - ddsol->pts[iy][ix] - 180.0;
888  if (raa > 180.0) raa = raa - 360.0;
889  if (raa < -180.0) raa = raa + 360.0;
890  if (raa < 0.0) raa = -raa;
891  ddra->pts[iy][ix] = raa;
892  }
893  }
894  omap.insert({"relative_azimuth", ddra});
895  return omap;
896 }
897 
898 /**************************************************************************
899  * NAME: VIIRS()
900  * DESCRIPTION: Class Constructor
901  *************************************************************************/
903 {
904 }
905 
906 /**************************************************************************
907  * NAME: ~VIIRS()
908  * DESCRIPTION: Class Destructor
909  *************************************************************************/
911 {
912 }
913 
914 /**************************************************************************
915  * NAME: noise_model()
916  *
917  * DESCRIPTION: Virtual instrument-dependent noise model. Noise coefficients
918  * entered in order: {C0,C1} such that C0 + C1 * lt
919  *
920  *************************************************************************/
921 float VIIRS::noise_model(float lt, int iw, float snr_mult)
922 {
923  float sigma, noise, snr, scaled_lt;
924  float coef[9][2] = {
925  {/*412:C0,C1*/0.05499859, 0.00008340},
926  {/*488:*/0.01927545, 0.00009450},
927  {/*550*/0.08769538, 0.00007000},
928  {/*670*/0.00496291, 0.00014050},
929  {/*865*/0.00312263, 0.00018600},
930  {/*1240*/0.07877732, 0.00049940},
931  {/*1380*/0.0, 0.0},
932  {/*1610*/0.26743281, 0.01044864},
933  {/*2250*/0.00628912, 0.00021160}
934  };
935  scaled_lt = lt;
936  noise = coef[iw][0] + coef[iw][1] * scaled_lt;
937  snr = scaled_lt * snr_mult / noise; //noise model based on
938  sigma = 1 / snr;
939 
940  return sigma;
941 }
942 
943 /**************************************************************************
944  * NAME: VIIRS::read_l1b()
945  *
946  * DESCRIPTION: Read granule-level VIIRS L1B data and compute derived status
947  * values.
948  *
949  *************************************************************************/
950 map<string,ddata*> VIIRS::read_l1b(const string & filepath,
951  vector<size_t> start, vector<size_t> count)
952 {
953  map<string, ddata*> omap;
954  int status = DTDB_SUCCESS;
955  ddval<int>* pstat = new ddval<int>(dtype::INT, status);
956  omap.insert({"status", pstat});
957 
958  NcFile* nc_input;
959  try {
960  nc_input = new NcFile(filepath, NcFile::read );
961  }
962  catch( NcException& e) {
963  e.what();
964  cerr << "VIIRS:: Failure opening VIIRS L1B file: " + filepath << endl;
965  pstat->val = DTDB_FAIL;
966  return omap;
967  }
968  try {
969  NcGroup nc_group = nc_input->getGroup("observation_data");
970 
971  ddma<float,2>* dda = new ddma<float,2>(nc_group, "M01", dtype::FLOAT, start, count);
972  omap.insert({"rhot_410", dda});
973 
974  dda = new ddma<float,2>(nc_group, "M02", dtype::FLOAT, start, count);
975  omap.insert({"rhot_445", dda});
976 
977  dda = new ddma<float,2>(nc_group, "M03", dtype::FLOAT, start, count);
978  omap.insert({"rhot_490", dda});
979 
980  dda = new ddma<float,2>(nc_group, "M04", dtype::FLOAT, start, count);
981  omap.insert({"rhot_550", dda});
982 
983  dda = new ddma<float,2>(nc_group, "M05", dtype::FLOAT, start, count);
984  omap.insert({"rhot_670", dda});
985 
986  dda = new ddma<float,2>(nc_group, "M07", dtype::FLOAT, start, count);
987  omap.insert({"rhot_865", dda});
988 
989  dda = new ddma<float,2>(nc_group, "M08", dtype::FLOAT, start, count);
990  omap.insert({"rhot_1240", dda});
991 
992  dda = new ddma<float,2>(nc_group, "M09", dtype::FLOAT, start, count);
993  omap.insert({"rhot_1380", dda});
994 
995  dda = new ddma<float,2>(nc_group, "M10", dtype::FLOAT, start, count);
996  omap.insert({"rhot_1610", dda});
997 
998  dda = new ddma<float,2>(nc_group, "M11", dtype::FLOAT, start, count);
999  omap.insert({"rhot_2250", dda});
1000  }
1001  catch( NcException& e) {
1002  e.what();
1003  cerr << "VIIRS::Failure reading VIIRS L1B data." << endl;
1004  pstat->val = DTDB_FAIL;
1005  return omap;
1006  }
1007  delete nc_input;
1008 /*
1009  RsViirs* rv = new RsViirs( count[0], count[1]);
1010  rv->generate_sort_index();
1011  for (auto &it : omap) {
1012  string name = (string) it.first;
1013  rv->resort( (static_cast<ddma<float,2>*>(omap[name]))->pts );
1014  rv->fill_the_fills( (static_cast<ddma<float,2>*>(omap[name]))->pts );
1015  }
1016  delete rv;
1017 */
1018  return omap;
1019 }
1020 
1021 /**************************************************************************
1022  * VIIRS::read_l1b_attributes()
1023  *
1024  * Read granule global attributes contained in input file
1025  *
1026  *************************************************************************/
1027 map<string,ddata*> VIIRS::read_l1b_attributes(NcFile* nc_input)
1028 {
1029  map<string, ddata*> omap;
1030  int status = DTDB_SUCCESS;
1031  ddval<int>* pstat = new ddval<int>(dtype::INT, status);
1032  omap.insert({"status", pstat});
1033 
1034  multimap <string, NcGroupAtt> attributes;
1035 
1036  attributes = nc_input->getAtts(NcGroup::Current);
1037  string tcs,tce,tstr;
1038  (attributes.find("time_coverage_start")->second).getValues(tcs);
1039  ddstr* dstr = new ddstr(tcs);
1040  omap.insert({"time_coverage_start", dstr});
1041  (attributes.find("time_coverage_end")->second).getValues(tce);
1042  dstr = new ddstr(tce);
1043  omap.insert({"time_coverage_end", dstr});
1044  (attributes.find("instrument")->second).getValues(tstr);
1045  dstr = new ddstr(tstr);
1046  omap.insert({"instrument", dstr});
1047  dstr = new ddstr("VIIRS");
1048  omap.insert({"platform", dstr});
1049 
1050 // 2015-08-18T17:30:00.000Z
1051 
1052  ddval<int>* dval = new ddval<int>(dtype::INT, atoi(tcs.substr(0,4).c_str()));
1053  omap.insert({"start_year", dval});
1054  int start_month = atoi(tcs.substr(5,2).c_str());
1055  dval = new ddval<int>(dtype::INT, start_month);
1056  omap.insert({"start_month", dval});
1057  dval = new ddval<int>(dtype::INT, atoi(tcs.substr(8,2).c_str()));
1058  omap.insert({"start_day", dval});
1059  dval = new ddval<int>(dtype::INT, atoi(tcs.substr(11,2).c_str()));
1060  omap.insert({"start_hour", dval});
1061  dval = new ddval<int>(dtype::INT, atoi(tce.substr(11,2).c_str()));
1062  omap.insert({"end_hour", dval});
1063  dval = new ddval<int>(dtype::INT, atoi(tcs.substr(14,2).c_str()));
1064  omap.insert({"start_minute", dval});
1065  dval = new ddval<int>(dtype::INT, atoi(tce.substr(14,2).c_str()));
1066  omap.insert({"end_minute", dval});
1067  dval = new ddval<int>(dtype::INT, atoi(tcs.substr(17,2).c_str()));
1068  omap.insert({"start_second", dval});
1069  dval = new ddval<int>(dtype::INT, atoi(tce.substr(17,2).c_str()));
1070  omap.insert({"end_second", dval});
1071  int season = (start_month == 12) ? 0 : start_month/3;
1072  dval = new ddval<int>(dtype::INT, season);
1073  omap.insert({"season", dval});
1074 
1075  int num;
1076  (attributes.find("orbit_number")->second).getValues(&num);
1077  dval = new ddval<int>(dtype::INT, num);
1078  omap.insert({"orbit_number", dval});
1079 
1080  dval = new ddval<int>(dtype::INT, nc_input->getDim("number_of_pixels").getSize());
1081  omap.insert({"num_pixels", dval});
1082  dval = new ddval<int>(dtype::INT, nc_input->getDim("number_of_lines").getSize());
1083  omap.insert({"num_lines", dval});
1084 
1085  NcGroup nc_group = nc_input->getGroup("scan_line_attributes");
1086  vector<size_t> starts = {0};
1087  vector<size_t> countl = {(size_t)dval->val};
1088  vector<size_t> counts = {(size_t)dval->val/VDETECTORS};
1089  ddma<unsigned char,1>* ddh = new ddma<unsigned char,1>(dtype::UBYTE, starts, countl);
1090  omap.insert({"mside", ddh});
1091  ddma<double,1>* dde = new ddma<double,1>(dtype::DOUBLE, starts, countl);
1092  omap.insert({"scan_time", dde});
1093  double scantimes[VIIRSSCANS];
1094  nc_group.getVar("ev_mid_time").getVar( &scantimes[0] );
1095  for (size_t i=0; i<countl[0]; i++) {
1096  ddh->pts[i] = 255;
1097  dde->pts[i] = tai58_to_unix(scantimes[i/VIIRSSCANS]);
1098  }
1099 
1100  vector<size_t> startw = {0};
1101  vector<size_t> countw = {NTWL};
1102  ddma<int,1>* ddw = new ddma<int,1>(dtype::INT, startw, countw);
1103  omap.insert({"wavelength", ddw});
1104  ddw->pts[(size_t)rhot_band::W410] = 410;
1105  ddw->pts[(size_t)rhot_band::W445] = 445;
1106  ddw->pts[(size_t)rhot_band::W490] = 490;
1107  ddw->pts[(size_t)rhot_band::W550] = 550;
1108  ddw->pts[(size_t)rhot_band::W670] = 670;
1109  ddw->pts[(size_t)rhot_band::W865] = 865;
1110  ddw->pts[(size_t)rhot_band::W1240] = 1240;
1111  ddw->pts[(size_t)rhot_band::W1380] = 1380;
1112  ddw->pts[(size_t)rhot_band::W1610] = 1610;
1113  ddw->pts[(size_t)rhot_band::W2250] = 2250;
1114 
1115  return omap;
1116 }
1117 
1118 /**************************************************************************
1119  * NAME: VIIRS::read_geo()
1120  *
1121  * DESCRIPTION: Read VIIRS geolocation data and compute derived status
1122  * values.
1123  *
1124  *************************************************************************/
1125 
1126 map<string,ddata*> VIIRS::read_geo(const string & filepath,
1127  vector<size_t> start, vector<size_t> count)
1128 {
1129  map<string, ddata*> omap;
1130  int status = DTDB_SUCCESS;
1131  ddval<int>* pstat = new ddval<int>(dtype::INT, status);
1132  omap.insert({"status", pstat});
1133 
1134  NcFile* nc_input;
1135  try {
1136  nc_input = new NcFile(filepath, NcFile::read );
1137  }
1138  catch( NcException& e) {
1139  e.what();
1140  cerr << "VIIRS:: Failure opening VIIRS geo file: " + filepath << endl;
1141  pstat->val = DTDB_FAIL;
1142  return omap;
1143  }
1144 
1145  try {
1146  NcGroup nc_group = nc_input->getGroup("geolocation_data");
1147 
1148  ddma<float,2>* dda = new ddma<float,2>(nc_group,
1149  "latitude", dtype::FLOAT, start, count);
1150  omap.insert({"latitude", dda});
1151 
1152  dda = new ddma<float,2>(nc_group,
1153  "longitude", dtype::FLOAT, start, count);
1154  omap.insert({"longitude", dda});
1155 
1156  dda = new ddma<float,2>(nc_group,
1157  "height", dtype::FLOAT, start, count);
1158  omap.insert({"elevation", dda});
1159 
1160  dda = new ddma<float,2>(nc_group,
1161  "sensor_azimuth", dtype::FLOAT, start, count);
1162  omap.insert({"sensor_azimuth", dda});
1163 
1164  dda = new ddma<float,2>(nc_group,
1165  "sensor_zenith", dtype::FLOAT, start, count);
1166  omap.insert({"sensor_zenith", dda});
1167 
1168  dda = new ddma<float,2>(nc_group,
1169  "solar_azimuth", dtype::FLOAT, start, count);
1170  omap.insert({"solar_azimuth", dda});
1171 
1172  dda = new ddma<float,2>(nc_group,
1173  "solar_zenith", dtype::FLOAT, start, count);
1174  omap.insert({"solar_zenith", dda});
1175  }
1176  catch( NcException& e) {
1177  e.what();
1178  cerr << "VIIRS::Failure reading VIIRS geo data." << endl;
1179  pstat->val = DTDB_FAIL;
1180  return omap;
1181  }
1182  delete nc_input;
1183 
1185  for ( size_t iy=0; iy<count[0]; iy++) {
1186  for ( size_t ix=start[1]; ix<count[1]; ix++) {
1187  float sen = static_cast<ddma<float,2>*>(omap["sensor_azimuth"])->pts[iy][ix];
1188  float sol = static_cast<ddma<float,2>*>(omap["solar_azimuth"])->pts[iy][ix];
1189  float raa = sen - sol - 180.0;
1190  if (raa > 180.0) raa = raa - 360.0;
1191  if (raa < -180.0) raa = raa + 360.0;
1192  if (raa < 0.0) raa = -raa;
1193  ddra->pts[iy][ix] = raa;
1194  }
1195  }
1196  omap.insert({"relative_azimuth", ddra});
1197 
1198  return omap;
1199 }
1200 
map< string, ddata * > create(vector< size_t > start, vector< size_t > count)
Definition: DDSensor.cpp:74
void read_landmask(int argc, IDL_VPTR argv[])
Definition: read_landmask.c:8
~POCI()
Definition: DDSensor.cpp:579
#define LANDMASK_LAT
Definition: DDSensor.h:73
int32_t day
POCI()
Definition: DDSensor.cpp:571
int status
Definition: l1_czcs_hdf.c:32
#define DAYSCENE
Definition: l12_parms.h:87
@ UBYTE
unsigned 1 byte int
These are used to scale the SD before writing it to the HDF4 file The default is and which means the product is not scaled at all Since the product is usually stored as a float inside of this is a way to write the float out as a integer l2prod min
#define UNKNOWNSCENE
Definition: l12_parms.h:90
map< string, ddata * > read_l1b_attributes(NcFile *nc_input)
Definition: DDSensor.cpp:1027
map< string, float > F0
Definition: DDSensor.cpp:39
boost::multi_array< T, ndim > pts
Definition: DDataset.hpp:324
@ FLOAT
single precision floating point number
map< string, ddata * > read_l1b_attributes(NcFile *nc_input)
Definition: DDSensor.cpp:728
string get_option(const string &name)
Definition: DDOptions.cpp:211
float rfl[NOWL]
Definition: DbAlgOcean.cpp:41
float * lat
uint8 * counts
Definition: l1_czcs_hdf.c:30
float tm[MODELMAX]
double esdist_(int32_t *year, int32_t *day, int32_t *msec)
map< string, ddata * > read(vector< size_t > start, vector< size_t > count)
Definition: DDSensor.cpp:111
double lon[LANDMASK_LON]
Definition: DDSensor.h:79
unsigned long int random_seed()
Definition: loadl1.c:40
this program makes no use of any feature of the SDP Toolkit that could generate such a then geolocation is calculated at that and then aggregated up to Resolved feature request Bug by adding three new int8 SDSs for each high resolution offsets between the high resolution geolocation and a bi linear interpolation extrapolation of the positions This can be used to reconstruct the high resolution geolocation Resolved Bug by delaying cumulation of gflags until after validation of derived products Resolved Bug by setting Latitude and Longitude to the correct fill resolving to support Near Real Time because they may be unnecessary if use of entrained ephemeris and attitude data is turned resolving bug report Corrected to filter out Aqua attitude records with missing status helping resolve bug MOD_PR03 will still correctly write scan and pixel data that does not depend upon the start thereby resolving MODur00108 Changed header guard macro names to avoid reserved name resolving MODur00104 Maneuver list file for Terra satellite was updated to include data from Jecue DuChateu Maneuver list files for both Terra and Aqua were updated to include two maneuvers from recent IOT weekly reports The limits for Z component of angular momentum was and to set the fourth GEO scan quality flag for a scan depending upon whether or not it occurred during one of them Added _FillValue attributes to many and changed the fill value for the sector start times from resolving MODur00072 Writes boundingcoordinate metadata to L1A archived metadata For PERCENT *ECS change to treat rather resolving GSFcd01518 Added a LogReport Changed to create the Average Temperatures vdata even if the number of scans is
Definition: HISTORY.txt:301
int32 nscan
Definition: l1_czcs_hdf.c:19
const string INPUT_SLINE
Definition: DDOptions.cpp:31
#define DAYANDNIGHT
Definition: l12_parms.h:89
const string INPUT_ELINE
Definition: DDOptions.cpp:32
#define NIGHTSCENE
Definition: l12_parms.h:88
@ string
const string INPUT_L1B
Definition: DDOptions.cpp:40
string nodestr[3]
Definition: DDSensor.cpp:36
map< string, ddata * > read_geo(const string &filepath, vector< size_t > start, vector< size_t > count)
Definition: DDSensor.cpp:1126
@ PS2260
Definition: DDSensor.h:105
#define VIIRSSCANS
Definition: DDOptions.h:20
@ PS1615
Definition: DDSensor.h:104
map< string, ddata * > create_l2(map< string, ddata * >)
Definition: DDSensor.cpp:299
string daynightstr[4]
Definition: DDSensor.cpp:37
float noise_model(float rfl, int iw, float snr_mult)
Definition: DDSensor.cpp:590
virtual map< string, ddata * > read_geo(const string &filepath, vector< size_t > start, vector< size_t > count)
Definition: DDSensor.cpp:560
virtual map< string, ddata * > read_l1b_attributes(NcFile *nc_input)
Definition: DDSensor.cpp:284
int get_option_int(const string &name)
Definition: DDOptions.cpp:223
map< string, ddata * > read_l1b(const string &filepath, vector< size_t > start, vector< size_t > count)
Definition: DDSensor.cpp:950
#define DSCENDING
Definition: scene_meta.h:13
const string INPUT_GEO
Definition: DDOptions.cpp:41
#define ASCENDING
Definition: scene_meta.h:12
float make_noise(float sigma)
Definition: DDSensor.cpp:242
const string INPUT_SPIX
Definition: DDOptions.cpp:28
map< string, ddata * > read_l1b(const string &filepath, vector< size_t > start, vector< size_t > count)
Definition: DDSensor.cpp:620
#define M_PI
Definition: pml_iop.h:15
char watermask[LANDMASK_LAT][LANDMASK_LON]
Definition: DDSensor.h:80
~VIIRS()
Definition: DDSensor.cpp:910
#define VDETECTORS
Definition: DDOptions.h:21
string filepath
Definition: color_dtdb.py:207
virtual float noise_model(float rfl, int iw, float snr_mult)
Definition: DDSensor.cpp:259
virtual map< string, ddata * > read_l1b(const string &filepath, vector< size_t > start, vector< size_t > count)
Definition: DDSensor.cpp:268
#define SOLZNIGHT
Definition: l1.h:57
@ PS1250
Definition: DDSensor.h:104
double tai58_to_unix(double tai58)
Definition: yds2tai.c:29
float noise_model(float rfl, int iw, float snr_mult)
Definition: DDSensor.cpp:921
this program makes no use of any feature of the SDP Toolkit that could generate such a then geolocation is calculated at that and then aggregated up to Resolved feature request Bug by adding three new int8 SDSs for each high resolution offsets between the high resolution geolocation and a bi linear interpolation extrapolation of the positions This can be used to reconstruct the high resolution geolocation Resolved Bug by delaying cumulation of gflags until after validation of derived products Resolved Bug by setting Latitude and Longitude to the correct fill resolving to support Near Real Time because they may be unnecessary if use of entrained ephemeris and attitude data is turned resolving bug report Corrected to filter out Aqua attitude records with missing status helping resolve bug MOD_PR03 will still correctly write scan and pixel data that does not depend upon the start time
Definition: HISTORY.txt:248
int32 spix
Definition: l1_czcs_hdf.c:21
@ INT
signed 4 byte integer
virtual ~DDSensor()
Definition: DDSensor.cpp:65
float * lon
int32 epix
Definition: l1_czcs_hdf.c:23
const string INPUT_EPIX
Definition: DDOptions.cpp:29
const string INPUT_LANDMASK
Definition: DDOptions.cpp:45
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 as required for compatibility with version of the SDP toolkit Corrected test output file names to end in per delivery and then split off a new MYD_PR03 pcf file for Aqua Added AssociatedPlatformInstrumentSensor to the inventory metadata in MOD01 mcf and MOD03 mcf Created new versions named MYD01 mcf and MYD03 where AssociatedPlatformShortName is rather than Terra The program itself has been changed to read the Satellite Instrument validate it against the input L1A and LUT and to use it determine the correct files to retrieve the ephemeris and attitude data from Changed to produce a LocalGranuleID starting with MYD03 if run on Aqua data Added the Scan Type file attribute to the Geolocation copied from the L1A and attitude_angels to radians rather than degrees The accumulation of Cumulated gflags was moved from GEO_validate_earth_location c to GEO_locate_one_scan c
Definition: HISTORY.txt:464
DDSensor()
Definition: DDSensor.cpp:56
map< string, ddata * > read_landmask(map< string, ddata * > gmap, vector< size_t > start, vector< size_t > count)
Definition: DDSensor.cpp:165
VIIRS()
Definition: DDSensor.cpp:902
int i
Definition: decode_rs.h:71
double lat[LANDMASK_LAT]
Definition: DDSensor.h:78
msiBandIdx val
Definition: l1c_msi.cpp:34
static const map< string, rhot_band > rhot_band_names
Definition: DDProcess.h:156
@ PS1378
Definition: DDSensor.h:104
map< string, ddata * > read_geo(const string &filepath, vector< size_t > start, vector< size_t > count)
Definition: DDSensor.cpp:824
@ DOUBLE
double precision floating point number
unsigned long int random_seed()
Definition: DDSensor.cpp:229
el
Definition: decode_rs.h:168
int npix
Definition: get_cmp.c:27
#define LANDMASK_LON
Definition: DDSensor.h:74
l2prod max
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
int count
Definition: decode_rs.h:79