UFO
src/ufo/utils/PrimitiveVariables.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2021 Met Office UK
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_UTILS_PRIMITIVEVARIABLES_H_
9 #define UFO_UTILS_PRIMITIVEVARIABLES_H_
10 
11 #include <memory>
12 #include <string>
13 #include <vector>
14 
15 #include "ioda/ObsDataVector.h"
16 #include "ufo/filters/Variable.h"
17 #include "ufo/filters/Variables.h"
18 #include "ufo/utils/ArrowProxy.h"
19 
20 namespace ioda {
21  template <typename DATATYPE> class ObsDataVector;
22  class ObsSpace;
23 }
24 
25 namespace ufo {
26 
27 class ObsFilterData;
28 
29 /// A proxy object providing access to the name, group and values of a "primitive", i.e.
30 /// single-channel, variable pointed to by a PrimitiveVariablesIterator.
31 ///
32 /// \see PrimitiveVariables for an example of its use.
33 ///
34 /// \warning Never use a PrimitiveVariable object obtained by dereferencing a
35 /// PrimitiveVariablesIterator after incrementing this iterator or when the iterator has gone out
36 /// of scope.
38  public:
39  PrimitiveVariable(const Variable &variable, size_t channelIndex,
40  const std::vector<float> &values)
41  : variable_(variable), channelIndex_(channelIndex), values_(values)
42  {}
43 
44  /// Return the name of the primitive variable.
45  std::string name() const { return variable_.variable(channelIndex_); }
46  /// Return the group of the primitive variable.
47  const std::string &group() const { return variable_.group(); }
48  /// Return a Variable object representing the primitive variable.
50  /// Return the values of the primitive variable at all observation locations.
51  const std::vector<float> &values() const { return values_; }
52 
53  private:
55  size_t channelIndex_;
56  const std::vector<float> &values_;
57 };
58 
59 /// \brief Iterator over the names and values of primitive variables held in a Variables object.
60 ///
61 /// \see PrimitiveVariables
62 ///
63 /// Note: this iterator exists to support range-based for loops, but it doesn't have a copy
64 /// constructor (it would need to be very costly -- requiring a copy of the ObsDataVector stored
65 /// in the iterator), so it can't be passed to STL algorithms that take iterators by value.
67  public:
68  typedef ptrdiff_t difference_type;
72  typedef std::forward_iterator_tag iterator_category;
73 
74  struct BeginTag {};
75  struct EndTag {};
76 
77  /// \brief Create an iterator pointing to the first primitive variable in \p variables.
79  : variables_(variables), data_(data), variableIndex_(0), channelIndex_(0)
80  {
82  }
83 
84  /// \brief Create an iterator pointing past the range of primitive variables in \p variables.
85  PrimitiveVariablesIterator(const Variables &variables, const ObsFilterData &data, EndTag)
86  : variables_(variables), data_(data), variableIndex_(variables_.size()), channelIndex_(0)
87  {}
88 
89  /// \brief Dereference the iterator, returning a proxy object whose methods such as name(),
90  /// group() and values() can be called to get access to the name, group and values of the
91  /// primitive variable pointed to by the iterator.
94  }
95 
97  return ArrowProxy<PrimitiveVariable>(operator*());
98  }
99 
101  if (variableIndex_ < variables_.size()) {
102  ++channelIndex_;
103  if (channelIndex_ == variables_[variableIndex_].size()) {
104  ++variableIndex_;
105  channelIndex_ = 0;
107  }
108  }
109  return *this;
110  }
111 
112  bool operator==(const PrimitiveVariablesIterator& other) const {
113  // In principle we should also check variables_ and data_ for equality.
114  // We don't do it for efficiency.
115  return variableIndex_ == other.variableIndex_;
116  return channelIndex_ == other.channelIndex_;
117  }
118 
119  bool operator!=(const PrimitiveVariablesIterator& other) const {
120  return !operator==(other);
121  }
122 
123  private:
124  void loadCurrentVariable();
125 
126  private:
131  std::unique_ptr<ioda::ObsDataVector<float>> vector_;
132 };
133 
134 /// \brief A range covering all "primitive" (single-channel) variables in a Variables object.
135 ///
136 /// It makes it possible to iterate over all these primitive variables using a range-based for loop.
137 /// Each iteration has access to the name and group of a single variable as well as the vector of
138 /// its values at all observation locations. For example:
139 ///
140 /// Variables vars = ...;
141 /// ObsFilterData data = ...; // within a filter, we'd typically use the data_ member variable
142 /// for (PrimitiveVariable var : PrimitiveVariables(vars, data)) {
143 /// // Access to the name of the current primitive variable: var.name()
144 /// // Access to its group: var.group()
145 /// // Access to its values (a vector of floats): var.values()
146 /// }
148  public:
149  PrimitiveVariables(const Variables &variables, const ObsFilterData &data)
150  : variables_(variables), data_(data)
151  {}
152 
155  }
156 
159  }
160 
161  private:
164 };
165 
166 } // namespace ufo
167 
168 #endif // UFO_UTILS_PRIMITIVEVARIABLES_H_
Utility class used in overloads of operator-> in forward iterators.
Definition: ArrowProxy.h:17
ObsFilterData provides access to all data related to an ObsFilter.
const std::vector< float > & values_
const std::vector< float > & values() const
Return the values of the primitive variable at all observation locations.
const std::string & group() const
Return the group of the primitive variable.
Variable variable() const
Return a Variable object representing the primitive variable.
PrimitiveVariable(const Variable &variable, size_t channelIndex, const std::vector< float > &values)
std::string name() const
Return the name of the primitive variable.
A range covering all "primitive" (single-channel) variables in a Variables object.
PrimitiveVariablesIterator end() const
PrimitiveVariablesIterator begin() const
PrimitiveVariables(const Variables &variables, const ObsFilterData &data)
Iterator over the names and values of primitive variables held in a Variables object.
std::unique_ptr< ioda::ObsDataVector< float > > vector_
PrimitiveVariablesIterator(const Variables &variables, const ObsFilterData &data, BeginTag)
Create an iterator pointing to the first primitive variable in variables.
ArrowProxy< PrimitiveVariable > operator->() const
PrimitiveVariable operator*() const
Dereference the iterator, returning a proxy object whose methods such as name(), group() and values()...
bool operator==(const PrimitiveVariablesIterator &other) const
PrimitiveVariablesIterator(const Variables &variables, const ObsFilterData &data, EndTag)
Create an iterator pointing past the range of primitive variables in variables.
bool operator!=(const PrimitiveVariablesIterator &other) const
const std::string & variable() const
Definition: Variable.cc:99
const std::string & group() const
Definition: Variable.cc:116
size_t size() const
Return the number of constituent Variable objects (some of which may contain multiple channels).
Definition: Variables.cc:92
Forward declarations.
Definition: ObsAodExt.h:25
Definition: RunCRTM.h:27