OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
get_pml.c
Go to the documentation of this file.
1 /*
2  * get_pml.c
3  *
4  * MSl12 wrapper for PML IOP Algorithm
5  *
6  * Plymouth Marine Laboratory, UK
7  *
8  * Reference: Smyth et al. (2006) "Semianalytical model for the derivation of
9  * ocean color inherent optical properties: description, implementation,
10  * and performance assessment" Applied Optics, 45(31).
11  */
12 
13 #include <stdlib.h>
14 #include <math.h>
15 #include "pml.h"
16 #include "pml_iop.h"
17 #include "pml_iop_config.h"
18 #include "pml_iop_tables.h"
19 #include "pml_iop_calculate.h"
20 
21 #include "l12_proto.h"
22 #include "l2prod.h"
23 
24 static int PMLRecNum = -1;
25 static float badval = BAD_FLT;
26 
27 static float *atot;
28 static float *bb;
29 static float *bbp;
30 static float *adg;
31 static float *aph;
32 
33 static float *aw;
34 static float *bbw;
35 
36 static int iw410;
37 static int iw440;
38 static int iw490;
39 static int iw510;
40 static int iw531;
41 static int iw555;
42 static int iw670;
43 
44 int pml_ran(int recnum) {
45  if (recnum == PMLRecNum)
46  return 1;
47  else
48  return 0;
49 }
50 
51 /* Allocate private arrays for a single scan line */
52 void alloc_pml(int32_t npix, int32_t nbands) {
53  atot = (float*) calloc(npix*nbands, sizeof (float));
54  aph = (float*) calloc(npix*nbands, sizeof (float));
55  adg = (float*) calloc(npix*nbands, sizeof (float));
56  bb = (float*) calloc(npix*nbands, sizeof (float));
57  bbp = (float*) calloc(npix*nbands, sizeof (float));
58 }
59 
60 static float* alloc_bandsf(int32_t nbands, float *nbarray) {
61  if ((nbarray = (float *) calloc(nbands, sizeof (float))) == NULL) {
62  printf("-E- : Error allocating float memory in get_pml\n");
63  exit(FATAL_ERROR);
64  }
65  return nbarray;
66 }
67 
68 static double* alloc_bandsd(int32_t nbands, double *nbarray) {
69  if ((nbarray = (double *) calloc(nbands, sizeof (double))) == NULL) {
70  printf("-E- : Error allocating double memory in get_pml\n");
71  exit(FATAL_ERROR);
72  }
73  return nbarray;
74 }
75 
76 void run_pml(l2str *l2rec) {
77  char *tmp_str;
78  char configfname[FILENAME_MAX];
79 
80  static int firstCall = 1;
81  int result = 0; /* flag for successful iterations */
82  int CASEII; /* flag for caseII waters (set by the bright pixel code) */
83 
84  static float *Rrs; /* above surface Rrs */
85  static double *rho_w; /* above surface water reflectance */
86  static float *buf; /* temporary storage for QAA algorithm */
87  static double *a_pml;
88  static double *bb_pml;
89  static double *bbp_pml;
90  static double *adg_pml;
91  static double *aph_pml;
92  double solz;
93  float senz, phi;
94 
95  int32_t ip, ib, ipb;
96 
97  l1str *l1rec = l2rec->l1rec;
98  filehandle *l1file = l1rec->l1file;
99  int32_t nbands = l1file->nbands;
100 
101 
102  buf = alloc_bandsf(4 * nbands, buf);
103  Rrs = alloc_bandsf(nbands, Rrs);
104  rho_w = alloc_bandsd(nbands, rho_w);
105  a_pml = alloc_bandsd(nbands, a_pml);
106  bb_pml = alloc_bandsd(nbands, bb_pml);
107  bbp_pml = alloc_bandsd(nbands, bbp_pml);
108  adg_pml = alloc_bandsd(nbands, adg_pml);
109  aph_pml = alloc_bandsd(nbands, aph_pml);
110 
111  if (firstCall) {
112 
113  firstCall = 0;
114  if ((aw = (float *) calloc(nbands + 1, sizeof (float))) == NULL) {
115  printf("-E- : Error allocating memory to aw in get_pml\n");
116  exit(FATAL_ERROR);
117  }
118  if ((bbw = (float *) calloc(nbands + 1, sizeof (float))) == NULL) {
119  printf("-E- : Error allocating memory to bbw in get_pmln");
120  exit(FATAL_ERROR);
121  }
122 
123  /* Load the various LUTs into memory */
124  if ((tmp_str = getenv("OCDATAROOT")) == NULL) {
125  printf("OCDATAROOT environment variable is not defined.\n");
126  exit(1);
127  }
128  strcpy(configfname, tmp_str);
129  strcat(configfname, "/common/pml.cfg");
130  printf("Loading PML IOP model config file: %s\n", configfname);
131  load_work_tab(configfname, l1file->sensorID);
132 
133  /* Load the various parameters into memory */
134  load_config(configfname);
135 
136  alloc_pml(l1rec->npix, nbands);
137 
138  iw410 = bindex_get(410);
139  iw440 = bindex_get(440);
140  iw490 = bindex_get(490);
141  iw510 = bindex_get(510);
142  iw531 = bindex_get(531);
143  iw555 = bindex_get(551);
144  iw670 = bindex_get(670);
145 
146  if (iw531 > 0 && iw510 < 0) {
147  printf("PML IOP model using MODIS eps_a slopes\n");
148  iw510 = iw531;
149  }
150 
151  if (iw410 < 0 || iw440 < 0 || iw490 < 0 || iw510 < 0 || iw555 < 0) {
152  printf("-E- %s line %d: PML model requires bands near 410, 440, 490, 510 and 555nm\n",
153  __FILE__, __LINE__);
154  exit(1);
155  }
156 
157  if (l1_input->outband_opt >= 2) {
158  for (ib = 0; ib < nbands; ib++) {
159  aw [ib] = aw_spectra(l1file->iwave[ib], BANDW);
160  bbw[ib] = bbw_spectra(l1file->iwave[ib], BANDW);
161  }
162  } else {
163  for (ib = 0; ib < nbands; ib++) {
164  aw [ib] = l1file->aw[ib];
165  bbw[ib] = l1file->bbw[ib];
166  }
167  }
168 
169  if (!pml_is_initialized()) {
170  pml_init(1, iw410, iw440, iw490, iw510, iw555, iw670, aw, bbw);
171  }
172  }
173 
174  for (ip = 0; ip < l1rec->npix; ip++) {
175 
176  /* Get the angular information */
177  solz = (M_PI / 180.)*(l1rec->solz[ip]);
178  senz = (M_PI / 180.)*(l1rec->senz[ip]);
179  phi = (M_PI / 180.)*(l1rec->delphi[ip]);
180 
181  /* clear static globals */
182  for (ib = 0; ib < nbands; ib++) {
183  ipb = ip * nbands + ib;
184  bb [ipb] = -1.0;
185  bbp [ipb] = -1.0;
186  atot[ipb] = -1.0;
187  adg [ipb] = -1.0;
188  aph [ipb] = -1.0;
189  /* difference for these parameters as done on line-by-line basis */
190  a_pml[ib] = -1.0;
191  bb_pml[ib] = -1.0;
192  adg_pml[ib] = -1.0;
193  aph_pml[ib] = -1.0;
194  }
195 
196  if (!l1rec->mask[ip]) {
197 
198  ipb = ip*nbands;
199 
200  /* compute Rrs at 412, 443, 488/490, 531/510, 551/555, 667/670 */
201  for (ib = 0; ib < nbands; ib++) {
202  Rrs[ib] = l2rec->Rrs[ipb + ib];
203  /* convert Rrs into rho_w for running of model */
204  rho_w[ib] = M_PI * Rrs[ib];
205  }
206 
207  /* run the model in here */
208  CASEII = 0;
209  /* if (l2rec->bpsed[ip] > 0.)
210  CASEII = 1; */
211 
212  result = iop_model(rho_w, solz, senz, phi, a_pml, bb_pml, adg_pml, aph_pml, iw531, CASEII);
213 
214  /* store results for this pixel in static globals */
215  for (ib = 0; ib < nbands; ib++) {
216 
217  ipb = ip * nbands + ib;
218 
219  if (isfinite(bb_pml[ib]) && result != 1) {
220  bbp[ipb] = bb_pml[ib];
221  bb [ipb] = bb_pml[ib] + bbw[ib];
222  } else {
223  bbp[ipb] = badval;
224  bb [ipb] = badval;
225  l1rec->flags[ip] |= PRODFAIL;
226  }
227 
228  if (isfinite(a_pml[ib]) && result != 1)
229  atot[ipb] = a_pml[ib] + aw[ib];
230  else {
231  atot[ipb] = badval;
232  l1rec->flags[ip] |= PRODFAIL;
233  }
234 
235  if (isfinite(adg_pml[ib]) && result != 2)
236  adg[ipb] = adg_pml[ib];
237  else {
238  adg[ipb] = badval;
239  l1rec->flags[ip] |= PRODFAIL;
240  }
241 
242  if (isfinite(aph_pml[ib]) && result != 2)
243  aph[ipb] = aph_pml[ib];
244  else {
245  aph[ipb] = badval;
246  l1rec->flags[ip] |= PRODFAIL;
247  }
248  }
249  }
250  }
251 
252  PMLRecNum = l1rec->iscan;
253 
254  free(buf);
255  free(Rrs);
256  free(rho_w);
257  free(a_pml);
258  free(bb_pml);
259  free(bbp_pml);
260  free(adg_pml);
261  free(aph_pml);
262 
263  return;
264 }
265 
266 /* Interface to l2_hdf_generic() to return PML products */
267 
268 void get_pml(l2str *l2rec, l2prodstr *p, float prod[]) {
269  int band = p->prod_ix;
270  int prodID = p->cat_ix;
271  int ip, ipb;
272 
273  if (!pml_ran(l2rec->l1rec->iscan))
274  run_pml(l2rec);
275 
276  for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
277 
278  ipb = ip * l2rec->l1rec->l1file->nbands + band;
279 
280  switch (prodID) {
281 
282  case CAT_a_pml:
283  prod[ip] = (float) atot[ipb];
284  break;
285 
286  case CAT_adg_pml:
287  prod[ip] = (float) adg[ipb];
288  break;
289 
290  case CAT_aph_pml:
291  prod[ip] = (float) aph[ipb];
292  break;
293 
294  case CAT_bb_pml:
295  prod[ip] = (float) bb[ipb];
296  break;
297 
298  case CAT_bbp_pml:
299  prod[ip] = (float) bbp[ipb];
300  break;
301 
302  default:
303  printf("-E- %s line %d : erroneous product ID %d passed to get_pml().\n",
304  __FILE__, __LINE__, prodID);
305  exit(1);
306  }
307  }
308 
309  return;
310 }
311 
312 /* Interface to convl12() to return PML iops */
313 void iops_pml(l2str *l2rec) {
314  int32_t ib, ip, ipb;
315  int32_t nbands = l2rec->l1rec->l1file->nbands;
316 
317  if (!pml_ran(l2rec->l1rec->iscan))
318  run_pml(l2rec);
319 
320  for (ip = 0; ip < l2rec->l1rec->npix; ip++)
321  for (ib = 0; ib < nbands; ib++) {
322  ipb = ip * nbands + ib;
323  l2rec->a [ipb] = (float) atot[ipb];
324  l2rec->bb[ipb] = (float) bb [ipb];
325  }
326 
327  return;
328 }
329 
int32 l1file(int32 sdfid, int32 *nsamp, int32 *nscans, int16 *dtynum)
Definition: l1stat_chk.c:586
int load_work_tab(char *configfname, int sensorID)
#define CAT_a_pml
Definition: l2prod.h:179
#define NULL
Definition: decode_rs.h:63
read l1rec
PARAM_TYPE_NONE Default value No parameter is buried in the product name name_prefix is case insensitive string compared to the product name PARAM_TYPE_VIS_WAVE The visible wavelength bands from the sensor are buried in the product name The product name is compared by appending and name_suffix ie aph_412_giop where prod_ix will be set to PARAM_TYPE_IR_WAVE same search method as PARAM_TYPE_VIS_WAVE except only wavelength above are looped through but prod_ix is still based ie aph_2_giop for the second band
int pml_init(int iter8, int i410, int i440, int i490, int i510, int i555, int i670, float *awptr, float *bbwptr)
Definition: pml.c:60
#define CAT_aph_pml
Definition: l2prod.h:183
#define PRODFAIL
Definition: l2_flags.h:41
#define CAT_adg_pml
Definition: l2prod.h:184
int bindex_get(int32_t wave)
Definition: windex.c:45
void get_pml(l2str *l2rec, l2prodstr *p, float prod[])
Definition: get_pml.c:268
read recnum
#define CAT_bb_pml
Definition: l2prod.h:181
float aw_spectra(int32_t wl, int32_t width)
l1_input_t * l1_input
Definition: l1_options.c:9
#define FATAL_ERROR
Definition: swl0_parms.h:5
float bbw_spectra(int32_t wl, int32_t width)
void load_config(char *configfname)
#define M_PI
Definition: pml_iop.h:15
int pml_is_initialized(void)
Definition: pml.c:42
int iop_model(double rho_w[], float sun_theta, float sen_theta, float dphi, double a[], double bbp[], double ady[], double ap[], int MODIS, int CASEII)
void run_pml(l2str *l2rec)
Definition: get_pml.c:76
#define CAT_bbp_pml
Definition: l2prod.h:182
void iops_pml(l2str *l2rec)
Definition: get_pml.c:313
#define BAD_FLT
Definition: jplaeriallib.h:19
int pml_ran(int recnum)
Definition: get_pml.c:44
int32_t nbands
#define BANDW
Definition: l1.h:52
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int npix
Definition: get_cmp.c:27
float p[MODELMAX]
Definition: atrem_corl1.h:131
void alloc_pml(int32_t npix, int32_t nbands)
Definition: get_pml.c:52