IODA Bundle
DataContainer.cpp
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2020 NOAA/NWS/NCEP/EMC
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  */
7 
8 
9 #include <map>
10 #include <string>
11 #include <ostream>
12 
13 #include "Eigen/Dense"
14 #include "eckit/exception/Exceptions.h"
15 
16 #include "DataContainer.h"
17 
18 
19 namespace Ingester
20 {
22  categoryMap_({})
23  {
24  makeDataSets();
25  }
26 
28  categoryMap_(categoryMap)
29  {
30  makeDataSets();
31  }
32 
33  void DataContainer::add(const std::string& fieldName,
34  const std::shared_ptr<DataObject> data,
35  const SubCategory& categoryId)
36  {
37  if (hasKey(fieldName, categoryId))
38  {
39  std::ostringstream errorStr;
40  errorStr << "ERROR: Field called " << fieldName << " already exists ";
41  errorStr << "for subcategory " << makeSubCategoryStr(categoryId) << std::endl;
42  throw eckit::BadParameter(errorStr.str());
43  }
44 
45  dataSets_.at(categoryId).insert({fieldName, data});
46  }
47 
48  std::shared_ptr<DataObject> DataContainer::get(const std::string& fieldName,
49  const SubCategory& categoryId) const
50  {
51  if (!hasKey(fieldName, categoryId))
52  {
53  std::ostringstream errStr;
54  errStr << "ERROR: Either field called " << fieldName;
55  errStr << " or category " << makeSubCategoryStr(categoryId);
56  errStr << " does not exist.";
57 
58  throw eckit::BadParameter(errStr.str());
59  }
60 
61  return dataSets_.at(categoryId).at(fieldName);
62  }
63 
64  bool DataContainer::hasKey(const std::string& fieldName,
65  const SubCategory& categoryId) const
66  {
67  bool hasKey = false;
68  if (dataSets_.find(categoryId) != dataSets_.end() &&
69  dataSets_.at(categoryId).find(fieldName) != dataSets_.at(categoryId).end())
70  {
71  hasKey = true;
72  }
73 
74  return hasKey;
75  }
76 
77  size_t DataContainer::size(const SubCategory &categoryId) const
78  {
79  if (dataSets_.find(categoryId) == dataSets_.end())
80  {
81  std::ostringstream errStr;
82  errStr << "ERROR: Category called " << makeSubCategoryStr(categoryId);
83  errStr << " does not exist.";
84 
85  throw eckit::BadParameter(errStr.str());
86  }
87 
88  return dataSets_.at(categoryId).begin()->second->nrows();
89  }
90 
91  std::vector<SubCategory> DataContainer::allSubCategories() const
92  {
93  std::vector<SubCategory> allCategories;
94 
95  for (const auto &dataSetPair : dataSets_)
96  {
97  allCategories.push_back(dataSetPair.first);
98  }
99 
100  return allCategories;
101  }
102 
104  {
105  std::function<void(std::vector<size_t>&, const std::vector<size_t>&, size_t)> incIdx;
106  incIdx = [&incIdx](std::vector<size_t>& indicies,
107  const std::vector<size_t>& lengths,
108  size_t idx)
109  {
110  if (indicies[idx] + 1 >= lengths[idx])
111  {
112  if (idx + 1 < indicies.size())
113  {
114  indicies[idx] = 0;
115  incIdx(indicies, lengths, idx + 1);
116  }
117  }
118  else
119  {
120  indicies[idx]++;
121  }
122  };
123 
124  size_t numCombos = 1;
125  std::vector<size_t> indicies;
126  std::vector<size_t> lengths;
127  for (const auto& category : categoryMap_)
128  {
129  indicies.push_back(0);
130  lengths.push_back(category.second.size());
131  numCombos = numCombos * category.second.size();
132  }
133 
134  if (!indicies.empty())
135  {
136  for (size_t idx = 0; idx < numCombos; idx++) {
137  size_t catIdx = 0;
138  std::vector<std::string> subsets;
139  for (const auto &category : categoryMap_) {
140  subsets.push_back(category.second[indicies[catIdx]]);
141  catIdx++;
142  }
143 
144  dataSets_.insert({subsets, DataSetMap()});
145  incIdx(indicies, lengths, 0);
146  }
147  }
148  else
149  {
150  dataSets_.insert({{}, DataSetMap()});
151  }
152  }
153 
154  std::string DataContainer::makeSubCategoryStr(const SubCategory &categoryId)
155  {
156  std::ostringstream catStr;
157 
158  if (!categoryId.empty())
159  {
160  for (const auto &subCategory : categoryId)
161  {
162  catStr << subCategory << "_";
163  }
164  }
165  else
166  {
167  catStr << "__MAIN__";
168  }
169 
170  return catStr.str();
171  }
172 } // namespace Ingester
DataSets dataSets_
Map of data for each possible subcategory.
Definition: DataContainer.h:86
std::shared_ptr< DataObject > get(const std::string &fieldName, const SubCategory &categoryId={}) const
Get a DataObject from the collection.
bool hasKey(const std::string &fieldName, const SubCategory &categoryId={}) const
Check if DataObject with name is available.
void makeDataSets()
Uses category map to generate listings of all possible subcategories.
size_t size(const SubCategory &categoryId={}) const
Get the number of rows of the specified sub category.
DataContainer()
Simple constructor.
void add(const std::string &fieldName, std::shared_ptr< DataObject > data, const SubCategory &categoryId={})
Add a DataObject to the collection.
std::vector< SubCategory > allSubCategories() const
Get the number of rows of the specified sub category.
static std::string makeSubCategoryStr(const SubCategory &categoryId)
Convenience function used to make a string out of a subcategory listing.
const CategoryMap categoryMap_
Category map given (see constructor).
Definition: DataContainer.h:83
std::map< std::string, std::shared_ptr< DataObject > > DataSetMap
Map string paths (ex: variable/radiance) to DataObject.
Definition: DataContainer.h:30
std::map< std::string, SubCategory > CategoryMap
Map of data set id's to vector of possible value strings.
Definition: DataContainer.h:27
std::vector< std::string > SubCategory
List of possible category strings (for splitting data)
Definition: DataContainer.h:24