NASA Logo
Ocean Color Science Software

ocssw V2022
L3File.cpp
Go to the documentation of this file.
1 #include <L3File.h>
2 #include <genutils.h>
3 #include <boost/algorithm/string.hpp>
4 
5 #include "L3ShapeIsine.h"
6 
7 using namespace std;
8 //using namespace boost::geometry;
9 
10 namespace l3 {
11 
12 //----------------------------------------------------------------------------
13 // L3Bin
14 //----------------------------------------------------------------------------
15 
16 L3Bin::L3Bin(int32_t numProducts) {
17  internalInit(numProducts);
18 }
19 
20 L3Bin::L3Bin(const L3Bin &bin) {
21  internalCopy(bin);
22 }
23 
24 L3Bin::~L3Bin() {
25  free(sums);
26  free(sumSquares);
27 }
28 
29 void L3Bin::clear() {
30  binNum = -1;
31  recordNum = -1;
32  nobs = 0;
33  nscenes = 0;
34  timeRec = 0.0;
35  weights = 0.0;
36  quality = qualityUnused;
37  for (int i = 0; i < numProducts; i++) {
38  sums[i] = 0.0;
39  sumSquares[i] = 0.0;
40  }
41 }
42 
48 void L3Bin::internalAllocate(int32_t numProducts) {
49  if (numProducts != this->numProducts) {
50  if (sums)
51  free(sums);
52  if (sumSquares)
53  free(sumSquares);
54  sums = (float*) allocateMemory(numProducts * sizeof (float),
55  "sums for L3Bin");
56  sumSquares = (float*) allocateMemory(numProducts * sizeof (float),
57  "sumSquares for L3Bin");
58  this->numProducts = numProducts;
59  }
60 }
61 
66 void L3Bin::internalInit(int32_t numProducts) {
67  this->numProducts = 0;
68  sums = sumSquares = NULL;
69  internalAllocate(numProducts);
70  clear();
71 }
72 
78 void L3Bin::internalCopy(const L3Bin &bin) {
79  binNum = bin.binNum;
80  recordNum = bin.recordNum;
81  nobs = bin.nobs;
82  nscenes = bin.nscenes;
83  quality = bin.quality;
84  timeRec = bin.timeRec;
85  weights = bin.weights;
86 
87  internalAllocate(bin.numProducts);
88  memcpy(sums, bin.sums, numProducts * sizeof (float));
89  memcpy(sumSquares, bin.sumSquares, numProducts * sizeof (float));
90 }
91 
96 void L3Bin::internalAdd(const L3Bin &bin) {
97  if (numProducts != bin.numProducts) {
98  setNumProducts(bin.numProducts);
99  }
100  if (bin.quality != qualityUnused) {
101  if (bin.quality < quality) {
102  clear();
103  quality = bin.quality;
104  }
105  }
106  binNum = bin.binNum; // just copy the binNum
107  nobs += bin.nobs;
108  nscenes += bin.nscenes;
109  timeRec += bin.timeRec;
110  weights += bin.weights;
111  for (int i = 0; i < numProducts; i++) {
112  sums[i] += bin.sums[i];
113  sumSquares[i] += bin.sumSquares[i];
114  }
115 }
116 
117 void L3Bin::checkProdId(int32_t prodId) const {
118  if (prodId < 0) {
119  fprintf(stderr,
120  "-E- L3Bin::checkProdId - prodId (%d) must be positive\n",
121  prodId);
122  exit(EXIT_FAILURE);
123  }
124  if (prodId >= numProducts) {
125  fprintf(stderr,
126  "-E- L3Bin::checkProdId - prodId (%d) is greater than the numProducts (%d)\n",
127  prodId, numProducts);
128  exit(EXIT_FAILURE);
129  }
130 }
131 
132 L3Bin& L3Bin::operator=(const L3Bin &bin) {
133  internalCopy(bin);
134  return *this;
135 }
136 
137 L3Bin& L3Bin::operator+=(const L3Bin &bin) {
138  internalAdd(bin);
139  return *this;
140 }
141 
142 void L3Bin::addWeighted(const L3Bin &bin, float weighting) {
143  if (bin.quality != qualityUnused) {
144  if (bin.quality < quality) {
145  clear();
146  quality = bin.quality;
147  }
148  }
149  nobs += bin.nobs;
150  nscenes += bin.nscenes;
151  timeRec += bin.timeRec;
152  weights += bin.weights * weighting;
153  for (int i = 0; i < numProducts; i++) {
154  sums[i] += bin.sums[i] * weighting;
155  sumSquares[i] += bin.sumSquares[i] * weighting;
156  }
157 }
158 
163 void L3Bin::setNumProducts(int32_t numProducts) {
164  if (numProducts < 1) {
165  fprintf(stderr,
166  "-E- L3Bin::setNumProducts - numProducts (%d) must be at least 1\n",
167  numProducts);
168  exit(EXIT_FAILURE);
169  }
170  internalAllocate(numProducts);
171  clear();
172 }
173 
178 int32_t L3Bin::getNumProducts() const {
179  return numProducts;
180 }
181 
186 int64_t L3Bin::getBinNum() const {
187  return binNum;
188 }
189 
194 int32_t L3Bin::getNobs() const {
195  return nobs;
196 }
197 
202 int32_t L3Bin::getNscenes() const {
203  return nscenes;
204 }
205 
210 int64_t L3Bin::getRecordNum() const {
211  return recordNum;
212 }
213 
218 float L3Bin::getObsTime() const {
219  return timeRec / nobs;
220 }
221 
226 float L3Bin::getWeights() const {
227  return weights;
228 }
229 
234 uint8_t L3Bin::getQuality() const {
235  return quality;
236 }
237 
243 float L3Bin::getSum(int32_t prodId) const {
244  checkProdId(prodId);
245  return sums[prodId];
246 }
247 
253 float L3Bin::getSumSquares(int32_t prodId) const {
254  checkProdId(prodId);
255  return sumSquares[prodId];
256 }
257 
263 float L3Bin::getMean(int32_t prodId) const {
264  checkProdId(prodId);
265  return sums[prodId] / weights;
266 }
267 
273 float L3Bin::getVariance(int32_t prodId) const {
274  checkProdId(prodId);
275  if (weights * weights > nscenes) {
276  double val = sums[prodId] / weights;
277  val = (sumSquares[prodId] / weights) - (val * val);
278  return val * weights * weights / (weights * weights - nscenes);
279  }
280  return 0.0;
281 }
282 
288 float L3Bin::getStdev(int32_t prodId) const {
289  return sqrt(getVariance(prodId));
290 }
291 
292 
293 //----------------------------------------------------------------------------
294 // L3Row
295 //----------------------------------------------------------------------------
296 
297 L3Row::L3Row(int32_t row, int64_t numBins, int32_t numProducts) {
298  this->row = row;
299  this->numBins = numBins;
300  this->numProducts = numProducts;
301  binArray.resize(numBins);
302  for (int64_t i = 0; i < numBins; i++) {
303  binArray[i] = new L3Bin(numProducts);
304  }
305  lastBin = numBins / 2;
306 }
307 
308 L3Row::~L3Row() {
309  setNumBins(0);
310 }
311 
312 int32_t L3Row::getRow() const {
313  return row;
314 }
315 
316 int32_t L3Row::getNumProducts() const {
317  return numProducts;
318 }
319 
320 int64_t L3Row::getNumBins() const {
321  return numBins;
322 }
323 
324 void L3Row::setNumBins(int64_t numBins) {
325  this->numBins = numBins;
326  while (binArray.size() > (uint64_t) numBins) {
327  delete binArray.back();
328  binArray.pop_back();
329  }
330  while (binArray.size() < (uint64_t) numBins) {
331  binArray.push_back(new L3Bin(numProducts));
332  }
333  lastBin = numBins / 2;
334 }
335 
336 L3Bin* L3Row::getBin(int64_t binNum) {
337  L3Bin* l3Bin;
338  int64_t hi, mid, lo;
339  int64_t tmpBinNum;
340  int64_t tmp;
341 
342  if (numBins == 0)
343  return NULL;
344 
345  // start at the bin we found last time
346  lo = 0;
347  hi = numBins - 1;
348  mid = lastBin;
349 
350  while (lo <= hi) {
351  l3Bin = binArray[mid];
352  tmpBinNum = l3Bin->getBinNum();
353  if (tmpBinNum == binNum) {
354  lastBin = mid + 1;
355  if (lastBin >= numBins)
356  lastBin--;
357  if (l3Bin->nscenes == 0)
358  return NULL;
359  else
360  return l3Bin;
361  }
362  tmp = mid + (binNum - tmpBinNum);
363  if (binNum > tmpBinNum) {
364  lo = mid + 1;
365  if (hi > tmp)
366  hi = tmp;
367  } else {
368  hi = mid - 1;
369  if (lo < tmp)
370  lo = tmp;
371  }
372  mid = (lo + hi) / 2;
373  }
374  return NULL;
375 }
376 
382 L3Bin* L3Row::getBinByIndex(int32_t index) {
383  if (index < 0 || index >= numBins)
384  return NULL;
385  return binArray[index];
386 }
392 int64_t L3Row::getFirstBinNum() {
393  if (binArray.empty()){
394  return -1;
395  }
396  return binArray[0]->getBinNum();
397 }
398 
404 int64_t L3Row::getLastBinNum() {
405  if (binArray.empty()){
406  return -1;
407  }
408  return binArray.back()->getBinNum();
409 }
410 
411 //----------------------------------------------------------------------------
412 // L3File
413 //----------------------------------------------------------------------------
414 
415 L3File::L3File() {
416  shape = NULL;
417  binObj = NULL;
418  numCacheRows = 500;
419  baseRecord = NULL;
420  extentbin = NULL;
421  sumBuffer = NULL;
422  qualityBuffer = NULL;
423  prodMap = NULL;
424  numProds = 0;
425 }
426 
427 L3File::~L3File() {
428  close();
429  if (shape)
430  delete shape;
431  if (binObj)
432  delete binObj;
433 }
434 
435 void L3File::clearCache() {
436  L3Row* l3Row;
437  while (!rowList.empty()) {
438  l3Row = rowList.back();
439  delete l3Row;
440  rowList.pop_back();
441  }
442 }
443 
444 void L3File::setNumCacheRows(int32_t numRows) {
445  numCacheRows = numRows;
446  L3Row* l3Row;
447  while (rowList.size() > (uint32_t) numRows) {
448  l3Row = rowList.back();
449  delete l3Row;
450  rowList.pop_back();
451  }
452 }
453 
454 bool L3File::open(const char* fileName) {
455  close();
456  int tmpWantVerbose = want_verbose;
457  want_verbose = 0;
458  binObj = Hdf::openBinObject(fileName);
459  want_verbose = tmpWantVerbose;
460  if (binObj == NULL)
461  return false;
462  shape = new L3ShapeIsine(binObj->nrows);
463  initRecordLookup();
464  return true;
465 }
466 
467 void L3File::close() {
468  if (shape) {
469  delete shape;
470  shape = NULL;
471  }
472  if (binObj) {
473  delete binObj;
474  binObj = NULL;
475  }
476  if (sumBuffer) {
477  free(sumBuffer);
478  sumBuffer = NULL;
479  }
480  if (qualityBuffer) {
481  free(qualityBuffer);
482  qualityBuffer = NULL;
483  }
484  if (baseRecord) {
485  free(baseRecord);
486  baseRecord = NULL;
487  }
488  if (extentbin) {
489  free(extentbin);
490  extentbin = NULL;
491  }
492  clearCache();
493  if (prodMap) {
494  free(prodMap);
495  prodMap = NULL;
496  }
497 }
498 
499 meta_l3bType* L3File::getMetaData() {
500  if (binObj) {
501  return &binObj->meta_l3b;
502  }
503  return NULL;
504 }
505 
510 int L3File::initRecordLookup() {
511 
512  if (binObj->nrows == 0) {
513  fprintf(stderr,
514  "-E- %s %d: initRecordLookup: Number of rows needs to be set and bin grid must be initialized first.\n",
515  __FILE__, __LINE__);
516  exit(EXIT_FAILURE);
517  }
518 
519  // remove memory if it exists
520  if (baseRecord) {
521  free(baseRecord);
522  }
523  baseRecord = (int64_t*) allocateMemory(binObj->nrows * sizeof (int64_t),
524  "baseRecord");
525  if (extentbin) {
526  free(extentbin);
527  }
528  extentbin = (int32_t*) allocateMemory(binObj->nrows * sizeof (int32_t),
529  "extbin");
530 
531  int64_t index = 0;
532  for (int row = 0; row < binObj->nrows; row++) {
533  binObj->readBinIndex(row);
534  int32_t extent = binObj->get_ext();
535  extentbin[row] = extent;
536  if (extent > 0) {
537  baseRecord[row] = index;
538  index += extent;
539  } else {
540  baseRecord[row] = -1;
541  }
542  }
543  return 0;
544 }
545 
553 int64_t L3File::rowbin2record(int32_t row, int64_t bin) {
554  int64_t recordIndex;
555 
556  recordIndex = baseRecord[row];
557  if (recordIndex == -1) // there are no records in this row
558  return -1;
559  L3Row* l3Row = getRow(row);
560  if (l3Row == NULL || l3Row->getNumBins() == 0)
561  return -1;
562  L3Bin* l3Bin = l3Row->getBin(bin);
563  if (l3Bin == NULL)
564  return -1;
565  return l3Bin->getRecordNum();
566 }
567 
574 int64_t L3File::rowcol2record(int32_t row, int32_t col) {
575  int64_t bin;
576  bin = shape->rowcol2bin(row, col);
577  return rowbin2record(row, bin);
578 }
579 
586 int64_t L3File::latlon2record(float lat, float lon) {
587  int32_t row, col;
588  int64_t bin;
589  shape->latlon2rowcol(lat, lon, row, col);
590  bin = shape->rowcol2bin(row, col);
591  return rowbin2record(row, bin);
592 }
593 
599 int64_t L3File::bin2record(int64_t bin) {
600  int32_t row;
601  row = shape->bin2row(bin);
602  return rowbin2record(row, bin);
603 }
604 
605 int32_t L3File::getNumProducts() {
606  if (binObj == NULL)
607  return 0;
608  return binObj->nprod();
609 }
610 
612  return binObj->getProdName(index);
613 }
614 
615 bool L3File::setActiveProductList(const char* prodStr) {
616  //free the sum buffer since it depends on the number of products
617  if (sumBuffer) {
618  free(sumBuffer);
619  sumBuffer = NULL;
620  }
621  clearCache();
622  int status = binObj->read((char*) prodStr);
623  if (status == -1)
624  return false;
625 
626  // find number of products
627  string tmpStr(prodStr);
628  activeProdNameList.clear();
629  boost::split(activeProdNameList, tmpStr, boost::is_any_of(","));
630 
631  // populate the product map
632  prodMap = (size_t*) allocateMemory(
633  activeProdNameList.size() * sizeof (size_t), "prodMap");
634  numProds = activeProdNameList.size();
635  for (size_t myIndex = 0; myIndex < numProds; myIndex++) {
636  boost::trim(activeProdNameList[myIndex]);
637  for (int32_t objIndex = 0; objIndex < binObj->n_active_prod;
638  objIndex++) {
639  if (activeProdNameList[myIndex].compare(
640  binObj->getActiveProdName(objIndex)) == 0) {
641  prodMap[myIndex] = objIndex;
642  break;
643  }
644  }
645  }
646 
647  outBin.setNumProducts(activeProdNameList.size());
648 
649  return true;
650 }
651 
652 int32_t L3File::getNumActiveProducts() {
653  return activeProdNameList.size();
654 }
655 
656 string L3File::getActiveProductName(size_t index) {
657  return activeProdNameList[index];
658 }
659 
660 L3Row* L3File::readRow(int32_t row) {
661  L3Row* l3Row;
662 
663  if (row < 0 || row >= binObj->nrows)
664  return NULL;
665 
666  int32_t extent = extentbin[row];
667  int64_t base = baseRecord[row];
668  if (rowList.size() < (uint32_t) numCacheRows) {
669  l3Row = new L3Row(row, extent, numProds);
670  } else {
671  l3Row = rowList.back();
672  rowList.pop_back();
673  l3Row->setNumBins(extent);
674  l3Row->row = row;
675  }
676  rowList.push_front(l3Row);
677 
678  if (extent == 0)
679  return l3Row;
680 
681  // read the bin list
682  binObj->readBinList(extent, base);
683 
684  // allocate the sum buffer if necessary
685  if (sumBuffer == NULL)
686  sumBuffer = (float*) allocateMemory(
687  4 * binObj->nrows * binObj->n_active_prod * sizeof (float),
688  "L3File::sumBuffer");
689 
690  binObj->setDataPtrAbsolute(base);
691  binObj->readSums(sumBuffer, extent, -1);
692 
693  if (qualityBuffer)
694  binObj->readQual((uint8_t*) qualityBuffer, extent, base);
695 
696  L3Bin* l3Bin;
697  size_t sumOffset;
698  for (int i = 0; i < extent; i++) {
699  l3Bin = l3Row->binArray[i];
700  l3Bin->binNum = binObj->get_bin_num(i);
701  l3Bin->recordNum = base + i;
702  l3Bin->nobs = binObj->get_nobs(i);
703  l3Bin->nscenes = binObj->get_nscenes(i);
704  l3Bin->timeRec = binObj->get_time_rec(i);
705  l3Bin->weights = binObj->get_weights(i);
706  for (size_t prod = 0; prod < numProds; prod++) {
707  sumOffset = prodMap[prod] * extent * 2 + i * 2;
708  l3Bin->sums[prod] = sumBuffer[sumOffset];
709  l3Bin->sumSquares[prod] = sumBuffer[sumOffset + 1];
710  }
711  if (qualityBuffer)
712  l3Bin->quality = qualityBuffer[i];
713  else
714  l3Bin->quality = L3Bin::qualityUnused;
715  }
716  return l3Row;
717 }
718 
719 L3Row* L3File::getRow(int32_t row) {
720  L3Row* l3Row;
721 
722  // check first cache position
723  list<L3Row*>::iterator it = rowList.begin();
724  if (it != rowList.end()) {
725  l3Row = *it;
726  if (l3Row->getRow() == row)
727  return l3Row;
728  }
729 
730  // check the rest of the cache
731  for (it++; it != rowList.end(); it++) {
732  l3Row = *it;
733  if (l3Row->getRow() == row) {
734  if (it != rowList.begin()) {
735  rowList.erase(it);
736  rowList.push_front(l3Row);
737  }
738  return l3Row;
739  }
740  }
741 
742  // not found in cache, so read the row
743  return readRow(row);
744 }
745 
750 int32_t L3File::getNumRows() {
751  if (shape) {
752  return shape->getNumRows();
753  }
754  return -1;
755 }
756 
763 L3Bin* L3File::getClosestBin(float lat, float lon) {
764  if (shape == NULL) {
765  fprintf(stderr,
766  "-E- %s %d: need to open L3File before looking for a bin.\n",
767  __FILE__, __LINE__);
768  exit(EXIT_FAILURE);
769  }
770  int32_t row, col;
771  shape->latlon2rowcol(lat, lon, row, col);
772  L3Row* l3Row = getRow(row);
773  if (l3Row == NULL)
774  return NULL;
775  int64_t binNum = shape->rowcol2bin(row, col);
776  return l3Row->getBin(binNum);
777 }
778 
785 L3Bin* L3File::getBin(int32_t row, int32_t col) {
786  if (shape == NULL) {
787  fprintf(stderr,
788  "-E- %s %d: need to open L3File before looking for a bin.\n",
789  __FILE__, __LINE__);
790  exit(EXIT_FAILURE);
791  }
792  if (row < 0 || row >= shape->getNumRows())
793  return NULL;
794  if (col < 0 || col >= shape->getNumCols(row))
795  return NULL;
796 
797  L3Row* l3Row = getRow(row);
798  if (l3Row == NULL)
799  return NULL;
800  int64_t binNum = shape->rowcol2bin(row, col);
801  return l3Row->getBin(binNum);
802 }
803 
808 Hdf::hdf_bin* L3File::getHdfBinObject() const {
809  return binObj;
810 }
811 
812 bool L3File::hasQuality() {
813  if (binObj) {
814  return binObj->has_qual();
815  }
816  return false;
817 }
818 
819 void L3File::setQualityProcessing(bool val) {
820  if (qualityBuffer)
821  free(qualityBuffer);
822  qualityBuffer = NULL;
823  if (val) {
824  if (shape == NULL) {
825  fprintf(stderr,
826  "-E- %s %d: need to open L3File before setting qualityProcessing.\n",
827  __FILE__, __LINE__);
828  exit(EXIT_FAILURE);
829  }
830  qualityBuffer = (uint8_t*) allocateMemory(2 * shape->getNumRows(),
831  "L3File::qualityBuffer");
832  }
833 }
834 
835 bool L3File::getQualityProcessing() const {
836  if (qualityBuffer)
837  return true;
838  else
839  return false;
840 }
847 int64_t L3File::getBaseBin(int32_t row) const {
848  return baseRecord[row];
849 }
850 
857 int32_t L3File::getRowExtent(int32_t row) const {
858  return extentbin[row];
859 }
860 } // namespace l3
an array had not been initialized Several spelling and grammar corrections were which is read from the appropriate MCF the above metadata values were hard coded A problem calculating the average background DN for SWIR bands when the moon is in the space view port was corrected The new algorithm used to calculate the average background DN for all reflective bands when the moon is in the space view port is now the same as the algorithm employed by the thermal bands For non SWIR changes in the averages are typically less than Also for non SWIR the black body DNs remain a backup in case the SV DNs are not available For SWIR the changes in computed averages were larger because the old which used the black body suffered from contamination by the micron leak As a consequence of the if SV DNs are not available for the SWIR the EV pixels will not be the granule time is used to identify the appropriate tables within the set given for one LUT the first two or last two tables respectively will be used for the interpolation If there is only one LUT in the set of it will be treated as a constant LUT The manner in which Earth View data is checked for saturation was changed Previously the raw Earth View DNs and Space View DNs were checked against the lookup table values contained in the table dn_sat The change made is to check the raw Earth and Space View DNs to be sure they are less than the maximum saturation value and to check the Space View subtracted Earth View dns against a set of values contained in the new lookup table dn_sat_ev The metadata configuration and ASSOCIATEDINSTRUMENTSHORTNAME from the MOD02HKM product The same metatdata with extensions and were removed from the MOD021KM and MOD02OBC products ASSOCIATEDSENSORSHORTNAME was set to MODIS in all products These changes are reflected in new File Specification which users may consult for exact the pow functions were eliminated in Emissive_Cal and Emissive bands replaced by more efficient code Other calculations throughout the code were also made more efficient Aside from a few round off there was no difference to the product The CPU time decreased by about for a day case and for a night case A minor bug in calculating the uncertainty index for emissive bands was corrected The frame index(0-based) was previously being used the frame number(1-based) should have been used. There were only a few minor changes to the uncertainty index(maximum of 1 digit). 3. Some inefficient arrays(Sigma_RVS_norm_sq) were eliminated and some code lines in Preprocess_L1A_Data were moved into Process_OBCEng_Emiss. There were no changes to the product. Required RAM was reduced by 20 MB. Now
virtual bool has_qual()=0
int status
Definition: l1_czcs_hdf.c:32
float * sumSquares
Definition: L3File.h:74
void * allocateMemory(size_t numBytes, const char *name)
Definition: allocateMemory.c:7
#define NULL
Definition: decode_rs.h:63
L3Bin * getBin(int64_t binNum)
Definition: L3File.cpp:336
int32_t nscenes
Definition: L3File.h:69
hdf_bin * openBinObject(const char *binFileName)
Definition: bin_io.cpp:32
std::vector< L3Bin * > binArray
Definition: L3File.h:125
float32 base
Definition: maplists.h:106
int32_t row
Definition: L3File.h:122
int32_t nobs
Definition: L3File.h:68
int32_t nobs
Definition: atrem_cor.h:93
data_t tmp
Definition: decode_rs.h:74
uint8_t quality
Definition: L3File.h:70
float weights
Definition: L3File.h:72
int32_t getRow() const
Definition: L3File.cpp:312
int want_verbose
int64_t getNumBins() const
Definition: L3File.cpp:320
int64_t getBinNum() const
Definition: L3File.cpp:186
string & trim(string &s, const string &delimiters)
Definition: EnvsatUtil.cpp:29
int64_t binNum
Definition: L3File.h:66
void getProductName(char *name, l2prodstr *product)
float timeRec
Definition: L3File.h:71
void setNumBins(int64_t numBins)
Definition: L3File.cpp:324
int64_t getRecordNum() const
Definition: L3File.cpp:210
int16_t * nscenes
Definition: l2bin.cpp:80
Definition: L3File.cpp:10
int64_t recordNum
Definition: L3File.h:67
float * sums
Definition: L3File.h:73
int i
Definition: decode_rs.h:71