Due to the lapse in federal government funding, NASA is not updating this website. We sincerely regret this inconvenience.
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:679
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