OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
convl21.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include "l12_proto.h"
6 #include "filehandle.h"
7 
8 /* ---------------------------------------------------------- */
9 /* Converts a sensor-generic level-2 record to level-1 */
10 /* */
11 /* B. A. Franz, GSC, SIMBIOS Project, August 1998 */
12 
13 /* ---------------------------------------------------------- */
14 
15 int convl21(l2str *l2rec, tgstr *tgrec, int32_t spix, int32_t epix,
16  float *vLt, vcstr *vrec) {
17  static int firstCall = 1;
18  static int vcal_opt = -1;
19  static float *brdfsensor;
20  static float *brdfinsitu;
21  static float *F0;
22  static float *wave;
23  static int32_t nwvis;
24 
25  int32_t ip; /* Pixel index */
26  int32_t ib; /* Band index */
27  int32_t ipb; /* Combined index */
28  float tLw;
29  float solz_insitu;
30  float mu0_sensor;
31  float mu0_insitu;
32  float chl;
33  float tau;
34  float *Rrs;
35  float *nLw;
36  float *Lw;
37  int foundneg;
38 
39  l1str *l1rec = l2rec->l1rec;
40  filehandle *l1file = l1rec->l1file;
41  int32_t nbands = l1file->nbands;
42 
43  /* Initialize static vars */
44  if (firstCall) {
45  firstCall = 0;
46  if ((brdfsensor = (float *) calloc(nbands, sizeof (float))) == NULL) {
47  printf("-E- %s line %d : error allocating memory for brdfsensor in convl21.\n",
48  __FILE__, __LINE__);
49  exit(1);
50  }
51  if ((brdfinsitu = (float *) calloc(nbands, sizeof (float))) == NULL) {
52  printf("-E- %s line %d : error allocating memory for brdfinsitu in convl21.\n",
53  __FILE__, __LINE__);
54  exit(1);
55  }
56  if ((F0 = (float *) calloc(nbands, sizeof (float))) == NULL) {
57  printf("-E- %s line %d : error allocating memory for F0 in convl21.\n",
58  __FILE__, __LINE__);
59  exit(1);
60  }
61  if ((wave = (float *) calloc(nbands, sizeof (float))) == NULL) {
62  printf("-E- %s line %d : error allocating memory for wave in convl21.\n",
63  __FILE__, __LINE__);
64  exit(1);
65  }
66 
67  for (ib = 0; ib < nbands; ib++) {
68  brdfsensor[ib] = 1.0;
69  brdfinsitu[ib] = 1.0;
70  /* Disabling. Assume full-band target data.
71  if (input->outband_opt >= 2)
72  F0[ib] = l2rec->Fonom[ib];
73  else
74  F0[ib] = l2rec->Fobar[ib];
75  */
76  F0[ib] = l1file->Fobar[ib];
77  }
78  for (ib = 0; ib < nbands; ib++)
79  wave[ib] = l1file->fwave[ib];
80  nwvis = rdsensorinfo(l1file->sensorID, l1_input->evalmask, "NbandsVIS", NULL);
81 
82  if (input->mode == INVERSE_LW || input->vcal_opt == INVERSE_LW)
83  vcal_opt = INVERSE_LW;
84  else if (input->mode == INVERSE_NLW || input->vcal_opt == INVERSE_NLW)
85  vcal_opt = INVERSE_NLW;
86  else if (input->mode == INVERSE_ZERO || input->vcal_opt == INVERSE_ZERO)
87  vcal_opt = INVERSE_ZERO;
88  else {
89  printf("%s: Unknown calibration inversion option %d %d\n",
90  __FILE__, input->mode, input->vcal_opt);
91  exit(1);
92  }
93  }
94  if ((Rrs = (float *) calloc(nbands, sizeof (float))) == NULL) {
95  printf("-E- %s line %d : error allocating memory for Rrs in convl21.\n",
96  __FILE__, __LINE__);
97  exit(1);
98  }
99  if ((nLw = (float *) calloc(nbands, sizeof (float))) == NULL) {
100  printf("-E- %s line %d : error allocating memory for nLw in convl21.\n",
101  __FILE__, __LINE__);
102  exit(1);
103  }
104  if ((Lw = (float *) calloc(nbands, sizeof (float))) == NULL) {
105  printf("-E- %s line %d : error allocating memory for Lw in convl21.\n",
106  __FILE__, __LINE__);
107  exit(1);
108  }
109 
110  /* Initialize radiances to zero */
111  memset(vLt, 0, sizeof (float)*l1rec->npix * l1file->nbands);
112 
113  /* */
114  /* Loop through each pixel and reconstruct the TOA */
115  /* radiances at each band from the components of the */
116  /* atmospheric correction and the nLw */
117  /* */
118  for (ip = spix; ip <= epix; ip++) {
119 
120  if (vrec != NULL) {
121  for (ib = 0; ib < nbands; ib++) {
122  ipb = ip * nbands + ib;
123  vrec->vLt [ipb] = BAD_FLT;
124  vrec->tLw [ipb] = BAD_FLT;
125  vrec->Lw [ipb] = BAD_FLT;
126  vrec->nLw [ipb] = BAD_FLT;
127  vrec->brdfsat[ipb] = BAD_FLT;
128  vrec->brdftgt[ipb] = BAD_FLT;
129  }
130  }
131 
132  /* If atmospheric corr failed, go to next pixel */
133  if (l1rec->mask[ip] || (l1rec->flags[ip] & ATMFAIL) != 0)
134  continue;
135 
136  /* If any target radiances are negative, go to next */
137  foundneg = 0;
138  if (tgrec != NULL) {
139  for (ib = 0; ib < nbands; ib++) {
140  ipb = ip * nbands + ib;
141  if (vcal_opt == INVERSE_LW) {
142  if (tgrec->Lw[ipb] < 0.0)
143  foundneg = 1;
144  } else if (vcal_opt == INVERSE_NLW) {
145  if (tgrec->nLw[ipb] < 0.0)
146  foundneg = 1;
147  }
148  }
149  }
150  if (foundneg) continue;
151 
152  /* Compute cos(solz) for sensor and in situ */
153  mu0_sensor = cos(l1rec->solz[ip] / RADEG);
154  if (tgrec != NULL)
155  if (tgrec->solz[ip] >= 0.0)
156  solz_insitu = tgrec->solz[ip];
157  else
158  solz_insitu = l1rec->solz[ip];
159  else {
160  if (input->vcal_solz >= 0.0)
161  solz_insitu = input->vcal_solz;
162  else
163  solz_insitu = l1rec->solz[ip];
164  }
165  mu0_insitu = cos(solz_insitu / RADEG);
166 
167 
168  /* Build target nLw from target Lw, using retrieved atmosphere */
169  for (ib = 0; ib < nbands; ib++) {
170  ipb = ip * nbands + ib;
171  if (vcal_opt == INVERSE_LW) {
172  tau = -log(l1rec->tg_sol[ipb] * l1rec->t_sol[ipb])
173  * mu0_sensor;
174  if (tgrec != NULL)
175  Lw[ib] = tgrec->Lw[ipb];
176  else
177  Lw[ib] = input->vcal_Lw[ib];
178  nLw[ib] = Lw[ib]
179  / mu0_insitu
180  / exp(-tau / mu0_insitu)
181  / l1rec->fsol;
182  } else if (vcal_opt == INVERSE_NLW) {
183  if (tgrec != NULL)
184  nLw[ib] = tgrec->nLw[ipb];
185  else
186  nLw[ib] = input->vcal_nLw[ib];
187  } else {
188  nLw[ib] = 0.0;
189  }
190  Rrs[ib] = nLw[ib] / F0[ib];
191  }
192 
193  /* Get chlorophyll from target nLw (if not specified) */
194  if (vcal_opt != INVERSE_ZERO) {
195  if (input->vcal_chl >= 0.0)
196  chl = input->vcal_chl;
197  else {
198  chl = get_default_chl(l2rec, Rrs);
199  if (chl < 0.0) continue;
200  }
201  } else {
202  chl = 0.0;
203  }
204 
205  /* Compute f/Q corrections, if requested */
206  if (input->brdf_opt != NOBRDF) {
207 
208  /* correction from sensor geometry to nadir view, zero sun angle */
209  ocbrdf(l2rec, ip, input->brdf_opt, wave, nwvis,
210  l1rec->solz[ip], l1rec->senz[ip], l1rec->delphi[ip], l1rec->ws[ip],
211  chl, nLw, F0, brdfsensor);
212 
213  /* correction from in situ geometry to nadir view, zero sun angle */
214  if (vcal_opt == INVERSE_LW) {
215  ocbrdf(l2rec, ip, input->brdf_opt, wave, nwvis,
216  solz_insitu, 0.0, 0.0, l1rec->ws[ip],
217  chl, nLw, F0, brdfinsitu);
218  }
219  }
220 
221  /* */
222  /* OK, loop through each band */
223  /* */
224  for (ib = 0; ib < nbands; ib++) {
225 
226  ipb = ip * nbands + ib;
227 
228  /* */
229  /* The target type controls how tLw is reconstructed */
230  /* */
231  switch (vcal_opt) {
232  case INVERSE_ZERO:
233  tLw = 0.0;
234  break;
235  case INVERSE_NLW:
236  tLw = nLw[ib]
237  / brdfsensor[ib]
238  * l1rec->polcor[ipb]
239  * l1rec->t_sol[ipb]
240  * l1rec->t_sen[ipb]
241  * l1rec->tg_sol[ipb]
242  * l1rec->tg_sen[ipb]
243  * mu0_sensor
244  * l1rec->fsol;
245  break;
246  case INVERSE_LW:
247  tLw = nLw[ib] * brdfinsitu[ib]
248  / brdfsensor[ib]
249  * l1rec->polcor[ipb]
250  * l1rec->t_sol[ipb]
251  * l1rec->t_sen[ipb]
252  * l1rec->tg_sol[ipb]
253  * l1rec->tg_sen[ipb]
254  * mu0_sensor
255  * l1rec->fsol;
256  break;
257  }
258 
259 
260  vLt[ipb] = tLw
261  + (((l1rec->TLg[ipb]
262  + l2rec->La[ipb])
263  * l1rec->t_o2[ipb]
264  + l1rec->tLf[ipb]
265  + l1rec->Lr [ipb])
266  * l1rec->polcor[ipb])
267  * l1rec->tg_sol[ipb]
268  * l1rec->tg_sen[ipb];
269 
270  if (vrec != NULL) {
271  vrec->tLw [ipb] = tLw;
272  vrec->Lw [ipb] = Lw[ib];
273  vrec->nLw [ipb] = nLw[ib];
274  vrec->brdfsat[ipb] = brdfsensor[ib];
275  vrec->brdftgt[ipb] = brdfinsitu[ib];
276  }
277  }
278  }
279 
280  free(Rrs);
281  free(nLw);
282  free(Lw);
283 
284  return (0);
285 }
int32 l1file(int32 sdfid, int32 *nsamp, int32 *nscans, int16 *dtynum)
Definition: l1stat_chk.c:586
#define INVERSE_NLW
Definition: filehandle.h:13
#define NULL
Definition: decode_rs.h:63
map< string, float > F0
Definition: DDSensor.cpp:39
read l1rec
instr * input
character(len=1000) if
Definition: names.f90:13
#define NOBRDF
Definition: l12_parms.h:50
l1_input_t * l1_input
Definition: l1_options.c:9
#define RADEG
Definition: czcs_ctl_pt.c:5
#define ATMFAIL
Definition: l2_flags.h:11
#define BAD_FLT
Definition: jplaeriallib.h:19
float get_default_chl(l2str *l2rec, float Rrs[])
Definition: get_chl.c:392
int32_t nbands
int32 spix
Definition: l1_czcs_hdf.c:21
int convl21(l2str *l2rec, tgstr *tgrec, int32_t spix, int32_t epix, float *vLt, vcstr *vrec)
Definition: convl21.c:15
int32 epix
Definition: l1_czcs_hdf.c:23
int32_t rdsensorinfo(int32_t, int32_t, const char *, void **)
Definition: rdsensorinfo.c:69
#define INVERSE_LW
Definition: filehandle.h:14
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 INVERSE_ZERO
Definition: filehandle.h:12