8 #include "ufo/ObsBias.h"
10 #include <Eigen/Dense>
16 #include "ioda/Engines/Factory.h"
17 #include "ioda/Engines/HH.h"
18 #include "ioda/Layout.h"
19 #include "ioda/ObsGroup.h"
20 #include "ioda/ObsVector.h"
22 #include "oops/base/Variables.h"
23 #include "oops/util/IntSetParser.h"
24 #include "oops/util/Logger.h"
27 #include "ufo/ObsDiagnostics.h"
35 : numStaticPredictors_(0), numVariablePredictors_(0), vars_(odb.obsvariables()),
36 rank_(odb.distribution()->rank()) {
37 oops::Log::trace() <<
"ObsBias::create starting." << std::endl;
41 params.
staticBC.value().predictors.value()) {
59 oops::Log::trace() <<
"ObsBias::create done." << std::endl;
65 : predictors_(other.predictors_),
66 prednames_(other.prednames_),
67 numStaticPredictors_(other.numStaticPredictors_),
68 numVariablePredictors_(other.numVariablePredictors_),
70 geovars_(other.geovars_), hdiags_(other.hdiags_), rank_(other.rank_) {
71 oops::Log::trace() <<
"ObsBias::copy ctor starting." << std::endl;
79 oops::Log::trace() <<
"ObsBias::copy ctor done." << std::endl;
92 if (rhs.
size() > 0 && this->size() == rhs.
size()) {
109 oops::Log::trace() <<
"ObsBias::read and initialize from file, starting "<< std::endl;
111 if (params.
inputFile.value() != boost::none) {
113 ioda::Engines::BackendNames backendName = ioda::Engines::BackendNames::Hdf5File;
114 ioda::Engines::BackendCreationParameters backendParams;
115 backendParams.fileName = *params.
inputFile.value();
116 backendParams.action = ioda::Engines::BackendFileActions::Open;
117 backendParams.openMode = ioda::Engines::BackendOpenModes::Read_Only;
121 ioda::Group backend = constructBackend(backendName, backendParams);
122 ioda::ObsGroup obsgroup = ioda::ObsGroup(backend,
123 ioda::detail::DataLayoutPolicy::generate(
124 ioda::detail::DataLayoutPolicy::Policies::None));
127 ioda::Variable coeffvar = obsgroup.vars[
"bias_coefficients"];
128 Eigen::ArrayXXf allbiascoeffs;
129 coeffvar.readWithEigenRegular(allbiascoeffs);
140 for (
size_t jpred = 0; jpred < pred_idx.size(); ++jpred) {
141 for (
size_t jvar = 0; jvar < var_idx.size(); ++jvar) {
142 biascoeffs_[
index(jpred, jvar)] = allbiascoeffs(pred_idx[jpred], var_idx[jvar]);
147 oops::Log::warning() <<
"ObsBias::prior file is NOT available, starting from ZERO"
151 oops::Log::trace() <<
"ObsBias::read and initilization done " << std::endl;
159 const std::vector<std::string> & predictors,
160 const std::vector<int> & channels,
161 const Eigen::MatrixXd & coeffs) {
163 ioda::NewDimensionScales_t dims {
164 ioda::NewDimensionScale<int>(
"npredictors", predictors.size()),
165 ioda::NewDimensionScale<int>(
"nchannels", channels.size())
168 ioda::ObsGroup ogrp = ioda::ObsGroup::generate(parent, dims);
171 ioda::Variable predsVar = ogrp.vars.createWithScales<std::string>(
172 "predictors", {ogrp.vars[
"npredictors"]});
173 predsVar.write(predictors);
175 ioda::Variable chansVar = ogrp.vars.createWithScales<
int>(
"channels", {ogrp.vars[
"nchannels"]});
176 chansVar.write(channels);
179 ioda::VariableCreationParameters float_params;
180 float_params.chunk =
true;
181 float_params.compressWithGZIP();
182 float missing_value = util::missingValue(missing_value);
183 float_params.setFillValue<
float>(missing_value);
186 ioda::Variable biasVar = ogrp.vars.createWithScales<
float>(
"bias_coefficients",
187 {ogrp.vars[
"npredictors"], ogrp.vars[
"nchannels"]}, float_params);
188 biasVar.writeWithEigenRegular(coeffs);
196 if (
rank_ != 0)
return;
198 if (params.
outputFile.value() != boost::none) {
200 if (
vars_.channels().size() == 0) {
201 throw eckit::NotImplemented(
"ObsBias::write not implemented for variables without channels",
205 const std::string output_filename = *params.
outputFile.value();
206 ioda::Group group = ioda::Engines::HH::createFile(output_filename,
207 ioda::Engines::BackendCreateModes::Truncate_If_Exists);
213 Eigen::Map<const Eigen::MatrixXd>
219 oops::Log::warning() <<
"obs bias.output file is NOT available, bias coefficients "
220 <<
"will not be saved." << std::endl;
228 oops::Log::trace() <<
"ObsBias::norm starting." << std::endl;
239 const int numCoeffs = numUnitCoeffs +
biascoeffs_.size();
240 if (numCoeffs > 0) zz = std::sqrt(zz/numCoeffs);
242 oops::Log::trace() <<
"ObsBias::norm done." << std::endl;
255 return std::vector<std::shared_ptr<const PredictorBase>>(
262 if (this->
size() > 0) {
264 Eigen::Map<const Eigen::MatrixXd>
266 os <<
"Obs bias coefficients: " << std::endl;
267 os <<
"---------------------------------------------------------------" << std::endl;
269 os << std::fixed << std::setw(20) <<
prednames_[p]
270 <<
": Min= " << std::setw(15) << std::setprecision(8)
272 <<
", Max= " << std::setw(15) << std::setprecision(8)
274 <<
", Norm= " << std::setw(15) << std::setprecision(8)
275 << std::sqrt(
static_cast<double>(
vars_.size()))
280 <<
": Min= " << std::setw(15) << std::setprecision(8)
281 << coeffs.row(p).minCoeff()
282 <<
", Max= " << std::setw(15) << std::setprecision(8)
283 << coeffs.row(p).maxCoeff()
284 <<
", Norm= " << std::setw(15) << std::setprecision(8)
285 << coeffs.row(p).norm()
288 os <<
"---------------------------------------------------------------";
298 geovars_ += pred->requiredGeovars();
299 hdiags_ += pred->requiredHdiagnostics();
302 if (
vars_.channels().size() > 0) {
305 ASSERT(
vars_.size() ==
vars_.channels().size());
306 for (
auto & job :
vars_.channels()) {
310 for (
const std::string & variable :
vars_.variables())
ObsBias & operator=(const ObsBias &)
size_t rank_
MPI rank, used to determine whether the task should output bias coeffs to a file.
Eigen::VectorXd biascoeffs_
bias correction coefficients (npredictors x nprimitivevariables)
Predictors predictors_
bias correction predictors
void zero()
Set all variable predictors coefficients to zero (used in the test)
oops::Variables geovars_
Variables that need to be requested from the model (for computation of predictors)
ObsBias(ioda::ObsSpace &, const Parameters_ &)
void print(std::ostream &) const override
void initPredictor(const PredictorParametersWrapper ¶ms)
ObsBias & operator+=(const ObsBiasIncrement &)
const Predictors & predictors() const
Return a reference to the vector of all (static and variable) predictors.
std::vector< std::string > prednames_
predictor names
std::size_t numStaticPredictors_
number of static predictors (i.e. predictors with fixed coefficients all equal to 1)
size_t index(size_t jpred, size_t jvar) const
index in the flattened biascoeffs_ for predictor jpred and variable jvar
std::vector< std::shared_ptr< const PredictorBase > > variablePredictors() const
Return the vector of variable predictors.
oops::Variables hdiags_
Diagnostics that need to be requested from the obs operator (for computation of predictors)
void read(const Parameters_ &)
Read bias correction coefficients from file.
oops::Variables vars_
corrected variables names (for now has to be same as "simulated variables")
std::size_t numVariablePredictors_
number of variable predictors (i.e. predictors with variable coefficients)
void write(const Parameters_ &) const
Contains increments to bias correction coefficients.
const Eigen::VectorXd & data() const
Return bias coefficient increments.
Parameters influencing the bias correction process.
oops::Parameter< StaticOrVariationalBCParameters > variationalBC
List of predictors with coefficients determined by variational analysis (VarBC).
oops::Parameter< StaticOrVariationalBCParameters > staticBC
List of predictors with unit coefficients (unaffected by VarBC).
oops::OptionalParameter< std::string > outputFile
oops::OptionalParameter< std::string > inputFile
static std::unique_ptr< PredictorBase > create(const PredictorParametersBase ¶meters, const oops::Variables &vars)
Create and return a new predictor.
Contains a polymorphic parameter holding an instance of a subclass of PredictorParametersBase.
oops::RequiredPolymorphicParameter< PredictorParametersBase, PredictorFactory > predictorParameters
std::vector< int > getRequiredVariableIndices(const ioda::ObsGroup &obsgroup, const std::string &varname, typename std::vector< std::string >::const_iterator elements_to_look_for_begin, typename std::vector< std::string >::const_iterator elements_to_look_for_end)
std::vector< int > getRequiredVarOrChannelIndices(const ioda::ObsGroup &obsgroup, const oops::Variables &vars_to_look_for)
ioda::ObsGroup saveBiasCoeffsWithChannels(ioda::Group &parent, const std::vector< std::string > &predictors, const std::vector< int > &channels, const Eigen::MatrixXd &coeffs)