OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
productInfo.cpp
Go to the documentation of this file.
1 #include <productInfo.h>
2 
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <pugixml.hpp>
7 #include <genutils.h>
8 #include <sensorInfo.h>
9 
10 #define XML_STRING_SIZE 512
11 
12 using namespace pugi;
13 
14 /*
15  * global variables
16  */
17 static bool productInitialized = false;
18 static char productXMLFileName[FILENAME_MAX];
19 static xml_document rootNode;
20 static xml_node productsNode;
21 static xml_node productNode;
22 static xml_node algorithmNode;
23 
24 static productInfo_t* productInfo = NULL;
25 static productInfo_t* algorithmInfo = NULL;
26 
27 /*
28  * dup string if src is not NULL.
29  */
30 static char* duplicateString(const char* src) {
31  if (src == NULL)
32  return NULL;
33  else
34  return strdup(src);
35 }
36 
42 extern "C" void clearProductInfo(productInfo_t* info) {
43  if (info->description)
44  free(info->description);
45  info->description = duplicateString(PRODUCT_DEFAULT_description);
46  if (info->units)
47  free(info->units);
48  info->units = duplicateString(PRODUCT_DEFAULT_units);
49  if (info->palette)
50  free(info->palette);
51  info->palette = duplicateString(PRODUCT_DEFAULT_palette);
52  if (info->paramDesignator)
53  free(info->paramDesignator);
54  info->paramDesignator = duplicateString(PRODUCT_DEFAULT_paramDesignator);
55  info->paramWaveMin = PRODUCT_DEFAULT_paramWaveMin;
56  info->paramWaveMax = PRODUCT_DEFAULT_paramWaveMax;
57  if (info->standardName)
58  free(info->standardName);
59  info->standardName = duplicateString(PRODUCT_DEFAULT_standardName);
60  if (info->category)
61  free(info->category);
62  info->category = duplicateString(PRODUCT_DEFAULT_category);
63  if (info->dataType)
64  free(info->dataType);
65  info->dataType = duplicateString(PRODUCT_DEFAULT_dataType);
66  if (info->prefix)
67  free(info->prefix);
68  info->prefix = duplicateString(PRODUCT_DEFAULT_prefix);
69  if (info->suffix)
70  free(info->suffix);
71  info->suffix = duplicateString(PRODUCT_DEFAULT_suffix);
72  if (info->algorithmName)
73  free(info->algorithmName);
74  info->algorithmName = duplicateString(PRODUCT_DEFAULT_algorithmName);
75  if (info->productName)
76  free(info->productName);
77  info->productName = duplicateString(PRODUCT_DEFAULT_productName);
78  info->cat_ix = PRODUCT_DEFAULT_cat_ix;
79  info->prod_ix = PRODUCT_DEFAULT_prod_ix;
80  info->rank = PRODUCT_DEFAULT_rank;
81  info->fillValue = PRODUCT_DEFAULT_fillValue;
82  info->validMin = PRODUCT_DEFAULT_validMin;
83  info->validMax = PRODUCT_DEFAULT_validMax;
84  if (info->displayScale)
85  free(info->displayScale);
86  info->displayScale = duplicateString(PRODUCT_DEFAULT_displayScale);
87  info->displayMin = PRODUCT_DEFAULT_displayMin;
88  info->displayMax = PRODUCT_DEFAULT_displayMax;
89  info->scaleFactor = PRODUCT_DEFAULT_scaleFactor;
90  info->addOffset = PRODUCT_DEFAULT_addOffset;
91  if (info->reference)
92  free(info->reference);
93  info->reference = duplicateString(PRODUCT_DEFAULT_reference);
94  if (info->comment)
95  free(info->comment);
96  info->comment = duplicateString(PRODUCT_DEFAULT_comment);
97  if (info->titleFormat)
98  free(info->titleFormat);
99  info->titleFormat = duplicateString(PRODUCT_DEFAULT_titleFormat);
100 }
101 
107 extern "C" void initProductInfo(productInfo_t* info) {
108  bzero(info, sizeof (productInfo_t));
109  clearProductInfo(info);
110 }
111 
118 extern "C" productInfo_t* allocateProductInfo() {
119  productInfo_t* info = (productInfo_t*) allocateMemory(sizeof (productInfo_t),
120  "productInfo");
121  clearProductInfo(info);
122  return info;
123 }
124 
130 extern "C" void freeProductInfo(productInfo_t* info) {
131  if (info->description)
132  free(info->description);
133  if (info->units)
134  free(info->units);
135  if (info->palette)
136  free(info->palette);
137  if (info->paramDesignator)
138  free(info->paramDesignator);
139  if (info->standardName)
140  free(info->standardName);
141  if (info->category)
142  free(info->category);
143  if (info->dataType)
144  free(info->dataType);
145  if (info->prefix)
146  free(info->prefix);
147  if (info->suffix)
148  free(info->suffix);
149  if (info->algorithmName)
150  free(info->algorithmName);
151  if (info->productName)
152  free(info->productName);
153  if (info->displayScale)
154  free(info->displayScale);
155  if (info->reference)
156  free(info->reference);
157  if (info->comment)
158  free(info->comment);
159  if (info->titleFormat)
160  free(info->titleFormat);
161  free(info);
162 }
163 
170 void copyProductInfoHeader(productInfo_t* dest, const productInfo_t* src) {
171  if (dest->productName)
172  free(dest->productName);
173  dest->productName = duplicateString(src->productName);
174  if (dest->paramDesignator)
175  free(dest->paramDesignator);
176  dest->paramDesignator = duplicateString(src->paramDesignator);
177  dest->paramWaveMin = src->paramWaveMin;
178  dest->paramWaveMax = src->paramWaveMax;
179 }
180 
187 extern "C" void copyProductInfo(productInfo_t* dest, const productInfo_t* src) {
188  if (dest->description && strlen(dest->description) > 0)
189  free(dest->description);
190  dest->description = duplicateString(src->description);
191  if (dest->units)
192  free(dest->units);
193  dest->units = duplicateString(src->units);
194  if (dest->palette)
195  free(dest->palette);
196  dest->palette = duplicateString(src->palette);
197  if (dest->paramDesignator)
198  free(dest->paramDesignator);
199  dest->paramDesignator = duplicateString(src->paramDesignator);
200  dest->paramWaveMin = src->paramWaveMin;
201  dest->paramWaveMax = src->paramWaveMax;
202  if (dest->standardName)
203  free(dest->standardName);
204  dest->standardName = duplicateString(src->standardName);
205  if (dest->category)
206  free(dest->category);
207  dest->category = duplicateString(src->category);
208  if (dest->dataType)
209  free(dest->dataType);
210  dest->dataType = duplicateString(src->dataType);
211  if (dest->prefix)
212  free(dest->prefix);
213  dest->prefix = duplicateString(src->prefix);
214  if (dest->suffix)
215  free(dest->suffix);
216  dest->suffix = duplicateString(src->suffix);
217  if (dest->algorithmName)
218  free(dest->algorithmName);
219  dest->algorithmName = duplicateString(src->algorithmName);
220  if (dest->productName)
221  free(dest->productName);
222  dest->productName = duplicateString(src->productName);
223  dest->cat_ix = src->cat_ix;
224  dest->prod_ix = src->prod_ix;
225  dest->rank = src->rank;
226  dest->fillValue = src->fillValue;
227  dest->validMin = src->validMin;
228  dest->validMax = src->validMax;
229  if (dest->displayScale)
230  free(dest->displayScale);
231  dest->displayScale = duplicateString(src->displayScale);
232  dest->displayMin = src->displayMin;
233  dest->displayMax = src->displayMax;
234  dest->scaleFactor = src->scaleFactor;
235  dest->addOffset = src->addOffset;
236  if (dest->reference)
237  free(dest->reference);
238  dest->reference = duplicateString(src->reference);
239  if (dest->comment)
240  free(dest->comment);
241  dest->comment = duplicateString(src->comment);
242  if (dest->titleFormat)
243  free(dest->titleFormat);
244  dest->titleFormat = duplicateString(src->titleFormat);
245 }
246 
250 void initXmlFile() {
251 
252  // bail if root node is already set
253  if (productInitialized)
254  return;
255  productInitialized = true;
256 
257  char *dataRoot;
258  if ((dataRoot = getenv("OCDATAROOT")) == NULL) {
259  printf("OCDATAROOT environment variable is not defined.\n");
260  exit(1);
261  }
262  strcpy(productXMLFileName, dataRoot);
263  strcat(productXMLFileName, "/common/product.xml");
264 
265  xml_parse_result result = rootNode.load_file(productXMLFileName);
266  if (!result) {
267  printf("%s Line %d: could not open product XML file = %s\n",
268  __FILE__, __LINE__, productXMLFileName);
269  printf(" %s", result.description());
270  exit(1);
271  }
272  productsNode = rootNode.child("products");
273  if (!productsNode) {
274  printf("%s Line %d: could not find products tag in XML file = %s\n",
275  __FILE__, __LINE__, productXMLFileName);
276  exit(1);
277  }
278 
279  productInfo = allocateProductInfo();
280  algorithmInfo = allocateProductInfo();
281 
282 }
283 
288  const char *tmpStr;
289 
290  tmpStr = productNode.name();
291  if (strcmp(tmpStr, "product") != 0) {
292  printf("%s Line %d: \"product\" node expected, found \"%s\" in file %s\n",
293  __FILE__, __LINE__, tmpStr, productXMLFileName);
294  exit(1);
295  }
296 }
297 
302  const char *tmpStr;
303 
304  tmpStr = algorithmNode.name();
305  if (strcmp(tmpStr, "algorithm") != 0) {
306  printf("%s Line %d: \"algorithm\" node expected, found \"%s\" in file %s\n",
307  __FILE__, __LINE__, tmpStr, productXMLFileName);
308  exit(1);
309  }
310 }
311 
315 void readParamDesignator(productInfo_t* info, xml_node node) {
316  char *tmpStr;
317  const char *tmpStr1;
318  xml_node tmpNode;
319 
320  tmpNode = node.child("paramDesignator");
321 
322  // reset the param designator to none if there is one
323  if (tmpNode) {
324  free(info->paramDesignator);
325  info->paramDesignator = strdup(PRODUCT_DEFAULT_paramDesignator);
326  info->paramWaveMin = PRODUCT_DEFAULT_paramWaveMin;
327  info->paramWaveMax = PRODUCT_DEFAULT_paramWaveMax;
328  }
329 
330  while (tmpNode) {
331 
332  // grab the text
333 
334  tmpStr1 = tmpNode.child_value();
335  tmpStr = trimBlanksDup(tmpStr1);
336 
337  if (strcmp(tmpStr, "none") == 0 ||
338  strcmp(tmpStr, "band") == 0 ||
339  strcmp(tmpStr, "int") == 0) {
340  free(info->paramDesignator);
341  info->paramDesignator = tmpStr;
342  info->paramWaveMin = PRODUCT_DEFAULT_paramWaveMin;
343  info->paramWaveMax = PRODUCT_DEFAULT_paramWaveMax;
344  return;
345  } else if (strcmp(tmpStr, "uv") == 0) {
346  if (strcmp(info->paramDesignator, "wave") != 0) {
347  free(info->paramDesignator);
348  info->paramDesignator = strdup("wave");
349  }
350  if (info->paramWaveMin == PRODUCT_DEFAULT_paramWaveMin ||
351  info->paramWaveMin > 100)
352  info->paramWaveMin = 100;
353  if (info->paramWaveMax == PRODUCT_DEFAULT_paramWaveMax ||
354  info->paramWaveMax < 400)
355  info->paramWaveMax = 400;
356  } else if (strcmp(tmpStr, "visible") == 0) {
357  if (strcmp(info->paramDesignator, "wave") != 0) {
358  free(info->paramDesignator);
359  info->paramDesignator = strdup("wave");
360  }
361  if (info->paramWaveMin == PRODUCT_DEFAULT_paramWaveMin ||
362  info->paramWaveMin > 400)
363  info->paramWaveMin = 400;
364  if (info->paramWaveMax == PRODUCT_DEFAULT_paramWaveMax ||
365  info->paramWaveMax < 725)
366  info->paramWaveMax = 725;
367  } else if (strcmp(tmpStr, "nir") == 0) {
368  if (strcmp(info->paramDesignator, "wave") != 0) {
369  free(info->paramDesignator);
370  info->paramDesignator = strdup("wave");
371  }
372  if (info->paramWaveMin == PRODUCT_DEFAULT_paramWaveMin ||
373  info->paramWaveMin > 725)
374  info->paramWaveMin = 725;
375  if (info->paramWaveMax == PRODUCT_DEFAULT_paramWaveMax ||
376  info->paramWaveMax < 1400)
377  info->paramWaveMax = 1400;
378  } else if (strcmp(tmpStr, "swir") == 0) {
379  if (strcmp(info->paramDesignator, "wave") != 0) {
380  free(info->paramDesignator);
381  info->paramDesignator = strdup("wave");
382  }
383  if (info->paramWaveMin == PRODUCT_DEFAULT_paramWaveMin ||
384  info->paramWaveMin > 1400)
385  info->paramWaveMin = 1400;
386  if (info->paramWaveMax == PRODUCT_DEFAULT_paramWaveMax ||
387  info->paramWaveMax < 3000)
388  info->paramWaveMax = 3000;
389  } else if (strcmp(tmpStr, "emissive") == 0) {
390  if (strcmp(info->paramDesignator, "wave") != 0) {
391  free(info->paramDesignator);
392  info->paramDesignator = strdup("wave");
393  }
394  if (info->paramWaveMin == PRODUCT_DEFAULT_paramWaveMin ||
395  info->paramWaveMin > 3000)
396  info->paramWaveMin = 3000;
397  if (info->paramWaveMax == PRODUCT_DEFAULT_paramWaveMax ||
398  info->paramWaveMax < 15000)
399  info->paramWaveMax = 15000;
400  } else {
401  printf("%s Line %d: \"paramDesignator\" node has illegal value \"%s\" in file %s\n",
402  __FILE__, __LINE__, tmpStr, productXMLFileName);
403  exit(1);
404  }
405 
406  free(tmpStr);
407 
408  // grab next node
409  tmpNode = tmpNode.next_sibling("paramDesignator");
410  }
411 }
412 
419 void readSingleRange(productInfo_t* productInfo, xml_node rangeNode) {
420  xml_node node;
421  if ((node = rangeNode.child("validMin")))
422  productInfo->validMin = atof(node.child_value());
423  if ((node = rangeNode.child("validMax")))
424  productInfo->validMax = atof(node.child_value());
425  if ((node = rangeNode.child("displayMin")))
426  productInfo->displayMin = atof(node.child_value());
427  if ((node = rangeNode.child("displayMax")))
428  productInfo->displayMax = atof(node.child_value());
429  if ((node = rangeNode.child("scaleFactor")))
430  productInfo->scaleFactor = atof(node.child_value());
431  if ((node = rangeNode.child("addOffset")))
432  productInfo->addOffset = atof(node.child_value());
433 }
434 
442 void readRange(productInfo_t* productInfo, xml_node productNode, int paramVal) {
443  int min, max;
444  xml_node rangeNode;
445  xml_attribute attr;
446 
447  // set the default
448  rangeNode = productNode.child("range");
449  do {
450 
451  // make sure min and max are not defined
452  if (rangeNode.attribute("min"))
453  continue;
454  if (rangeNode.attribute("max"))
455  continue;
456 
457  readSingleRange(productInfo, rangeNode);
458 
459  } while ((rangeNode = rangeNode.next_sibling("range")));
460 
461  // now search for the matching range
462  rangeNode = productNode.child("range");
463  do {
464  // make sure min and max are defined
465  if ((attr = rangeNode.attribute("min"))) {
466  min = attr.as_int();
467  if ((attr = rangeNode.attribute("max"))) {
468  max = attr.as_int();
469  if (min <= paramVal && paramVal <= max) {
470  readSingleRange(productInfo, rangeNode);
471  break;
472  }
473  }
474  }
475  } while ((rangeNode = rangeNode.next_sibling("range")));
476 
477 }
478 
483 
484  // clear and set productName
485  if (productInfo->productName)
486  free(productInfo->productName);
487  productInfo->productName = trimBlanksDup(productNode.attribute("name").value());
488 
489  // clear and set paramDesignator
490  if (productInfo->paramDesignator)
491  free(productInfo->paramDesignator);
492  productInfo->paramDesignator = duplicateString(PRODUCT_DEFAULT_paramDesignator);
493  readParamDesignator(productInfo, productNode);
494 }
495 
499 void readProduct(int paramVal) {
500  xml_node node;
501 
502  // clear product structure to defaults
503  clearProductInfo(productInfo);
504 
505  if (productInfo->productName)
506  free(productInfo->productName);
507  productInfo->productName = trimBlanksDup(productNode.attribute("name").value());
508 
509  if ((node = productNode.child("standardName"))) {
510  if (productInfo->standardName)
511  free(productInfo->standardName);
512  productInfo->standardName = trimBlanksDup(node.child_value());
513  }
514 
515  node = productNode.child("units");
516  if (!node) {
517  printf("-E- Need to define \"units\" in product \"%s\" in product.xml\n",
518  productInfo->productName);
519  exit(EXIT_FAILURE);
520  }
521  if (productInfo->units)
522  free(productInfo->units);
523  productInfo->units = trimBlanksDup(node.child_value());
524 
525 
526  if ((node = productNode.child("palette"))) {
527  if (productInfo->palette)
528  free(productInfo->palette);
529  productInfo->palette = trimBlanksDup(node.child_value());
530  }
531 
532  node = productNode.child("category");
533  if (!node) {
534  printf("-E- Need to define \"category\" in product \"%s\" in product.xml\n",
535  productInfo->productName);
536  exit(EXIT_FAILURE);
537  }
538  if (productInfo->category)
539  free(productInfo->category);
540  productInfo->category = trimBlanksDup(node.child_value());
541 
542  if ((node = productNode.child("displayScale"))) {
543  if (productInfo->displayScale)
544  free(productInfo->displayScale);
545  productInfo->displayScale = trimBlanksDup(node.child_value());
546  }
547 
548  if ((node = productNode.child("type"))) {
549  if (productInfo->dataType)
550  free(productInfo->dataType);
551  productInfo->dataType = trimBlanksDup(node.child_value());
552  if(!strcmp(productInfo->dataType, "byte")) {
553  if(productInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
554  productInfo->fillValue = PRODUCT_DEFAULT_fillValue_byte;
555  }
556  } else if(!strcmp(productInfo->dataType, "ubyte")) {
557  if(productInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
558  productInfo->fillValue = PRODUCT_DEFAULT_fillValue_ubyte;
559  }
560  } else if(!strcmp(productInfo->dataType, "ushort")) {
561  if(productInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
562  productInfo->fillValue = PRODUCT_DEFAULT_fillValue_ushort;
563  }
564  } else if(!strcmp(productInfo->dataType, "uint")) {
565  if(productInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
566  productInfo->fillValue = PRODUCT_DEFAULT_fillValue_uint;
567  }
568  }
569  }
570 
571  if ((node = productNode.child("reference"))) {
572  if (productInfo->reference)
573  free(productInfo->reference);
574  productInfo->reference = trimBlanksDup(node.child_value());
575  }
576 
577  if ((node = productNode.child("comment"))) {
578  if (productInfo->comment)
579  free(productInfo->comment);
580  productInfo->comment = trimBlanksDup(node.child_value());
581  }
582 
583  readParamDesignator(productInfo, productNode);
584  if (strcmp(productInfo->paramDesignator, "none") != 0) {
585  productInfo->prod_ix = paramVal;
586  }
587 
588  readRange(productInfo, productNode, paramVal);
589 }
590 
596 
597  xml_attribute attr;
598  xml_node node;
599 
600  // copy header info from the productInfo
601  copyProductInfoHeader(algorithmInfo, productInfo);
602 
603  // clear algorithm header
604  if (algorithmInfo->algorithmName) {
605  free(algorithmInfo->algorithmName);
606  algorithmInfo->algorithmName = NULL;
607  }
608  if (algorithmInfo->prefix) {
609  free(algorithmInfo->prefix);
610  algorithmInfo->prefix = NULL;
611  }
612  if (algorithmInfo->suffix) {
613  free(algorithmInfo->suffix);
614  algorithmInfo->suffix = NULL;
615  }
616 
617  // populate the fields
618  if ((attr = algorithmNode.attribute("name"))) {
619  algorithmInfo->algorithmName = trimBlanksDup(attr.value());
620  } else {
621  algorithmInfo->algorithmName = strdup("");
622  }
623 
624  readParamDesignator(algorithmInfo, algorithmNode);
625 
626  char defaultPrefix[XML_STRING_SIZE];
627  if (strcmp(algorithmInfo->paramDesignator, "none") == 0) {
628  strcpy(defaultPrefix, algorithmInfo->productName);
629  } else {
630  strcpy(defaultPrefix, algorithmInfo->productName);
631  strcat(defaultPrefix, "_");
632  }
633 
634  if ((node = algorithmNode.child("prefix"))) {
635  algorithmInfo->prefix = trimBlanksDup(node.child_value());
636  } else {
637  algorithmInfo->prefix = strdup(defaultPrefix);
638  }
639  if ((node = algorithmNode.child("suffix"))) {
640  algorithmInfo->suffix = trimBlanksDup(node.child_value());
641  } else {
642  if (strlen(algorithmInfo->algorithmName) > 0) {
643  algorithmInfo->suffix = (char*) malloc(strlen(algorithmInfo->algorithmName) + 2);
644  strcpy(algorithmInfo->suffix, "_");
645  strcat(algorithmInfo->suffix, algorithmInfo->algorithmName);
646  } else {
647  algorithmInfo->suffix = strdup("");
648  }
649  }
650 }
651 
655 void readAlgorithm(int paramVal) {
656  char tmpStr[XML_STRING_SIZE];
657  xml_node node;
658 
659  // start with the productInfo as default values
660  copyProductInfo(algorithmInfo, productInfo);
662 
663  algorithmInfo->cat_ix = atoi(algorithmNode.child_value("cat_ix"));
664  if ((node = algorithmNode.child("rank")))
665  algorithmInfo->rank = atoi(node.child_value());
666 
667 
668  if ((node = algorithmNode.child("units"))) {
669  if (algorithmInfo->units)
670  free(algorithmInfo->units);
671  algorithmInfo->units = trimBlanksDup(node.child_value());
672  }
673 
674  if ((node = algorithmNode.child("fillValue")))
675  algorithmInfo->fillValue = atof(node.child_value());
676 
677  node = algorithmNode.child("description");
678  if (!node) {
679  printf("-E- Need to define \"description\" in product \"%s_%s\" in product.xml\n",
680  productInfo->productName, productInfo->algorithmName);
681  exit(EXIT_FAILURE);
682 
683  }
684  strcpy(tmpStr, node.child_value());
685  trimBlanks(tmpStr);
686 
687  if (algorithmInfo->titleFormat)
688  free(algorithmInfo->titleFormat);
689  algorithmInfo->titleFormat = strdup(tmpStr);
690  if (algorithmInfo->description)
691  free(algorithmInfo->description);
692  if (strcmp(algorithmInfo->paramDesignator, "none") == 0) {
693  if ((node = algorithmNode.child("prod_ix")))
694  algorithmInfo->prod_ix = atoi(node.child_value());
695  algorithmInfo->description = trimBlanksDup(tmpStr);
696  } else {
697  algorithmInfo->description = (char*) malloc(strlen(tmpStr) + 64);
698  algorithmInfo->prod_ix = paramVal;
699  sprintf(algorithmInfo->description, tmpStr, algorithmInfo->prod_ix);
700  }
701 
702  if ((node = algorithmNode.child("reference"))) {
703  if (algorithmInfo->reference)
704  free(algorithmInfo->reference);
705  algorithmInfo->reference = trimBlanksDup(node.child_value());
706  }
707 
708  if ((node = algorithmNode.child("comment"))) {
709  if (algorithmInfo->comment)
710  free(algorithmInfo->comment);
711  algorithmInfo->comment = trimBlanksDup(node.child_value());
712  }
713 
714  if ((node = algorithmNode.child("type"))) {
715  if (algorithmInfo->dataType)
716  free(algorithmInfo->dataType);
717  algorithmInfo->dataType = trimBlanksDup(node.child_value());
718  if(!strcmp(algorithmInfo->dataType, "byte")) {
719  if(algorithmInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
720  algorithmInfo->fillValue = PRODUCT_DEFAULT_fillValue_byte;
721  }
722  } else if(!strcmp(algorithmInfo->dataType, "ubyte")) {
723  if(algorithmInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
724  algorithmInfo->fillValue = PRODUCT_DEFAULT_fillValue_ubyte;
725  }
726  } else if(!strcmp(algorithmInfo->dataType, "ushort")) {
727  if(algorithmInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
728  algorithmInfo->fillValue = PRODUCT_DEFAULT_fillValue_ushort;
729  }
730  } else if(!strcmp(algorithmInfo->dataType, "uint")) {
731  if(algorithmInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
732  algorithmInfo->fillValue = PRODUCT_DEFAULT_fillValue_uint;
733  }
734  }
735  }
736 
737  readRange(algorithmInfo, algorithmNode, paramVal);
738 }
739 
744  productNode = productsNode.child("product");
745  if (!productNode) {
746  printf("%s Line %d: could not find first product tag in XML file = %s\n",
747  __FILE__, __LINE__, productXMLFileName);
748  exit(1);
749  }
752 
753  algorithmNode = productNode.child("algorithm");
754  if (!algorithmNode) {
755  printf("%s Line %d: could not find first algorithm tag for product=%s in XML file = %s\n",
756  __FILE__, __LINE__, productInfo->productName, productXMLFileName);
757  exit(1);
758  }
761 }
762 
769  algorithmNode = algorithmNode.next_sibling("algorithm");
770  if (!algorithmNode) {
771 
772  // try next product
773  productNode = productNode.next_sibling("product");
774  if (!productNode)
775  return 0;
778 
779  algorithmNode = productNode.child("algorithm");
780  if (!algorithmNode) {
781  printf("%s Line %d: could not find first algorithm tag for product=%s in XML file = %s\n",
782  __FILE__, __LINE__, productInfo->productName, productXMLFileName);
783  exit(1);
784  }
785  }
788  return 1;
789 }
790 
799 int compareAlgorithmHeader(const char* productFullName, int sensorId, int* paramVal) {
800 
801  // see if prefix matches
802  if (strncmp(productFullName, algorithmInfo->prefix, strlen(algorithmInfo->prefix)))
803  return 0;
804 
805  char tmpStr[XML_STRING_SIZE];
806  if (strcmp(algorithmInfo->paramDesignator, "none") == 0) {
807  strcpy(tmpStr, algorithmInfo->prefix);
808  strcat(tmpStr, algorithmInfo->suffix);
809  if (strcmp(tmpStr, productFullName) == 0) {
810  *paramVal = PRODUCT_DEFAULT_prod_ix;
811  return 1;
812  } else {
813  return 0;
814  }
815  } else {
816  int nameLen = strlen(productFullName);
817  int prefixLen = strlen(algorithmInfo->prefix);
818  int suffixLen = strlen(algorithmInfo->suffix);
819  int paramLen = nameLen - prefixLen - suffixLen;
820 
821  // need at least one char to be a valid param
822  if (paramLen < 1)
823  return 0;
824 
825  // check the suffix
826  if (strcmp(algorithmInfo->suffix, productFullName + nameLen - suffixLen) != 0)
827  return 0;
828 
829  // get the param value
830  char paramStr[XML_STRING_SIZE];
831  if (paramLen > XML_STRING_SIZE - 1) // just in case
832  paramLen = XML_STRING_SIZE - 1;
833  paramStr[0] = 0;
834  strncat(paramStr, productFullName + prefixLen, paramLen);
835 
836  if (!isValidInt(paramStr))
837  return 0;
838 
839  int i = atoi(paramStr);
840  if (strcmp(algorithmInfo->paramDesignator, "wave") == 0) {
841  if (algorithmInfo->paramWaveMin <= i && i <= algorithmInfo->paramWaveMax) {
842  int32_t numBands;
843  int32_t *iwave;
844  int waveIndex;
845  int old_verbose = want_verbose;
846  want_verbose = 0;
847  numBands = rdsensorinfo(sensorId, 0, "iwave", (void**) &iwave);
848  numBands += rdsensorinfo(sensorId, 0, "NbandsIR", NULL);
849  want_verbose = old_verbose;
850  if (numBands != -1) {
851  for (waveIndex = 0; waveIndex < numBands; waveIndex++) {
852  if (i == iwave[waveIndex]) {
853  *paramVal = i;
854  return 1;
855  }
856  }
857  }
858 
859  }
860  } else {
861  *paramVal = i;
862  return 1;
863  }
864  }
865  return 0;
866 }
867 
873 extern "C" void getFirstProductInfo(productInfo_t* info) {
874  initXmlFile();
876  readProduct(-1);
877  readAlgorithm(-1);
878  copyProductInfo(info, algorithmInfo);
879 }
880 
887 extern "C" int getNextProductInfo(productInfo_t* info) {
888  if (findNextAlgorithmHeader()) {
889  readProduct(-1);
890  readAlgorithm(-1);
891  copyProductInfo(info, algorithmInfo);
892  return 1;
893  }
894  return 0;
895 }
896 
905 extern "C" int findProductInfo(const char* productName, int sensorId, productInfo_t* info) {
906  int paramVal;
907  const char* tmpProductName = productName;
908 
909 
910  if (strcmp(productName, "chl_ocx") == 0) {
911  switch (sensorId) {
912  case OCTS:
913  case SEAWIFS:
914  case OCM1:
915  case OCM2:
916  case MOS:
917  case MERIS:
918  case HICO:
919  case OCIA:
920  case OCI:
921  case HAWKEYE:
922  case AVIRIS:
923  case PRISM:
924  case OLCIS3A:
925  case OLCIS3B:
926  tmpProductName = "chl_oc4";
927  break;
928  case MODIST:
929  case MODISA:
930  case CZCS:
931  case OSMI:
932  case VIIRSN:
933  case VIIRSJ1:
934  case OCRVC:
935  case GOCI:
936  case SGLI:
937  case OLIL8:
938  case OLIL9:
939  tmpProductName = "chl_oc3";
940  break;
941  case L5TM:
942  case L7ETMP:
943  case MISR:
944  tmpProductName = "chl_oc2";
945  break;
946  default:
947  printf("%s Line %d: need a default chlorophyll algorithm for this sensor\n",
948  __FILE__, __LINE__);
949  exit(1);
950  break;
951 
952  }
953  }
954 
955  initXmlFile();
957  do {
958  if (compareAlgorithmHeader(tmpProductName, sensorId, &paramVal)) {
959  readProduct(paramVal);
960  readAlgorithm(paramVal);
961  copyProductInfo(info, algorithmInfo);
962  if (strcmp(productName, "chl_ocx") == 0) {
963  free(info->suffix);
964  info->suffix = strdup("_ocx");
965  }
966  return 1;
967  }
968  } while (findNextAlgorithmHeader());
969 
970  return 0;
971 }
972 
978 extern "C" char* getProductNameFull(productInfo_t* info) {
979  static char name[XML_STRING_SIZE];
980 
981  if (strcmp(info->paramDesignator, "none") == 0) {
982  strcpy(name, info->prefix);
983  strcat(name, info->suffix);
984  } else {
985  sprintf(name, "%s%d%s", info->prefix, info->prod_ix, info->suffix);
986  }
987  return name;
988 }
989 
996 extern "C" void printProductInfo(const char* productFullName, const productInfo_t* info) {
997  printf("fullProductName=%s\n", productFullName);
998  printf("description=%s\n", info->description);
999  printf("units=%s\n", info->units);
1000  printf("palette=%s\n", info->palette);
1001  printf("paramDesignator=%s\n", info->paramDesignator);
1002  printf("paramWaveMin=%d\n", info->paramWaveMin);
1003  printf("paramWaveMax=%d\n", info->paramWaveMax);
1004  printf("standardName=%s\n", info->standardName);
1005  printf("category=%s\n", info->category);
1006  printf("dataType=%s\n", info->dataType);
1007  printf("prefix=%s\n", info->prefix);
1008  printf("suffix=%s\n", info->suffix);
1009  printf("algorithmName=%s\n", info->algorithmName);
1010  printf("productName=%s\n", info->productName);
1011  printf("cat_ix=%d\n", info->cat_ix);
1012  printf("prod_ix=%d\n", info->prod_ix);
1013  printf("rank=%d\n", info->rank);
1014  printf("fillValue=%g\n", info->fillValue);
1015  printf("validMin=%g\n", info->validMin);
1016  printf("validMax=%g\n", info->validMax);
1017  printf("displayScale=%s\n", info->displayScale);
1018  printf("displayMin=%g\n", info->displayMin);
1019  printf("displayMax=%g\n", info->displayMax);
1020  printf("scaleFactor=%g\n", info->scaleFactor);
1021  printf("addOffset=%g\n", info->addOffset);
1022  printf("reference=%s\n", info->reference);
1023  printf("comment=%s\n", info->comment);
1024  printf("titleFormat=%s\n", info->titleFormat);
1025 }
#define OLCIS3A
Definition: sensorDefs.h:32
void checkAlgorithmNode()
void freeProductInfo(productInfo_t *info)
#define PRODUCT_DEFAULT_standardName
Definition: productInfo.h:18
#define SGLI
Definition: sensorDefs.h:33
void readParamDesignator(productInfo_t *info, xml_node node)
#define OCI
Definition: sensorDefs.h:42
These are used to scale the SD before writing it to the HDF4 file The default is and which means the product is not scaled at all Since the product is usually stored as a float inside of this is a way to write the float out as a integer l2prod min
void initProductInfo(productInfo_t *info)
void getFirstProductInfo(productInfo_t *info)
#define PRODUCT_DEFAULT_validMax
Definition: productInfo.h:34
#define PRODUCT_DEFAULT_addOffset
Definition: productInfo.h:39
#define PRODUCT_DEFAULT_paramWaveMin
Definition: productInfo.h:16
void * allocateMemory(size_t numBytes, const char *name)
Definition: allocateMemory.c:7
void printProductInfo(const char *productFullName, const productInfo_t *info)
#define OSMI
Definition: sensorDefs.h:16
#define NULL
Definition: decode_rs.h:63
#define PRODUCT_DEFAULT_suffix
Definition: productInfo.h:22
#define OLIL9
Definition: sensorDefs.h:45
#define PRODUCT_DEFAULT_prod_ix
Definition: productInfo.h:26
#define VIIRSN
Definition: sensorDefs.h:23
void trimBlanks(char *str)
Definition: trimBlanks.c:10
#define L5TM
Definition: sensorDefs.h:35
#define PRODUCT_DEFAULT_algorithmName
Definition: productInfo.h:23
int isValidInt(const char *str)
Definition: isValidInt.c:9
#define MERIS
Definition: sensorDefs.h:22
#define PRODUCT_DEFAULT_category
Definition: productInfo.h:19
#define PRODUCT_DEFAULT_comment
Definition: productInfo.h:41
#define MODIST
Definition: sensorDefs.h:18
#define PRODUCT_DEFAULT_scaleFactor
Definition: productInfo.h:38
#define PRODUCT_DEFAULT_description
Definition: productInfo.h:12
#define OCIA
Definition: sensorDefs.h:29
void bzero()
void clearProductInfo(productInfo_t *info)
Definition: productInfo.cpp:42
#define OLIL8
Definition: sensorDefs.h:27
#define PRODUCT_DEFAULT_fillValue
Definition: productInfo.h:28
#define PRODUCT_DEFAULT_paramDesignator
Definition: productInfo.h:15
void readRange(productInfo_t *productInfo, xml_node productNode, int paramVal)
void readSingleRange(productInfo_t *productInfo, xml_node rangeNode)
#define XML_STRING_SIZE
Definition: productInfo.cpp:10
#define PRODUCT_DEFAULT_fillValue_byte
Definition: productInfo.h:29
int findNextAlgorithmHeader()
#define PRODUCT_DEFAULT_reference
Definition: productInfo.h:40
productInfo_t * allocateProductInfo()
char * strdup(const char *)
#define PRODUCT_DEFAULT_palette
Definition: productInfo.h:14
#define PRODUCT_DEFAULT_paramWaveMax
Definition: productInfo.h:17
#define PRODUCT_DEFAULT_displayMin
Definition: productInfo.h:36
#define PRODUCT_DEFAULT_units
Definition: productInfo.h:13
#define HAWKEYE
Definition: sensorDefs.h:39
#define PRODUCT_DEFAULT_displayMax
Definition: productInfo.h:37
#define PRODUCT_DEFAULT_titleFormat
Definition: productInfo.h:42
void readAlgorithm(int paramVal)
#define PRODUCT_DEFAULT_prefix
Definition: productInfo.h:21
#define PRODUCT_DEFAULT_rank
Definition: productInfo.h:27
#define PRISM
Definition: sensorDefs.h:31
int want_verbose
#define PRODUCT_DEFAULT_dataType
Definition: productInfo.h:20
#define PRODUCT_DEFAULT_fillValue_uint
Definition: productInfo.h:32
void initXmlFile()
#define AVIRIS
Definition: sensorDefs.h:30
#define PRODUCT_DEFAULT_fillValue_ubyte
Definition: productInfo.h:30
void readAlgorithmHeader()
void readProductHeader()
#define MOS
Definition: sensorDefs.h:13
#define MISR
Definition: sensorDefs.h:40
int findProductInfo(const char *productName, int sensorId, productInfo_t *info)
#define L7ETMP
Definition: sensorDefs.h:36
#define OCTS
Definition: sensorDefs.h:14
char * getProductNameFull(productInfo_t *info)
#define OCM1
Definition: sensorDefs.h:20
void checkProductNode()
#define PRODUCT_DEFAULT_displayScale
Definition: productInfo.h:35
void copyProductInfo(productInfo_t *dest, const productInfo_t *src)
#define PRODUCT_DEFAULT_validMin
Definition: productInfo.h:33
#define CZCS
Definition: sensorDefs.h:17
int32_t rdsensorinfo(int32_t, int32_t, const char *, void **)
Definition: rdsensorinfo.c:69
char * trimBlanksDup(const char *str)
Definition: trimBlanks.c:58
void findFirstAlgorithmHeader()
#define OLCIS3B
Definition: sensorDefs.h:41
void readProduct(int paramVal)
#define HICO
Definition: sensorDefs.h:25
#define OCRVC
Definition: sensorDefs.h:24
#define SEAWIFS
Definition: sensorDefs.h:12
int i
Definition: decode_rs.h:71
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
#define MODISA
Definition: sensorDefs.h:19
#define PRODUCT_DEFAULT_productName
Definition: productInfo.h:24
#define VIIRSJ1
Definition: sensorDefs.h:37
#define PRODUCT_DEFAULT_cat_ix
Definition: productInfo.h:25
void copyProductInfoHeader(productInfo_t *dest, const productInfo_t *src)
#define PRODUCT_DEFAULT_fillValue_ushort
Definition: productInfo.h:31
#define OCM2
Definition: sensorDefs.h:21
int getNextProductInfo(productInfo_t *info)
int compareAlgorithmHeader(const char *productFullName, int sensorId, int *paramVal)
l2prod max
#define GOCI
Definition: sensorDefs.h:26