NASA Logo
Ocean Color Science Software

ocssw V2022
atmocor1.c
Go to the documentation of this file.
1 #include "l12_proto.h"
2 #include "glint.h"
3 /* ========================================================================== */
4 /* module atmocor1() - computes pre-aerosol atmospheric components */
5 /* */
6 /* Written By: B. A. Franz, SAIC, SeaWiFS Project, February 1998 */
7 /* Conversion to C, May 2006 */
8 /* ========================================================================== */
9 
10 
11 /* ------------------------------------------------------------------- */
12 /* correction factor to remove oxygen absorption from La(765) */
13 
14 /* ------------------------------------------------------------------- */
15 float oxygen_aer(float airmass) {
16  /* base case: m80_t50_strato visibility (550nm ,0-2km):25km */
17  static float a[] = {-1.0796, 9.0481e-2, -6.8452e-3};
18  return (1.0 + pow(10.0, a[0] + airmass * a[1] + airmass * airmass * a[2]));
19 }
20 
21 
22 /* ------------------------------------------------------------------- */
23 /* correction factor to replace oxygen absorption to Lr(765) */
24 
25 /* ------------------------------------------------------------------- */
26 float oxygen_ray(float airmass) {
27  /* base case is the 1976 Standard atmosphere without aerosols */
28  static float a[] = {-1.3491, 0.1155, -7.0218e-3};
29  return (1.0 / (1.0 + pow(10.0, a[0] + airmass * a[1] + airmass * airmass * a[2])));
30 }
31 
32 
33 /* ------------------------------------------------------------------- */
34 /* main function, loads various quanitities into l1 record for 1 pixel */
35 
36 /* ------------------------------------------------------------------- */
37 
38 void atmocor1(l1str *l1rec, int32_t ip) {
39  static float p0 = STDPR;
40 
41  int32_t sensorID = l1rec->l1file->sensorID;
42  int32_t nwave = l1rec->l1file->nbands;
43 
44  float solz = l1rec->solz[ip];
45  float senz = l1rec->senz[ip];
46  float raz = l1rec->delphi[ip];
47  float mu0 = l1rec->csolz[ip];
48  float mu = l1rec->csenz[ip];
49 
50  float ws = l1rec->ws[ip];
51  float pr = l1rec->pr[ip];
52  float wv = l1rec->wv[ip];
53 
54  float *Fo = l1rec->Fo;
55  float *Tau_r = l1rec->l1file->Tau_r;
56 
57  float zero = 0.0;
58  int32_t ib765 = -1;
59  float airmass;
60  float a_o2;
61  float glint_coef_q;
62  float glint_coef_u;
63  int32_t ib, ipb;
64  float scaleRayleigh;
65 
66  airmass = 1.0 / mu0 + 1.0 / mu;
67  ipb = ip*nwave;
68 
69  /* Initialize output values */
70  for (ib = 0; ib < nwave; ib++) {
71 
72  l1rec->Lr [ipb + ib] = 0.0;
73  l1rec->L_q [ipb + ib] = 0.0;
74  l1rec->L_u [ipb + ib] = 0.0;
75  l1rec->tLf [ipb + ib] = 0.0;
76  l1rec->tg_sol[ipb + ib] = 1.0;
77  l1rec->tg_sen[ipb + ib] = 1.0;
78  l1rec->tg [ipb + ib] = 1.0;
79  l1rec->t_h2o [ipb + ib] = 1.0;
80  l1rec->t_o2 [ipb + ib] = 1.0;
81  l1rec->t_sol [ipb + ib] = exp(-0.5 * pr / p0 * Tau_r[ib] / mu0);
82  l1rec->t_sen [ipb + ib] = exp(-0.5 * pr / p0 * Tau_r[ib] / mu);
83 
84  // Explicitly only doing the Ding and Gordon correction if the sensor has a band AT 765nm
85  // So, you know, SeaWiFS, OCTS, OSMI, and any others to be named later...
86  if (input->oxaband_opt == 1 && l1rec->l1file->iwave[ib] == 765) {
87  ib765 = ib;
88  l1rec->t_o2[ipb + ib765] = 1.0 / oxygen_aer(airmass);
89  }
90 
91  if (sensorID == SEAWIFS && ((input->gas_opt & GAS_TRANS_TBL_BIT) == 0)) {
92  /* this is for rhos only, but effects seawifs land products and cloud */
93  /* will modify get_rhos() to use gaseous transmittance in future update */
94  l1rec->t_h2o[ipb + ib] = water_vapor(ib, wv, airmass);
95  }
96 
97  }
98 
99  /* apply gaseous transmittance */
101 
102  /* white-cap radiances at TOA */
103  whitecaps(sensorID, l1_input->evalmask, nwave, ws, input->wsmax, &l1rec->rhof[ipb]);
104  for (ib = 0; ib < nwave; ib++) {
105  l1rec->tLf[ipb + ib] = l1rec->rhof[ipb + ib] * l1rec->t_sen[ipb + ib] * l1rec->t_sol[ipb + ib] * Fo[ib] * mu0 / M_PI;
106  }
107 
108  /* Rayleigh scattering */
109  if (sensorID != AVHRR && sensorID != OCRVC) {
110  rayleigh(l1rec, ip);
111  }
112 
113  // If we are running with Ding and Gordon, need to do the rayleigh part as well...
114  if (input->oxaband_opt == 1 && ib765 > -1) {
115  a_o2 = oxygen_ray(airmass);
116  l1rec->Lr [ipb + ib765] *= a_o2;
117  l1rec->L_q[ipb + ib765] *= a_o2;
118  l1rec->L_u[ipb + ib765] *= a_o2;
119  }
120 
121  //Scale by the altitude of the sensor, assuming height of atmosphere=100km
122  if (l1rec->alt > 0) {
123 
124  scaleRayleigh = 1.0 - exp(-l1rec->alt / 10); // Assume 10km is e-folding height
125 
126  for (ib = 0; ib < nwave; ib++) {
127  l1rec->Lr [ipb + ib] *= scaleRayleigh;
128  l1rec->L_q[ipb + ib] *= scaleRayleigh;
129  l1rec->L_u[ipb + ib] *= scaleRayleigh;
130  }
131  }
132 
133  /* glint coefficients and approximate glint radiances */
134  /* also add glint to polarization components */
135 
136  /* for avhrr, l1_aci_hdf.c calls avhrrsub5h.f which calls getglint */
137  if (sensorID != AVHRR) {
138 
139  getglint_iqu(senz, solz, raz, ws, zero,
140  &l1rec->glint_coef[ip], &glint_coef_q, &glint_coef_u);
141 
142  // getglint_iqu_(&senz, &solz, &raz, &ws, &zero,
143  // &l1rec->glint_coef[ip], &glint_coef_q, &glint_coef_u);
144 
145  for (ib = 0; ib < nwave; ib++) {
146  l1rec->TLg[ipb + ib] = l1rec->glint_coef[ip] * exp(-(Tau_r[ib] + 0.1) * airmass) * Fo[ib];
147  l1rec->L_q[ipb + ib] += (glint_coef_q * l1rec->TLg[ipb + ib]);
148  l1rec->L_u[ipb + ib] += (glint_coef_u * l1rec->TLg[ipb + ib]);
149  }
150  }
151 
152 }
float oxygen_ray(float airmass)
Definition: atmocor1.c:26
#define AVHRR
Definition: sensorDefs.h:15
read l1rec
float mu
void rayleigh(l1str *l1rec, int32_t ip)
Definition: rayleigh.c:169
instr * input
#define M_PI
Definition: dtranbrdf.cpp:19
float water_vapor
Definition: atrem_corl1.h:226
void atmocor1(l1str *l1rec, int32_t ip)
Definition: atmocor1.c:38
void gaseous_transmittance(l1str *l1rec, int32_t ip)
Definition: gas_trans.c:633
l1_input_t * l1_input
Definition: l1_options.c:9
void whitecaps(int32_t sensorID, int32_t evalmask, int32_t nwave, float ws, float ws_max, float rhof[])
Definition: whitecaps.c:51
#define STDPR
Definition: l12_parms.h:85
float oxygen_aer(float airmass)
Definition: atmocor1.c:15
#define GAS_TRANS_TBL_BIT
Definition: l12_parms.h:62
float mu0
#define OCRVC
Definition: sensorDefs.h:24
#define SEAWIFS
Definition: sensorDefs.h:12
PGE01 indicating that PGE02 PGE01 V6 for and PGE01 V2 for MOD03 were used to produce the granule By convention adopted in all MODIS Terra PGE02 code versions are The fourth digit of the PGE02 version denotes the LUT version used to produce the granule The source of the metadata environment variable ProcessingCenter was changed from a QA LUT value to the Process Configuration A sign used in error in the second order term was changed to a
Definition: HISTORY.txt:424
int32_t sensorID[MAXNFILES]
Definition: l2bin.cpp:91
void getglint_iqu(float senz, float solz, float raz, float ws, float chi, float *glint_coef, float *glint_coef_q, float *glint_coef_u)
Get the glint iqu object.
Definition: getglint.c:78