NASA Logo
Ocean Color Science Software

ocssw V2022
sst_adt.cpp
Go to the documentation of this file.
1 #include "sst_adt.hpp"
2 
3 namespace adt {
5  const std::unordered_set<std::string> non_test_keywords = {"true", "false", "thresholds", "addTreesum", "setFlags",
6  "decision_tree"};
10  std::map<std::string, Traverse> traversal_functions = {
11  {"single_max",
12  [](float *treesum, int16_t *flags, const TestParameters &parameters, const VarsAtPixel &vars,
13  Treenode *node) {
14  if (vars.vars.at(parameters.test_name) < parameters.max_var &&
15  vars.masks.at(parameters.test_name)) {
16  node->children.at(1).second = false;
17  } else {
18  node->children.at(0).second = false;
19  }
20  }},
21  {"single_min",
22  [](float *treesum, int16_t *flags, const TestParameters &parameters, const VarsAtPixel &vars,
23  Treenode *node) {
24  if (vars.vars.at(parameters.test_name) >= parameters.min_var) {
25  node->children.at(1).second = false;
26  } else {
27  node->children.at(0).second = false;
28  }
29  }},
30  {"double_condition",
31  [](float *treesum, int16_t *flags, const TestParameters &parameters, const VarsAtPixel &vars,
32  Treenode *node) {
33  if (vars.vars.at(parameters.test_name) >= parameters.min_var &&
34  vars.vars.at(parameters.test_name) <= parameters.max_var) {
35  node->children.at(1).second = false;
36  } else {
37  node->children.at(0).second = false;
38  }
39  }},
40  {"addTreesum",
41  [](float *treesum, int16_t *flags, const TestParameters &parameters, const VarsAtPixel &vars,
42  Treenode *node) {
43  *treesum += parameters.treesum_increment;
44  }},
45  {"setFlags",
46  [](float *treesum, int16_t *flags, const TestParameters &parameters, const VarsAtPixel &vars,
47  Treenode *node) {
48  *flags |= parameters.flag;
49  }},
50  {"default",
51  [](float *treesum, int16_t *flags, const TestParameters &parameters, const VarsAtPixel &vars,
52  Treenode *node) {
53  }},
54  };
55 
56  auto set_node_parameters = [](Treenode *node, const std::string &test_name,
57  const std::map<std::string, boost::variant<int16_t, float, bool>> &ranges) {
58  auto params = &node->set_parameters;
59  if (ranges.count("threshold_max") > 0)
60  params->max_var = boost::get<float>(ranges.at("threshold_max"));
61  if (ranges.count("threshold_min") > 0)
62  params->min_var = boost::get<float>(ranges.at("threshold_min"));
63  if (ranges.count("addTreesum"))
64  params->treesum_increment = boost::get<float>(ranges.at("addTreesum"));
65  if (ranges.count("setFlags"))
66  params->flag = boost::get<int16_t>(ranges.at("setFlags"));
67  if (ranges.count("incl"))
68  params->not_use_mask = !boost::get<bool>(ranges.at("incl"));
69  params->test_name = test_name; //
70  };
71 
73  if (root == nullptr)
74  return;
75  for (auto &child: root->children) {
76  deallocate_tree(child.first);
77  }
78  delete root;
79  };
80 
81  void tree_traversal(float *inp_treesum, int16_t *inp_flags_sst, const VarsAtPixel &vars, Treenode *node) {
82  if (node == nullptr)
83  return;
84  node->traverse(inp_treesum, inp_flags_sst, vars);
85  for (auto &child: node->children) {
86  if (child.second) {
87  tree_traversal(inp_treesum, inp_flags_sst, vars, child.first);
88  }
89  }
90  }
91 
93  if (node == nullptr)
94  return;
95  for (auto &child: node->children) {
96  child.second = true;
97  tree_traversal(child.first);
98  }
99  }
100 
101  void readTreeTest(const rapidjson::Value &member) {
102  for (rapidjson::Value::ConstMemberIterator iter = member.MemberBegin(); iter != member.MemberEnd(); ++iter) {
103  if (iter->value.IsObject())
104  readTreeTest(iter->value);
105  if (iter->value.IsArray()) {
106  const rapidjson::Value &array = iter->value;
107  for (const rapidjson::Value &el: array.GetArray()) {
108  readTreeTest(el);
109  }
110  }
111  }
112  }
113 
114  void build_sub_tree(const rapidjson::Value &member, Treenode *node, std::set<std::string> &tests_name) {
115 
116  for (rapidjson::Value::ConstMemberIterator iter = member.MemberBegin(); iter != member.MemberEnd(); ++iter) {
117  const std::string key = iter->name.GetString();
118  {
119  assert(iter->value.IsObject() == 1); //
120  }
121  const rapidjson::Value &nodes = iter->value;
122  // disecting what is that
123  if (non_test_keywords.count(key) == 0) // it's a test
124  {
125  std::map<std::string, boost::variant<int16_t, float, bool>> thresholds;
126  tests_name.insert(key);
127  // here it should read the threshold value
128  if (nodes.FindMember("thresholds") != nodes.MemberEnd()) {
129  if (!nodes["thresholds"].IsArray()) {
131  "Thresholds must be an array. Check the test ");
132  }
133  const rapidjson::Value &arr = nodes["thresholds"];
134  for (const auto &thresh_iter: arr.GetArray()) {
135  for (const auto &field: thresh_iter.GetObject()) {
136  if (field.value.IsFloat())
137  thresholds[field.name.GetString()] = field.value.GetFloat();
138  if (field.value.IsBool())
139  thresholds[field.name.GetString()] = field.value.GetBool();
140  if (field.value.IsInt())
141  thresholds[field.name.GetString()] = (int16_t) field.value.GetInt();
142  }
143  }
144  set_node_parameters(node, key, thresholds);
145  } // defining the parameters
146 
147  if (thresholds.count("threshold_min") > 0 && thresholds.count("threshold_max") > 0)
148  node->traverse_ptr = traversal_functions.at("double_condition");
149  else if (thresholds.count("threshold_min") > 0)
150  node->traverse_ptr = traversal_functions.at("single_min");
151  else if (thresholds.count("threshold_max") > 0)
152  node->traverse_ptr = traversal_functions.at("single_max");
153  else
154  node->traverse_ptr = traversal_functions.at("default");
155  } else // this is a branch, now all the branches are binary, "true" or "false"
156  {
157  if (key != "true" && key != "false") {
158  print_error_message_for_adt(config_adt_path, key, "Undefined keyword for a branch ");
159  }
160  assert(((key == "true") || (key == "false")) == 1);
161  // here it should read the threshold value
162  std::map<std::string, boost::variant<int16_t, float, bool>> thresholds;
163  if (nodes.FindMember("addTreesum") != nodes.MemberEnd()) {
164  node->traverse_ptr = traversal_functions.at("addTreesum");
165  assert(nodes["addTreesum"].IsFloat());
166  thresholds["addTreesum"] = nodes["addTreesum"].GetFloat();
167  set_node_parameters(node, "addTreesum_" + key, thresholds);
168  // looking for addTreesum or set flags ( decision has been made)}
169  } else if (nodes.FindMember("setFlags") != nodes.MemberEnd()) {
170  node->traverse_ptr = traversal_functions.at("setFlags");
171  assert(nodes["setFlags"].IsInt());
172  thresholds["setFlags"] = (int16_t) nodes["setFlags"].GetInt();
173  set_node_parameters(node, "setFlags_" + key, thresholds);
174  // looking for addTreesum or set flags ( decision has been made)}
175  } else {
176  node->traverse_ptr = traversal_functions.at("default");
177  set_node_parameters(node, "branch_node_" + key, thresholds);
178  }
179  }
180 
181  if (nodes.FindMember("children") != nodes.MemberEnd()) {
182  const rapidjson::Value &children = nodes["children"];
183  if (children.IsArray() != 1) {
185  "Children must be an array. Check the test ");
186  };
187  size_t number_of_children = children.Size();
188  for (size_t _ = 0; _ < number_of_children; _++)
189  node->children.push_back(std::make_pair(new Treenode(), true));
190 
191  for (size_t i = 0; i < number_of_children; i++) {
192  build_sub_tree(children[i], node->children[i].first, tests_name);
193  }
194  }
195  }
196  }
197 
198  void build_tree(const std::string &config_path, Treenode *decision_tree, std::set<std::string> &tests_name) {
199  config_adt_path = config_path;
200  std::ifstream ifs{config_path};
201  if (!ifs.is_open()) {
202  std::cerr << "Could not open the ADT json file for reading : " << config_path << std::endl;
203  exit(EXIT_FAILURE);
204  return;
205  } else {
206  std::cout << "Reading the ADT parameters from the follwing file : " << config_path << "\n";
207  }
208  rapidjson::IStreamWrapper isw{ifs};
209  rapidjson::Document doc{};
210  doc.ParseStream(isw);
211  const rapidjson::Value &tree_builder = doc["decision_tree"];
212  readTreeTest(tree_builder);
213  {
214  std::cout << "The json file for the ADT has been read and processed succesfully"
215  << "\n";
216  }
217  if (tree_builder.FindMember("children") != tree_builder.MemberEnd()) {
218  const rapidjson::Value &children = tree_builder["children"];
219  if (children.IsArray() != 1) {
221  "Children must be an array. Check the test ");
222  };
223  size_t number_of_children = children.Size();
224  decision_tree->set_parameters.test_name = "decision_tree";
225  decision_tree->traverse_ptr = [](float *, int16_t *, const TestParameters &, const VarsAtPixel &,
226  Treenode *) {};
227 
228  // check for additional traversal functions
229  if (tree_builder.FindMember("addTreesum") != tree_builder.MemberEnd()) {
230  std::map<std::string, boost::variant<int16_t, float, bool>> thresholds;
231  decision_tree->traverse_ptr = traversal_functions.at("addTreesum");
232  assert(tree_builder["addTreesum"].IsFloat());
233  thresholds["addTreesum"] = tree_builder["addTreesum"].GetFloat();
234  set_node_parameters(decision_tree, "decision_tree", thresholds);
235  // looking for addTreesum or set flags ( decision has been made)}
236  }
237  for (size_t _ = 0; _ < number_of_children; _++)
238  decision_tree->children.push_back(std::make_pair(new Treenode(), true));
239  for (size_t i = 0; i < number_of_children; i++) {
240  build_sub_tree(children[i], decision_tree->children[i].first, tests_name);
241  }
242  } else {
243  std::cerr << "Error : Empty decision tree. Exiting " << std::endl;
244  exit(EXIT_FAILURE);
245  }
246  }
247 
248  void
249  print_error_message_for_adt(const std::string &file_path, const std::string &key_word, const std::string &message) {
250  std::ifstream file(file_path);
251  if (!file.is_open()) {
252  std::cerr << "Problem opening the ADT config " << file_path << std::endl;
253  exit(EXIT_FAILURE);
254  }
256  size_t line_num = 0;
257  while (std::getline(file, str)) {
258  if (boost::algorithm::contains(str, key_word))
259  std::cerr << message << " : " << key_word << " in line " << line_num << " in file " << file_path
260  << std::endl;
261  line_num++;
262  }
263  file.close();
264  exit(EXIT_FAILURE);
265  }
266 
267 
268 }
std::string config_adt_path
Definition: sst_adt.cpp:4
data_t root[NROOTS]
Definition: decode_rs.h:78
void build_sub_tree(const rapidjson::Value &member, Treenode *node, std::set< std::string > &tests_name)
Recursively building the tree *.
Definition: sst_adt.cpp:114
namespace to contains the ADT data structures and functions *
Definition: sst_adt.cpp:3
const std::unordered_set< std::string > non_test_keywords
Definition: sst_adt.cpp:5
void(* traverse_ptr)(float *, int16_t *, const TestParameters &, const VarsAtPixel &, Treenode *)
Definition: sst_adt.hpp:60
@ string
std::string test_name
Definition: sst_adt.hpp:37
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 file
Definition: HISTORY.txt:413
void tree_traversal(float *inp_treesum, int16_t *inp_flags_sst, const VarsAtPixel &vars, Treenode *node)
Definition: sst_adt.cpp:81
auto set_node_parameters
Definition: sst_adt.cpp:56
void print_error_message_for_adt(const std::string &file_path, const std::string &key_word, const std::string &message)
Prints error message for unrecognized keywords in the ADT config file.
Definition: sst_adt.cpp:249
void build_tree(const std::string &config_path, Treenode *decision_tree, std::set< std::string > &tests_name)
Building the from a json file *.
Definition: sst_adt.cpp:198
instead the metadata field ProcessingEnvinronment is filled in from the output of a call to the POSIX compliant function uname from within the L1B code A small bug in L1B_Tables an incorrect comparison of RVS coefficients for TEBs to RVS coefficients for RSBs was being made This was replaced with a comparison between TEB coefficients This error never resulted in an incorrect RVS correction but did lead to recalculating the coefficients for each detector in a thermal band even if the coefficients were the same for all detectors To reduce to overall size of the reflective LUT HDF fill values were eliminated from all LUTs previously dimensioned where and where NUM_TIMES is the number of time dependent table pieces In Preprocess a small error where the trailing dropped scan counter was incremented when the leading dropped scan counter should have been was fixed This counter is internal only and is not yet used for any chiefly to casting of were added to make it LINUX compatible Output of code run on LINUX machines displays differences of at most scaled sector incalculable values of the Emissive calibration factor and incalculable values of SV or BB averages was moved outside the loop over frames in Emissive_Cal c since none of these quantities are frame dependent Initialization of b1 and XMS values in Preprocess c routine Process_OBCENG_Emiss was moved inside the detector loops The code was altered so that if up to five scans are dropped between the leading middle or middle trailing the leading or trailing granule will still be used in emissive calibration to form a cross granule average QA bits and are set for a gap between the leading middle and middle trailing granules respectively This may in rare instances lead to a change in emissive calibration coefficients for scans at the beginning or end of a granule A small bug in the Band correction algorithm was corrected an uncertainty value was being checked against an upper bound whereas the proper quantity to be checked was the corresponding which is the product of the Band radiance times the ratio of the Band to Band scaling factors times the LUT correction value for that detector In addition a new LUT which allows for a frame offset with regard to the Band radiance was added A LUT which switches the correction off or on was also added Changes which do not affect scientific output of the the pixel is flagged with the newly created flag and the number of pixels for which this occurs is counted in the QA_common table The array of b1s in Preprocess c was being initialized to outside the loop over which meant that if b1 could not be the value of b1 from the previous band for that scan detector combination was used The initialization was moved inside the band loop Minor code changes were made to eliminate compiler warnings when the code is compiled in bit mode Temperature equations were upgraded to be MODIS AQUA or MODIS TERRA specific and temperature conversion coefficients for AQUA were MOD_PR02 will not cease execution if the value of this parameter is not but will print a message
Definition: HISTORY.txt:644
void deallocate_tree(Treenode *root)
Definition: sst_adt.cpp:72
std::map< std::string, Traverse > traversal_functions
possible traversal functions.
Definition: sst_adt.cpp:10
The decision tree.
Definition: sst_adt.hpp:57
flags
Definition: DDAlgorithm.h:22
void readTreeTest(const rapidjson::Value &member)
Definition: sst_adt.cpp:101
TestParameters set_parameters
Definition: sst_adt.hpp:62
argpar_child children[]
Definition: argpar-help.c:49
int i
Definition: decode_rs.h:71
std::vector< std::pair< Treenode *, bool > > children
Definition: sst_adt.hpp:58
Definition: aerosol.c:136
el
Definition: decode_rs.h:168
#define str(s)