OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l1_octs_hdf.c
Go to the documentation of this file.
1 /* ====================================================== */
2 /* Module l1_octs_hdf.c */
3 /* */
4 /* Functions to open and read a OCTS HDF l1b file. */
5 /* */
6 /* Written By: */
7 /* JT */
8 /* NASA/SIMBIOS Project */
9 /* 1/99 */
10 /* Modifications By: */
11 /* J. Gales */
12 /* Futuretech */
13 /* NASA/SIMBIOS Project */
14 /* 6/99 */
15 /* */
16 /* 10/00 */
17 /* */
18 /* Add support for OCTS L1A */
19 /* */
20 /* Sean Baiey */
21 /* Futuretech */
22 /* 6/08 */
23 /* Numerous minor mods to get extract processing */
24 /* to work properly */
25 /* ====================================================== */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <hdf4utils.h>
32 #include "l1.h"
33 #include "filehdr_struc.h"
34 #include "l1_octs_hdf.h"
35 
36 #include <hdf.h>
37 #include <mfhdf.h>
38 
39 #define RADIUS 6378.137 /* Earth radius in km */
40 #define FL 1.0/298.257 /* Earth flatening factor */
41 #define NR 560 /* # rows */
42 #define NC 30 /* max # columns */
43 
44 #define MAXOCLIN 6700 /* max # lines */
45 #define MAXOCPIX 2218 /* max # pixels */
46 #define MAXOCARR 10000
47 #define NOCBANDS 8
48 
49 void reform_octs_time(char *time);
50 
51 static int32_t msec_start;
52 static int32_t msec[MAXOCLIN];
53 static float tilt[MAXOCLIN];
54 static int16_t year, day, nline, npix, sline;
55 static int32_t spix;
56 static int16_t maxday;
57 static float solz1, sola1, senz1, sena1;
58 static float *lon, *lat, *senz, *sena, *solz, *sola;
59 static float m[NOCBANDS], b[NOCBANDS];
60 static int ncol;
61 static int32_t scansPerScene;
62 static int32_t linesPerScan;
63 static int16_t *tilt_flag;
64 static int16_t *gain;
65 static float *inst_temp;
66 static int16_t *miss_qual;
67 static int16_t num_tab;
68 static int32_t extr_line_offset = 0;
69 static int16_t *start_scan;
70 static int16_t last_table = 0;
71 static int32_t samp_start[8];
72 static int32_t samp_edges[8];
73 static int16_t sample_table[3][8][2][400][2];
74 
75 
76 /* ========================================================================= */
77 /* */
78 /* Module get_octs_cal.c */
79 /* */
80 /* Functions to open the given calibration HDF file and apply apply to */
81 /* L1A counts, returns TOA radiances. */
82 /* */
83 /* Modification history: */
84 /* */
85 /* Sean Bailey Futuretech Corporation 16 Dec 2005 Original development */
86 /* */
87 /* ========================================================================= */
88 
89 #define NTILT 3
90 #define NDET 10
91 #define NBND 12
92 #define NSEG 2
93 #define NGAIN 4
94 
95 int32_t get_octs_cal(char *file, int16_t year, int16_t day, int32_t msec[MAXOCLIN],
96  int32_t recnum, int16_t npix, int32_t spix, int32_t tilt,
97  int16_t gainset[MAXOCLIN], float inst_temp[MAXOCLIN],
98  int16_t sample_table[3][8][2][400][2], int32_t scansPerScene,
99  uint16_t l1acnts[NOCBANDS][MAXOCPIX], float l1brads[MAXOCPIX][NOCBANDS]) {
100 
101  static float basic_offset [NBND][NDET][NGAIN];
102  static float calib_coeff_gain [NBND][NDET][NGAIN];
103  static float det_norm_slope [NOCBANDS][NDET];
104  static float det_norm_offset [NOCBANDS][NDET];
105  static float L_Border [NOCBANDS][NDET];
106  static float tilt_refl [NBND][NTILT];
107  static float time_dep [NBND][NSEG][3];
108 
109  static float unit_conv = 1.0e-1;
110  static int firstCall = 1;
111  static double refjsec;
112  static int32_t refyear = 1996;
113  static int refday = 306;
114 
115  int16_t subpix;
116  int i, j, idet, iscn, ign, itilt, mside, igscnmod, rdet;
117  float eta, Lt, A, tcorr;
118  double jsec = yds2unix(year, day, ((double) (msec[recnum])) / 1000.0);
119  int segment = 0;
120  if (jsec >= 854769600.)
121  segment = 1;
122 
123  if (firstCall) {
124 
125  char name [H4_MAX_NC_NAME] = "";
126  char sdsname[H4_MAX_NC_NAME] = "";
127  int32_t sd_id;
128  int32_t sds_id;
129  int32_t rank;
130  int32_t nt;
131  int32_t dims[H4_MAX_VAR_DIMS];
132  int32_t nattrs;
133  int32_t start[3] = {0, 0, 0};
134  int32_t status;
135 
136  /* get the current calibration */
137  if (file == NULL) {
138  fprintf(stderr,
139  "-E %s Line %d: No calibration file specified.\n",
140  __FILE__, __LINE__);
141  exit(1);
142  }
143 
144  if (want_verbose)
145  printf("Loading caltable: %s\n", file);
146 
147  /* Open the file */
148  sd_id = SDstart(file, DFACC_RDONLY);
149  if (sd_id == FAIL) {
150  fprintf(stderr, "-E- %s line %d: SDstart(%s, %d) failed.\n",
151  __FILE__, __LINE__, file, DFACC_RDONLY);
152  exit(1);
153  }
154 
155  strcpy(sdsname, "basic_offset");
156  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
157  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
158  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) basic_offset);
159  if (status != 0) {
160  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
161  __FILE__, __LINE__, sdsname, file);
162  exit(1);
163  } else {
164  status = SDendaccess(sds_id);
165  }
166 
167  strcpy(sdsname, "calib_coeff_gain");
168  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
169  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
170  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) calib_coeff_gain);
171  if (status != 0) {
172  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
173  __FILE__, __LINE__, sdsname, file);
174  exit(1);
175  } else {
176  status = SDendaccess(sds_id);
177  }
178 
179  strcpy(sdsname, "det_norm_slope");
180  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
181  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
182  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) det_norm_slope);
183  if (status != 0) {
184  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
185  __FILE__, __LINE__, sdsname, file);
186  exit(1);
187  } else {
188  status = SDendaccess(sds_id);
189  }
190 
191  strcpy(sdsname, "det_norm_offset");
192  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
193  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
194  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) det_norm_offset);
195  if (status != 0) {
196  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
197  __FILE__, __LINE__, sdsname, file);
198  exit(1);
199  } else {
200  status = SDendaccess(sds_id);
201  }
202 
203  strcpy(sdsname, "L_Border");
204  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
205  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
206  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) L_Border);
207  if (status != 0) {
208  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
209  __FILE__, __LINE__, sdsname, file);
210  exit(1);
211  } else {
212  status = SDendaccess(sds_id);
213  }
214 
215  strcpy(sdsname, "tilt_refl");
216  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
217  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
218  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) tilt_refl);
219  if (status != 0) {
220  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
221  __FILE__, __LINE__, sdsname, file);
222  exit(1);
223  } else {
224  status = SDendaccess(sds_id);
225  }
226 
227  strcpy(sdsname, "time_dep");
228  sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
229  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
230 
231  status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) time_dep);
232  if (status != 0) {
233  printf("-E- %s Line %d: Error reading SDS %s from %s.\n",
234  __FILE__, __LINE__, sdsname, file);
235  exit(1);
236  } else {
237  status = SDendaccess(sds_id);
238  }
239 
240  /* terminate access to the SD interface and close the file */
241  status = SDend(sd_id);
242  refjsec = yds2unix(refyear, refday, (double) 0.0);
243 
244  firstCall = 0;
245  }
246 
247  /* Apply the appropriate coefficients */
248 
249  /* Tilt index for reflectance correction */
250  itilt = 1;
251  if (tilt < -10) itilt = 0;
252  if (tilt > 10) itilt = 2;
253 
254  for (j = 0; j < npix; j++) {
255  subpix = spix + j;
256  for (i = 0; i < NOCBANDS; i++) {
257 
258  iscn = recnum / 2;
259  mside = recnum % 2;
260  //rdet = sample_table[0][itilt][i][mside][j][1];
261  rdet = sample_table[itilt][i][mside][subpix][1];
262  idet = (rdet + 200) % 10;
263  igscnmod = 1;
264 
265  /* account for detectors from previous or following scan (or two) */
266  if (rdet < -9) igscnmod -= 2;
267  if (rdet >= -9 && rdet < 0) igscnmod -= 1;
268  if (rdet >= 10 && rdet < 20) igscnmod += 1;
269  if (rdet >= 20) igscnmod += 2;
270 
271  if (idet < 0.) idet += 9;
272  if (idet < 0 || idet > 9) {
273  printf("-W- idet %d outside bounds [0,9]\n", idet);
274  }
275 
276  if (iscn < 0 || iscn > scansPerScene - 1) {
277  printf("-W- iscn %d outside bounds [0,%d]\n", iscn, scansPerScene);
278  l1brads[j][i] = 0.0;
279  } else if (l1acnts[i][j] == 0) {
280  l1brads[j][i] = 0.0;
281  } else if (inst_temp[iscn] > 30) {
282  printf("inst_temp: %8.5f\n", inst_temp[iscn]);
283  l1brads[j][i] = 0.0;
284  } else if (iscn + igscnmod < 0 || iscn + igscnmod > scansPerScene - 1) {
285  // Some of the detectors are out of range
286  l1brads[j][i] = 0.0;
287  } else {
288  ign = gainset[iscn + igscnmod];
289  eta = tilt_refl[i][itilt];
290 
291  Lt = unit_conv * (l1acnts[i][j] - basic_offset[i][idet][ign]) /
292  calib_coeff_gain[i][4][ign];
293 
294  if (Lt <= L_Border[i][idet]) {
295  A = det_norm_slope[i][idet] * Lt + det_norm_offset[i][idet];
296  } else {
297  A = det_norm_slope[i][idet] * L_Border[i][idet] +
298  det_norm_offset[i][idet];
299  }
300 
301  /* Calculate time dependent correction... */
302  tcorr = time_dep[i][segment][1]*(jsec - refjsec) + time_dep[i][segment][0];
303  l1brads[j][i] = (A * Lt / eta) * tcorr;
304  }
305 
306  } /* end i */
307 
308  } /* end j */
309 
310  return 0;
311 }
312 
313 
314 /* ------------------------------------------------------ */
315 /* openl1_read_octs_hdf() - opens a OCTS HDF level-1 file */
316 /* for reading, if not already opened. */
317 /* Reads the global attributes. */
318 /* Calculates the subscene info, if */
319 /* necessary, ane gets the navigation */
320 /* info. */
321 /* */
322 /* CALLS: getHDFattr() */
323 /* navigation() */
324 /* rdSDS() */
325 /* */
326 
327 /* ------------------------------------------------------ */
328 int openl1_read_octs_hdf(filehandle *l1file) {
329  int i, j;
330  int32_t status;
331  int32_t pixPerScan;
332  int32_t linesPerScene;
333  int32_t msec_temp1[MAXOCARR], msec_temp2[MAXOCARR];
334  char buf[32];
335  int32_t fileID;
336  int32_t sds_index, sds_id;
337  int32_t dims[H4_MAX_VAR_DIMS];
338 
339  /* open the file and get the file ID */
340  fileID = SDstart(l1file->name, DFACC_RDONLY);
341 
342  /* get attributes pertaining to the full scene */
343  status = getHDFattr(fileID, "Start Year", "", (VOIDP) & year);
344  status = getHDFattr(fileID, "Start Day", "", (VOIDP) & day);
345  status = getHDFattr(fileID, "Number of Scan Lines", "", (VOIDP) & scansPerScene);
346  status = getHDFattr(fileID, "Pixels per Scan Line", "", (VOIDP) & pixPerScan);
347  status = getHDFattr(fileID, "Lines per Scan", "", (VOIDP) & linesPerScan);
348  status = getHDFattr(fileID, "Orbit Node Longitude", "", (VOIDP) & l1file->orbit_node_lon);
349  status = getHDFattr(fileID, "Orbit Number", "", (VOIDP) & l1file->orbit_number);
350  status = getHDFattr(fileID, "Node Crossing Time", "", (VOIDP) & buf);
351  reform_octs_time(buf);
352  l1file->node_crossing_time = zulu2unix(buf);
353 
354 
355  if (getDims(fileID, "pxl", dims) != 0) {
356  printf("-E- %s: Error reading control-point column dimension.\n",
357  "__FILE__");
358  exit(FATAL_ERROR);
359  }
360  ncol = dims[0];
361 
362 
363  linesPerScene = scansPerScene * linesPerScan;
364 
365  /* Reformat OCTS Times */
366  // reform_octs_time(l1file->node_crossing_time);
367 
368  /* Adjust spix if this is an extract file from l1extract */
369  /* 19 May 2008, BAF */
370  status = getHDFattr(fileID, "Extract Pixel Offset", "", (VOIDP) & spix);
371  if (status != -1) {
372  status = getHDFattr(fileID, "Extract Line Offset", "", (VOIDP) & extr_line_offset);
373  printf("File is Level-1A extract starting on line %d.\n", extr_line_offset + 1);
374  } else {
375  extr_line_offset = 0;
376  spix = 0;
377  }
378  sline = 0;
379  nline = linesPerScene;
380  npix = pixPerScan;
381 
382 
383  /* Check that number of scene lines not greater than allocation */
384  if (nline > MAXOCLIN) {
385  printf("-E- %s: Number of scene lines: %d, greater than array allocation: %d.\n",
386  "openl1_read_octs_hdf", nline, MAXOCLIN);
387  status = SDend(fileID);
388  exit(FATAL_ERROR);
389  }
390 
391 
392  /* Check that number of pixels per scan not greater than allocation */
393  if (npix > MAXOCPIX) {
394  printf("-E- %s: Number of scan pixels: %d, greater than array allocation: %d.\n",
395  "openl1_read_octs_hdf", npix, MAXOCPIX);
396  status = SDend(fileID);
397  exit(FATAL_ERROR);
398  }
399 
400 
401  lon = (float *) calloc(npix*nline, sizeof (float));
402  lat = (float *) calloc(npix*nline, sizeof (float));
403  senz = (float *) calloc(npix*nline, sizeof (float));
404  sena = (float *) calloc(npix*nline, sizeof (float));
405  solz = (float *) calloc(npix*nline, sizeof (float));
406  sola = (float *) calloc(npix*nline, sizeof (float));
407 
408  l1file->npix = npix;
409  l1file->nscan = nline;
410  l1file->sd_id = fileID;
411  strcpy(l1file->spatialResolution, "3.5 km");
412 
413  /* compute and store the view angles for the scene
414  or subscene */
416 
417  /* get the time for each line of full scene */
418  status = rdSDS(fileID, "msec", 0, 0, 0, 0, (VOIDP) & msec_temp1);
419 
420  for (i = 0; i < scansPerScene; i++) {
421  for (j = 0; j < linesPerScan; j++) {
422  msec_temp2[i * linesPerScan + j] = msec_temp1[i];
423  }
424  }
425  msec_start = msec_temp2[0];
426  j = 0;
427  for (i = sline; i < (sline + nline); i++) {
428  msec[j] = msec_temp2[i];
429  j++;
430  }
431 
432  /* get the tilt for each line of full scene */
433  status = rdSDS(fileID, "tilt", 0, 0, 0, 0, (VOIDP) & tilt);
434 
435  maxday = 365 + abs(LeapCheck(year));
436 
437  /* get image data scaling parameters (y=mx+b) */
438  if (l1file->format == FT_OCTSL1B) {
439  status = getHDFattr(fileID, "slope", "l1b_b1_data", (VOIDP) & m[0]);
440  status = getHDFattr(fileID, "slope", "l1b_b2_data", (VOIDP) & m[1]);
441  status = getHDFattr(fileID, "slope", "l1b_b3_data", (VOIDP) & m[2]);
442  status = getHDFattr(fileID, "slope", "l1b_b4_data", (VOIDP) & m[3]);
443  status = getHDFattr(fileID, "slope", "l1b_b5_data", (VOIDP) & m[4]);
444  status = getHDFattr(fileID, "slope", "l1b_b6_data", (VOIDP) & m[5]);
445  status = getHDFattr(fileID, "slope", "l1b_b7_data", (VOIDP) & m[6]);
446  status = getHDFattr(fileID, "slope", "l1b_b8_data", (VOIDP) & m[7]);
447  status = getHDFattr(fileID, "intercept", "l1b_b1_data", (VOIDP) & b[0]);
448  status = getHDFattr(fileID, "intercept", "l1b_b2_data", (VOIDP) & b[1]);
449  status = getHDFattr(fileID, "intercept", "l1b_b3_data", (VOIDP) & b[2]);
450  status = getHDFattr(fileID, "intercept", "l1b_b4_data", (VOIDP) & b[3]);
451  status = getHDFattr(fileID, "intercept", "l1b_b5_data", (VOIDP) & b[4]);
452  status = getHDFattr(fileID, "intercept", "l1b_b6_data", (VOIDP) & b[5]);
453  status = getHDFattr(fileID, "intercept", "l1b_b7_data", (VOIDP) & b[6]);
454  status = getHDFattr(fileID, "intercept", "l1b_b8_data", (VOIDP) & b[7]);
455  }
456 
457 
458  /* L1A GAC Processing */
459  if (l1file->format == FT_OCTSL1A) {
460 
461  /* Get tilt flag, instrument temperature, and gain index */
462  tilt_flag = (int16_t *) calloc(scansPerScene, sizeof (int16_t));
463  status = rdSDS(fileID, "tilt_flag", 0, 0, 0, 0, (VOIDP) & tilt_flag[0]);
464  inst_temp = (float *) calloc(4 * scansPerScene, sizeof (float));
465  status = rdSDS(fileID, "inst_temp", 0, 0, 0, 0, (VOIDP) & inst_temp[0]);
466  gain = (int16_t *) calloc(8 * scansPerScene, sizeof (int16_t));
467  status = rdSDS(fileID, "gain", 0, 0, 0, 0, (VOIDP) & gain[0]);
468  miss_qual = (int16_t *) calloc(scansPerScene, sizeof (int16_t));
469  status = rdSDS(fileID, "miss_qual", 0, 0, 0, 0, (VOIDP) & miss_qual[0]);
470 
471  /* Read GAC subsampling table */
472  status = rdSDS(fileID, "num_tables", 0, 0, 1, 1, (VOIDP) & num_tab);
473  start_scan = (int16_t *) calloc(num_tab, sizeof (int16_t));
474  status = rdSDS(fileID, "start_line", 0, 0, 0, 0, (VOIDP) & start_scan[0]);
475 
476  for (i = 0; i < num_tab; i++) {
477  if ((extr_line_offset + sline) / linesPerScan < start_scan[i]) {
478  last_table = i - 1;
479  break;
480  }
481  }
482 
483  samp_start[0] = last_table;
484  samp_edges[0] = 1;
485  samp_start[1] = 0;
486  samp_edges[1] = 3;
487  samp_start[2] = 0;
488  samp_edges[2] = 8;
489  samp_start[3] = 0;
490  samp_edges[3] = 2;
491  samp_start[4] = 0;
492  samp_edges[4] = 400;
493  samp_start[5] = 0;
494  samp_edges[5] = 2;
495 
496  sds_index = SDnametoindex(fileID, "samp_table");
497  sds_id = SDselect(fileID, sds_index);
498 
499  status = SDreaddata(sds_id, samp_start, NULL, samp_edges, (VOIDP) sample_table);
500  }
501 
502  return (0);
503 }
504 
505 /* ------------------------------------------------------ */
506 /* readl1_octs_hdf() - reads a OCTS HDF level-1 record. */
507 /* */
508 
509 /* ------------------------------------------------------ */
510 int readl1_octs_hdf(filehandle *l1file, int32_t recnum, l1str *l1rec) {
511  int i, j, status;
512  uint16_t dataarr[NOCBANDS][MAXOCPIX];
513  float scanarr[MAXOCPIX][NOCBANDS];
514  int32_t fileID;
515  int32_t start[8], edges[8];
516  int32_t sds_index, sds_id;
517  int32_t tilt_deg;
518  int32_t scan;
519  int32_t ip, ib, iw;
520  int32_t nwave = l1rec->l1file->nbands;
521  int32_t *bindx = l1rec->l1file->bindx;
522  char *cal_path = l1_input->calfile;
523  int32_t rank;
524  int32_t nt;
525  int32_t dims[H4_MAX_VAR_DIMS];
526  int32_t nattrs;
527  char name [H4_MAX_NC_NAME] = "";
528  static int FirstCall = 1;
529  int current_scan = recnum / linesPerScan;
530  fileID = l1file->sd_id;
531 
532  /* load scan times */
533  /* if the day changed between the start of the scene
534  and the start of the subscene, adjust the day/year
535  accordingly */
536  static int dayIncrimented = 0;
537  if (msec[recnum] < msec_start) {
538  if(!dayIncrimented) {
539  dayIncrimented = 1;
540  day = day + 1;
541  if (day > maxday) {
542  year = year + 1;
543  day = day - maxday;
544  }
545  }
546  }
547  if (msec[recnum] >= 86400000L) {
548  msec[recnum] = msec[recnum] - 86400000L;
549  if(!dayIncrimented) {
550  dayIncrimented = 1;
551  day = day + 1;
552  if (day > maxday) {
553  year = year + 1;
554  day = day - maxday;
555  }
556  }
557  }
558  l1rec->scantime = yds2unix(year, day, (double) (msec[recnum] / 1.e3));
559 
560  /* load standard navigation */
561  memcpy(l1rec->lon, &lon [recnum * npix], sizeof (float)*npix);
562  memcpy(l1rec->lat, &lat [recnum * npix], sizeof (float)*npix);
563  memcpy(l1rec->solz, &solz[recnum * npix], sizeof (float)*npix);
564  memcpy(l1rec->sola, &sola[recnum * npix], sizeof (float)*npix);
565  memcpy(l1rec->senz, &senz[recnum * npix], sizeof (float)*npix);
566  memcpy(l1rec->sena, &sena[recnum * npix], sizeof (float)*npix);
567 
568 
569  if (l1file->format == FT_OCTSL1A) {
570 
571  /* Read the l1a data */
572  sds_index = SDnametoindex(fileID, "l1a_data");
573  sds_id = SDselect(fileID, sds_index);
574 
575  start[1] = recnum;
576  start[2] = 0;
577  edges[0] = 1;
578  edges[1] = 1;
579  edges[2] = npix;
580  for (i = 0; i < NOCBANDS; i++) {
581  start[0] = i;
582  status = SDreaddata(sds_id, start, NULL, edges, &dataarr[i][0]);
583  }
584 
585  scan = (recnum + extr_line_offset) / linesPerScan;
586 
587  l1rec->tilt = tilt[current_scan];
588 
589  tilt_deg = 0;
590  if (tilt_flag[current_scan] == 1) tilt_deg = +20;
591  if (tilt_flag[current_scan] == 2) tilt_deg = 0;
592  if (tilt_flag[current_scan] == 4) tilt_deg = -20;
593 
594  /* Read the next subsample table if necessary */
595  if (FirstCall == 1 && recnum > 0) {
596  for (i = 0; i < num_tab; i++) {
597  if (scan / linesPerScan < start_scan[i]) {
598  last_table = i;
599  FirstCall = 0;
600  break;
601  }
602  }
603  }
604 
605 
606  if (scan >= start_scan[last_table + 1]) {
607  last_table++;
608  samp_start[0] = last_table;
609 
610  sds_index = SDnametoindex(fileID, "samp_table");
611  sds_id = SDselect(fileID, sds_index);
612  status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
613  status = SDreaddata(sds_id, samp_start, NULL, samp_edges, (VOIDP) sample_table);
614  }
615 
616  /* Calibrate the l1a data */
617  status = get_octs_cal(cal_path, year, day, msec, recnum, npix, spix, tilt_deg,
618  gain, inst_temp, sample_table, scansPerScene,
619  dataarr, scanarr);
620 
621  if (status < 0) {
622  fprintf(stderr,
623  "-E- %s line %d: Error applying calibration table \"%s\".\n",
624  __FILE__, __LINE__, cal_path);
625  exit(status);
626  }
627 
628  }
629 
630 
631  /* load the L1B image data arrays (Lt)*/
632  if (l1file->format == FT_OCTSL1B) {
633 
634  l1rec->tilt = tilt[current_scan];
635 
636  status = rdSDS(fileID, "l1b_b1_data", recnum, 0, 1, npix, (VOIDP) & dataarr[0][0]);
637  status = rdSDS(fileID, "l1b_b2_data", recnum, 0, 1, npix, (VOIDP) & dataarr[1][0]);
638  status = rdSDS(fileID, "l1b_b3_data", recnum, 0, 1, npix, (VOIDP) & dataarr[2][0]);
639  status = rdSDS(fileID, "l1b_b4_data", recnum, 0, 1, npix, (VOIDP) & dataarr[3][0]);
640  status = rdSDS(fileID, "l1b_b5_data", recnum, 0, 1, npix, (VOIDP) & dataarr[4][0]);
641  status = rdSDS(fileID, "l1b_b6_data", recnum, 0, 1, npix, (VOIDP) & dataarr[5][0]);
642  status = rdSDS(fileID, "l1b_b7_data", recnum, 0, 1, npix, (VOIDP) & dataarr[6][0]);
643  status = rdSDS(fileID, "l1b_b8_data", recnum, 0, 1, npix, (VOIDP) & dataarr[7][0]);
644  for (i = 0; i < NOCBANDS; i++) {
645  for (j = 0; j < npix; j++) {
646  dataarr[i][j] = dataarr[i][j] & 8191;
647  }
648  }
649 
650  for (i = 0; i < npix; i++) {
651  scanarr[i][0] = (float) dataarr[0][i] * m[0] + b[0];
652  scanarr[i][1] = (float) dataarr[1][i] * m[1] + b[1];
653  scanarr[i][2] = (float) dataarr[2][i] * m[2] + b[2];
654  scanarr[i][3] = (float) dataarr[3][i] * m[3] + b[3];
655  scanarr[i][4] = (float) dataarr[4][i] * m[4] + b[4];
656  scanarr[i][5] = (float) dataarr[5][i] * m[5] + b[5];
657  scanarr[i][6] = (float) dataarr[6][i] * m[6] + b[6];
658  scanarr[i][7] = (float) dataarr[7][i] * m[7] + b[7];
659  }
660  }
661  /* copy the scan array over all bands, and npix pixels */
662  for (ip = 0; ip < npix; ip++) {
663 
664  // if solz NaN set navfail
665  if (isnan(l1rec->solz[ip]))
666  l1rec->navfail[ip] = 1;
667 
668  for (iw = 0; iw < nwave; iw++) {
669  ib = bindx[iw];
670  l1rec->Lt [ip * nwave + ib] = scanarr[ip][iw];
671 
672  /* Also set flags */
673  if (gain[iw * scansPerScene + current_scan] > 0)
674  l1rec->navwarn[ip] = 1;
675  if (miss_qual[current_scan] > 0)
676  l1rec->navwarn[ip] = 1;
677  if (dataarr[iw][ip] > 1022)
678  l1rec->hilt[ip] = 1;
679  if (scanarr[ip][iw] <= 0.0)
680  l1rec->navfail[ip] = 1;
681  }
682  }
683 
684  l1rec->npix = l1file->npix;
685 
686  return (0);
687 }
688 
689 /* ------------------------------------------------------ */
690 /* navigation() - generates navigation info interpolated */
691 /* for each pixel, using info from a NASDA */
692 /* OCTS HDF file */
693 /* */
694 
695 /* ------------------------------------------------------ */
696 int navigation(int32_t fileID) {
697  int16_t det;
698 
699  int16_t *pxl;
700  float *xctl;
701  float *inlon, *inlat;
702  float *insolz, *insola;
703  float *insenz, *insena;
704  float *usun, *pos;
705  int *row;
706  int *indx;
707  float *yctl;
708  float *in1, *in2;
709 
710  float iusun[3], ipos[3];
711  float usun_sum;
712  int i, j, k, l;
713  int eline, nlon, nlat;
714  int ilat[MAXOCLIN], ilon[MAXOCLIN];
715  float out1[MAXOCLIN], out2[MAXOCLIN];
716  int jout;
717  float *spl_aux;
718  float *x_ctl_ll, *y_ctl_ll, *z_ctl_ll;
719  float *x_ctl_sol, *y_ctl_sol, *z_ctl_sol;
720  float *x_ctl_sen, *y_ctl_sen, *z_ctl_sen;
721  float * in_ptr[3][3], *out_ptr[3][2];
722 
723  inlon = (float *) calloc(ncol*scansPerScene, sizeof (float));
724  inlat = (float *) calloc(ncol*scansPerScene, sizeof (float));
725  insolz = (float *) calloc(ncol*scansPerScene, sizeof (float));
726  insola = (float *) calloc(ncol*scansPerScene, sizeof (float));
727  insenz = (float *) calloc(ncol*scansPerScene, sizeof (float));
728  insena = (float *) calloc(ncol*scansPerScene, sizeof (float));
729  usun = (float *) calloc(3 * scansPerScene, sizeof (float));
730  pos = (float *) calloc(3 * scansPerScene, sizeof (float));
731  row = (int *) calloc(scansPerScene, sizeof (int));
732  pxl = (int16_t *) calloc(ncol, sizeof (int16_t));
733  xctl = (float *) calloc(ncol, sizeof (float));
734  indx = (int *) calloc(scansPerScene, sizeof (int));
735  yctl = (float *) calloc(scansPerScene, sizeof (float));
736  in1 = (float *) calloc(scansPerScene, sizeof (float));
737  in2 = (float *) calloc(scansPerScene, sizeof (float));
738 
739  /* read the data sets */
740  rdSDS(fileID, "det", 0, 0, 1, 1, (VOIDP) & det);
741  rdSDS(fileID, "pxl", 0, 0, 0, 0, (VOIDP) pxl); /* control pt. pixels */
742  rdSDS(fileID, "lon", 0, 0, 0, 0, (VOIDP) inlon); /* geodetic longitude */
743  rdSDS(fileID, "lat", 0, 0, 0, 0, (VOIDP) inlat); /* geodetic latitude */
744  rdSDS(fileID, "sun_ref", 0, 0, 0, 0, (VOIDP) usun); /* geocentric ECR solar refercence vector */
745  rdSDS(fileID, "orb_vec", 0, 0, 0, 0, (VOIDP) pos); /* geocentric ECR S/C position */
746 
747  det = det - 1;
748  for (i = 0; i < ncol; i++) {
749  pxl[i] = pxl[i] - 1;
750  }
751 
752  /* convert sun vector to unit vector */
753  for (i = 0; i < scansPerScene; i++) {
754  usun_sum = 0;
755  for (j = 0; j < 3; j++) {
756  usun_sum = usun_sum + usun[3 * i + j] * usun[3 * i + j];
757  }
758  for (j = 0; j < 3; j++) {
759  usun[3 * i + j] = usun[3 * i + j] / sqrt(usun_sum);
760  }
761  }
762 
763  /* define control point grid */
764  if (want_verbose)
765  printf("scansPerScene,ncol = %d %d \n", scansPerScene, ncol);
766  for (i = 0; i < ncol; i++) {
767  xctl[i] = (float) pxl[i];
768  }
769  for (i = 0; i < scansPerScene; i++) {
770  row[i] = i * linesPerScan + det;
771  }
772 
773  /* define output grid */
774  eline = sline + nline - 1;
775  nlon = npix; /* # of output pixs */
776  if (nline < linesPerScan * scansPerScene) {
777  nlat = nline; /* # of output lines */
778  } else nlat = linesPerScan*scansPerScene;
779 
780  for (i = 0; i < nlon; i++) {
781  ilon[i] = i + spix; /* pix #'s of output grid */
782  }
783  for (i = 0; i < nlat; i++) {
784  ilat[i] = i + sline; /* line #'s of output grid */
785  }
786 
787  /* create index of output lines to control point lines */
788  k = 0;
789  for (i = 0; i < nlat; i++) {
790  for (j = 0; j < scansPerScene; j++) {
791  if (ilat[i] == row[j]) {
792  indx[k] = i;
793  k++;
794  }
795  }
796  }
797 
798  for (i = 0; i < nlat / linesPerScan; i++) {
799  yctl[i] = (float) indx[i];
800  }
801 
802 
803  /* compute solar and sensor zenith and azimuth at input
804  control points from info provided */
805  if (want_verbose)
806  printf("Computing view angles at input control points\n");
807  for (i = 0; i < scansPerScene; i++) {
808  for (j = 0; j < ncol; j++) {
809  for (k = 0; k < 3; k++) {
810  ipos[k] = pos[3 * i + k];
811  iusun[k] = usun[3 * i + k];
812  }
813  CalcViewAngle(inlon[i * ncol + j], inlat[i * ncol + j], ipos, iusun);
814  insolz[i * ncol + j] = solz1;
815  insola[i * ncol + j] = sola1;
816  insenz[i * ncol + j] = senz1;
817  insena[i * ncol + j] = sena1;
818  }
819  }
820 
821 
822  /* Compute unit vectors from lon/lat of control points */
823  x_ctl_ll = (float *) calloc(ncol*scansPerScene, sizeof (float));
824  y_ctl_ll = (float *) calloc(ncol*scansPerScene, sizeof (float));
825  z_ctl_ll = (float *) calloc(ncol*scansPerScene, sizeof (float));
826 
827  x_ctl_sol = (float *) calloc(ncol*scansPerScene, sizeof (float));
828  y_ctl_sol = (float *) calloc(ncol*scansPerScene, sizeof (float));
829  z_ctl_sol = (float *) calloc(ncol*scansPerScene, sizeof (float));
830 
831  x_ctl_sen = (float *) calloc(ncol*scansPerScene, sizeof (float));
832  y_ctl_sen = (float *) calloc(ncol*scansPerScene, sizeof (float));
833  z_ctl_sen = (float *) calloc(ncol*scansPerScene, sizeof (float));
834 
835 
836  for (i = 0; i < scansPerScene; i++) {
837  for (j = 0; j < ncol; j++) {
838  inlon[i * ncol + j] = inlon[i * ncol + j] / RADEG;
839  inlat[i * ncol + j] = inlat[i * ncol + j] / RADEG;
840 
841  x_ctl_ll[i * ncol + j] = cos(inlat[i * ncol + j]) * cos(inlon[i * ncol + j]);
842  y_ctl_ll[i * ncol + j] = cos(inlat[i * ncol + j]) * sin(inlon[i * ncol + j]);
843  z_ctl_ll[i * ncol + j] = sin(inlat[i * ncol + j]);
844 
845 
846  insola[i * ncol + j] = insola[i * ncol + j] / RADEG;
847  insolz[i * ncol + j] = insolz[i * ncol + j] / RADEG;
848 
849  x_ctl_sol[i * ncol + j] = cos(insolz[i * ncol + j]) * cos(insola[i * ncol + j]);
850  y_ctl_sol[i * ncol + j] = cos(insolz[i * ncol + j]) * sin(insola[i * ncol + j]);
851  z_ctl_sol[i * ncol + j] = sin(insolz[i * ncol + j]);
852 
853 
854  insena[i * ncol + j] = insena[i * ncol + j] / RADEG;
855  insenz[i * ncol + j] = insenz[i * ncol + j] / RADEG;
856 
857  x_ctl_sen[i * ncol + j] = cos(insenz[i * ncol + j]) * cos(insena[i * ncol + j]);
858  y_ctl_sen[i * ncol + j] = cos(insenz[i * ncol + j]) * sin(insena[i * ncol + j]);
859  z_ctl_sen[i * ncol + j] = sin(insenz[i * ncol + j]);
860  }
861  }
862 
863  in_ptr[0][0] = x_ctl_ll;
864  in_ptr[0][1] = y_ctl_ll;
865  in_ptr[0][2] = z_ctl_ll;
866  in_ptr[1][0] = x_ctl_sol;
867  in_ptr[1][1] = y_ctl_sol;
868  in_ptr[1][2] = z_ctl_sol;
869  in_ptr[2][0] = x_ctl_sen;
870  in_ptr[2][1] = y_ctl_sen;
871  in_ptr[2][2] = z_ctl_sen;
872 
873  out_ptr[0][0] = lon;
874  out_ptr[0][1] = lat;
875  out_ptr[1][0] = sola;
876  out_ptr[1][1] = solz;
877  out_ptr[2][0] = sena;
878  out_ptr[2][1] = senz;
879 
880 
881  /* we now have all the info at each control point, so we
882  can interpolate to all pixels, all lines */
883  /* interpolate angles across each control point line */
884  if (want_verbose)
885  printf("Interpolating rows for longitude/azimuth\n");
886  spl_aux = (float *) calloc(ncol, sizeof (float));
887 
888  for (i = 0; i < scansPerScene; i++) {
889  jout = row[i] - sline;
890  if ((row[i] >= sline) && (row[i] <= eline)) {
891  for (l = 0; l < 3; l++) {
892  spline(xctl, in_ptr[l][0] + i*ncol, ncol, 1e30, 1e30, spl_aux);
893  for (j = 0; j < nlon; j++)
894  splint(xctl, in_ptr[l][0] + i * ncol, spl_aux, ncol,
895  (float) ilon[j], out_ptr[l][0] + jout * npix + j);
896 
897  spline(xctl, in_ptr[l][1] + i*ncol, ncol, 1e30, 1e30, spl_aux);
898  for (j = 0; j < nlon; j++)
899  splint(xctl, in_ptr[l][1] + i * ncol, spl_aux, ncol,
900  (float) ilon[j], out_ptr[l][1] + jout * npix + j);
901  }
902  }
903  }
904  free(spl_aux);
905 
906 
907  /* fill missing lines by interpolating columns */
908  if (want_verbose)
909  printf("Interpolating columns for longitude/azimuth\n");
910  spl_aux = (float *) calloc(nlat / linesPerScan, sizeof (float));
911 
912  for (i = 0; i < nlon; i++) {
913  for (l = 0; l < 3; l++) {
914  for (k = 0; k < nlat / linesPerScan; k++) {
915  in1[k] = *(out_ptr[l][0] + indx[k] * npix + i);
916  in2[k] = *(out_ptr[l][1] + indx[k] * npix + i);
917  }
918  spline(yctl, in1, nlat / linesPerScan, 1e30, 1e30, spl_aux);
919  for (j = 0; j < nlat; j++)
920  splint(yctl, in1, spl_aux, nlat / linesPerScan, (float) j, (float *) &out1[j]);
921 
922  spline(yctl, in2, nlat / linesPerScan, 1e30, 1e30, spl_aux);
923  for (j = 0; j < nlat; j++)
924  splint(yctl, in2, spl_aux, nlat / linesPerScan, (float) j, (float *) &out2[j]);
925 
926  for (j = 0; j < nlat; j++) {
927  *(out_ptr[l][0] + j * npix + i) = atan2(out2[j], out1[j]) * RADEG;
928  if (l >= 1 && *(out_ptr[l][0] + j * npix + i) < 0) {
929  *(out_ptr[l][0] + j * npix + i) += 360;
930  }
931  }
932  }
933  }
934  free(spl_aux);
935 
936 
937  if (want_verbose)
938  printf("Interpolating rows for latitude/zenith\n");
939  spl_aux = (float *) calloc(ncol, sizeof (float));
940 
941  for (i = 0; i < scansPerScene; i++) {
942  jout = row[i] - sline;
943  if ((row[i] >= sline) && (row[i] <= eline)) {
944  for (l = 0; l < 3; l++) {
945  spline(xctl, in_ptr[l][2] + i*ncol, ncol, 1e30, 1e30, spl_aux);
946  for (j = 0; j < nlon; j++)
947  splint(xctl, in_ptr[l][2] + i * ncol, spl_aux, ncol,
948  (float) ilon[j], out_ptr[l][1] + jout * npix + j);
949  }
950  }
951  }
952  free(spl_aux);
953 
954 
955  /* fill missing lines by interpolating columns */
956  if (want_verbose)
957  printf("Interpolating columns for latitude/zenith\n");
958  spl_aux = (float *) calloc(nlat / linesPerScan, sizeof (float));
959 
960  for (i = 0; i < nlon; i++) {
961  for (l = 0; l < 3; l++) {
962  for (k = 0; k < nlat / linesPerScan; k++) {
963  in1[k] = *(out_ptr[l][1] + indx[k] * npix + i);
964  }
965  spline(yctl, in1, nlat / linesPerScan, 1e30, 1e30, spl_aux);
966  for (j = 0; j < nlat; j++)
967  splint(yctl, in1, spl_aux, nlat / linesPerScan, (float) j, (float *) &out1[j]);
968 
969  for (j = 0; j < nlat; j++) {
970  *(out_ptr[l][1] + j * npix + i) = asin(out1[j]) * RADEG;
971  }
972  }
973  }
974  free(spl_aux);
975 
976 
977  free(x_ctl_ll);
978  free(y_ctl_ll);
979  free(z_ctl_ll);
980  free(x_ctl_sol);
981  free(y_ctl_sol);
982  free(z_ctl_sol);
983  free(x_ctl_sen);
984  free(y_ctl_sen);
985  free(z_ctl_sen);
986 
987  free(inlon);
988  free(inlat);
989  free(insolz);
990  free(insola);
991  free(insenz);
992  free(insena);
993  free(usun);
994  free(pos);
995  free(row);
996  free(pxl);
997  free(xctl);
998  free(indx);
999  free(yctl);
1000  free(in1);
1001  free(in2);
1002 
1003  return (0);
1004 }
1005 
1006 
1007 
1008 /* ------------------------------------------------------ */
1009 /* CalcViewAngle() - calculates the solar and sensor view */
1010 /* angles from one geodetic longitude and */
1011 /* latitude, position vector, and solar unit */
1012 /* vector. */
1013 /* */
1014 /* INPUT DESCRIPTION */
1015 /* ----- ----------- */
1016 /* lon longitude of pixel in degrees */
1017 /* lat latitude of pixel in degrees */
1018 /* pos[3] vector from earth center to spacecraft in */
1019 /* ECR, km */
1020 /* usun[3] unit vector from earth center to sun in */
1021 /* ECR */
1022 /* */
1023 /* OUTPUT DESCRIPTION */
1024 /* ------ ----------- */
1025 /* solz solar zenith angle of pixel in degrees */
1026 /* sola solar azimuth angle of pixel in degrees */
1027 /* senz sensor zenith angle of pixel in degrees */
1028 /* sena sensor azimuth angle of pixel in degrees */
1029 /* */
1030 
1031 /* ------------------------------------------------------ */
1032 int CalcViewAngle(float lon1, float lat1, float pos[3],
1033  float usun[3]) {
1034  float rmat[3][3]; /* rotation matrix */
1035  float rlon, rlat;
1036  float up[3], upxy, ea[3], no[3];
1037  float phi, R;
1038  float gvec[3], scvec[3], senl[3], sunl[3];
1039  int i, j;
1040 
1041  rlon = lon1 * PI / 180.0;
1042  rlat = lat1 * PI / 180.0;
1043 
1044  /* First, we must define the axes (in ECR space) of a
1045  pixel-local coordinate system, with the z-axis along
1046  the geodetic pixel normal, x-axis pointing east, and
1047  y-axis pointing north. */
1048  up[0] = cos(rlat) * cos(rlon);
1049  up[1] = cos(rlat) * sin(rlon);
1050  up[2] = sin(rlat);
1051  upxy = sqrt(up[0] * up[0 ] + up[1] * up[1]);
1052  ea[0] = -up[1] / upxy;
1053  ea[1] = up[0] / upxy;
1054  ea[2] = 0.0;
1055  /* calculate cross product of up and ea */
1056  no[0] = up[1] * ea[2] - ea[1] * up[2];
1057  no[1] = up[2] * ea[0] - ea[2] * up[0];
1058  no[2] = up[0] * ea[1] - ea[0] * up[1];
1059 
1060 
1061  /* Now we need the pixel-to-spacecraft vector in ECR,
1062  Compute geocentric pixel location vector in km and subtract
1063  from spacecraft position. */
1064  /* geocentric latitude */
1065  phi = atan(tan(rlat)*(1 - FL)*(1 - FL));
1066  /* dist to Earth surface */
1067  R = RADIUS * (1 - FL) / sqrt(1 - (2 - FL) * FL * (cos(phi) * cos(phi)));
1068  gvec[0] = R * cos(phi) * cos(rlon);
1069  gvec[1] = R * cos(phi) * sin(rlon);
1070  gvec[2] = R * sin(phi);
1071  for (i = 0; i < 3; i++) {
1072  scvec[i] = pos[i] - gvec[i];
1073  }
1074 
1075  /* Now we can transform the pixel-to-spacecraft and Sun
1076  vectors into the local frame. */
1077  for (i = 0; i < 3; i++) {
1078  rmat[0][i] = ea[i];
1079  rmat[1][i] = no[i];
1080  rmat[2][i] = up[i];
1081  }
1082  for (i = 0; i < 3; i++) {
1083  senl[i] = 0;
1084  sunl[i] = 0;
1085  for (j = 0; j < 3; j++) {
1086  senl[i] = senl[i] + rmat[i][j] * scvec[j];
1087  sunl[i] = sunl[i] + rmat[i][j] * usun[j];
1088  }
1089  }
1090 
1091  /* Compute the solar zenith and azimuth */
1092  solz1 = RADEG * atan(sqrt(sunl[0] * sunl[0] + sunl[1] * sunl[1]) / sunl[2]);
1093  if (solz1 < 0.0) solz1 += 180.0;
1094 
1095  if (solz1 > 0.05) {
1096  sola1 = RADEG * (atan2(sunl[0], sunl[1]));
1097  } else {
1098  sola1 = 0.0;
1099  }
1100  if (sola1 < 0.0) {
1101  sola1 = sola1 + 360.0;
1102  }
1103 
1104  /* Compute the sensor zenith and azimuth */
1105  senz1 = RADEG * atan(sqrt(senl[0] * senl[0] + senl[1] * senl[1]) / senl[2]);
1106  if (senz1 < 0.0) senz1 += 180.0;
1107  if (senz1 > 0.05) {
1108  sena1 = RADEG * (atan2(senl[0], senl[1]));
1109  } else {
1110  sena1 = 0.0;
1111  }
1112  if (sena1 < 0.0) {
1113  sena1 = sena1 + 360.0;
1114  }
1115  return (0);
1116 }
1117 
1118 
1119 /* ------------------------------------------------------ */
1120 /* LeapCheck() - checks if the year is a leap year: */
1121 /* returns -1 if leap year */
1122 /* returns 0 if non-leap year */
1123 /* */
1124 
1125 /* ------------------------------------------------------ */
1126 int LeapCheck(int yr) {
1127  int leap;
1128 
1129  leap = 0;
1130  if ((yr % 4) == 0) {
1131  leap = -1;
1132  }
1133  if ((yr % 100) == 0) {
1134  leap = 0;
1135  }
1136  if ((yr % 400) == 0) {
1137  leap = -1;
1138  }
1139  return (leap);
1140 }
1141 
1142 /* ------------------------------------------------------ */
1143 /* closel1_octs_hdf() - closes the level 1 OCTS HDF file */
1144 /* */
1145 
1146 /* ------------------------------------------------------ */
1147 int closel1_octs_hdf(filehandle *l1file) {
1148  free(lon);
1149  free(lat);
1150  free(senz);
1151  free(sena);
1152  free(solz);
1153  free(sola);
1154 
1155  if (l1file->format == FT_OCTSL1A) {
1156  free(start_scan);
1157  free(tilt_flag);
1158  free(inst_temp);
1159  }
1160 
1161  /* End access to the HDF file */
1162  SDend(l1file->sd_id);
1163 
1164  return (0);
1165 }
1166 
1167 void reform_octs_time(char *time) {
1168  int year, month, day, hour, min;
1169  double sec;
1170 
1171  sscanf(time, "%4d%2d%2d %2d:%2d:%lf", &year, &month, &day, &hour, &min, &sec);
1172  sec = sec + 60. * min + 3600. * hour;
1173  strncpy(time, ydhmsf(ymds2unix(year, month, day, sec), 'G'), 16);
1174  time[16] = '\0';
1175 }
char * ydhmsf(double dtime, char zone)
Definition: ydhmsf.c:12
void reform_octs_time(char *time)
Definition: l1_octs_hdf.c:1167
int32 l1file(int32 sdfid, int32 *nsamp, int32 *nscans, int16 *dtynum)
Definition: l1stat_chk.c:586
int navigation(int32_t fileID)
Definition: l1_octs_hdf.c:696
const int bindx[3]
Definition: DbLutNetcdf.cpp:28
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
#define MAXOCPIX
Definition: l1_octs_hdf.c:45
double yds2unix(int16_t year, int16_t day, double secs)
Definition: yds2unix.c:7
#define L(lambda, T)
Definition: PreprocessP.h:185
#define NGAIN
Definition: l1_octs_hdf.c:93
int16 * gain
Definition: l1_czcs_hdf.c:33
These are used to scale the SD before writing it to the HDF4 file The default is and which means the product is not scaled at all Since the product is usually stored as a float inside of this is a way to write the float out as a integer l2prod min
int16_t fileID
#define NBND
Definition: l1_octs_hdf.c:91
#define FAIL
Definition: ObpgReadGrid.h:18
#define NULL
Definition: decode_rs.h:63
MOD_PR01 Production producing one five minute granule of output data in each run It can be configured to produce as many as three five minute granules per run Each execution with one construction record and one date file for each dataset In normal these are created by which splits them out of the hour datasets For LANCE they are created by which merges all session MODIS L0 datasets overlapping the requested time and extracts from the merged data those packets which fall within that time period Each scan of data is stored in the L1A granule that covers the start time of that scan
Definition: MOD_PR01_pr.txt:19
read l1rec
#define MAXOCARR
Definition: l1_octs_hdf.c:46
subroutine spline(s, x, y, n, in, t, il, iu, vl, vu, e, u)
Definition: phs.f:1348
float32 * pos
Definition: l1_czcs_hdf.c:35
float * lat
int32 * msec
Definition: l1_czcs_hdf.c:31
@ FT_OCTSL1A
Definition: filetype.h:37
int LeapCheck(int yr)
Definition: l1_octs_hdf.c:1126
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
#define PI
Definition: l3_get_org.c:6
@ FT_OCTSL1B
Definition: filetype.h:38
int getDims(int32_t fileID, const char sdsname[], int32_t dims[])
int32_t mside
read recnum
double zulu2unix(char *zulu)
Definition: zulu2unix.c:3
int closel1_octs_hdf(filehandle *l1file)
Definition: l1_octs_hdf.c:1147
#define NOCBANDS
Definition: l1_octs_hdf.c:47
l1_input_t * l1_input
Definition: l1_options.c:9
int getHDFattr(int32_t fileID, const char attrname[], const char sdsname[], void *data)
#define FATAL_ERROR
Definition: swl0_parms.h:5
int want_verbose
#define NDET
Definition: l1_octs_hdf.c:90
#define RADIUS
Definition: l1_octs_hdf.c:39
#define MAXOCLIN
Definition: l1_octs_hdf.c:44
#define RADEG
Definition: czcs_ctl_pt.c:5
int readl1_octs_hdf(filehandle *l1file, int32_t recnum, l1str *l1rec)
Definition: l1_octs_hdf.c:510
data_t b[NROOTS+1]
Definition: decode_rs.h:77
int32_t get_octs_cal(char *file, int16_t year, int16_t day, int32_t msec[MAXOCLIN], int32_t recnum, int16_t npix, int32_t spix, int32_t tilt, int16_t gainset[MAXOCLIN], float inst_temp[MAXOCLIN], int16_t sample_table[3][8][2][400][2], int32_t scansPerScene, uint16_t l1acnts[NOCBANDS][MAXOCPIX], float l1brads[MAXOCPIX][NOCBANDS])
Definition: l1_octs_hdf.c:95
this program makes no use of any feature of the SDP Toolkit that could generate such a then geolocation is calculated at that and then aggregated up to Resolved feature request Bug by adding three new int8 SDSs for each high resolution offsets between the high resolution geolocation and a bi linear interpolation extrapolation of the positions This can be used to reconstruct the high resolution geolocation Resolved Bug by delaying cumulation of gflags until after validation of derived products Resolved Bug by setting Latitude and Longitude to the correct fill resolving to support Near Real Time because they may be unnecessary if use of entrained ephemeris and attitude data is turned resolving bug report Corrected to filter out Aqua attitude records with missing status helping resolve bug MOD_PR03 will still correctly write scan and pixel data that does not depend upon the start time
Definition: HISTORY.txt:248
int32 spix
Definition: l1_czcs_hdf.c:21
int CalcViewAngle(float lon1, float lat1, float pos[3], float usun[3])
Definition: l1_octs_hdf.c:1032
#define NTILT
Definition: l1_octs_hdf.c:89
Extra metadata that will be written to the HDF4 file l2prod rank
subroutine splint(xa, ya, y2a, n, x, y)
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 and prod_ix set to PARAM_TYPE_INT name_prefix is compared with the beginning of the product name If name_suffix is not empty the it must match the end of the product name The characters right after the prefix are read as an integer and prod_ix is set to that number strncpy(l2prod->name_prefix, "myprod", UNITLEN)
float * lon
int openl1_read_octs_hdf(filehandle *l1file)
Definition: l1_octs_hdf.c:328
double ymds2unix(short year, short month, short day, double secs)
for(i=0;i< NROOTS;i++) s[i]
Definition: decode_rs.h:85
#define R
Definition: make_L3_v1.1.c:96
logical function leap(YEAR)
Definition: leap.f:10
#define FL
Definition: l1_octs_hdf.c:40
int16_t * tilt
Definition: l2bin.cpp:86
#define abs(a)
Definition: misc.h:90
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")
int k
Definition: decode_rs.h:73
#define NSEG
Definition: l1_octs_hdf.c:92
int npix
Definition: get_cmp.c:27