UFO
ProcessAMVQI.cc
Go to the documentation of this file.
1 /*
2  * (C) 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 <algorithm>
11 #include <string>
12 #include <vector>
13 
14 #include "ioda/ObsSpace.h"
15 
16 #include "oops/util/Logger.h"
17 
19 
20 namespace ufo {
21 
22 // -----------------------------------------------------------------------------
23 
24 ProcessAMVQI::ProcessAMVQI(ioda::ObsSpace & obsdb, const Parameters_ & parameters,
25  std::shared_ptr<ioda::ObsDataVector<int>> flags,
26  std::shared_ptr<ioda::ObsDataVector<float>> obserr)
27  : ObsProcessorBase(obsdb, false /*deferToPost?*/, flags, obserr),
28  parameters_(parameters)
29 {
30  oops::Log::trace() << "ProcessAMVQI contructor starting" << std::endl;
31 }
32 
33 // -----------------------------------------------------------------------------
34 
36  oops::Log::trace() << "ProcessAMVQI destructed" << std::endl;
37 }
38 
39 // -----------------------------------------------------------------------------
40 /*! \brief A filter to convert new BUFR formatted data into variables with names
41  * corressponding to the wind generating application.
42  *
43  * Example:
44  * \code{.unparsed}
45  * obs filter:
46  * - filter: Process AMV QI
47  * number of generating apps: 4
48  * \endcode
49  *
50  * \author A.Martins (Met Office)
51  *
52  * \date 02/08/2021: Created
53  */
54 void ProcessAMVQI::doFilter() const {
55  oops::Log::trace() << "ProcessAMVQI doFilter" << std::endl;
56 
57  const float missing = util::missingValue(float());
58  const int int_missing = util::missingValue(int());
59  const size_t nlocs = obsdb_.nlocs();
60  const size_t number_of_apps = parameters_.number_of_apps.value();
61 
62  // vectors to store BUFR data
63  std::vector<float> percent_confidence(nlocs);
64  std::vector<int> wind_generating_application(nlocs);
65 
66  // Create vector of strings for percent_confidence_<number> to new variable
67  // Wind generating application number = QI type
68  // Table 1:
69  // 1 = Full weighted mixture of individual quality tests
70  // 2 = Weighted mixture of individual tests, but excluding forecast comparison
71  // 3 = Recursive filter function
72  // 4 = Common quality index (QI) without forecast
73  // 5 = QI without forecast
74  // 6 = QI with forecast
75  // 7 = Estimated Error (EE) in m/s converted to a percent confidence
76  std::vector<std::string> new_variables = {
77  "QI_full_weighted_mixture",
78  "QI_weighted_mixture_exc_forecast_comparison",
79  "QI_recursive_filter_function",
80  "QI_common",
81  "QI_without_forecast",
82  "QI_with_forecast",
83  "QI_estimated_error" };
84  const size_t total_variables = new_variables.size();
85 
86  // create variable to write to obsdb
87  std::vector<std::vector<float>> new_percent_confidence(total_variables,
88  std::vector<float>(nlocs, missing));
89 
90  // Get BUFR data
91  for (size_t iapp = 0; iapp < number_of_apps; ++iapp) {
92  // names of variables
93  std::string percent_confidence_name = "percent_confidence_";
94  std::string wind_generating_application_name = "wind_generating_application_";
95 
96  obsdb_.get_db("MetaData",
97  percent_confidence_name.append(std::to_string(iapp + 1)),
98  percent_confidence);
99 
100  obsdb_.get_db("MetaData",
101  wind_generating_application_name.append(std::to_string(iapp + 1)),
102  wind_generating_application);
103 
104  for (size_t idata = 0; idata < nlocs; ++idata) {
105  if (wind_generating_application[idata] != int_missing) {
106  new_percent_confidence[wind_generating_application[idata] - 1][idata] =
107  percent_confidence[idata];
108  }
109  }
110  }
111 
112  // Need to check database for the named variables and add to them if they exist.
113  for (size_t inum = 0; inum < total_variables; ++inum) {
114  if (std::any_of(new_percent_confidence[inum].begin(),
115  new_percent_confidence[inum].end(),
116  [missing] (float elem) {return elem != missing;})) {
117  // Check if new_variable already exists in obsdb
118  std::vector<float> existing_new_percent_confidence(nlocs, missing);
119  if (obsdb_.has("MetaData",
120  new_variables[inum])) {
121  obsdb_.get_db("MetaData",
122  new_variables[inum],
123  existing_new_percent_confidence);
124  } else {
125  oops::Log::trace() << "ProcessAMIQI: New variable: " << new_variables[inum] <<
126  " not present in input data" << std::endl;
127  }
128 
129  // Check if existing_new_percent_confidence has non-missing values
130  // and update new_percent_confidence.
131 
132  for (size_t idata = 0; idata < nlocs; ++idata) {
133  if (existing_new_percent_confidence[idata] != missing) {
134  if (new_percent_confidence[inum][idata] == missing) {
135  new_percent_confidence[inum][idata] =
136  existing_new_percent_confidence[idata];
137  } else {
138  oops::Log::trace() << "[WARN] New variable (created from new BUFR data)" << "\n"
139  "[WARN] already has value in old BUFR format" << "\n"
140  "[WARN] new BUFR: " <<
141  new_percent_confidence[inum][idata] << "\n"
142  "[WARN] old BUFR: " <<
143  existing_new_percent_confidence[idata] << "\n";
144  }
145  }
146  }
147  // write to new or existing QI vectors
148  obsdb_.put_db("MetaData",
149  new_variables[inum],
150  new_percent_confidence[inum]);
151  }
152  }
153 }
154 
155 // -----------------------------------------------------------------------------
156 
157 void ProcessAMVQI::print(std::ostream & os) const {
158  os << "ProcessAMVQI filter" << parameters_ << std::endl;
159 }
160 
161 // -----------------------------------------------------------------------------
162 
163 } // namespace ufo
Base class for UFO observation processors (including QC filters).
ioda::ObsSpace & obsdb_
ProcessAMVQI(ioda::ObsSpace &obsdb, const Parameters_ &parameters, std::shared_ptr< ioda::ObsDataVector< int >> flags, std::shared_ptr< ioda::ObsDataVector< float >> obserr)
Definition: ProcessAMVQI.cc:24
void doFilter() const override
A filter to convert new BUFR formatted data into variables with names corressponding to the wind gene...
Definition: ProcessAMVQI.cc:54
void print(std::ostream &) const override
Parameters_ parameters_
Definition: ProcessAMVQI.h:73
~ProcessAMVQI() override
Definition: ProcessAMVQI.cc:35
Parameters controlling the operation of the ProcessAMVQI filter.
Definition: ProcessAMVQI.h:25
oops::RequiredParameter< size_t > number_of_apps
How many generating applications to search for.
Definition: ProcessAMVQI.h:30
constexpr int missing
Definition: QCflags.h:20
integer function nlocs(this)
Return the number of observational locations in this Locations object.
Definition: RunCRTM.h:27