UFO
ProfileDataHandler.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_PROFILE_PROFILEDATAHANDLER_H_
9 #define UFO_PROFILE_PROFILEDATAHANDLER_H_
10 
11 #include <memory>
12 #include <string>
13 #include <unordered_map>
14 #include <utility>
15 #include <vector>
16 
17 #include "boost/variant.hpp"
18 
19 #include "ioda/ObsDataVector.h"
20 #include "ioda/ObsSpace.h"
21 
22 #include "oops/util/CompareNVectors.h"
23 #include "oops/util/missingValues.h"
24 
26 #include "ufo/filters/Variables.h"
27 
31 
33 #include "ufo/utils/StringUtils.h"
34 
35 namespace ioda {
36  class ObsSpace;
37 }
38 
39 namespace ufo {
40  class GeoVaLs;
41  class ObsDiagnostics;
42  class ProfileDataHolder;
43 }
44 
45 namespace ufo {
46 
47  /// \brief Retrieve and store data for individual profiles.
48  /// To do this, first the vector of values in the entire data sample is retrieved
49  /// then the relevant data corresponding to this profile are extracted.
51  public:
53  const DataHandlerParameters &options,
54  const std::vector <bool> &apply,
55  const Variables &filtervars,
56  std::vector<std::vector<bool>> &flagged);
57 
58  /// Retrieve a vector containing the requested variable for the current profile.
59  /// -# If the variable has previously been placed in a vector, return the vector.
60  /// -# Otherwise obtain the vector from the entire data sample, as long as the entire sample
61  /// is not empty.
62  /// Also store the name of the variable, enabling it to be retrieved later.
63  template <typename T>
64  std::vector<T>& get(const std::string &fullname)
65  {
66  // Determine variable and group names
67  std::string varname;
68  std::string groupname;
69  ufo::splitVarGroup(fullname, varname, groupname);
70 
71  auto it_profileData = profileData_.find(fullname);
72  if (it_profileData != profileData_.end()) {
73  // If the vector is already present, return it.
74  // If the type T is incorrect then boost::get will return an exception;
75  // provide additional information if that occurs.
76  try {
77  return boost::get<std::vector<T>> (it_profileData->second);
78  } catch (boost::bad_get) {
79  throw eckit::BadParameter("Template parameter passed to boost::get for " +
80  fullname + " probably has the wrong type", Here());
81  }
82  } else {
83  std::vector <T> vec_prof; // Vector storing data for current profile.
84  // Retrieve variable vector from entire sample.
85  const std::vector <T> &vec_all = entireSampleDataHandler_->get<T>(fullname);
86  // Only proceed if the vector is not empty.
87  if (!vec_all.empty()) {
89  for (const auto& profileIndex : profileIndicesInEntireSample_)
90  vec_prof.emplace_back(vec_all[profileIndex]);
91  }
92  // Add vector to map (even if it is empty).
93  profileData_.emplace(fullname, std::move(vec_prof));
94  return boost::get<std::vector<T>> (profileData_[fullname]);
95  }
96  }
97 
98  /// Directly set a vector for the current profile.
99  /// Typically used to store variables that are used locally in checks
100  /// (e.g. intermediate values).
101  /// Also initialise a vector in the entire sample, allowing the data to
102  /// be stored between checks.
103  template <typename T>
104  void set(const std::string &fullname, std::vector<T> &&vec_in)
105  {
106  // Determine variable and group names
107  std::string varname;
108  std::string groupname;
109  ufo::splitVarGroup(fullname, varname, groupname);
110  // Check whether vector is already in map.
111  auto it_profileData = profileData_.find(fullname);
112  if (it_profileData != profileData_.end()) {
113  // Replace vector in map.
114  it_profileData->second = std::move(vec_in);
115  } else {
116  // Add vector to map.
117  profileData_.emplace(fullname, std::move(vec_in));
118  }
119  entireSampleDataHandler_->initialiseVector<T>(fullname);
120  // Transfer this profile's data into the entire sample.
122  std::vector <T>& entireSampleData = entireSampleDataHandler_->get<T>(fullname);
123  const std::vector <T>& profileData = this->get<T>(fullname);
124  size_t idx = 0;
125  for (const auto& profileIndex : profileIndicesInEntireSample_) {
126  updateValueIfPresent(profileData, idx, entireSampleData, profileIndex);
127  idx++;
128  }
129  }
130 
131  /// Initialise the next profile prior to applying checks.
132  /// Clears \p profileData_ and determines the \p profileIndices_ for the next profile.
133  void initialiseNextProfile();
134 
135  /// Update information for this profile.
136  /// This function calls three other functions which take the following actions:
137  /// 1. Set final report flags in this profile,
138  /// 2. Modify 'flagged' vector for each filter variable based on check results,
139  /// 3. If any variables in the current profile were modified by the checks,
140  /// the equivalent variables in the entire sample are set to the modified values.
142 
143  /// Write various quantities to the obsdb so they can be used in future QC checks.
144  /// Use the method in EntireSampleDataHandler to do this.
145  void writeQuantitiesToObsdb();
146 
147  /// Return obsdb
148  ioda::ObsSpace &getObsdb() {return obsdb_;}
149 
150  /// Return number of levels to which QC checks should be applied.
151  int getNumProfileLevels() const {return profileIndices_->getNumProfileLevels();}
152 
153  /// Get GeoVaLs for a particular profile.
154  std::vector <float>& getGeoVaLVector(const std::string &variableName);
155 
156  /// Get ObsDiags for a particular profile.
157  std::vector <float>& getObsDiag(const std::string &variableName);
158 
159  /// Reset profile indices (required if it is desired to loop through
160  /// the entire sample again).
162 
163  /// Produce a vector of all profiles, loading the requested variables into each one.
164  std::vector <ProfileDataHolder> produceProfileVector
165  (const std::vector <std::string> &variableNamesInt,
166  const std::vector <std::string> &variableNamesFloat,
167  const std::vector <std::string> &variableNamesString,
168  const std::vector <std::string> &variableNamesGeoVaLs,
169  const std::vector <std::string> &variableNamesObsDiags);
170 
171  /// Read values from a collection of profiles and update information related to each one.
172  void updateAllProfiles(std::vector <ProfileDataHolder> &profiles);
173 
174  private: // functions
175  /// Reset profile information (vectors and corresponding names).
176  /// This should be called every time a new profile will be retrieved.
178 
179  /// If any variables in the current profile were modified by the checks,
180  /// the equivalent variables in the entire sample are set to the modified values.
181  /// The variables that are (potentially) modified are hardcoded but this could be
182  /// changed to a configurable list if requred.
183  void updateEntireSampleData();
184 
185  /// Set final report flags based on the NumAnyErrors counter.
186  void setFinalReportFlags();
187 
188  /// Update the 'flagged' vector based on any flags that may have changed during the checks.
189  /// The QC flag group is hardocded but this could be changed to
190  /// a configurable value if required.
191  void setFlagged();
192 
193  /// Transfer values from one vector to another (as long as neither is empty).
194  template <typename T>
195  void updateValueIfPresent(const std::vector <T> &vecIn, const size_t &idxIn,
196  std::vector <T> &vecOut, const size_t &idxOut)
197  {
198  // Ensure neither vector is empty.
199  if (oops::anyVectorEmpty(vecIn, vecOut)) return;
200  vecOut[idxOut] = vecIn[idxIn];
201  }
202 
203  /// Get indices in entire sample corresponding to current profile.
204  void getProfileIndicesInEntireSample(const std::string& groupname);
205 
206  /// Get the name of the vertical coordinate that is used to determine the slant path
207  /// locations for the variable \p variableName.
208  std::string getAssociatedVerticalCoordinate(const std::string & variableName) const;
209 
210  private: // members
211  /// Container of each variable in the current profile.
212  std::unordered_map <std::string, boost::variant
213  <std::vector <int>, std::vector <float>, std::vector <std::string>>> profileData_;
214 
215  /// Container of GeoVaLs in the current profile.
216  std::unordered_map <std::string, std::vector <float>> GeoVaLData_;
217 
218  /// Container of ObsDiags in the current profile.
219  std::unordered_map <std::string, std::vector <float>> obsDiagData_;
220 
221  /// Observation database.
222  ioda::ObsSpace &obsdb_;
223 
224  /// GeoVaLs loaded by the filter.
225  const GeoVaLs* const geovals_;
226 
227  /// ObsDiags loaded by the filter.
228  const ObsDiagnostics* const obsdiags_;
229 
230  /// Configurable parameters.
232 
233  /// Filter variables
235 
236  /// Flagged values
237  std::vector<std::vector<bool>> &flagged_;
238 
239  /// Class that handles the entire data sample.
240  std::unique_ptr <EntireSampleDataHandler> entireSampleDataHandler_;
241 
242  /// Class that handles profile indices.
243  std::unique_ptr <ProfileIndices> profileIndices_;
244 
245  /// Indices in the entire data sample that correspond to the current profile.
246  std::vector <size_t> profileIndicesInEntireSample_;
247  };
248 } // namespace ufo
249 
250 #endif // UFO_PROFILE_PROFILEDATAHANDLER_H_
Options controlling the operation of the EntireSampleDataHandler and ProfileDataHandler classes.
GeoVaLs: geophysical values at locations.
ObsFilterData provides access to all data related to an ObsFilter.
Retrieve and store data for individual profiles. To do this, first the vector of values in the entire...
ProfileDataHandler(const ObsFilterData &data, const DataHandlerParameters &options, const std::vector< bool > &apply, const Variables &filtervars, std::vector< std::vector< bool >> &flagged)
std::vector< T > & get(const std::string &fullname)
const DataHandlerParameters & options_
Configurable parameters.
void updateAllProfiles(std::vector< ProfileDataHolder > &profiles)
Read values from a collection of profiles and update information related to each one.
std::unique_ptr< EntireSampleDataHandler > entireSampleDataHandler_
Class that handles the entire data sample.
void set(const std::string &fullname, std::vector< T > &&vec_in)
std::vector< float > & getGeoVaLVector(const std::string &variableName)
Get GeoVaLs for a particular profile.
const Variables & filtervars_
Filter variables.
const ObsDiagnostics *const obsdiags_
ObsDiags loaded by the filter.
std::unordered_map< std::string, std::vector< float > > obsDiagData_
Container of ObsDiags in the current profile.
std::vector< ProfileDataHolder > produceProfileVector(const std::vector< std::string > &variableNamesInt, const std::vector< std::string > &variableNamesFloat, const std::vector< std::string > &variableNamesString, const std::vector< std::string > &variableNamesGeoVaLs, const std::vector< std::string > &variableNamesObsDiags)
Produce a vector of all profiles, loading the requested variables into each one.
int getNumProfileLevels() const
Return number of levels to which QC checks should be applied.
std::unique_ptr< ProfileIndices > profileIndices_
Class that handles profile indices.
std::vector< float > & getObsDiag(const std::string &variableName)
Get ObsDiags for a particular profile.
std::unordered_map< std::string, std::vector< float > > GeoVaLData_
Container of GeoVaLs in the current profile.
ioda::ObsSpace & obsdb_
Observation database.
void updateValueIfPresent(const std::vector< T > &vecIn, const size_t &idxIn, std::vector< T > &vecOut, const size_t &idxOut)
Transfer values from one vector to another (as long as neither is empty).
void setFinalReportFlags()
Set final report flags based on the NumAnyErrors counter.
std::vector< std::vector< bool > > & flagged_
Flagged values.
void getProfileIndicesInEntireSample(const std::string &groupname)
Get indices in entire sample corresponding to current profile.
ioda::ObsSpace & getObsdb()
Return obsdb.
std::string getAssociatedVerticalCoordinate(const std::string &variableName) const
std::vector< size_t > profileIndicesInEntireSample_
Indices in the entire data sample that correspond to the current profile.
const GeoVaLs *const geovals_
GeoVaLs loaded by the filter.
std::unordered_map< std::string, boost::variant< std::vector< int >, std::vector< float >, std::vector< std::string > > > profileData_
Container of each variable in the current profile.
Forward declarations.
Definition: ObsAodExt.h:25
Definition: RunCRTM.h:27
void splitVarGroup(const std::string &vargrp, std::string &var, std::string &grp)
Definition: StringUtils.cc:27