IODA
ObsSpacePutDbChannels.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2018-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 
8 #ifndef TEST_IODA_OBSSPACEPUTDBCHANNELS_H_
9 #define TEST_IODA_OBSSPACEPUTDBCHANNELS_H_
10 
11 #include <memory>
12 #include <string>
13 #include <vector>
14 
15 #include <boost/make_unique.hpp>
16 #include "Eigen/Core"
17 
18 #include "eckit/config/LocalConfiguration.h"
19 #include "eckit/testing/Test.h"
20 
21 #include "oops/mpi/mpi.h"
22 #include "oops/runs/Test.h"
23 #include "oops/test/TestEnvironment.h"
24 
25 #include "ioda/Engines/HH.h"
26 #include "ioda/ObsSpace.h"
27 
28 namespace ioda {
29 namespace test {
30 
31 CASE("ioda/ObsSpace/testPutDb") {
32  const auto &topLevelConf = ::test::TestEnvironment::config();
33 
34  util::DateTime bgn(topLevelConf.getString("window begin"));
35  util::DateTime end(topLevelConf.getString("window end"));
36 
37  std::vector<eckit::LocalConfiguration> confs;
38  topLevelConf.get("observations", confs);
39 
40  for (const eckit::LocalConfiguration & conf : confs) {
41  eckit::LocalConfiguration obsconf(conf, "obs space");
42 
43  std::unique_ptr<ObsSpace> obsspace = boost::make_unique<ObsSpace>(
44  obsconf, oops::mpi::world(), bgn, end, oops::mpi::myself());
45 
46  const Dimensions_t nlocs = obsspace->nlocs();
47  const Dimensions_t nchans = obsspace->nchans();
48  const bool hasChannels = nchans != 0;
49 
50  std::vector<float> testVec1(nlocs), testVec2(nlocs);
51  std::iota(testVec1.begin(), testVec1.end(), 1.0f);
52  std::iota(testVec2.begin(), testVec2.end(), 2.0f);
53  obsspace->put_db("DummyGroup", "multi_dimensional_var_2", testVec1);
54  obsspace->put_db("DummyGroup", "multi_dimensional_var_4", testVec2);
55  obsspace->put_db("MetaData", "single_dimensional_var_2", testVec1);
56  obsspace->put_db("DummyGroup", "single_dimensional_var", testVec1);
57  if (hasChannels) {
58  // Channel 1000000 does not exist
59  EXPECT_THROWS(obsspace->put_db("DummyGroup", "multi_dimensional_var_1000000", testVec1));
60  // The variable single_dimensional_var already exists, but is not associated with the
61  // nchans dimension
62  EXPECT_THROWS(obsspace->put_db("DummyGroup", "single_dimensional_var_2", testVec1));
63  }
64 
65  // Call the ObsSpace close function to force an output file to be written
66  obsspace->save();
67 
68  // Read the output file and check its contents are correct
69 
70  const std::string fileName = uniquifyFileName(obsconf.getString("obsdataout.obsfile"), 0, -1);
73 
74  if (hasChannels) {
75  const Variable nchansVar = group.vars.open("nchans");
76  const std::vector<int> channels = nchansVar.readAsVector<int>();
77  const std::size_t channel2Index =
78  std::find(channels.begin(), channels.end(), 2) - channels.begin();
79  const std::size_t channel4Index =
80  std::find(channels.begin(), channels.end(), 4) - channels.begin();
81 
82  {
83  const Variable var = group.vars.open("DummyGroup/multi_dimensional_var");
84  const Dimensions dims = var.getDimensions();
85  EXPECT_EQUAL(dims.dimensionality, 2);
86  const std::vector<Dimensions_t> expectedDimsCur{nlocs, nchans};
87  EXPECT_EQUAL(dims.dimsCur, expectedDimsCur);
88 
89  Eigen::ArrayXXf values;
90  var.readWithEigenRegular(values);
91  std::vector<float> channelValues(nlocs);
92  for (std::size_t loc = 0; loc < nlocs; ++loc)
93  channelValues[loc] = values(loc, channel2Index);
94  EXPECT_EQUAL(channelValues, testVec1);
95 
96  for (std::size_t loc = 0; loc < nlocs; ++loc)
97  channelValues[loc] = values(loc, channel4Index);
98  EXPECT_EQUAL(channelValues, testVec2);
99  }
100  } else { // has no channels
101  {
102  const Variable var = group.vars.open("DummyGroup/multi_dimensional_var_2");
103  const Dimensions dims = var.getDimensions();
104  EXPECT_EQUAL(dims.dimensionality, 1);
105  const std::vector<Dimensions_t> expectedDimsCur{nlocs};
106  EXPECT_EQUAL(dims.dimsCur, expectedDimsCur);
107 
108  const std::vector<float> values = var.readAsVector<float>();
109  EXPECT_EQUAL(values, testVec1);
110  }
111 
112  {
113  const Variable var = group.vars.open("DummyGroup/multi_dimensional_var_4");
114  const Dimensions dims = var.getDimensions();
115  EXPECT_EQUAL(dims.dimensionality, 1);
116  const std::vector<Dimensions_t> expectedDimsCur{nlocs};
117  EXPECT_EQUAL(dims.dimsCur, expectedDimsCur);
118 
119  const std::vector<float> values = var.readAsVector<float>();
120  EXPECT_EQUAL(values, testVec2);
121  }
122  }
123 
124  {
125  const Variable var = group.vars.open("DummyGroup/single_dimensional_var");
126  const Dimensions dims = var.getDimensions();
127  EXPECT_EQUAL(dims.dimensionality, 1);
128  const std::vector<Dimensions_t> expectedDimsCur{nlocs};
129  EXPECT_EQUAL(dims.dimsCur, expectedDimsCur);
130 
131  const std::vector<float> values = var.readAsVector<float>();
132  EXPECT_EQUAL(values, testVec1);
133  }
134 
135  {
136  const Variable var = group.vars.open("MetaData/single_dimensional_var_2");
137  const Dimensions dims = var.getDimensions();
138  EXPECT_EQUAL(dims.dimensionality, 1);
139  const std::vector<Dimensions_t> expectedDimsCur{nlocs};
140  EXPECT_EQUAL(dims.dimsCur, expectedDimsCur);
141 
142  const std::vector<float> values = var.readAsVector<float>();
143  EXPECT_EQUAL(values, testVec1);
144  }
145  }
146 }
147 
148 class ObsSpacePutDbChannels : public oops::Test {
149  private:
150  std::string testid() const override {return "test::ObsSpacePutDbChannels";}
151 
152  void register_tests() const override {}
153 
154  void clear() const override {}
155 };
156 
157 // -----------------------------------------------------------------------------
158 
159 } // namespace test
160 } // namespace ioda
161 
162 #endif // TEST_IODA_OBSSPACEPUTDBCHANNELS_H_
HDF5 engine.
Groups are a new implementation of ObsSpaces.
Definition: Group.h:159
Variables store data!
Definition: Variable.h:680
Has_Variables vars
Use this to access variables.
Definition: Group.h:123
virtual Variable open(const std::string &name) const
Open a Variable by name.
virtual Dimensions getDimensions() const
Definition: Variable.cpp:160
std::vector< DataType > readAsVector(const Selection &mem_selection=Selection::all, const Selection &file_selection=Selection::all) const
Read the variable into a new vector. Python convenience function.
Definition: Variable.h:502
Variable_Implementation readWithEigenRegular(EigenClass &res, const Selection &mem_selection=Selection::all, const Selection &file_selection=Selection::all) const
Read data into an Eigen::Array, Eigen::Matrix, Eigen::Map, etc.
Definition: Variable.h:551
std::string testid() const override
IODA_DL Group openFile(const std::string &filename, BackendOpenModes mode, HDF5_Version_Range compat=defaultVersionRange())
Open a ioda::Group backed by an HDF5 file.
Definition: HH.cpp:135
@ Read_Only
Open the file in read-only mode.
CASE("Derived variable and unit conversion methods")
std::string uniquifyFileName(const std::string &fileName, const std::size_t rankNum, const int timeRankNum)
uniquify the output file name
Definition: IodaUtils.cc:343
Describes the dimensions of an Attribute or Variable.
Definition: Dimensions.h:22
std::vector< Dimensions_t > dimsCur
The dimensions of the data.
Definition: Dimensions.h:23
Dimensions_t dimensionality
The dimensionality (rank) of the data.
Definition: Dimensions.h:25