OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
photic_depth.c
Go to the documentation of this file.
1 #include "l12_proto.h"
2 
3 /* =================================================================== */
4 /* Algorithms for computing photic depths */
5 /* */
6 /* B. Franz, NASA Ocean Biology Processing Group, SAIC, March 2005. */
7 /* =================================================================== */
8 
9 #include <stdlib.h>
10 #include <math.h>
11 #include <gsl/gsl_poly.h>
12 #include "l12_proto.h"
13 
14 #define Z_CHL_MAX 15.0
15 
16 /* ------------------------------------------------------------------- */
17 /* Zphotic_lee() - photic depth (ZP Lee) */
18 /* */
19 /* Inputs: */
20 /* l2rec - level-2 structure containing one complete scan after */
21 /* atmospheric correction. */
22 /* p - product catalog entry */
23 /* */
24 /* Outputs: */
25 /* Zp - euphtic depth, 1 value per pixel. */
26 /* */
27 /* Description: */
28 /* */
29 /* Reference: */
30 /* Lee, at al (2007) "Euphotic zone depth: Its derivation and */
31 /* implication to ocean-color remote sensing", JGR, 112, C03009, */
32 /* pp 1-12. */
33 /* */
34 /* Original Implementation: B. Franz, August 2007 */
35 
36 /*---------------------------------------------------------------------*/
37 void Zphotic_lee(l2str *l2rec, l2prodstr *p, float Zp[]) {
38  static int ib490 = -1;
39 
40  float stheta = 0.0; /* use solz = 0.0 */
41  float ctheta = 1.0; /* use solz = 0.0 */
42 
43  const float c1 [] = {-0.057, 0.482, 4.221};
44  const float c2 [] = {0.183, 0.702, -2.567};
45  const float alpha[] = {0.090, 1.465, -0.667};
46 
47  double k1, k2;
48  double y1, y2, y3;
49  double z1, z2, z3;
50  double tau;
51  float a490, bb490;
52  int ip, ipb;
53 
54  l1str *l1rec = l2rec->l1rec;
55 
56  switch (p->prod_ix) {
57  case -1: /*Zsd*/
58  tau = -log(0.1);
59  break;
60  case -2: /*Zeu*/
61  tau = -log(0.01);
62  break;
63  case -3: /* 1st optical depth */
64  tau = 1.0;
65  break;
66  default:
67  if (p->prod_ix <= 0 || p->prod_ix > 100) {
68  printf("Zeu_lee: percent light should be between 1 and 100.\n");
69  exit(1);
70  }
71  tau = -log(p->prod_ix / 100.0);
72  break;
73  }
74 
75  if (input->iop_opt == IOPNONE) {
76  printf("IOP-based Z*_lee product requires iop model selection (iop_opt). ");
77  printf("Using default model.\n");
78  input->iop_opt = IOPDEFAULT;
79  get_iops(l2rec, input->iop_opt);
80  }
81 
82  if (ib490 < 0) {
83  ib490 = bindex_get(490);
84  if (ib490 < 0) {
85  printf("Zeu_lee: a 490nm channel is required for this algorithm\n");
86  exit(1);
87  }
88  }
89 
90  for (ip = 0; ip < l1rec->npix; ip++) {
91 
92  ipb = ip * l1rec->l1file->nbands + ib490;
93 
94  a490 = l2rec->a[ipb];
95  bb490 = l2rec->bb[ipb];
96 
97  Zp[ip] = p->badData;
98 
99  if (l1rec->mask[ip] || a490 <= 0.0 || bb490 <= 0.0) {
100  l1rec->flags[ip] |= PRODFAIL;
101  } else {
102  stheta = sin(l1rec->solz[ip] / RADEG);
103  ctheta = cos(l1rec->solz[ip] / RADEG);
104  k1 = (c1[0] + c1[1] * sqrt(a490) + c1[2] * bb490)*(1 + alpha[0] * stheta);
105  k2 = (c2[0] + c2[1]* (a490) + c2[2] * bb490)*(alpha[1] + alpha[2] * ctheta);
106  y1 = (k1 * k1 - k2 * k2 - 2.0 * tau * k1) / (k1 * k1);
107  y2 = (tau * tau - 2.0 * tau * k1) / (k1 * k1);
108  y3 = (tau * tau) / (k1 * k1);
109  gsl_poly_solve_cubic(y1, y2, y3, &z1, &z2, &z3);
110  if (z2 > 0.0 && z3 > 0.0)
111  Zp[ip] = MIN(z2, z3);
112  else if (z1 > 0.0 && z2 > 0.0)
113  Zp[ip] = MIN(z1, z2);
114  else if (z1 > 0.0 && z3 > 0.0)
115  Zp[ip] = MIN(z1, z3);
116  else
117  l1rec->flags[ip] |= PRODFAIL;
118  }
119  }
120 
121  return;
122 }
123 
124 
125 /* ------------------------------------------------------------------- */
126 /* zeu_morel() - depth of the euphotic layer (1%) by Morel */
127 /* */
128 /* Inputs: */
129 /* l2rec - level-2 structure containing one complete scan after */
130 /* atmospheric correction. */
131 /* p - product catalog entry */
132 /* */
133 /* Outputs: */
134 /* Zeu - euphtic depth, 1 value per pixel. */
135 /* */
136 /* Description: */
137 /* */
138 /* Reference: */
139 /* */
140 /* Morel, A., Y. Huot, B. Gentili, P.J. Werdell, S.B. Hooker (2007). */
141 /* Consistency of products derived from various ocean color sensors: */
142 /* An examination before merging these products and extending their */
143 /* applications, Remote Sensing of Environment, to be submitted. */
144 /* */
145 /* Original Implementation: B. Franz, November 2006 */
146 
147 /*---------------------------------------------------------------------*/
148 void Zeu_morel(l2str *l2rec, l2prodstr *p, float *Zeu) {
149  float chl, x;
150  int32_t ip;
151 
152  l1str *l1rec = l2rec->l1rec;
153 
154  for (ip = 0; ip < l1rec->npix; ip++) {
155 
156  chl = l2rec->chl[ip];
157 
158  if (chl > Z_CHL_MAX) {
159  l1rec->flags[ip] |= PRODWARN;
160  }
161 
162  if (l1rec->mask[ip] || chl <= 0.0) {
163  Zeu[ip] = p->badData;
164  l1rec->flags[ip] |= PRODFAIL;
165  } else {
166  x = log10(chl);
167  Zeu[ip] = pow(10.0, 1.524 + x * (-0.460 + x * (-0.00051 + x * 0.0282)));
168  }
169  }
170 
171  return;
172 }
173 
174 
175 /* ------------------------------------------------------------------- */
176 /* Zsd_morel() - secchi depth by Morel */
177 /* */
178 /* Inputs: */
179 /* l2rec - level-2 structure containing one complete scan after */
180 /* atmospheric correction. */
181 /* p - product catalog entry */
182 /* */
183 /* Outputs: */
184 /* Zsd - secchi depth depth, 1 value per pixel. */
185 /* */
186 /* Description: */
187 /* */
188 /* Reference: */
189 /* */
190 /* Morel, A., Y. Huot, B. Gentili, P.J. Werdell, S.B. Hooker (2007). */
191 /* Consistency of products derived from various ocean color sensors: */
192 /* An examination before merging these products and extending their */
193 /* applications, Remote Sensing of Environment, to be submitted. */
194 /* */
195 /* Implementation: B. Franz, November 2006 */
196 
197 /*---------------------------------------------------------------------*/
198 void Zsd_morel(l2str *l2rec, l2prodstr *p, float *Zsd) {
199  float chl, x;
200  int32_t ip;
201 
202  l1str *l1rec = l2rec->l1rec;
203 
204  for (ip = 0; ip < l1rec->npix; ip++) {
205 
206  chl = l2rec->chl[ip];
207 
208  if (chl > Z_CHL_MAX) {
209  l1rec->flags[ip] |= PRODWARN;
210  }
211 
212  if (l1rec->mask[ip] || chl <= 0.0 || chl > Z_CHL_MAX) {
213  Zsd[ip] = p->badData;
214  l1rec->flags[ip] |= PRODFAIL;
215  } else {
216  x = log10(chl);
217  Zsd[ip] = 8.50 + x * (-12.6 + x * (7.36 - x * 1.43));
218  }
219  }
220 
221  return;
222 }
223 
224 
225 /* ------------------------------------------------------------------- */
226 /* intchl_morel() - quasi depth integrated chl using morel */
227 
228 /*---------------------------------------------------------------------*/
229 void intchl_morel(l2str *l2rec, l2prodstr *p, float *intchl) {
230  float Zeu, chl, x;
231  int32_t ip;
232 
233  l1str *l1rec = l2rec->l1rec;
234 
235  for (ip = 0; ip < l1rec->npix; ip++) {
236 
237  chl = l2rec->chl[ip];
238 
239  if (chl > Z_CHL_MAX) {
240  l1rec->flags[ip] |= PRODWARN;
241  }
242 
243  if (l1rec->mask[ip] || chl <= 0.0) {
244  intchl[ip] = p->badData;
245  l1rec->flags[ip] |= PRODFAIL;
246  } else {
247  x = log10(chl);
248  Zeu = pow(10.0, 1.524 + x * (-0.460 + x * (-0.00051 + x * 0.0282)));
249  intchl[ip] = Zeu*chl;
250  }
251  }
252 
253  return;
254 }
255 
256 
257 /* ------------------------------------------------------------------- */
258 
259 /*---------------------------------------------------------------------*/
260 void Zsd_gbr(l2str *l2rec, l2prodstr *p, float *Zsd) {
261  static int firstCall = 1;
262  static float a0, a1;
263 
264  int32_t ip;
265  l1str *l1rec = l2rec->l1rec;
266 
267  if (firstCall) {
268  firstCall = 0;
269  switch (l1rec->l1file->sensorID) {
270  case MODIST:
271  case MODISA:
272  a0 = 0.580;
273  a1 = 0.742;
274  break;
275  default:
276  a0 = 0.518;
277  a1 = 0.811;
278  break;
279  }
280  }
281 
282  p->prod_ix = -1; // 10% light
283  Zphotic_lee(l2rec, p, Zsd);
284 
285  for (ip = 0; ip < l1rec->npix; ip++) {
286 
287  if (Zsd[ip] > 0.0)
288  Zsd[ip] = pow(10.0, (log10(Zsd[ip]) - a0) / a1);
289  else {
290  Zsd[ip] = p->badData;
291  l1rec->flags[ip] |= PRODFAIL;
292  }
293  }
294 
295  return;
296 }
297 
298 
299 /* ------------------------------------------------------------------- */
300 /* get_photic_depth() - l2_hdf_generic interface for photic depth */
301 
302 /* ------------------------------------------------------------------- */
303 void get_photic_depth(l2str *l2rec, l2prodstr *p, float prod[]) {
304 
305  switch (p->cat_ix) {
306  case CAT_Zeu_morel:
307  Zeu_morel(l2rec, p, prod);
308  break;
309  case CAT_Zsd_morel:
310  Zsd_morel(l2rec, p, prod);
311  break;
312  case CAT_Zphotic_lee:
313  Zphotic_lee(l2rec, p, prod);
314  break;
315  case CAT_Zsd_gbr:
316  Zsd_gbr(l2rec, p, prod);
317  break;
318  }
319 
320  return;
321 }
#define MIN(x, y)
Definition: rice.h:169
#define CAT_Zsd_gbr
Definition: l2prod.h:248
read l1rec
#define PRODWARN
Definition: l2_flags.h:13
#define MODIST
Definition: sensorDefs.h:18
void Zsd_morel(l2str *l2rec, l2prodstr *p, float *Zsd)
Definition: photic_depth.c:198
#define IOPDEFAULT
Definition: l12_parms.h:76
#define PRODFAIL
Definition: l2_flags.h:41
#define IOPNONE
Definition: l12_parms.h:67
instr * input
real, dimension(4) ctheta
int bindex_get(int32_t wave)
Definition: windex.c:45
#define CAT_Zsd_morel
Definition: l2prod.h:148
void get_iops(l2str *l2rec, int32_t iop_opt)
Definition: convl12.c:113
void intchl_morel(l2str *l2rec, l2prodstr *p, float *intchl)
Definition: photic_depth.c:229
void Zsd_gbr(l2str *l2rec, l2prodstr *p, float *Zsd)
Definition: photic_depth.c:260
#define RADEG
Definition: czcs_ctl_pt.c:5
#define CAT_Zphotic_lee
Definition: l2prod.h:160
void get_photic_depth(l2str *l2rec, l2prodstr *p, float prod[])
Definition: photic_depth.c:303
void Zphotic_lee(l2str *l2rec, l2prodstr *p, float Zp[])
Definition: photic_depth.c:37
void Zeu_morel(l2str *l2rec, l2prodstr *p, float *Zeu)
Definition: photic_depth.c:148
#define Z_CHL_MAX
Definition: photic_depth.c:14
#define MODISA
Definition: sensorDefs.h:19
float p[MODELMAX]
Definition: atrem_corl1.h:131
#define CAT_Zeu_morel
Definition: l2prod.h:146