NASA Logo
Ocean Color Science Software

ocssw V2022
l3mapgen.cpp
Go to the documentation of this file.
1 /*
2  * l3mapgen.cpp
3  *
4  * Created on: Jan 15, 2014
5  * Author: dshea
6  */
7 #include "l3mapgen.h"
8 
9 #include "OutFile.h"
10 #include <L3FileSMI.h>
11 
12 #include <iostream>
13 #include <iomanip>
14 #include <fstream>
15 
16 #include <genutils.h>
17 #include <timeutils.h>
18 #include <nc4utils.h>
19 #include <string>
20 
21 #include <proj.h>
22 #include <sensorInfo.h>
23 #include <productInfo.h>
24 #include <boost/algorithm/string.hpp>
25 #include <boost/lexical_cast.hpp>
26 #include <unordered_map>
27 #include <unordered_set>
28 #include <boost/algorithm/string.hpp>
29 #define EXIT_LOG(...) \
30  { \
31  __VA_ARGS__; \
32  std::cerr << "Exiting. See line " << __LINE__ << " in " << __FILE__ << std::endl; \
33  exit(EXIT_FAILURE); \
34  }
35 
36 using namespace std;
37 using namespace l3;
38 
39 #define NUM_SEARCH_POINTS 51
40 
44 // namespace to hold 3d expansion/mapping between 3D and 2D
45 namespace wv3d {
46 std::vector<std::string> wavelength_3d_list_separated;
47 std::unordered_map<std::string, std::vector<int32_t>> wv3d_2d_name_to_3d_expansion;
48 std::unordered_map<std::string, std::string> wv3d_3d_name_to_2d_name;
49 std::vector<std::string> output_products_with_3d;
51 } // namespace wv3d
52 
53 const std::unordered_map<std::string, std::vector<int32_t>>& get_wv3d_2d_name_to_3d_expansion() {
55 }
56 
57 const std::unordered_map<std::string, std::string>& get_wv3d_3d_name_to_2d_name() {
59 }
60 
61 size_t get_len_wv3d() {
63 }
64 
66  switch (measure) {
67  case Avg:
68  return "";
69  case Stdev:
70  return "_stdev";
71  case Variance:
72  return "_var";
73  case Nobs:
74  return "_nobs";
75  case Nscenes:
76  return "_nscenes";
77  case ObsTime:
78  return "_obs_time";
79  case BinNum:
80  return "_bin_num";
81  default:
82  return "";
83  }
84 }
85 // global params for program
86 double widthInDeg;
87 double heightInDeg;
88 double mapEast;
89 double mapWest;
90 
91 int imageWidth = 0;
92 int imageHeight = 0;
93 bool doingQuality = false;
94 bool doingRGB = false;
95 bool doingTransparency = false;
96 bool trimNSEW = false;
97 bool write_projtext = false;
98 
99 string prodName;
100 vector<string> prodNameList;
101 vector<MeasurementType> prodMeasurementList;
102 string qualName;
103 
105 
106 // landmask
107 bool applyMask = false;
108 static grid_info_t* landmaskGrid = {0};
109 
110 int isLand(float lat, float lon) {
111  if (landmaskGrid != NULL) {
112  double value;
113  int status = get_bylatlon(landmaskGrid, lat, lon, &value);
114  if (!status)
115  return ((short)value != 1); // 1 = water
116  }
117  return (0); // assume water if lon, lat not found
118 }
119 
120 void printStartInfo(vector<OutFile*> outFiles) {
121  if (want_verbose) {
122  meta_l3bType* metaData = outFiles[0]->getMetadata();
123 
125  printf("ifile : %s\n", clo_getString(optionList, "ifile"));
126  printf("ofile : ");
127  for (OutFile* outFile : outFiles) {
128  if (outFile == outFiles[0])
129  printf("%s", outFile->getFileName().c_str());
130  else
131  printf(",%s", outFile->getFileName().c_str());
132  }
133  printf("\n");
134 
135  printf("oformat : %s\n", clo_getString(optionList, "oformat"));
136  if (clo_isSet(optionList, "ofile2")) {
137  printf("ofile2 : %s\n", clo_getString(optionList, "ofile2"));
138  printf("oformat2 : %s\n", clo_getString(optionList, "oformat2"));
139  }
140  printf("projection : %s\n", clo_getRawString(optionList, "projection"));
141  printf("resolution : %.3fm\n", outFiles[0]->getResolution());
142  if (clo_isSet(optionList, "width"))
143  printf("width : %d\n", clo_getInt(optionList, "width"));
144  if (doingRGB)
145  printf("product_rgb: %s\n", prodName.c_str());
146  else
147  printf("product : %s\n", prodName.c_str());
148  if (doingQuality)
149  printf("qual_prod : %s\n", qualName.c_str());
150  printf("north : %8.3f\n", metaData->north);
151  printf("south : %8.3f\n", metaData->south);
152  printf("east : %8.3f\n", metaData->east);
153  printf("west : %8.3f\n", metaData->west);
154  float tmpf = clo_getFloat(optionList, "central_meridian");
155  if (tmpf > -900.0) {
156  printf("central_meridian : %8.3f\n", tmpf);
157  }
158  if (clo_isSet(optionList, "lat_ts")) {
159  printf("lat_ts : %8.3f\n", clo_getFloat(optionList, "lat_ts"));
160  }
161  if (clo_isSet(optionList, "lat_0")) {
162  printf("lat_0 : %8.3f\n", clo_getFloat(optionList, "lat_0"));
163  }
164  if (clo_isSet(optionList, "azimuth")) {
165  printf("azimuth : %8.3f\n", clo_getFloat(optionList, "azimuth"));
166  }
167  printf("image size : %d x %d\n", imageHeight, imageWidth);
168 
169  printf("\n");
170  }
171 }
172 
173 void printEndInfo(OutFile* outFile) {
174  if (want_verbose) {
175  printf("\n\n");
176  printf("actual data min : %f\n", outFile->getFileMinVal());
177  printf("actual data max : %f\n", outFile->getFileMaxVal());
178  printf("num filled pixels : %d\n", outFile->getNumFilledPixels());
179  printf("percent filled pixels : %.2f%%\n", outFile->getPercentFilledPixels());
180  printf("\n");
181  }
182 }
183 
184 void printPercentDone(float percentDone) {
185  static float percentPrev = 0.0;
186  static const float percentDelta = 0.01;
187  if (want_verbose && (percentDone - percentPrev > percentDelta)) {
188  percentPrev = percentDone;
189  printf("\r%2d%% complete", (int)(percentDone * 100));
190  fflush(stdout);
191  }
192 }
193 
195  int i;
196  float centralMeridian = clo_getFloat(optionList, "central_meridian");
197  if (centralMeridian > -900.0) {
198  i = 0;
199  while (centralMeridian < -180.0) {
200  centralMeridian += 360.0;
201  i++;
202  if (i > 5) {
203  printf("-E- central meridian is way off\n");
204  exit(EXIT_FAILURE);
205  }
206  }
207  i = 0;
208  while (centralMeridian > 180.0) {
209  centralMeridian -= 360.0;
210  i++;
211  if (i > 5) {
212  printf("-E- central meridian is way off\n");
213  exit(EXIT_FAILURE);
214  }
215  }
216  } else {
217  centralMeridian = (mapWest + mapEast) / 2.0;
218  }
219  return constrainLon(centralMeridian);
220 }
221 
223  string s = str;
224  boost::trim(s);
225  boost::to_lower(s);
226 
227  if (s.compare("bin") == 0)
228  return Interp_Bin;
229  if (s.compare("linear") == 0)
230  return Interp_Linear;
231  if (s.compare("area") == 0)
232  return Interp_Area;
233 
234  return Interp_Nearest;
235 }
236 
238  switch (interp) {
239  case Interp_Nearest:
240  return "nearest";
241  case Interp_Bin:
242  return "bin";
243  case Interp_Linear:
244  return "linear";
245  case Interp_Area:
246  return "area";
247  default:
248  return "unknown";
249  }
250 }
251 
252 bool checkDateLineCrossed(double lon, double deltaLon) {
253  bool crossed = false;
254 
255  float minlon = constrainLon(lon) - (deltaLon / 2.0);
256  float maxlon = constrainLon(lon) + (deltaLon / 2.0);
257 
258  if (minlon > 0 && maxlon < 0)
259  crossed = true;
260 
261  return crossed;
262 }
263 
264 Box_t getBox(float lat, float lon, float deltaLat, float deltaLon, int eastwest = notEastOrWest) {
265  Point_t pMin;
266  Point_t pMax;
267  lon = constrainLon(lon);
268  if (eastwest == IsEast) {
269  pMin.set<0>(180.0);
270  pMin.set<1>(lat - (deltaLat / 2.0));
271  pMax.set<0>(lon + (deltaLon / 2.0));
272  pMax.set<1>(lat + (deltaLat / 2.0));
273  } else if (eastwest == IsWest) {
274  pMin.set<0>(lon - (deltaLon / 2.0));
275  pMin.set<1>(lat - (deltaLat / 2.0));
276  pMax.set<0>(180.0);
277  pMax.set<1>(lat + (deltaLat / 2.0));
278  } else {
279  pMin.set<0>(lon - (deltaLon / 2.0));
280  pMin.set<1>(lat - (deltaLat / 2.0));
281  pMax.set<0>(lon + (deltaLon / 2.0));
282  pMax.set<1>(lat + (deltaLat / 2.0));
283  }
284  Box_t box(pMin, pMax);
285  return box;
286 }
287 
288 L3Bin* getBoxBins(L3File* l3File, float lat, float lon, float deltaLat, float deltaLon, float fudge,
289  bool areaWeighted, int eastwest = notEastOrWest) {
290  Box_t box = getBox(lat, lon, deltaLat, deltaLon, eastwest);
291 
292  L3Bin* l3Bin = l3File->getBinsInside(box, areaWeighted);
293 
294  if (!l3Bin && fudge > 1) { // try again with fudge factor
295  Box_t box = getBox(lat, lon, deltaLat * fudge, deltaLon * fudge, eastwest);
296  l3Bin = l3File->getBinsInside(box, areaWeighted);
297  }
298  return l3Bin;
299 }
300 
306 bool setupQualityProcessing(L3File* l3File, vector<OutFile*> outFiles, OutFile* outFile2) {
307  doingQuality = true;
308  clo_option_t* option = clo_findOption(optionList, "use_quality");
309  if (clo_isOptionSet(option)) {
310  if (clo_getOptionBool(option)) {
311  if (l3File->hasQuality()) {
312  doingQuality = true;
313  } else {
314  printf(
315  "-E- Quality processing was requested, "
316  "but the input file does not have quality data.\n");
317  exit(EXIT_FAILURE);
318  }
319  if (clo_isSet(optionList, "quality_product")) {
320  qualName = clo_getRawString(optionList, "quality_product");
321  } else {
322  qualName = "qual_" + prodNameList[0];
323  }
324  } else {
325  doingQuality = false;
326  }
327  } else {
328  if (l3File->hasQuality())
329  doingQuality = true;
330  else
331  doingQuality = false;
332  }
333 
335  for (OutFile* outFile : outFiles) {
336  outFile->setQualityProcessing(doingQuality);
337  outFile->setQualityName(qualName);
338  }
339  if (outFile2) {
341  outFile2->setQualityName(qualName);
342  }
343  return doingQuality;
344 }
345 
346 void setupProduct(string& prodName, MeasurementType measure, OutFile* outFile, OutFile* outFile2) {
347  // get the product info
348  productInfo_t* p_info;
349  p_info = allocateProductInfo();
350 
351  int sensorId = sensorName2SensorId(outFile->getMetadata()->sensor_name);
352  if (sensorId == -1) {
353  printf("-E- Unknown sensor name %s\n", outFile->getMetadata()->sensor_name);
354  exit(EXIT_FAILURE);
355  }
356 
357  if (!findProductInfo(prodName.c_str(), sensorId, p_info)) {
358  printf("-E- product %s not found in XML product table\n", prodName.c_str());
359  exit(EXIT_FAILURE);
360  }
361 
362  // now we have to fix the p_info structure
363  // Avg, Stdev, Variance, Nobs, Nscenes, ObsTime, BinNum
364  string tmpStr;
365  switch (measure) {
366  case Avg:
367  break;
368  case Stdev:
369  tmpStr = p_info->description;
370  free(p_info->description);
371  tmpStr += " (Standard Deviation)";
372  p_info->description = strdup(tmpStr.c_str());
373  free(p_info->palette);
374  p_info->palette = strdup(PRODUCT_DEFAULT_palette);
375  free(p_info->dataType);
376  p_info->dataType = strdup("float");
377  tmpStr = p_info->suffix;
378  free(p_info->suffix);
379  tmpStr += "_stdev";
380  p_info->suffix = strdup(tmpStr.c_str());
381  free(p_info->displayScale);
382  p_info->displayScale = strdup("linear");
383  p_info->addOffset = 0.0;
384  p_info->scaleFactor = 1.0;
385  break;
386  case Variance:
387  tmpStr = p_info->description;
388  free(p_info->description);
389  tmpStr += " (Variance)";
390  p_info->description = strdup(tmpStr.c_str());
391  free(p_info->palette);
392  p_info->palette = strdup(PRODUCT_DEFAULT_palette);
393  free(p_info->dataType);
394  p_info->dataType = strdup("float");
395  tmpStr = p_info->suffix;
396  free(p_info->suffix);
397  tmpStr += "_var";
398  p_info->suffix = strdup(tmpStr.c_str());
399  free(p_info->displayScale);
400  p_info->displayScale = strdup("linear");
401  p_info->addOffset = 0.0;
402  p_info->scaleFactor = 1.0;
403  break;
404  case Nobs:
405  tmpStr = p_info->description;
406  free(p_info->description);
407  tmpStr += " (number of observations)";
408  p_info->description = strdup(tmpStr.c_str());
409  free(p_info->units);
410  p_info->units = strdup("counts");
411  free(p_info->palette);
412  p_info->palette = strdup(PRODUCT_DEFAULT_palette);
413  free(p_info->dataType);
414  p_info->dataType = strdup("short");
415  tmpStr = p_info->suffix;
416  free(p_info->suffix);
417  tmpStr += "_nobs";
418  p_info->suffix = strdup(tmpStr.c_str());
419  p_info->fillValue = PRODUCT_DEFAULT_fillValue;
420  p_info->validMin = 0;
421  p_info->validMax = 32767;
422  free(p_info->displayScale);
423  p_info->displayScale = strdup("linear");
424  p_info->displayMin = PRODUCT_DEFAULT_displayMin;
425  p_info->displayMax = PRODUCT_DEFAULT_displayMax;
426  p_info->addOffset = 0.0;
427  p_info->scaleFactor = 1.0;
428  break;
429  case Nscenes:
430  tmpStr = p_info->description;
431  free(p_info->description);
432  tmpStr += " (number of scenes)";
433  p_info->description = strdup(tmpStr.c_str());
434  free(p_info->units);
435  p_info->units = strdup("counts");
436  free(p_info->palette);
437  p_info->palette = strdup(PRODUCT_DEFAULT_palette);
438  free(p_info->dataType);
439  p_info->dataType = strdup("short");
440  tmpStr = p_info->suffix;
441  free(p_info->suffix);
442  tmpStr += "_nscenes";
443  p_info->suffix = strdup(tmpStr.c_str());
444  p_info->fillValue = PRODUCT_DEFAULT_fillValue;
445  p_info->validMin = 0;
446  p_info->validMax = 32767;
447  free(p_info->displayScale);
448  p_info->displayScale = strdup("linear");
449  p_info->displayMin = PRODUCT_DEFAULT_displayMin;
450  p_info->displayMax = PRODUCT_DEFAULT_displayMax;
451  p_info->addOffset = 0.0;
452  p_info->scaleFactor = 1.0;
453  break;
454  case ObsTime:
455  tmpStr = p_info->description;
456  free(p_info->description);
457  tmpStr += " (observation time, TAI93)";
458  p_info->description = strdup(tmpStr.c_str());
459  free(p_info->units);
460  p_info->units = strdup("counts");
461  free(p_info->palette);
462  p_info->palette = strdup(PRODUCT_DEFAULT_palette);
463  free(p_info->dataType);
464  p_info->dataType = strdup("float");
465  tmpStr = p_info->suffix;
466  free(p_info->suffix);
467  tmpStr += "_obs_time";
468  p_info->suffix = strdup(tmpStr.c_str());
469  p_info->fillValue = PRODUCT_DEFAULT_fillValue;
470  p_info->validMin = PRODUCT_DEFAULT_validMin;
471  p_info->validMax = PRODUCT_DEFAULT_validMin;
472  free(p_info->displayScale);
473  p_info->displayScale = strdup("linear");
474  p_info->displayMin = PRODUCT_DEFAULT_displayMin;
475  p_info->displayMax = PRODUCT_DEFAULT_displayMax;
476  p_info->addOffset = 0.0;
477  p_info->scaleFactor = 1.0;
478  break;
479  case BinNum:
480  tmpStr = p_info->description;
481  free(p_info->description);
482  tmpStr += " (bin ID number)";
483  p_info->description = strdup(tmpStr.c_str());
484  free(p_info->units);
485  p_info->units = strdup("dimensionless");
486  free(p_info->palette);
487  p_info->palette = strdup(PRODUCT_DEFAULT_palette);
488  free(p_info->dataType);
489  p_info->dataType = strdup("int");
490  tmpStr = p_info->suffix;
491  free(p_info->suffix);
492  tmpStr += "_bin_num";
493  p_info->suffix = strdup(tmpStr.c_str());
494  p_info->fillValue = PRODUCT_DEFAULT_fillValue;
495  p_info->validMin = PRODUCT_DEFAULT_validMin;
496  p_info->validMax = PRODUCT_DEFAULT_validMin;
497  free(p_info->displayScale);
498  p_info->displayScale = strdup("linear");
499  p_info->displayMin = PRODUCT_DEFAULT_displayMin;
500  p_info->displayMax = PRODUCT_DEFAULT_displayMax;
501  p_info->addOffset = 0.0;
502  p_info->scaleFactor = 1.0;
503  break;
504  } // switch
505 
506  // load landmask options before palette
507  applyMask = clo_getBool(optionList, "mask_land");
508  if (applyMask) {
509  char* strVal = clo_getOptionString(clo_findOption(optionList, "land"));
510  char landmaskFile[FILENAME_MAX];
511  parse_file_name(strVal, landmaskFile);
512  static const char* landmaskVars[] = {"watermask", "landmask", "z", NULL};
513  landmaskGrid = allocate_gridinfo();
514  int status = init_gridinfo(landmaskFile, landmaskVars, landmaskGrid);
515  if (status != NC_NOERR) {
516  free(landmaskGrid);
517  landmaskGrid = NULL;
518  cerr << "Error reading file " << landmaskFile << ": " << nc_strerror(status) << "\n"
519  << "Land mask will not be applied.\n";
520  applyMask = false;
521  }
522  }
523 
524  // load palette
525  if (clo_getBool(optionList, "apply_pal")) {
526  // set land_rgb before loading palette
527  outFile->setLandRGB(clo_getRawString(optionList, "rgb_land"));
528  if (outFile2)
529  outFile2->setLandRGB(clo_getRawString(optionList, "rgb_land"));
530 
531  clo_option_t* option = clo_findOption(optionList, "palfile");
532  if (clo_isOptionSet(option)) {
533  outFile->setPalette(clo_getOptionString(option), applyMask);
534  if (outFile2)
535  outFile2->setPalette(clo_getOptionString(option), applyMask);
536  } else {
537  outFile->setPalette(p_info->palette, applyMask);
538  if (outFile2)
539  outFile2->setPalette(p_info->palette, applyMask);
540  }
541  }
542 
543  // set the default scale factors for RGB
544  if (doingRGB) {
545  p_info->displayMin = 0.01;
546  p_info->displayMax = 0.9;
547  if (p_info->displayScale)
548  free(p_info->displayScale);
549  p_info->displayScale = strdup("log");
550  }
551 
552  // override default scale parameters if set on command line
553  if (clo_isSet(optionList, "datamin")) {
554  p_info->displayMin = clo_getFloat(optionList, "datamin");
555  }
556  if (clo_isSet(optionList, "datamax")) {
557  p_info->displayMax = clo_getFloat(optionList, "datamax");
558  }
559  if (clo_isSet(optionList, "scale_type")) {
560  if (p_info->displayScale)
561  free(p_info->displayScale);
562  p_info->displayScale = strdup(clo_getString(optionList, "scale_type"));
563  }
564 
565  outFile->addProduct(p_info);
566  if (outFile2)
567  outFile2->addProduct(p_info);
568 
569  freeProductInfo(p_info);
570 }
571 
572 void writeRawFile(L3File* l3File, vector<OutFile*> outFiles, OutFile* outFile2) {
573  L3Bin* l3Bin;
574  L3Row* l3Row;
575  imageHeight = l3File->getNumRows();
576  double resolution = EARTH_CIRCUMFERENCE / (imageHeight * 2);
577  imageWidth = imageHeight * 2;
578  int32_t start;
579  int32_t numBins;
580  int64_t baseBin;
581  int64_t endBin;
582  int64_t binNum;
583  int32_t row, col;
584 
585  int32_t numFilledPixels = 0;
586  meta_l3bType* metaData = outFiles[0]->getMetadata();
587 
588  string mapDesc = "Bin";
589  string projName = "Integerized Sinusoidal";
590 
591  if (clo_isSet(optionList, "suite"))
592  sprintf(metaData->title, "%s Level-3 %s Mapped Image %s", metaData->sensor_name, mapDesc.c_str(), clo_getString(optionList, "suite"));
593  else
594  sprintf(metaData->title, "%s Level-3 %s Mapped Image", metaData->sensor_name, mapDesc.c_str());
595  for (OutFile* outFile : outFiles) {
596  strcpy(outFile->getMetadata()->title, metaData->title);
597  outFile->setFullLatLon(false);
598  outFile->setMapProjection(projName);
599  outFile->setResolution(resolution);
600  outFile->setSize(imageWidth, imageHeight);
601  }
602  if (outFile2) {
603  strcpy(outFile2->getMetadata()->title, metaData->title);
604  outFile2->setFullLatLon(false);
605  outFile2->setMapProjection(projName);
606  outFile2->setResolution(resolution);
607  outFile2->setSize(imageWidth, imageHeight);
608  }
609 
610  // setup all the product structures
611  for (size_t i = 0; i < prodNameList.size(); i++) {
612  OutFile* outFile;
613  if (outFiles.size() == 1)
614  outFile = outFiles[0];
615  else
616  outFile = outFiles[i];
617  setupProduct(prodNameList[i], prodMeasurementList[i], outFile, outFile2);
618  }
619 
620  printStartInfo(outFiles);
621 
622  for (OutFile* outFile : outFiles) {
623  if (!outFile->open()) {
624  printf("-E- Could not open ofile=\"%s\".\n", outFile->getFileName().c_str());
625  exit(EXIT_FAILURE);
626  }
627  }
628  if (outFile2) {
629  if (!outFile2->open()) {
630  printf("-E- Could not open ofile2=\"%s\".\n", outFile2->getFileName().c_str());
631  exit(EXIT_FAILURE);
632  }
633  }
634 
635  float centralMeridian = getCentralMeridian();
636 
637  for (row = imageHeight - 1; row >= 0; row--) {
638  printPercentDone(1.0 - (float)row / (float)imageHeight);
639 
640  l3Row = l3File->getRow(row);
641  numBins = l3File->getShape()->getNumCols(row);
642  baseBin = l3File->getShape()->getBaseBin(row);
643  endBin = baseBin + numBins;
644  if (centralMeridian < 0)
645  binNum = baseBin + numBins * (centralMeridian + 360.0) / 360.0;
646  else
647  binNum = baseBin + numBins * centralMeridian / 360.0;
648  start = (imageWidth - numBins) / 2;
649 
650  // clear out beginning empty pixels
651  for (col = 0; col < start; col++) {
652  for (OutFile* outFile : outFiles)
653  outFile->fillPixel(col);
654  if (outFile2)
655  outFile2->fillPixel(col);
656  }
657 
658  // set pixel values
659  for (int i = 0; i < numBins; i++) {
660  l3Bin = l3Row->getBin(binNum);
661  if (l3Bin) {
662  if (doingRGB) {
663  outFiles[0]->setPixelRGB(col, l3Bin->getMean(0), l3Bin->getMean(1), l3Bin->getMean(2));
664  if (outFile2)
665  outFile2->setPixelRGB(col, l3Bin->getMean(0), l3Bin->getMean(1), l3Bin->getMean(2));
666  } else {
667  for (size_t prod = 0; prod < prodNameList.size(); prod++) {
668  float val;
669  switch (prodMeasurementList[prod]) {
670  case Avg:
671  val = l3Bin->getMean(prod);
672  break;
673  case Stdev:
674  val = l3Bin->getStdev(prod);
675  break;
676  case Variance:
677  val = l3Bin->getVariance(prod);
678  break;
679  case Nobs:
680  val = l3Bin->getNobs();
681  break;
682  case Nscenes:
683  val = l3Bin->getNscenes();
684  break;
685  case ObsTime:
686  val = l3Bin->getObsTime();
687  break;
688  case BinNum:
689  val = l3Bin->getBinNum();
690  break;
691  default:
692  val = l3Bin->getMean(prod);
693  }
694  if (outFiles.size() == 1)
695  outFiles[0]->setPixel(col, val, prod);
696  else
697  outFiles[prod]->setPixel(col, val, 0);
698  if (outFile2)
699  outFile2->setPixel(col, val, prod);
700  }
701  }
702  numFilledPixels++;
703  } else {
704  for (OutFile* outFile : outFiles)
705  outFile->missingPixel(col);
706  if (outFile2)
707  outFile2->missingPixel(col);
708  }
709  col++;
710  binNum++;
711  if (binNum >= endBin)
712  binNum = baseBin;
713  }
714 
715  // clear out trailing empty pixels
716  for (; col < imageWidth; col++) {
717  for (OutFile* outFile : outFiles)
718  outFile->fillPixel(col);
719  if (outFile2)
720  outFile2->fillPixel(col);
721  }
722 
723  for (OutFile* outFile : outFiles)
724  outFile->writeLine();
725  if (outFile2)
726  outFile2->writeLine();
727  }
728 
729  for (OutFile* outFile : outFiles) {
730  outFile->setNumFilledPixels(numFilledPixels);
731  outFile->close();
732  }
733  if (outFile2) {
734  outFile2->setNumFilledPixels(numFilledPixels);
735  outFile2->close();
736  }
737 }
738 
739 void writeSmiFile(L3File* l3File, vector<OutFile*> outFiles, OutFile* outFile2) {
740  int32_t numFilledPixels = 0;
741  meta_l3bType* metaData = outFiles[0]->getMetadata();
742  double resolution = outFiles[0]->getResolution();
743 
744  string mapDesc = "Standard";
745  string projName = "Equidistant Cylindrical";
746 
747  sprintf(metaData->title, "%s Level-3 %s Mapped Image", metaData->sensor_name, mapDesc.c_str());
748 
749  // set up image parameters
750  if (imageWidth <= 0) {
752  if (imageWidth == 0)
753  imageWidth = 1;
754  } else {
756  for (OutFile* outFile : outFiles)
757  outFile->setResolution(resolution);
758  if (outFile2)
759  outFile2->setResolution(resolution);
760  }
762  if (imageHeight == 0)
763  imageHeight = 1;
764  double deltaLon = widthInDeg / imageWidth;
765  double deltaLat = heightInDeg / imageHeight;
766 
767  for (OutFile* outFile : outFiles) {
768  strcpy(outFile->getMetadata()->title, metaData->title);
769  outFile->setSize(imageWidth, imageHeight);
770  outFile->setMapProjection(projName);
771  }
772  if (outFile2) {
773  strcpy(outFile2->getMetadata()->title, metaData->title);
774  outFile2->getMetadata()->east = metaData->east;
775  outFile2->getMetadata()->west = metaData->west;
776  outFile2->setSize(imageWidth, imageHeight);
777  outFile2->setMapProjection(projName);
778  }
779 
780  // set up all the product structures
781  for (size_t i = 0; i < prodNameList.size(); i++) {
782  OutFile* outFile;
783  if (outFiles.size() == 1)
784  outFile = outFiles[0];
785  else
786  outFile = outFiles[i];
787  setupProduct(prodNameList[i], prodMeasurementList[i], outFile, outFile2);
788  }
789  // set up quality processing
790  setupQualityProcessing(l3File, outFiles, outFile2);
791 
792  printStartInfo(outFiles);
793 
794  for (OutFile* outFile : outFiles) {
795  if (!outFile->open()) {
796  printf("-E- Could not open ofile=\"%s\".\n", outFile->getFileName().c_str());
797  exit(EXIT_FAILURE);
798  }
799  }
800 
801  if (outFile2) {
802  if (!outFile2->open()) {
803  printf("-E- Could not open ofile2=\"%s\".\n", outFile2->getFileName().c_str());
804  exit(EXIT_FAILURE);
805  }
806  }
807 
809  float fudge = clo_getFloat(optionList, "fudge");
810 
811  // loop through output pixels
812  double lat = metaData->north - (deltaLat / 2.0);
813  L3Bin* l3Bin;
814 
815  for (int row = 0; row < imageHeight; row++) {
816  printPercentDone((float)row / (float)imageHeight);
817  double lon = metaData->west + (deltaLon / 2.0);
818 
819  for (int col = 0; col < imageWidth; col++) {
820  if (applyMask && isLand(lat, lon)) {
821  for (OutFile* outFile : outFiles)
822  outFile->landPixel(col);
823  if (outFile2)
824  outFile2->landPixel(col);
825 
826  } else {
827  switch (interp) {
828  case Interp_Nearest:
829  l3Bin = l3File->getClosestBin(lat, lon);
830  break;
831  case Interp_Bin:
832  case Interp_Area: {
833  bool areaWeighted;
834 
835  if (interp == Interp_Area)
836  areaWeighted = true;
837  else
838  areaWeighted = false;
839 
840  l3Bin = getBoxBins(l3File, lat, lon, deltaLat, deltaLon, fudge, areaWeighted);
841 
842  break;
843  }
844  default:
845  printf("-E- interp = %s is not implemented.", interpType2Str(interp));
846  exit(EXIT_FAILURE);
847  }
848 
849  if (l3Bin) {
850  numFilledPixels++;
851  if (doingRGB) {
852  outFiles[0]->setPixelRGB(col, l3Bin->getMean(0), l3Bin->getMean(1),
853  l3Bin->getMean(2));
854  if (outFile2)
855  outFile2->setPixelRGB(col, l3Bin->getMean(0), l3Bin->getMean(1),
856  l3Bin->getMean(2));
857  } else {
858  for (size_t prod = 0; prod < prodNameList.size(); prod++) {
859  float val;
860  switch (prodMeasurementList[prod]) {
861  case Avg:
862  val = l3Bin->getMean(prod);
863  break;
864  case Stdev:
865  val = l3Bin->getStdev(prod);
866  break;
867  case Variance:
868  val = l3Bin->getVariance(prod);
869  break;
870  case Nobs:
871  val = l3Bin->getNobs();
872  break;
873  case Nscenes:
874  val = l3Bin->getNscenes();
875  break;
876  case ObsTime:
877  val = l3Bin->getObsTime();
878  break;
879  case BinNum:
880  val = l3Bin->getBinNum();
881  break;
882  default:
883  val = l3Bin->getMean(prod);
884  }
885  if (outFiles.size() == 1)
886  outFiles[0]->setPixel(col, val, prod);
887  else
888  outFiles[prod]->setPixel(col, val, 0);
889  if (outFile2)
890  outFile2->setPixel(col, val, prod);
891  }
892  }
893  if (doingQuality) {
894  for (OutFile* outFile : outFiles)
895  outFile->setQuality(col, l3Bin->getQuality());
896  if (outFile2)
897  outFile2->setQuality(col, l3Bin->getQuality());
898  }
899  } else {
900  for (OutFile* outFile : outFiles)
901  outFile->missingPixel(col);
902  if (outFile2)
903  outFile2->missingPixel(col);
904  }
905  }
906  lon += deltaLon;
907  } // for col
908  for (OutFile* outFile : outFiles)
909  outFile->writeLine();
910  if (outFile2)
911  outFile2->writeLine();
912  lat -= deltaLat;
913  } // for row
914 
915  for (OutFile* outFile : outFiles) {
916  outFile->setNumFilledPixels(numFilledPixels);
917  outFile->close();
918  }
919  if (outFile2) {
920  outFile2->setNumFilledPixels(numFilledPixels);
921  outFile2->close();
922  }
923 }
924 
925 // writing netcdf 4 file
926 // the writitng is done here
927 void writeProj4File(L3File* l3File, char* projectionStr, vector<OutFile*> outFiles, OutFile* outFile2,
928  bool trimNSEW) {
929  int32_t numFilledPixels = 0;
930  meta_l3bType* metaData = outFiles[0]->getMetadata();
931  double resolution = outFiles[0]->getResolution();
932 
933  L3Bin* l3Bin;
934 
935  // how about circumference of earth + 25%
936  double limitMin = EARTH_CIRCUMFERENCE * -0.625;
937  double limitMax = EARTH_CIRCUMFERENCE * 0.625;
938  // calculate the min and max
939  double minX = limitMax;
940  double minY = limitMax;
941  double maxX = limitMin;
942  double maxY = limitMin;
943  bool* inBox;
944  double lat, lon;
945  double x, y;
946  double deltaLat = (metaData->north - metaData->south) / (NUM_SEARCH_POINTS - 1);
947  double deltaLon = (mapEast - mapWest) / (NUM_SEARCH_POINTS - 1);
948 
949  // parse central meridian (lon_0)
950  float centralMeridian = getCentralMeridian();
951  string cmStr = " +lon_0=" + to_string(centralMeridian);
952  string tsStr;
953  if (clo_isSet(optionList, "lat_ts")) {
954  tsStr = " +lat_ts=" + to_string(clo_getFloat(optionList, "lat_ts"));
955  }
956 
957  float lat0 = (metaData->north + metaData->south) / 2.0;
958  string lat0Str;
959  if (clo_isSet(optionList, "lat_0")) {
960  lat0 = clo_getFloat(optionList, "lat_0");
961  }
962  lat0Str = " +lat_0=" + to_string(lat0);
963 
964  string lat1Str;
965  if (clo_isSet(optionList, "lat_1")) {
966  lat1Str = " +lat_1=" + to_string(clo_getFloat(optionList, "lat_1"));
967  } else {
968  lat1Str = " +lat_1=" + to_string(metaData->south);
969  }
970  string lat2Str;
971  if (clo_isSet(optionList, "lat_2")) {
972  lat2Str = " +lat_2=" + to_string(clo_getFloat(optionList, "lat_2"));
973  } else {
974  lat2Str = " +lat_2=" + to_string(metaData->north);
975  }
976  string aziStr;
977  if (clo_isSet(optionList, "azimuth")) {
978  aziStr = " +alpha=" + to_string(clo_getFloat(optionList, "azimuth"));
979  }
980  string utmStr;
981  if (clo_isSet(optionList, "utm_zone")) {
982  string zone = clo_getString(optionList, "utm_zone");
983  utmStr = " +zone=";
984  utmStr += zone;
985  if (utmStr.find('S') != std::string::npos) {
986  utmStr.pop_back();
987  utmStr += " +south";
988  }
989  }
990 
991  // define proj.4 parameters according to shortcut
992  string mapDesc;
993  string projName;
994  string projStr;
995 
996  if (strcasecmp(projectionStr, "mollweide") == 0) {
997  mapDesc = "Mollweide";
998  projName = "Mollweide";
999  projStr = "+proj=moll +ellps=WGS84 +datum=WGS84";
1000  projStr += cmStr;
1001 
1002  } else if (strcasecmp(projectionStr, "lambert") == 0) {
1003  mapDesc = "Lambert";
1004  projName = "Lambert";
1005  projStr = "+proj=lcc +ellps=WGS84 +datum=WGS84";
1006  projStr += cmStr + lat0Str + lat1Str + lat2Str;
1007 
1008  } else if (strcasecmp(projectionStr, "albersconic") == 0) {
1009  mapDesc = "Albers Equal Area Conic";
1010  projName = "Albersconic";
1011  projStr = "+proj=aea +ellps=WGS84 +datum=WGS84";
1012  projStr += cmStr + lat0Str + lat1Str + lat2Str;
1013 
1014  } else if (strcasecmp(projectionStr, "aeqd") == 0) {
1015  mapDesc = "Azimuthal Equidistant";
1016  projName = "AzimuthalEquidistant";
1017  projStr = "+proj=aeqd +ellps=WGS84 +datum=WGS84";
1018  projStr += cmStr + lat0Str;
1019 
1020  } else if (strcasecmp(projectionStr, "mercator") == 0) {
1021  mapDesc = "Mercator";
1022  projName = "Mercator";
1023  projStr = "+proj=merc +ellps=WGS84 +datum=WGS84";
1024  projStr += cmStr;
1025 
1026  } else if (strcasecmp(projectionStr, "tmerc") == 0) {
1027  mapDesc = "Transverse Mercator";
1028  projName = "TransverseMercator";
1029  projStr = "+proj=tmerc +ellps=WGS84 +datum=WGS84";
1030  projStr += cmStr + lat0Str;
1031 
1032  } else if (strcasecmp(projectionStr, "utm") == 0) {
1033  mapDesc = "Universal Transverse Mercator";
1034  projName = "UTM";
1035  projStr = "+proj=utm";
1036  projStr += utmStr;
1037 
1038  } else if (strcasecmp(projectionStr, "obliquemerc") == 0) {
1039  if (!clo_isSet(optionList, "lat_0") || !clo_isSet(optionList, "azimuth")) {
1040  printf("-E- lat_0 and azimuth need to be defined for obliquemerc projection");
1041  exit(EXIT_FAILURE);
1042  }
1043  mapDesc = "Oblique Mercator";
1044  projName = "ObliqueMercator";
1045  projStr = "+proj=omerc +gamma=0 +k_0=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84";
1046  projStr += lat0Str;
1047  projStr += " +lonc=" + to_string(centralMeridian);
1048  projStr += aziStr;
1049 
1050  } else if (strcasecmp(projectionStr, "ease2") == 0) {
1051  mapDesc = "Ease Grid 2";
1052  projName = "Ease2";
1053  projStr = "EPSG:6933";
1054 
1055  } else if (strcasecmp(projectionStr, "stere") == 0) {
1056  if (!clo_isSet(optionList, "lat_0") || !clo_isSet(optionList, "lat_ts")) {
1057  printf("-E- lat_0 and lat_ts need to be defined for stere projection");
1058  exit(EXIT_FAILURE);
1059  }
1060  mapDesc = "Stereographic";
1061  projName = "Stereo";
1062  projStr =
1063  "+proj=stere "
1064  " +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
1065  projStr += cmStr + tsStr + lat0Str;
1066 
1067  } else if (strcasecmp(projectionStr, "ortho") == 0) {
1068  mapDesc = "Orthographic";
1069  projName = "Ortho";
1070  projStr =
1071  "+proj=ortho "
1072  " +ellps=GRS80 +units=m +no_defs";
1073  projStr += cmStr + lat0Str;
1074 
1075  } else if (strcasecmp(projectionStr, "conus") == 0) {
1076  mapDesc = "USA Contiguous Albers Equal Area Conic USGS version";
1077  projName = "Conus";
1078  projStr =
1079  "+proj=aea +lat_1=29.5 +lat_2=45.5"
1080  " +lat_0=23.0 +lon_0=-96 +x_0=0 +y_0=0"
1081  " +ellps=GRS80 +datum=NAD83 +units=m +no_defs";
1082 
1083  } else if (strcasecmp(projectionStr, "alaska") == 0) {
1084  mapDesc = "Alaska Albers Equal Area Conic USGS version";
1085  projName = "Alaska";
1086  projStr = "EPSG:3338";
1087 
1088  } else if (strcasecmp(projectionStr, "gibs") == 0) {
1089  if (((metaData->north + metaData->south) / 2.) > 60.) {
1090  mapDesc = "Stereographic";
1091  projName = "GIBS Stereo";
1092  projStr = "EPSG:3413";
1093 
1094  } else if (((metaData->north + metaData->south) / 2.) < -60.) {
1095  mapDesc = "Stereographic";
1096  projName = "GIBS Stereo";
1097  projStr = "EPSG:3031";
1098 
1099  } else {
1100  mapDesc = "Equidistant Cylindrical";
1101  projName = "PlateCarree";
1102  projStr =
1103  "+proj=eqc"
1104  " +lat_ts=0 +lat_0=0 +x_0=0 +y_0=0"
1105  " +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
1106  projStr += cmStr;
1107  }
1108 
1109  } else if (strcasecmp(projectionStr, "platecarree") == 0) {
1110  mapDesc = "Equidistant Cylindrical";
1111  projName = "PlateCarree";
1112  projStr =
1113  "+proj=eqc"
1114  " +lat_ts=0 +lat_0=0 +x_0=0 +y_0=0"
1115  " +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
1116  projStr += cmStr;
1117 
1118  } else {
1119  mapDesc = "Proj4";
1120  projName = projectionStr;
1121  projStr = projectionStr;
1122  }
1123 
1124  // save parameters in metadata
1125  sprintf(metaData->title, "%s Level-3 %s Mapped Image", metaData->sensor_name, mapDesc.c_str());
1126  for (OutFile* outFile : outFiles) {
1127  if (outFile->getMetadata() != metaData)
1128  strcpy(outFile->getMetadata()->title, metaData->title);
1129  outFile->setMapProjection(projName);
1130  }
1131  if (outFile2) {
1132  strcpy(outFile2->getMetadata()->title, metaData->title);
1133  outFile2->getMetadata()->east = metaData->east;
1134  outFile2->getMetadata()->west = metaData->west;
1135  outFile2->setMapProjection(projName);
1136  }
1137 
1138  PJ *pj, *pj_new;
1139  PJ_COORD c, c_out;
1140 
1141  // init the proj4 projections
1142  // pj = proj_create_crs_to_crs(PJ_DEFAULT_CTX, "+proj=longlat +ellps=WGS84 +datum=WGS84",
1143  // projStr.c_str(), NULL);
1144  pj = proj_create_crs_to_crs(PJ_DEFAULT_CTX, "EPSG:4326", projStr.c_str(), NULL);
1145  if (pj == NULL) {
1146  printf("Error - l3mapgen first PROJ projection failed to init\n");
1147  exit(1);
1148  }
1149  pj_new = proj_normalize_for_visualization(PJ_DEFAULT_CTX, pj);
1150  if (pj_new == NULL) {
1151  printf("Error - l3mapgen visualization PROJ projection failed to init\n");
1152  exit(1);
1153  }
1154  proj_destroy(pj);
1155  pj = NULL;
1156 
1157  // calculate start and delta for grid
1158  // set default z and t
1159  c.xyzt.z = 0.0;
1160  // c.xyzt.t = HUGE_VAL;
1161  c.xyzt.t = 0.0;
1162 
1163  // define "inBox" region for trimNSEW option using lat/lon arrays based on
1164  // metaData struct
1165  std::array<double, 9> lats{{metaData->south, metaData->south, metaData->south,
1166  (metaData->north + metaData->south) / 2., metaData->north, metaData->north,
1167  metaData->north, (metaData->north + metaData->south) / 2., metaData->south}};
1168  std::array<double, 9> lons{{metaData->west, (metaData->east + metaData->west) / 2., metaData->east,
1169  metaData->east, metaData->east, (metaData->east + metaData->west) / 2.,
1170  metaData->west, metaData->west, metaData->west}};
1171  std::vector<Point_t> points;
1172  for (int32_t i = 0; i < 9; i++) {
1173  c.xy.x = lons[i];
1174  c.xy.y = lats[i];
1175  c_out = proj_trans(pj_new, PJ_FWD, c);
1176 
1177  if (isfinite(c_out.xy.x) && isfinite(c_out.xy.y)) {
1178  Point_t point(c_out.xy.x, c_out.xy.y);
1179  points.push_back(point);
1180  }
1181  }
1182 
1183  // Create a polygon object and assign the points to it.
1184  Polygon_t NSEW;
1185  boost::geometry::assign_points(NSEW, points);
1186 
1187  if (clo_isSet(optionList, "north")) {
1188  // ...if user defined the region
1189  lat = metaData->south;
1190  for (int j = 0; j < NUM_SEARCH_POINTS; j++) {
1191  lon = metaData->west;
1192  for (int i = 0; i < NUM_SEARCH_POINTS; i++) {
1193  c.xy.x = lon;
1194  c.xy.y = lat;
1195  c_out = proj_trans(pj_new, PJ_FWD, c);
1196  x = c_out.xy.x;
1197  y = c_out.xy.y;
1198  if (isfinite(x) && isfinite(y)) {
1199  if (x < limitMax && x > limitMin) {
1200  if (x < minX)
1201  minX = x;
1202  if (x > maxX)
1203  maxX = x;
1204  }
1205  if (y < limitMax && y > limitMin) {
1206  if (y < minY)
1207  minY = y;
1208  if (y > maxY)
1209  maxY = y;
1210  }
1211  }
1212  lon += deltaLon;
1213  }
1214  lat += deltaLat;
1215  }
1216  } else {
1217  // If no user input, grab extents from the file -
1218  // not taking the easy route and using metadata because of the square
1219  // Earth problem
1220  double latmin = 999., latmax = -999., lonmin = 999., lonmax = -999.;
1221  double lonmin360 = 999., lonmax360 = -999.;
1222  L3Shape* shape = l3File->getShape();
1223  for (int row = 0; row < l3File->getNumRows(); row++) {
1224  // First column
1225  L3Row* l3row = l3File->getRow(row);
1226  x = std::numeric_limits<double>::quiet_NaN();
1227  y = std::numeric_limits<double>::quiet_NaN();
1228  int32_t binindex = 0;
1229 
1230  // search for first good bin
1231  while ((!isfinite(x) || !(isfinite(y))) && binindex < l3row->getNumBins()) {
1232  int64_t bin = l3row->getBinByIndex(binindex)->getBinNum();
1233  if (bin > -1) {
1234  shape->bin2latlon(bin, lat, lon);
1235  c.xy.x = lon;
1236  c.xy.y = lat;
1237  c_out = proj_trans(pj_new, PJ_FWD, c);
1238  x = c_out.xy.x;
1239  y = c_out.xy.y;
1240  binindex++;
1241  }
1242  }
1243  if (isfinite(x) && isfinite(y)) {
1244  if (lon < lonmin)
1245  lonmin = lon;
1246  if (lon > lonmax)
1247  lonmax = lon;
1248 
1249  double lon360;
1250  if (lon < 0)
1251  lon360 = lon + 360.0;
1252  else
1253  lon360 = lon;
1254  if (lon360 < lonmin360)
1255  lonmin360 = lon360;
1256  if (lon360 > lonmax360)
1257  lonmax360 = lon360;
1258 
1259  if (lat < latmin)
1260  latmin = lat;
1261  if (lat > latmax)
1262  latmax = lat;
1263 
1264  if (x < limitMax && x > limitMin) {
1265  if (x < minX) {
1266  minX = x;
1267  }
1268  if (x > maxX) {
1269  maxX = x;
1270  }
1271  }
1272  if (y < limitMax && y > limitMin) {
1273  if (y < minY) {
1274  minY = y;
1275  }
1276  if (y > maxY) {
1277  maxY = y;
1278  }
1279  }
1280  }
1281 
1282  // Last column
1283  if ((l3row->getNumBins() > 1) && (binindex != l3row->getNumBins())) {
1284  binindex = l3row->getNumBins() - 1;
1285  x = std::numeric_limits<double>::quiet_NaN();
1286  y = std::numeric_limits<double>::quiet_NaN();
1287 
1288  // search for last good bin
1289  while ((!isfinite(x) || !(isfinite(y))) && (binindex > 0)) {
1290  int64_t bin = l3row->getBinByIndex(binindex)->getBinNum();
1291  if (bin > -1) {
1292  shape->bin2latlon(bin, lat, lon);
1293  c.xy.x = lon;
1294  c.xy.y = lat;
1295  c_out = proj_trans(pj_new, PJ_FWD, c);
1296  x = c_out.xy.x;
1297  y = c_out.xy.y;
1298  binindex--;
1299  }
1300  }
1301  if (isfinite(x) && isfinite(y)) {
1302  if (lon < lonmin)
1303  lonmin = lon;
1304  if (lon > lonmax)
1305  lonmax = lon;
1306 
1307  double lon360;
1308  if (lon < 0)
1309  lon360 = lon + 360.0;
1310  else
1311  lon360 = lon;
1312  if (lon360 < lonmin360)
1313  lonmin360 = lon360;
1314  if (lon360 > lonmax360)
1315  lonmax360 = lon360;
1316 
1317  if (lat < latmin)
1318  latmin = lat;
1319  if (lat > latmax)
1320  latmax = lat;
1321 
1322  if (x < limitMax && x > limitMin) {
1323  if (x < minX) {
1324  minX = x;
1325  }
1326  if (x > maxX) {
1327  maxX = x;
1328  }
1329  }
1330  if (y < limitMax && y > limitMin) {
1331  if (y < minY) {
1332  minY = y;
1333  }
1334  if (y > maxY) {
1335  maxY = y;
1336  }
1337  }
1338  }
1339  }
1340  }
1341 
1342  // add a little padding to get last pixel
1343  minX -= resolution;
1344  maxX += resolution;
1345  minY -= resolution;
1346  maxY += resolution;
1347 
1348  metaData->north = latmax;
1349  metaData->south = latmin;
1350 
1351  double delta = lonmax - lonmin;
1352  lonmax360 = fmod(lonmax + 360.0, 360.0);
1353  lonmin360 = fmod(lonmin + 360.0, 360.0);
1354  double delta360 = lonmax360 - lonmin360;
1355 
1356  if (delta360 < delta) {
1357  if (lonmin360 > 180.0)
1358  metaData->west = lonmin360 - 360.0;
1359  else
1360  metaData->west = lonmin360;
1361  if (lonmax360 > 180.0)
1362  metaData->east = lonmax360 - 360.0;
1363  else
1364  metaData->east = lonmax360;
1365  } else {
1366  metaData->west = lonmin;
1367  metaData->east = lonmax;
1368  }
1369 
1370  mapEast = metaData->east;
1371  mapWest = metaData->west;
1372  if (mapEast < mapWest)
1373  mapEast += 360;
1375  heightInDeg = metaData->north - metaData->south;
1376 
1377  } // "north" not set
1378 
1379  // set up image parameters
1380  if (imageWidth <= 0) {
1381  imageWidth = rint((maxX - minX) / resolution);
1382  if (imageWidth <= 0)
1383  imageWidth = 1;
1384  } else {
1385  resolution = (maxX - minX) / imageWidth;
1386  for (OutFile* outFile : outFiles)
1387  outFile->setResolution(resolution);
1388  if (outFile2)
1389  outFile2->setResolution(resolution);
1390  }
1391  imageHeight = rint((maxY - minY) / resolution);
1392  if (imageHeight <= 0)
1393  imageHeight = 1;
1394  for (OutFile* outFile : outFiles)
1395  outFile->setSize(imageWidth, imageHeight);
1396  if (outFile2)
1397  outFile2->setSize(imageWidth, imageHeight);
1398 
1399  for (OutFile* outFile : outFiles) {
1400  outFile->setProj4Info(projStr, minX, maxY);
1401  }
1402 
1403  if (outFile2) {
1404  outFile2->setProj4Info(projStr, minX, maxY);
1405  }
1406 
1407  // set up all the product structures
1408  for (size_t i = 0; i < prodNameList.size(); i++) {
1409  OutFile* outFile;
1410  if (outFiles.size() == 1)
1411  outFile = outFiles[0];
1412  else
1413  outFile = outFiles[i];
1414  setupProduct(prodNameList[i], prodMeasurementList[i], outFile, outFile2);
1415  }
1416 
1417  // set up quality processing
1418  setupQualityProcessing(l3File, outFiles, outFile2);
1419 
1420  printStartInfo(outFiles);
1421 
1422  for (OutFile* outFile : outFiles) {
1423  if (!outFile->open()) {
1424  printf("-E- Could not open ofile=\"%s\".\n", outFile->getFileName().c_str());
1425  exit(EXIT_FAILURE);
1426  }
1427  }
1428 
1429  if (outFile2) {
1430  if (!outFile2->open()) {
1431  printf("-E- Could not open ofile2=\"%s\".\n", outFile2->getFileName().c_str());
1432  exit(EXIT_FAILURE);
1433  }
1434  }
1435 
1437  float fudge = clo_getFloat(optionList, "fudge");
1438 
1439  // loop through output pixels
1440  double* tmpX = (double*)allocateMemory(imageWidth * sizeof(double), "tmpX");
1441  double* tmpY = (double*)allocateMemory(imageWidth * sizeof(double), "tmpY");
1442  inBox = (bool*)allocateMemory(imageWidth * sizeof(bool), "inBox");
1443 
1444  deltaLon = widthInDeg / imageWidth;
1445  deltaLat = heightInDeg / imageHeight;
1446  double startX = minX + resolution / 2;
1447  double startY = maxY - resolution / 2;
1448  y = startY;
1449  // setting values begins
1450  for (int row = 0; row < imageHeight; row++) {
1451  printPercentDone((float)row / (float)imageHeight);
1452  x = startX;
1453  std::fill(inBox, inBox + imageWidth, false);
1454  for (int col = 0; col < imageWidth; col++) {
1455  c.xy.x = x;
1456  c.xy.y = y;
1457  c_out = proj_trans(pj_new, PJ_INV, c);
1458  tmpX[col] = c_out.xy.x;
1459  tmpY[col] = c_out.xy.y;
1460  if (!isfinite(tmpX[col]) || !isfinite(tmpY[col])) {
1461  tmpX[col] = -999.0; // set to fill value
1462  tmpY[col] = -999.0; // set to fill value
1463 
1464  } else if (trimNSEW) {
1465  Point_t pixel(x, y);
1466  if (boost::geometry::within(pixel, NSEW)) {
1467  inBox[col] = true;
1468  }
1469  }
1470  x += resolution;
1471  }
1472  // loop through each pixel in this row
1473  for (int col = 0; col < imageWidth; col++) {
1474  lon = tmpX[col];
1475  lat = tmpY[col];
1476  if (!isfinite(lon) || !isfinite(lat)) {
1477  for (OutFile* outFile : outFiles)
1478  outFile->fillPixel(col);
1479  if (outFile2)
1480  outFile2->fillPixel(col);
1481  } else if (trimNSEW && inBox[col] == false) {
1482  for (OutFile* outFile : outFiles)
1483  outFile->fillPixel(col);
1484  if (outFile2)
1485  outFile2->fillPixel(col);
1486  } else if (applyMask && isLand(lat, lon)) {
1487  for (OutFile* outFile : outFiles)
1488  outFile->landPixel(col);
1489  if (outFile2)
1490  outFile2->landPixel(col);
1491 
1492  } else {
1493  switch (interp) {
1494  case Interp_Nearest:
1495  l3Bin = l3File->getClosestBin(lat, lon);
1496  break;
1497  case Interp_Bin:
1498  case Interp_Area: {
1499  bool areaWeighted;
1500 
1501  if (interp == Interp_Area)
1502  areaWeighted = true;
1503  else
1504  areaWeighted = false;
1505 
1506  if (checkDateLineCrossed(lon, deltaLon)) {
1507  // East
1508  l3Bin =
1509  getBoxBins(l3File, lat, lon, deltaLat, deltaLon, fudge, areaWeighted, IsEast);
1510 
1511  // West
1512  L3Bin* tmpBin =
1513  getBoxBins(l3File, lat, lon, deltaLat, deltaLon, fudge, areaWeighted, IsWest);
1514  if (tmpBin) {
1515  *l3Bin += *tmpBin;
1516  }
1517 
1518  } else {
1519  l3Bin = getBoxBins(l3File, lat, lon, deltaLat, deltaLon, fudge, areaWeighted);
1520  }
1521  break;
1522  }
1523  default:
1524  printf("-E- interp = %s is not implemented.", interpType2Str(interp));
1525  exit(EXIT_FAILURE);
1526  }
1527 
1528  if (l3Bin) {
1529  numFilledPixels++;
1530  if (doingRGB) {
1531  outFiles[0]->setPixelRGB(col, l3Bin->getMean(0), l3Bin->getMean(1),
1532  l3Bin->getMean(2));
1533  if (outFile2)
1534  outFile2->setPixelRGB(col, l3Bin->getMean(0), l3Bin->getMean(1),
1535  l3Bin->getMean(2));
1536  } else {
1537  // it loops through product index
1538  for (size_t prod = 0; prod < prodNameList.size(); prod++) {
1539  float val;
1540  switch (prodMeasurementList[prod]) {
1541  case Avg:
1542  val = l3Bin->getMean(prod);
1543  break;
1544  case Stdev:
1545  val = l3Bin->getStdev(prod);
1546  break;
1547  case Variance:
1548  val = l3Bin->getVariance(prod);
1549  break;
1550  case Nobs:
1551  val = l3Bin->getNobs();
1552  break;
1553  case Nscenes:
1554  val = l3Bin->getNscenes();
1555  break;
1556  case ObsTime:
1557  val = l3Bin->getObsTime();
1558  break;
1559  case BinNum:
1560  val = l3Bin->getBinNum();
1561  break;
1562  default:
1563  val = l3Bin->getMean(prod);
1564  }
1565  if (outFiles.size() == 1)
1566  outFiles[0]->setPixel(col, val, prod);
1567  else
1568  outFiles[prod]->setPixel(col, val, 0);
1569  if (outFile2)
1570  outFile2->setPixel(col, val, prod);
1571  }
1572  }
1573  if (doingQuality) {
1574  for (OutFile* outFile : outFiles)
1575  outFile->setQuality(col, l3Bin->getQuality());
1576  if (outFile2)
1577  outFile2->setQuality(col, l3Bin->getQuality());
1578  }
1579  } else {
1580  for (OutFile* outFile : outFiles)
1581  outFile->missingPixel(col);
1582  if (outFile2)
1583  outFile2->missingPixel(col);
1584  }
1585  }
1586  } // for col
1587  for (OutFile* outFile : outFiles) {
1588  outFile->setLatLon(tmpY, tmpX);
1589  outFile->writeLine();
1590  }
1591  if (outFile2) {
1592  outFile2->setLatLon(tmpY, tmpX);
1593  outFile2->writeLine();
1594  }
1595  y -= resolution;
1596  } // for row
1597  // values set ends here
1598  free(tmpX);
1599  free(tmpY);
1600  free(inBox);
1601 
1602  proj_destroy(pj_new);
1603 
1604  for (OutFile* outFile : outFiles) {
1605  if (write_projtext) {
1606  string projtxtfilename;
1607  projtxtfilename = outFile->getFileName();
1608  projtxtfilename += ".projtxt";
1609  ofstream projtxtfile(projtxtfilename);
1610  if (projtxtfile.is_open()) {
1611  projtxtfile << "# Projection information for " << outFile->getFileName() << "\n";
1612  projtxtfile << "proj=" << projStr << "\n";
1613  projtxtfile << "minX=" << std::setprecision(11) << minX << "\n";
1614  projtxtfile << "maxX=" << std::setprecision(11) << maxX << "\n";
1615  projtxtfile << "minY=" << std::setprecision(11) << minY << "\n";
1616  projtxtfile << "maxY=" << std::setprecision(11) << maxY << "\n";
1617  projtxtfile << "north=" << std::setprecision(11) << metaData->north << "\n";
1618  projtxtfile << "south=" << std::setprecision(11) << metaData->south << "\n";
1619  projtxtfile << "east=" << std::setprecision(11) << metaData->east << "\n";
1620  projtxtfile << "west=" << std::setprecision(11) << metaData->west << "\n";
1621 
1622  projtxtfile << "scale_type=" << outFile->getScaleTypeString() << "\n";
1623  projtxtfile << "datamin=" << std::setprecision(11) << outFile->getMinValue() << "\n";
1624  projtxtfile << "datamax=" << std::setprecision(11) << outFile->getMaxValue() << "\n";
1625  projtxtfile << "width=" << imageWidth << "\n";
1626  projtxtfile << "height=" << imageHeight << "\n";
1627 
1628  projtxtfile.close();
1629  }
1630  }
1631 
1632  outFile->setNumFilledPixels(numFilledPixels);
1633  outFile->close();
1634  }
1635  if (outFile2) {
1636  outFile2->setNumFilledPixels(numFilledPixels);
1637  outFile2->close();
1638  }
1639 }
1640 
1641 OutFile* makeOutputFile(const char* oformatStr, bool useColor) {
1642  OutFile* outFile = NULL;
1643 
1644  const char* oformatStr2 = getFileFormatName(oformatStr);
1645 
1646  if (oformatStr2 == NULL) {
1647  printf("-E- Unknown output file format \"%s\"\n", oformatStr);
1648  exit(EXIT_FAILURE);
1649  }
1650 
1651  string oformat = oformatStr2;
1652  if (oformat.compare("PPM") == 0) {
1653  if (doingRGB) {
1654  outFile = new OutFile_ppm_rgb();
1655  } else {
1656  if (useColor) {
1657  outFile = new OutFile_ppm();
1658  } else {
1659  outFile = new OutFile_pgm();
1660  }
1661  }
1662  } else if (oformat.compare("PNG") == 0) {
1663  if (doingRGB) {
1664  outFile = new OutFile_png_rgb();
1665  } else {
1666  outFile = new OutFile_png(useColor);
1667  }
1668  } else if (oformat.compare("TIFF") == 0) {
1669  if (doingRGB) {
1670  outFile = new OutFile_tiff_rgb();
1671  } else {
1672  if (useColor) {
1673  outFile = new OutFile_tiff_color();
1674  } else {
1675  outFile = new OutFile_tiff_gray();
1676  }
1677  }
1678  } else if (oformat.compare("HDF4") == 0) {
1679  outFile = new OutFile_hdf4();
1680  } else if (oformat.compare("netCDF4") == 0) {
1681  outFile = new OutFile_netcdf4();
1682  } else {
1683  printf("-E- Output file type %s not implemented\n", oformat.c_str());
1684  exit(EXIT_FAILURE);
1685  }
1686  if (doingTransparency)
1687  outFile->setTransparency();
1688 
1689  return outFile;
1690 }
1691 
1693  vector<OutFile*> outFiles;
1694  OutFile* outFile;
1695  string oformatStr = getFileFormatName(clo_getString(optionList, "oformat"));
1696  string originalOfile = clo_getString(optionList, "ofile");
1697  string tag = clo_getString(optionList, "ofile_product_tag");
1698  // if netcdf4 format specified just one file will be produced
1699  // need to put a check : if there 3D vars, then only netcdf is acceptable
1700  if (oformatStr.compare("netCDF4") == 0 || prodNameList.size() == 1 || doingRGB) {
1701  outFile = makeOutputFile(clo_getString(optionList, "oformat"), clo_getBool(optionList, "apply_pal"));
1702  outFile->setFileName(originalOfile);
1703  outFiles.push_back(outFile);
1704  } else {
1705  size_t pos = originalOfile.find(tag);
1706  if (pos == string::npos) {
1707  printf("Error: ofile_product_tag=%s, not found in ofile=%s\n", tag.c_str(),
1708  originalOfile.c_str());
1709  printf(
1710  " and you asked for multiple products with image "
1711  "oformat\n");
1712  exit(EXIT_FAILURE);
1713  }
1714 
1715  for (size_t i = 0; i < prodNameList.size(); i++) {
1716  std::string newName = originalOfile;
1717  std::string prodName_clean = prodNameList.at(i);
1719  newName.replace(pos, tag.size(), prodName_clean + modifier);
1720  outFile =
1721  makeOutputFile(clo_getString(optionList, "oformat"), clo_getBool(optionList, "apply_pal"));
1722  outFile->setFileName(newName);
1723  outFiles.push_back(outFile);
1724  } // loop products
1725  }
1726 
1727  return outFiles;
1728 }
1729 
1730 //------------------------------------------------------------------------------
1731 // main
1732 //------------------------------------------------------------------------------
1733 
1734 int main(int argc, char* argv[]) {
1735  vector<OutFile*> outFiles;
1736  OutFile* outFile2 = NULL;
1737  char* ifileName;
1738  string oformat;
1739  int i;
1740  char* tmpStr;
1741 
1742  char softwareVersion[200];
1743  sprintf(softwareVersion, "%d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, GITSHA);
1744 
1745  // init the netCDF file cache
1747 
1749 
1750  l3mapgen_init_options(optionList, softwareVersion);
1751  if (argc == 1) {
1753  exit(EXIT_FAILURE);
1754  }
1756 
1757  if (clo_getBool(optionList, "quiet")) {
1758  want_verbose = 0;
1759  }
1760 
1761  ifileName = clo_getString(optionList, "ifile");
1762 
1763  // try SMI input file
1764  int oldVerbose = want_verbose;
1765  want_verbose = 0;
1766  L3File* l3File = new L3FileSMI();
1767  if (!l3File->open(ifileName)) {
1768  // try real L3 bin format
1769  delete l3File;
1770  l3File = new L3File();
1771  if (!l3File->open(ifileName)) {
1772  printf("-E- Could not open ifile=\"%s\".\n", ifileName);
1773  exit(EXIT_FAILURE);
1774  }
1775  }
1776  want_verbose = oldVerbose;
1777 
1778  if (clo_getBool(optionList, "use_transparency")) {
1779  doingTransparency = true;
1780  }
1781  if (clo_getBool(optionList, "use_rgb")) {
1782  doingRGB = true;
1783  prodName = clo_getRawString(optionList, "product_rgb");
1784  } else {
1785  doingRGB = false;
1786  if (clo_isSet(optionList, "product")) {
1787  prodName = clo_getRawString(optionList, "product");
1788  } else {
1789  prodName.clear();
1790  for (int i = 0; i < l3File->getNumProducts(); i++) {
1791  string tmpName = l3File->getProductName(i);
1792  if (tmpName != "qual_l3") {
1793  if (!prodName.empty())
1794  prodName += ",";
1795  prodName += tmpName;
1796  }
1797  }
1798  }
1799  }
1800  trimNSEW = clo_getBool(optionList, "trimNSEW");
1801  write_projtext = clo_getBool(optionList, "write_projtext");
1802 
1803  boost::split(prodNameList, prodName, boost::is_any_of(","));
1804  string cleanProdName;
1805  vector<string> parts;
1806  meta_l3bType metaData = *l3File->getMetaData(); // get metadata
1807  // all the wavelength for the sensor
1808  int32_t* wave_array_of_the_sensor;
1809  // quick look up for wv
1810  std::unordered_set<int32_t> look_up_for_wv;
1811  want_verbose = 0;
1812  const auto total_num_bands =
1813  rdsensorinfo(metaData.sensorID, 0, "Lambda", (void**)&wave_array_of_the_sensor);
1814  // to lookup a rank
1815  productInfo_t* p_info;
1816  p_info = allocateProductInfo();
1817  want_verbose = 1;
1818  for (int i = 0; i < total_num_bands; i++) {
1819  look_up_for_wv.insert(wave_array_of_the_sensor[i]);
1820  }
1821  if (clo_isSet(optionList, "wavelength_3d")) {
1822  const std::string wavelengths_3d_list = clo_getRawString(optionList, "wavelength_3d");
1823  boost::split(wv3d::wavelength_3d_list_separated, wavelengths_3d_list, boost::is_any_of(", "),
1824  boost::algorithm::token_compress_on);
1825 
1826  std::vector<std::string> colon_expanded_list;
1827  for (const auto& wv_par : wv3d::wavelength_3d_list_separated) {
1828  if (boost::contains(wv_par, ":")) {
1829  std::vector<std::string> pars;
1830  boost::split(pars, wv_par, boost::is_any_of(":"));
1831  if (pars.size() != 2) {
1832  EXIT_LOG(std::cerr << "--Error-: Wrong range specifier: " << wv_par << std::endl;)
1833  }
1834  try {
1835  int wav_st = boost::lexical_cast<int32_t>(pars.at(0));
1836  int wav_end = boost::lexical_cast<int32_t>(pars.at(1));
1837  if (look_up_for_wv.count(wav_st) == 0) {
1838  EXIT_LOG(std::cerr << "--Error--: The start wavelength " << wav_st
1839  << " is not found in sensor wv list.\n Check "
1840  "the range "
1841  << wv_par << std::endl);
1842  }
1843  if (look_up_for_wv.count(wav_end) == 0) {
1844  EXIT_LOG(std::cerr << "--Error--: The end wavelength " << wav_end
1845  << " is not found in sensor wv list.\n Check "
1846  "the range "
1847  << wv_par << std::endl);
1848  }
1849  for (int32_t i = wav_st; i <= wav_end; i++) {
1850  if (look_up_for_wv.count(i) == 0)
1851  continue;
1852  colon_expanded_list.push_back(boost::lexical_cast<std::string>(i));
1853  }
1854  } catch (const boost::bad_lexical_cast& e) {
1855  EXIT_LOG(std::cerr << e.what() << '\n'; std::cerr
1856  << "--Error--: Provided wavelength are not valid "
1857  "numbers. "
1858  << wv_par << std::endl;)
1859  }
1860  } else {
1861  colon_expanded_list.push_back(wv_par);
1862  }
1863  }
1864  wv3d::wavelength_3d_list_separated = std::move(colon_expanded_list);
1865  }
1866 
1867  // make temp unordered set for quick lookup;
1868  std::unordered_set<std::string> look_up_table_product_availiable_list;
1869  const int number_of_products = l3File->getNumProducts();
1870  for (int i = 0; i < number_of_products; i++) {
1871  const std::string& name = l3File->getProductName(i);
1872  look_up_table_product_availiable_list.insert(name);
1873  }
1874  std::vector<std::string> temp_prod_name_list;
1875  std::unordered_set<std::string> already_set_wv;
1876  // check that there are no duplicates in the wv list
1877  for (const auto& wv : wv3d::wavelength_3d_list_separated)
1878  if (already_set_wv.count(wv) == 0) {
1879  already_set_wv.insert(wv);
1880  } else {
1881  EXIT_LOG(std::cerr << "--Error--: A duplicate found in the wavelength_3d list " << wv
1882  << std::endl);
1883  }
1884 
1885  for (size_t i = 0; i < prodNameList.size(); i++) {
1886  std::vector<std::string> names;
1887  boost::split(names, prodNameList.at(i), boost::is_any_of(":"));
1888  std::string clean_name = names.at(0);
1889  int result = findProductInfo(clean_name.c_str(), metaData.sensorID, p_info);
1890  if (result != 1) {
1891  EXIT_LOG(std::cerr << "--Error--: Could not find the product: " << clean_name << std::endl);
1892  }
1893  int prod_rank = p_info->rank;
1894  const std::string suffix = p_info->suffix;
1895  std::string prefix = p_info->prefix;
1896 
1897  if (look_up_table_product_availiable_list.count(clean_name) == 0) {
1898  if (prod_rank != 3) {
1899  EXIT_LOG(std::cerr << "--Error--: Non-3D Product " << clean_name
1900  << " is not found in the bin l3 file\n");
1901  }
1902  // check if the list empty
1903  if (wv3d::wavelength_3d_list_separated.empty()) {
1904  for (const auto& product_in_l3in : look_up_table_product_availiable_list) {
1905  int res = findProductInfo(product_in_l3in.c_str(), metaData.sensorID, p_info);
1906 
1907  if (res != 1) {
1908  EXIT_LOG(std::cerr << "--Error--: Could not read the product info " << product_in_l3in
1909  << std::endl);
1910  }
1911  const std::string local_suffix = p_info->suffix;
1912  const std::string local_name = p_info->productName;
1913  if (boost::contains(clean_name, local_name)) {
1914  if (!local_suffix.empty()) {
1915  if (!boost::contains(clean_name, local_suffix))
1916  continue;
1917  } else {
1918  if (clean_name != local_name)
1919  continue;
1920  }
1921 
1922  const std::string wave_length = boost::lexical_cast<std::string>(p_info->prod_ix);
1923  if (wave_length.empty()) {
1924  EXIT_LOG(std::cerr << "--Error--: Not valid 2D slice of " << clean_name
1925  << "in the l3bin file " << std::endl);
1926  }
1927  wv3d::wavelength_3d_list_separated.push_back(wave_length);
1928  }
1929  }
1932  }
1933  bool prod_3d_expand_found = false;
1934  for (size_t i = 0; i < wv3d::wavelength_3d_list_separated.size(); i++) {
1936  std::string prod_3d_name = prefix + "_" + wv + suffix;
1937  if (look_up_table_product_availiable_list.count(prod_3d_name) == 0) {
1938  EXIT_LOG(std::cerr << "--Error--: Neither product " << clean_name
1939  << " or its wavelength 3d slice " << prod_3d_name
1940  << " are found. \nExiting ... " << std::endl);
1941  } else {
1942  prod_3d_expand_found = true;
1943  names.at(0) = prod_3d_name;
1944  int32_t wavelength;
1945  try {
1946  wavelength = boost::lexical_cast<int32_t>(wv);
1947  } catch (const boost::bad_lexical_cast& e) {
1948  EXIT_LOG(std::cerr << e.what() << '\n';
1949  std::cerr << "--Error--: Provided wavelength are not valid "
1950  "numbers. \nExiting...");
1951  }
1952 
1953  wv3d::wv3d_2d_name_to_3d_expansion[clean_name].push_back(wavelength);
1954  wv3d::wv3d_3d_name_to_2d_name[prod_3d_name] = clean_name;
1955  std::string temp_prod_3d_name;
1956  for (const auto& name : names) {
1957  if (!temp_prod_3d_name.empty())
1958  temp_prod_3d_name += ":";
1959  temp_prod_3d_name += name;
1960  }
1961  temp_prod_name_list.push_back(temp_prod_3d_name);
1962  }
1963  }
1964  if (!prod_3d_expand_found) {
1965  EXIT_LOG(std::cerr << "--Error--: Product not found : " << clean_name << std::endl);
1966  }
1967 
1968  } else {
1969  if (prod_rank != 2) {
1970  EXIT_LOG(std::cerr << "--Error--: The product in the bin file " << clean_name
1971  << " is not a 2D prodcut" << std::endl);
1972  }
1973  temp_prod_name_list.push_back(prodNameList.at(i));
1974  }
1975  wv3d::output_products_with_3d.push_back(clean_name);
1976  }
1977  prodNameList = std::move(temp_prod_name_list);
1979  if (wv3d::wavelength_3d_size >= 1) {
1981  if (clo_isSet(optionList, "ofile2")) {
1982  const std::string oformatStr2 = getFileFormatName(clo_getString(optionList, "oformat2"));
1983  if (oformatStr2.compare("netCDF4") != 0) {
1984  EXIT_LOG(std::cerr << "The user supplied a 3D product "
1985  << " and the output format for ofile2 is not netCDF4.\n"
1986  << "Exiting ... " << std::endl);
1987  }
1988  }
1989  }
1990  }
1991  // setup measurments
1992  for (size_t i = 0; i < prodNameList.size(); i++) {
1993  if (i != 0)
1994  cleanProdName += ",";
1995  boost::split(parts, prodNameList[i], boost::is_any_of(":"));
1996  if (parts.size() == 1) {
1997  cleanProdName += parts[0];
1998  prodMeasurementList.push_back(Avg);
1999  } else if (parts.size() == 2) {
2000  prodNameList[i] = parts[0]; // get rid of the modifier
2001  cleanProdName += parts[0];
2002  if (parts[1].compare("avg") == 0)
2003  prodMeasurementList.push_back(Avg);
2004  else if (parts[1].compare("stdev") == 0)
2005  prodMeasurementList.push_back(Stdev);
2006  else if (parts[1].compare("var") == 0)
2007  prodMeasurementList.push_back(Variance);
2008  else if (parts[1].compare("nobs") == 0)
2009  prodMeasurementList.push_back(Nobs);
2010  else if (parts[1].compare("nscenes") == 0)
2011  prodMeasurementList.push_back(Nscenes);
2012  else if (parts[1].compare("obs_time") == 0)
2013  prodMeasurementList.push_back(ObsTime);
2014  else if (parts[1].compare("bin_num") == 0)
2015  prodMeasurementList.push_back(BinNum);
2016  else {
2017  EXIT_LOG(
2018  printf("-E- measurement type \"%s\" "
2019  "not understood for product \"%s\".\n",
2020  parts[1].c_str(), parts[0].c_str()));
2021  }
2022  } else {
2023  EXIT_LOG(printf("-E- product name not understood \"%s\".\n", prodNameList[i].c_str()));
2024  }
2025  }
2026  if (!l3File->setActiveProductList(cleanProdName.c_str())) {
2027  EXIT_LOG(
2028  printf("-E- Could not find product=\"%s\" in file=\"%s\".\n", cleanProdName.c_str(), ifileName));
2029  }
2030 
2031  l3File->setNumCacheRows(clo_getInt(optionList, "num_cache"));
2032 
2033  // copy the L3 meta data since we will modify it a bit for the output file.
2034 
2035  // output file list is here
2036  // should be modified first
2037  outFiles = makeOutputFileList(optionList);
2038 
2039  if (clo_isSet(optionList, "ofile2")) {
2040  outFile2 =
2041  makeOutputFile(clo_getString(optionList, "oformat2"), clo_getBool(optionList, "apply_pal"));
2042  outFile2->setFileName(clo_getString(optionList, "ofile2"));
2043  }
2044 
2045  // resolution = # of meters across 1 pixel in the center of the scene
2046  double res;
2047  if (clo_isSet(optionList, "resolution")) {
2048  outFiles[0]->setResolution(clo_getString(optionList, "resolution"));
2049  res = outFiles[0]->getResolution();
2050  } else {
2051  res = l3File->getMetaData()->resolution; // in meters
2052  if (res < 0) {
2053  outFiles[0]->setResolution("9km");
2054  res = outFiles[0]->getResolution();
2055  }
2056  }
2057 
2058  for (OutFile* outFile : outFiles) {
2059  outFile->setResolution(res);
2060  }
2061 
2062  if (outFile2)
2063  outFile2->setResolution(res);
2064 
2065  // get imageWidth, if specified
2066  if (clo_isSet(optionList, "width"))
2067  imageWidth = clo_getInt(optionList, "width");
2068 
2069  // projection
2070  clo_option_t* projectionOption = clo_findOption(optionList, "projection");
2071  char* projectionStr = clo_getOptionRawString(projectionOption);
2072 
2073  // check the metadata of the bin file
2074  if (metaData.north == metaData.south) {
2075  printf("-E- north and south metadata are equal.\n");
2076  exit(110);
2077  }
2078  if (metaData.east == metaData.west) {
2079  printf("-E- east and west metadata are equal.\n");
2080  exit(110);
2081  }
2082 
2083  // default to whole globe for SMI files
2084  if ((strcmp(projectionStr, "smi") == 0) || (strcmp(projectionStr, "raw") == 0)) {
2085  metaData.north = 90.0;
2086  metaData.south = -90.0;
2087  metaData.east = 180.0;
2088  metaData.west = -180.0;
2089  }
2090  // read in north, south, east, west from command line
2091  float north = clo_getFloat(optionList, "north");
2092  int32_t nsew = 0;
2093  if (north > -90.0 && north <= 90.0) {
2094  metaData.north = north;
2095  nsew++;
2096  }
2097  float south = clo_getFloat(optionList, "south");
2098  if (south < 90.0 && south >= -90) {
2099  metaData.south = south;
2100  nsew++;
2101  }
2102  float east = clo_getFloat(optionList, "east");
2103  if (east > -180.0 && east <= 180.0) {
2104  metaData.east = east;
2105  nsew++;
2106  }
2107  float west = clo_getFloat(optionList, "west");
2108  if (west < 180.0 && west >= -180.) {
2109  metaData.west = west;
2110  nsew++;
2111  }
2112  if ((nsew > 0) && (nsew < 4)) {
2113  printf("-E- If any of north, south, east or west are provided, ALL need to be provided.\n");
2114  exit(EXIT_FAILURE);
2115  }
2116  if (metaData.north <= metaData.south) {
2117  printf("-E- north must be greater than south.\n");
2118  exit(EXIT_FAILURE);
2119  }
2120  heightInDeg = metaData.north - metaData.south;
2121  if (heightInDeg > 180.0) {
2122  printf("-E- height in degrees must be less than or equal to 180.\n");
2123  exit(EXIT_FAILURE);
2124  }
2125  mapEast = metaData.east;
2126  mapWest = metaData.west;
2127  if (mapEast < mapWest)
2128  mapEast += 360;
2130 
2131  if (widthInDeg > 360.0) {
2132  printf("-E- width in degrees must be less than or equal to 360.\n");
2133  exit(EXIT_FAILURE);
2134  }
2135 
2136  // set other fields in the metadata
2137  strcpy(metaData.soft_name, "l3mapgen");
2138  strcpy(metaData.soft_ver, softwareVersion);
2139  if ((tmpStr = strrchr(ifileName, '/')) != NULL)
2140  tmpStr++;
2141  else
2142  tmpStr = ifileName;
2143  strcpy(metaData.infiles, tmpStr);
2144  metaData.proc_con[0] = 0;
2145  for (i = 0; i < argc; i++) {
2146  strcat(metaData.proc_con, argv[i]);
2147  strcat(metaData.proc_con, " ");
2148  }
2149  strcpy(metaData.pversion, clo_getString(optionList, "pversion"));
2150 
2151  // set input parameters
2152  metaData.input_parms[0] = 0;
2153  int numOptions = clo_getNumOptions(optionList);
2154  for (int i = 0; i < numOptions; i++) {
2155  clo_option_t* option = clo_getOption(optionList, i);
2156  if (option) {
2157  if (strcmp(option->key, "help") == 0)
2158  continue;
2159  if (strcmp(option->key, "version") == 0)
2160  continue;
2161  if (strstr(option->key, "dump_options"))
2162  continue;
2163  char* val = option->valStr;
2164  if (val == NULL)
2165  val = option->defaultVal;
2166  if (val == NULL)
2167  val = "";
2168  strcat(metaData.input_parms, option->key);
2169  strcat(metaData.input_parms, "=");
2170  strcat(metaData.input_parms, val);
2171  strcat(metaData.input_parms, "|");
2172  }
2173  }
2174 
2175  // set processing time
2176  get_time(metaData.ptime);
2177 
2178  for (OutFile* outFile : outFiles) {
2179  outFile->setMetaData(&metaData);
2180  outFile->setDeflate(clo_getInt(optionList, "deflate"));
2181  outFile->setFullLatLon(clo_getBool(optionList, "full_latlon"));
2182  }
2183  if (outFile2) {
2184  outFile2->setMetaData(&metaData);
2185  outFile2->setDeflate(clo_getInt(optionList, "deflate"));
2186  outFile2->setFullLatLon(clo_getBool(optionList, "full_latlon"));
2187  }
2188  // writing netcdf4 file? // assume so
2189  if (strcasecmp(projectionStr, "raw") == 0) {
2190  writeRawFile(l3File, outFiles, outFile2);
2191  } else if (strcasecmp(projectionStr, "smi") == 0) {
2192  writeSmiFile(l3File, outFiles, outFile2);
2193  } else {
2194  writeProj4File(l3File, projectionStr, outFiles, outFile2, trimNSEW);
2195  }
2196 
2197  // check if no pixels are filled
2198  if (outFiles[0]->getNumFilledPixels() == 0) {
2199  printf("\nThere are no filled pixels\n");
2200  printf("Deleting output file.\n");
2201 
2202  string cmd;
2203  for (OutFile* outFile : outFiles) {
2204  cmd = "rm -f ";
2205  cmd += outFile->getFileName();
2206  system(cmd.c_str());
2207  }
2208 
2209  if (outFile2) {
2210  cmd = "rm -f ";
2211  cmd += outFile2->getFileName();
2212  system(cmd.c_str());
2213  }
2214  exit(110);
2215  }
2216 
2217  // check the % filled threshold
2218  float threshold = clo_getFloat(optionList, "threshold");
2219  if (threshold > 0.0) {
2220  if (outFiles[0]->getPercentFilledPixels() < threshold) {
2221  printf(
2222  "\nPercent filled pixels (%.1f) "
2223  "is below the threshold (%.1f)\n",
2224  outFiles[0]->getPercentFilledPixels(), threshold);
2225  printf("Deleting output file.\n");
2226 
2227  string cmd;
2228  for (OutFile* outFile : outFiles) {
2229  cmd = "rm -f ";
2230  cmd += outFile->getFileName();
2231  system(cmd.c_str());
2232  }
2233 
2234  if (outFile2) {
2235  cmd = "rm -f ";
2236  cmd += outFile2->getFileName();
2237  system(cmd.c_str());
2238  }
2239  exit(110);
2240  }
2241  }
2242 
2243  printEndInfo(outFiles[0]);
2244  for (OutFile* outFile : outFiles) {
2245  delete outFile;
2246  }
2247  if (outFile2)
2248  delete outFile2;
2249  delete l3File;
2250 
2251  return EXIT_SUCCESS;
2252 }
virtual void setMetaData(meta_l3bType *metaData)
Definition: OutFile.cpp:503
int32 value
Definition: Granule.c:1235
char * defaultVal
Definition: clo.h:109
virtual void setPixel(int32_t x, double val, int32_t prod=0)
Definition: OutFile.cpp:385
#define NUM_SEARCH_POINTS
Definition: l3mapgen.cpp:39
virtual void writeLine()=0
#define EXIT_SUCCESS
Definition: GEO_basic.h:72
virtual L3Bin * getClosestBin(float lat, float lon)
Definition: L3File.cpp:763
void freeProductInfo(productInfo_t *info)
int j
Definition: decode_rs.h:73
std::unordered_map< std::string, std::vector< int32_t > > wv3d_2d_name_to_3d_expansion
Definition: l3mapgen.cpp:47
char * clo_getString(clo_optionList_t *list, const char *key)
Definition: clo.c:1357
int status
Definition: l1_czcs_hdf.c:32
virtual bool hasQuality()
Definition: L3File.cpp:812
@ Avg
Definition: l3mapgen.cpp:41
virtual int32_t getNumCols(int32_t row) const =0
virtual void landPixel(int32_t x)
Definition: OutFile.cpp:418
virtual void setPixelRGB(int32_t x, float red, float green, float blue)
Definition: OutFile.cpp:397
@ IsWest
Definition: l3mapgen.cpp:43
char infiles[LG_ATTRSZ]
Definition: meta_l3b.h:38
void * allocateMemory(size_t numBytes, const char *name)
Definition: allocateMemory.c:7
vector< OutFile * > makeOutputFileList(clo_optionList_t *optionList)
Definition: l3mapgen.cpp:1692
float getCentralMeridian()
Definition: l3mapgen.cpp:194
virtual void missingPixel(int32_t x)
Definition: OutFile.cpp:440
#define VERSION_MINOR
Definition: version.h:2
#define NULL
Definition: decode_rs.h:63
size_t get_len_wv3d()
Definition: l3mapgen.cpp:61
L3Bin * getBin(int64_t binNum)
Definition: L3File.cpp:336
string qualName
Definition: l3mapgen.cpp:102
char * key
Definition: clo.h:107
this program makes no use of any feature of the SDP Toolkit that could generate such a then geolocation is calculated at that resolution
Definition: HISTORY.txt:188
virtual bool open(const char *fileName)
Definition: L3File.cpp:454
char * clo_getOptionRawString(clo_option_t *option)
Definition: clo.c:1030
char input_parms[LG_ATTRSZ]
Definition: meta_l3b.h:36
int sensorName2SensorId(const char *name)
Definition: sensorInfo.c:371
vector< string > prodNameList
Definition: l3mapgen.cpp:100
int clo_isSet(clo_optionList_t *list, const char *key)
Definition: clo.c:2270
PARAM_TYPE_NONE Default value No parameter is buried in the product name name_prefix is case insensitive string compared to the product name PARAM_TYPE_VIS_WAVE The visible wavelength bands from the sensor are buried in the product name The product name is compared by appending wavelength
#define GITSHA
Definition: version.h:4
clo_option_t * clo_findOption(clo_optionList_t *list, const char *key)
Definition: clo.c:967
float32 * pos
Definition: l1_czcs_hdf.c:35
std::vector< std::string > wavelength_3d_list_separated
Definition: l3mapgen.cpp:46
InterpType
Definition: l3mapgen.cpp:42
#define VERSION_PATCH
Definition: version.h:3
size_t wavelength_3d_size
Definition: l3mapgen.cpp:50
EastWest
Definition: l3mapgen.cpp:43
string prodName
Definition: l3mapgen.cpp:99
void setFullLatLon(bool val)
Definition: OutFile.h:237
double constrainLon(double lon)
Definition: L3Shape.cpp:26
virtual void setNumCacheRows(int32_t numRows)
Definition: L3File.cpp:444
virtual L3Shape * getShape() const
Definition: L3File.h:321
bool applyMask
Definition: l3mapgen.cpp:107
int clo_getInt(clo_optionList_t *list, const char *key)
Definition: clo.c:1393
@ string
virtual void fillPixel(int32_t x)
Definition: OutFile.cpp:429
int clo_isOptionSet(clo_option_t *option)
Definition: clo.c:2257
grid_info_t * allocate_gridinfo()
Definition: nc_gridutils.c:107
#define VERSION_MAJOR
Definition: version.h:1
L3Bin * getBinByIndex(int32_t index)
Definition: L3File.cpp:382
double heightInDeg
Definition: l3mapgen.cpp:87
virtual int32_t getNumRows()
Definition: L3File.cpp:750
virtual void setMapProjection(std::string projection)
Definition: OutFile.cpp:579
@ Nobs
Definition: l3mapgen.cpp:41
#define PRODUCT_DEFAULT_fillValue
Definition: productInfo.h:29
bool doingQuality
Definition: l3mapgen.cpp:93
virtual bool setActiveProductList(const char *prodStr)
Definition: L3File.cpp:615
@ Interp_Nearest
Definition: l3mapgen.cpp:42
InterpType interpStr2Type(const char *str)
Definition: l3mapgen.cpp:222
virtual void setLandRGB(const char *rgb_land_string)
Definition: OutFile.cpp:494
virtual void setSize(int32_t width, int32_t height)
Definition: OutFile.cpp:358
bool setupQualityProcessing(L3File *l3File, vector< OutFile * > outFiles, OutFile *outFile2)
Definition: l3mapgen.cpp:306
@ Interp_Bin
Definition: l3mapgen.cpp:42
OutFile * makeOutputFile(const char *oformatStr, bool useColor)
Definition: l3mapgen.cpp:1641
clo_optionList_t * clo_createList()
Definition: clo.c:532
virtual void setQualityName(std::string qualName)
Definition: OutFile.h:221
virtual int32_t getNumProducts()
Definition: L3File.cpp:605
int init_gridinfo(const char *filename, const char *varnames[], grid_info_t *grid)
Definition: nc_gridutils.c:132
virtual std::string getProductName(size_t index=0)
Definition: L3File.cpp:611
virtual void setDeflate(int val)
Definition: OutFile.h:231
virtual void setQualityProcessing(bool val)
Definition: L3File.cpp:819
virtual L3Row * getRow(int32_t row)
Definition: L3File.cpp:719
void sort(unsigned long n, float arr[])
productInfo_t * allocateProductInfo()
void get_time(char *pr_time)
Definition: get_time.c:28
bool write_projtext
Definition: l3mapgen.cpp:97
const char * getFileFormatName(const char *str)
char * valStr
Definition: clo.h:111
std::unordered_map< std::string, std::string > wv3d_3d_name_to_2d_name
Definition: l3mapgen.cpp:48
char * strdup(const char *)
float clo_getFloat(clo_optionList_t *list, const char *key)
Definition: clo.c:1429
virtual void setResolution(std::string resolutionStr)
char * clo_getOptionString(clo_option_t *option)
Definition: clo.c:1050
virtual bool setPalette(const char *paletteName, bool applyMask)
Definition: OutFile.cpp:459
virtual meta_l3bType * getMetadata()
Definition: OutFile.h:190
#define PRODUCT_DEFAULT_palette
Definition: productInfo.h:15
@ Nscenes
Definition: l3mapgen.cpp:41
const char * interpType2Str(InterpType interp)
Definition: l3mapgen.cpp:237
double mapEast
Definition: l3mapgen.cpp:88
bool doingTransparency
Definition: l3mapgen.cpp:95
void clo_printUsage(clo_optionList_t *list)
Definition: clo.c:1988
#define PRODUCT_DEFAULT_displayMin
Definition: productInfo.h:37
uint8_t getQuality() const
Definition: L3File.cpp:234
bg::model::polygon< Point_t > Polygon_t
Definition: get_dataday.cpp:25
vector< MeasurementType > prodMeasurementList
Definition: l3mapgen.cpp:101
#define PRODUCT_DEFAULT_displayMax
Definition: productInfo.h:38
virtual float getPercentFilledPixels()
Definition: OutFile.cpp:609
virtual int64_t getBaseBin(int32_t row) const =0
L3Bin * getBinsInside(Geometry geo, bool areaWeighted=false)
Definition: L3File.h:268
@ notEastOrWest
Definition: l3mapgen.cpp:43
double resolution
Definition: meta_l3b.h:53
void setupProduct(string &prodName, MeasurementType measure, OutFile *outFile, OutFile *outFile2)
Definition: l3mapgen.cpp:346
virtual meta_l3bType * getMetaData()
Definition: L3File.cpp:499
virtual double getFileMinVal()
Definition: OutFile.h:204
const double delta
clo_optionList_t * optionList
Definition: l3mapgen.cpp:104
bg::model::point< double, 2, bg::cs::spherical_equatorial< bg::degree > > Point_t
Definition: get_dataday.cpp:23
int want_verbose
virtual int32_t getNumFilledPixels()
Definition: OutFile.cpp:602
MeasurementType
Definition: l3mapgen.cpp:41
int imageHeight
Definition: l3mapgen.cpp:92
virtual void bin2latlon(int64_t bin, double &lat, double &lon)
Definition: L3Shape.cpp:99
std::vector< std::string > output_products_with_3d
Definition: l3mapgen.cpp:49
L3Bin * getBoxBins(L3File *l3File, float lat, float lon, float deltaLat, float deltaLon, float fudge, bool areaWeighted, int eastwest=notEastOrWest)
Definition: l3mapgen.cpp:288
bool doingRGB
Definition: l3mapgen.cpp:94
@ ObsTime
Definition: l3mapgen.cpp:41
float getObsTime() const
Definition: L3File.cpp:218
bool checkDateLineCrossed(double lon, double deltaLon)
Definition: l3mapgen.cpp:252
int64_t getNumBins() const
Definition: L3File.cpp:320
clo_option_t * clo_getOption(clo_optionList_t *list, int i)
Definition: clo.c:908
float north
Definition: meta_l3b.h:49
#define EARTH_CIRCUMFERENCE
Definition: genutils.h:10
virtual void setQuality(int32_t x, uint8_t val)
Definition: OutFile.cpp:406
int isLand(float lat, float lon)
Definition: l3mapgen.cpp:110
int64_t getBinNum() const
Definition: L3File.cpp:186
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 pixel
Definition: HISTORY.txt:192
string & trim(string &s, const string &delimiters)
Definition: EnvsatUtil.cpp:29
char title[SM_ATTRSZ]
Definition: meta_l3b.h:17
bool trimNSEW
Definition: l3mapgen.cpp:96
int clo_getNumOptions(clo_optionList_t *list)
Definition: clo.c:1017
double mapWest
Definition: l3mapgen.cpp:89
int l3mapgen_read_options(clo_optionList_t *list, int argc, char *argv[])
void parse_file_name(const char *inpath, char *outpath)
@ IsEast
Definition: l3mapgen.cpp:43
float west
Definition: meta_l3b.h:52
int sensorID
Definition: meta_l3b.h:18
int findProductInfo(const char *productName, int sensorId, productInfo_t *info)
int get_bylatlon(grid_info_t *grid, float lat, float lon, double *value)
Definition: nc_gridutils.c:368
int32_t getNobs() const
Definition: L3File.cpp:194
virtual void setTransparency()
Definition: OutFile.cpp:402
float getMean(int32_t prodId=0) const
Definition: L3File.cpp:263
int l3mapgen_init_options(clo_optionList_t *list, const char *softwareVersion)
virtual void setLatLon(double *lat, double *lon)
Definition: OutFile.cpp:451
Definition: names.f90:1
float south
Definition: meta_l3b.h:50
char proc_con[MD_ATTRSZ]
Definition: meta_l3b.h:35
void writeRawFile(L3File *l3File, vector< OutFile * > outFiles, OutFile *outFile2)
Definition: l3mapgen.cpp:572
float getStdev(int32_t prodId=0) const
Definition: L3File.cpp:288
Box_t getBox(float lat, float lon, float deltaLat, float deltaLon, int eastwest=notEastOrWest)
Definition: l3mapgen.cpp:264
char soft_ver[SM_ATTRSZ]
Definition: meta_l3b.h:33
double widthInDeg
Definition: l3mapgen.cpp:86
virtual void setQualityProcessing(bool val)
Definition: OutFile.cpp:626
@ Interp_Area
Definition: l3mapgen.cpp:42
#define PRODUCT_DEFAULT_validMin
Definition: productInfo.h:34
float getVariance(int32_t prodId=0) const
Definition: L3File.cpp:273
void setProj4Info(std::string projStr, double minX, double maxY)
Definition: OutFile.cpp:583
void writeProj4File(L3File *l3File, char *projectionStr, vector< OutFile * > outFiles, OutFile *outFile2, bool trimNSEW)
Definition: l3mapgen.cpp:927
char ptime[SM_ATTRSZ]
Definition: meta_l3b.h:34
data_t s[NROOTS]
Definition: decode_rs.h:75
int imageWidth
Definition: l3mapgen.cpp:91
void nc_init_chunk_cache()
int32_t rdsensorinfo(int32_t, int32_t, const char *, void **)
Definition: rdsensorinfo.c:69
char * clo_getRawString(clo_optionList_t *list, const char *key)
Definition: clo.c:1339
char pversion[SM_ATTRSZ]
Definition: meta_l3b.h:30
Definition: L3File.cpp:10
@ Variance
Definition: l3mapgen.cpp:41
int clo_getBool(clo_optionList_t *list, const char *key)
Definition: clo.c:1375
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
void printPercentDone(float percentDone)
Definition: l3mapgen.cpp:184
float east
Definition: meta_l3b.h:51
void printEndInfo(OutFile *outFile)
Definition: l3mapgen.cpp:173
@ Interp_Linear
Definition: l3mapgen.cpp:42
char sensor_name[SM_ATTRSZ]
Definition: meta_l3b.h:19
int32_t getNscenes() const
Definition: L3File.cpp:202
int i
Definition: decode_rs.h:71
double rint(double)
virtual void setFileName(std::string fileName)
Definition: OutFile.cpp:381
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
std::string get_modifier_from_measure(MeasurementType measure)
Definition: l3mapgen.cpp:65
int main(int argc, char *argv[])
Definition: l3mapgen.cpp:1734
virtual void setNumFilledPixels(int32_t num)
Definition: OutFile.cpp:596
void clo_printVersion()
Definition: clo.c:1968
Definition: aerosol.c:136
char soft_name[SM_ATTRSZ]
Definition: meta_l3b.h:32
#define EXIT_LOG(...)
Definition: l3mapgen.cpp:29
virtual double getFileMaxVal()
Definition: OutFile.h:208
int clo_getOptionBool(clo_option_t *option)
Definition: clo.c:1087
void writeSmiFile(L3File *l3File, vector< OutFile * > outFiles, OutFile *outFile2)
Definition: l3mapgen.cpp:739
virtual bool close()=0
const std::unordered_map< std::string, std::string > & get_wv3d_3d_name_to_2d_name()
Definition: l3mapgen.cpp:57
#define str(s)
@ BinNum
Definition: l3mapgen.cpp:41
virtual std::string getFileName()
Definition: OutFile.h:156
bg::model::box< Point_t > Box_t
Definition: l1c.cpp:69
@ Stdev
Definition: l3mapgen.cpp:41
virtual bool open()=0
void printStartInfo(vector< OutFile * > outFiles)
Definition: l3mapgen.cpp:120
const std::unordered_map< std::string, std::vector< int32_t > > & get_wv3d_2d_name_to_3d_expansion()
Definition: l3mapgen.cpp:53
virtual int32_t addProduct(productInfo_t *productInfo)
Definition: OutFile.cpp:512