UFO
Gaussian_Thinning.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2019 UCAR
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 <cmath>
12 #include <string>
13 #include <utility>
14 #include <vector>
15 
16 #include "eckit/config/Configuration.h"
17 #include "ioda/ObsDataVector.h"
18 #include "ioda/ObsSpace.h"
19 #include "oops/base/Variables.h"
20 #include "oops/util/DateTime.h"
21 #include "oops/util/Duration.h"
22 #include "oops/util/Logger.h"
23 #include "oops/util/missingValues.h"
25 #include "ufo/utils/Constants.h"
32 
33 namespace ufo {
34 
35 namespace {
36 
37 ///
38 /// \brief Gather data from all tasks and deliver the combined data to all tasks.
39 ///
40 /// \returns A vector that contains the elements of \p v from process 0 followed by the elements
41 /// of \p v from process 1 etc.
42 ///
43 template <typename T>
44 std::vector<T> allGatherv(const eckit::mpi::Comm &comm, const std::vector<T> &v) {
45  eckit::mpi::Buffer<T> buffer(comm.size());
46  comm.allGatherv(v.begin(), v.end(), buffer);
47  return buffer.buffer;
48 }
49 
50 } // namespace
51 
52 // -----------------------------------------------------------------------------
53 
54 Gaussian_Thinning::Gaussian_Thinning(ioda::ObsSpace & obsdb, const eckit::Configuration & config,
55  std::shared_ptr<ioda::ObsDataVector<int> > flags,
56  std::shared_ptr<ioda::ObsDataVector<float> > obserr)
57  : FilterBase(obsdb, config, flags, obserr)
58 {
59  oops::Log::debug() << "Gaussian_Thinning: config = " << config_ << std::endl;
60 
62  options_->deserialize(config);
63 }
64 
65 // -----------------------------------------------------------------------------
66 
67 // Required for the correct destruction of options_.
69 {}
70 
71 // -----------------------------------------------------------------------------
72 
73 void Gaussian_Thinning::applyFilter(const std::vector<bool> & apply,
74  const Variables & filtervars,
75  std::vector<std::vector<bool>> & flagged) const {
76  ParallelObsDistribution obsDistribution(obsdb_);
77 
78  std::vector<size_t> validObsIds = getValidObservationIds(apply, obsDistribution);
79 
80  RecursiveSplitter splitter(validObsIds.size());
81  std::vector<float> distancesToBinCenter(validObsIds.size(), 0.f);
82  std::unique_ptr<DistanceCalculator> distanceCalculator = makeDistanceCalculator(*options_);
83 
84  groupObservationsByCategory(validObsIds, obsDistribution, splitter);
85  groupObservationsByPressure(validObsIds, *distanceCalculator, obsDistribution,
86  splitter, distancesToBinCenter);
87  groupObservationsByTime(validObsIds, *distanceCalculator, obsDistribution,
88  splitter, distancesToBinCenter);
89  groupObservationsBySpatialLocation(validObsIds, *distanceCalculator, obsDistribution,
90  splitter, distancesToBinCenter);
91 
92  const std::vector<bool> isThinned = identifyThinnedObservations(
93  validObsIds, obsDistribution, splitter, distancesToBinCenter);
94  flagThinnedObservations(isThinned, obsDistribution, flagged);
95 
96  if (filtervars.size() != 0) {
97  oops::Log::trace() << "Gaussian_Thinning: flagged? = " << flagged[0] << std::endl;
98  }
99 }
100 
101 // -----------------------------------------------------------------------------
102 
104  const std::vector<bool> & apply, const ParallelObsDistribution &obsDistribution) const {
105  const size_t rank = obsdb_.comm().rank();
106  const size_t obsIdDisplacement = obsDistribution.localObsIdDisplacements()[rank];
107  std::vector<size_t> validObsIds;
108  for (size_t obsId = 0; obsId < apply.size(); ++obsId)
109  if (apply[obsId] && (*flags_)[0][obsId] == QCflags::pass)
110  validObsIds.push_back(obsIdDisplacement + obsId);
111 
112  return allGatherv(obsdb_.comm(), validObsIds);
113 }
114 
115 // -----------------------------------------------------------------------------
116 
117 std::unique_ptr<DistanceCalculator> Gaussian_Thinning::makeDistanceCalculator(
118  const GaussianThinningParameters &options) {
119  switch (options.distanceNorm.value()) {
121  return std::unique_ptr<DistanceCalculator>(new GeodesicDistanceCalculator());
123  return std::unique_ptr<DistanceCalculator>(new MaxNormDistanceCalculator());
124  }
125  throw eckit::BadParameter("Unrecognized distance norm", Here());
126 }
127 
128 // -----------------------------------------------------------------------------
129 
131  const std::vector<size_t> &validObsIds,
132  const DistanceCalculator &distanceCalculator,
133  const ParallelObsDistribution &obsDistribution,
134  RecursiveSplitter &splitter,
135  std::vector<float> &distancesToBinCenter) const {
136  boost::optional<SpatialBinSelector> binSelector = makeSpatialBinSelector(*options_);
137  if (binSelector == boost::none)
138  return;
139 
140  oops::Log::debug() << "Gaussian_Thinning: zonal band width (degrees) = "
141  << binSelector->latitudeBinWidth() << std::endl;
142  oops::Log::debug() << "Gaussian_Thinning: number of horizontal bins = "
143  << binSelector->totalNumBins() << std::endl;
144 
145  const std::vector<float> lat = getGlobalVariableValues<float>(
146  obsdb_, obsDistribution, "latitude", "MetaData");
147  std::vector<float> lon = getGlobalVariableValues<float>(
148  obsdb_, obsDistribution, "longitude", "MetaData");
149  // Longitudes will typically be either in the [-180, 180] degree range or in the [0, 360]
150  // degree range. The spatial bin selector is written with the latter convention in mind,
151  // so let's shift any negative longitudes up by 360 degrees.
152  for (float &longitude : lon)
153  if (longitude < 0)
154  longitude += 360;
155 
156  std::vector<size_t> latBins;
157  std::vector<size_t> lonBins;
158  latBins.reserve(validObsIds.size());
159  lonBins.reserve(validObsIds.size());
160  for (size_t obsId : validObsIds) {
161  const size_t latBin = binSelector->latitudeBin(lat[obsId]);
162  latBins.push_back(latBin);
163  lonBins.push_back(binSelector->longitudeBin(latBin, lon[obsId]));
164  }
165  splitter.groupBy(latBins);
166  splitter.groupBy(lonBins);
167 
168  oops::Log::debug() << "Gaussian_Thinning: latitudes = " << lat << std::endl;
169  oops::Log::debug() << "Gaussian_Thinning: longitudes = " << lon << std::endl;
170  oops::Log::debug() << "Gaussian_Thinning: lat bins = " << latBins << std::endl;
171  oops::Log::debug() << "Gaussian_Thinning: lon bins = " << lonBins << std::endl;
172 
173  for (size_t validObsIndex = 0; validObsIndex < validObsIds.size(); ++validObsIndex) {
174  const size_t obsId = validObsIds[validObsIndex];
175  float component = distanceCalculator.spatialDistanceComponent(
176  lat[obsId], lon[obsId],
177  binSelector->latitudeBinCenter(latBins[validObsIndex]),
178  binSelector->longitudeBinCenter(latBins[validObsIndex], lonBins[validObsIndex]),
179  binSelector->inverseLatitudeBinWidth(),
180  binSelector->inverseLongitudeBinWidth(latBins[validObsIndex]));
181  distancesToBinCenter[validObsIndex] = distanceCalculator.combineDistanceComponents(
182  distancesToBinCenter[validObsIndex], component);
183  }
184 }
185 
186 // -----------------------------------------------------------------------------
187 
188 boost::optional<SpatialBinSelector> Gaussian_Thinning::makeSpatialBinSelector(
189  const GaussianThinningParameters &options) {
190  if (options.horizontalMesh <= 0)
191  return boost::none;
192 
193  oops::Log::debug() << "Gaussian_Thinning: requested horizontal bin size (km) = "
194  << options.horizontalMesh << std::endl;
195 
198 
199  const float earthRadius = Constants::mean_earth_rad; // km
200  const float meridianLength = M_PI * earthRadius;
201  const float tentativeNumLatBins = meridianLength / options.horizontalMesh;
202  const int numLatBins = SpatialBinSelector::roundNumBins(tentativeNumLatBins, roundingMode);
203 
204  if (options.useReducedHorizontalGrid) {
205  // Use fewer bins at high latitudes
206  return SpatialBinSelector(numLatBins, roundingMode);
207  } else {
208  // Use the same number of bins at all latitudes
209  const int equatorToMeridianLengthRatio = 2;
210  return SpatialBinSelector(numLatBins, equatorToMeridianLengthRatio * numLatBins);
211  }
212 }
213 
214 // -----------------------------------------------------------------------------
215 
217  const std::vector<size_t> &validObsIds,
218  const ParallelObsDistribution &obsDistribution,
219  RecursiveSplitter &splitter) const {
220  boost::optional<Variable> categoryVariable = options_->categoryVariable;
221  if (categoryVariable == boost::none)
222  return;
223 
224  const std::vector<int> category = getGlobalVariableValues<int>(
225  obsdb_, obsDistribution, categoryVariable.get().variable(), categoryVariable.get().group());
226 
227  std::vector<int> validObsCategories(validObsIds.size());
228  for (size_t validObsIndex = 0; validObsIndex < validObsIds.size(); ++validObsIndex)
229  validObsCategories[validObsIndex] = category[validObsIds[validObsIndex]];
230  splitter.groupBy(validObsCategories);
231 }
232 
233 // -----------------------------------------------------------------------------
234 
236  const std::vector<size_t> &validObsIds,
237  const DistanceCalculator &distanceCalculator,
238  const ParallelObsDistribution &obsDistribution,
239  RecursiveSplitter &splitter,
240  std::vector<float> &distancesToBinCenter) const {
241  boost::optional<EquispacedBinSelector> binSelector = makePressureBinSelector(*options_);
242  if (binSelector == boost::none)
243  return;
244 
245  oops::Log::debug() << "Gaussian_Thinning: number of vertical bins = "
246  << binSelector->numBins() << std::endl;
247 
248  const std::vector<float> pres = getGlobalVariableValues<float>(
249  obsdb_, obsDistribution, "air_pressure", "MetaData");
250 
251  std::vector<size_t> bins;
252  bins.reserve(validObsIds.size());
253  for (size_t obsId : validObsIds)
254  {
255  bins.push_back(binSelector->bin(pres[obsId]));
256  }
257  splitter.groupBy(bins);
258 
259  oops::Log::debug() << "Gaussian_Thinning: pressures = " << pres << std::endl;
260  oops::Log::debug() << "Gaussian_Thinning: pressure bins = " << bins << std::endl;
261 
262  for (size_t validObsIndex = 0; validObsIndex < validObsIds.size(); ++validObsIndex) {
263  const size_t obsId = validObsIds[validObsIndex];
264  const float component = distanceCalculator.nonspatialDistanceComponent(
265  pres[obsId], binSelector->binCenter(bins[validObsIndex]),
266  binSelector->inverseBinWidth());
267  distancesToBinCenter[validObsIndex] = distanceCalculator.combineDistanceComponents(
268  distancesToBinCenter[validObsIndex], component);
269  }
270 }
271 
272 // -----------------------------------------------------------------------------
273 
274 boost::optional<EquispacedBinSelector> Gaussian_Thinning::makePressureBinSelector(
275  const GaussianThinningParameters &options) {
276  if (options.verticalMesh <= 0)
277  return boost::none;
278 
279  const int numVerticalBins = std::max(
280  1,
281  static_cast<int>(std::ceil((options.verticalMax - options.verticalMin) /
282  options.verticalMesh)));
283  // Adjust verticalMax upwards to make the range of pressures
284  // evenly divisible into bins of width verticalMesh.
285  const float adjustedVerticalMax = options.verticalMin + numVerticalBins * options.verticalMesh;
286 
287  oops::Log::debug() << "Gaussian_Thinning: number of vertical bins = "
288  << numVerticalBins << std::endl;
289  return EquispacedBinSelector(options.verticalMin, adjustedVerticalMax, numVerticalBins);
290 }
291 
292 // -----------------------------------------------------------------------------
293 
295  const std::vector<size_t> &validObsIds,
296  const DistanceCalculator &distanceCalculator,
297  const ParallelObsDistribution &obsDistribution,
298  RecursiveSplitter &splitter,
299  std::vector<float> &distancesToBinCenter) const {
300  util::DateTime timeOffset;
301  boost::optional<EquispacedBinSelector> binSelector = makeTimeBinSelector(*options_, timeOffset);
302  if (binSelector == boost::none)
303  return;
304 
305  oops::Log::debug() << "Gaussian_Thinning: number of time bins = "
306  << binSelector->numBins() << std::endl;
307 
308  const std::vector<util::DateTime> times = getGlobalVariableValues<util::DateTime>(
309  obsdb_, obsDistribution, "datetime", "MetaData");
310 
311  std::vector<size_t> bins;
312  bins.reserve(validObsIds.size());
313  for (size_t obsId : validObsIds)
314  {
315  bins.push_back(binSelector->bin((times[obsId] - timeOffset).toSeconds()));
316  }
317  splitter.groupBy(bins);
318 
319  oops::Log::debug() << "Gaussian_Thinning: times = ";
320  eckit::__print_list(oops::Log::debug(), times, eckit::VectorPrintSimple());
321  oops::Log::debug() << std::endl;
322  oops::Log::debug() << "Gaussian_Thinning: time bins = " << bins << std::endl;
323 
324  for (size_t validObsIndex = 0; validObsIndex < validObsIds.size(); ++validObsIndex) {
325  const size_t obsId = validObsIds[validObsIndex];
326  const float component = distanceCalculator.nonspatialDistanceComponent(
327  (times[obsId] - timeOffset).toSeconds(),
328  binSelector->binCenter(bins[validObsIndex]),
329  binSelector->inverseBinWidth());
330  distancesToBinCenter[validObsIndex] = distanceCalculator.combineDistanceComponents(
331  distancesToBinCenter[validObsIndex], component);
332  }
333 }
334 
335 // -----------------------------------------------------------------------------
336 
337 boost::optional<EquispacedBinSelector> Gaussian_Thinning::makeTimeBinSelector(
338  const GaussianThinningParameters &options, util::DateTime &timeOffset) {
339  if (options.timeMesh.value() == boost::none ||
340  options.timeMin.value() == boost::none ||
341  options.timeMax.value() == boost::none)
342  return boost::none;
343 
344  const util::Duration timeMesh = options.timeMesh.value().get();
345  if (timeMesh.toSeconds() == 0)
346  return boost::none;
347 
348  const util::DateTime timeMin = options.timeMin.value().get();
349  const util::DateTime timeMax = options.timeMax.value().get();
350 
351  oops::Log::debug() << "(timeMax - timeMin).toSeconds() = "
352  << ((timeMax - timeMin).toSeconds()) << std::endl;
353  oops::Log::debug() << "timeMesh.toSeconds() = " << timeMesh.toSeconds() << std::endl;
354 
355  const int numTimeBins = std::max(
356  1,
357  static_cast<int>(std::ceil((timeMax - timeMin).toSeconds() /
358  static_cast<float>(timeMesh.toSeconds()))));
359 
360  // NOTE: the upper bound of the time interval is effectively adjusted upwards
361  // to make space for an integral number of bins of specified width.
362 
363  timeOffset = timeMin;
364  return EquispacedBinSelector(0.0f, numTimeBins * timeMesh.toSeconds(), numTimeBins);
365 }
366 
367 // -----------------------------------------------------------------------------
368 
370  const std::vector<size_t> &validObsIds,
371  const ParallelObsDistribution &obsDistribution,
372  const RecursiveSplitter &splitter,
373  const std::vector<float> &distancesToBinCenter) const {
374 
375  std::function<bool(size_t, size_t)> comparator = makeObservationComparator(
376  validObsIds, distancesToBinCenter, obsDistribution);
377 
378  std::vector<bool> isThinned(obsDistribution.globalObsCount(), false);
379  for (auto group : splitter.multiElementGroups()) {
380  const size_t bestValidObsIndex = *std::min_element(
381  std::begin(group), std::end(group), comparator);
382 
383  for (size_t validObsIndex : group)
384  if (validObsIndex != bestValidObsIndex)
385  isThinned[validObsIds[validObsIndex]] = true;
386  }
387 
388  return isThinned;
389 }
390 
391 // Should return true if the first observation is "better" than the second one.
392 std::function<bool(size_t, size_t)> Gaussian_Thinning::makeObservationComparator(
393  const std::vector<size_t> &validObsIds,
394  const std::vector<float> &distancesToBinCenter,
395  const ParallelObsDistribution &obsDistribution) const
396 {
397  if (options_->priorityVariable.value() == boost::none) {
398  oops::Log::debug() << "priority_variable not found" << std::endl;
399  return [&distancesToBinCenter](size_t validObsIndexA, size_t validObsIndexB) {
400  return distancesToBinCenter[validObsIndexA] < distancesToBinCenter[validObsIndexB];
401  };
402  }
403 
404  const ufo::Variable priorityVariable = options_->priorityVariable.value().get();
405 
406  const std::vector<int> priorities = getGlobalVariableValues<int>(
407  obsdb_, obsDistribution, priorityVariable.variable(), priorityVariable.group());
408 
409  oops::Log::debug() << "priorities = " << priorities << std::endl;
410 
411  // TODO(wsmigaj): In C++14, use move capture for 'priorities'.
412  return [priorities, &validObsIds, &distancesToBinCenter]
413  (size_t validObsIndexA, size_t validObsIndexB) {
414  // Prefer observations with large priorities and small distances
415  return std::make_pair(-priorities[validObsIds[validObsIndexA]],
416  distancesToBinCenter[validObsIndexA]) <
417  std::make_pair(-priorities[validObsIds[validObsIndexB]],
418  distancesToBinCenter[validObsIndexB]);
419  };
420 }
421 
422 // -----------------------------------------------------------------------------
423 
425  const std::vector<bool> & isThinned,
426  const ParallelObsDistribution &obsDistribution,
427  std::vector<std::vector<bool>> & flagged) const {
428  const size_t rank = obsdb_.comm().rank();
429  const size_t displacement = obsDistribution.localObsIdDisplacements()[rank];
430  for (std::vector<bool> & variableFlagged : flagged) {
431  ASSERT(obsDistribution.localObsCounts()[rank] == variableFlagged.size());
432  for (size_t localObsId = 0; localObsId < variableFlagged.size(); ++localObsId) {
433  const size_t globalObsId = displacement + localObsId;
434  if (isThinned[globalObsId])
435  variableFlagged[localObsId] = true;
436  }
437  }
438 }
439 
440 // -----------------------------------------------------------------------------
441 
442 void Gaussian_Thinning::print(std::ostream & os) const {
443  os << "Gaussian_Thinning: config = " << config_ << std::endl;
444 }
445 
446 // -----------------------------------------------------------------------------
447 
448 } // namespace ufo
ufo::Gaussian_Thinning::flagThinnedObservations
void flagThinnedObservations(const std::vector< bool > &isThinned, const ParallelObsDistribution &obsDistribution, std::vector< std::vector< bool > > &flagged) const
Definition: Gaussian_Thinning.cc:424
ufo::Gaussian_Thinning::groupObservationsBySpatialLocation
void groupObservationsBySpatialLocation(const std::vector< size_t > &validObsIds, const DistanceCalculator &distanceCalculator, const ParallelObsDistribution &obsDistribution, RecursiveSplitter &splitter, std::vector< float > &distancesToBinCenter) const
Definition: Gaussian_Thinning.cc:130
ufo::SpatialBinSelector
Represents a partition of a sphere into a number of subsets (bins).
Definition: SpatialBinSelector.h:25
ufo::GaussianThinningParameters::distanceNorm
oops::Parameter< DistanceNorm > distanceNorm
Definition: GaussianThinningParameters.h:124
ufo::ParallelObsDistribution
Describes how observations in an ObsSpace are distributed across MPI processes.
Definition: src/ufo/utils/ParallelObsDistribution.h:19
ufo::QCflags::pass
constexpr int pass
Definition: QCflags.h:14
ufo::Variables
Definition: src/ufo/filters/Variables.h:24
ufo::ParallelObsDistribution::globalObsCount
size_t globalObsCount() const
Return the total number of observations held by all MPI processes.
Definition: src/ufo/utils/ParallelObsDistribution.h:26
ufo::SpatialBinSelector::roundNumBins
static IndexType roundNumBins(float idealNumBins, SpatialBinCountRoundingMode roundingMode)
Return idealNumBins rounded to a positive integer according to the rounding strategy roundingMode.
Definition: SpatialBinSelector.cc:51
ufo::RecursiveSplitter::multiElementGroups
MultiElementGroupRange multiElementGroups() const
Return the range of equivalence classes consisting of more than one element.
Definition: src/ufo/utils/RecursiveSplitter.h:293
ufo::Gaussian_Thinning::applyFilter
void applyFilter(const std::vector< bool > &, const Variables &, std::vector< std::vector< bool >> &) const override
Definition: Gaussian_Thinning.cc:73
ufo_radiancerttov_utils_mod::debug
logical, public debug
Definition: ufo_radiancerttov_utils_mod.F90:100
ufo::FilterBase::obsdb_
ioda::ObsSpace & obsdb_
Definition: FilterBase.h:59
ufo::GaussianThinningParameters::verticalMax
oops::Parameter< float > verticalMax
Definition: GaussianThinningParameters.h:89
ufo::Gaussian_Thinning::identifyThinnedObservations
std::vector< bool > identifyThinnedObservations(const std::vector< size_t > &validObsIds, const ParallelObsDistribution &obsDistribution, const RecursiveSplitter &splitter, const std::vector< float > &distancesToBinCenter) const
Definition: Gaussian_Thinning.cc:369
ufo::FilterBase
FilterBase: Base class for UFO QC filters.
Definition: FilterBase.h:42
ufo::RecursiveSplitter
Partitions an array into groups of elements equivalent according to certain criteria.
Definition: src/ufo/utils/RecursiveSplitter.h:63
ufo::GaussianThinningParameters::roundHorizontalBinCountToNearest
oops::Parameter< bool > roundHorizontalBinCountToNearest
Definition: GaussianThinningParameters.h:76
EquispacedBinSelector.h
ufo::GaussianThinningParameters::verticalMin
oops::Parameter< float > verticalMin
Lower bound of the pressure interval split into cells of size vertical_mesh.
Definition: GaussianThinningParameters.h:85
ufo
Definition: RunCRTM.h:27
ufo::DistanceNorm::MAXIMUM
@ MAXIMUM
ufo::GaussianThinningParameters::useReducedHorizontalGrid
oops::Parameter< bool > useReducedHorizontalGrid
Definition: GaussianThinningParameters.h:69
ufo::SpatialBinCountRoundingMode::NEAREST
@ NEAREST
ufo::Gaussian_Thinning::~Gaussian_Thinning
~Gaussian_Thinning() override
Definition: Gaussian_Thinning.cc:68
ufo::Constants::mean_earth_rad
static constexpr double mean_earth_rad
Definition: Constants.h:39
ufo::GaussianThinningParameters::horizontalMesh
oops::Parameter< float > horizontalMesh
Definition: GaussianThinningParameters.h:66
ufo::ParallelObsDistribution::localObsCounts
const std::vector< int > & localObsCounts() const
Return a vector whose ith element is the number of observations held by the MPI process with rank i.
Definition: src/ufo/utils/ParallelObsDistribution.h:33
ufo::Variables::size
size_t size() const
Definition: Variables.cc:92
ufo::RecursiveSplitter::groupBy
void groupBy(const std::vector< size_t > &categories)
Split existing equivalence classes according to a new criterion.
Definition: src/ufo/utils/RecursiveSplitter.h:275
Gaussian_Thinning.h
ufo::ParallelObsDistribution::localObsIdDisplacements
const std::vector< int > & localObsIdDisplacements() const
Return a vector whose ith element is the total number of observations held by the MPI processes with ...
Definition: src/ufo/utils/ParallelObsDistribution.h:40
ufo::FilterBase::flags_
std::shared_ptr< ioda::ObsDataVector< int > > flags_
Definition: FilterBase.h:61
ufo::Gaussian_Thinning::makeDistanceCalculator
static std::unique_ptr< DistanceCalculator > makeDistanceCalculator(const GaussianThinningParameters &options)
Definition: Gaussian_Thinning.cc:117
SpatialBinSelector.h
ufo::GaussianThinningParameters
Options controlling the operation of the Gaussian_Thinning filter.
Definition: GaussianThinningParameters.h:54
ufo::Gaussian_Thinning::Gaussian_Thinning
Gaussian_Thinning(ioda::ObsSpace &obsdb, const eckit::Configuration &config, std::shared_ptr< ioda::ObsDataVector< int > > flags, std::shared_ptr< ioda::ObsDataVector< float > > obserr)
Definition: Gaussian_Thinning.cc:54
ufo::Variable::group
const std::string & group() const
Definition: Variable.cc:117
GaussianThinningParameters.h
ufo::GaussianThinningParameters::verticalMesh
oops::Parameter< float > verticalMesh
Definition: GaussianThinningParameters.h:83
ufo::SpatialBinCountRoundingMode::DOWN
@ DOWN
ufo::Variable::variable
const std::string & variable() const
Definition: Variable.cc:100
ufo::GaussianThinningParameters::timeMin
oops::OptionalParameter< util::DateTime > timeMin
Definition: GaussianThinningParameters.h:98
ufo::Gaussian_Thinning::options_
std::unique_ptr< GaussianThinningParameters > options_
Definition: Gaussian_Thinning.h:128
ioda::ObsDataVector< int >
ufo::Gaussian_Thinning::makePressureBinSelector
static boost::optional< EquispacedBinSelector > makePressureBinSelector(const GaussianThinningParameters &options)
Definition: Gaussian_Thinning.cc:274
ufo::Gaussian_Thinning::groupObservationsByPressure
void groupObservationsByPressure(const std::vector< size_t > &validObsIds, const DistanceCalculator &distanceCalculator, const ParallelObsDistribution &obsDistribution, RecursiveSplitter &splitter, std::vector< float > &distancesToBinCenter) const
Definition: Gaussian_Thinning.cc:235
ufo::Gaussian_Thinning::makeSpatialBinSelector
static boost::optional< SpatialBinSelector > makeSpatialBinSelector(const GaussianThinningParameters &options)
Definition: Gaussian_Thinning.cc:188
ufo::FilterBase::config_
const eckit::LocalConfiguration config_
Definition: FilterBase.h:60
ufo::GaussianThinningParameters::timeMax
oops::OptionalParameter< util::DateTime > timeMax
Definition: GaussianThinningParameters.h:102
ParallelObsDistribution.h
ufo::EquispacedBinSelector
Represents a set of consecutive intervals (bins) of the same width.
Definition: EquispacedBinSelector.h:22
ufo::Gaussian_Thinning::makeTimeBinSelector
static boost::optional< EquispacedBinSelector > makeTimeBinSelector(const GaussianThinningParameters &options, util::DateTime &timeOffset)
Definition: Gaussian_Thinning.cc:337
GeodesicDistanceCalculator.h
ufo::Gaussian_Thinning::print
void print(std::ostream &) const override
Definition: Gaussian_Thinning.cc:442
ufo::DistanceNorm::GEODESIC
@ GEODESIC
ufo::MaxNormDistanceCalculator
Definition: MaxNormDistanceCalculator.h:22
ufo::DistanceCalculator::combineDistanceComponents
virtual float combineDistanceComponents(float componentA, float componentB) const =0
Constants.h
ufo::Gaussian_Thinning::getValidObservationIds
std::vector< size_t > getValidObservationIds(const std::vector< bool > &apply, const ParallelObsDistribution &obsDistribution) const
Definition: Gaussian_Thinning.cc:103
ufo::GaussianThinningParameters::timeMesh
oops::OptionalParameter< util::Duration > timeMesh
Definition: GaussianThinningParameters.h:95
ufo::Gaussian_Thinning::groupObservationsByCategory
void groupObservationsByCategory(const std::vector< size_t > &validObsIds, const ParallelObsDistribution &obsDistribution, RecursiveSplitter &splitter) const
Definition: Gaussian_Thinning.cc:216
ufo::Variable
Definition: Variable.h:23
MaxNormDistanceCalculator.h
ufo::DistanceCalculator::spatialDistanceComponent
virtual float spatialDistanceComponent(float obsLatitude, float obsLongitude, float latitudeBinCenter, float longitudeBinCenter, float inverseLatitudeBinWidth, float inverseLongitudeBinWidth) const =0
ufo::Gaussian_Thinning::groupObservationsByTime
void groupObservationsByTime(const std::vector< size_t > &validObsIds, const DistanceCalculator &distanceCalculator, const ParallelObsDistribution &obsDistribution, RecursiveSplitter &splitter, std::vector< float > &distancesToBinCenter) const
Definition: Gaussian_Thinning.cc:294
RecursiveSplitter.h
ufo::DistanceCalculator
Calculates distances between observations and centres of bins used during thinning.
Definition: DistanceCalculator.h:33
ufo::Gaussian_Thinning::makeObservationComparator
std::function< bool(size_t, size_t)> makeObservationComparator(const std::vector< size_t > &validObsIds, const std::vector< float > &distancesToBinCenter, const ParallelObsDistribution &obsDistribution) const
Definition: Gaussian_Thinning.cc:392
ufo::anonymous_namespace{Gaussian_Thinning.cc}::allGatherv
std::vector< T > allGatherv(const eckit::mpi::Comm &comm, const std::vector< T > &v)
Gather data from all tasks and deliver the combined data to all tasks.
Definition: Gaussian_Thinning.cc:44
ufo::SpatialBinCountRoundingMode
SpatialBinCountRoundingMode
Definition: SpatialBinSelector.h:19
ufo::DistanceCalculator::nonspatialDistanceComponent
virtual float nonspatialDistanceComponent(float obs, float binCenter, float inverseBinWidth) const =0
ufo::GeodesicDistanceCalculator
Definition: GeodesicDistanceCalculator.h:22