OOPS
ObsTable.cc
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 #include "lorenz95/ObsTable.h"
12 
13 #include <algorithm>
14 #include <cmath>
15 #include <fstream>
16 #include <iostream>
17 #include <map>
18 #include <memory>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 #include "eckit/config/LocalConfiguration.h"
24 #include "eckit/exception/Exceptions.h"
25 
26 #include "lorenz95/ObsIterator.h"
27 #include "oops/mpi/mpi.h"
28 #include "oops/util/abor1_cpp.h"
29 #include "oops/util/DateTime.h"
30 #include "oops/util/Duration.h"
31 #include "oops/util/Logger.h"
32 #include "oops/util/missingValues.h"
33 #include "oops/util/Random.h"
34 #include "oops/util/stringFunctions.h"
35 
36 namespace sf = util::stringfunctions;
37 
38 // -----------------------------------------------------------------------------
39 namespace lorenz95 {
40 // -----------------------------------------------------------------------------
41 
42 ObsTable::ObsTable(const Parameters_ & params, const eckit::mpi::Comm & comm,
43  const util::DateTime & bgn, const util::DateTime & end,
44  const eckit::mpi::Comm & timeComm)
45  : oops::ObsSpaceBase(params, comm, bgn, end), winbgn_(bgn), winend_(end), comm_(timeComm),
46  obsvars_()
47 {
48  oops::Log::trace() << "ObsTable::ObsTable starting" << std::endl;
49  if (params.obsdatain.value() != boost::none) {
50  nameIn_ = *params.obsdatain.value();
51  otOpen(nameIn_);
52  }
53  // Generate locations etc... if required
54  if (params.generate.value() != boost::none) {
55  generateDistribution(*params.generate.value());
56  }
57  if (params.obsdataout.value() != boost::none) {
58  nameOut_ = *params.obsdataout.value();
59  sf::swapNameMember(params.toConfiguration(), nameOut_);
60  }
61  oops::Log::trace() << "ObsTable::ObsTable created nobs = " << nobs() << std::endl;
62 }
63 
64 // -----------------------------------------------------------------------------
65 
67  oops::Log::trace() << "ObsTable::ObsTable destructed" << std::endl;
68 }
69 
70 // -----------------------------------------------------------------------------
71 
72 void ObsTable::save() const {
73  if (!nameOut_.empty()) otWrite(nameOut_);
74 }
75 
76 // -----------------------------------------------------------------------------
77 
78 bool ObsTable::has(const std::string & col) const {
79  return (data_.find(col) != data_.end());
80 }
81 
82 // -----------------------------------------------------------------------------
83 
84 void ObsTable::putdb(const std::string & col, const std::vector<int> & vec) const {
85  std::vector<double> tmp(vec.size());
86  int intmiss = util::missingValue(int());
87  double doublemiss = util::missingValue(double());
88  for (size_t jobs = 0; jobs < vec.size(); ++jobs) {
89  if (vec[jobs] == intmiss) {
90  tmp[jobs] = doublemiss;
91  } else {
92  tmp[jobs] = static_cast<double>(vec[jobs]);
93  }
94  }
95  this->putdb(col, tmp);
96 }
97 
98 // -----------------------------------------------------------------------------
99 
100 void ObsTable::putdb(const std::string & col, const std::vector<float> & vec) const {
101  std::vector<double> tmp(vec.size());
102  float floatmiss = util::missingValue(float());
103  double doublemiss = util::missingValue(double());
104  for (size_t jobs = 0; jobs < vec.size(); ++jobs) {
105  if (vec[jobs] == floatmiss) {
106  tmp[jobs] = doublemiss;
107  } else {
108  tmp[jobs] = static_cast<double>(vec[jobs]);
109  }
110  }
111  this->putdb(col, tmp);
112 }
113 
114 // -----------------------------------------------------------------------------
115 
116 void ObsTable::putdb(const std::string & col, const std::vector<double> & vec) const {
117  ASSERT(vec.size() == nobs());
118  if (data_.find(col) != data_.end()) {
119  oops::Log::info() << "ObsTable::putdb over-writing " << col << std::endl;
120  data_[col] = vec;
121  } else {
122  data_.insert(std::pair<std::string, std::vector<double> >(col, vec));
123  }
124 }
125 
126 // -----------------------------------------------------------------------------
127 
128 void ObsTable::getdb(const std::string & col, std::vector<int> & vec) const {
129  std::vector<double> tmp;
130  this->getdb(col, tmp);
131  int intmiss = util::missingValue(int());
132  double doublemiss = util::missingValue(double());
133  vec.resize(nobs());
134  for (size_t jobs = 0; jobs < nobs(); ++jobs) {
135  if (tmp[jobs] == doublemiss) {
136  vec[jobs] = intmiss;
137  } else {
138  vec[jobs] = lround(tmp[jobs]);
139  }
140  }
141 }
142 
143 // -----------------------------------------------------------------------------
144 
145 void ObsTable::getdb(const std::string & col, std::vector<float> & vec) const {
146  std::vector<double> tmp;
147  this->getdb(col, tmp);
148  float floatmiss = util::missingValue(float());
149  double doublemiss = util::missingValue(double());
150  vec.resize(nobs());
151  for (size_t jobs = 0; jobs < nobs(); ++jobs) {
152  if (tmp[jobs] == doublemiss) {
153  vec[jobs] = floatmiss;
154  } else {
155  vec[jobs] = static_cast<float>(tmp[jobs]);
156  }
157  }
158 }
159 
160 // -----------------------------------------------------------------------------
161 
162 void ObsTable::getdb(const std::string & col, std::vector<double> & vec) const {
163  std::map<std::string, std::vector<double> >::const_iterator ic = data_.find(col);
164  if (ic == data_.end()) {
165  oops::Log::error() << "ObsTable::getdb " << col << " not found." << std::endl;
166  ABORT("ObsTable::getdb column not found");
167  }
168  vec.resize(nobs());
169  for (unsigned int jobs = 0; jobs < nobs(); ++jobs) {
170  vec[jobs] = ic->second[jobs];
171  }
172 }
173 
174 // -----------------------------------------------------------------------------
175 
177  oops::Log::trace() << "ObsTable::generateDistribution starting" << std::endl;
178 
179  const util::Duration &first = params.begin;
180  util::Duration last(winend_-winbgn_);
181  if (params.end.value() != boost::none) {
182  last = *params.end.value();
183  }
184  const util::Duration &freq = params.obsFrequency;
185 
186  int nobstimes = 0;
187  util::Duration step(first);
188  while (step <= last) {
189  ++nobstimes;
190  step += freq;
191  }
192 
193  const unsigned int nobs_locations = params.obsDensity;
194  const unsigned int nobs = nobs_locations*nobstimes;
195  double dx = 1.0/static_cast<double>(nobs_locations);
196 
197  times_.resize(nobs);
198  locations_.resize(nobs);
199 
200  unsigned int iobs = 0;
201  util::DateTime now(winbgn_);
202  step = first;
203  while (step <= last) {
204  now = winbgn_ + step;
205  for (unsigned int jobs = 0; jobs < nobs_locations; ++jobs) {
206  double xpos = jobs*dx;
207  times_[iobs] = now;
208  locations_[iobs] = xpos;
209  ++iobs;
210  }
211  step += freq;
212  }
213  ASSERT(iobs == nobs);
214 
215 // Generate obs error
216  const double err = params.obsError;
217  std::vector<double> obserr(nobs);
218  for (unsigned int jj = 0; jj < nobs; ++jj) {
219  obserr[jj] = err;
220  }
221  this->putdb("ObsError", obserr);
222 
223  oops::Log::trace() << "ObsTable::generateDistribution done, nobs= " << nobs << std::endl;
224 }
225 
226 // -----------------------------------------------------------------------------
227 
228 void ObsTable::random(std::vector<double> & data) const {
229  util::NormalDistribution<double> x(data.size(), 0.0, 1.0, getSeed());
230  for (size_t jj = 0; jj < data.size(); ++jj) data[jj] = x[jj];
231 }
232 
233 // -----------------------------------------------------------------------------
234 // ObsTable Private Methods
235 // -----------------------------------------------------------------------------
236 
237 void ObsTable::otOpen(const std::string & filename) {
238  oops::Log::trace() << "ObsTable::ot_read starting" << std::endl;
239  std::ifstream fin(filename.c_str());
240  if (!fin.is_open()) ABORT("ObsTable::otOpen: Error opening file: " + filename);
241 
242  int ncol, nobs;
243  fin >> ncol;
244 
245  std::vector<std::string> colnames;
246  for (int jc = 0; jc < ncol; ++jc) {
247  std::string col;
248  fin >> col;
249  colnames.push_back(col);
250  }
251 
252  fin >> nobs;
253  locations_.clear();
254  std::vector<double> newcol;
255  for (int jc = 0; jc < ncol; ++jc) {
256  ASSERT(data_.find(colnames[jc]) == data_.end());
257  data_.insert(std::pair<std::string, std::vector<double> >(colnames[jc], newcol));
258  }
259 
260  times_.clear();
261  for (int jobs = 0; jobs < nobs; ++jobs) {
262  int jjj;
263  fin >> jjj;
264  ASSERT(jjj == jobs);
265  std::string sss;
266  fin >> sss;
267  util::DateTime ttt(sss);
268  bool inside = ttt > winbgn_ && ttt <= winend_;
269 
270  if (inside) times_.push_back(ttt);
271  double loc;
272  fin >> loc;
273  if (inside) locations_.push_back(loc);
274  for (std::map<std::string, std::vector<double> >::iterator jo = data_.begin();
275  jo != data_.end(); ++jo) {
276  double val;
277  fin >> val;
278  if (inside) jo->second.push_back(val);
279  }
280  }
281 
282  fin.close();
283  oops::Log::trace() << "ObsTable::ot_read done" << std::endl;
284 }
285 
286 // -----------------------------------------------------------------------------
287 
288 void ObsTable::otWrite(const std::string & filename) const {
289  oops::Log::trace() << "ObsTable::otWrite writing " << filename << std::endl;
290 
291  const size_t ioproc = 0;
292 
293  int nobs = times_.size();
294  if (comm_.size() > 1) comm_.allReduceInPlace(nobs, eckit::mpi::Operation::SUM);
295 
296  std::vector<util::DateTime> timebuff(nobs);
297  oops::mpi::gather(comm_, times_, timebuff, ioproc);
298 
299  std::vector<double> locbuff(nobs);
300  oops::mpi::gather(comm_, locations_, locbuff, ioproc);
301 
302  std::vector<double> datasend(times_.size() * data_.size());
303  size_t iobs = 0;
304  for (size_t jobs = 0; jobs < times_.size(); ++jobs) {
305  for (auto jo = data_.begin(); jo != data_.end(); ++jo) {
306  datasend[iobs] = jo->second[jobs];
307  ++iobs;
308  }
309  }
310  std::vector<double> databuff(data_.size() * nobs);
311  oops::mpi::gather(comm_, datasend, databuff, ioproc);
312 
313  if (comm_.rank() == ioproc) {
314  std::ofstream fout(filename.c_str());
315  if (!fout.is_open()) ABORT("ObsTable::otWrite: Error opening file: " + filename);
316 
317  int ncol = data_.size();
318  fout << ncol << std::endl;
319 
320  for (auto jo = data_.begin(); jo != data_.end(); ++jo)
321  fout << jo->first << std::endl;
322 
323  fout << nobs << std::endl;
324 
325  size_t iii = 0;
326  for (int jobs = 0; jobs < nobs; ++jobs) {
327  fout << jobs;
328  fout << " " << timebuff[jobs];
329  fout << " " << locbuff[jobs];
330  for (int jcol = 0; jcol < ncol; ++jcol) {
331  fout << " " << databuff[iii];
332  ++iii;
333  }
334  fout << std::endl;
335  }
336 
337  fout.close();
338  }
339 
340  oops::Log::trace() << "ObsTable::otWrite done" << std::endl;
341 }
342 
343 // -----------------------------------------------------------------------------
345  return ObsIterator(locations_, 0);
346 }
347 // -----------------------------------------------------------------------------
349  return ObsIterator(locations_, locations_.size());
350 }
351 // -----------------------------------------------------------------------------
352 
353 void ObsTable::print(std::ostream & os) const {
354  os << "ObsTable: assimilation window = " << winbgn_ << " to " << winend_ << std::endl;
355  os << "ObsTable: file in = " << nameIn_ << ", file out = " << nameOut_;
356 }
357 
358 // -----------------------------------------------------------------------------
359 
360 } // namespace lorenz95
Options controlling generation of artificial observations.
Definition: ObsTable.h:34
oops::RequiredParameter< util::Duration > begin
Definition: ObsTable.h:38
oops::RequiredParameter< util::Duration > obsFrequency
Definition: ObsTable.h:40
oops::RequiredParameter< int > obsDensity
Number of observations to generate in each time slot.
Definition: ObsTable.h:42
oops::OptionalParameter< util::Duration > end
Definition: ObsTable.h:39
oops::RequiredParameter< double > obsError
Definition: ObsTable.h:43
Iterator over all observations.
void random(std::vector< double > &) const
Definition: ObsTable.cc:228
std::vector< double > locations_
Definition: ObsTable.h:109
void print(std::ostream &) const
Definition: ObsTable.cc:353
std::string nameIn_
Definition: ObsTable.h:114
bool has(const std::string &col) const
Definition: ObsTable.cc:78
void getdb(const std::string &, std::vector< int > &) const
Definition: ObsTable.cc:128
unsigned int nobs() const
Definition: ObsTable.h:89
void otWrite(const std::string &) const
Definition: ObsTable.cc:288
const eckit::mpi::Comm & comm_
Definition: ObsTable.h:112
ObsIterator begin() const
iterator to the first observation
Definition: ObsTable.cc:344
const util::DateTime winbgn_
Definition: ObsTable.h:105
void save() const
Definition: ObsTable.cc:72
void generateDistribution(const ObsGenerateParameters &params)
Definition: ObsTable.cc:176
const util::DateTime winend_
Definition: ObsTable.h:106
std::map< std::string, std::vector< double > > data_
Definition: ObsTable.h:110
ObsIterator end() const
iterator to the observation past-the-last
Definition: ObsTable.cc:348
std::string nameOut_
Definition: ObsTable.h:115
std::vector< util::DateTime > times_
Definition: ObsTable.h:108
void otOpen(const std::string &)
Definition: ObsTable.cc:237
void putdb(const std::string &, const std::vector< int > &) const
Definition: ObsTable.cc:84
ObsTable(const Parameters_ &, const eckit::mpi::Comm &, const util::DateTime &, const util::DateTime &, const eckit::mpi::Comm &)
Definition: ObsTable.cc:42
Configuration parameters for the L95 model's ObsSpace.
Definition: ObsTable.h:48
oops::OptionalParameter< std::string > obsdatain
File from which to load observations.
Definition: ObsTable.h:53
oops::OptionalParameter< std::string > obsdataout
File to which to save observations and analysis.
Definition: ObsTable.h:55
oops::OptionalParameter< ObsGenerateParameters > generate
Options controlling generation of artificial observations.
Definition: ObsTable.h:57
int64_t getSeed() const
Definition: ObsSpaceBase.h:58
int error
Definition: compare.py:168
The namespace for the L95 model.
void gather(const eckit::mpi::Comm &comm, const std::vector< double > &send, std::vector< double > &recv, const size_t root)
Definition: oops/mpi/mpi.cc:96
The namespace for the main oops code.