5 #include <boost/lexical_cast.hpp> 6 #include <boost/bind.hpp> 17 const std::string& Lsi_group)
24 (
new LsiRt(rt_lows, rt_highs, Config_file, Lsi_group));
65 const std::string& Lsi_fname,
66 double Water_vapor_fraction_threshold)
68 low_stream_rt(Low_stream_rt), high_stream_rt(High_stream_rt),
69 wv_threshold(Water_vapor_fraction_threshold)
71 if(low_stream_rt->number_stokes() != high_stream_rt->number_stokes())
72 throw Exception(
"Low stream and high stream need to have the same number of stokes parameters");
76 throw Exception(
"Trouble reading LSI file " + Lsi_fname);
77 in.exceptions(std::ifstream::badbit);
79 std::string main_gas_in;
81 in >> main_gas_in >> nbound;
82 main_gas.push_back(main_gas_in);
83 std::vector<double> t(nbound);
84 for(
int j = 0; j < nbound; ++j)
86 optical_depth_boundary.push_back(t);
119 const std::string& Lsi_group,
120 double Water_vapor_fraction_threshold)
122 low_stream_rt(Low_stream_rt), high_stream_rt(High_stream_rt),
123 wv_threshold(Water_vapor_fraction_threshold)
125 if(low_stream_rt->number_stokes() != high_stream_rt->number_stokes())
126 throw Exception(
"Low stream and high stream need to have the same number of stokes parameters");
128 Array<std::string, 1> mg = Config_file.
read_field<std::string, 1>(Lsi_group +
"/main_gas");
130 Array<double, 1> d = Config_file.
read_field<double, 1>
131 (Lsi_group +
"/optical_depth_boundary_" +
132 boost::lexical_cast<std::string>(i + 1));
133 optical_depth_boundary.push_back(std::vector<double>(d.begin(), d.end()));
134 main_gas.push_back(mg(i));
145 Os <<
"\n Water vapor fraction threshold: " << wv_threshold <<
"\n";
146 for(
int i = 0; i < (int) optical_depth_boundary.size(); ++i) {
147 Os <<
" Main gas[" << i <<
"]: " << main_gas[i] <<
"\n";
148 Os <<
" Optical depth boundary[" << i <<
"]:\n";
150 for(
int j = 0; j < (int) optical_depth_boundary[i].size(); ++j) {
151 Os << optical_depth_boundary[i][j];
152 if(j != (
int) optical_depth_boundary[i].size() - 1)
158 Os <<
"\n High stream:\n";
159 high_stream_rt->print(opad, Short_form);
161 Os <<
" Low stream:\n";
162 low_stream_rt->print(opad,
true);
168 int Spec_index)
const 172 Logger::info() <<
"RT for band " << Spec_index + 1 <<
"\n";
173 calc_correction(Spec_domain, Spec_index,
false,
false);
174 for(
int i = 0; i < Spec_domain.
data().rows(); ++i) {
175 Array<AutoDerivative<double>, 1> err_est;
176 if(gas_opd.
value()(i) > log_threshold)
177 err_est.reference(linear_interp[wv_index(i)](gas_opd(i)));
179 err_est.reference(log_linear_interp[wv_index(i)](gas_opd(i)));
181 stokes_only(i,0) = stokes_only(i,0) / (1 + err_est(0).value());
182 for(
int j = 1; j < stokes_only.cols(); ++j)
183 stokes_only(i,j) = stokes_only(i,j) - err_est(j).value();
185 Logger::info() << low_stream_rt->atmosphere_ptr()->timer_info();
194 Logger::info() <<
"RT + Jac for band " << Spec_index + 1 <<
"\n";
195 calc_correction(Spec_domain, Spec_index,
true,
false);
196 for(
int i = 0; i < Spec_domain.
data().rows(); ++i) {
197 Array<AutoDerivative<double>, 1> err_est;
198 if(gas_opd.
value()(i) > log_threshold)
199 err_est.reference(linear_interp[wv_index(i)](gas_opd(i)));
201 err_est.reference(log_linear_interp[wv_index(i)](gas_opd(i)));
203 stokes_and_jac(i,0) = stokes_and_jac(i,0) / (1 + err_est(0));
204 for(
int j = 1; j < stokes_and_jac.
cols(); ++j)
205 stokes_and_jac(i,j) = stokes_and_jac(i,j) - err_est(j);
207 Logger::info() << low_stream_rt->atmosphere_ptr()->timer_info();
208 return stokes_and_jac;
223 Logger::info() <<
"LSI corrrection only for band " << Spec_index + 1 <<
"\n";
224 calc_correction(Spec_domain, Spec_index,
false,
true);
227 for(
int i = 0; i < Spec_domain.
data().rows(); ++i) {
229 if(gas_opd.
value()(i) > log_threshold)
239 res(i, Range::all()) = err_est;
241 Logger::info() << low_stream_rt->atmosphere_ptr()->timer_info();
267 int Spec_index,
bool Calc_jacobian,
268 bool Skip_stokes_calc)
const 270 Range ra(Range::all());
273 const RtAtmosphere& atm = *low_stream_rt->atmosphere_ptr();
274 const std::vector<double>& odb = optical_depth_boundary[Spec_index];
323 init_atm_sum_value = 0;
326 std::vector<BinMap<int> > cnt;
327 std::vector<BinMap<AutoDerivative<double> > > log_opd_sum;
328 std::vector<BinMap<ArrayAd<double, 2> > > atm_sum;
329 for(
int i = 0; i < 2; ++i) {
330 cnt.push_back(
BinMap<int>(odb.begin(), odb.end(), 0));
331 log_opd_sum.push_back
339 wv_index.resize(
wn.rows());
340 if(!Skip_stokes_calc) {
352 for(
int i = 0; i <
wn.rows(); ++i) {
358 gas_opd(i) = maingas_opd + wv_opd;
362 if(gas_opd(i).
value() < 1e-10)
364 wv_index(i) = (wv_opd / gas_opd(i) >= wv_threshold ? 0 : 1);
366 ++cnt[wv_index(i)][gas_opd.
value()(i)];
367 log_opd_sum[wv_index(i)][gas_opd.
value()(i)] += log(gas_opd(i));
368 atm_sum[wv_index(i)][gas_opd.
value()(i)].
value() += atmv.value();
369 atm_sum[wv_index(i)][gas_opd.
value()(i)].
jacobian() += atmv.jacobian();
373 if(!Skip_stokes_calc) {
375 stokes_and_jac(i, ra) = low_stream_rt->stokes_and_jacobian_single_wn
378 stokes_only(i, ra) = low_stream_rt->stokes_single_wn
401 double wn_mid = (max(
wn) + min(
wn)) / 2;
402 double wn_mid_closest =
wn(0);
403 double wn_dist = fabs(wn_mid_closest - wn_mid);
404 for(
int i = 0; i <
wn.rows(); ++i)
405 if(fabs(
wn(i) - wn_mid) < wn_dist) {
406 wn_dist = fabs(
wn(i) - wn_mid);
407 wn_mid_closest =
wn(i);
409 linear_interp.clear();
410 log_linear_interp.clear();
411 for(
int i = 0; i < 2; ++i) {
412 std::vector<int> cnt_w = cnt[i].value();
413 std::vector<AutoDerivative<double> > log_opd_sum_w = log_opd_sum[i].value();
414 std::vector<ArrayAd<double, 2> > atm_avg_w = atm_sum[i].value();
415 std::vector<AutoDerivative<double> > gas_opd_avg;
416 std::vector<Array<AutoDerivative<double>, 1> > err_est;
417 for(
int j = 0; j < (int) cnt_w.size(); ++j) {
420 gas_opd_avg.push_back(exp(log_opd_sum_w[j] / cnt_w[j]));
423 atm_avg_w[j].value() /= cnt_w[j];
424 atm_avg_w[j].jacobian() /= cnt_w[j];
427 Array<AutoDerivative<double>, 1> low =
428 low_stream_rt->stokes_and_jacobian_single_wn
429 (wn_mid_closest, Spec_index, atm_avg_w[j]).to_array();
430 Array<AutoDerivative<double>, 1> high =
431 high_stream_rt->stokes_and_jacobian_single_wn
432 (wn_mid_closest, Spec_index, atm_avg_w[j]).to_array();
434 Array<AutoDerivative<double>, 1> c(low.rows());
443 c(0) = (fabs(high(0).
value()) > 1e-15 ?
444 (low(0) - high(0)) / high(0) : 0);
445 for(
int i =1; i < c.rows(); ++i)
446 c(i) = low(i) - high(i);
447 err_est.push_back(c);
452 linear_interp.push_back
456 log_linear_interp.push_back
virtual void print(std::ostream &Os, bool Short_form=false) const
Print to stream.
static AccumulatedTimer timer
virtual blitz::Array< double, 2 > stokes(const SpectralDomain &Spec_domain, int Spec_index) const
Calculate stokes vector for the given set of wavenumbers/wavelengths.
virtual int number_stokes() const
Number of stokes parameters we will return in stokes and stokes_and_jacobian.
LsiRt(const boost::shared_ptr< RadiativeTransferSingleWn > &Low_stream_rt, const boost::shared_ptr< RadiativeTransferSingleWn > &High_stream_rt, const std::string &Lsi_fname, double Water_vapor_fraction_threshold=0.8)
Create a object that uses the low stream RT + LSI corrections based on the low and high stream RT...
virtual int number_spectrometer() const
Number of spectrometer we have.
This does a Low Stream Interpolator correction to another RadiativeTransfer object.
This class is responsible for setting up the atmosphere and ground information needed to run the Radi...
virtual ArrayAd< double, 2 > correction_only(const SpectralDomain &Spec_domain, int Spec_index) const
Normally we calculate both the low streams stokes parameters, the LSI correction, and we apply them...
This is a filtering stream that adds a pad to the front of every line written out.
blitz::Array< T, D > read_field(const std::string &Dataname) const
Read a given field.
For different instruments, it is more natural to either work with wavenumbers (e.g., GOSAT) or wavelength (e.g., OCO).
This class takes a set of points and values, and linearly interpolates between those values...
This is the base of the exception hierarchy for Full Physics code.
blitz::Array< T, 2 > jacobian(const blitz::Array< AutoDerivative< T >, 1 > &Ad)
Utility function to extract the Jacobian as a separate matrix from an array of AutoDerivative.
Wrapper around LinearInterpolate that uses log(x) rather than x in interpolating. ...
#define REGISTER_LUA_DERIVED_CLASS(X, Y)
const double log_threshold
This is a RadiativeTransfer that supplies an interface that can be called for a single wavenumber...
This class reads and writes a HDF5 file.
virtual AutoDerivative< double > column_optical_depth(double wn, int spec_index, const std::string &Gas_name) const =0
Total column optical depth for the given gas.
Apply value function to a blitz array.
const blitz::Array< T, D > & value() const
virtual void print(std::ostream &Os, bool Short_form=false) const
Print to stream.
void resize(const blitz::TinyVector< int, D > &Shape, int nvar)
This runs a Radiative Transfer code to determine the reflectance for a given set of wavelengths...
FunctionTimer function_timer(bool Auto_log=false) const
Function timer.
This is a map that takes and index and returns a value.
It can be convenient to allow comments in a text data file that are ignored by the program reading it...
ArrayAd< T, D > copy() const
virtual ArrayAd< double, 2 > intermediate_variable(double wn, int spec_index) const =0
This gives the values of the intermediate variables and the Jacobian with respect to the state vector...
boost::shared_ptr< boost::progress_display > progress_display(const blitz::Array< double, 1 > &wn) const
Helper routine, creates a progress meter.
int number_variable() const
void reference(const ArrayAd< T, D > &V)
blitz::Array< double, 1 > wavenumber(const Unit &Units=units::inv_cm) const
Return data as wavenumbers.
Contains classes to abstract away details in various Spurr Radiative Transfer software.
#define REGISTER_LUA_END()
def(luabind::constructor< int >()) .def("rows"
virtual ArrayAd< double, 2 > stokes_and_jacobian(const SpectralDomain &Spec_domain, int Spec_index) const
Calculate stokes vector for the given set of wavenumbers/wavelengths.
Helper class for AccumulatedTimer.
const boost::shared_ptr< StokesCoefficient > & stokes_coefficient() const
Stokes coefficients used to go from Stokes vector to scalar reflectance.
double value(const FullPhysics::AutoDerivative< double > &Ad)
For GOSAT and OCO, we have a set of stokes coefficients to go from Stokes vector to radiation...
const blitz::Array< double, 1 > & data() const
Return data.