FV3 Bundle
test/fileio/IodaIO.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2009-2016 ECMWF.
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  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation nor
8  * does it submit to any jurisdiction.
9  */
10 
11 #ifndef TEST_INTERFACE_OBSSPACE_H_
12 #define TEST_INTERFACE_OBSSPACE_H_
13 
14 #include <string>
15 #include <cmath>
16 
17 #define BOOST_TEST_NO_MAIN
18 #define BOOST_TEST_ALTERNATIVE_INIT_API
19 #define BOOST_TEST_DYN_LINK
20 #include <boost/test/unit_test.hpp>
21 
22 #include <boost/noncopyable.hpp>
23 
24 #include "eckit/config/LocalConfiguration.h"
25 #include "oops/runs/Test.h"
26 #include "oops/util/Logger.h"
27 #include "test/TestEnvironment.h"
28 
29 #include "fileio/IodaIO.h"
30 #include "fileio/IodaIOfactory.h"
31 
32 namespace ioda {
33 namespace test {
34 
35 // -----------------------------------------------------------------------------
36 
38  const eckit::LocalConfiguration conf(::test::TestEnvironment::config());
39  std::vector<eckit::LocalConfiguration> obstypes;
40 
41  std::string FileName;
42  std::string TestObsType;
43  std::unique_ptr<ioda::IodaIO> TestIO;
44 
45  std::size_t Nlocs;
46  std::size_t Nobs;
47  std::size_t Nrecs;
48  std::size_t Nvars;
49  std::size_t ExpectedNobs;
50  std::size_t ExpectedNlocs;
51  std::size_t ExpectedNrecs;
52  std::size_t ExpectedNvars;
53 
54  // Walk through the different ObsTypes and try constructing with the files.
55  conf.get("ObsTypes", obstypes);
56  for (std::size_t i = 0; i < obstypes.size(); ++i) {
57  oops::Log::debug() << "IodaIO::ObsTypes: conf" << obstypes[i] << std::endl;
58 
59  TestObsType = obstypes[i].getString("ObsType");
60  oops::Log::debug() << "IodaIO::ObsType: " << TestObsType << std::endl;
61 
62  FileName = obstypes[i].getString("Input.filename");
63  TestIO.reset(ioda::IodaIOfactory::Create(FileName, "r"));
64  BOOST_CHECK(TestIO.get());
65 
66  // Constructor in read mode is also responsible for setting nobs and nlocs
67  ExpectedNlocs = obstypes[i].getInt("Input.metadata.nlocs");
68  ExpectedNobs = obstypes[i].getInt("Input.metadata.nobs");
69  ExpectedNrecs = obstypes[i].getInt("Input.metadata.nrecs");
70  ExpectedNvars = obstypes[i].getInt("Input.metadata.nvars");
71  Nlocs = TestIO->nlocs();
72  Nobs = TestIO->nobs();
73  Nrecs = TestIO->nrecs();
74  Nvars = TestIO->nvars();
75 
76  BOOST_CHECK_EQUAL(ExpectedNlocs, Nlocs);
77  BOOST_CHECK_EQUAL(ExpectedNobs, Nobs);
78  BOOST_CHECK_EQUAL(ExpectedNrecs, Nrecs);
79  BOOST_CHECK_EQUAL(ExpectedNvars, Nvars);
80 
81  if (obstypes[i].has("Output.filename")) {
82  FileName = obstypes[i].getString("Output.filename");
83  ExpectedNlocs = obstypes[i].getInt("Output.metadata.nlocs");
84  ExpectedNobs = obstypes[i].getInt("Output.metadata.nobs");
85  ExpectedNrecs = obstypes[i].getInt("Output.metadata.nrecs");
86  ExpectedNvars = obstypes[i].getInt("Output.metadata.nvars");
87 
88  TestIO.reset(ioda::IodaIOfactory::Create(FileName, "W", ExpectedNlocs, ExpectedNobs, ExpectedNrecs, ExpectedNvars));
89  BOOST_CHECK(TestIO.get());
90 
91  Nlocs = TestIO->nlocs();
92  Nobs = TestIO->nobs();
93  Nrecs = TestIO->nrecs();
94  Nvars = TestIO->nvars();
95 
96  BOOST_CHECK_EQUAL(ExpectedNlocs, Nlocs);
97  BOOST_CHECK_EQUAL(ExpectedNobs, Nobs);
98  BOOST_CHECK_EQUAL(ExpectedNrecs, Nrecs);
99  BOOST_CHECK_EQUAL(ExpectedNvars, Nvars);
100  }
101  }
102  }
103 
104 // -----------------------------------------------------------------------------
105 
106 void testReadVar() {
107  const eckit::LocalConfiguration conf(::test::TestEnvironment::config());
108 
109  std::vector<eckit::LocalConfiguration> obstypes;
110  std::vector<std::string> varnames;
111  std::vector<float> ExpectedVnorms;
112 
113  std::string FileName;
114  std::string TestObsType;
115  std::unique_ptr<ioda::IodaIO> TestIO;
116  std::size_t Vsize;
117  std::unique_ptr<float[]> TestVarData;
118  float Vnorm;
119  float Tol;
120 
121  // Walk through the different ObsTypes and try constructing with the files.
122  conf.get("ObsTypes", obstypes);
123  for (std::size_t i = 0; i < obstypes.size(); ++i) {
124  oops::Log::debug() << "IodaIO::ObsTypes: conf" << obstypes[i] << std::endl;
125 
126  TestObsType = obstypes[i].getString("ObsType");
127  oops::Log::debug() << "IodaIO::ObsType: " << TestObsType << std::endl;
128 
129  FileName = obstypes[i].getString("Input.filename");
130  TestIO.reset(ioda::IodaIOfactory::Create(FileName, "r"));
131 
132  // Read in data from the file and check values.
133  varnames = obstypes[i].getStringVector("Input.variables");
134  ExpectedVnorms = obstypes[i].getFloatVector("Input.metadata.norms");
135  Tol = obstypes[i].getFloat("Input.metadata.tolerance");
136  Vsize = TestIO->nlocs();
137  TestVarData.reset(new float[Vsize]);
138  for(std::size_t j = 0; j < varnames.size(); ++j) {
139  TestIO->ReadVar(varnames[j], TestVarData.get());
140 
141  // Compute the vector length TestVarData and compare with config values
142  Vnorm = 0.0;
143  for(std::size_t k = 0; k < Vsize; ++k) {
144  Vnorm += pow(TestVarData.get()[k], 2.0);
145  }
146  Vnorm = sqrt(Vnorm);
147 
148  BOOST_CHECK_CLOSE(Vnorm, ExpectedVnorms[j], Tol);
149  }
150  }
151  }
152 
153 // -----------------------------------------------------------------------------
154 
155 void testWriteVar() {
156  const eckit::LocalConfiguration conf(::test::TestEnvironment::config());
157  std::vector<eckit::LocalConfiguration> obstypes;
158  std::vector<std::string> varnames;
159 
160  std::string FileName;
161  std::string TestObsType;
162  std::unique_ptr<ioda::IodaIO> TestIO;
163  std::size_t Nlocs;
164  std::size_t Nobs;
165  std::size_t Nrecs;
166  std::size_t Nvars;
167  std::unique_ptr<float[]> TestVarData;
168 
169  std::size_t TestNlocs;
170  std::size_t TestNobs;
171  std::size_t TestNrecs;
172  std::size_t TestNvars;
173 
174  int VarSum;
175  int ExpectedSum;
176 
177  // Walk through the different ObsTypes and try constructing with the files.
178  conf.get("ObsTypes", obstypes);
179  for (std::size_t i = 0; i < obstypes.size(); ++i) {
180  oops::Log::debug() << "IodaIO::ObsTypes: conf" << obstypes[i] << std::endl;
181 
182  TestObsType = obstypes[i].getString("ObsType");
183  oops::Log::debug() << "IodaIO::ObsType: " << TestObsType << std::endl;
184 
185  // Not all of the tests have output files
186  if (obstypes[i].has("Output.filename")) {
187  FileName = obstypes[i].getString("Output.filename");
188  Nlocs = obstypes[i].getInt("Output.metadata.nlocs");
189  Nobs = obstypes[i].getInt("Output.metadata.nobs");
190  Nrecs = obstypes[i].getInt("Output.metadata.nrecs");
191  Nvars = obstypes[i].getInt("Output.metadata.nvars");
192  TestIO.reset(ioda::IodaIOfactory::Create(FileName, "W", Nlocs, Nobs, Nrecs, Nvars));
193 
194  // Try writing contrived data into the output file
195  varnames = obstypes[i].getStringVector("Output.variables");
196  TestVarData.reset(new float[Nlocs]);
197  ExpectedSum = 0;
198  for (std::size_t j = 0; j < Nlocs; ++j) {
199  TestVarData.get()[j] = float(j);
200  ExpectedSum += j;
201  }
202  ExpectedSum *= varnames.size();
203 
204  for(std::size_t j = 0; j < varnames.size(); ++j) {
205  TestIO->WriteVar(varnames[j], TestVarData.get());
206  }
207 
208  // open the file we just created and see if it contains what we just wrote into it
209  TestIO.reset(ioda::IodaIOfactory::Create(FileName, "r"));
210 
211  TestNlocs = TestIO->nlocs();
212  TestNobs = TestIO->nobs();
213  TestNrecs = TestIO->nrecs();
214  TestNvars = TestIO->nvars();
215 
216  BOOST_CHECK_EQUAL(TestNlocs, Nlocs);
217  BOOST_CHECK_EQUAL(TestNobs, Nobs);
218  BOOST_CHECK_EQUAL(TestNrecs, Nrecs);
219  BOOST_CHECK_EQUAL(TestNvars, Nvars);
220 
221  VarSum = 0;
222  for(std::size_t j = 0; j < varnames.size(); ++j) {
223  TestIO->ReadVar(varnames[j], TestVarData.get());
224  for(std::size_t k = 0; k < Nlocs; ++k) {
225  VarSum += int(TestVarData.get()[k]);
226  }
227  }
228 
229  BOOST_CHECK_EQUAL(VarSum, ExpectedSum);
230  }
231  }
232  }
233 
234 // -----------------------------------------------------------------------------
235 
237  const eckit::LocalConfiguration conf(::test::TestEnvironment::config());
238 
239  std::vector<eckit::LocalConfiguration> obstypes;
240 
241  std::string FileName;
242  std::string TestObsType;
243  std::unique_ptr<ioda::IodaIO> TestIO;
244  std::size_t Vsize;
245  std::unique_ptr<int[]> TestVarDate;
246  std::unique_ptr<int[]> TestVarTime;
247  float Dnorm;
248  float Tnorm;
249  float ExpectedDnorm;
250  float ExpectedTnorm;
251  float Tol;
252 
253  // Walk through the different ObsTypes and try constructing with the files.
254  conf.get("ObsTypes", obstypes);
255  for (std::size_t i = 0; i < obstypes.size(); ++i) {
256  oops::Log::debug() << "IodaIO::ObsTypes: conf" << obstypes[i] << std::endl;
257 
258  TestObsType = obstypes[i].getString("ObsType");
259  oops::Log::debug() << "IodaIO::ObsType: " << TestObsType << std::endl;
260 
261  FileName = obstypes[i].getString("Input.filename");
262  TestIO.reset(ioda::IodaIOfactory::Create(FileName, "r"));
263 
264  // Read in data from the file and check values.
265  Vsize = TestIO->nlocs();
266  TestVarDate.reset(new int[Vsize]);
267  TestVarTime.reset(new int[Vsize]);
268  TestIO->ReadDateTime(TestVarDate.get(), TestVarTime.get());
269 
270  // Compute the vector length TestVarData and compare with config values
271  Dnorm = 0.0;
272  Tnorm = 0.0;
273  for(std::size_t k = 0; k < Vsize; ++k) {
274  Dnorm += pow(float(TestVarDate.get()[k]), 2.0);
275  Tnorm += pow(float(TestVarTime.get()[k]), 2.0);
276  }
277  Dnorm = sqrt(Dnorm);
278  Tnorm = sqrt(Tnorm);
279 
280  ExpectedDnorm = obstypes[i].getFloat("Input.datetime.dnorm");
281  ExpectedTnorm = obstypes[i].getFloat("Input.datetime.tnorm");
282  Tol = obstypes[i].getFloat("Input.datetime.tolerance");
283 
284  BOOST_CHECK_CLOSE(Dnorm, ExpectedDnorm, Tol);
285  BOOST_CHECK_CLOSE(Tnorm, ExpectedTnorm, Tol);
286  }
287  }
288 
289 // -----------------------------------------------------------------------------
290 
291 class IodaIO : public oops::Test {
292  public:
293  IodaIO() {}
294  virtual ~IodaIO() {}
295  private:
296  std::string testid() const {return "test::IodaIO";}
297 
298  void register_tests() const {
299  boost::unit_test::test_suite * ts = BOOST_TEST_SUITE("IodaIO");
300 
301  ts->add(BOOST_TEST_CASE(&testConstructor));
302  ts->add(BOOST_TEST_CASE(&testReadVar));
303  ts->add(BOOST_TEST_CASE(&testWriteVar));
304  ts->add(BOOST_TEST_CASE(&testReadDateTime));
305 
306  boost::unit_test::framework::master_test_suite().add(ts);
307  }
308 };
309 
310 // -----------------------------------------------------------------------------
311 
312 } // namespace test
313 } // namespace ioda
314 
315 #endif // TEST_INTERFACE_OBSSPACE_H_
l_size ! loop over number of fields ke do je do i
void testReadDateTime()
Definition: conf.py:1
static const eckit::Configuration & config()
l_size ! loop over number of fields ke do j
logical debug
Definition: mpp.F90:1297
void register_tests() const
void testConstructor()
std::string testid() const
static ioda::IodaIO * Create(const std::string &FileName, const std::string &FileMode)
Instantiate a IodaIO object in read mode.