NASA Logo
Ocean Color Science Software

ocssw V2022
loadl1.c
Go to the documentation of this file.
1 /* =========================================================== */
2 /* Module loadl1.c */
3 /* */
4 /* Functions to fill a level-1b file with precomputed */
5 /* atmospheric and masking data. */
6 /* */
7 /* Note: due to filtering capabilities of MSl12, it can not be */
8 /* assumed that the same l1rec pointer will be passed in later */
9 /* calls to this function, so all fields must be reloaded. In */
10 /* addition, it is possible for MSl12 to process a L1B file */
11 /* containing data from different time periods, so earth-sun */
12 /* distance can not be assumed to be constant. */
13 /* */
14 /* Written By: */
15 /* */
16 /* B. A. Franz */
17 /* SAIC General Sciences Corp. */
18 /* NASA/SIMBIOS Project */
19 /* February 1999 */
20 /* */
21 /* Perturbed By: */
22 /* E.Karakoylu (SAIC) */
23 /* Summer 2015 */
24 /* =========================================================== */
25 
26 #include <stdio.h>
27 #include "l12_proto.h"
28 #include "smi_climatology.h"
29 #include "read_pixel_anc_file.h"
30 #include "anc_acq.h"
31 #include <libnav.h>
32 #include <xcal.h>
33 #include <smile.h>
34 
35 
36 int loadl1(filehandle *l1file, l1str *l1rec) {
37  static double radeg = RADEG;
38  static int32_t sensorID = -999;
39  static float *aw;
40  static float *bbw;
41  int navfail_cnt = 0;
42 
43  int32_t ip, ipb, ib, iw, ix;
44  double esdist;
45  int32_t nbands = l1rec->l1file->nbands;
46 
47  double *rvs;
48  double temp;
49  int16_t year, day;
50  double sec;
51  unix2yds(l1rec->scantime, &year, &day, &sec);
52 
53  if (sensorID != l1file->sensorID) {
54 
55  sensorID = l1file->sensorID;
56  aw = l1file->aw;
57  bbw = l1file->bbw;
58 
59 
60  printf("Loading land mask information from %s\n", input->land);
61  if (land_mask_init() != 0) {
62  printf("-E- %s : Unable to initialize land mask\n", __FILE__);
63  exit(1);
64  }
65 
66  printf("Loading DEM information from %s\n", input->demfile);
67  if (input->dem_auxfile[0])
68  printf("Loading auxiliary elevation file from %s\n", input->dem_auxfile);
69  if (dem_init() != 0) {
70  printf("-E- %s : Unable to initialize DEM \n", __FILE__);
71  exit(1);
72  }
73 
74  printf("Loading ice mask file from %s\n", input->icefile);
75  if (ice_mask_init(input->icefile, (int) year,
76  (int) day, input->ice_threshold) != 0) {
77  printf("-E- %s : Unable to initialize ice mask\n", __FILE__);
78  exit(1);
79  }
80 
81  }
82 
83  /* Get correction for Earth-Sun distance and apply to Fo */
84  int32_t yr = (int32_t) year;
85  int32_t dy = (int32_t) day;
86  int32_t ms = (int32_t) (sec * 1.e3);
87  esdist = esdist_(&yr, &dy, &ms);
88  l1rec->fsol = pow(1.0 / esdist, 2);
89 
90  for (iw = 0; iw < nbands; iw++) {
91  l1rec->Fo[iw] = l1file->Fobar[iw] * l1rec->fsol;
92  }
93 
94  /* Apply vicarious cross-calibration gains */
95 
96  for (ix = 0; ix < l1_input->xcal_nwave; ix++) {
97  if ((l1_input->xcal_opt[ix] & XCALRVS) != 0) {
98  if ((ib = bindex_get(l1_input->xcal_wave[ix])) < 0) {
99  printf("-E- %s line %d: xcal wavelength %f does not match sensor\n",
100  __FILE__, __LINE__, l1_input->xcal_wave[ix]);
101  exit(1);
102  };
103  rvs = get_xcal(l1rec, XRVS, l1file->iwave[ib]);
104 
105  for (ip = 0; ip < l1rec->npix; ip++) {
106  ipb = ip * nbands + ib;
107  if (rvs == 0x0) {
108  l1rec->Lt[ipb] = -999.0;
109  continue;
110  }
111  if (l1rec->Lt[ipb] > 0.0 && l1rec->Lt[ipb] < 1000.0)
112  l1rec->Lt[ipb] /= rvs[ip];
113  }
114  }
115  }
116 
117  for (ip = 0; ip < l1rec->npix; ip++) {
118  /* Apply vicarious calibration */
119 
120  for (iw = 0; iw < nbands; iw++) {
121  ipb = ip * nbands + iw;
122 
123  if (l1rec->Lt[ipb] > 0.0 && l1rec->Lt[ipb] < 1000.0) {
124  l1rec->Lt[ipb] *= l1_input->gain[iw];
125  l1rec->Lt[ipb] += l1_input->offset [iw];
126  }
127  }
128 
129  /*** Geolocation-based lookups ***/
130  if (!l1rec->navfail[ip]) {
131 
132  /* Enforce longitude convention */
133  if (l1rec->lon[ip] < -180.)
134  l1rec->lon[ip] += 360.0;
135 
136  else if (l1rec->lon[ip] > 180.0)
137  l1rec->lon[ip] -= 360.0;
138 
139  l1rec->dem[ip] = get_dem(l1rec->lat[ip], l1rec->lon[ip]);
140  /* Get terrain height */
141  if (input->proc_land) {
142  if (get_height(l1rec, ip,
143  l1file->terrain_corrected) != 0) {
144  printf("-E- %s line %d: Error getting terrain height.\n",
145  __FILE__, __LINE__);
146  return (1);
147  }
148  } else
149  l1rec->height[ip] = 0.0;
150 
151  /* Set land, bathymetry and ice flags */
152  if (input->proc_ocean != 2 &&
153  l1file->format != FT_L3BIN ) {
154  if( land_bath_mask(l1rec,ip) )
155  printf("-E- %s line %d: Error setting land and bathymetry masks.\n",
156  __FILE__, __LINE__);
157  }
158 
159  if (!l1rec->land[ip] &&
160  ice_mask(l1rec->lon[ip], l1rec->lat[ip]) != 0) {
161  l1rec->ice[ip] = ON;
162  }
163  } else {
164  navfail_cnt++;
165  }
166  /*** end Geolocation-based lookups ***/
167 
168  /* Set sea surface temperature and salinity, and seawater optical properties */
169  for (iw = 0; iw < nbands; iw++) {
170  ipb = ip * nbands + iw;
171  l1rec->sw_n [ipb] = 1.334;
172  // center band
173  l1rec->sw_a [ipb] = aw_spectra(l1file->fwave[iw], BANDW);
174  l1rec->sw_bb[ipb] = bbw_spectra(l1file->fwave[iw], BANDW);
175  // band-averaged
176  l1rec->sw_a_avg [ipb] = aw [iw];
177  l1rec->sw_bb_avg[ipb] = bbw[iw];
178  }
179 
180  l1rec->sstref[ip] = BAD_FLT;
181  l1rec->sssref[ip] = BAD_FLT;
182 
183  if (!l1rec->land[ip]) {
184  float bbw_fac;
185  l1rec->sstref[ip] = get_sstref(input->sstreftype, input->sstfile, l1rec, ip);
186  l1rec->sssref[ip] = get_sssref(input->sssfile, l1rec->lon[ip], l1rec->lat[ip], (int) day);
187  if (l1rec->sstref[ip] > BAD_FLT && l1rec->sssref[ip] > BAD_FLT && input->seawater_opt > 0) {
188  for (iw = 0; iw < nbands; iw++) {
189  ipb = ip * nbands + iw;
190  l1rec->sw_n [ipb] = seawater_nsw(l1file->fwave[iw], l1rec->sstref[ip], l1rec->sssref[ip], NULL);
191  // scale bbw based on ratio of center-band model results for actual sea state versus
192  // conditions of Morel measurements used to derive center and band-averaged bbw
193  bbw_fac = seawater_bb(l1file->fwave[iw], l1rec->sstref[ip], l1rec->sssref[ip], 0.039) / seawater_bb(l1file->fwave[iw], 20.0, 38.4, 0.039);
194  l1rec->sw_bb[ipb] *= bbw_fac;
195  l1rec->sw_bb_avg[ipb] *= bbw_fac;
196  }
197  }
198  }
200 
201  /* Compute relative azimuth */
202  /* CLASS AVHRR files contain relative azimuth so don't overwrite it */
203  if (sensorID != AVHRR) {
204  l1rec->delphi[ip] = l1rec->sena[ip] - 180.0 - l1rec->sola[ip];
205  }
206  if (l1rec->delphi[ip] < -180.)
207  l1rec->delphi[ip] += 360.0;
208  else if (l1rec->delphi[ip] > 180.0)
209  l1rec->delphi[ip] -= 360.0;
210 
211  /* Precompute frequently used trig relations */
212  l1rec->csolz[ip] = cos(l1rec->solz[ip] / radeg);
213  l1rec->csenz[ip] = cos(l1rec->senz[ip] / radeg);
214 
215  /* Scattering angle */
216  temp = sqrt((1.0 - l1rec->csenz[ip] * l1rec->csenz[ip])*(1.0 - l1rec->csolz[ip] * l1rec->csolz[ip]))
217  * cos(l1rec->delphi[ip] / radeg);
218  l1rec->scattang[ip] = acos(MAX(-l1rec->csenz[ip] * l1rec->csolz[ip] + temp, -1.0)) * radeg;
219 
220  }
221  /* get derived quantities for band-dependent view angles */
222  if (l1rec->geom_per_band != NULL)
224 
225  /* add ancillary data */
226  // the navfail_cnt test is a kludge to prevent processing failures for scans that are entirely invalid.
227  if (navfail_cnt != l1rec->npix) {
228  if (setanc(l1rec) != 0)
229  return (1);
230  } else {
231  // allocate the profile and cloud storage if files are in use
232  if( input->anc_profile1[0] != 0 )
233  if (init_anc_add(l1rec) != 0)
234  return 1;
235  if( strlen(input->sfc_albedo ) )
236  if (init_cld_dat(l1rec) != 0)
237  return 1;
238  }
239 
240  if (input->pixel_anc_file[0])
241  read_pixel_anc_file(input->pixel_anc_file, l1rec);
242 
243  if (input->windspeed > -999)
244  for (ip = 0; ip < l1rec->npix; ip++)
245  l1rec->ws[ip] = input->windspeed;
246  if (input->windangle > -999)
247  for (ip = 0; ip < l1rec->npix; ip++)
248  l1rec->wd[ip] = input->windangle;
249  if (input->pressure > -999)
250  for (ip = 0; ip < l1rec->npix; ip++)
251  l1rec->pr[ip] = input->pressure;
252  if (input->ozone > -999)
253  for (ip = 0; ip < l1rec->npix; ip++)
254  l1rec->oz[ip] = input->ozone;
255  if (input->watervapor > -999)
256  for (ip = 0; ip < l1rec->npix; ip++)
257  l1rec->wv[ip] = input->watervapor;
258  if (input->relhumid > -999)
259  for (ip = 0; ip < l1rec->npix; ip++)
260  l1rec->rh[ip] = input->relhumid;
261 
262  /* SWIM bathymetry */
263  // for (ip = 0; ip < l1rec->npix; ip++)
264  // if (!l1rec->navfail[ip])
265  // l1rec->dem[ip] = get_elev(l1rec->lat[ip], l1rec->lon[ip]);
266 
267  /* add atmospheric cnomponents that do not depend on Lt */
268  for (ip = 0; ip < l1rec->npix; ip++) {
269 
270  if (l1rec->is_l2){
271  // l1rec->Lt is actually Rrs, so skip atmo, etc
272  } else {
273  /* ------------------------------------------------ */
274  /* Ocean processing */
275  /* ------------------------------------------------ */
276  if ((input->proc_ocean != 0) && !l1rec->land[ip] && !l1rec->navfail[ip]) {
277 
278  atmocor1(l1rec, ip);
279 
280  /* set polarization correction */
281  polcor(l1rec, ip);
282 
283  /* add surface reflectance */
284  get_rhos(l1rec, ip);
285  }
286  /* ------------------------------------------------ */
287  /* Land Processing */
288  /* ------------------------------------------------ */
289  else if (input->proc_land && l1rec->land[ip] && !l1rec->navfail[ip]) {
290  atmocor1_land(l1rec, ip);
291  get_rhos(l1rec, ip);
292  }
293  /* ------------------------------------------------ */
294  /* General Processing */
295  /* ------------------------------------------------ */
296  else {
297  for (ib = 0; ib < nbands; ib++) {
298  ipb = ip * nbands + ib;
299  l1rec->Lr [ipb] = 0.0;
300  l1rec->t_sol [ipb] = 1.0;
301  l1rec->t_sen [ipb] = 1.0;
302  l1rec->tg_sol[ipb] = 1.0;
303  l1rec->tg_sen[ipb] = 1.0;
304  l1rec->t_o2 [ipb] = 1.0;
305  l1rec->t_h2o [ipb] = 1.0;
306  l1rec->polcor [ipb] = 1.0;
307  }
308  }
309  }
310 
311  }
312  /* set masks and flags */
313  if (setflags(l1rec) == 0)
314  return (1);
315 
316  setflagbits_l1(1, l1rec, -1);
317 
318  return (0);
319 }
int32 l1file(int32 sdfid, int32 *nsamp, int32 *nscans, int16 *dtynum)
Definition: l1stat_chk.c:586
#define MAX(A, B)
Definition: swl0_utils.h:25
int32_t day
float get_sstref(short reftyp, char *file, l1str *l1rec, int32_t ip)
Definition: sstref.c:1601
#define AVHRR
Definition: sensorDefs.h:15
int get_height(l1str *l1rec, int32_t ip, int terrain_corrected)
Definition: get_height.c:20
int loadl1(filehandle *l1file, l1str *l1rec)
Definition: loadl1.c:36
#define NULL
Definition: decode_rs.h:63
#define XCALRVS
Definition: l1.h:86
int dem_init()
Definition: read_mask.c:43
read l1rec
int geom_per_band_deriv(l1str *l1rec)
Definition: geom_per_band.c:51
#define XRVS
Definition: xcal.h:10
int setanc(l1str *l1rec)
Definition: setanc.c:628
double esdist_(int32_t *year, int32_t *day, int32_t *msec)
void polcor(l1str *l1rec, int32_t ip)
Definition: polcor.c:17
#define ON
Definition: l1.h:44
instr * input
character(len=1000) if
Definition: names.f90:13
int land_mask_init()
Definition: read_mask.c:23
int bindex_get(int32_t wave)
Definition: windex.c:45
void atmocor1(l1str *l1rec, int32_t ip)
Definition: atmocor1.c:38
float seawater_nsw(float wave, float sst, float sss, float *dnswds)
Definition: seawater.c:8
int ice_mask_init(char *file, int year, int day, float threshold)
Definition: ice_mask.c:900
float get_sssref(char *file, float lon, float lat, int day)
Definition: sssref.c:360
int land_bath_mask(l1str *l1rec, int32_t ip)
Definition: read_mask.c:125
int init_anc_add(l1str *l1rec)
Definition: anc_acq.c:1131
float aw_spectra(int32_t wl, int32_t width)
l1_input_t * l1_input
Definition: l1_options.c:9
float bbw_spectra(int32_t wl, int32_t width)
int get_rhos(l1str *l1rec, int32_t ip)
Definition: get_rhos.c:23
int atmocor1_land(l1str *l1rec, int32_t ip)
Definition: atmocor1_land.c:20
char ice_mask(float lon, float lat)
Definition: ice_mask.c:993
void unix2yds(double usec, short *year, short *day, double *secs)
#define RADEG
Definition: czcs_ctl_pt.c:5
double * get_xcal(l1str *l1rec, int type, int wave)
Definition: xcal.c:33
#define BAD_FLT
Definition: jplaeriallib.h:19
int32_t nbands
real *8 function esdist(iyr, iday, msec)
Definition: esdist.f:3
int setflags(l1str *l1rec)
Definition: setflags_l1.c:16
void setflagbits_l1(int level, l1str *l1rec, int32_t ipix)
Definition: setflags_l1.c:131
#define BANDW
Definition: l1.h:53
for(i=0;i< NROOTS;i++) s[i]
Definition: decode_rs.h:85
void read_pixel_anc_file(char *filename, l1str *l1rec)
float get_dem(float lat, float lon)
Definition: read_mask.c:112
int32_t sensorID[MAXNFILES]
Definition: l2bin.cpp:91
int init_cld_dat(l1str *l1rec)
float seawater_bb(float wave, float sst, float sss, double delta)
Definition: seawater.c:176
@ FT_L3BIN
Definition: filetype.h:24
void seawater_set(l1str *l1rec)
Definition: seawater_get.c:8