ReFRACtor
ils_convolution.cc
Go to the documentation of this file.
1 #include "ils_convolution.h"
2 #include "hdf_file.h"
3 #include "ostream_pad.h"
4 #include <boost/lexical_cast.hpp>
5 using namespace FullPhysics;
6 using namespace blitz;
7 
8 #ifdef HAVE_LUA
9 #include "register_lua.h"
11 .def(luabind::constructor<const boost::shared_ptr<Dispersion>&,
13 .def(luabind::constructor<const boost::shared_ptr<Dispersion>&,
16 #endif
17 
18 // See base class for description.
19 blitz::Array<double, 1> IlsConvolution::apply_ils
20 (const blitz::Array<double, 1>& Hres_wn,
21  const blitz::Array<double, 1>& Hres_rad,
22  const std::vector<int>& Pixel_list) const
23 {
24  if(Hres_wn.rows() != Hres_rad.rows())
25  throw Exception("wave_number and radiance need to be the same size");
26  Array<double, 1> disp_wn(disp->pixel_grid().data());
27  ArrayAd<double, 1> response;
28  Array<double,1> res((int) Pixel_list.size());
29  for(int i = 0; i < res.rows(); ++i) {
30  // Find the range of Hres_wn that lie within
31  // wn_center +- ils_half_width
32 
33  double wn_center = disp_wn(Pixel_list[i]);
34  Array<double, 1>::const_iterator itmin =
35  std::lower_bound(Hres_wn.begin(), Hres_wn.end(),
36  wn_center - ils_half_width_.value);
37  Array<double, 1>::const_iterator itmax =
38  std::lower_bound(Hres_wn.begin(), Hres_wn.end(),
39  wn_center + ils_half_width_.value);
40  int jmin = (itmin == Hres_wn.end() ? Hres_wn.rows() - 1 : itmin.position()(0));
41  int jmax = (itmax == Hres_wn.end() ? Hres_wn.rows() - 1 : itmax.position()(0));
42  Range r(jmin, jmax);
43 
44  // Convolve with response
45 
46  ils_func->ils(wn_center, Hres_wn(r), response);
47  Array<double, 1> conv(response.value() * Hres_rad(r));
48 
49  // And integrate to get pixel value.
50 
51  res(i) = integrate(Hres_wn(r), conv) /
52  integrate(Hres_wn(r), response.value());
53  }
54  return res;
55 }
56 
57 
58 //-----------------------------------------------------------------------
60 //-----------------------------------------------------------------------
61 
62 double IlsConvolution::integrate(const blitz::Array<double, 1>& x,
63  const blitz::Array<double, 1>& y) const
64 {
65  double res = 0;
66  for(int i = 1; i < x.rows(); ++i)
67  res += (x(i) - x(i - 1)) * (y(i) + y(i - 1));
68  return res / 2.0;
69 }
70 
71 //-----------------------------------------------------------------------
73 //-----------------------------------------------------------------------
74 
75 AutoDerivative<double> IlsConvolution::integrate(const blitz::Array<double, 1>& x,
76  const ArrayAd<double, 1>& y) const
77 {
78  double resv = 0;
79  Array<double, 1> resgrad(y.number_variable());
80  resgrad = 0;
81  for(int i = 1; i < x.rows(); ++i) {
82  double t = x(i) - x(i - 1);
83  resv += t * (y.value()(i) + y.value()(i - 1));
84  resgrad += t * (y.jacobian()(i, Range::all()) +
85  y.jacobian()(i - 1, Range::all()));
86  }
87  resv /= 2.0;
88  resgrad /= 2.0;
89  return AutoDerivative<double>(resv, resgrad);
90 }
91 
92 
93 // See base class for description.
95 (const blitz::Array<double, 1>& Hres_wn,
96  const ArrayAd<double, 1>& Hres_rad,
97  const std::vector<int>& Pixel_list) const
98 {
99  firstIndex i1; secondIndex i2;
100  if(Hres_wn.rows() != Hres_rad.rows())
101  throw Exception("wave_number and radiance need to be the same size");
102  ArrayAd<double, 1> disp_wn(disp->pixel_grid().data_ad());
103  ArrayAd<double,1> res((int) Pixel_list.size(),
104  std::max(disp_wn.number_variable(),
105  Hres_rad.number_variable()));
106  // A few scratch variables, defined outside of loop so we don't keep
107  // recreating them.
108  Array<double, 1> one(1);
109  one = 1;
110  Array<double, 1> normfact_grad(disp_wn.number_variable());
111  ArrayAd<double, 1> conv(1, res.number_variable());
112  ArrayAd<double, 1> response;
113  for(int i = 0; i < res.rows(); ++i) {
114  // Find the range of Hres_wn that lie within
115  // wn_center +- ils_half_width
116 
117  AutoDerivative<double> wn_center = disp_wn(Pixel_list[i]);
118  Array<double, 1>::const_iterator itmin =
119  std::lower_bound(Hres_wn.begin(), Hres_wn.end(),
120  wn_center.value() - ils_half_width_.value);
121  Array<double, 1>::const_iterator itmax =
122  std::lower_bound(Hres_wn.begin(), Hres_wn.end(),
123  wn_center.value() + ils_half_width_.value);
124  int jmin = (itmin == Hres_wn.end() ? Hres_wn.rows() - 1 : itmin.position()(0));
125  int jmax = (itmax == Hres_wn.end() ? Hres_wn.rows() - 1 : itmax.position()(0));
126  Range r(jmin, jmax);
127 
128  // Convolve with response
129 
130  // For speed, we just calculate dresponse/dwn_center. This along
131  // with the chain rule is enough to calculate the Jacobian, and is
132  // faster.
133  AutoDerivative<double> wn_center2(wn_center.value(), one);
134  ils_func->ils(wn_center2, Hres_wn(r), response);
135 
136  // Response may not be normalized, so calculate normalization
137  // factor.
138  AutoDerivative<double> normfact_dwn = integrate(Hres_wn(r), response);
139  // Convert gradient from dwn_center to dState
140  normfact_grad = normfact_dwn.gradient()(0) * wn_center.gradient();
141  AutoDerivative<double> normfact(normfact_dwn.value(), normfact_grad);
142 
143  conv.resize(response.rows(), res.number_variable());
144  conv.value() = response.value() * Hres_rad(r).value();
145  if(!Hres_rad.is_constant() && !wn_center.is_constant())
146  conv.jacobian() = response.value()(i1) * Hres_rad(r).jacobian()(i1, i2) +
147  response.jacobian()(Range::all(), 0)(i1) * wn_center.gradient()(i2) *
148  Hres_rad(r).value()(i1);
149  else if(!wn_center.is_constant())
150  conv.jacobian() = response.jacobian()(Range::all(), 0)(i1) *
151  wn_center.gradient()(i2) * Hres_rad(r).value()(i1);
152  else if(!Hres_rad.is_constant())
153  conv.jacobian() = response.value()(i1) * Hres_rad(r).jacobian()(i1, i2);
154  res(i) = integrate(Hres_wn(r), conv) / normfact;
155  }
156  return res;
157 }
158 
160 {
161  return boost::shared_ptr<Ils>(new IlsConvolution(disp->clone(),
162  ils_func, ils_half_width_));
163 }
164 
165 void IlsConvolution::print(std::ostream& Os) const
166 {
167  Os << "IlsConvolution:\n";
168  OstreamPad opad(Os, " ");
169  opad << *disp << "\n" << *ils_func << "\n"
170  << "Half Width: " << ils_half_width_ << "\n";
171  opad.strict_sync();
172 }
bool is_constant() const
Definition: array_ad.h:371
bool is_constant() const
Is this object a constant (with a gradient() all zeros)?
This is a filtering stream that adds a pad to the front of every line written out.
Definition: ostream_pad.h:32
virtual void print(std::ostream &Os) const
This is a ILS where we use a Dispersion object to determine the wavenumbers of each pixel...
This is the base of the exception hierarchy for Full Physics code.
Definition: fp_exception.h:16
#define REGISTER_LUA_DERIVED_CLASS(X, Y)
Definition: register_lua.h:136
const blitz::Array< T, D+1 > jacobian() const
Definition: array_ad.h:307
Apply value function to a blitz array.
const blitz::Array< T, D > & value() const
Definition: array_ad.h:306
const blitz::Array< T, 1 > & gradient() const
Gradient.
We frequently have a double with units associated with it.
int number_variable() const
Definition: array_ad.h:376
virtual blitz::Array< double, 1 > apply_ils(const blitz::Array< double, 1 > &High_resolution_wave_number, const blitz::Array< double, 1 > &High_resolution_radiance, const std::vector< int > &Pixel_list) const
Apply the ILS.
This class models an Instrument Line Shape (ILS).
Definition: ils.h:13
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
const T & value() const
Convert to type T.
#define REGISTER_LUA_END()
Definition: register_lua.h:134
virtual boost::shared_ptr< Ils > clone() const
Clone an Ils object.
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