ReFRACtor
empirical_orthogonal_function.cc
Go to the documentation of this file.
2 #include "linear_interpolate.h"
3 #include <boost/make_shared.hpp>
4 using namespace FullPhysics;
5 using namespace blitz;
6 
7 #ifdef HAVE_LUA
8 #include "register_lua.h"
9 // Luabind is restricted to 10 arguments in a function. The
10 // constructor for EmpiricalOrthogonalFunction takes too many. As an easy
11 // workaround, just stuff a number of the values into an array.
13 bool Used_flag,
14 const HdfFile& Hdf_static_input,
15 const ArrayWithUnit<double, 1>& Uncertainty,
16 const std::string& Band_name,
17 const std::string& Hdf_group,
18 const blitz::Array<double, 1>& Val)
19 {
20  return boost::make_shared<EmpiricalOrthogonalFunction>
21  (Val(0), Used_flag, Hdf_static_input, Uncertainty,
22  static_cast<int>(Val(1)), static_cast<int>(Val(2)),
23  static_cast<int>(Val(3)),
24  Band_name, Hdf_group, Val(4));
25 }
27 .def(luabind::constructor<double, bool, const Dispersion&, const HdfFile&,
28  int, int, int, const std::string&, const std::string&>())
29 .def(luabind::constructor<double, bool, const HdfFile&,
30  int, int, int, const std::string&, const std::string&>())
31 .scope
32 [
33  luabind::def("create", &eof_create)
34 ]
36 #endif
37 
38 //-----------------------------------------------------------------------
68 //-----------------------------------------------------------------------
69 
71 (double Coeff,
72  bool Used_flag,
73  const Dispersion& Disp,
74  const HdfFile& Hdf_static_input,
75  int Spec_index,
76  int Sounding_number,
77  int Order,
78  const std::string& Band_name,
79  const std::string& Hdf_group)
81  band_name(Band_name),
82  hdf_group(Hdf_group),
83  order_(Order),
84  sounding_number_(Sounding_number),
85  eof_scale_uncertainty_(false),
86  scale_to_stddev_(-1)
87 {
88  using namespace H5;
89  std::string fldname = hdf_group + "/EOF_"
90  + boost::lexical_cast<std::string>(Order) +
91  "_waveform_"
92  + boost::lexical_cast<std::string>(Spec_index + 1);
94  // Determine if we have a sounding number index.
95  DataSet d = Hdf_static_input.h5_file().openDataSet(fldname);
96  DataSpace ds = d.getSpace();
97  if(ds.getSimpleExtentNdims() == 3) {
98  ArrayWithUnit<double, 3> full_table =
99  Hdf_static_input.read_field_with_unit<double, 3>(fldname);
100  table.units = full_table.units;
101  table.value.reference(full_table.value(Sounding_number, Range::all(),
102  Range::all()));
103  eof_depend_on_sounding_number_ = true;
104  } else {
105  table = Hdf_static_input.read_field_with_unit<double, 2>(fldname);
106  eof_depend_on_sounding_number_ = false;
107  }
108  // See the we have the Wave Units. If not, we default to
109  // "cm^-1". This is for backwards compatibility.
110  Unit wave_unit("cm^-1");
111  if(Hdf_static_input.has_attribute(fldname + "/WaveUnits"))
112  wave_unit = Unit(Hdf_static_input.read_attribute<std::string>(fldname + "/WaveUnits"));
113 
114  // Separate columns
115  Array<double, 1> wn(table.value(Range::all(), 0));
116  Array<double, 1> waveform(table.value(Range::all(), 1));
117  // Set up interpolation
119  waveform_interpolate(wn.begin(), wn.end(), waveform.begin(),
121  Array<double, 1> pixel_grid = Disp.pixel_grid().convert_wave(wave_unit);
122  eof_.units = table.units;
123  eof_.value.resize(pixel_grid.shape());
124  for(int i = 0; i < pixel_grid.rows(); ++i)
125  eof_.value(i) = waveform_interpolate(pixel_grid(i));
126 }
127 
128 //-----------------------------------------------------------------------
160 //-----------------------------------------------------------------------
161 
163 (double Coeff,
164  bool Used_flag,
165  const HdfFile& Hdf_static_input,
166  int Spec_index,
167  int Sounding_number,
168  int Order,
169  const std::string& Band_name,
170  const std::string& Hdf_group)
172  band_name(Band_name),
173  hdf_group(Hdf_group),
174  order_(Order),
175  sounding_number_(Sounding_number),
176  eof_scale_uncertainty_(false),
177  scale_to_stddev_(-1)
178 {
179  using namespace H5;
180  std::string fldname = hdf_group + "/EOF_"
181  + boost::lexical_cast<std::string>(Order) +
182  "_waveform_"
183  + boost::lexical_cast<std::string>(Spec_index + 1);
184  // Determine if we have a sounding number index.
185  DataSet d = Hdf_static_input.h5_file().openDataSet(fldname);
186  DataSpace ds = d.getSpace();
187  if(ds.getSimpleExtentNdims() == 2) {
188  ArrayWithUnit<double, 2> full_table =
189  Hdf_static_input.read_field_with_unit<double, 2>(fldname);
190  eof_.units = full_table.units;
191  eof_.value.reference(full_table.value(Sounding_number, Range::all()));
192  eof_depend_on_sounding_number_ = true;
193  } else {
194  eof_ = Hdf_static_input.read_field_with_unit<double, 1>(fldname);
195  eof_depend_on_sounding_number_ = false;
196  }
197 }
198 
199 //-----------------------------------------------------------------------
241 //-----------------------------------------------------------------------
242 
244 (double Coeff,
245  bool Used_flag,
246  const HdfFile& Hdf_static_input,
247  const ArrayWithUnit<double, 1>& Uncertainty,
248  int Spec_index,
249  int Sounding_number,
250  int Order,
251  const std::string& Band_name,
252  const std::string& Hdf_group,
253  double Scale_to_stddev)
255  band_name(Band_name),
256  hdf_group(Hdf_group),
257  order_(Order),
258  sounding_number_(Sounding_number),
259  eof_scale_uncertainty_(true),
260  scale_to_stddev_(Scale_to_stddev)
261 {
262  using namespace H5;
263  std::string fldname = hdf_group + "/EOF_"
264  + boost::lexical_cast<std::string>(Order) +
265  "_waveform_"
266  + boost::lexical_cast<std::string>(Spec_index + 1);
267  // Determine if we have a sounding number index.
268  DataSet d = Hdf_static_input.h5_file().openDataSet(fldname);
269  DataSpace ds = d.getSpace();
270  if(ds.getSimpleExtentNdims() == 2) {
271  Array<double, 2> full_table =
272  Hdf_static_input.read_field<double, 2>(fldname);
273  eof_.units = Uncertainty.units;
274  eof_.value.reference(full_table(Sounding_number, Range::all()));
275  eof_depend_on_sounding_number_ = true;
276  } else {
277  eof_.units = Uncertainty.units;
278  eof_.value.reference(Hdf_static_input.read_field<double, 1>(fldname));
279  eof_depend_on_sounding_number_ = false;
280  }
281  eof_.value = eof_.value * Uncertainty.value;
282  // Scale eof so stddev is the given value
283  double s = scale_to_stddev_ / sqrt(sum(sqr(eof_.value - mean(eof_.value))) /
284  (eof_.value.size() - 1));
285  eof_.value = eof_.value * s;
286 }
287 
289  const
290 {
292  (new EmpiricalOrthogonalFunction(coeff.value()(0), used_flag(0),
293  eof_, order_,band_name, hdf_group,
294  sounding_number_,
295  eof_depend_on_sounding_number_));
296 }
297 
299 (const SpectralDomain& Pixel_grid,
300  const std::vector<int>& Pixel_list,
301  SpectralRange& Radiance) const
302 {
303  ArrayWithUnit<double, 1> eofv = eof_.convert(Radiance.units());
304  if(Radiance.data_ad().number_variable() == 0) {
305  for(int i = 0; i < Radiance.data().rows(); ++i) {
306  range_check(Pixel_list[i], 0, eofv.value.rows());
307  Radiance.data()(i) += coeff.value()(0) * eofv.value(Pixel_list[i]);
308  }
309  } else {
310  for(int i = 0; i < Radiance.data_ad().rows(); ++i) {
311  range_check(Pixel_list[i], 0, eofv.value.rows());
312  Radiance.data_ad()(i) = Radiance.data_ad()(i) +
313  coeff(0) * eofv.value(Pixel_list[i]);
314  }
315  }
316 }
317 
318 void EmpiricalOrthogonalFunction::print(std::ostream& Os) const
319 {
320  Os << "EmpiricalOrthogonalFunction:\n"
321  << " Band: " << band_name << "\n"
322  << " HDF group: " << hdf_group << "\n"
323  << " Order: " << order_ << "\n"
324  << " Sounding number: " << sounding_number_ << "\n"
325  << " Depend on sounding number: "
326  << (eof_depend_on_sounding_number_ ? "yes" : "no") << "\n"
327  << " Scale by uncertainty: "
328  << (eof_scale_uncertainty_ ? "yes" : "no") << "\n"
329  << " Scale: " << coeff(0).value() << "\n"
330  << " Fit: "
331  << (used_flag(0) ? "True\n" : "False\n");
332  if(eof_scale_uncertainty_)
333  Os << " Scale to stddev: " << scale_to_stddev_ << "\n";
334 }
virtual SpectralDomain pixel_grid() const =0
Returns as list of grid points for each instrument pixel, and the gradient of the points wrt the stat...
#define range_check(V, Min, Max)
Range check.
Definition: fp_exception.h:140
const Unit s("s", 1.0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0)
EmpiricalOrthogonalFunction(double Coeff, bool Used_flag, const ArrayWithUnit< double, 1 > &Eof_waveform, int Order, const std::string &Band_name, const std::string &Hdf_group="N/A", int Sounding_number=0, bool Eof_depend_on_sounding_number=false)
Constructor.
blitz::Array< T, D > read_field(const std::string &Dataname) const
Read a given field.
Definition: hdf_file.h:564
For different instruments, it is more natural to either work with wavenumbers (e.g., GOSAT) or wavelength (e.g., OCO).
#define REGISTER_LUA_DERIVED_CLASS(X, Y)
Definition: register_lua.h:136
This class applies a empirical orthogonal function (EOF) correction to instrument data...
blitz::Array< T, D > value
This class reads and writes a HDF5 file.
Definition: hdf_file.h:39
Apply value function to a blitz array.
const Unit & units() const
Units of data.
blitz::Array< double, 1 > convert_wave(const Unit &Units) const
Return data as the supplied the units.
int number_variable() const
Definition: array_ad.h:376
We have a number of different spectrums that appear in different parts of the code.
const ArrayAd< double, 1 > & data_ad() const
Underlying data, possibly with a Jacobian.
double sqr(double x)
Libraries such as boost::units allow unit handling where we know the units at compile time...
Definition: unit.h:25
This class calculates the wavenumber for each pixel in a single band of an Instrument.
Definition: dispersion.h:12
blitz::Array< T, D > read_attribute(const std::string &Aname) const
Read the given attribute attached to a group or dataset.
Definition: hdf_file.h:206
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
#define REGISTER_LUA_END()
Definition: register_lua.h:134
def(luabind::constructor< int >()) .def("rows"
ArrayWithUnit< T, D > read_field_with_unit(const std::string &Dataname) const
Read a given field, along with metadata describing the units.
Definition: hdf_file.h:575
H5::H5File & h5_file()
Definition: hdf_file.h:155
bool has_attribute(const std::string &Aname) const
Check to see if a attribute is in the file.
Definition: hdf_file.cc:363
virtual boost::shared_ptr< InstrumentCorrection > clone() const
Clone an InstrumentCorrection object.
ArrayWithUnit< T, D > convert(const Unit &R) const
Convert to the given units.
const blitz::Array< double, 1 > & data() const
Underlying data.
This class models an Instrument correction.
virtual void apply_correction(const SpectralDomain &Pixel_grid, const std::vector< int > &Pixel_list, SpectralRange &Radiance) const
Apply correction to radiance values, in place.
int rows() const
Definition: array_ad.h:368

Copyright © 2017, California Institute of Technology.
ALL RIGHTS RESERVED.
U.S. Government Sponsorship acknowledged.
Generated Fri Aug 24 2018 15:44:08