UFO
ProfileIndices.cc
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 #include <algorithm>
9 #include <utility>
10 
12 
13 namespace ufo {
14  ProfileIndices::ProfileIndices(ioda::ObsSpace &obsdb,
15  const ProfileConsistencyCheckParameters &options,
16  const std::vector <bool> &apply)
17  : obsdb_(obsdb),
18  options_(options),
19  apply_(apply),
20  profileNums_(obsdb.recnum()),
21  profileNumCurrent_(0),
22  profileNumToFind_(0),
23  profIndex_(0)
24  {
25  // If not sorting observations, ensure number of profiles is consistent
26  // with quantity reported by obsdb.
27  // (If sorting is imposed, nothing is assumed about the ordering of the input data
28  // so this validation should not be performed.)
29  if (obsdb_.obs_sort_var().empty() && options_.ValidateTotalNumProf.value()) {
31  }
32 
33  // If sorting observations, point to beginning of record index iterator
34  if (!obsdb_.obs_sort_var().empty() &&
35  obsdb_.obs_sort_order() == "descending") {
36  profidx_current_ = obsdb_.recidx_begin();
37  }
38  }
39 
41  {
42  profileIndices_.clear();
43 
44  // If there are no profiles in the sample, warn and exit
45  if (profileNums_.size() == 0) {
46  oops::Log::debug() << "No profiles found in the sample" << std::endl;
47  return;
48  }
49 
50  // Determine indices in the full sample that correspond to
51  // the profile ID to be found.
52  // The method used to fill the profile indices depends upon the sorting chosen.
53  if (obsdb_.obs_sort_var().empty()) {
54  // If no sorting has been specified just increment indices
56  if (apply_[profIndex_]) {
57  profileIndices_.emplace_back(profIndex_);
58  }
59  profIndex_++;
60  }
61  } else {
62  if (obsdb_.obs_sort_order() == "descending") {
63  // Sort variable (usually pressure) in descending order
64  // Sorted indices for the current profile
65  const std::vector<std::size_t> profidx_sorted = profidx_current_->second;
66  auto it_profidx_sorted = profidx_sorted.begin();
68  if (apply_[profIndex_]) {
69  profileIndices_.emplace_back(*it_profidx_sorted);
70  }
71  profIndex_++;
72  std::advance(it_profidx_sorted, 1);
73  }
74  } else {
75  // This will not work for pressures in ascending order
76  throw eckit::BadParameter("sort order is ascending.", Here());
77  }
78  }
79 
80  // Number of levels to which QC checks should be applied
81  numLevelsToCheck_ = static_cast<int> (profileIndices_.size());
82 
83  if (numLevelsToCheck_ > 0) {
84  oops::Log::debug() << "First and last profile indices: " << profileIndices_.front()
85  << ", " << profileIndices_.back() << std::endl;
86  }
87 
88  // Replace with maxlev if defined (a legacy of the OPS code)
89  if (options_.maxlev.value() != boost::none) {
90  numLevelsToCheck_ = std::min(options_.maxlev.value().get(), numLevelsToCheck_);
91  }
92 
93  // Update counters and iterators (if used)
94 
95  // Current profile number
97 
98  // Return value indicates whether or not the end of the entire sample has been reached
99  if (profIndex_ < profileNums_.size()) {
100  // Next profile number to find
102  // Iterator corresponding to next profile
103  if (!obsdb_.obs_sort_var().empty() &&
104  obsdb_.obs_sort_order() == "descending") {
105  std::advance(profidx_current_, 1);
106  }
107  }
108  }
109 
111  // If no sorting is performed on the observations it is possible that
112  // two separate profiles could (inadvertently) have the same value of the group variable.
113  // This would lead to an incorrect value of nrecs.
114  // This routine ensures that nrecs is the same as the actual number of profiles in the sample.
115 
116  size_t profNum = 0;
117  std::vector <size_t> allProfileNums = {0};
118  for (size_t j = 0; j < profileNums_.size(); ++j) {
119  size_t profNum_j = profileNums_[j];
120  if (profNum_j != profNum) {
121  allProfileNums.emplace_back(profNum_j);
122  profNum = profNum_j;
123  }
124  }
125 
126  if (allProfileNums.size() != obsdb_.nrecs()) {
127  throw eckit::BadValue("incorrect number of profiles in unsorted sample", Here());
128  }
129  }
130 } // namespace ufo
ufo::ProfileIndices::profileIndices_
std::vector< size_t > profileIndices_
Indices for this profile.
Definition: ProfileIndices.h:87
ufo_radiancerttov_utils_mod::debug
logical, public debug
Definition: ufo_radiancerttov_utils_mod.F90:100
ProfileIndices.h
ufo::ProfileConsistencyCheckParameters::ValidateTotalNumProf
oops::Parameter< bool > ValidateTotalNumProf
If not sorting observations, ensure number of profiles is consistent.
Definition: ProfileConsistencyCheckParameters.h:48
ufo::ProfileIndices::profileNumCurrent_
size_t profileNumCurrent_
Current profile number in the sample.
Definition: ProfileIndices.h:93
ufo
Definition: RunCRTM.h:27
ufo::ProfileIndices::options_
const ProfileConsistencyCheckParameters & options_
Configurable parameters.
Definition: ProfileIndices.h:72
ufo::ProfileIndices::profileNumToFind_
size_t profileNumToFind_
Next profile number to find in the sample.
Definition: ProfileIndices.h:96
ufo::ProfileIndices::determineProfileIndices
void determineProfileIndices()
Determine indices in entire sample for this profile.
Definition: ProfileIndices.cc:40
ufo::ProfileConsistencyCheckParameters
Options controlling the operation of the ProfileConsistencyChecks filter.
Definition: ProfileConsistencyCheckParameters.h:33
ufo::ProfileIndices::obsdb_
ioda::ObsSpace & obsdb_
Observation database.
Definition: ProfileIndices.h:69
ufo::ProfileIndices::apply_
const std::vector< bool > & apply_
Observations to apply the filter to.
Definition: ProfileIndices.h:75
ufo::ProfileIndices::numLevelsToCheck_
int numLevelsToCheck_
Number of profile levels to which QC checks should be applied.
Definition: ProfileIndices.h:90
ufo::ProfileIndices::profIndex_
size_t profIndex_
Definition: ProfileIndices.h:99
ufo::ProfileIndices::profidx_current_
ProfIdxIter profidx_current_
Iterator pointing to current profile index (initially points to beginning).
Definition: ProfileIndices.h:84
ufo::ProfileIndices::ProfileIndices
ProfileIndices(ioda::ObsSpace &obsdb, const ProfileConsistencyCheckParameters &options, const std::vector< bool > &apply)
Definition: ProfileIndices.cc:14
ufo::ProfileIndices::profileNums_
const std::vector< size_t > profileNums_
Profile numbers for the entire sample.
Definition: ProfileIndices.h:78
ufo::ProfileIndices::validateTotalNumProf
void validateTotalNumProf()
Definition: ProfileIndices.cc:110
ufo::ProfileConsistencyCheckParameters::maxlev
oops::OptionalParameter< int > maxlev
Definition: ProfileConsistencyCheckParameters.h:42