UFO
InterpolateDataFromFile.cc
Go to the documentation of this file.
1 /*
2  * (C) Crown copyright 2021, Met Office
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  */
7 
9 
10 #include <set>
11 #include <string>
12 #include <vector>
13 
14 #include <boost/make_unique.hpp>
15 
16 #include "eckit/exception/Exceptions.h"
17 #include "ioda/ObsSpace.h"
18 #include "oops/util/AssociativeContainers.h"
20 
21 namespace ufo {
22 
23 namespace {
24 
25 /// \brief Store all components of `input` in `output`.
26 void save(const ioda::ObsDataVector<float> &input, ioda::ObsVector &output) {
27  const float fmiss = util::missingValue(fmiss);
28  const double dmiss = util::missingValue(dmiss);
29  const size_t numLocs = input.nlocs();
30  const size_t numInputVars = input.nvars();
31  const size_t numOutputVars = output.nvars();
32  for (size_t inputVarIndex = 0; inputVarIndex < numInputVars; ++inputVarIndex) {
33  const ioda::ObsDataRow<float> &inputVarValues = input[inputVarIndex];
34  const size_t outputVarIndex = output.varnames().find(input.varnames()[inputVarIndex]);
35  for (size_t locIndex = 0; locIndex < numLocs; ++locIndex) {
36  const float value = inputVarValues[locIndex];
37  output[locIndex * numOutputVars + outputVarIndex] =
38  (value == fmiss) ? dmiss : static_cast<double>(value);
39  }
40  }
41 }
42 
43 std::set<std::string> getVariableNamesWithoutChannels(const oops::Variables &vars) {
44  if (vars.channels().empty()) {
45  return std::set<std::string>(vars.variables().begin(), vars.variables().end());
46  } else {
47  // We assume there's only a single multi-channel variable
48  ASSERT(vars.channels().size() == vars.variables().size());
49  std::string channellessVariable = vars.variables().front();
50  channellessVariable.resize(channellessVariable.find_last_of('_'));
51  return std::set<std::string>{channellessVariable};
52  }
53 }
54 
55 } // namespace
56 
57 static PredictorMaker<InterpolateDataFromFile> maker("interpolate_data_from_file");
58 
60  const oops::Variables & vars)
61  : PredictorBase(parameters, vars) {
62  const std::set<std::string> channellessVariables = getVariableNamesWithoutChannels(vars_);
63 
64  for (const VariableCorrectionParameters & varParams : parameters.correctedVariables.value()) {
65  if (!oops::contains(channellessVariables, varParams.name))
66  throw eckit::UserError("'" + varParams.name.value() +
67  "' is not in the list of bias-corrected variables", Here());
68  eckit::LocalConfiguration varConfig = varParams.details.toConfiguration();
69  varConfig.set("group", "ObsBias");
70  obsFunctions_[varParams.name] = boost::make_unique<DrawValueFromFile<float>>(varConfig);
71  }
72 
73  for (const auto &varAndObsFunction : obsFunctions_) {
74  const DrawValueFromFile<float> &obsFunction = *varAndObsFunction.second;
75  const ufo::Variables &requiredVariables = obsFunction.requiredVariables();
76  geovars_ += requiredVariables.allFromGroup("GeoVaLs").toOopsVariables();
77  hdiags_ += requiredVariables.allFromGroup("ObsDiag").toOopsVariables();
78  }
79 }
80 
81 void InterpolateDataFromFile::compute(const ioda::ObsSpace & /*odb*/,
82  const GeoVaLs & geovals,
83  const ObsDiagnostics & obsdiags,
84  ioda::ObsVector & out) const {
85  ObsFilterData obsFilterData(out.space());
86  obsFilterData.associate(geovals);
87  obsFilterData.associate(obsdiags);
88 
89  out.zero();
90 
91  for (const auto &varAndObsFunction : obsFunctions_) {
92  const std::string &varName = varAndObsFunction.first;
93  const DrawValueFromFile<float> &obsFunction = *varAndObsFunction.second;
94 
95  oops::Variables currentVars({varName}, vars_.channels());
96  ioda::ObsDataVector<float> obsFunctionResult(out.space(), currentVars);
97  obsFunction.compute(obsFilterData, obsFunctionResult);
98  save(obsFunctionResult, out);
99  }
100 }
101 
102 } // namespace ufo
const ufo::Variables & requiredVariables() const
geovals required to compute the function
void compute(const ObsFilterData &, ioda::ObsDataVector< T > &) const
compute the result of the function
GeoVaLs: geophysical values at locations.
void compute(const ioda::ObsSpace &, const GeoVaLs &, const ObsDiagnostics &, ioda::ObsVector &) const override
compute the predictor
std::map< std::string, std::unique_ptr< DrawValueFromFile< float > > > obsFunctions_
InterpolateDataFromFile(const Parameters_ &, const oops::Variables &)
Configuration parameters of the interpolate_data_from_file predictor.
oops::Parameter< std::vector< VariableCorrectionParameters > > correctedVariables
ObsFilterData provides access to all data related to an ObsFilter.
void associate(const GeoVaLs &)
Associates GeoVaLs with this ObsFilterData.
oops::Variables vars_
variables that will be bias-corrected using this predictor
Definition: PredictorBase.h:84
oops::Variables geovars_
required GeoVaLs
Definition: PredictorBase.h:85
oops::Variables hdiags_
required ObsDiagnostics
Definition: PredictorBase.h:86
oops::Variables toOopsVariables() const
Definition: Variables.cc:156
Variables allFromGroup(const std::string &) const
Definition: Variables.cc:128
std::set< std::string > getVariableNamesWithoutChannels(const oops::Variables &vars)
void save(const ioda::ObsDataVector< float > &input, ioda::ObsVector &output)
Store all components of input in output.
bool contains(const std::set< T > &set, const T &element)
Definition: RunCRTM.h:27
static ObsOperatorMaker< ObsBackgroundErrorIdentity > maker("BackgroundErrorIdentity")