Loading [MathJax]/extensions/tex2jax.js
IODA
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ODC.cpp
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2020-2021 UCAR
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 /*! \addtogroup ioda_cxx_engines_pub_ODC
8  *
9  * @{
10  * \file ODC.cpp
11  * \brief ODB / ODC engine bindings
12  */
13 #include <set>
14 #include <string>
15 #include <vector>
16 #include <algorithm>
17 
18 #include "DataFromSQL.h"
19 
20 #include "eckit/config/LocalConfiguration.h"
21 #include "eckit/config/YAMLConfiguration.h"
22 #include "eckit/filesystem/PathName.h"
23 
24 #include "ioda/Engines/ODC.h"
25 #include "ioda/Exception.h"
26 #include "ioda/Group.h"
27 #include "ioda/config.h"
28 
29 #if odc_FOUND
30 #include "odc/api/odc.h"
31 #include "./DataFromSQL.h"
33 #endif
34 
35 namespace ioda {
36 namespace Engines {
37 namespace ODC {
38 
39 /// @brief Standard message when the ODC API is unavailable.
40 const char odcMissingMessage[] {
41  "The ODB / ODC engine is disabled. odc was "
42  "not found at compile time."};
43 
44 /// @brief Function initializes the ODC API, just once.
45 void initODC() { static bool inited = false;
46  if (!inited) {
47 #if odc_FOUND
48  odc_initialise_api();
49 #else
51 #endif
52  inited = true;
53  }
54 }
55 
56 ObsGroup openFile(const ODC_Parameters& odcparams,
57  Group storageGroup)
58 {
59  // Check first that the ODB engine is enabled. If the engine
60  // is not enabled, then throw an exception.
61 #if odc_FOUND
62  initODC();
63 
64  using std::set;
65  using std::string;
66  using std::vector;
67 
68  // Parse the query file to extract the list of columns and varnos
69  eckit::YAMLConfiguration conf(eckit::PathName(odcparams.queryFile));
70  OdbQueryParameters queryParameters;
71  queryParameters.validateAndDeserialize(conf);
72 
73  vector<std::string> columns = {"lat", "lon", "date", "time", "seqno", "varno", "ops_obsgroup", "vertco_type", "initial_obsvalue"};
74  for (const OdbVariableParameters &varParameters : queryParameters.variables.value()) {
75  columns.push_back(varParameters.name);
76  }
77  std::sort(columns.begin(), columns.end());
78  auto last = std::unique(columns.begin(), columns.end());
79  columns.erase(last, columns.end());
80 
81  // TODO(someone): Handle the case of the 'varno' option being set to ALL.
82  const vector<int> &varnos = queryParameters.where.value().varno.value().as<std::vector<int>>();
83 
84  DataFromSQL sql_data;
85  sql_data.select(columns, odcparams.filename, varnos, queryParameters.where.value().query);
86 
87  const int num_rows = sql_data.numberOfMetadataRows();
88  if (num_rows <= 0) return storageGroup;
89 
90  NewDimensionScales_t vertcos = sql_data.getVertcos();
91 
92  std::vector<std::string> ignores;
93  ignores.push_back("nlocs");
94  ignores.push_back("MetaData/datetime");
95  ignores.push_back("MetaData/receiptdatetime");
96  ignores.push_back("nchans");
97 
98  auto og = ObsGroup::generate(
99  storageGroup,
100  vertcos,
103 
105  // Writing in the data
106  ioda::Variable v;
107 
108  // Datetime variables are handled specially -- date and time are stored in separate ODB columns,
109  // but ioda represents them in a single variable.
110  v = og.vars.createWithScales<std::string>(
111  "MetaData/datetime", {og.vars["nlocs"]}, params);
112  v.write(sql_data.getDates("date", "time"));
113  v = og.vars.createWithScales<std::string>(
114  "MetaData/receiptdatetime", {og.vars["nlocs"]}, params);
115  v.write(sql_data.getDates("receipt_date", "receipt_time"));
116 
117  auto groups = og.listObjects();
118 
119  auto sqlColumns = sql_data.getColumns();
120  for (int i = 0; i < sqlColumns.size(); i++) {
121  const set<string> ignoredNames{"initial_obsvalue",
122  "initial_vertco_reference",
123  "date",
124  "time",
125  "receipt_date",
126  "receipt_time",
127  "seqno",
128  "varno",
129  "vertco_type",
130  "entryno",
131  "ops_obsgroup"};
132 
133  if (ignoredNames.count(sqlColumns.at(i))) continue;
134  sql_data.getIodaVariable(sqlColumns.at(i), og, params);
135  }
136 
137  groups = og.listObjects();
138  for (int i = 0; i < varnos.size(); i++) {
139  if (sql_data.getObsgroup() == obsgroup_amsr) {
140  if (varnos.at(i) == varno_rawbt) {
141  sql_data.getIodaObsvalue(varnos.at(i), og, params);
142  }
143  } else if (sql_data.getObsgroup() == obsgroup_mwsfy3) {
144  if (varnos.at(i) == varno_rawbt_mwts) {
145  sql_data.getIodaObsvalue(varnos.at(i), og, params);
146  }
147  } else {
148  sql_data.getIodaObsvalue(varnos.at(i), og, params);
149  }
150  }
151 
152  return og;
153 #else
155 #endif
156 }
157 
158 } // namespace ODC
159 } // namespace Engines
160 } // namespace ioda
implements ODC bindings
IODA's error system.
Interfaces for ioda::Group and related classes.
ODB / ODC engine.
void select(const std::vector< std::string > &columns, const std::string &filename, const std::vector< int > &varnos, const std::string &query)
Populate structure with data from specified columns, file and varnos.
oops::Parameter< std::vector< OdbVariableParameters > > variables
Variables to select.
oops::RequiredParameter< OdbWhereParameters > where
Selection criteria.
The ioda exception class.
Definition: Exception.h:54
Groups are a new implementation of ObsSpaces.
Definition: Group.h:159
An ObsGroup is a specialization of a ioda::Group. It provides convenience functions and guarantees th...
Definition: ObsGroup.h:32
static ObsGroup generate(Group &emptyGroup, const NewDimensionScales_t &fundamentalDims, std::shared_ptr< const detail::DataLayoutPolicy > layout=nullptr)
Create an empty ObsGroup and populate it with the fundamental dimensions.
Definition: ObsGroup.cpp:72
Variables store data!
Definition: Variable.h:680
static std::shared_ptr< const DataLayoutPolicy > generate(const std::string &polid="")
Factory generator.
Definition: Layout.cpp:28
virtual Variable write(gsl::span< char > data, const Type &in_memory_dataType, const Selection &mem_selection=Selection::all, const Selection &file_selection=Selection::all)
The fundamental write function. Backends overload this function to implement all write operations.
Definition: Variable.cpp:317
IODA_DL ObsGroup openFile(const ODC_Parameters &params, Group emptyStorageGroup=ioda::Engines::ObsStore::createRootGroup())
Import an ODB file.
Definition: ODC.cpp:56
const char odcMissingMessage[]
Standard message when the ODC API is unavailable.
Definition: ODC.cpp:40
void initODC()
Function initializes the ODC API, just once.
Definition: ODC.cpp:45
static constexpr int varno_rawbt_mwts
Definition: DataFromSQL.h:60
static constexpr int obsgroup_mwsfy3
Definition: DataFromSQL.h:44
static constexpr int obsgroup_amsr
Definition: DataFromSQL.h:39
static constexpr int varno_rawbt
Definition: DataFromSQL.h:52
std::vector< std::shared_ptr< NewDimensionScale_Base > > NewDimensionScales_t
#define ioda_Here()
Encapsulate the parameters to make calling simpler.
Definition: ODC.h:32
std::string filename
The name of the database "file" to open.
Definition: ODC.h:34
Used to specify Variable creation-time properties.
Definition: Has_Variables.h:57