9 #include <boost/optional/optional_io.hpp>
13 #include "eckit/exception/Exceptions.h"
15 #include "ioda/ObsDataVector.h"
17 #include "oops/util/CompareNVectors.h"
18 #include "oops/util/Logger.h"
19 #include "oops/util/missingValues.h"
20 #include "oops/util/PropertiesOfNVectors.h"
38 if (!oops::allVectorsSameNonZeroSize(xvals, errors) ||
39 ((xvals.size() <= 1 || errors.size() <= 1))) {
40 std::ostringstream errString;
41 errString <<
"At least one vector is the wrong size - either unequal or less than 2."
42 << std::endl <<
"Vector sizes of xvals, errors: "
43 << oops::listOfVectorSizes(xvals, errors) << std::endl;
44 oops::Log::error() << errString.str();
45 throw eckit::BadValue(errString.str());
50 ASSERT(xvar.
size() == 1);
58 oops::Log::debug() <<
" StepwiseLinear, scale_factor_var: " << *scale_factor_var << std::endl;
62 for (
size_t i = 0; i < errors.size(); ++i) {
63 ASSERT(errors[i] >= 0.0);
69 if (xvals.back() < xvals.front()) {
72 for (
size_t kv = 1; kv < xvals.size(); ++kv) {
74 std::ostringstream errString;
75 errString <<
"The xvals vector of elements is NOT internally consistent."
76 <<
" It must be entirely either ascending or descending order,"
77 <<
" or two consecutive values are the same." << std::endl;
78 oops::Log::error() << errString.str();
79 throw eckit::BadValue(errString.str());
83 << config << std::endl;
104 <<
" and group: " << xvar.
group() << std::endl;
109 data.
get(xvar, testdata);
112 std::unique_ptr<ioda::ObsDataVector<float>> obvalues;
117 oops::Log::debug() <<
" ObsErrorModelStepwiseLinear, scale_factor_var name: "
118 << (*scale_factor_var).variable() <<
" and group: "
119 << (*scale_factor_var).group() << std::endl;
121 (*scale_factor_var).toOopsVariables()));
122 data.
get(*scale_factor_var, *obvalues);
127 if (testdata[iv].size() != obserr[iv].size()) {
128 std::ostringstream errString;
129 errString <<
"Something is wrong, testdata size not equal obserr size."
130 <<
" Sizes: " << testdata[iv].size() <<
" and " << obserr[iv].size() << std::endl;
131 oops::Log::error() << errString.str();
132 throw eckit::BadValue(errString.str());
135 for (
size_t jobs = 0; jobs < testdata[iv].size(); ++jobs) {
138 if (testdata[iv][jobs] ==
missing) {
141 xstar = testdata[iv][jobs];
146 error = errors[errors.size()-1];
148 for (
size_t kv = 1; kv < xvals.size(); ++kv) {
149 if ((
isAscending_ && (xstar > xvals[kv-1]) && (xstar <= xvals[kv])) ||
150 (!
isAscending_ && (xstar < xvals[kv-1]) && (xstar >= xvals[kv]))) {
155 error = y0 + (xstar-x0)*((y1-y0)/(x1-x0));
163 obserr[iv][jobs] = error*(*obvalues)[iv][jobs];
165 obserr[iv][jobs] = error;
const ufo::Variables & requiredVariables() const
geovals required to compute the function
void compute(const ObsFilterData &, ioda::ObsDataVector< float > &) const
compute the result of the function
~ObsErrorModelStepwiseLinear()
ObsErrorModelStepwiseLinearParameters options_
ObsErrorModelStepwiseLinear(const eckit::LocalConfiguration)
oops::OptionalParameter< Variable > scale_factor_var
When final answer is a multiplication factor, we need to know which variable to multiply.
oops::RequiredParameter< Variable > xvar
the name of the xvar
oops::RequiredParameter< std::vector< float > > errors
vector of error values corresponding to vector of X-steps
oops::RequiredParameter< std::vector< float > > xvals
vector of X-steps
ObsFilterData provides access to all data related to an ObsFilter.
ioda::ObsSpace & obsspace() const
Returns reference to ObsSpace associated with ObsFilterData.
void get(const Variable &varname, std::vector< float > &values) const
Fills a std::vector with values of the specified variable.
const std::string & variable() const
const std::string & group() const
oops::Variables toOopsVariables() const
static ObsFunctionMaker< ObsErrorFactorConventional > makerSteps_("ObsErrorFactorConventional")