OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
target_io.c
Go to the documentation of this file.
1 /* =========================================================== */
2 /* Module read_target.c */
3 /* */
4 /* Functions to open and read a recalibration target file. */
5 /* */
6 /* Written By: */
7 /* */
8 /* B. A. Franz */
9 /* SAIC General Sciences Corp. */
10 /* NASA/SIMBIOS Project */
11 /* April 1998 */
12 /* */
13 /* =========================================================== */
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include "l12_proto.h"
20 #include "filehdr_struc.h"
21 /*
22 #include "target_struc.h"
23 #include "filehandle.h"
24  */
25 #include "read_l3bin.h"
26 #include <gsl/gsl_math.h>
27 #include <gsl/gsl_spline.h>
28 
29 static FILE *fp = NULL;
30 static char current_file[FILENAME_MAX];
31 
32 
33 /* ----------------------------------------------------------- */
34 /* close_target() - close recal target file */
35 
36 /* ----------------------------------------------------------- */
37 void close_target(void) {
38  fclose(fp);
39 }
40 
41 
42 /* ----------------------------------------------------------- */
43 /* read_targethdr() - loads header info */
44 
45 /* ----------------------------------------------------------- */
46 int read_targethdr(filehandle *file) {
47  filehdr hdr;
48 
49  fseek(fp, 0, SEEK_SET);
50 
51  if (fread(&hdr, 1, sizeof (hdr), fp) != sizeof (hdr)) {
52  printf("-E- %s: File read error.\n", __FILE__);
53  return (1);
54  }
55 
56  if (hdr.length < 0 || hdr.length > 1000000 ||
57  hdr.npix < 0 || hdr.npix > 10000) {
58  printf("-E- %s: Header values out of range.\n", __FILE__);
59  printf(" Record length = %d\n", hdr.length);
60  printf(" Pixels per scan = %d\n", hdr.npix);
61  return (1);
62  }
63 
64  file->sensorID = hdr.sensorID;
65  file->length = hdr.length;
66  file->npix = hdr.npix;
67  file->format = hdr.format;
68  file->nscan = hdr.nscan;
69  file->mode = READ;
70 
71  return (0);
72 }
73 
74 
75 /* ----------------------------------------------------------- */
76 /* open_target() - opens file if not already opened */
77 
78 /* ----------------------------------------------------------- */
79 int open_target(filehandle *file) {
80  if (fp == NULL || strcmp(file->name, current_file) != 0) {
81  if (fp != NULL) close_target();
82  if ((fp = fopen(file->name, "r")) == NULL) {
83  printf("-E- %s: Error opening %s for reading.\n",
84  __FILE__, file->name);
85  return (1);
86  }
87  strcpy(current_file, file->name);
88  if (read_targethdr(file) != 0) {
89  printf("-E- %s: Error reading header for %s.\n",
90  __FILE__, file->name);
91  return (1);
92  }
93  }
94 
95  return (0);
96 }
97 
98 
99 /* ----------------------------------------------------------- */
100 /* read_target() - reads one recal target record */
101 /* */
102 /* B. A. Franz, GSC, SIMBIOS Project, March 1998 */
103 
104 /* ----------------------------------------------------------- */
105 int read_target(filehandle *file, int32_t recnum, tgstr *tgrec) {
106  /* */
107  /* Open the input file if it is not already open */
108  /* */
109  if (open_target(file) != 0) {
110  printf("-E- %s: File open error.\n", __FILE__);
111  return (1);
112  }
113 
114  if (feof(fp)) {
115  printf("-I- %s: End of target file %s reached.",
116  __FILE__, file->name);
117  return (1);
118  }
119 
120  if (fseek(fp, (recnum + 1) * file->length, SEEK_SET) != 0) {
121  printf("-E- %s: Error seeking record %d in %s.",
122  __FILE__, recnum, file->name);
123  return (1);
124  }
125 
126  if (fread(tgrec->data, 1, file->length, fp) != file->length) {
127  return (1);
128  }
129 
130  tgrec->sensorID = file->sensorID;
131  tgrec->length = file->length;
132  tgrec->npix = file->npix;
133 
134  return (0);
135 }
136 
146 int32_t bin_match(int32_t nbins, int32_t *bins, int32_t bin_num) {
147  int32_t jl = -1, ju = nbins, jm = 0;
148  int32_t ascnd;
149 
150  ascnd = (bins[nbins - 1] >= bins[0]);
151  while (ju - jl > 1) {
152  jm = (ju + jl) / 2;
153  if (ascnd == (bin_num >= bins[jm]))
154  jl = jm;
155  else
156  ju = jm;
157  }
158 
159  if (bin_num == bins[jl]) return (jl);
160  if (jl + 1 < nbins && bin_num == bins[jl + 1]) return (jl + 1);
161  if (jl > 0 && bin_num == bins[jl - 1]) return (jl - 1);
162  if (bin_num == bins[0]) return (0);
163  if (bin_num == bins[nbins - 1]) return (nbins - 1);
164 
165  return (-1);
166 }
167 
176 int32_t lonlat2bin(l3binstr *l3bin, float lon, float lat) {
177  int32_t row;
178  int32_t col;
179  int32_t bin;
180 
181  lat = MAX(MIN(lat, 90), -90);
182  lon = MAX(MIN(lon, 180), -180);
183 
184  row = MIN(((90 + lat) * l3bin->nrows / 180.0), l3bin->nrows - 1);
185  col = MIN(((lon + 180.0) * l3bin->numbin[row] / 360.0), l3bin->numbin[row]);
186 
187  bin = l3bin->basebin[row] + col;
188 
189  return (bin);
190 }
191 
192 
193 /* ----------------------------------------------------------- */
194 /* read_target_l3() - loads one recal target record */
195 /* */
196 /* B. A. Franz, GSC, SIMBIOS Project, March 1998 */
197 /* ----------------------------------------------------------- */
198 
209 int read_target_l3(filehandle *file, l1str *l1rec, int32_t nbands, tgstr *tgrec) {
210  static int firstCall = 1;
211  static l3binstr l3bin;
212  static int l3nwaves;
213  static float *l3wvls;
214  static double *l3wvlinterp;
215  static int *wvlmatch;
216  static int nvisbands;
217 
218  int32_t ip, ib, ipb, band;
219  int32_t bin, idx, nobs, nscenes;
220  float chl, aot;
221  static int needBandShift = 0;
222  int l3nbands;
223  static float *l3vals;
224  static double *l3valsinterp;
225  static gsl_interp_accel *acc;
226  static gsl_spline *spline_steffen;
227  float interpband; // for linear and spline interp
228 
229  if (firstCall) {
230  l3nbands = rdsensorinfo(tgrec->sensorID, 0, "fwave", (void **) &l3wvls);
231 
232  read_l3bin(file->name, &l3bin, l3nbands);
233  l3nwaves = l3bin.nwave;
234  if ((l3bin.sensorID != l1rec->l1file->sensorID) && (input->band_shift_opt != 2)) {
235  needBandShift = 1;
236  }
237  wvlmatch = (int *) malloc(l1rec->l1file->nbands * sizeof (int));
238 
239  for (ib = 0; ib < l1rec->l1file->nbands; ib++) {
240  wvlmatch[ib] = windex(l1rec->l1file->fwave[ib], l3bin.wavelengths, l3nwaves);
241  if (l1rec->l1file->iwave[ib] < 700) {
242  nvisbands++;
243  }
244  }
245  l3wvlinterp = (double *) calloc(l3nwaves, sizeof (double));
246  for (band = 0; band < l3nwaves; band++) {
247  l3wvlinterp[band] = l3bin.wavelengths[band];
248  }
249  l3valsinterp = (double *) calloc(l3nwaves, sizeof (double));
250  l3vals = (float *) calloc(l3nwaves, sizeof (float));
251 
252  acc = gsl_interp_accel_alloc();
253  spline_steffen = gsl_spline_alloc(gsl_interp_steffen, l3nwaves);
254  firstCall = 0;
255  }
256 
257  for (ip = 0; ip < l1rec->npix; ip++) {
258  // initialize target rec
259  for (ib = 0; ib < nbands; ib++) {
260  ipb = ip * nbands + ib;
261  tgrec->nLw[ipb] = BAD_FLT;
262  tgrec->Lw[ipb] = BAD_FLT;
263  }
264  tgrec->solz[ip] = BAD_FLT;
265 
266  // check L1 masking
267  if (input->vcal_depth < 0) {
268  if (l1rec->dem[ip] > input->vcal_depth)
269  continue;
270  }
271  // locate bin
272  bin = lonlat2bin(&l3bin, l1rec->lon[ip], l1rec->lat[ip]);
273  idx = bin_match(l3bin.nbins, l3bin.bins, bin);
274 
275  // check masking and copy values
276  if (idx >= 0) {
277  chl = l3bin.chl[idx];
278  aot = l3bin.tau[idx];
279  nobs = l3bin.nobs[idx];
280  nscenes = l3bin.nscenes[idx];
281  for (band = 0; band < l3nwaves; band++) {
282  l3valsinterp[band] = l3bin.data[idx][band];
283  l3vals[band] = l3bin.data[idx][band];
284  if (!l3bin.hasRrs) {
285  l3vals[band] /= l1rec->Fo[ib];
286  l3valsinterp[band] /= l1rec->Fo[ib];
287  } // Need Rrs for bandshift
288 
289  }
290 
291  gsl_spline_init(spline_steffen, l3wvlinterp, l3valsinterp, l3nwaves);
292 
293  if (chl <= input->chlthreshold && aot <= input->aotthreshold
294  && nobs >= input->vcal_min_nbin && nscenes >= input->vcal_min_nscene) {
295 
296  for (ib = 0; ib < nvisbands; ib++) {
297  ipb = ip * nbands + ib;
298  // Only bandshift if L2 wvl is different from L3 wvl even if sensors differ
299  if (needBandShift && (l3bin.wavelengths[wvlmatch[ib]] != l1rec->l1file->fwave[ib])) {
300  // option 0: linear interpolation
301  if (input->band_shift_opt == 0 || l1rec->l1file->fwave[ib] > 700) {
302  if (l1rec->l1file->fwave[ib] > l3bin.wavelengths[0] &&
303  l1rec->l1file->fwave[ib] < l3bin.wavelengths[l3nwaves-1]) {
304  // interpband = linterp(l3wvls, l3vals, l3nwaves, l1rec->l1file->fwave[ib]);
305  interpband = gsl_spline_eval(spline_steffen, l1rec->l1file->fwave[ib], acc);
306  } else {
307  // don't extrapolate, just use the l3 value as if we didn't need to shift
308  interpband = l3bin.data[idx][wvlmatch[ib]];
309  }
310  // option 1: bio-optical band shift
311  } else if (input->band_shift_opt == 1 && l1rec->l1file->fwave[ib] <= 700) {
312  interpband = bioBandShift(l3bin.wavelengths, l3vals, chl, l3nwaves, l1rec->l1file->fwave[ib]);
313  } else {
314  printf("-E- %s:%d: band_shift_opt error.\n", __FILE__, __LINE__);
315  exit(EXIT_FAILURE);
316  }
317 
318  interpband *= l1rec->Fo[ib];
319  tgrec->nLw[ipb] = interpband;
320 
321  //the nLws in the target files are now in W/m2/um/sr, so a factor of 10 too big
322  if (l3bin.hasRrs == 0)
323  tgrec->nLw[ipb] /= 10.;
324  } else {
325  if (l3bin.hasRrs == 1)
326  tgrec->nLw[ipb] = l3bin.data[idx][wvlmatch[ib]] * l1rec->Fo[ib];
327  else
328  tgrec->nLw[ipb] = l3bin.data[idx][wvlmatch[ib]] / 10.;
329  }
330  }
331  for (ib = nvisbands; ib < nbands; ib++) {
332  ipb = ip * nbands + ib;
333  tgrec->nLw[ipb] = 0.0;
334  }
335  }
336  }
337  }
338 
339  tgrec->sensorID = l1rec->l1file->sensorID;
340  tgrec->npix = l1rec->npix;
341 
342  return (0);
343 }
#define MAX(A, B)
Definition: swl0_utils.h:26
#define MIN(x, y)
Definition: rice.h:169
#define NULL
Definition: decode_rs.h:63
#define READ
Definition: l1c.h:32
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 open_target(filehandle *file)
Definition: target_io.c:79
float * lat
int read_target_l3(filehandle *file, l1str *l1rec, int32_t nbands, tgstr *tgrec)
Definition: target_io.c:209
int32_t bin_match(int32_t nbins, int32_t *bins, int32_t bin_num)
Definition: target_io.c:146
int32_t nobs
Definition: atrem_cor.h:93
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude resolving resolving GSFcd00179 Corrected handling of fill values for[Sensor|Solar][Zenith|Azimuth] resolving MODxl01751 Changed to validate LUT version against a value retrieved from the resolving MODxl02056 Changed to calculate Solar Diffuser angles without adjustment for estimated post launch changes in the MODIS orientation relative to incidentally resolving defects MODxl01766 Also resolves MODxl01947 Changed to ignore fill values in SCI_ABNORM and SCI_STATE rather than treating them as resolving MODxl01780 Changed to use spacecraft ancillary data to recognise when the mirror encoder data is being set by side A or side B and to change calculations accordingly This removes the need for seperate LUTs for Side A and Side B data it makes the new LUTs incompatible with older versions of the and vice versa Also resolves MODxl01685 A more robust GRing algorithm is being which will create a non default GRing anytime there s even a single geolocated pixel in a granule Removed obsolete messages from seed file
Definition: HISTORY.txt:413
instr * input
int32_t read_l3bin(char *file, l3binstr *l3bin, int32_t nbands)
Definition: read_l3bin.cpp:27
read recnum
int read_target(filehandle *file, int32_t recnum, tgstr *tgrec)
Definition: target_io.c:105
#define BAD_FLT
Definition: jplaeriallib.h:19
int32_t nbands
int windex(float wave, float twave[], int ntwave)
Definition: windex.c:73
int16_t * nscenes
Definition: l2bin.cpp:86
float * lon
void close_target(void)
Definition: target_io.c:37
float bioBandShift(float wvl[], float rrs[], float chla, int nw, float tarWvl)
Definition: convert_band.c:366
int32_t rdsensorinfo(int32_t, int32_t, const char *, void **)
Definition: rdsensorinfo.c:69
int read_targethdr(filehandle *file)
Definition: target_io.c:46
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int32_t lonlat2bin(l3binstr *l3bin, float lon, float lat)
Definition: target_io.c:176