NASA Logo
Ocean Color Science Software

ocssw V2022
FileReader.hpp
Go to the documentation of this file.
1 
2 #ifndef FOCS_FILEREADER
3 #define FOCS_FILEREADER
4 
5 #include <array>
6 #include <cstdio>
7 #include <string>
8 #include <unordered_map>
9 #include <filesystem>
10 #include <boost/property_tree/ptree.hpp>
11 #include <boost/property_tree/xml_parser.hpp>
12 #include <boost/property_tree/json_parser.hpp>
13 #include "optional"
14 #include "DataProvider.hpp"
15 #include "DataRecord.hpp"
16 #include <rapidjson/document.h>
17 #include <rapidjson/istreamwrapper.h>
18 #include <rapidjson/writer.h>
19 #include <rapidjson/stringbuffer.h>
20 #include <rapidjson/ostreamwrapper.h>
21 #include "rapidjson/error/en.h"
22 #include <netcdf>
23 #include "productInfo.h"
24 #include "sensorInfo.h"
25 #include <stack>
26 #include <l1.h>
27 namespace focs {
28 namespace rj = rapidjson;
29 namespace fs = std::filesystem;
30 extern const std::array<int, 4> NETCDF1_MAGIC_NUMBER;
31 extern const std::array<int, 4> NETCDF2_MAGIC_NUMBER;
32 extern const std::array<int, 4> HDF4_MAGIC_NUMBER;
33 extern const std::array<int, 8> HDF5_MAGIC_NUMBER;
34 
36  std::unordered_map<std::string, std::unordered_map<std::string, ANY>> attributes;
37  std::set<std::string> product_names;
38 };
39 
40 template <typename, typename = void>
41 constexpr bool is_prod_gen_attr{};
42 
43 template <typename T>
44 constexpr bool
45  is_prod_gen_attr<T, std::void_t<decltype(std::declval<T>().getAttrGen())>> =
46  true;
47 
48 class ConfigReader {
49  protected:
50  std::unique_ptr<rj::Document> document;
51  std::optional<fs::path> path;
52  [[maybe_unused]] std::unique_ptr<productInfo_t> product_xml; // from ocssw oel_util, not implemented yet
54 
55  public:
56  ConfigReader() = default;
58  ConfigReader(const fs::path& path,const std::string& type); // generic json or xml file
59  bool exist() const;
60  const rj::Document* getDoc() const;
61  const ProdAttrGeneric & getAttrGen() const;
62 };
63 
64 // Everything that writes to hints.attributes_ is performing a copy (of what they're adding). Switch to smart pointers?
66  public:
67  FileReaderHints() = default;
68  explicit FileReaderHints(const std::string& path);
69 
70  bool magic_number(const std::string& bytes) const noexcept;
71  template<std::size_t N> bool magic_number(const std::array<int, N>& bytes) const noexcept;
72 
73  const std::array<int, 8>& first_bytes() const noexcept {return first_bytes_;}
74  void first_bytes(const std::array<int, 8>& bytes){first_bytes_ = bytes;}
75 
76  uintmax_t size() const noexcept {return size_;}
77  void size(uintmax_t size){size_ = size;}
78 
79  const std::string& filename() const noexcept {return filename_;}
80  void filename(const std::string& filename){filename_ = filename;}
81 
82  const std::string& format() const noexcept {return format_;}
83  void format(const std::string& format){format_ = format;}
84 
85  auto& attributes(){return attributes_;}
86 
87  bool is_hdf4() const noexcept;
88  bool is_hdf5() const noexcept;
89  bool is_netcdf() const noexcept;
90  std::set<Attribute> parse_hdf4_metadata(const std::string &);
91  // hdf4 legacy keywords
92  const static std::string core_metadata;
93  const static std::string struct_metadata;
94  const static std::string archive_metadata;
95  private:
96  std::string filename_{};
97  std::array<int, 8> first_bytes_{{0, 0, 0, 0, 0, 0, 0, 0}};
98  uintmax_t size_{0};
99  std::string format_{"unknown"};
100  std::set<focs::Attribute> attributes_{};
101 
102 
103 };
104 class FileReader : public DataProvider {
105  public:
108 
109  enum validity {
111  };
112  virtual ~FileReader() override {}
113 
114  // virtual const std::vector<Product>& provides() const override;
115  virtual std::vector<std::shared_ptr<Product>>& needs() override; // returns empty
116 
117  // TODO: undefine these empty ones, it's not compiling without them for some reason
118  virtual validity is_valid_file(const std::string& file, FileReaderHints& hints){(void)file; (void)hints; return invalid;}
120  FileReaderHints hints{file};
121  return is_valid_file(file, hints);
122  }
123 
124  virtual std::unique_ptr<FileReader> initialize_reader(DataProviderConfiguration& configuration, const std::filesystem::path& path) = 0;
125  virtual std::set<focs::Attribute> get_file_attributes() = 0;
126  virtual TileParameters read_next_tile(DataProviderConfiguration& configuration, DataRecord& record){(void)configuration; (void)record; return {0,0}; } // true on finished? For now.
127 };
128 
129 
131 {
132 protected:
133  std::unique_ptr<ConfigReader> _config;
134  std::unordered_map<std::string,ConfigReader> configs;
135  std::unordered_map<std::string,std::set<focs::Attribute>> _attributes;
136  productInfo_t *info = nullptr;
137 
138  public:
139  AttributeReader(const std::filesystem::path& path, const std::string& mode = "default",
140  const std::unordered_set<std::string>& products_requested = {});
141  AttributeReader(netCDF::NcFile& nc, const std::string& key);
143  AttributeReader();
144  ~AttributeReader() = default;
145  void addAttributes(const std::filesystem::path& path, const std::string& mode = "default",
146  const std::unordered_set<std::string>& products_requested = {});
147  void addAttributes(FileReaderHints& hints, const std::string& key);
148  void addAttributes(netCDF::NcFile& nc, const std::string& key);
149  template <typename T, std::enable_if_t<is_prod_gen_attr<T>, bool> = true,
150  typename pointer_type = decltype((std::declval<T>().getAttrGen())),
151  std::enable_if_t<std::is_same_v<pointer_type, const ProdAttrGeneric&>, bool> = true>
152  void addAttributes(T&& storage_object, const std::string& mode,
153  const std::unordered_set<std::string>& products_requested = {}) {
154  const ProdAttrGeneric& prods = storage_object.getAttrGen();
155  if (mode == "add") {
156  for (const auto& prod_name : prods.product_names) {
157  if (!products_requested.empty() && products_requested.count(prod_name) == 0)
158  continue;
159  if (_attributes.count(prod_name) > 0) {
160  std::unordered_set<std::string> existing_attrs;
161  for (const auto& attr : _attributes.at(prod_name)) {
162  existing_attrs.insert(attr.name());
163  }
164  // insert ANY attributes
165  for (const auto& attr : prods.attributes.at(prod_name)) {
166  std::string name = attr.first;
167  if (existing_attrs.count(name) == 0) {
168  _attributes.at(prod_name).insert(focs::Attribute{name, attr.second, 1});
169  }
170  }
171  } else {
172  for (const auto& attr : prods.attributes.at(prod_name)) {
173  _attributes[prod_name].insert(focs::Attribute{attr.first, attr.second, 1});
174  }
175  }
176  }
177  } else if (mode == "override") {
178  // needs to be implemented
179  }
180  }
181  template <typename T, std::enable_if_t<is_iterable<T>, bool> = true,
182  typename pointer_type = decltype(*(std::declval<T>().begin())),
183  std::enable_if_t<std::is_same_v<pointer_type, const Attribute&>, bool> = true> //
184  void addAttributes(const T& custom_attrs, const std::string& type, const std::string& mode = "add") {
185  if (mode == "add") {
186  std::unordered_set<std::string> existing_attrs;
187  for (const auto& attr : _attributes.at(type)) {
188  existing_attrs.insert(attr.name());
189  }
190  for (const auto& attr : custom_attrs) {
191  std::string name = attr.name();
192  if (existing_attrs.count(name) == 0) {
193  _attributes.at(type).insert(attr);
194  }
195  }
196 
197  } else if (mode == "override") {
198  std::unordered_set<std::string> override_names;
199  for (const auto& attr : custom_attrs) {
200  override_names.insert(attr.name());
201  }
202  std::stack<std::set<focs::Attribute>::iterator> its_to_remove;
203  for (auto it = _attributes.at(type).begin(); it != _attributes.at(type).end(); it++) {
204  if (override_names.count(it->name()) > 0) {
205  its_to_remove.push(it);
206  }
207  }
208  while (!its_to_remove.empty()) {
209  auto it = its_to_remove.top();
210  _attributes.at(type).erase(it);
211  its_to_remove.pop();
212  }
213  _attributes.at(type).insert(custom_attrs.begin(), custom_attrs.end());
214  }
215  }
216  const std::unordered_map<std::string,std::set<focs::Attribute>> & getAttrs() const;
217 };
218 
219 } // namespace focs
220 
221 #endif // FOCS_FILEREADER
222 
const static std::string struct_metadata
Definition: FileReader.hpp:93
virtual std::vector< std::shared_ptr< Product > > & needs() override
validity is_valid_file(const std::string &file)
Definition: FileReader.hpp:119
void first_bytes(const std::array< int, 8 > &bytes)
Definition: FileReader.hpp:74
std::optional< fs::path > path
Definition: FileReader.hpp:51
FileReader(const std::string &name, const std::string &description)
Definition: FileReader.hpp:106
bool exist() const
void addAttributes(const T &custom_attrs, const std::string &type, const std::string &mode="add")
Definition: FileReader.hpp:184
const std::array< int, 4 > NETCDF1_MAGIC_NUMBER
bool is_hdf4() const noexcept
const rj::Document * getDoc() const
const std::string & name() const
void addAttributes(const std::filesystem::path &path, const std::string &mode="default", const std::unordered_set< std::string > &products_requested={})
FileReader(const std::string &name)
Definition: FileReader.hpp:107
const std::array< int, 4 > HDF4_MAGIC_NUMBER
README for MOD_PR02AQUA(AQUA) Version to set to For disabling creating and output data sets when in night mode
Definition: README.txt:96
constexpr bool is_prod_gen_attr
Definition: FileReader.hpp:41
bool is_hdf5() const noexcept
@ string
const std::string & filename() const noexcept
Definition: FileReader.hpp:79
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
const std::string & format() const noexcept
Definition: FileReader.hpp:82
void size(uintmax_t size)
Definition: FileReader.hpp:77
const static std::string core_metadata
Definition: FileReader.hpp:92
std::unique_ptr< ConfigReader > _config
Definition: FileReader.hpp:133
virtual std::set< focs::Attribute > get_file_attributes()=0
const std::array< int, 8 > HDF5_MAGIC_NUMBER
virtual validity is_valid_file(const std::string &file, FileReaderHints &hints)
Definition: FileReader.hpp:118
string path
Definition: color_dtdb.py:221
virtual ~FileReader() override
Definition: FileReader.hpp:112
bool magic_number(const std::string &bytes) const noexcept
ConfigReader()=default
std::unique_ptr< productInfo_t > product_xml
Definition: FileReader.hpp:52
void format(const std::string &format)
Definition: FileReader.hpp:83
const ProdAttrGeneric & getAttrGen() const
productInfo_t * info
Definition: FileReader.hpp:136
virtual std::unique_ptr< FileReader > initialize_reader(DataProviderConfiguration &configuration, const std::filesystem::path &path)=0
std::unordered_map< std::string, std::unordered_map< std::string, ANY > > attributes
Definition: FileReader.hpp:36
void filename(const std::string &filename)
Definition: FileReader.hpp:80
std::set< std::string > product_names
Definition: FileReader.hpp:37
virtual TileParameters read_next_tile(DataProviderConfiguration &configuration, DataRecord &record)
Definition: FileReader.hpp:126
void addAttributes(T &&storage_object, const std::string &mode, const std::unordered_set< std::string > &products_requested={})
Definition: FileReader.hpp:152
std::unique_ptr< rj::Document > document
Definition: FileReader.hpp:50
std::unordered_map< std::string, ConfigReader > configs
Definition: FileReader.hpp:134
~AttributeReader()=default
std::set< Attribute > parse_hdf4_metadata(const std::string &)
bool is_netcdf() const noexcept
const std::array< int, 4 > NETCDF2_MAGIC_NUMBER
const std::string & description() const
std::unordered_map< std::string, std::set< focs::Attribute > > _attributes
Definition: FileReader.hpp:135
const static std::string archive_metadata
Definition: FileReader.hpp:94
float rj(float x, float y, float z, float p)
const std::unordered_map< std::string, std::set< focs::Attribute > > & getAttrs() const
ProdAttrGeneric attrs
Definition: FileReader.hpp:53
uintmax_t size() const noexcept
Definition: FileReader.hpp:76
const std::array< int, 8 > & first_bytes() const noexcept
Definition: FileReader.hpp:73