23 #include "eckit/config/LocalConfiguration.h"
24 #include "eckit/exception/Exceptions.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"
37 namespace sf = util::stringfunctions;
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),
49 oops::Log::trace() <<
"ObsTable::ObsTable starting" << std::endl;
52 if (config.has(
"obsdatain")) {
53 nameIn_ = config.getString(
"obsdatain");
57 if (config.has(
"generate")) {
58 const eckit::LocalConfiguration gconf(config,
"generate");
61 if (config.has(
"obsdataout")) {
62 nameOut_ = config.getString(
"obsdataout");
63 sf::swapNameMember(config,
nameOut_);
65 oops::Log::trace() <<
"ObsTable::ObsTable created nobs = " <<
nobs() << std::endl;
74 oops::Log::trace() <<
"ObsTable::ObsTable destructed" << std::endl;
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;
93 tmp[jobs] =
static_cast<double>(vec[jobs]);
96 this->
putdb(col, tmp);
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;
109 tmp[jobs] =
static_cast<double>(vec[jobs]);
112 this->
putdb(col, tmp);
117 void ObsTable::putdb(
const std::string & col,
const std::vector<double> & vec)
const {
118 ASSERT(vec.size() ==
nobs());
120 oops::Log::info() <<
"ObsTable::putdb over-writing " << col << std::endl;
123 data_.insert(std::pair<std::string, std::vector<double> >(col, vec));
130 std::vector<double> tmp;
131 this->
getdb(col, tmp);
132 int intmiss = util::missingValue(intmiss);
133 double doublemiss = util::missingValue(doublemiss);
135 for (
size_t jobs = 0; jobs <
nobs(); ++jobs) {
136 if (tmp[jobs] == doublemiss) {
139 vec[jobs] = lround(tmp[jobs]);
147 std::vector<double> tmp;
148 this->
getdb(col, tmp);
149 float floatmiss = util::missingValue(floatmiss);
150 double doublemiss = util::missingValue(doublemiss);
152 for (
size_t jobs = 0; jobs <
nobs(); ++jobs) {
153 if (tmp[jobs] == doublemiss) {
154 vec[jobs] = floatmiss;
156 vec[jobs] =
static_cast<float>(tmp[jobs]);
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");
170 for (
unsigned int jobs = 0; jobs <
nobs(); ++jobs) {
171 vec[jobs] = ic->second[jobs];
178 oops::Log::trace() <<
"ObsTable::generateDistribution starting" << std::endl;
180 util::Duration first(config.getString(
"begin"));
182 if (config.has(
"end")) {
183 last = util::Duration(config.getString(
"end"));
185 util::Duration freq(config.getString(
"obs_frequency"));
188 util::Duration step(first);
189 while (step <= last) {
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);
201 unsigned int iobs = 0;
204 while (step <= last) {
206 for (
unsigned int jobs = 0; jobs < nobs_locations; ++jobs) {
207 double xpos = jobs*dx;
214 ASSERT(iobs ==
nobs);
217 const double err = config.getDouble(
"obs_error");
218 std::vector<double> obserr(
nobs);
219 for (
unsigned int jj = 0; jj <
nobs; ++jj) {
222 this->
putdb(
"ObsError", obserr);
224 oops::Log::trace() <<
"ObsTable::generateDistribution done, nobs= " <<
nobs << std::endl;
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];
237 oops::Log::info() <<
"ObsTable::printJo not implemented" << std::endl;
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);
252 std::vector<std::string> colnames;
253 for (
int jc = 0; jc < ncol; ++jc) {
256 colnames.push_back(col);
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));
268 for (
int jobs = 0; jobs <
nobs; ++jobs) {
274 util::DateTime ttt(sss);
277 if (inside)
times_.push_back(ttt);
281 for (std::map<std::string, std::vector<double> >::iterator jo =
data_.begin();
282 jo !=
data_.end(); ++jo) {
285 if (inside) jo->second.push_back(
val);
290 oops::Log::trace() <<
"ObsTable::ot_read done" << std::endl;
296 oops::Log::trace() <<
"ObsTable::otWrite writing " << filename << std::endl;
298 const size_t ioproc = 0;
301 if (
comm_.size() > 1)
comm_.allReduceInPlace(
nobs, eckit::mpi::Operation::SUM);
303 std::vector<util::DateTime> timebuff(
nobs);
306 std::vector<double> locbuff(
nobs);
309 std::vector<double> datasend(
times_.size() *
data_.size());
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];
317 std::vector<double> databuff(
data_.size() *
nobs);
320 if (
comm_.rank() == ioproc) {
321 std::ofstream fout(filename.c_str());
322 if (!fout.is_open()) ABORT(
"ObsTable::otWrite: Error opening file: " + filename);
324 int ncol =
data_.size();
325 fout << ncol << std::endl;
327 for (
auto jo =
data_.begin(); jo !=
data_.end(); ++jo)
328 fout << jo->first << std::endl;
330 fout <<
nobs << std::endl;
333 for (
int jobs = 0; jobs <
nobs; ++jobs) {
335 fout <<
" " << timebuff[jobs];
336 fout <<
" " << locbuff[jobs];
337 for (
int jcol = 0; jcol < ncol; ++jcol) {
338 fout <<
" " << databuff[iii];
347 oops::Log::trace() <<
"ObsTable::otWrite done" << std::endl;
353 os <<
"ObsTable: assimilation window = " <<
winbgn_ <<
" to " <<
winend_ << std::endl;
354 os <<
"ObsTable: file in = " <<
nameIn_ <<
", file out = " <<
nameOut_ << std::endl;