23 #include "eckit/config/LocalConfiguration.h"
24 #include "eckit/exception/Exceptions.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"
36 namespace sf = util::stringfunctions;
43 const util::DateTime & bgn,
const util::DateTime & end,
44 const eckit::mpi::Comm & timeComm)
45 :
oops::ObsSpaceBase(config, comm, bgn, end), winbgn_(bgn), winend_(end), comm_(timeComm),
48 oops::Log::trace() <<
"ObsTable::ObsTable starting" << std::endl;
51 if (config.has(
"obsdatain")) {
52 nameIn_ = config.getString(
"obsdatain");
56 if (config.has(
"generate")) {
57 const eckit::LocalConfiguration gconf(config,
"generate");
60 if (config.has(
"obsdataout")) {
61 nameOut_ = config.getString(
"obsdataout");
62 sf::swapNameMember(config,
nameOut_);
64 oops::Log::trace() <<
"ObsTable::ObsTable created nobs = " <<
nobs() << std::endl;
70 oops::Log::trace() <<
"ObsTable::ObsTable destructed" << std::endl;
87 void ObsTable::putdb(
const std::string & col,
const std::vector<int> & vec)
const {
88 std::vector<double> tmp(vec.size());
89 int intmiss = util::missingValue(
int());
90 double doublemiss = util::missingValue(
double());
91 for (
size_t jobs = 0; jobs < vec.size(); ++jobs) {
92 if (vec[jobs] == intmiss) {
93 tmp[jobs] = doublemiss;
95 tmp[jobs] =
static_cast<double>(vec[jobs]);
98 this->
putdb(col, tmp);
104 std::vector<double> tmp(vec.size());
105 float floatmiss = util::missingValue(
float());
106 double doublemiss = util::missingValue(
double());
107 for (
size_t jobs = 0; jobs < vec.size(); ++jobs) {
108 if (vec[jobs] == floatmiss) {
109 tmp[jobs] = doublemiss;
111 tmp[jobs] =
static_cast<double>(vec[jobs]);
114 this->
putdb(col, tmp);
119 void ObsTable::putdb(
const std::string & col,
const std::vector<double> & vec)
const {
120 ASSERT(vec.size() ==
nobs());
122 oops::Log::info() <<
"ObsTable::putdb over-writing " << col << std::endl;
125 data_.insert(std::pair<std::string, std::vector<double> >(col, vec));
132 std::vector<double> tmp;
133 this->
getdb(col, tmp);
134 int intmiss = util::missingValue(
int());
135 double doublemiss = util::missingValue(
double());
137 for (
size_t jobs = 0; jobs <
nobs(); ++jobs) {
138 if (tmp[jobs] == doublemiss) {
141 vec[jobs] = lround(tmp[jobs]);
149 std::vector<double> tmp;
150 this->
getdb(col, tmp);
151 float floatmiss = util::missingValue(
float());
152 double doublemiss = util::missingValue(
double());
154 for (
size_t jobs = 0; jobs <
nobs(); ++jobs) {
155 if (tmp[jobs] == doublemiss) {
156 vec[jobs] = floatmiss;
158 vec[jobs] =
static_cast<float>(tmp[jobs]);
166 std::map<std::string, std::vector<double> >::const_iterator ic =
data_.find(col);
167 if (ic ==
data_.end()) {
168 oops::Log::error() <<
"ObsTable::getdb " << col <<
" not found." << std::endl;
169 ABORT(
"ObsTable::getdb column not found");
172 for (
unsigned int jobs = 0; jobs <
nobs(); ++jobs) {
173 vec[jobs] = ic->second[jobs];
180 oops::Log::trace() <<
"ObsTable::generateDistribution starting" << std::endl;
182 util::Duration first(config.getString(
"begin"));
184 if (config.has(
"end")) {
185 last = util::Duration(config.getString(
"end"));
187 util::Duration
freq(config.getString(
"obs_frequency"));
190 util::Duration step(first);
191 while (step <= last) {
196 const unsigned int nobs_locations = config.getInt(
"obs_density");
197 const unsigned int nobs = nobs_locations*nobstimes;
198 double dx = 1.0/
static_cast<double>(nobs_locations);
203 unsigned int iobs = 0;
206 while (step <= last) {
208 for (
unsigned int jobs = 0; jobs < nobs_locations; ++jobs) {
209 double xpos = jobs*dx;
216 ASSERT(iobs ==
nobs);
219 const double err = config.getDouble(
"obs_error");
220 std::vector<double> obserr(
nobs);
221 for (
unsigned int jj = 0; jj <
nobs; ++jj) {
224 this->
putdb(
"ObsError", obserr);
226 oops::Log::trace() <<
"ObsTable::generateDistribution done, nobs= " <<
nobs << std::endl;
232 util::NormalDistribution<double> x(data.size(), 0.0, 1.0,
getSeed());
233 for (
size_t jj = 0; jj < data.size(); ++jj) data[jj] = x[jj];
241 oops::Log::trace() <<
"ObsTable::ot_read starting" << std::endl;
242 std::ifstream fin(filename.c_str());
243 if (!fin.is_open()) ABORT(
"ObsTable::otOpen: Error opening file: " + filename);
248 std::vector<std::string> colnames;
249 for (
int jc = 0; jc < ncol; ++jc) {
252 colnames.push_back(col);
257 std::vector<double> newcol;
258 for (
int jc = 0; jc < ncol; ++jc) {
259 ASSERT(
data_.find(colnames[jc]) ==
data_.end());
260 data_.insert(std::pair<std::string, std::vector<double> >(colnames[jc], newcol));
264 for (
int jobs = 0; jobs <
nobs; ++jobs) {
270 util::DateTime ttt(sss);
273 if (inside)
times_.push_back(ttt);
277 for (std::map<std::string, std::vector<double> >::iterator jo =
data_.begin();
278 jo !=
data_.end(); ++jo) {
281 if (inside) jo->second.push_back(
val);
286 oops::Log::trace() <<
"ObsTable::ot_read done" << std::endl;
292 oops::Log::trace() <<
"ObsTable::otWrite writing " << filename << std::endl;
294 const size_t ioproc = 0;
297 if (
comm_.size() > 1)
comm_.allReduceInPlace(
nobs, eckit::mpi::Operation::SUM);
299 std::vector<util::DateTime> timebuff(
nobs);
302 std::vector<double> locbuff(
nobs);
305 std::vector<double> datasend(
times_.size() *
data_.size());
307 for (
size_t jobs = 0; jobs <
times_.size(); ++jobs) {
308 for (
auto jo =
data_.begin(); jo !=
data_.end(); ++jo) {
309 datasend[iobs] = jo->second[jobs];
313 std::vector<double> databuff(
data_.size() *
nobs);
316 if (
comm_.rank() == ioproc) {
317 std::ofstream fout(filename.c_str());
318 if (!fout.is_open()) ABORT(
"ObsTable::otWrite: Error opening file: " + filename);
320 int ncol =
data_.size();
321 fout << ncol << std::endl;
323 for (
auto jo =
data_.begin(); jo !=
data_.end(); ++jo)
324 fout << jo->first << std::endl;
326 fout <<
nobs << std::endl;
329 for (
int jobs = 0; jobs <
nobs; ++jobs) {
331 fout <<
" " << timebuff[jobs];
332 fout <<
" " << locbuff[jobs];
333 for (
int jcol = 0; jcol < ncol; ++jcol) {
334 fout <<
" " << databuff[iii];
343 oops::Log::trace() <<
"ObsTable::otWrite done" << std::endl;
357 os <<
"ObsTable: assimilation window = " <<
winbgn_ <<
" to " <<
winend_ << std::endl;
358 os <<
"ObsTable: file in = " <<
nameIn_ <<
", file out = " <<
nameOut_;
Iterator over all observations.
void random(std::vector< double > &) const
std::vector< double > locations_
void print(std::ostream &) const
bool has(const std::string &col) const
void getdb(const std::string &, std::vector< int > &) const
unsigned int nobs() const
void otWrite(const std::string &) const
const eckit::mpi::Comm & comm_
ObsIterator begin() const
iterator to the first observation
const util::DateTime winbgn_
const util::DateTime winend_
std::map< std::string, std::vector< double > > data_
ObsIterator end() const
iterator to the observation past-the-last
ObsTable(const eckit::Configuration &, const eckit::mpi::Comm &, const util::DateTime &, const util::DateTime &, const eckit::mpi::Comm &)
void generateDistribution(const eckit::Configuration &)
std::vector< util::DateTime > times_
void otOpen(const std::string &)
void putdb(const std::string &, const std::vector< int > &) const
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)
The namespace for the main oops code.