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