OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l1_czcs_hdf.c
Go to the documentation of this file.
1 /*
2  * W. Robinson, SAIC, 10 Dec 2004 I/O routines for CZCS
3  */
4 #include "l1.h"
5 #include <hdf4utils.h>
6 #include "mfhdf.h"
7 #include "l1_czcs_hdf.h"
8 #include <math.h>
9 #include <libnav.h>
10 
11 #define NREC_IN_BUF 1
12 #define NBND_CZCS 5
13 #define POS_ERR_THRESH 2000. /* orbit position error tolerence */
14 
15 int syear, sday; /* data start date */
16 int32 smsec; /* data start time */
17 int16 eyear, eday; /* data end date */
18 int32 emsec; /* data end time */
19 int32 nscan; /* number of scans */
20 int32 npix; /* number pixels per scan */
21 int32 spix; /* start pixel number (from 0) */
22 int32 dpix; /* LAC pixel increment */
23 int32 epix;
24 
25 char dtype[8];
26 
27 int32 nsta;
28 int32 ninc;
29 
31 int32 *msec;
34 float32 *tilt, *att_ang, *slope, *intercept;
38 float *lt750; /* internal 750 mn data source */
39 char *ring_sat; /* set to 1 if 443, 520 or 550 are saturated for ringing
40  mask computation */
41 
42 int czcs_ring(int gain, float *lt750, char *ring_sat, l1str *l1rec)
43 /*******************************************************************
44 
45  czcs_ring
46 
47  purpose: use the Mueller ringing flagging algorithm to set the stray
48  light mask for CZCS
49 
50  Returns type: int - 0 if OK
51 
52  Parameters: (in calling order)
53  Type Name I/O Description
54  ---- ---- --- -----------
55  int gain I gain for the line of data
56  float * lt750 I 750 nm total rads
57  char * ring_sat I 1 if bands 1,2,or 3 are
58  saturated = use the 750
59  excess rad in this case
60  l1str * l1rec I/O L1 struc including tot rads,
61  flags
62 
63  Modification history:
64  Programmer Date Description of change
65  ---------- ---- ---------------------
66  W. Robinson 31 May 2005 Original development
67  W. Robinson 31 Jul 2007 repaired problem that occurs in SGIs
68  if bsum = 0, avoid log and set ring
69  distance to 0
70 
71  Based on the algorithm of Mueller, J. L., Nimbus-7 CZCS: electronic
72  overshoot due to cloud reflectance, Appl. Optics, Vol 27, No 3, 1 Feb,
73  1988, pp 438 - 440
74  Modified to only include the excess radiance in 750 for pixels where
75  bands 1, 2, or 3 have saturated. This is to reduce the masking from
76  coastal areas where the vis is not as bright as for cloud
77 
78  *******************************************************************/ {
79  static float gtrans[4] = {1.0, 1.25, 1.5, 2.1};
80  /* note that the values below have +- of 9.7 and 3.3 in paper */
81  /* standard values followed by low, high confidence values
82  static float mueller_int = 3.9, mueller_slp = 30.8;
83  static float mueller_int = -6.2, mueller_slp = 27.5;
84  static float mueller_int = 13.6, mueller_slp = 34.1;
85  */
86  static float mueller_int = 3.9, mueller_slp = 30.8;
87 
88  static float l0_750 = 2.45;
89 
90  float gfac, lthresh, gfac_ln, excess_brit[1968], bsub, bsum;
91  int i, ipx, btarg, last_btarg, igrp, iavg, pxloc, n_ring;
92  extern int32 npix;
93 
94  /*
95  * set up gfac - gain factor for line, lthresh, brightness threshold
96  * and flags for current and last pixel above threshold radiance
97  */
98  gfac = gtrans[ gain - 1];
99  lthresh = l0_750 / gfac;
100  gfac_ln = log(gfac);
101  btarg = 0;
102  last_btarg = 0;
103 
104  /*
105  * go through pixels and set the mask for pixels downstream of bright target
106  */
107  for (i = 0; i < npix; i++) {
108  if (*(lt750 + i) > lthresh) {
109  btarg = 1;
110  excess_brit[i] =
111  (*(ring_sat + i) == 1) ? *(lt750 + i) - lthresh : 0.;
112  l1rec->stlight[i] = 1;
113  } else
114  excess_brit[i] = 0.;
115 
116  if ((btarg == 0) && (last_btarg == 1)) {
117  /*
118  * sum up excess brightness in 5 groups of 10, weighted by f(dist)
119  */
120  bsum = 0.;
121  for (igrp = 0; igrp < 5; igrp++) {
122  bsub = 0.;
123  for (iavg = 0; iavg < 10; iavg++) {
124  pxloc = i - 1 - (iavg + igrp * 10);
125  if (pxloc >= 0)
126  bsub += excess_brit[ pxloc ];
127  }
128  bsub = bsub / 10.;
129  bsum += bsub * exp(-0.32 * (igrp + 1));
130  }
131  /*
132  * compute # pixels to mask and mark the pixels in that range
133  */
134  bsum = (bsum > 450.) ? 450. : bsum;
135  if (bsum > 0.) {
136  n_ring = mueller_int + mueller_slp * (log(bsum) + gfac_ln);
137  n_ring = (n_ring < 0) ? 0 : n_ring;
138  } else
139  n_ring = 0;
140 
141  for (ipx = 0; ipx < n_ring; ipx++) {
142  pxloc = ipx + i;
143  if (pxloc < npix)
144  l1rec->stlight[pxloc] = 1;
145  }
146  }
147  /*
148  * lastly, reset to go to next pixel
149  */
150  last_btarg = btarg;
151  btarg = 0;
152  }
153  return 0;
154 }
155 
156 #define NBND 4
157 #define NGAIN 4
158 #define NEPOCH 5
159 
160 int get_czcscal(char *file, int orbit, int16 year, int16 day, int32 msec, short l1acnt[], float slope750, float intercept750, int16 igain, float32 l1brads[])
161 /******************************************************************
162 
163  get_czcscal
164  purpose: replicate the Evans & Gordon calibration
165 
166  Modification history:
167  Programmer Date Description of change
168  ---------- ---- ---------------------
169  Sean Bailey 08 Feb 2006 Original development
170 
171  Based on the original czcscaleg.f
172  Modified to use cal_czcs.hdf
173 
174  *******************************************************************/ {
175  static int firstCall = 1;
176  static float slope_coeff[NGAIN][NBND_CZCS];
177  static float offsets[NGAIN][NBND_CZCS];
178  static float rk[NGAIN][NBND_CZCS];
179  static float tdecay[NEPOCH][NBND_CZCS];
180  static int orbitepoch[NEPOCH];
181  static float timeconst[2];
182  static float time_dep[NBND_CZCS][NGAIN][3];
183 
184  int epochidx = 0;
185  int i, j, iorbit;
186  float rden, rnum;
187  float tcorr, slp, S;
188  static int orbepoch670 = 6750;
189  float g[NBND];
190  float64 jsec = yds2unix(year, day, ((double) (msec)) / 1000.0);
191  float64 refjsec = yds2unix(1978, 278, (double) 0.0);
192  float64 decayday = (jsec - refjsec) / 86400.;
193 
194  igain -= 1;
195 
196  if (firstCall) {
197  char name [H4_MAX_NC_NAME] = "";
198  char sdsname[H4_MAX_NC_NAME] = "";
199  int32 sd_id;
200  int32 sds_id;
201  int32 rank;
202  int32 nt;
203  int32 dims[H4_MAX_VAR_DIMS];
204  int32 nattrs;
205  int32 start[3] = {0, 0, 0};
206  int32 status;
207  /* get the current calibration */
208  if (file == NULL) {
209  fprintf(stderr,
210  "-E %s Line %d: No calibration file specified.\n",
211  __FILE__, __LINE__);
212  exit(1);
213  }
214 
215  if (want_verbose)
216  printf("Loading caltable: %s\n", file);
217  /* Open the file */
218  sd_id = SDstart(file, DFACC_RDONLY);
219  if (sd_id == FAIL) {
220  fprintf(stderr, "-E- %s line %d: SDstart(%s, %d) failed.\n",
221  __FILE__, __LINE__, file, DFACC_RDONLY);
222  exit(1);
223  }
224 
225  strcpy(sdsname, "slope_coeff");
226  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
227  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
228  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) slope_coeff);
229  if (status != 0) {
230  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
231  __FILE__, __LINE__, sdsname, file);
232  exit(1);
233  } else {
234  status = SDendaccess(sds_id);
235  }
236 
237  strcpy(sdsname, "offsets");
238  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
239  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
240  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) offsets);
241  if (status != 0) {
242  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
243  __FILE__, __LINE__, sdsname, file);
244  exit(1);
245  } else {
246  status = SDendaccess(sds_id);
247  }
248 
249  strcpy(sdsname, "rk");
250  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
251  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
252  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) rk);
253  if (status != 0) {
254  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
255  __FILE__, __LINE__, sdsname, file);
256  exit(1);
257  } else {
258  status = SDendaccess(sds_id);
259  }
260 
261  strcpy(sdsname, "dec");
262  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
263  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
264  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) tdecay);
265  if (status != 0) {
266  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
267  __FILE__, __LINE__, sdsname, file);
268  exit(1);
269  } else {
270  status = SDendaccess(sds_id);
271  }
272 
273  strcpy(sdsname, "iorbdec");
274  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
275  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
276  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) orbitepoch);
277  if (status != 0) {
278  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
279  __FILE__, __LINE__, sdsname, file);
280  exit(1);
281  } else {
282  status = SDendaccess(sds_id);
283  }
284 
285  strcpy(sdsname, "timeconst");
286  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
287  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
288  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) timeconst);
289  if (status != 0) {
290  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
291  __FILE__, __LINE__, sdsname, file);
292  exit(1);
293  } else {
294  status = SDendaccess(sds_id);
295  }
296 
297  strcpy(sdsname, "time_dep");
298  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
299  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
300  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) time_dep);
301  if (status != 0) {
302  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
303  __FILE__, __LINE__, sdsname, file);
304  exit(1);
305  } else {
306  status = SDendaccess(sds_id);
307  }
308  /* terminate access to the SD interface and close the file */
309  status = SDend(sd_id);
310 
311  firstCall = 0;
312  }
313 
314  iorbit = MIN(orbit, 39000);
315  for (j = 0; j < NEPOCH - 1; j++) {
316  if ((iorbit >= orbitepoch[j]) && (iorbit <= orbitepoch[j + 1]))
317  epochidx = j;
318  }
319 
320  rden = (float) orbitepoch[epochidx + 1] - (float) orbitepoch[epochidx];
321 
322  for (i = 0; i < NBND; i++) {
323  /* Calculate time dependent correction... */
324  /* double exp
325  tcorr = time_dep[i][igain][0] - time_dep[i][igain][1] * (1.0 - exp(timeconst[0]*decayday)) - time_dep[i][igain][2] *(1.0 - exp(timeconst[1]*decayday));
326  */
327  /* single exp */
328  tcorr = time_dep[i][igain][0] - time_dep[i][igain][1] * (1.0 - exp(-1 * time_dep[i][igain][2] * decayday));
329 
330  rnum = tdecay[epochidx + 1][i] - tdecay[epochidx][i];
331  slp = rnum / rden;
332 
333  /* Antione modification for 670nm */
334  if (i == 3 && iorbit > orbepoch670) {
335  rden = (float) orbitepoch[4] - (float) orbepoch670;
336  rnum = tdecay[4][i] - tdecay[3][i];
337  slp = rnum / rden;
338  S = (float) iorbit - (float) orbepoch670;
339  g[i] = 1.0 / (S * slp + tdecay[3][i]);
340 
341  } else {
342  S = (float) iorbit - (float) orbitepoch[epochidx];
343  g[i] = 1.0 / (S * slp + tdecay[epochidx][i]);
344  }
345  /*fprintf(stderr,"i: %d g: %8.6f tcorr: %8.6f\n",i,g[i],tcorr);*/
346 
347  l1brads[i] = (tcorr * g[i] * rk[igain][i] * slope_coeff[igain][i] * (float) l1acnt[i]) + offsets[igain][i];
348 
349  }
350 
351  l1brads[4] = slope750 * (float) l1acnt[4] + intercept750;
352 
353  return 0;
354 }
355 
356 /*
357  W. Robinson, SAIC, 6 Jan 2006 add code to read the position and
358  position error SDSes
359  */
360 
361 int openl1_czcs(filehandle *file) {
362 
363  /* */
364  /* get_l1a_open interface */
365  /* */
366  int32 fileID;
367  int32 status;
368  int16 sy, sd;
369  int i;
370 
371  /* open the file and get the file ID */
372  fileID = SDstart(file->name, DFACC_RDONLY);
373 
374  if (fileID < 0) {
375  fprintf(stderr,
376  "-E %s Line %d: Error opening %s for reading.\n",
377  __FILE__, __LINE__, file->name);
378  return (1);
379  }
380  status = getHDFattr(fileID, "Start Year", "", (VOIDP) & sy);
381  syear = (int32) sy;
382  status = getHDFattr(fileID, "Start Day", "", (VOIDP) & sd);
383  sday = (int32) sd;
384  status = getHDFattr(fileID, "Start Millisec", "", (VOIDP) & smsec);
385  status = getHDFattr(fileID, "End Year", "", (VOIDP) & eyear);
386  status = getHDFattr(fileID, "End Day", "", (VOIDP) & eday);
387  status = getHDFattr(fileID, "End Millisec", "", (VOIDP) & emsec);
388  status = getHDFattr(fileID, "Number of Scan Lines", "", (VOIDP) & nscan);
389  status = getHDFattr(fileID, "Data Type", "", (VOIDP) & dtype);
390 
391  status = getHDFattr(fileID, "Pixels per Scan Line", "", (VOIDP) & npix);
392  status = getHDFattr(fileID, "LAC Pixel Start Number", "", (VOIDP) & nsta);
393  status = getHDFattr(fileID, "LAC Pixel Subsampling", "", (VOIDP) & ninc);
394 
395  status = getHDFattr(fileID, "Orbit Number", "", (VOIDP) & file->orbit_number);
396  /* WDR not in czcs l1 file, so comment for now
397  status = getHDFattr(fileID, "Orbit Node Longitude", "",
398  (VOIDP)&file->orbit_node_lon);
399  status = getHDFattr(fileID, "Node Crossing Time", "",
400  (VOIDP)&file->node_crossing_time[0]);
401  */
402  status = getHDFattr(fileID, "Number of Pixel Control Points", "",
403  (VOIDP) & nctl_pt);
404  status = getHDFattr(fileID, "Parameter Presence Code", "",
405  (VOIDP) & cz_band_present);
406 
407  /* call cdata.f to initialize global FORTRAN common block data */
408  cdata_();
409 
410 
411  file->npix = npix;
412  file->nscan = nscan;
413  file->sensorID = CZCS;
414  file->sd_id = fileID;
415  strcpy(file->spatialResolution, "825 m");
416 
417  msec = (int32 *) calloc(nscan, sizeof (int32));
418  status = rdSDS(file->sd_id, "msec", 0, 0, 0, 0, (VOIDP) msec);
419 
420  att_ang = (float32 *) calloc(nscan * 3, sizeof ( float32));
421  status = rdSDS(file->sd_id, "att_ang", 0, 0, 0, 0, (VOIDP) att_ang);
422 
423  ctl_pt_cols = (int32 *) calloc(nctl_pt, sizeof ( int32));
424  status = rdSDS(file->sd_id, "cntl_pt_cols", 0, 0, 0, 0,
425  (VOIDP) ctl_pt_cols);
426  ctl_pt_x = (float *) calloc(nctl_pt, sizeof ( float));
427  for (i = 0; i < nctl_pt; i++)
428  ctl_pt_x[i] = (float) ctl_pt_cols[i] - 1.;
429 
430  tilt = (float32 *) calloc(nscan, sizeof (float32));
431  status = rdSDS(file->sd_id, "tilt", 0, 0, 0, 0, (VOIDP) tilt);
432 
433  slope = (float32 *) calloc(nscan * 6, sizeof (float32));
434  status = rdSDS(file->sd_id, "slope", 0, 0, 0, 0, (VOIDP) slope);
435  intercept = (float32 *) calloc(nscan * 6, sizeof (float32));
436  status = rdSDS(file->sd_id, "intercept", 0, 0, 0, 0, (VOIDP) intercept);
437  /* get nav orbit data */
438  pos = (float32 *) malloc(nscan * 3 * sizeof (float32));
439  status = rdSDS(file->sd_id, "orb_vec", 0, 0, 0, 0, (VOIDP) pos);
440  pos_err = (float32 *) malloc(nscan * sizeof (float32));
441  status = rdSDS(file->sd_id, "pos_err", 0, 0, 0, 0, (VOIDP) pos_err);
442 
443  gain = (int16 *) malloc(nscan * sizeof ( int16));
444  counts = (uint8 *) malloc(npix * NBND_CZCS * sizeof ( uint8));
445  ctl_pt_lat = (float32 *) malloc(nctl_pt * sizeof ( float32));
446  ctl_pt_lon = (float32 *) malloc(nctl_pt * sizeof ( float32));
447  ctl_pt_vx = (float32 *) malloc(nctl_pt * sizeof ( float32));
448  ctl_pt_vy = (float32 *) malloc(nctl_pt * sizeof ( float32));
449  ctl_pt_vz = (float32 *) malloc(nctl_pt * sizeof ( float32));
450  y2_vx = (float32 *) malloc(npix * sizeof ( float32));
451  y2_vy = (float32 *) malloc(npix * sizeof ( float32));
452  y2_vz = (float32 *) malloc(npix * sizeof ( float32));
453  lt750 = (float *) malloc(npix * sizeof ( float));
454  ring_sat = (char *) malloc(npix * sizeof ( char));
455 
456  spix = nsta - 1;
457  dpix = ninc;
458  epix = spix + npix * dpix;
459 
460 
461  return (status);
462 }
463 
464 /*
465  W. Robinson 31 May 2005 add ringing masking call
466  W. Robinson, SAIC, 6 Jan 2005 add code to compute sat angles with
467  cz_posll_2_satang if pos_err is acceptable
468  J. Gales 23 Sep 2005 add kludge for subsetted pixel range in
469  satang
470  (note that satang may not give proper values in pixel subsets with this
471  but it may be academic with...)
472  W. Robinson, SAIC, 10 Sep 2010 use vectors instead of lat, lon when
473  doing interpolation of ctl pt lat, lon to
474  all samples
475  */
476 
477 int readl1_czcs(filehandle *file, int32_t recnum, l1str *l1rec) {
478  /*void czcscal_( int *, float[], float[], short *, int *, float * );*/
479  void satang_(double *, double *, float *, float *, float *, float *,
480  float *, float *, float *, float *);
481  void sunangs_(int *, int *, float *, float *, float *, float *, float *);
482  int ll2vec(float *, float *);
483  int vec2ll(float *, float *);
484  short cnt_vec[NBND_CZCS];
485  float lt_lcl[NBND_CZCS], yout1, yout2, yout3, llvec[2], vec[3], gmt;
486  int ipx, ibnd, orbit, i, tpix;
487  uint8 cal_sum[5], cal_scan[6];
488  int32 status, navbad, ltsat;
489  double pi, radeg;
490  int32_t ib;
491 
492  int32_t nwave = l1rec->l1file->nbands;
493  int32_t *bindx = l1rec->l1file->bindx;
494  char *cal_path = l1_input->calfile;
495  /* load scan times */
496  /* int year = *l1rec->year;
497  int day = *l1rec->day;*/
498  /* int32 msec = l1rec->msec[recnum];*/
499 
500  float lonbuf[1968], latbuf[1968], senzbuf[1968], senabuf[1968];
501 
502  /*
503  * read in the line of counts, latitude, longitude
504  */
505  status = rdSDS(file->sd_id, "band1", recnum, 0, 1, npix, (VOIDP) counts);
506  status = rdSDS(file->sd_id, "band2", recnum, 0, 1, npix,
507  (VOIDP) (counts + npix));
508  status = rdSDS(file->sd_id, "band3", recnum, 0, 1, npix,
509  (VOIDP) (counts + 2 * npix));
510  status = rdSDS(file->sd_id, "band4", recnum, 0, 1, npix,
511  (VOIDP) (counts + 3 * npix));
512  status = rdSDS(file->sd_id, "band5", recnum, 0, 1, npix,
513  (VOIDP) (counts + 4 * npix));
514 
515  status = rdSDS(file->sd_id, "gain", recnum, 0, 1, 1, (VOIDP) gain);
516  status = rdSDS(file->sd_id, "latitude", recnum, 0, 1, nctl_pt,
517  (VOIDP) ctl_pt_lat);
518  status = rdSDS(file->sd_id, "longitude", recnum, 0, 1, nctl_pt,
519  (VOIDP) ctl_pt_lon);
520 
521  status = rdSDS(file->sd_id, "cal_sum", recnum, 0, 1, 5, (VOIDP) cal_sum);
522  status = rdSDS(file->sd_id, "cal_scan", recnum, 0, 1, 6, (VOIDP) cal_scan);
523  /*
524  * flag setting for entire line: set navfail if cal_sum shows problems
525  * (suspect it is * bad ephemeris or atitude) and set hilt if bands
526  * missing
527  */
528  ltsat = 0;
529  navbad = 0;
530  if ((cz_band_present & 0XF8) != 0XF8)
531  ltsat = 1;
532  else {
533  if ((cal_sum[3] != 0) || (cal_sum[4] != 0))
534  navbad = 1;
535  if ((cal_scan[0] != 0) || (cal_scan[1] != 0) ||
536  (cal_scan[2] != 0) || (cal_scan[3] != 0) ||
537  (cal_scan[4] != 0)) {
538  ltsat = 1;
539  navbad = 1;
540  }
541  }
542  /*
543  * calibrate the radiances and set flags for pixels
544  */
545  for (ipx = 0; ipx < npix; ipx++) {
546  for (ibnd = 0; ibnd < NBND_CZCS; ibnd++) {
547  cnt_vec[ibnd] = *(counts + ipx + ibnd * npix);
548  if ((cnt_vec[ibnd] == 255) || (ltsat == 1)) l1rec->hilt[ipx] = 1;
549  }
550  *(ring_sat + ipx) = ((cnt_vec[0] == 255) || (cnt_vec[1] == 255)
551  || (cnt_vec[2] == 255)) ? 1 : 0;
552  /*
553  * call the fortran calibration routine
554  */
555  orbit = (int) file->orbit_number;
556  /*czcscal_( &orbit, slope + recnum * 6,
557  intercept + recnum * 6, cnt_vec, &lgain, lt_lcl );*/
558  status = get_czcscal(cal_path, orbit, syear, sday, msec[recnum],
559  cnt_vec, slope[4], intercept[4], gain[0], lt_lcl);
560  /*
561  * assign the calibrated radiances
562  */
563  for (ibnd = 0; ibnd < nwave; ibnd++) {
564  ib = bindx[ ibnd ];
565  l1rec->Lt[ ipx * nwave + ib ] = lt_lcl[ibnd];
566  }
567  /*
568  * save the 750 nm data here
569  */
570  *(lt750 + ipx) = lt_lcl[4];
571 
572  if (navbad == 1) l1rec->navfail[ipx] = 1;
573  }
574  /*
575  * set the ringing mask
576  */
578  /*
579  * get navigation at all points from control point lat and lon values
580  * use spline interpolation to fill in, do in vector space to avoid date
581  * line discontinuity
582  */
583  for (i = 0; i < nctl_pt; i++) {
584  llvec[0] = ctl_pt_lat[i];
585  llvec[1] = ctl_pt_lon[i];
586  if (ll2vec(llvec, vec) == 0) {
587  ctl_pt_vx[i] = *vec;
588  ctl_pt_vy[i] = *(vec + 1);
589  ctl_pt_vz[i] = *(vec + 2);
590  } else {
591  fprintf(stderr, "-E %s Line %d: ll2vec failure.\n",
592  __FILE__, __LINE__);
593  exit(1);
594  }
595  }
596  spline(ctl_pt_x, ctl_pt_vx, nctl_pt, 1e30, 1e30, y2_vx);
597  spline(ctl_pt_x, ctl_pt_vy, nctl_pt, 1e30, 1e30, y2_vy);
598  spline(ctl_pt_x, ctl_pt_vz, nctl_pt, 1e30, 1e30, y2_vz);
599  for (i = 0; i < npix; i++) {
600  tpix = i * ninc /*+ spix*/;
601  splint(ctl_pt_x, ctl_pt_vx, y2_vx, nctl_pt, tpix, &yout1);
602  splint(ctl_pt_x, ctl_pt_vy, y2_vy, nctl_pt, tpix, &yout2);
603  splint(ctl_pt_x, ctl_pt_vz, y2_vz, nctl_pt, tpix, &yout3);
604 
605  *vec = yout1;
606  *(vec + 1) = yout2;
607  *(vec + 2) = yout3;
608  vec2ll(vec, llvec);
609 
610  l1rec->lon[i] = llvec[1];
611  l1rec->lat[i] = llvec[0];
612  }
613  /*
614  * calculate geometry. For sensor angles, use the orbit info if the
615  * position error is available and within error threshold
616  */
617  if ((*(pos_err + recnum) >= 0.) &&
618  (*(pos_err + recnum) < POS_ERR_THRESH)) {
619  cz_posll_2_satang((pos + 3 * recnum), npix, l1rec->lat, l1rec->lon,
620  l1rec->senz, l1rec->sena);
621  } else {
622  pi = PI;
623  radeg = RADEG;
624  for (i = 0; i < 1968; i++) {
625  lonbuf[i] = 0.0;
626  latbuf[i] = 0.0;
627  senzbuf[i] = 0.0;
628  senabuf[i] = 0.0;
629  }
630 
631  for (i = 0; i < npix; i++) {
632  lonbuf[i] = l1rec->lon[i];
633  latbuf[i] = l1rec->lat[i];
634  }
635 
636  satang_(&pi, &radeg, tilt + recnum, att_ang + 3 * recnum + 1,
637  att_ang + 3 * recnum + 2, att_ang + 3 * recnum, lonbuf,
638  latbuf, senzbuf, senabuf);
639 
640  for (i = 0; i < npix; i++) {
641  l1rec->senz[i] = senzbuf[i];
642  l1rec->sena[i] = senabuf[i];
643  }
644  }
645 
646 
647  /* for( i = spix; i < epix; i = i + ninc )*/
648  for (i = 0; i < npix; i++) {
649  gmt = (float) msec[recnum] / (1000. * 3600);
650  sunangs_(&syear, &sday, &gmt, (l1rec->lon) + i, (l1rec->lat) + i,
651  (l1rec->solz) + i, (l1rec->sola) + i);
652  }
653  /*
654  * set scan time
655  */
656  double secs = (double) (msec[recnum] / 1000.0);
657  int16_t year = syear;
658  int16_t day = sday;
659 
660  if (recnum > 0 && msec[recnum] < msec[recnum - 1]) { /* adjust for day rollover */
661  day += 1;
662  if (day > (365 + (year % 4 == 0))) {
663  year += 1;
664  day = 1;
665  }
666  }
667  l1rec->scantime = yds2unix(year, day, secs);
668 
669  return (status);
670 }
671 
672 /* W. Robinson, SAIC, 6 Jan 2005 include the pos, pos_err arrays in free */
673 
674 int closel1_czcs(filehandle *file) {
675  free(msec);
676  free(tilt);
677  free(att_ang);
678  free(counts);
679  free(ctl_pt_lat);
680  free(ctl_pt_lon);
681  free(ctl_pt_vx);
682  free(ctl_pt_vy);
683  free(ctl_pt_vz);
684  free(y2_vx);
685  free(y2_vy);
686  free(y2_vz);
687  free(ctl_pt_x);
688  free(ctl_pt_cols);
689  free(slope);
690  free(intercept);
691  free(lt750);
692  free(ring_sat);
693  free(pos);
694  free(pos_err);
695 
696  SDend(file->sd_id);
697 
698  return (0);
699 }
700 
701 #define re 6378.137
702 #define f 1. / 298.257
703 #define omf2 ( 1 - f ) * ( 1 - f )
704 
705 int cz_posll_2_satang(float *pos, int npix, float *lat, float *lon,
706  float *senz, float *sena)
707 /*******************************************************************
708 
709  cz_posll_2_satang
710 
711  purpose: convert satellite position, lat, lon into satellite zenith
712  and azimuth for a line of czcs data
713 
714  Returns type: int - 0 if no problems
715 
716  Parameters: (in calling order)
717  Type Name I/O Description
718  ---- ---- --- -----------
719  float * pos I position (x, y, z) of
720  satellite in meters
721  int npix I # pixels of lat, lon to find
722  sat angles for
723  float * lat I latitude array in degrees E
724  float * lon I longitude array in degrees E
725  float * senz O sensor zenith in degrees
726  float * sena O sensor azimuth in degrees
727 
728  Modification history:
729  Programmer Date Description of change
730  ---------- ---- ---------------------
731  W. Robinson, SAIC 5-Jan-2006 Original development
732 
733  *******************************************************************/ {
734  double up[3], ea[3], no[3], radeg, upxy, xlmat[3][3], xlatg, gv[3];
735  double r, rh[3], rl[3];
736  int i, j;
737 
738  radeg = 90. / asin(1.);
739 
740  for (i = 0; i < npix; i++) {
741  /*
742  * Compute the local vertical, East and North unit vectors
743  */
744  up[0] = cos(*(lat + i) / radeg) * cos(*(lon + i) / radeg);
745  up[1] = cos(*(lat + i) / radeg) * sin(*(lon + i) / radeg);
746  up[2] = sin(*(lat + i) / radeg);
747 
748  upxy = sqrt(up[0] * up[0] + up[1] * up[1]);
749 
750  ea[0] = -up[1] / upxy;
751  ea[1] = up[0] / upxy;
752  ea[2] = 0.;
753 
754  cross_prod(up, ea, no);
755 
756  /*
757  * Store vectors in 3x3 array
758  */
759  for (j = 0; j < 3; j++) {
760  xlmat[0][j] = ea[j];
761  xlmat[1][j] = no[j];
762  xlmat[2][j] = up[j];
763  }
764  /*
765  * Compute geocentric position vector
766  */
767  xlatg = radeg * atan(tan(*(lat + i) / radeg) * omf2);
768  gv[0] = cos(xlatg / radeg) * cos(*(lon + i) / radeg);
769  gv[1] = cos(xlatg / radeg) * sin(*(lon + i) / radeg);
770  gv[2] = sin(xlatg / radeg);
771 
772  r = re * (1. - f) /
773  sqrt(1. - (2. - f) * f * pow(cos(xlatg / radeg), 2));
774 
775  /* note that pos is in m but rest of constants are in km, hence the
776  1000 factor */
777  for (j = 0; j < 3; j++)
778  rh[j] = pos[j] / 1000. - r * gv[j];
779  /*
780  * Transform the pixel-to-spacecraft vector into the local frame
781  */
782  matrix_mult(rh, xlmat, rl);
783  /*
784  * Compute the sensor zenith and azimuth
785  * if zenith close to 0, set azimuth to 0 (and normalize azimuth)
786  */
787  *(senz + i) = radeg * atan2(sqrt(rl[0] * rl[0] + rl[1] * rl[1]),
788  rl[2]);
789  if (*(senz + i) > 0.05)
790  *(sena + i) = radeg * atan2(rl[0], rl[1]);
791  else
792  *(sena + i) = 0.;
793 
794  if (*(sena + i) < 0.) *(sena + i) += 360.;
795  }
796  /*
797  * and end
798  */
799  return 0;
800 }
801 
802 void matrix_mult(double vecin[3], double matrix[3][3], double vecout[3])
803 /*******************************************************************
804 
805  matrix_mult
806 
807  purpose: multiply a vector by a matrix and produce the output vector
808 
809  Returns type: void
810 
811  Parameters: (in calling order)
812  Type Name I/O Description
813  ---- ---- --- -----------
814  double[3] vecin I input vector
815  double[3][3] matrix I rotation matrix
816  double[3] vecout O rotated vector
817 
818  Modification history:
819  Programmer Date Description of change
820  ---------- ---- ---------------------
821  W. Robinson, SAIC 2-Nov-2005 Original development
822 
823  *******************************************************************/ {
824  int i, j;
825  for (i = 0; i < 3; i++) {
826  vecout[i] = 0.;
827  for (j = 0; j < 3; j++) {
828  vecout[i] += matrix[i][j] * vecin[j];
829  }
830  }
831 }
832 
833 void cross_prod(double *v1, double *v2, double *vout)
834 /*******************************************************************
835 
836  cross_prod
837 
838  purpose: produce the cross product of 2 vectors
839 
840  Returns type: void
841 
842  Parameters: (in calling order)
843  Type Name I/O Description
844  ---- ---- --- -----------
845  double * v1 I vector 1
846  double * v2 I vector 1
847  double * vout O v1 X v2
848 
849  Modification history:
850  Programmer Date Description of change
851  ---------- ---- ---------------------
852  W. Robinson, SAIC 4-Jan-2006 Original development
853 
854  *******************************************************************/ {
855  *vout = v1[1] * v2[2] - v1[2] * v2[1];
856  *(vout + 1) = v1[2] * v2[0] - v1[0] * v2[2];
857  *(vout + 2) = v1[0] * v2[1] - v1[1] * v2[0];
858 }
integer, parameter int16
Definition: cubeio.f90:3
const int bindx[3]
Definition: DbLutNetcdf.cpp:28
#define MIN(x, y)
Definition: rice.h:169
int r
Definition: decode_rs.h:73
int16 eday
Definition: l1_czcs_hdf.c:17
int czcs_ring(int gain, float *lt750, char *ring_sat, l1str *l1rec)
Definition: l1_czcs_hdf.c:42
int ll2vec(float *ll, float *vec)
Definition: ll2vec.c:6
int j
Definition: decode_rs.h:73
int rdSDS(int32_t fileID, const char sdsname[], int32_t start1, int32_t start2, int32_t edges1, int32_t edges2, void *array_data)
int32_t day
int status
Definition: l1_czcs_hdf.c:32
double yds2unix(int16_t year, int16_t day, double secs)
Definition: yds2unix.c:7
float32 * tilt
Definition: l1_czcs_hdf.c:34
int16 * gain
Definition: l1_czcs_hdf.c:33
*********************************************HISTORY FILE for MOD_PR02AQUA **Version ****Point of no algorithm change is made in this so the and when the blackbody temperature is above a threshold Since the LWIR FPA temperature oscillates on orbit
Definition: HISTORY.txt:106
int16_t fileID
#define FAIL
Definition: ObpgReadGrid.h:18
float * lt750
Definition: l1_czcs_hdf.c:38
#define NULL
Definition: decode_rs.h:63
read l1rec
#define NBND_CZCS
Definition: l1_czcs_hdf.c:12
#define NBND
Definition: l1_czcs_hdf.c:156
const double pi
float32 * ctl_pt_lat
Definition: l1_czcs_hdf.c:35
int32 * ctl_pt_cols
Definition: l1_czcs_hdf.c:36
subroutine spline(s, x, y, n, in, t, il, iu, vl, vu, e, u)
Definition: phs.f:1348
float * ctl_pt_vy
Definition: l1_czcs_hdf.c:37
float32 * intercept
Definition: l1_czcs_hdf.c:34
float32 * pos
Definition: l1_czcs_hdf.c:35
float * lat
int32 * msec
Definition: l1_czcs_hdf.c:31
uint8 * counts
Definition: l1_czcs_hdf.c:30
void cross_prod(double *v1, double *v2, double *vout)
Definition: l1_czcs_hdf.c:833
int16 eyear
Definition: l1_czcs_hdf.c:17
float ** matrix(long nrl, long nrh, long ncl, long nch)
Definition: nrutil.c:60
uint8 cz_band_present
Definition: l1_czcs_hdf.c:30
int syear
Definition: l1_czcs_hdf.c:15
float * ctl_pt_vz
Definition: l1_czcs_hdf.c:37
int32 nscan
Definition: l1_czcs_hdf.c:19
int32 smsec
Definition: l1_czcs_hdf.c:16
int readl1_czcs(filehandle *file, int32_t recnum, l1str *l1rec)
Definition: l1_czcs_hdf.c:477
#define POS_ERR_THRESH
Definition: l1_czcs_hdf.c:13
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
int sday
Definition: l1_czcs_hdf.c:15
#define PI
Definition: l3_get_org.c:6
int32 nsta
Definition: l1_czcs_hdf.c:27
int cz_posll_2_satang(float *pos, int npix, float *lat, float *lon, float *senz, float *sena)
Definition: l1_czcs_hdf.c:705
void sunangs_(int *, int *, float *, float *, float *, float *, float *)
float * y2_vz
Definition: l1_czcs_hdf.c:37
read recnum
float * y2_vx
Definition: l1_czcs_hdf.c:37
int closel1_czcs(filehandle *file)
Definition: l1_czcs_hdf.c:674
int get_czcscal(char *file, int orbit, int16 year, int16 day, int32 msec, short l1acnt[], float slope750, float intercept750, int16 igain, float32 l1brads[])
Definition: l1_czcs_hdf.c:160
void satang_(double *, double *, float *, float *, float *, float *, float *, float *, float *, float *)
#define re
Definition: l1_czcs_hdf.c:701
int32 ninc
Definition: l1_czcs_hdf.c:28
#define NGAIN
Definition: l1_czcs_hdf.c:157
void cdata_()
l1_input_t * l1_input
Definition: l1_options.c:9
int getHDFattr(int32_t fileID, const char attrname[], const char sdsname[], void *data)
int openl1_czcs(filehandle *file)
Definition: l1_czcs_hdf.c:361
int want_verbose
char * ring_sat
Definition: l1_czcs_hdf.c:39
integer, parameter double
int32 nctl_pt
Definition: l1_czcs_hdf.c:36
#define RADEG
Definition: czcs_ctl_pt.c:5
#define NEPOCH
Definition: l1_czcs_hdf.c:158
int vec2ll(float *vec, float *ll)
Definition: ll2vec.c:53
int32 emsec
Definition: l1_czcs_hdf.c:18
#define omf2
Definition: l1_czcs_hdf.c:703
float * ctl_pt_x
Definition: l1_czcs_hdf.c:37
float32 * ctl_pt_lon
Definition: l1_czcs_hdf.c:35
void matrix_mult(double vecin[3], double matrix[3][3], double vecout[3])
Definition: l1_czcs_hdf.c:802
an array had not been initialized Several spelling and grammar corrections were which is read from the appropriate MCF the above metadata values were hard coded A problem calculating the average background DN for SWIR bands when the moon is in the space view port was corrected The new algorithm used to calculate the average background DN for all reflective bands when the moon is in the space view port is now the same as the algorithm employed by the thermal bands For non SWIR changes in the averages are typically less than Also for non SWIR the black body DNs remain a backup in case the SV DNs are not available For SWIR the changes in computed averages were larger because the old which used the black body suffered from contamination by the micron leak As a consequence of the if SV DNs are not available for the SWIR the EV pixels will not be the granule time is used to identify the appropriate tables within the set given for one LUT the first two or last two tables respectively will be used for the interpolation If there is only one LUT in the set of it will be treated as a constant LUT The manner in which Earth View data is checked for saturation was changed Previously the raw Earth View DNs and Space View DNs were checked against the lookup table values contained in the table dn_sat The change made is to check the raw Earth and Space View DNs to be sure they are less than the maximum saturation value and to check the Space View subtracted Earth View dns against a set of values contained in the new lookup table dn_sat_ev The metadata configuration and ASSOCIATEDINSTRUMENTSHORTNAME from the MOD02HKM product The same metatdata with extensions and were removed from the MOD021KM and MOD02OBC products ASSOCIATEDSENSORSHORTNAME was set to MODIS in all products These changes are reflected in new File Specification which users may consult for exact the pow functions were eliminated in Emissive_Cal and Emissive bands replaced by more efficient code Other calculations throughout the code were also made more efficient Aside from a few round off there was no difference to the product The CPU time decreased by about for a day case and for a night case A minor bug in calculating the uncertainty index for emissive bands was corrected The frame the required RAM for each execution is MB on the DEC ALPHA and MB on the SGI Octane v2
Definition: HISTORY.txt:728
int32 dpix
Definition: l1_czcs_hdf.c:22
dtype
Definition: DDataset.hpp:31
int32 spix
Definition: l1_czcs_hdf.c:21
float * y2_vy
Definition: l1_czcs_hdf.c:37
Extra metadata that will be written to the HDF4 file l2prod rank
#define CZCS
Definition: sensorDefs.h:17
subroutine splint(xa, ya, y2a, n, x, y)
float32 * slope
Definition: l1_czcs_hdf.c:34
float * lon
int32 epix
Definition: l1_czcs_hdf.c:23
int lgain
Definition: l1_czcs_hdf.c:32
float32 * pos_err
Definition: l1_czcs_hdf.c:35
#define f
Definition: l1_czcs_hdf.c:702
float32 * att_ang
Definition: l1_czcs_hdf.c:34
int i
Definition: decode_rs.h:71
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int32 npix
Definition: l1_czcs_hdf.c:20
float * ctl_pt_vx
Definition: l1_czcs_hdf.c:37