OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
DbAlgOcean.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * NAME: DbAlgOcean.cpp
4  *
5  * DESCRIPTION: Object class that provides data structures and processes that
6  * compute processings for a given DDProcess object class.
7  *
8  * Created on: October 13, 2018
9  * Author: Sam Anderson, DT
10  *
11  * Modified:
12  *
13  *******************************************************************************/
14 
15 #include <math.h>
16 #include <fstream>
17 #include <math.h>
18 #include <levmar.h>
19 
20 #include <DDProcess.h>
21 #include <DDOptions.h>
22 #include "deepblue/DbLutNetcdf.h"
23 #include "deepblue/DbMask.h"
24 #include "deepblue/DbAlgorithm.h"
25 
26 #define real __minpack_real__
27 
28 using namespace std;
29 
33 void fcn(const int* m, const int* n, const double* x,
34  double* fvec, double* fdif, int* iflag);
35 
39 void fcn_lm(double *fvec, double *x, const int m, const int n, void *adata);
40 
41 float rfl[NOWL];
42 float plut[NOWL][NFMF3][NAOT1];
43 int num_fmf;
44 int num_aot;
45 
46 
47 /**************************************************************************
48  * NAME: DbAlgOcean()
49  *
50  * DESCRIPTION: Class Constructor
51  *
52  *************************************************************************/
53 
55 {
56 }
57 
58 /**************************************************************************
59  * NAME: ~DbAlgOcean()
60  *
61  * DESCRIPTION: Class Destructor
62  *
63  *************************************************************************/
64 
66 {
67  delete bath_lut_;
68  delete chl_lut_;
69  delete oaLut_[DUST];
70  delete oaLut_[FINE];
71  delete oaLut_[MARI];
72  delete oaLut_[MIX];
73  delete cm_;
74 }
75 
76 /**************************************************************************
77  * NAME: initialize()
78  *
79  * DESCRIPTION: Virtual function initializes data and object classes for
80  * processing operations.
81  *
82  *************************************************************************/
83 
84 int DbAlgOcean::initialize( map<string, ddata*> imap )
85 {
86  int status = DTDB_SUCCESS;
87 
89  if (status != DTDB_SUCCESS) {
90  std::cerr << "DbAlgLand:: Base class initialization failure" << std::endl;
91  return status;
92  }
93  status = initialize_LUT_data();
94  if (status != DTDB_SUCCESS) {
95  std::cerr << "DbAlgOcean:: LUT initialization failure" << std::endl;
96  return status;
97  }
98  cm_ = new DbCloudMaskOcean(this);
99 
100  return status;
101 }
102 
103 /**************************************************************************
104  * NAME: initialize_LUT_data()
105  *
106  * DESCRIPTION: Read all calibration LUTs from binary files and create the
107  * radiance and brightness temperature output LUTs.
108  *
109  *************************************************************************/
110 
112 {
113  int status = DTDB_SUCCESS;
114 
115 // Load LUTs
116  DbLutNetcdf* lutgen = new DbLutNetcdf();
117  bath_lut_ = new dbBathymetryLUT;
118  memset(bath_lut_, 0, sizeof(dbBathymetryLUT));
119  status = lutgen->read_bathymetry_lut(bath_lut_);
120  chl_lut_ = new dbChlLUT();
121  memset(chl_lut_, 0, sizeof(dbChlLUT));
122  status = lutgen->read_chl_lut(chl_lut_);
123  oaLut_[DUST] = new dbOceanAerosolLUMA;
125  oaLut_[FINE] = new dbOceanAerosolLUMA;
127  oaLut_[MARI] = new dbOceanAerosolLUMA;
129  oaLut_[MIX] = new dbOceanAerosolLUMA;
131  delete lutgen;
132 
133  return status;
134 }
135 
136 /**************************************************************************
137  * NAME: compute()
138  *
139  * DESCRIPTION: Virtual function computes processing.
140  *
141  *************************************************************************/
142 
143 map<string, ddata*> DbAlgOcean::process(vector<size_t> start, vector<size_t> count,
144  map<string, ddata*> imap)
145 {
146  int status = get_inputs(start, count, imap);
147  size_t iy = start[0];
148  size_t ix = start[1];
149 
150 // -- Skip pixels with invalid angles
151  if ((solz_ > 84.0) || (solz_ < 0.0) || (senz_ < 0.0) || (senz_ > 90.0) ||
152  (raa_ < 0.0) || (raa_ > 180.0) || (ws_ < 0.0) || (ws_ > 99.0)) {
153 // std::cerr << "DbAlgOcean:: Invalid angles at "<< iy << ":" << ix << std::endl;
154  return set_fills();
155  }
156 // -- Skip pixels with invalid reflectances
157  if ((rfl_[(size_t)rhot_band::W490] < 0) || (rfl_[(size_t)rhot_band::W550] < 0) || (rfl_[(size_t)rhot_band::W670] < 0) ||
158  (rfl_[(size_t)rhot_band::W865] < 0)) {
159 // std::cerr << "DbAlgOcean:: Invalid reflectances at "<< iy << ":" << ix << std::endl;
160  l2_flags_ += (int) flags::BOWTIEDEL;
161  return set_fills();
162  }
163 
164  compute_glint_angle(glint_angle_);
165  compute_scatter_angle(scatter_angle_);
166 
167  // -- skip bad pixels (cloud, deletion pixels, etc)
168  mask_cm_ = cloud_mask_;
169  if (mask_cm_ == DFILL_UBYTE) {
170  cm_->compute( mask_cm_ );
171  cloud_mask_ = mask_cm_;
172  }
173  if (bcloudmask_ && cloud_mask_) {
174  l2_flags_ += (int) flags::CLDICE;
175  return set_fills();
176  }
177 
178 // -- skip glint-affected regions.
179  float glint = calc_glint_refl(iy, ix, status);
180  if (status != 0) {
181  std::cerr << "DbAlgOcean:: Failed to calculate glint angle" << std::endl;
182  return set_fills();
183  }
184 // Old threshold was 0.003. This recovers area and doesn't introduce problems.
185  if (bglintmask_) {
186  if (glint > 0.005) {
187 // std::cerr << "DbAlgOcean:: Glint exceeds threshold" << std::endl;
188  l2_flags_ += (int) flags::HIGLINT;
189  return set_fills();
190  }
191  }
192 
193 // convert from VIIRS to IOF units
194  double cossza = cos(solz_*DEGtoRAD);
195  for ( int i=0; i<NTWL; i++) {
196  if (rfl_[i] > DFILL_TEST) {
197  rfl_[i] *= (cossza/M_PI);
198  }
199  for (size_t il=0; il<=2; il++) {
200  for (size_t ip=0; ip<=2; ip++) {
201  if (rfla_[i][il][ip] > DFILL_TEST) {
202  rfla_[i][il][ip] *= (cossza/M_PI);
203  }
204  }
205  }
206  }
207 
208  set_fill_out();
209  OMODEL_ENUM min_model = NMODEL;
210 
211  if (bgascorrect_) {
212  compute_gas_correction();
213  for (size_t ib=0; ib<NTWL; ib++) {
214  if (rfl_[ib] > DFILL_TEST) {
215  rfl_[ib] *= gasc_[ib];
216  }
217  }
218  }
219 
220  int ilat = min((int)((lat_ + 90.)*10.0 + 0.5),1800-1);
221  int ilon = min((int)((lon_ + 180.0)*10.0 + 0.5),3600-1);
222  chl_ = chl_lut_->log_chl[ilat][ilon][month_-1];
223  int xind = min((int)((lon_ + 180.0)*60.0 + 0.5), 21600);
224  int yind = min((int)((lat_ + 90.0)*60.0 + 0.5), 10800);
225  bathy_ = bath_lut_->z[yind][xind];
226 
227  for (int i=0; i<NDBMDL+1; i++) {
228  memset(&oOut_[i], 0, sizeof(osOut));
229  }
230 
231 // -- run ocean retrieval for this pixel. Check for status < 0 as 0 is a successful
232 // -- retrieval while 1 means the pixel was too turbid -- not an error.
233  oOut_[DUST].model_flag = DUST;
234  status = run_inversion(iy, ix, oaLut_[DUST], &oOut_[DUST]);
235  if (status < 0) {
236  std::cerr << "DbAlgOcean:: Coarse aerosol inversion failed" << std::endl;
237  }
238  oOut_[FINE].model_flag = FINE;
239  status = run_inversion(iy, ix, oaLut_[FINE], &oOut_[FINE]);
240  if (status < 0) {
241  std::cerr << "DbAlgOcean:: Fine aerosol inversion failed" << std::endl;
242  }
243  oOut_[MARI].model_flag = MARI;
244  status = run_inversion(iy, ix, oaLut_[MARI], &oOut_[MARI]);
245  if (status < 0) {
246  std::cerr << "DbAlgOcean:: Maritime aerosol inversion failed" << std::endl;
247  }
248  oOut_[MIX].model_flag = MIX;
249  status = run_inversion(iy, ix, oaLut_[MIX], &oOut_[MIX]);
250  if (status < 0) {
251  std::cerr << "DbAlgOcean:: Mixed aerosol inversion failed" << std::endl;
252  }
253 
254  if (oOut_[DUST].ss > 0) {
255  if ((oOut_[DUST].ss < oOut_[FINE].ss || oOut_[FINE].ss < 0) &&
256  (oOut_[DUST].ss < oOut_[MARI].ss || oOut_[MARI].ss < 0) &&
257  (oOut_[DUST].ss < oOut_[MIX].ss || oOut_[MIX].ss < 0)) {
258  min_model = DUST;
259  }
260  }
261  if (oOut_[FINE].ss > 0) {
262  if ((oOut_[FINE].ss < oOut_[DUST].ss || oOut_[DUST].ss < 0) &&
263  (oOut_[FINE].ss < oOut_[MARI].ss || oOut_[MARI].ss < 0) &&
264  (oOut_[FINE].ss < oOut_[MIX].ss || oOut_[MIX].ss < 0)) {
265  min_model = FINE;
266  }
267  }
268  if (oOut_[MARI].ss > 0) {
269  if ((oOut_[MARI].ss < oOut_[DUST].ss || oOut_[DUST].ss < 0) &&
270  (oOut_[MARI].ss < oOut_[FINE].ss || oOut_[FINE].ss < 0) &&
271  (oOut_[MARI].ss < oOut_[MIX].ss || oOut_[MIX].ss < 0)) {
272  min_model = MARI;
273  }
274  }
275  if (oOut_[MIX].ss > 0) {
276  if ((oOut_[MIX].ss < oOut_[DUST].ss || oOut_[DUST].ss < 0) &&
277  (oOut_[MIX].ss < oOut_[FINE].ss || oOut_[FINE].ss < 0) &&
278  (oOut_[MIX].ss < oOut_[MARI].ss || oOut_[MARI].ss < 0)) {
279  min_model = MIX;
280  }
281  }
282 
283  if (min_model < NMODEL) {
284  oOut_[BEST].aot550 = oOut_[min_model].aot550;
285  oOut_[BEST].fmf = oOut_[min_model].fmf;
286  oOut_[BEST].ae = oOut_[min_model].ae;
287  oOut_[BEST].ss = oOut_[min_model].ss;
288  oOut_[BEST].chl = oOut_[min_model].chl;
289  oOut_[BEST].alg_flag = oOut_[min_model].alg_flag;
290  oOut_[BEST].model_flag = oOut_[min_model].model_flag;
291  for (int i=0; i<NOWL; i++) {
292  oOut_[BEST].aot[i] = oOut_[min_model].aot[i];
293  }
294  }
295 
296  // write to generic outputs
297 
298  qual_flag_ = (oOut_[BEST].aot550 < DFILL_TEST) ? 0 : 3;
299  if (oOut_[BEST].model_flag == 1 ) {
300  aerosol_type_ = 0;
301  }else if (oOut_[BEST].model_flag == 2 ) {
302  aerosol_type_ = 7;
303  }else if (oOut_[BEST].model_flag == 3 ) {
304  aerosol_type_ = 6;
305  }else if (oOut_[BEST].model_flag == 4 ) {
306  aerosol_type_ = 5;
307  } else {
308  aerosol_type_ = 8;
309  }
310  error_flag_ = DFILL_SHORT;
311 
312  scatter_ang_ = scatter_angle_;
313  glint_ang_ = glint_angle_;
314  sse_ = oOut_[BEST].ss;
315  fmf_ = oOut_[BEST].fmf;
316  aot_550_ = oOut_[BEST].aot550;
317  ae1_ = oOut_[BEST].ae;
318  ae2_ = DFILL_FLOAT;
319  ndv_ = DFILL_FLOAT;
320  chlor_ = chl_;
321  aot_[0] = DFILL_FLOAT;
322  for ( int ib=0; ib<NOWL; ib++ ) {
323  aot_[ib+1] = oOut_[BEST].aot[ib];
324  }
325  for ( int ib=0; ib<NLWL+1; ib++ ) {
326  sr_[ib] = DFILL_FLOAT;
327  ssa_[ib] = DFILL_FLOAT;
328  }
329  for (int ib = 0; ib < DB_RFL_BANDS; ib++) {
330  rfl_[ib] *= (M_PI/cossza);
331  }
332 
333  return set_outputs();
334 }
335 
336 /**************************************************************************
337  * NAME: run_inversion()
338  *
339  * DESCRIPTION: Run inversion to extract tau estimates.
340  *
341  **************************************************************************
342  * Library Function
343  *
344  * NAME: lmdif1
345  *
346  * the purpose of lmdif1 is to minimize the sum of the squares of
347  * m nonlinear functions in n variables by a modification of the
348  * levenberg-marquardt algorithm. this is done by using the more
349  * general least-squares solver lmdif. the user must provide a
350  * subroutine which calculates the functions. the jacobian is
351  * then calculated by a forward-difference approximation.
352  *
353  * the subroutine statement is
354  *
355  * subroutine lmdif1(fcn,m,n,x,fvec,tol,info,iwa,wa,lwa)
356  *
357  * where
358  *
359  * fcn is the name of the user-supplied subroutine which
360  * calculates the functions. fcn must be declared
361  * in an external statement in the user calling
362  * program, and should be written as follows.
363  *
364  * subroutine fcn(m,n,x,fvec,iflag)
365  * integer m,n,iflag
366  * double precision x(n),fvec(m)
367  * ----------
368  * calculate the functions at x and
369  * return this vector in fvec.
370  * ----------
371  * return
372  * end
373  *
374  * the value of iflag should not be changed by fcn unless
375  * the user wants to terminate execution of lmdif1.
376  * in this case set iflag to a negative integer.
377  *
378  * m is a positive integer input variable set to the number
379  * of functions.
380  *
381  * n is a positive integer input variable set to the number
382  * of variables. n must not exceed m.
383  *
384  * x is an array of length n. on input x must contain
385  * an initial estimate of the solution vector. on output x
386  * contains the final estimate of the solution vector.
387  *
388  * fvec is an output array of length m which contains
389  * the functions evaluated at the output x.
390  *
391  * tol is a nonnegative input variable. termination occurs
392  * when the algorithm estimates either that the relative
393  * error in the sum of squares is at most tol or that
394  * the relative error between x and the solution is at
395  * most tol.
396  *
397  * info is an integer output variable. if the user has
398  * terminated execution, info is set to the (negative)
399  * value of iflag. see description of fcn. otherwise,
400  * info is set as follows.
401  *
402  * info = 0 improper input parameters.
403  *
404  * info = 1 algorithm estimates that the relative error
405  * in the sum of squares is at most tol.
406  *
407  * info = 2 algorithm estimates that the relative error
408  * between x and the solution is at most tol.
409  *
410  * info = 3 conditions for info = 1 and info = 2 both hold.
411  *
412  * info = 4 fvec is orthogonal to the columns of the
413  * jacobian to machine precision.
414  *
415  * info = 5 number of calls to fcn has reached or
416  * exceeded 200*(n+1).
417  *
418  * info = 6 tol is too small. no further reduction in
419  * the sum of squares is possible.
420  *
421  * info = 7 tol is too small. no further improvement in
422  * the approximate solution x is possible.
423  *
424  * iwa is an integer work array of length n.
425  *
426  * wa is a work array of length lwa.
427  *
428  * lwa is a positive integer input variable not less than
429  * m*n+5*n+m.
430  *
431  * subprograms called
432  *
433  * user-supplied ...... fcn
434  *
435  * minpack-supplied ... lmdif
436  *
437  * argonne national laboratory. minpack project. march 1980.
438  * burton s. garbow, kenneth e. hillstrom, jorge j. more
439  *
440  *************************************************************************/
441 
442 int DbAlgOcean::run_inversion(size_t iy, size_t ix, dbOceanAerosolLUMA* lut,
443  osOut* iout )
444 {
445  int status = DTDB_SUCCESS;
446 
447  // -- find index for relative azimuth angle for linear interpolation
448  int rbeg = locate(NVRAA, &lut->raa[0], raa_, status);
449  if (status != 0) {
450  std::cerr << "DbAlgOcean::run_inversion:: Failed to locate raa index" << std::endl;
451  status = -1;
452  return status;
453  }
454  float raa_frac = (raa_ - lut->raa[rbeg]) / (lut->raa[rbeg+1]-lut->raa[rbeg]);
455 
456 // -- find indices for sza for linear interpolation
457  int mbeg = locate(NVSZA, &lut->sza[0], solz_, status);
458  if (status != 0) {
459  std::cerr << "DbAlgOcean::run_inversion:: Failed to locate sza index" << std::endl;
460  return status;
461  }
462  float sza_frac = (solz_-lut->sza[mbeg]) / (lut->sza[mbeg+1]-lut->sza[mbeg]);
463 
464 // -- find indices for vza for linear interpolation
465  int nbeg = locate(NVVZA, &lut->vza[0], senz_, status);
466  if (status != 0) {
467  std::cerr << "DbAlgOcean::run_inversion:: Failed to locate vza index" << std::endl;
468  return status;
469  }
470  float vza_frac = (senz_-lut->vza[nbeg]) / (lut->vza[nbeg+1]-lut->vza[nbeg]);
471 
472 // -- find indices for windspeed
473  float ws_frac = 0.0;
474  int wbeg = locate(NWS, &lut->wspd[0], ws_, status);
475  if (status != 0) {
476  switch (status) {
477  case -1:
478  if (ws_ < lut->wspd[0]) {
479  wbeg = 0;
480  ws_frac = 0.0;
481  } else {
482  std::cerr << "DbAlgOcean::run_inversion:: Failed windspeed lookup" << std::endl;
483  return status;
484  }
485  break;
486  case 1:
487  if (ws_ > lut->wspd[lut->nwspd-1]) {
488  wbeg = lut->nwspd - 2;
489  ws_frac = 1.0;
490  } else {
491  std::cerr << "DbAlgOcean::run_inversion:: Failed windspeed lookup" << std::endl;
492  return status;
493  }
494  break;
495  case -2:
496  std::cerr << "DbAlgOcean::run_inversion:: Windspeeds not monotonic" << std::endl;
497  return status;
498  break;
499  default:
500  std::cerr << "DbAlgOcean::run_inversion:: Unexpected status returned from locate" << std::endl;
501  return status;
502  break;
503  }
504  } else {
505  ws_frac = (ws_ - lut->wspd[wbeg])/(lut->wspd[wbeg+1]-lut->wspd[wbeg]);
506  }
507 // -- find indices for chl
508  float chl_frac = 0.0;
509  int cbeg = locate(NCHL, &lut->chl[0], chl_, status);
510  if (status != 0) {
511  switch (status) {
512  case (-1):
513  if (chl_ < lut->chl[0]) {
514  cbeg = 0;
515  chl_frac = 0.0;
516  } else {
517  std::cerr << "DbAlgOcean::run_inversion:: Failed CHL lookup" << std::endl;
518  return status;
519  }
520  break;
521  case (1):
522  if (chl_ > lut->chl[lut->nchl-1]) {
523  cbeg = lut->nchl - 2;
524  chl_frac = 1.0;
525  } else {
526  std::cerr << "DbAlgOcean::run_inversion:: Failed CHL lookup" << std::endl;
527  return status;
528  }
529  break;
530  case (-2):
531  std::cerr << "DbAlgOcean::run_inversion:: CHL not monotonic" << std::endl;
532  return status;
533  break;
534  default:
535  std::cerr << "DbAlgOcean::run_inversion:: Unexpected status returned from locate" << std::endl;
536  return status;
537  break;
538  }
539  } else {
540  chl_frac = (chl_- lut->chl[cbeg])/(lut->chl[cbeg+1]-lut->chl[cbeg]);
541  }
542 
543 // Note: in here, the yXXX quantities are the interpolated I/F.
544 // the xXXX quantities are the value of parameter (e.g. angle) we are interpolating too.
545 // Those are not actually needed, but calculate them so you can print as a sanity check
546 // that you are interpolating where you think you are.
547  float ysza[2];
548  float yvza[2];
549  float ywspd[2];
550  float ychl[2];
551  num_fmf = lut->nfmf;
552  num_aot = lut->naot;
553  for (size_t iwv=0; iwv<lut->nwave; iwv++) { // wavelength
554  for (size_t ifmf=0; ifmf<lut->nfmf; ifmf++) { // fine mode fraction
555  for (size_t iaot=0; iaot<lut->naot; iaot++) { // AOT
556  for (size_t iws=0; iws<=1; iws++) { // WSPD
557  for (size_t isza=0; isza<=1; isza++) { // SZA
558  for (size_t ivza=0; ivza<=1; ivza++) { // VZA
559  switch (iwv) {
560 // M03
561  case (0):
562  for (size_t ichl=0; ichl<=1; ichl++) {
563  ychl[ichl] = lut->m03[cbeg+ichl][wbeg+iws][ifmf][iaot][rbeg][nbeg+ivza][mbeg+isza]*(1.0-raa_frac) +
564  lut->m03[cbeg+ichl][wbeg+iws][ifmf][iaot][rbeg+1][nbeg+ivza][mbeg+isza]*raa_frac;
565  }
566  yvza[ivza] = ychl[0]*(1.0-chl_frac) + ychl[1]*chl_frac;
567  break;
568 // M04
569  case (1):
570  for (size_t ichl=0; ichl<=1; ichl++) {
571  ychl[ichl] = lut->m04[cbeg+ichl][wbeg+iws][ifmf][iaot][rbeg][nbeg+ivza][mbeg+isza]*(1.0-raa_frac) +
572  lut->m04[cbeg+ichl][wbeg+iws][ifmf][iaot][rbeg+1][nbeg+ivza][mbeg+isza]*raa_frac;
573  }
574  yvza[ivza] = ychl[0]*(1.0-chl_frac) + ychl[1]*chl_frac;
575  break;
576 // M05
577  case (2):
578  for (size_t ichl=0; ichl<=1; ichl++) {
579  ychl[ichl] = lut->m05[cbeg+ichl][wbeg+iws][ifmf][iaot][rbeg][nbeg+ivza][mbeg+isza]*(1.0-raa_frac) +
580  lut->m05[cbeg+ichl][wbeg+iws][ifmf][iaot][rbeg+1][nbeg+ivza][mbeg+isza]*raa_frac;
581  }
582  yvza[ivza] = ychl[0]*(1.0-chl_frac) + ychl[1]*chl_frac;
583  break;
584 // M07
585  case (3):
586  for (size_t ichl=0; ichl<=1; ichl++) {
587  ychl[ichl] = lut->m07[cbeg+ichl][wbeg+iws][ifmf][iaot][rbeg][nbeg+ivza][mbeg+isza]*(1.0-raa_frac) +
588  lut->m07[cbeg+ichl][wbeg+iws][ifmf][iaot][rbeg+1][nbeg+ivza][mbeg+isza]*raa_frac;
589  }
590  yvza[ivza] = ychl[0]*(1.0-chl_frac) + ychl[1]*chl_frac;
591  break;
592 // M08
593  case (4):
594  yvza[ivza] = lut->m08[wbeg+iws][ifmf][iaot][rbeg][nbeg+ivza][mbeg+isza]*(1.0-raa_frac) +
595  lut->m08[wbeg+iws][ifmf][iaot][rbeg+1][nbeg+ivza][mbeg+isza]*raa_frac;
596  break;
597 // M10
598  case (5):
599  yvza[ivza] = lut->m10[wbeg+iws][ifmf][iaot][rbeg][nbeg+ivza][mbeg+isza]*(1.0-raa_frac) +
600  lut->m10[wbeg+iws][ifmf][iaot][rbeg+1][nbeg+ivza][mbeg+isza]*raa_frac;
601  break;
602 // M11
603  case (6):
604  yvza[ivza] = lut->m11[wbeg+iws][ifmf][iaot][rbeg][nbeg+ivza][mbeg+isza]*(1.0-raa_frac) +
605  lut->m11[wbeg+iws][ifmf][iaot][rbeg+1][nbeg+ivza][mbeg+isza]*raa_frac;
606  break;
607  default:
608  std::cerr << "DbAlgOcean::run_inversion:: Unexpected wavelength" << std::endl;
609  return status;
610  break;
611  }
612  }
613  ysza[isza] = yvza[0]*(1.0-vza_frac) + yvza[1]*vza_frac;
614  }
615  ywspd[iws] = ysza[0]*(1.0-sza_frac) + ysza[1]*sza_frac;
616  }
617  plut[iwv][ifmf][iaot] = ywspd[0]*(1.0-ws_frac) + ywspd[1]*ws_frac;
618  }
619  }
620  }
621  rfl[O488] = rfl_[(size_t)rhot_band::W490];
622  rfl[O550] = rfl_[(size_t)rhot_band::W550];
623  rfl[O670] = rfl_[(size_t)rhot_band::W670];
624  rfl[O865] = rfl_[(size_t)rhot_band::W865];
625  rfl[O1240] = rfl_[(size_t)rhot_band::W1240];
626  rfl[O1610] = rfl_[(size_t)rhot_band::W1610];
627  rfl[O2250] = rfl_[(size_t)rhot_band::W2250];
628 
629 /*
630 //-- calculate turbid water residual. If too high, skip becayse too turbid.
631 //-- Otherwise, run turbid IR retrieval below.
632  float turb = calc_turbid_residual(solz_, rfl_[(size_t)rhot_band::W490], rfl_[(size_t)rhot_band::W1240],
633  rfl_[(size_t)rhot_band::W1610], rfl_[(size_t)rhot_band::W2250], rfl_[(size_t)rhot_band::W550], status);
634  if (status != 0) {
635  std::cerr << "DbAlgOcean::run_inversion:: Turbid water residual calculation failure" << std::endl;
636  return status;
637  }
638 
639 //-- convert reduced look up table to differences and feed to
640 //-- Leverberg-Marquardt (lmdif1).
641 //-- For more info on lmdif1: http://www.netlib.org/minpack/lmdif1.f
642 //-- If over turbid water, switch to 4 IR band retrieval or skip.
643  short nbands = 0;
644  float rfactor = cos(solz_*DEGtoRAD)/M_PI;
645  if (turb >= 0.1*rfactor) {
646 // std::cerr << "DbAlgOcean::run_inversion:: Turbid water exceeds threshold." << std::endl;
647  status = 1;
648  return status;
649  } else if ((turb > 0.011*rfactor && turb < 0.1*rfactor) ||
650  (bathy_ > -20) || (pow(10,chl_) >= 3)) {
651 // mildly turbid water or shallow water (that is not too turbid), try IR retrieval.
652 // bathy > -x means water with a depth < x m. Note this also catches elevated inland water.
653  for (size_t i=0; i<lut->naot; i++) {
654  for (size_t j=0; j<lut->nfmf; j++) {
655  plut[O488][j][i] = 0.0;
656  plut[O550][j][i] = 0.0;
657  plut[O670][j][i] = 0.0;
658  plut[O865][j][i] = (plut[O865][j][i] - rfl_[(size_t)rhot_band::W865]) /
659  (0.08*(rfl_[(size_t)rhot_band::W865] + 0.00001));
660  plut[O1240][j][i] = (plut[O1240][j][i] - rfl_[(size_t)rhot_band::W1240]) /
661  (0.07*(rfl_[(size_t)rhot_band::W1240] + 0.00001));
662  plut[O1610][j][i] = (plut[O1610][j][i] - rfl_[(size_t)rhot_band::W1610]) /
663  (0.06*(rfl_[(size_t)rhot_band::W1610] + 0.00001));
664  plut[O2250][j][i] = (plut[O2250][j][i] - rfl_[(size_t)rhot_band::W2250]) /
665  (0.10*(rfl_[(size_t)rhot_band::W2250] + 0.00001));
666  }
667  }
668  nbands = 4;
669  iout->alg_flag = 1;
670  } else { // clear water, do full retrieval.
671  for (size_t i=0; i<lut->naot; i++) {
672  for (size_t j=0; j<lut->nfmf; j++) {
673  plut[O488][j][i] = (plut[O488][j][i] - rfl_[(size_t)rhot_band::W490]) /
674  (0.06*(rfl_[(size_t)rhot_band::W490] + 0.00001));
675  plut[O550][j][i] = (plut[O550][j][i] - rfl_[(size_t)rhot_band::W550]) /
676  (0.06*(rfl_[(size_t)rhot_band::W550] + 0.00001));
677  plut[O670][j][i] = (plut[O670][j][i] - rfl_[(size_t)rhot_band::W670]) /
678  (0.04*(rfl_[(size_t)rhot_band::W670] + 0.00001));
679  plut[O865][j][i] = (plut[O865][j][i] - rfl_[(size_t)rhot_band::W865]) /
680  (0.04*(rfl_[(size_t)rhot_band::W865] + 0.00001));
681  plut[O1240][j][i] = (plut[O1240][j][i] - rfl_[(size_t)rhot_band::W1240]) /
682  (0.07*(rfl_[(size_t)rhot_band::W1240] + 0.00001));
683  plut[O1610][j][i] = (plut[O1610][j][i] - rfl_[(size_t)rhot_band::W1610]) /
684  (0.06*(rfl_[(size_t)rhot_band::W1610] + 0.00001));
685  plut[O2250][j][i] = (plut[O2250][j][i] - rfl_[(size_t)rhot_band::W2250]) /
686  (0.10*(rfl_[(size_t)rhot_band::W2250] + 0.00001));
687  }
688  }
689  nbands = 7;
690  iout->alg_flag = 0;
691  }
692 
693 // -- calculate sum of squares of node points, find min and use as starting point
694  double node_ss[NFMF3][NAOT1];
695  double fvec[NOWL];
696  double mins[2] = {0.0,0.0};
697  float min_ss = 999999;
698  memset(node_ss, 0, NFMF3*NAOT1*sizeof(double));
699  memset(fvec, 0, NOWL*sizeof(double));
700 
701  for (size_t i=0; i<lut->naot; i++) {
702  for (size_t j=0; j<lut->nfmf; j++) {
703  float sum = 0;
704  for (size_t k=0; k<lut->nwave; k++) {
705  sum += plut[k][j][i]*plut[k][j][i];
706  }
707  node_ss[j][i] = sum / (nbands - 2);
708  if (node_ss[j][i] < min_ss) {
709  min_ss = node_ss[j][i];
710  mins[0] = j;
711  mins[1] = i;
712  }
713  }
714  }
715 
716  const double tol = 1e-6;
717  int iwa[2];
718  const int lwa = 32;
719  double wa[32];
720 
721 // -- mins[1] = AOT index, mins[0] = FMAF index
722  __minpack_func__(lmdif1)(fcn, &m, &n, &mins[0], &fvec[0], &tol,
723  &status, &iwa[0], &wa[0], &lwa);
724 
725  if (status == 0 || status > 4) { // || status > 3) lmdif1 failed!
726  iout->aot550 = DFILL_FLOAT;
727  for (int j=0; j<NOWL; j++) {
728  iout->aot[j] = DFILL_FLOAT;
729  }
730  iout->fmf = DFILL_FLOAT;
731  iout->ae = DFILL_FLOAT;
732  iout->chl = DFILL_FLOAT;
733  iout->alg_flag = DFILL_SHORT;
734  iout->model_flag = DFILL_SHORT;
735  status = -1;
736  return status;
737  }
738 */
739  double info[LM_INFO_SZ];
740  double opts[LM_OPTS_SZ];
741 
742  /*Optimisation control parameters*/
743  opts[0] = 1E-3; //1E-3 LM_INIT_MU; /* scale factor for initial mu */
744  opts[1] = 1E-10; //1E-10 LM_INIT_MU; convergence in gradient
745  opts[2] = 1E-5; //1E-5 relative error desired in the approximate solution
746  opts[3] = 1E-7; //1E-7 relative error desired in the sum of squares
747  opts[4] = 1E-6; //1E-6 LM_DIFF_DELTA; /*step used in difference approximation to the Jacobian*/
748 
749  double lowerBounds[2] = {0.0, 0.0}; //Lower bounds for two parameters
750  double upperBounds[2] = {8.0, 14.0}; //Upper bounds for two parameters
751  int maxit = 1000;
752  double fvec[NOWL] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0};
753  double fdif[NOWL] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0};
754  double mins[2] = {0.0,1.0};
755  const int m = 2;
756  const int n = NOWL;
757 
758  /*Run optimization*/
759  /*levmar routine (dlevmar), box contstraints (bc), numerical partials (diff)*/
760  //For further details, see source code in: lmbc_core.c //
761  status = dlevmar_bc_dif(fcn_lm, &mins[0], &fvec[0], m, n,
762  lowerBounds, upperBounds, NULL, maxit, opts, info, NULL,
763  NULL, NULL);
764 
765  fcn( &m, &n, &mins[0], &fvec[0], &fdif[0], 0 );
766 
767  if (status < 0) { // dlevmar_dif failed!
768  return status;
769  }
770 
771 // -- adjust indices to maximum table values if lmdif1 was successful.
772  if (mins[0] < 0) mins[0] = 0;
773  if (mins[0] >= lut->nfmf-1) mins[0] =
774  (double)lut->nfmf-1.001; // needs to be just under
775  if (mins[1] < 0) mins[1] = 0; // max node value to be
776  if (mins[1] >= lut->naot-1) mins[1] =
777  (double)lut->naot-1.001; // correctly interpolated.
778 
779 // -- calculate the sum of the squares of the residuals of all bands
780 // normalized by nbands - 2.
781  iout->ss = 0.0;
782  for (int i=0; i<NOWL; i++) {
783  iout->ss += fdif[i]*fdif[i];
784  }
785  iout->ss /= (NOWL - 2);
786 
787  // -- convert indices to AOT, FMAF, and AE values, linear interpolation used.
788  int j1 = floor(mins[0]);
789  int j2 = j1 + 1;
790  int i1 = floor(mins[1]);
791  int i2 = i1 + 1;
792 
793  iout->aot550 = lut->aot550[i1] + (mins[1]-i1)*(lut->aot550[i2]-lut->aot550[i1]);
794 
795  iout->aot[O488] = (lut->aot[O488][j1][i1]*(i2-mins[1])*(j2-mins[0])) +
796  (lut->aot[O488][j1][i2]*(mins[1]-i1)*(j2-mins[0])) +
797  (lut->aot[O488][j2][i1]*(i2-mins[1])*(mins[0]-j1)) +
798  (lut->aot[O488][j2][i2]*(mins[1]-i1)*(mins[0]-j1));
799  iout->aot[O550] = (lut->aot[O550][j1][i1]*(i2-mins[1])*(j2-mins[0])) +
800  (lut->aot[O550][j1][i2]*(mins[1]-i1)*(j2-mins[0])) +
801  (lut->aot[O550][j2][i1]*(i2-mins[1])*(mins[0]-j1)) +
802  (lut->aot[O550][j2][i2]*(mins[1]-i1)*(mins[0]-j1));
803  iout->aot[O670] = (lut->aot[O670][j1][i1]*(i2-mins[1])*(j2-mins[0])) +
804  (lut->aot[O670][j1][i2]*(mins[1]-i1)*(j2-mins[0])) +
805  (lut->aot[O670][j2][i1]*(i2-mins[1])*(mins[0]-j1)) +
806  (lut->aot[O670][j2][i2]*(mins[1]-i1)*(mins[0]-j1));
807  iout->aot[O865] = (lut->aot[O865][j1][i1]*(i2-mins[1])*(j2-mins[0])) +
808  (lut->aot[O865][j1][i2]*(mins[1]-i1)*(j2-mins[0])) +
809  (lut->aot[O865][j2][i1]*(i2-mins[1])*(mins[0]-j1)) +
810  (lut->aot[O865][j2][i2]*(mins[1]-i1)*(mins[0]-j1));
811  iout->aot[O1240] = (lut->aot[O1240][j1][i1]*(i2-mins[1])*(j2-mins[0])) +
812  (lut->aot[O1240][j1][i2]*(mins[1]-i1)*(j2-mins[0])) +
813  (lut->aot[O1240][j2][i1]*(i2-mins[1])*(mins[0]-j1)) +
814  (lut->aot[O1240][j2][i2]*(mins[1]-i1)*(mins[0]-j1));
815  iout->aot[O1610] = (lut->aot[O1610][j1][i1]*(i2-mins[1])*(j2-mins[0])) +
816  (lut->aot[O1610][j1][i2]*(mins[1]-i1)*(j2-mins[0])) +
817  (lut->aot[O1610][j2][i1]*(i2-mins[1])*(mins[0]-j1)) +
818  (lut->aot[O1610][j2][i2]*(mins[1]-i1)*(mins[0]-j1));
819  iout->aot[O2250] = (lut->aot[O2250][j1][i1]*(i2-mins[1])*(j2-mins[0])) +
820  (lut->aot[O2250][j1][i2]*(mins[1]-i1)*(j2-mins[0])) +
821  (lut->aot[O2250][j2][i1]*(i2-mins[1])*(mins[0]-j1)) +
822  (lut->aot[O2250][j2][i2]*(mins[1]-i1)*(mins[0]-j1));
823 
824  iout->ae = (lut->ae[j1][i1]*(i2-mins[1])*(j2-mins[0])) +
825  (lut->ae[j1][i2]*(mins[1]-i1)*(j2-mins[0])) +
826  (lut->ae[j2][i1]*(i2-mins[1])*(mins[0]-j1)) +
827  (lut->ae[j2][i2]*(mins[1]-i1)*(mins[0]-j1));
828 
829  iout->fmf = lut->fmf[j1]+(mins[0]-j1)*(lut->fmf[j2]-lut->fmf[j1]);
830 
831  iout->chl = chl_;
832 
833  return status;
834 }
835 
836 
837  /**************************************************************************
838  * NAME: fcn_lm()
839  *
840  * DESCRIPTION: function for levmar
841  *
842  *************************************************************************/
843 
844  void fcn_lm(double *x, double *fvec, int m, int n, void *adata)
845  {
846  int flag;
847  double fdif[NOWL] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0};
848  string func_name = "fcn_lm";
849 
850  fcn( &n, &m, x, fvec, fdif, &flag );
851  }
852 
853 
854  /**************************************************************************
855  * NAME: fcn()
856  *
857  * DESCRIPTION: function for lmdif1, returns lut values for indices
858  * specified in x
859  *
860  *************************************************************************/
861 
862  void fcn(const int* m, const int* n, const double* x,
863  double* fvec, double* fdif, int* iflag)
864  {
865  string func_name = "fcn";
866 
867 // -- x values may be out of bounds for the lut.
868 // -- limit to size of plut
869  double tx[2];
870  tx[0] = x[0];
871  tx[1] = x[1];
872  int j = floor(x[0]);
873  int i = floor(x[1]);
874  if (i < 0) {
875  i = 0;
876 // tx[1] = 0.0;
877  }
878  if (j < 0) {
879  j = 0;
880  tx[0] = 0.0;
881  }
882  if (i > num_aot-2) {
883  i = num_aot-2;
884  tx[1] = num_aot-1;
885  }
886  if (j > num_fmf-2) {
887  j = num_fmf-2;
888  tx[0] = num_fmf-1;
889  }
890 
891 // -- bilinear interpolation of reduced look up table to indices x[0], x[1].
892  float f[NOWL];
893  f[O488] = (plut[O488][j][i])*(i+1-tx[1])*(j+1-tx[0]) +
894  (plut[O488][j][i+1])*(tx[1]-i)*(j+1-tx[0]) +
895  (plut[O488][j+1][i])*(i+1-tx[1])*(tx[0]-j) +
896  (plut[O488][j+1][i+1])*(tx[1]-i)*(tx[0]-j);
897  f[O550] = (plut[O550][j][i])*(i+1-tx[1])*(j+1-tx[0]) +
898  (plut[O550][j][i+1])*(tx[1]-i)*(j+1-tx[0]) +
899  (plut[O550][j+1][i])*(i+1-tx[1])*(tx[0]-j) +
900  (plut[O550][j+1][i+1])*(tx[1]-i)*(tx[0]-j);
901  f[O670] = (plut[O670][j][i])*(i+1-tx[1])*(j+1-tx[0]) +
902  (plut[O670][j][i+1])*(tx[1]-i)*(j+1-tx[0]) +
903  (plut[O670][j+1][i])*(i+1-tx[1])*(tx[0]-j) +
904  (plut[O670][j+1][i+1])*(tx[1]-i)*(tx[0]-j);
905  f[O865] = (plut[O865][j][i])*(i+1-tx[1])*(j+1-tx[0]) +
906  (plut[O865][j][i+1])*(tx[1]-i)*(j+1-tx[0]) +
907  (plut[O865][j+1][i])*(i+1-tx[1])*(tx[0]-j) +
908  (plut[O865][j+1][i+1])*(tx[1]-i)*(tx[0]-j);
909  f[O1240] = (plut[O1240][j][i])*(i+1-tx[1])*(j+1-tx[0]) +
910  (plut[O1240][j][i+1])*(tx[1]-i)*(j+1-tx[0]) +
911  (plut[O1240][j+1][i])*(i+1-tx[1])*(tx[0]-j) +
912  (plut[O1240][j+1][i+1])*(tx[1]-i)*(tx[0]-j);
913  f[O1610] = (plut[O1610][j][i])*(i+1-tx[1])*(j+1-tx[0]) +
914  (plut[O1610][j][i+1])*(tx[1]-i)*(j+1-tx[0]) +
915  (plut[O1610][j+1][i])*(i+1-tx[1])*(tx[0]-j) +
916  (plut[O1610][j+1][i+1])*(tx[1]-i)*(tx[0]-j);
917  f[O2250] = (plut[O2250][j][i])*(i+1-tx[1])*(j+1-tx[0]) +
918  (plut[O2250][j][i+1])*(tx[1]-i)*(j+1-tx[0]) +
919  (plut[O2250][j+1][i])*(i+1-tx[1])*(tx[0]-j) +
920  (plut[O2250][j+1][i+1])*(tx[1]-i)*(tx[0]-j);
921 
922  float fd[NOWL];
923  fd[O488] = f[O488] - rfl[O488];
924  fd[O550] = f[O550] - rfl[O550];
925  fd[O670] = f[O670] - rfl[O670];
926  fd[O865] = f[O865] - rfl[O865];
927  fd[O1240] = f[O1240] - rfl[O1240];
928  fd[O1610] = f[O1610] - rfl[O1610];
929  fd[O2250] = f[O2250] - rfl[O2250];
930 
931  fvec[O488] = fd[O488] / (0.06*(rfl[O488] + 0.00001));
932  fvec[O550] = fd[O550] / (0.06*(rfl[O550] + 0.00001));
933  fvec[O670] = fd[O670] / (0.04*(rfl[O670] + 0.00001));
934  fvec[O865] = fd[O865] / (0.04*(rfl[O865] + 0.00001));
935  fvec[O1240] = fd[O1240] / (0.07*(rfl[O1240] + 0.00001));
936  fvec[O1610] = fd[O1610] / (0.06*(rfl[O1610] + 0.00001));
937  fvec[O2250] = fd[O2250] / (0.10*(rfl[O2250] + 0.00001));
938 
939  fdif[O488] = fd[O488] / rfl[O488];
940  fdif[O550] = fd[O550] / rfl[O550];
941  fdif[O670] = fd[O670] / rfl[O670];
942  fdif[O865] = fd[O865] / rfl[O865];
943  fdif[O1240] = fd[O1240] / rfl[O1240];
944  fdif[O1610] = fd[O1610] / rfl[O1610];
945  fdif[O2250] = fd[O2250] / rfl[O2250];
946 
947  return;
948 }
949 
950 /**************************************************************************
951  * NAME: calc_glint_refl()
952  *
953  * DESCRIPTION: Calculate reflectance from glint region.
954  *
955  *************************************************************************/
956 
957 float DbAlgOcean::calc_glint_refl(size_t iy, size_t ix, int& status)
958 {
959  double cc = DEGtoRAD;
960  float nr = 1.341;
961 
962  double zx = (sin(senz_*cc)*sin(raa_*cc))/(cos(solz_*cc)+cos(senz_*cc));
963  double zy = (sin(solz_*cc)-sin(senz_*cc)*cos(raa_*cc))/(cos(solz_*cc)+cos(senz_*cc));
964  double sigx = sqrt(0.003+0.00192*ws_);
965  double sigy = sqrt(0.00316*ws_);
966  double zeta = zx / sigx;
967  double eta = zy / sigy;
968  double p = (1.0/(2.0*M_PI*sigx*sigy))*exp(-0.5*(zeta*zeta + eta*eta));
969  double costwoomega = cos(senz_*cc)*cos(solz_*cc) -
970  sin(senz_*cc)*sin(solz_*cc)*cos(raa_*cc);
971  double cosbeta = (cos(solz_*cc)+cos(senz_*cc))/(sqrt(2.0 + 2.0*costwoomega));
972  double w = 0.5 * acos(costwoomega);
973  double wp = asin(sin(w)/nr);
974  double a1 = sin(w - wp);
975  double b1 = sin(w+wp);
976  double c1 = tan(w-wp);
977  double d1 = tan(w+wp);
978  double R = 0.5*((a1*a1)/(b1*b1)+(c1*c1)/(d1*d1));
979 // double rgl = PI * p * R/(4*cos(solz_*cc)*cos(senz_*cc)*pow(cosbeta,4.0));
980  float glint_refl = p*R/(4*cos(senz_*cc)*pow(cosbeta,4.0));
981 
982  return glint_refl;
983 }
984 
985 /**************************************************************************
986  * NAME: calc_turbid_residual()
987  *
988  * DESCRIPTION: Calculate turbid water residual.
989  *
990  *************************************************************************/
991 
992 float DbAlgOcean::calc_turbid_residual(float sza, float r488,
993  float r1240, float r1600, float r2250, float r550, int& status )
994 {
995 
996  float x[4] = {0.486, 1.238, 1.601, 2.257};
997  float y[4] = {r488, r1240, r1600, r2250};
998  for (int i=0; i<4; i++) {
999  x[i] = log10(x[i]);
1000  y[i] = log10(y[i]);
1001  }
1002  float r[2];
1003  status = linfit(4, x, y, r);
1004  if (status != 0) {
1005  std::cerr << "DbAlgOcean::calc_turbid_residual:: Linfit error" << std::endl;
1006  return DFILL_FLOAT;
1007  }
1008  float est550 = r[0] + log10(0.551)*r[1];
1009  est550 = pow(10.0, est550);
1010 // -- calculate residual and convert to standard reflectance units via cos(sza)/pi.
1011  float res = r550 - est550;
1012 
1013  return res;
1014 }
1015 
1016 /**************************************************************************
1017  * NAME: linfit()
1018  *
1019  * DESCRIPTION: Compute linear fit for data in x and y arrays.
1020  *
1021  *************************************************************************/
1022 
1023 int DbAlgOcean::linfit(int size, float x[], float y[], float r[])
1024 {
1025  float sx = 0.0;
1026  float sy = 0.0;
1027  float sxy = 0.0;
1028  float sxx = 0.0;
1029  float syy = 0.0;
1030  for (int i=0; i<size; i++) {
1031  sx = sx + x[i];
1032  sy = sy + y[i];
1033  sxx = sxx + (x[i] * x[i]);
1034  sxy = sxy + (x[i] * y[i]);
1035  syy = syy + (y[i] * y[i]);
1036  }
1037 
1038  r[1] = ((size*sxy) - (sx*sy))/((size*sxx)-(sx*sx));
1039  r[0] = (sy/size)-(r[1]*sx/size);
1040 
1041  return DTDB_SUCCESS;
1042 }
1043 
1044 /**************************************************************************
1045  * NAME: set_fill_out()
1046  *
1047  * DESCRIPTION: Set output fill values.
1048  *
1049  *************************************************************************/
1050 
1052 {
1053  int status = DTDB_SUCCESS;
1054 
1055  for (int i=0; i<NDBMDL+1; i++) {
1056  oOut_[i].aot550 = DFILL_FLOAT;
1057  oOut_[i].fmf = DFILL_FLOAT;
1058  oOut_[i].ae = DFILL_FLOAT;
1059  oOut_[i].ss = DFILL_FLOAT;
1060  oOut_[i].chl = DFILL_FLOAT;
1061  oOut_[i].alg_flag = DFILL_SHORT;
1062  oOut_[i].model_flag = DFILL_SHORT;
1063  for (int j=0; j<NOWL; j++) {
1064  oOut_[i].aot[j] = DFILL_FLOAT;
1065  }
1066  }
1067  mask_cm_ = DFILL_SHORT;
1068 
1069  return status;
1070 }
boost::multi_array< float, 1 > vza
Definition: DbLutNetcdf.h:293
int r
Definition: decode_rs.h:73
boost::multi_array< float, 1 > aot550
Definition: DbLutNetcdf.h:295
int set_fill_out()
boost::multi_array< float, 7 > m04
Definition: DbLutNetcdf.h:286
int j
Definition: decode_rs.h:73
int linfit(int size, float x[], float y[], float r[])
int16 iflag[18338]
@ O488
Definition: DbAlgorithm.h:20
@ O1610
Definition: DbAlgorithm.h:25
int status
Definition: l1_czcs_hdf.c:32
constexpr unsigned char DFILL_UBYTE
Definition: DDataset.hpp:28
const static size_t nwave
Definition: DbLutNetcdf.h:284
const string LUT_OCEAN_AEROSOL_DUST
Definition: DDOptions.cpp:144
map< string, ddata * > process(vector< size_t > start, vector< size_t > count, map< string, ddata * > imap)
Definition: DbAlgOcean.cpp:143
constexpr float DFILL_TEST
Definition: DDataset.hpp:26
float plut[NOWL][NFMF3][NAOT1]
Definition: DbAlgOcean.cpp:42
These are used to scale the SD before writing it to the HDF4 file The default is and which means the product is not scaled at all Since the product is usually stored as a float inside of this is a way to write the float out as a integer l2prod min
int maxit
@ O2250
Definition: DbAlgorithm.h:26
@ MIX
Definition: DbAlgorithm.h:48
#define NULL
Definition: decode_rs.h:63
const static size_t nchl
Definition: DbLutNetcdf.h:283
@ BOWTIEDEL
@ O865
Definition: DbAlgorithm.h:23
float aot[NOWL]
Definition: DbAlgorithm.h:223
boost::multi_array< float, 1 > chl
Definition: DbLutNetcdf.h:298
float rfl[NOWL]
Definition: DbAlgOcean.cpp:41
const static size_t nwspd
Definition: DbLutNetcdf.h:282
int num_aot
Definition: DbAlgOcean.cpp:44
int read_ocean_aero_lut(dbOceanAerosolLUMA *lut, const string sType)
u5 which has been done in the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT production Changes from v6 which may affect scientific the sector rotation may actually occur during one of the scans earlier than the one where it is first reported As a the b1 values are about the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT to fill pixels affected by dead subframes with a special value Output the metadata of noisy and dead subframe Dead Subframe EV and Detector Quality Flag2 Removed the function call of Fill_Dead_Detector_SI to stop interpolating SI values for dead but also for all downstream products for science test only Changes from v5 which will affect scientific to conform to MODIS requirements Removed the Mixed option from the ScanType in the code because the L1A Scan Type is never Mixed Changed for ANSI C compliance and comments to better document the fact that when the HDF_EOS metadata is stricly the and products are off by and in the track respectively Corrected some misspelling of RCS swir_oob_sending_detector to the Reflective LUTs to enable the SWIR OOB correction detector so that if any of the sending detectors becomes noisy or non near by good detectors from the same sending band can be specified as the substitute in the new look up table Code change for adding an additional dimension of mirror side to the Band_21_b1 LUT to separate the coefficient of the two mirror sides for just like other thermal emissive so that the L1B code can calibrate Band scan to scan with mirror side dependency which leads better calibration result Changes which do not affect scientific when the EV data are not provided in this Crosstalk Correction will not be performed to the Band calibration data Changes which do not affect scientific and BB_500m in L1A Logic was added to turn off the or to spatial aggregation processes and the EV_250m_Aggr1km_RefSB and EV_500m_Aggr1km_RefSB fields were set to fill values when SDSs EV_250m and EV_500m are absent in L1A file Logic was added to skip the processing and turn off the output of the L1B QKM and HKM EV data when EV_250m and EV_500m are absent from L1A In this case
Definition: HISTORY.txt:343
character(len=1000) if
Definition: names.f90:13
void fcn(const int *m, const int *n, const double *x, double *fvec, double *fdif, int *iflag)
Definition: DbAlgOcean.cpp:862
@ DUST
Definition: DbAlgorithm.h:45
@ O550
Definition: DbAlgorithm.h:21
boost::multi_array< float, 1 > raa
Definition: DbLutNetcdf.h:294
#define DB_RFL_BANDS
Definition: DDOptions.h:48
double precision function f(R1)
Definition: tmd.lp.f:1454
int initialize_LUT_data()
Definition: DbAlgOcean.cpp:111
const string LUT_OCEAN_AEROSOL_MIX
Definition: DDOptions.cpp:146
const string LUT_OCEAN_AEROSOL_MARI
Definition: DDOptions.cpp:145
const string LUT_OCEAN_AEROSOL_FINE
Definition: DDOptions.cpp:143
boost::multi_array< float, 7 > m05
Definition: DbLutNetcdf.h:287
int read_bathymetry_lut(dbBathymetryLUT *lut)
boost::multi_array< float, 1 > wspd
Definition: DbLutNetcdf.h:297
boost::multi_array< float, 7 > m07
Definition: DbLutNetcdf.h:288
@ O1240
Definition: DbAlgorithm.h:24
int run_inversion(size_t iy, size_t ix, dbOceanAerosolLUMA *lut, osOut *iout)
Definition: DbAlgOcean.cpp:442
#define M_PI
Definition: pml_iop.h:15
integer, parameter double
boost::multi_array< float, 6 > m10
Definition: DbLutNetcdf.h:290
OMODEL_ENUM
Definition: DbAlgorithm.h:44
constexpr float DFILL_FLOAT
Definition: DDataset.hpp:25
boost::multi_array< float, 1 > fmf
Definition: DbLutNetcdf.h:296
boost::multi_array< float, 1 > sza
Definition: DbLutNetcdf.h:292
instead the metadata field ProcessingEnvinronment is filled in from the output of a call to the POSIX compliant function uname from within the L1B code A small bug in L1B_Tables an incorrect comparison of RVS coefficients for TEBs to RVS coefficients for RSBs was being made This was replaced with a comparison between TEB coefficients This error never resulted in an incorrect RVS correction but did lead to recalculating the coefficients for each detector in a thermal band even if the coefficients were the same for all detectors To reduce to overall size of the reflective LUT HDF fill values were eliminated from all LUTs previously dimensioned where and where NUM_TIMES is the number of time dependent table pieces In Preprocess a small error where the trailing dropped scan counter was incremented when the leading dropped scan counter should have been was fixed This counter is internal only and is not yet used for any chiefly to casting of were added to make it LINUX compatible Output of code run on LINUX machines displays differences of at most scaled sector incalculable values of the Emissive calibration factor b1
Definition: HISTORY.txt:576
subroutine locate(xx, n, x, j)
int initialize(map< string, ddata * > imap)
Definition: DbAlgOcean.cpp:84
@ O670
Definition: DbAlgorithm.h:22
@ BEST
Definition: DbAlgorithm.h:49
@ NMODEL
Definition: DbAlgorithm.h:50
@ MARI
Definition: DbAlgorithm.h:47
virtual int initialize(map< string, ddata * > imap)
Definition: DbAlgorithm.cpp:89
boost::multi_array< float, 7 > m03
Definition: DbLutNetcdf.h:285
float calc_glint_refl(size_t iy, size_t ix, int &status)
Definition: DbAlgOcean.cpp:957
def set_outputs(output_keys)
Definition: utils.py:164
for(i=0;i< NROOTS;i++) s[i]
Definition: decode_rs.h:85
int num_fmf
Definition: DbAlgOcean.cpp:43
#define R
Definition: make_L3_v1.1.c:96
float calc_turbid_residual(float sza, float r488, float r1240, float r1600, float r2250, float r550, int &status)
Definition: DbAlgOcean.cpp:992
@ FINE
Definition: DbAlgorithm.h:46
void fcn_lm(double *fvec, double *x, const int m, const int n, void *adata)
Definition: DbAlgOcean.cpp:844
int read_chl_lut(dbChlLUT *lut)
int i
Definition: decode_rs.h:71
boost::multi_array< float, 6 > m08
Definition: DbLutNetcdf.h:289
boost::multi_array< float, 3 > aot
Definition: DbLutNetcdf.h:301
constexpr short DFILL_SHORT
Definition: DDataset.hpp:27
float p[MODELMAX]
Definition: atrem_corl1.h:131
boost::multi_array< float, 6 > m11
Definition: DbLutNetcdf.h:291
int count
Definition: decode_rs.h:79
boost::multi_array< float, 2 > ae
Definition: DbLutNetcdf.h:300