ReFRACtor
error_analysis.cc
Go to the documentation of this file.
1 #include "error_analysis.h"
2 #include "absorber_absco.h"
3 #include <new> // std::bad_alloc
4 using namespace FullPhysics;
5 using namespace blitz;
6 
7 #ifdef HAVE_LUA
8 #include "register_lua.h"
10 .def(luabind::constructor<const boost::shared_ptr<ConnorSolver>&,
14 .def(luabind::constructor<const boost::shared_ptr<MaxAPosteriori>&,
19 #endif
20 
21 //-----------------------------------------------------------------------
23 //-----------------------------------------------------------------------
24 
28  const boost::shared_ptr<Observation>& inst_meas)
29  : solver(Solver), atm(Atm), fm(Fm), meas(inst_meas)
30 {
31 }
32 
33 //-----------------------------------------------------------------------
35 //-----------------------------------------------------------------------
36 
40  const boost::shared_ptr<Observation>& inst_meas)
41  : max_a_posteriori(Max_a_posteriori), atm(Atm), fm(Fm), meas(inst_meas)
42 {
43 }
44 
45 //-----------------------------------------------------------------------
50 //-----------------------------------------------------------------------
51 
55  const boost::shared_ptr<Observation>& inst_meas)
56 : solver(Solver), atm(boost::dynamic_pointer_cast<AtmosphereOco>(Atm)),
57  fm(Fm), meas(inst_meas)
58 {
59 }
60 
61 //-----------------------------------------------------------------------
66 //-----------------------------------------------------------------------
67 
71  const boost::shared_ptr<Observation>& inst_meas)
72 : max_a_posteriori(Max_a_posteriori),
73  atm(boost::dynamic_pointer_cast<AtmosphereOco>(Atm)),
74  fm(Fm), meas(inst_meas)
75 {
76 }
77 
78 //-----------------------------------------------------------------------
87 //-----------------------------------------------------------------------
88 
89 Array<double, 1> ErrorAnalysis::dxco2_dstate() const
90 {
91  FeDisableException disable_fp;
92  Array<double, 1> res(xco2().gradient().copy());
93  res = where(xco2_state_used(), res, 0.0);
94  return res;
95 }
96 
97 //-----------------------------------------------------------------------
104 //-----------------------------------------------------------------------
105 
107 {
108  FeDisableException disable_fp;
109  return sum(dxco2_dstate()(i1) * averaging_kernel()(i1, i3) *
110  aposteriori_covariance()(i3, i2) * dxco2_dstate()(i2));
111 }
112 
113 //-----------------------------------------------------------------------
120 //-----------------------------------------------------------------------
121 
123 {
124  FeDisableException disable_fp;
125  Array<bool, 1> xco2_state_usedv = xco2_state_used();
126  // t is a multiplier that turns S into S_a,CO2 as described in the ATB.
127  Array<double, 1> t(xco2_state_usedv.shape());
128  t = where(xco2_state_usedv, 1, 0);
129  Array<double, 2> ak(averaging_kernel());
130  Array<double, 2> ak_minus_i(ak.shape());
131  ak_minus_i = ak;
132  for(int i = 0; i < ak_minus_i.rows(); ++i)
133  ak_minus_i(i, i) -= 1;
134  Array<double, 2> s(apriori_covariance());
135  return sum(dxco2_dstate()(i1) * ak_minus_i(i1, i3) * t(i3) * s(i3, i4) *
136  t(i4) * ak_minus_i(i2, i4) * dxco2_dstate()(i2));
137 }
138 
139 //-----------------------------------------------------------------------
146 //-----------------------------------------------------------------------
147 
149 {
150  FeDisableException disable_fp;
151  Array<bool, 1> xco2_state_usedv = xco2_state_used();
152  // t is a multiplier that turns S into S_ae as described in the ATB.
153  Array<double, 1> t(xco2_state_usedv.shape());
154  t = where(xco2_state_usedv, 0, 1);
155  Array<double, 2> ak(averaging_kernel());
156  Array<double, 2> s(apriori_covariance());
157  return sum(dxco2_dstate()(i1) * ak(i1, i3) * t(i3) * s(i3, i4) * t(i4) *
158  ak(i2, i4) * dxco2_dstate()(i2));
159  return 0;
160 }
161 
162 //-----------------------------------------------------------------------
184 //-----------------------------------------------------------------------
185 
186 Array<double, 1> ErrorAnalysis::xco2_gain_vector() const
187 {
188  FeDisableException disable_fp;
189  Array<double, 1> result(meas->radiance_all().spectral_range().data().shape());
190  result = 0;
191 
192  // Temporary, we need to add handling for a iterative_solver.
193  if(!solver) {
194  Logger::warning() << "Can not calculate xco2_gain_vector since solver is non ConnorSolver" << '\n';
195  return result;
196  }
197 
198  // Make sure the AbsorberVMR for CO2 is a Absorber Hdf so we can use the
199  // pressure weighting function method
200  boost::shared_ptr<AbsorberAbsco> absorber = boost::dynamic_pointer_cast<AbsorberAbsco>(atm->absorber_ptr());
201  if(absorber != 0) {
202  // n = # sv items
203  // m = # of radiance points
204 
205  Array<bool, 1> xco2_state_usedv = xco2_state_used();
206  Array<double, 1> sv_press_weighting(xco2_state_usedv.shape());
207  sv_press_weighting = 0;
208  //
209  // Copy pressure weighting values where CO2 is located in the statevector
210  // Shape: n
211  Array<double, 1> press_wgt_grid(absorber->pressure_weighting_function_grid().value());
212  int p_wgt_idx = 0;
213  for(int sv_idx = 0; sv_idx < xco2_state_usedv.rows() && p_wgt_idx < press_wgt_grid.rows(); sv_idx++) {
214  if(xco2_state_usedv(sv_idx)) {
215  sv_press_weighting(sv_idx) = press_wgt_grid(p_wgt_idx);
216  p_wgt_idx++;
217  }
218  }
219 
220  // Shape: n x n
221  Array<double, 2> S(aposteriori_covariance());
222 
223  // Shape: m
224  Array<double, 1> Se(solver->residual_covariance_diagonal());
225 
226  // Compute Sy_m1 with 1/sqrt(Se) on the diagonal
227  // Shape: m x m
228  Array<double, 2> Sy_m1;
229  // Don't even try for larger sizes, since we don't want to
230  // suck up all the memory of a large system. This threshold is
231  // arbitrary, and we can change this in the future if needed.
232  if(Se.rows() > 20000) {
233  Logger::error() << "Se is too big for calculating xco2_gain_vector. Se.rows() = " << Se.rows() << '\n';
234  return result;
235  }
236  try {
237  Sy_m1.resize(Se.rows(), Se.rows());
238  } catch (std::bad_alloc& ba) {
239  // If Se is too big then we won't be able to allocated the memory
240  // for this operation and we should fail and return an empty result
241  Logger::error() << "Se is too big for calculating xco2_gain_vector. Se.rows() = " << Se.rows() << '\n';
242  return result;
243  }
244 
245  Sy_m1 = 0;
246  for(int r_idx = 0; r_idx < Se.rows(); r_idx++) {
247  Sy_m1(r_idx, r_idx) = 1 / Se(r_idx);
248  }
249 
250  // Shape: n x m
251  Array<double, 2> Kt(solver->jacobian().transpose(secondDim, firstDim));
252 
253  Array<double, 1> res1( sum(sv_press_weighting(i2) * S(i2, i1), i2) );
254  Array<double, 1> res2( sum(res1(i2) * Kt(i2, i1), i2) );
255  result = sum(res2(i2) * Sy_m1(i2, i1), i2);
256 
257  } else {
258  Logger::warning() << "Can not calculate xco2_gain_vector since atmosphere->absorber() is not of type AbscoAbsorber" << '\n';
259  }
260 
261  return result;
262 }
263 
264 //-----------------------------------------------------------------------
270 //-----------------------------------------------------------------------
271 
272 Array<double, 2> ErrorAnalysis::hmat() const
273 {
274  FeDisableException disable_fp;
275  int n = (solver ? solver->x_solution().rows() :
276  max_a_posteriori->parameters().rows());
277  Array<double, 2> res(n, n + 1);
278  res = 0;
279  res(Range::all(), 0) = dxco2_dstate();
280  for(int i = 0; i < n; ++i)
281  res(i, i + 1) = 1;
282  return res;
283 }
284 
285 //-----------------------------------------------------------------------
291 //-----------------------------------------------------------------------
292 
293 Array<double, 2> ErrorAnalysis::ht_c_h() const
294 {
295  FeDisableException disable_fp;
296  Array<double, 2> h(hmat());
297  Array<double, 2> res(h.cols(), h.cols());
298  res = sum(sum(h(i3, i1) * aposteriori_covariance()(i3, i4) *
299  h(i4, i2), i4), i3);
300  return res;
301 }
302 
303 //-----------------------------------------------------------------------
307 //-----------------------------------------------------------------------
308 
310 {
311  FeDisableException disable_fp;
312  Array<double, 2> ht_c_h_v(ht_c_h());
313  Array<double, 1> res(ht_c_h_v.rows() - 1);
314  Range r(1, ht_c_h_v.rows() - 1);
315  double t = ht_c_h_v(0,0);
316  res = where(t * ht_c_h_v(r, r)(i1, i1) > 0,
317  ht_c_h_v(0, r) / sqrt(t * ht_c_h_v(r, r)(i1, i1)), 0);
318  return res;
319 }
320 
321 //-----------------------------------------------------------------------
325 //-----------------------------------------------------------------------
326 
327 Array<double, 1> ErrorAnalysis::xco2_avg_kernel() const
328 {
329  FeDisableException disable_fp;
330  Array<double, 1> full_ak(xco2_avg_kernel_full());
331  Array<bool, 1> xco2_state_usedv = xco2_state_used();
332  Array<double, 1> res(count(xco2_state_usedv));
333  int ind = 0;
334  for(int i = 0; i < xco2_state_usedv.rows(); ++i)
335  if(xco2_state_usedv(i))
336  res(ind++) = full_ak(i);
337  return res;
338 }
339 
340 //-----------------------------------------------------------------------
342 //-----------------------------------------------------------------------
343 
344 Array<double, 1> ErrorAnalysis::xco2_avg_kernel_full() const
345 {
346  FeDisableException disable_fp;
347  Array<double, 2> ak(averaging_kernel());
348  Array<double, 1> res(ak.cols());
349  res = sum(dxco2_dstate()(i2) * ak(i2, i1), i2);
350  return res;
351 }
352 
353 //-----------------------------------------------------------------------
357 //-----------------------------------------------------------------------
358 
359 Array<double, 1> ErrorAnalysis::xco2_avg_kernel_norm() const
360 {
361  FeDisableException disable_fp;
362  Array<double, 2> ak(averaging_kernel());
363  Array<double, 1> full(ak.cols());
364  full = sum(dxco2_dstate()(i2) * ak(i2, i1), i2);
365  full = where(abs(dxco2_dstate()) > 1e-20, full / dxco2_dstate(), 0);
366  Array<bool, 1> xco2_state_usedv = xco2_state_used();
367  Array<double, 1> res(count(xco2_state_usedv));
368  int ind = 0;
369  for(int i = 0; i < xco2_state_usedv.rows(); ++i)
370  if(xco2_state_usedv(i))
371  res(ind++) = full(i);
372  return res;
373 }
374 
375 //-----------------------------------------------------------------------
379 //-----------------------------------------------------------------------
380 
382 {
383  FeDisableException disable_fp;
384  Array<double, 1> full_ak(xco2_avg_kernel_full());
385 
386  Array<double, 1> res(full_ak.shape());
387  Array<double, 2> cov(aposteriori_covariance());
388  // Allow cov to be slightly negative, e.g., due to round off error.
389  res = (full_ak - dxco2_dstate()) *
390  where(cov(i1, i1) > 0, sqrt(cov(i1, i1)), 0);
391  return res;
392 }
393 
394 //-----------------------------------------------------------------------
399 //-----------------------------------------------------------------------
400 
401 double ErrorAnalysis::signal(int band) const
402 {
403  FeDisableException disable_fp;
404  const int nrad = 10;
405  SpectralRange rad(meas->radiance(band).spectral_range());
406  if(rad.data().rows() ==0)
407  return 0;
408  Array<double, 1> r(rad.data().copy());
409  std::sort(r.data(), r.data() + r.rows()); // Min to max value
410  r.reverseSelf(firstDim); // Now max to min value
411  Range r2(0, std::min(nrad - 1, r.rows() - 1));
412  return sum(r(r2) / r2.length());
413 }
414 
415 //-----------------------------------------------------------------------
417 //-----------------------------------------------------------------------
418 // Don't have Doxygen document this class.
420 class DataRow {
421 public:
422  DataRow(int R, double V) : row(R), value(V) {}
423  int row;
424  double value;
425 };
426 
427 class DataRowCompare {
428 public:
429  bool operator()(const DataRow& D1, const DataRow& D2) const
430  { return D1.value > D2.value; }
431 };
432 
434 
435 //-----------------------------------------------------------------------
440 //-----------------------------------------------------------------------
441 
442 double ErrorAnalysis::noise(int band) const
443 {
444  FeDisableException disable_fp;
445  const int nrad = 10;
446  SpectralRange rad(meas->radiance(band).spectral_range());
447  if(rad.data().rows() < nrad || rad.uncertainty().rows() < nrad)
448  return 0;
449  std::vector<DataRow> dr;
450  dr.reserve(rad.data().rows());
451  for(int i = 0; i < rad.data().rows(); ++i)
452  dr.push_back(DataRow(i, rad.data()(i)));
453  std::sort(dr.begin(), dr.end(), DataRowCompare()); // Max to min value
454  double sum_noise = 0;
455  for(int i = 0; i < nrad; ++i)
456  sum_noise += rad.uncertainty()(dr[i].row);
457 
458  return sum_noise / nrad;
459 }
460 
461 //-----------------------------------------------------------------------
463 //-----------------------------------------------------------------------
464 
466 {
467  FeDisableException disable_fp;
468  firstIndex i1; secondIndex i2;
469  // Special handling if state vector hasn't been set to anything
470  // yet. Return a reasonable value.
471  Array<double, 2> cov(aposteriori_covariance());
472  if(cov.rows() == 0)
473  return 0.0;
474  return sqrt(sum(dxco2_dstate()(i1) * cov * dxco2_dstate()(i2)));
475 }
476 
477 //-----------------------------------------------------------------------
480 //-----------------------------------------------------------------------
481 
482 Array<double, 2> ErrorAnalysis::co2_averaging_kernel() const
483 {
484  FeDisableException disable_fp;
485  Array<double, 2> ak(averaging_kernel());
486  Array<bool, 1> used(xco2_state_used());
487  int sz = count(used);
488  Array<double, 2> res(sz, sz);
489  int ind1 = 0;
490  for(int i = 0; i < used.rows(); ++i)
491  if(used(i)) {
492  int ind2 = 0;
493  for(int j = 0; j < used.rows(); ++j)
494  if(used(j)) {
495  res(ind1, ind2) = ak(i, j);
496  ++ind2;
497  }
498  ++ind1;
499  }
500  return res;
501 }
blitz::Array< double, 2 > co2_averaging_kernel() const
Portion of averaging kernel that relates the part of the state vector that is used by the CO2 VMR cal...
static LogHelper error()
Definition: logger.h:111
const Unit s("s", 1.0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0)
This class maintains the absorber portion of the state.
Definition: doxygen.h:52
blitz::Array< double, 1 > xco2_gain_vector() const
This calculates xco2_gain_vector.
double signal(int band) const
Calculate an approximation to the size of the continuum signal where there is no significant atmosphe...
To detect things like divide by zero, we may turn on floating point exceptions.
double xco2_interference_error() const
Calculate XCO2 interference error.
#define REGISTER_LUA_CLASS(X)
Definition: register_lua.h:116
Apply value function to a blitz array.
blitz::Array< double, 1 > xco2_avg_kernel_norm() const
Calculate the normalized XCO2 averaging kernel.
double xco2_uncertainty() const
XCO2 uncertainty.
blitz::Array< double, 1 > xco2_avg_kernel_full() const
This the XCO2 averaging kernel for the full state vector.
blitz::Array< double, 1 > xco2_avg_kernel() const
Calculate the XCO2 averaging kernel.
We have a number of different spectrums that appear in different parts of the code.
blitz::Array< double, 1 > interference_smoothing_uncertainty() const
Calculate the interference smoothing uncertainty.
double xco2_smoothing_error() const
Calculate XCO2 smoothing error.
double xco2_measurement_error() const
Calculate XCO2 measurement error.
blitz::Array< double, 1 > xco2_correlation_interf() const
Calculate xco2_correlation_interf.
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
This calculates a variety of values to help with the error analysis of a Level 2 Full Physics Run...
This class maintains the atmosphere portion of the state, and uses this to set up the atmosphere and ...
ErrorAnalysis(const boost::shared_ptr< ConnorSolver > &Solver, const boost::shared_ptr< AtmosphereOco > &Atm, const boost::shared_ptr< ForwardModel > &Fm, const boost::shared_ptr< Observation > &inst_meas)
Constructor.
static LogHelper warning()
Definition: logger.h:110
const Unit rad("rad", 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0)
double value(const FullPhysics::AutoDerivative< double > &Ad)
double noise(int band) const
Helper class for sort done in noise.

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