OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
atmocor2.c
Go to the documentation of this file.
1 #include "l12_proto.h"
2 #include "atrem_corl1.h"
3 
4 /* --------------------------------------------------------------------------------------- */
5 /* atmocor2() - atmospheric correction, converts Lt -> nLw */
6 /* */
7 /* C-version, September 2004, B. Franz */
8 
9 /* --------------------------------------------------------------------------------------- */
10 
11 int atmocor2(l2str *l2rec, aestr *aerec, int32_t ip) {
12  static int firstCall = 1;
13  static int want_nirRrs = 0;
14  static int want_nirLw = 0;
15  static int want_mumm = 0;
16  static int want_ramp = 1;
17  static int32_t aer_iter_max = 1;
18  static int32_t aer_iter_min = 1;
19 
20  static float pi = PI;
21  static float radeg = RADEG;
22  static float badval = BAD_FLT;
23  static float badchl = BAD_FLT;
24  static float p0 = STDPR;
25  static float df = 0.33;
26  static float cbot = 0.7;
27  static float ctop = 1.3;
28  static float seed_chl = 0.0;
29  static float seed_green = 0.0;
30  static float seed_red = 0.0;
31  static float nir_chg = 0.02;
32  static float glint_min = GLINT_MIN;
33  static float cslp;
34  static float cint;
35 
36  static int32_t green;
37  static int32_t red;
38  static int32_t nir_s;
39  static int32_t nir_l;
40  static int32_t swir_s;
41  static int32_t swir_l;
42  static int32_t aer_s;
43  static int32_t aer_l;
44  static int32_t daer;
45  static int32_t nwvis;
46  static int32_t nwave;
47  static float *wave;
48 
49  l1str *l1rec = l2rec->l1rec;
50  filehandle *l1file = l1rec->l1file;
51 
52  int32_t sensorID = l1file->sensorID;
53  int32_t brdf_opt = input->brdf_opt;
54  int32_t aer_opt = input->aer_opt;
55  int32_t glint_opt = input->glint_opt;
56  int32_t cirrus_opt = input->cirrus_opt;
57 
58  float *Fo = l1rec->Fo;
59  float *Fobar = l1file->Fobar;
60  float fsol = l1rec->fsol;
61  float solz = l1rec->solz [ip];
62  float senz = l1rec->senz [ip];
63  float delphi = l1rec->delphi[ip];
64  float ws = l1rec->ws [ip];
65  float gc = l1rec->glint_coef[ip];
66 
67  int32_t *aermodmin = &l2rec->aermodmin[ip];
68  int32_t *aermodmax = &l2rec->aermodmax[ip];
69  float *aermodrat = &l2rec->aerratio [ip];
70  int32_t *aermodmin2 = &l2rec->aermodmin2[ip];
71  int32_t *aermodmax2 = &l2rec->aermodmax2[ip];
72  float *aermodrat2 = &l2rec->aerratio2 [ip];
73  float *eps = &l2rec->eps [ip];
74 
75  float *TLg = &l1rec->TLg [ip * l1file->nbands];
76  float *Lw = &l2rec->Lw [ip * l1file->nbands];
77  float *nLw = &l2rec->nLw [ip * l1file->nbands];
78  float *La = &l2rec->La [ip * l1file->nbands];
79  float *taua = &l2rec->taua [ip * l1file->nbands];
80  float *t_sol = &l1rec->t_sol[ip * l1file->nbands];
81  float *t_sen = &l1rec->t_sen[ip * l1file->nbands];
82  float *brdf = &l2rec->brdf [ip * l1file->nbands];
83  float *Rrs = &l2rec->Rrs [ip * l1file->nbands];
84 
85  float *nLw_unc = &l2rec->nLw_unc[ip * l1file->nbands];
86  float *Rrs_unc = &l2rec->Rrs_unc[ip * l1file->nbands];
87 
88  float *tg_sol = &l1rec->tg_sol[ip * l1file->nbands];
89 
90  float *taur;
91  float *tLw;
92  float *rhown_nir;
93  float *tLw_nir, *last_tLw_nir;
94  int32_t ib, ipb;
95  int32_t status;
96  int32_t iter, iter_max, iter_min, last_iter, iter_reset;
97  float mu, mu0;
98  int32_t nneg;
99  float airmass;
100  float *Ltemp;
101  float *Lunc;
102  float chl;
103  int want_glintcorr;
104  float refl_nir = 0, last_refl_nir = 0;
105  float tindx;
106  float Ka = 0.8; /* 1.375 um channel transmittance for water vapor (<=1) Gao et al. 1998 JGR */
107 
108  if (firstCall == 1) {
109  firstCall = 0;
110  nwave = l1file->nbands;
111  if ((wave = (float *) calloc(nwave, sizeof (float))) == NULL) {
112  printf("-E- : Error allocating memory to wave\n");
113  exit(FATAL_ERROR);
114  }
115  for (ib = 0; ib < nwave; ib++) {
116  wave[ib] = l1file->fwave[ib];
117  }
118  if (sensorID == CZCS) {
119  want_ramp = 0;
120  seed_chl = 0.01;
121  seed_green = 0.003;
122  seed_red = 0.00125;
123  }
124  nwvis = rdsensorinfo(l1file->sensorID, l1_input->evalmask, "NbandsVIS", NULL);
125  nir_s = bindex_get(input->aer_wave_short);
126  nir_l = bindex_get(input->aer_wave_long);
127  if (nir_s < 0 || nir_l < 0) {
128  printf("Aerosol selection bands %d and %d not available for this sensor\n",
129  input->aer_wave_short, input->aer_wave_long);
130  exit(1);
131  }
132  if (nir_l < nir_s) {
133  printf("Invalid aerosol selection bands: long (%d) must be greater than short (%d).\n",
134  input->aer_wave_long, input->aer_wave_short);
135  exit(1);
136  }
137  if (wave[nir_s] < 600) {
138  printf("Aerosol selection band(s) must be greater than 600nm");
139  exit(1);
140  }
141 
142  aer_s = nir_s;
143  aer_l = nir_l;
144  daer = MAX(nir_l - nir_s, 1);
145  cslp = 1. / (ctop - cbot);
146  cint = -cslp * cbot;
147  printf("Aerosol selection bands %d and %d\n", l1file->iwave[aer_s], l1file->iwave[aer_l]);
148 
149  switch (aer_opt) {
150  case AERWANGNIR:
151  case AERRHNIR:
152  case FIXANGSTROMNIR:
153  case FIXMODPAIRNIR:
154  want_nirLw = 1;
155  aer_iter_min = 1;
156  aer_iter_max = input->aer_iter_max;
157  printf("NIR correction enabled.\n");
158  break;
159  case AERMUMM:
160  case AERRHMUMM:
161  want_mumm = 1;
162  aer_iter_min = 3;
163  aer_iter_max = input->aer_iter_max;
164  printf("MUMM correction enabled.\n");
165  break;
166  case AERWANGSWIR:
167  case AERRHSWIR:
168  want_nirLw = 1;
169  aer_iter_min = 1;
170  aer_iter_max = input->aer_iter_max;
171  swir_s = bindex_get(input->aer_swir_short);
172  swir_l = bindex_get(input->aer_swir_long);
173  if (swir_s < 0 || swir_l < 0) {
174  printf("Aerosol selection bands %d and %d not available for this sensor\n",
175  input->aer_swir_short, input->aer_swir_long);
176  exit(1);
177  }
178  printf("NIR/SWIR switching correction enabled.\n");
179  break;
180  case AERRHMSEPS:
181  want_nirLw = 1;
182  aer_iter_min = 1;
183  aer_iter_max = input->aer_iter_max;
184  printf("NIR correction enabled --> for multi-scattering epsilon.\n");
185  break;
186  case AERRHSM:
187  want_nirLw = 1; //This needs to be turned on, but a new SWIR water model is needed for it to work
188  aer_iter_min = 1;
189  aer_iter_max = input->aer_iter_max;
190  printf("NIR correction enabled --> for spectral matching.\n");
191  break;
192  default:
193  if (input->aer_rrs_short >= 0.0 && input->aer_rrs_long >= 0.0) {
194  want_nirRrs = 1;
195  aer_iter_min = 3;
196  aer_iter_max = input->aer_iter_max;
197  printf("NIR correction via input Rrs enabled.\n");
198  }
199  break;
200  }
201  if (input->aer_iter_max < 1)
202  want_nirLw = 0;
203  if ( want_nirLw || want_nirRrs) {
204  if ((red = bindex_get(670)) < 0) {
205  if ((red = bindex_get(680)) < 0)
206  if ((red = bindex_get(620)) < 0)
207  if ((red = bindex_get(765)) < 0)
208  if ((red = bindex_get(655)) < 0)
209  if ((red = bindex_get(664)) < 0) /* added for MSI */ {
210  printf("%s line %d: can't find red band\n", __FILE__, __LINE__);
211  exit(1);
212  }
213  }
214  if ((green = bindex_get(550)) < 0) {
215  if ((green = bindex_get(555)) < 0)
216  if ((green = bindex_get(560)) < 0)
217  if ((green = bindex_get(565)) < 0) {
218  printf("%s line %d: can't find green band\n", __FILE__, __LINE__);
219  exit(1);
220  }
221  }
222  }
223 
224  }
225 
226  if ((taur = (float *) calloc(nwave, sizeof (float))) == NULL) {
227  printf("-E- : Error allocating memory to taur\n");
228  exit(FATAL_ERROR);
229  }
230  if ((tLw = (float *) calloc(nwave, sizeof (float))) == NULL) {
231  printf("-E- : Error allocating memory to tLw\n");
232  exit(FATAL_ERROR);
233  }
234  if ((rhown_nir = (float *) calloc(nwave, sizeof (float))) == NULL) {
235  printf("-E- : Error allocating memory to rhown_nir\n");
236  exit(FATAL_ERROR);
237  }
238  if ((tLw_nir = (float *) calloc(nwave, sizeof (float))) == NULL) {
239  printf("-E- : Error allocating memory to tLw_nir\n");
240  exit(FATAL_ERROR);
241  }
242  if ((last_tLw_nir = (float *) calloc(nwave, sizeof (float))) == NULL) {
243  printf("-E- : Error allocating memory to last_tLw_nir\n");
244  exit(FATAL_ERROR);
245  }
246  if ((Ltemp = (float *) calloc(nwave, sizeof (float))) == NULL) {
247  printf("-E- : Error allocating memory to Ltemp\n");
248  exit(FATAL_ERROR);
249  }
250  if ((Lunc = (float *) calloc(nwave, sizeof (float))) == NULL) {
251  printf("-E- : Error allocating memory to Lunc\n");
252  exit(FATAL_ERROR);
253  }
254 
255  /* Initialize output values. If any input radiances are negative, just return. */
256 
257  status = 0;
258  iter = 0;
259  nneg = 0;
260 
261  for (ib = 0; ib < nwave; ib++) {
262 
263  ipb = ip * nwave + ib;
264 
265  //t_sol [ib] = 1.0; leave them as rayleigh only
266  //t_sen [ib] = 1.0;
267  La [ib] = badval;
268  tLw [ib] = badval;
269  Lw [ib] = badval;
270  nLw [ib] = badval;
271  taua [ib] = badval;
272  if (glint_opt != 2) TLg [ib] = 0.0;
273  brdf [ib] = 1.0;
274  Rrs [ib] = badval;
275 
276  l2rec->eps[ip] = badval;
277 
278  if (l2rec->l1rec->Lt[ipb] <= 0.0)
279  if (wave[ib] < 1000) nneg++; /* don't test SWIR */
280  }
281 
282  /* If any expected channels are negative */
283  if (nneg > 0) {
284  free(taur);
285  free(tLw);
286  free(rhown_nir);
287  free(tLw_nir);
288  free(last_tLw_nir);
289  free(Ltemp);
290  free(Lunc);
291 
292  status = 1;
293  return (status);
294  }
295 
296  mu0 = cos(solz / radeg);
297  mu = cos(senz / radeg);
298  airmass = 1.0 / mu0 + 1.0 / mu;
299 
300  /* Remove pre-computed atmospheric effects */
301  /* --------------------------------------- */
302  for (ib = 0; ib < nwave; ib++) {
303 
304  ipb = ip * nwave + ib;
305 
306  /* Pressure correct the Rayleigh optical thickness */
307  taur[ib] = l1rec->pr[ip] / p0 * l1file->Tau_r[ib];
308 
309  /* Copy TOA radiance to temp var, eliminate missing bands */
310  Ltemp[ib] = l2rec->l1rec->Lt[ipb];
311  Lunc [ib] = l2rec->l1rec->Lt_unc[ipb];
312 
313  /* Correct for ozone absorption. We correct for inbound and outbound here, */
314  /* then we put the inbound back when computing Lw. */
315  Ltemp[ib] = Ltemp[ib] / l1rec->tg_sol[ipb] / l1rec->tg_sen[ipb];
316  Lunc [ib] = Lunc [ib] / l1rec->tg_sol[ipb] / l1rec->tg_sen[ipb];
317 
318  /* Do Cirrus correction - subtract off cirrus reflectance from Ltemp */
319  /* Ka is the 1.375 um transmittance of water vapor above cirrus clouds */
320  /* Add cirrus_opt to input */
321  if (cirrus_opt) Ltemp[ib] -= l1rec->rho_cirrus[ip] / Ka * Fo[ib] * mu0 / pi;
322 
323  /* Apply polarization correction */
324  Ltemp[ib] /= l1rec->polcor[ipb];
325  Lunc [ib] /= l1rec->polcor[ipb];
326 
327  /* Remove whitecap radiance */
328  Ltemp[ib] -= l1rec->tLf[ipb];
329 
330  /* Subtract the Rayleigh contribution for this geometry. */
331  Ltemp[ib] -= l1rec->Lr[ipb];
332 
333  /* If selected, correct for Ding and Gordon O2 absorption for the aerosol component (replace O2 losses) */
334  if (input->oxaband_opt == 1) {
335  Ltemp[ib] /= l1rec->t_o2[ipb];
336  Lunc [ib] /= l1rec->t_o2[ipb];
337  }
338  }
339 
340 
341  /* Compute BRDF correction, if not dependent on radiance */
342  if (brdf_opt < FOQMOREL && brdf_opt > NOBRDF)
343  ocbrdf(l2rec, ip, brdf_opt, wave, nwvis, solz, senz, delphi, ws, -1.0, NULL, NULL, brdf);
344 
345  /* Initialize iteration loop */
346  chl = seed_chl;
347  iter = 0;
348  last_iter = 0;
349  iter_max = aer_iter_max;
350  iter_min = aer_iter_min;
351  iter_reset = 0;
352  last_refl_nir = 100.;
353  want_glintcorr = 0;
354 
355  /* new glint_opt usage - a 2 will use the simple TLg from atmocor1 */
356  if (glint_opt == 1 && l1rec->glint_coef[ip] > glint_min) {
357  iter_max = MAX(2, iter_max);
358  iter_min = MAX(2, iter_min);
359  want_glintcorr = 1;
360  }
361  if (glint_opt == 2) {
362  want_glintcorr = 1;
363  }
364 
365  if (aer_opt == AERWANGSWIR || aer_opt == AERRHSWIR) {
366  tindx_shi(l2rec, ip, &tindx);
367  if (tindx >= 1.05) {
368  iter_max = 1;
369  aer_s = swir_s;
370  aer_l = swir_l;
371  want_nirLw = 0;
372  } else {
373  aer_s = nir_s;
374  aer_l = nir_l;
375  want_nirLw = 1;
376  }
377  daer = MAX(aer_l - aer_s, 1);
378  }
379 NIRSWIR:
380 
381  if (want_nirLw || want_nirRrs) {
382  for (ib = 0; ib < nwave; ib++) {
383  last_tLw_nir[ib] = 0.0;
384  tLw_nir[ib] = 0.0;
385  Rrs[ib] = 0.0;
386  }
387  Rrs[green] = seed_green;
388  Rrs[red ] = seed_red;
389  }
390 
391 
392  /* -------------------------------------------------------------------- */
393  /* Begin interations for aerosol with corrections for non-zero nLw(NIR) */
394  /* -------------------------------------------------------------------- */
395 
396  while (!last_iter) {
397 
398  iter++;
399  status = 0;
400 
401  /* Initialize tLw as surface + aerosol radiance */
402  for (ib = 0; ib < nwave; ib++) {
403  tLw[ib] = Ltemp[ib];
404  }
405 
406  /* Compute and subtract glint radiance */
407  if (want_glintcorr) {
408 
409  if (glint_opt == 1)
410  glint_rad(iter, nwave, aer_s, aer_l, gc, airmass, mu0, Fo, taur, taua, tLw, TLg);
411 
412 
413  for (ib = 0; ib < nwave; ib++) {
414  tLw[ib] -= TLg[ib];
415  }
416  }
417 
418  /* Adjust for non-zero NIR water-leaving radiances using input Rrs */
419  if (want_nirRrs) {
420 
421  rhown_nir[aer_s] = pi * input->aer_rrs_short;
422  rhown_nir[aer_l] = pi * input->aer_rrs_long;
423 
424  for (ib = aer_s; ib <= aer_l; ib += daer) {
425 
426  /* Convert NIR reflectance to TOA W-L radiance */
427  tLw_nir[ib] = rhown_nir[ib] / pi * Fo[ib] * mu0 * t_sol[ib] * t_sen[ib] / brdf[ib];
428 
429  /* Avoid over-subtraction */
430  if (tLw_nir[ib] > tLw[ib] && tLw[ib] > 0.0)
431  tLw_nir[ib] = tLw[ib];
432 
433  /* Remove estimated NIR water-leaving radiance */
434  tLw[ib] -= tLw_nir[ib];
435  }
436  }
437 
438 
439  /* Adjust for non-zero NIR water-leaving radiances using MUMM */
440  if (want_mumm) {
441 
442  get_rhown_mumm(l2rec, ip, aer_s, aer_l, rhown_nir);
443 
444  for (ib = aer_s; ib <= aer_l; ib += daer) {
445 
446  /* Convert NIR reflectance to TOA W-L radiance */
447  tLw_nir[ib] = rhown_nir[ib] / pi * Fo[ib] * mu0 * t_sol[ib] * t_sen[ib] / brdf[ib];
448 
449  /* Remove estimated NIR water-leaving radiance */
450  tLw[ib] -= tLw_nir[ib];
451  }
452  }
453 
454 
455  /* Adjust for non-zero NIR water-leaving radiances using IOP model */
456  if (want_nirLw) {
457 
458  ipb = ip*nwave;
459  get_rhown_eval(input->fqfile, Rrs, wave, aer_s, aer_l, nwave, &l1rec->sw_a_avg[ipb], &l1rec->sw_bb_avg[ipb], chl, solz, senz, delphi, rhown_nir);
460 
461  for (ib = aer_s; ib <= aer_l; ib += daer) {
462 
463  /* Convert NIR reflectance to TOA W-L radiance */
464  tLw_nir[ib] = rhown_nir[ib] / pi * Fo[ib] * mu0 * t_sol[ib] * t_sen[ib] / brdf[ib];
465 
466  /* Iteration damping */
467  tLw_nir[ib] = (1.0 - df) * tLw_nir[ib] + df * last_tLw_nir[ib];
468 
469  /* Ramp-up ?*/
470  if (want_ramp) {
471  if (chl > 0.0 && chl <= cbot)
472  tLw_nir[ib] = 0.0;
473  else if ((chl > cbot) && (chl < ctop))
474  tLw_nir[ib] *= (cslp * chl + cint);
475  }
476 
477  /* Remove estimated NIR water-leaving radiance */
478  tLw[ib] -= tLw_nir[ib];
479  }
480  }
481 
482  /* Compute the aerosol contribution */
483  if (status == 0) {
484  if (aer_opt != AERNULL)
485  status = aerosol(l2rec, aer_opt, aerec, ip, wave, nwave, aer_s, aer_l, Fo, tLw,
486  La, t_sol, t_sen, eps, taua, aermodmin, aermodmax, aermodrat,
487  aermodmin2, aermodmax2, aermodrat2);
488  else {
489  for (ib = 0; ib < nwave; ib++) {
490 
491  ipb = ip * nwave + ib;
492 
493  t_sol [ib] = 1.0;
494  t_sen [ib] = 1.0;
495  La [ib] = 0.0;
496  taua [ib] = 0.0;
497  *eps = 1.0;
498  }
499  }
500  }
501 
502 
503  /* Subtract aerosols and normalize */
504  if (status == 0) {
505 
506  for (ib = 0; ib < nwave; ib++) {
507 
508  /* subtract aerosol and normalize */
509  tLw[ib] = tLw[ib] - La[ib];
510  Lw [ib] = tLw[ib] / t_sen[ib] * tg_sol[ib];
511  nLw[ib] = Lw [ib] / t_sol[ib] / tg_sol[ib] / mu0 / fsol * brdf[ib];
512  }
513 
514  /* Compute new estimated chlorophyll */
515  if (want_nirLw) {
516  refl_nir = Rrs[red];
517  for (ib = aer_s; ib <= aer_l; ib += daer)
518  last_tLw_nir[ib] = tLw_nir[ib];
519  for (ib = 0; ib < nwvis; ib++) {
520  Rrs[ib] = nLw[ib] / Fobar[ib];
521  }
522  chl = get_default_chl(l2rec, Rrs);
523 
524  // if we passed atmospheric correction but the spectral distribution of
525  // Rrs is bogus (chl failed), assume this is a turbid-water case and
526  // reseed iteration as if all 670 reflectance is from water.
527 
528  if (chl == badchl && iter_reset == 0 && iter < iter_max) {
529  chl = 10.0;
530  Rrs[red] = 1.0 * (Ltemp[red] - TLg[red]) / t_sol[red] / tg_sol[red] / mu0 / fsol / Fobar[red];
531  iter_reset = 1;
532  }
533 
534  // if we already tried a reset, and still no convergence, force one last
535  // pass with an assumption that all red radiance is water component, and
536  // force iteration to end. this will be flagged as atmospheric correction
537  // failure, but a qualitatively useful retrieval may still result.
538 
539  if (chl == badchl && iter_reset == 1 && iter < iter_max) {
540  chl = 10.0;
541  Rrs[red] = 1.0 * (Ltemp[red] - TLg[red]) / t_sol[red] / tg_sol[red] / mu0 / fsol / Fobar[red];
542  iter = iter_max; // so iter will trigger maxiter flag and ATMFAIL
543  iter_reset = 2;
544  }
545  }
546 
547  } else {
548 
549  /* Aerosol determination failure */
550  for (ib = 0; ib < nwave; ib++) {
551  La [ib] = badval;
552  tLw[ib] = badval;
553  Lw[ib] = badval;
554  nLw[ib] = badval;
555  Rrs[ib] = badval;
556  }
557  }
558 
559  /* If NIR/SWIR switching, do secondary test for turbidity and reset if needed */
560  if (iter == 1 && (aer_opt == AERWANGSWIR || aer_opt == AERRHSWIR)) {
561  if (tindx >= 1.05 && status == 0) {
562  for (ib = 0; ib < nwvis; ib++) {
563  Rrs[ib] = nLw[ib] / Fobar[ib];
564  }
565  chl = get_default_chl(l2rec, Rrs);
566  //printf("Checking turbidity %d %f %f %f\n",ip,tindx,chl,nLw[nir_l]);
567  if (chl > 0 && (chl <= 1.0 || nLw[nir_l] < 0.08)) {
568  iter_max = aer_iter_max;
569  aer_s = nir_s;
570  aer_l = nir_l;
571  daer = MAX(aer_l - aer_s, 1);
572  want_nirLw = 1;
573  //printf("Reverting to NIR %d %f %f %f\n",ip,tindx,chl,nLw[nir_l]);
574  goto NIRSWIR;
575  } else
576  l1rec->flags[ip] |= TURBIDW;
577  }
578  }
579 
580 
581  /* Shall we continue iterating */
582  if (status != 0) {
583  last_iter = 1;
584  } else if (iter < iter_min) {
585  last_iter = 0;
586  } else if (want_nirLw && (fabs(refl_nir - last_refl_nir) < fabs(nir_chg * refl_nir) || refl_nir < 0.0)) {
587  last_iter = 1;
588  } else if (want_mumm || want_nirRrs) {
589  last_iter = 1;
590  } else if (iter > iter_max) {
591  last_iter = 1;
592  }
593 
594  last_refl_nir = refl_nir;
595 
596  } /* end of iteration loop */
597 
598  l2rec->num_iter[ip] = iter;
599 
600 
601  /* If the atmospheric correction failed, we don't need to do more. */
602  if (status != 0) {
603  free(taur);
604  free(tLw);
605  free(rhown_nir);
606  free(tLw_nir);
607  free(last_tLw_nir);
608  free(Ltemp);
609  free(Lunc);
610  return (status);
611 
612  }
613 
614  /* If we used a NIR Lw correction, we record the tLw as it was predicted. */
615  if (want_nirLw || want_nirRrs || want_mumm) {
616  for (ib = aer_s; ib <= aer_l; ib += daer) {
617  tLw[ib] = tLw_nir[ib];
618  Lw [ib] = tLw[ib] / t_sen[ib] * tg_sol[ib];
619  nLw[ib] = Lw [ib] / t_sol[ib] / tg_sol[ib] / mu0 / fsol * brdf[ib];
620  Rrs[ib] = nLw[ib] / Fobar[ib];
621  }
622  }
623 
624  /* Convert water-leaving radiances from band-averaged to band-centered. */
625  /* Switch mean solar irradiance from band-averaged to band centered also.*/
626  if (l1_input->outband_opt >= 2) {
627  nlw_outband(l1_input->evalmask, sensorID, wave, nwave, Lw, nLw, &l2rec->outband_correction[ip*nwave]);
628  Fobar = l1file->Fonom;
629  }
630 
631  /* Compute f/Q correction and apply to nLw */
632  if (brdf_opt >= FOQMOREL) {
633  ocbrdf(l2rec, ip, brdf_opt, wave, nwvis, solz, senz, delphi, ws, -1.0, nLw, Fobar, brdf);
634  for (ib = 0; ib < nwvis; ib++) {
635  nLw[ib] = nLw[ib] * brdf[ib];
636  }
637  }
638 
639  /* Compute final Rrs */
640  for (ib = 0; ib < nwave; ib++) {
641  if (ib != aer_s && ib != aer_l) {
642  Rrs[ib] = nLw[ib] / Fobar[ib];
643  l2rec->Rrs[ip * nwave + ib] = Rrs[ib];
644 
645  nLw_unc[ib] = Lunc[ib] / t_sen[ib] / t_sol[ib] / mu0 / fsol * brdf[ib];
646  Rrs_unc[ib] = nLw_unc[ib] / Fobar[ib];
647  }
648  }
649 
650  /* Compute final chl from final nLw (needed for flagging) */
651  l2rec->chl[ip] = get_default_chl(l2rec, Rrs);
652 
653  /*Determine Raman scattering contribution to Rrs*/
654  run_raman_cor(l2rec, ip);
655 
656  free(taur);
657  free(tLw);
658  free(rhown_nir);
659  free(tLw_nir);
660  free(last_tLw_nir);
661  free(Ltemp);
662  free(Lunc);
663 
664  return (status);
665 }
666 
667 
668 
int32 l1file(int32 sdfid, int32 *nsamp, int32 *nscans, int16 *dtynum)
Definition: l1stat_chk.c:586
#define MAX(A, B)
Definition: swl0_utils.h:26
void red(int iz1, int iz2, int jz1, int jz2, int jm1, int jm2, int jmf, int ic1, int jc1, int jcf, int kc, float ***c, float **s)
int status
Definition: l1_czcs_hdf.c:32
void nlw_outband(int32_t evalmask, int32_t sensorID, float wave[], int32_t nwave, float Lw[], float nLw[], float outband_correction[])
Definition: nlw_outband.c:3
#define FIXMODPAIRNIR
Definition: l12_parms.h:27
#define FOQMOREL
Definition: l12_parms.h:53
#define AERRHSM
Definition: l12_parms.h:37
#define NULL
Definition: decode_rs.h:63
#define FIXANGSTROMNIR
Definition: l12_parms.h:29
read l1rec
void tindx_shi(l2str *l2rec, int32_t ip, float *tindx)
Definition: turbid.c:4
int atmocor2(l2str *l2rec, aestr *aerec, int32_t ip)
Definition: atmocor2.c:11
const double pi
float mu
void glint_rad(int32_t iter, int32_t nband, int32_t nir_s, int32_t nir_l, float glint_coef, float airmass, float mu0, float F0[], float taur[], float taua[], float La[], float TLg[])
Definition: glint.c:40
int aerosol(l2str *l2rec, int32_t aer_opt_in, aestr *aerec, int32_t ip, float wave[], int32_t nwave, int32_t iwnir_s_in, int32_t iwnir_l_in, float F0_in[], float La1_in[], float La2_out[], float t_sol_out[], float t_sen_out[], float *eps, float taua_out[], int32_t *modmin, int32_t *modmax, float *modrat, int32_t *modmin2, int32_t *modmax2, float *modrat2)
Definition: aerosol.c:3922
#define AERRHNIR
Definition: l12_parms.h:24
instr * input
#define PI
Definition: l3_get_org.c:6
#define GLINT_MIN
Definition: l1.h:59
#define TURBIDW
Definition: l2_flags.h:22
int bindex_get(int32_t wave)
Definition: windex.c:45
#define NOBRDF
Definition: l12_parms.h:50
float tg_sol[NBANDS]
Definition: atrem_corl1.h:127
void get_rhown_mumm(l2str *l2rec, int32_t ip, int32_t nir_s, int32_t nir_l, float rhown[])
Definition: mumm.c:74
#define AERRHSWIR
Definition: l12_parms.h:33
l1_input_t * l1_input
Definition: l1_options.c:9
#define FATAL_ERROR
Definition: swl0_parms.h:5
#define AERMUMM
Definition: l12_parms.h:32
#define RADEG
Definition: czcs_ctl_pt.c:5
#define AERRHMSEPS
Definition: l12_parms.h:36
void get_rhown_eval(char *fqfile, float Rrs[], float wave[], int32_t nir_s, int32_t nir_l, int32_t nwave, float aw[], float bbw[], float chl, float solz, float senz, float phi, float rhown[])
#define STDPR
Definition: l12_parms.h:85
void run_raman_cor(l2str *l2rec, int ip)
Definition: raman.c:815
#define BAD_FLT
Definition: jplaeriallib.h:19
float get_default_chl(l2str *l2rec, float Rrs[])
Definition: get_chl.c:392
#define AERRHMUMM
Definition: l12_parms.h:35
#define fabs(a)
Definition: misc.h:93
#define CZCS
Definition: sensorDefs.h:17
float mu0
void rhown_nir(char *fqfile, float chl, float aw[], float bbw[], float Rrs[], float wave[], int32_t nwave, float solz, float senz, float phi, int32_t nir_s, int32_t nir_l, float rhown[])
int32_t rdsensorinfo(int32_t, int32_t, const char *, void **)
Definition: rdsensorinfo.c:69
#define AERWANGNIR
Definition: l12_parms.h:25
int32_t sensorID[MAXNFILES]
Definition: l2bin.cpp:97
int ocbrdf(l2str *l2rec, int32_t ip, int32_t brdf_opt, float wave[], int32_t nwave, float solz, float senz, float phi, float ws, float chl, float nLw[], float Fo[], float brdf[])
Definition: brdf.c:40
#define AERWANGSWIR
Definition: l12_parms.h:31
#define AERNULL
Definition: l12_parms.h:39