UFO
TransformBase.h
Go to the documentation of this file.
1 /*
2  * (C) Crown copyright 2020, 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 
8 #ifndef UFO_VARIABLETRANSFORMS_TRANSFORMBASE_H_
9 #define UFO_VARIABLETRANSFORMS_TRANSFORMBASE_H_
10 
11 #include <algorithm>
12 #include <cmath>
13 #include <functional>
14 #include <map>
15 #include <memory>
16 #include <ostream>
17 #include <string>
18 #include <vector>
19 
20 #include "eckit/exception/Exceptions.h"
21 #include "eckit/types/FloatCompare.h"
22 
23 #include "ioda/ObsDataVector.h"
24 
25 #include "oops/util/CompareNVectors.h"
26 #include "oops/util/Logger.h"
27 #include "oops/util/missingValues.h"
28 #include "oops/util/ObjectCounter.h"
29 #include "oops/util/PropertiesOfNVectors.h"
30 
32 #include "ufo/filters/QCflags.h"
33 #include "ufo/filters/Variables.h"
36 
37 
38 namespace ioda {
39 template <typename DATATYPE>
40 class ObsDataVector;
41 class ObsSpace;
42 class ObsVector;
43 }
44 
45 namespace ufo {
46 class VariableTransformsParameters;
47 class Variables;
48 }
49 
50 namespace ufo {
51 
52 /// \brief Base class for variable conversion
54  public:
56  const ObsFilterData& data,
57  const std::shared_ptr<ioda::ObsDataVector<int>>& flags);
58  /// Destructor
59  virtual ~TransformBase() {}
60  /// Run variable conversion
61  virtual void runTransform(const std::vector<bool> &apply) = 0;
62  /// Return list of required geovals
63  virtual Variables requiredVariables() const { return Variables(); }
64 
65  private:
66  /// templated function for float, int data types
67  template <typename T>
68  void filterObservation(const std::string &variableName,
69  std::vector<T> &obsVector) const {
70  if (flags_.has(variableName)) {
71  const T missing = util::missingValue(T());
72  const std::vector<int> *varFlags = &flags_[variableName];
73 
74  std::transform(obsVector.begin(), obsVector.end(), // Input range 1
75  varFlags->begin(), // 1st element of input range vector 2 (must be same size)
76  obsVector.begin(), // 1st element of output range (must be same size)
77  [missing](T obsvalue, int flag)
78  { return flag == QCflags::missing || flag == QCflags::bounds
79  ? missing : obsvalue; });
80  }
81  }
82 
83  /// Method used for the calculation
88  /// The observation name
89  std::string obsName_;
90 
91  protected:
92  /// templated function for float, int data types
93  template <typename T>
94  void getObservation(const std::string &originalTag, const std::string &varName,
95  std::vector<T> &obsVector, bool require = false) const {
96  if (!obsdb_.has(originalTag, varName)) {
97  if (require)
98  throw eckit::BadValue("The parameter `" + varName + "@" + originalTag +
99  "` does not exist in the ObsSpace ", Here());
100  else
101  return;
102  }
103 
104  obsVector.resize(obsdb_.nlocs());
105  obsdb_.get_db(originalTag, varName, obsVector);
106  // Set obsValue to missingValue if flag is equal to QCflags::missing or QCflags::bounds
107  if (UseValidDataOnly()) filterObservation(varName, obsVector);
108  }
109 
110  /// \brief Save a transformed variable to the `DerivedObsValue` group of the obs space.
111  ///
112  /// If the saved variable is a simulated variable, QC flags previously set to `missing` are reset
113  /// to `pass` at locations where a valid obs value has been assigned. Conversely, QC flags
114  /// previously set to `pass` are reset to `missing` at locations where the variable is set to a
115  /// missing value.
116  ///
117  /// \param varName Variable name.
118  /// \param obsVactor Variable values.
119  template <typename T>
120  void putObservation(const std::string &varName, const std::vector<T> &obsVector) {
121  obsdb_.put_db(outputTag, varName, obsVector);
122  if (flags_.has(varName)) {
123  std::vector<int> &varFlags = flags_[varName];
124  ASSERT(varFlags.size() == obsVector.size());
125 
126  const T missing = util::missingValue(T());
127  for (size_t iloc = 0; iloc < obsVector.size(); ++iloc) {
128  if (varFlags[iloc] == QCflags::missing && obsVector[iloc] != missing)
129  varFlags[iloc] = QCflags::pass;
130  else if (varFlags[iloc] == QCflags::pass && obsVector[iloc] == missing)
131  varFlags[iloc] = QCflags::missing;
132  }
133  }
134  }
135 
136  /// subclasses to access Method and formualtion used for the calculation
139  bool UseValidDataOnly() const { return UseValidDataOnly_; }
142  /// subclasses to access the observation name
143  std::string obsName() const { return obsName_; }
144  /// Configurable parameters
146 
147  /// Observation and geoval data
149  /// Observation space
150  ioda::ObsSpace &obsdb_ = data_.obsspace();
152  /// Missing value (int)
153  const int missingValueInt = util::missingValue(1);
154  /// Missing value (float)
155  const float missingValueFloat = util::missingValue(1.0f);
156  /// output tag for derived parameters
157  const std::string outputTag = "DerivedObsValue";
158 };
159 
160 /// \brief Transform factory
162  public:
163  static std::unique_ptr<TransformBase> create(
164  const std::string &, const VariableTransformsParameters &,
165  const ObsFilterData &,
166  const std::shared_ptr<ioda::ObsDataVector<int>> &);
167  virtual ~TransformFactory() = default;
168 
169  protected:
170  explicit TransformFactory(const std::string &);
171 
172  private:
173  virtual std::unique_ptr<TransformBase> make(
175  const ObsFilterData &,
176  const std::shared_ptr<ioda::ObsDataVector<int>> &) = 0;
177  static std::map<std::string, TransformFactory *> &getMakers() {
178  static std::map<std::string, TransformFactory *> makers_;
179  return makers_;
180  }
181 };
182 
183 /// \brief Transform maker
184 template <class T>
186  virtual std::unique_ptr<TransformBase> make(
187  const VariableTransformsParameters &options,
188  const ObsFilterData& data,
189  const std::shared_ptr<ioda::ObsDataVector<int>> &flags) {
190  return std::unique_ptr<TransformBase>(new T(options, data, flags));
191  }
192 
193  public:
194  explicit TransformMaker(const std::string &name) : TransformFactory(name) {}
195 };
196 
197 } // namespace ufo
198 
199 #endif // UFO_VARIABLETRANSFORMS_TRANSFORMBASE_H_
ObsFilterData provides access to all data related to an ObsFilter.
ioda::ObsSpace & obsspace() const
Returns reference to ObsSpace associated with ObsFilterData.
Base class for variable conversion.
Definition: TransformBase.h:53
std::string obsName() const
subclasses to access the observation name
TransformBase(const VariableTransformsParameters &options, const ObsFilterData &data, const std::shared_ptr< ioda::ObsDataVector< int >> &flags)
formulas::MethodFormulation method() const
subclasses to access Method and formualtion used for the calculation
const std::string outputTag
output tag for derived parameters
void SetUseValidDataOnly(bool t)
virtual Variables requiredVariables() const
Return list of required geovals.
Definition: TransformBase.h:63
formulas::MethodFormulation formulation_
Definition: TransformBase.h:85
void putObservation(const std::string &varName, const std::vector< T > &obsVector)
Save a transformed variable to the DerivedObsValue group of the obs space.
std::string obsName_
The observation name.
Definition: TransformBase.h:89
formulas::MethodFormulation formulation() const
bool UseValidDataOnly() const
const float missingValueFloat
Missing value (float)
void filterObservation(const std::string &variableName, std::vector< T > &obsVector) const
templated function for float, int data types
Definition: TransformBase.h:68
virtual void runTransform(const std::vector< bool > &apply)=0
Run variable conversion.
const int missingValueInt
Missing value (int)
ioda::ObsSpace & obsdb_
Observation space.
void getObservation(const std::string &originalTag, const std::string &varName, std::vector< T > &obsVector, bool require=false) const
templated function for float, int data types
Definition: TransformBase.h:94
formulas::MethodFormulation method_
Method used for the calculation.
Definition: TransformBase.h:84
const VariableTransformsParameters & options_
Configurable parameters.
virtual ~TransformBase()
Destructor.
Definition: TransformBase.h:59
bool AllowSuperSaturation() const
ioda::ObsDataVector< int > & flags_
ObsFilterData data_
Observation and geoval data.
Transform factory.
static std::map< std::string, TransformFactory * > & getMakers()
TransformFactory(const std::string &)
static std::unique_ptr< TransformBase > create(const std::string &, const VariableTransformsParameters &, const ObsFilterData &, const std::shared_ptr< ioda::ObsDataVector< int >> &)
virtual ~TransformFactory()=default
virtual std::unique_ptr< TransformBase > make(const VariableTransformsParameters &, const ObsFilterData &, const std::shared_ptr< ioda::ObsDataVector< int >> &)=0
Transform maker.
TransformMaker(const std::string &name)
virtual std::unique_ptr< TransformBase > make(const VariableTransformsParameters &options, const ObsFilterData &data, const std::shared_ptr< ioda::ObsDataVector< int >> &flags)
Options controlling the operation of the variablestansform filter.
logical, parameter t
Forward declarations.
Definition: ObsAodExt.h:25
constexpr int pass
Definition: QCflags.h:14
constexpr int missing
Definition: QCflags.h:20
MethodFormulation
Various Methods and Formulations available.
Definition: Formulas.h:26
Definition: RunCRTM.h:27