OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l1b_misr.c
Go to the documentation of this file.
1 #include "l1.h"
2 #include "l1b_misr.h"
3 #include <hdf4utils.h>
4 
5 #include <hdf.h>
6 #include <mfhdf.h>
7 
8 #include <gsl/gsl_math.h>
9 #include <gsl/gsl_interp2d.h>
10 #include <gsl/gsl_spline2d.h>
11 #include <gsl/gsl_multifit.h>
12 
13 #include <libgen.h>
14 
15 static gsl_spline2d *spline_misr;
16 static gsl_interp_accel *xacc, *yacc;
17 static double xa[32], ya[2];
18 
19 static int32_t geoFileId;
20 static int32_t lat_id;
21 static int32_t lon_id;
22 
23 static int32_t sd_id[N_CAMERAS];
24 static int32_t red_id[N_CAMERAS];
25 static int32_t grn_id[N_CAMERAS];
26 static int32_t blu_id[N_CAMERAS];
27 
28 static int32_t nir_id[N_CAMERAS];
29 
30 static int icamera;
31 static int single_ifile=0;
32 
33 int openl1b_misr(filehandle *file) {
34  int32_t i;
35  int32_t sds_id;
36  int32_t gmp_id;
37  int32_t refn;
38  int32_t start[3]={0,0,0};
39  int32_t count[3]={180,8,32};
40  intn status;
41  char camera_type[N_CAMERAS][3]=
42  {"DF","CF","BF","AF","AN","AA","BA","CA","DA"};
43  char camera_type_mc[N_CAMERAS][3]=
44  {"Df","Cf","Bf","Af","An","Aa","Ba","Ca","Da"};
45  char namebuf[512];
46 
47 
48  misr_t *private_data = file->private_data;
49  //(misr_t *) calloc(1, sizeof(misr_t));
50 
51  //file->private_data = private_data;
52 
53  for (i=0; i<N_CAMERAS; i++) sd_id[i] = -1;
54 
55  if ( private_data->multipleInput == 1) {
56  // Multiple input files
57 
58  for (i=0; i<N_CAMERAS; i++) {
59  strcpy(namebuf, dirname(file->name));
60  strcat(namebuf, "/");
61  strncat(namebuf, basename(file->name), 39);
62  strcat(namebuf, camera_type[i]);
63  strcat(namebuf, basename(file->name)+41);
64  sd_id[i] = SDstart(namebuf, DFACC_RDONLY);
65  if (sd_id[i] == FAIL) {
66  fprintf(stderr, "-E- %s line %d: SDstart(%s, %d) failed.\n",
67  __FILE__, __LINE__, namebuf, DFACC_RDONLY);
68  return (HDF_FUNCTION_ERROR);
69  }
70 
71  // Read radiance scale factors
72  if (i == 0)
73  getRadScaleFactors( namebuf, private_data->radScaleFactors);
74 
75  // Get BlockTime IDs
76  private_data->fileID[i] = Hopen(namebuf, DFACC_RDONLY, 0);
77  Vstart ( private_data->fileID[i]);
78  refn = VSfind( private_data->fileID[i], "PerBlockMetadataTime");
79  private_data->blockTimeID[i] =
80  VSattach( private_data->fileID[i], refn, "r");
81  } // camera loop
82  icamera = 0;
83  // private_data->isSingleFile = 0;
84  } else {
85  // Single input file
86 
87  for (i=0; i<N_CAMERAS; i++) {
88  if ( strncmp(basename(file->name)+39, camera_type[i], 2) == 0) {
89  icamera = i;
90  single_ifile = 1;
91  // private_data->isSingleFile = 1;
92  sd_id[icamera] = SDstart(file->name, DFACC_RDONLY);
93  if (sd_id[icamera] == FAIL) {
94  fprintf(stderr, "-E- %s line %d: SDstart(%s, %d) failed.\n",
95  __FILE__, __LINE__, file->name, DFACC_RDONLY);
96  return (HDF_FUNCTION_ERROR);
97  }
98 
99  // Read radiance scale factors
100  getRadScaleFactors( file->name, private_data->radScaleFactors);
101  // Get BlockTime IDs
102  private_data->fileID[icamera] = Hopen(file->name, DFACC_RDONLY, 0);
103  Vstart ( private_data->fileID[icamera]);
104  refn = VSfind( private_data->fileID[icamera], "PerBlockMetadataTime");
105  private_data->blockTimeID[icamera] =
106  VSattach( private_data->fileID[icamera], refn, "r");
107 
108  break;
109  }
110  } // camera loop
111  }
112 
113  for (i=0; i<N_CAMERAS; i++) {
114  if (sd_id[i] == -1) continue;
115  red_id[i] =
116  SDselect(sd_id[i],SDnametoindex(sd_id[i], "Red Radiance/RDQI"));
117  grn_id[i] =
118  SDselect(sd_id[i], SDnametoindex(sd_id[i], "Green Radiance/RDQI"));
119  blu_id[i] =
120  SDselect(sd_id[i], SDnametoindex(sd_id[i], "Blue Radiance/RDQI"));
121  nir_id[i] =
122  SDselect(sd_id[i], SDnametoindex(sd_id[i], "NIR Radiance/RDQI"));
123  } // camera loop
124 
125  // Open the AGP geofile
126  //
127  // Dimensions: Block 180
128  // Row 128
129  // Col 512
130 
131  // -111 = Fill above data
132  // -222 = Fill below data
133  // -333 = Fill IPI invalid
134  // -444 = Fill to side of data
135  // -555 = Fill not processed
136  // -999 = Fill IPI error
137 
138  geoFileId = SDstart(file->geofile, DFACC_RDONLY);
139  if (geoFileId == FAIL) {
140  fprintf(stderr, "-E- %s line %d: SDstart(%s, %d) failed.\n",
141  __FILE__, __LINE__, file->geofile, DFACC_RDONLY);
142  return (HDF_FUNCTION_ERROR);
143  }
144 
145  lat_id = SDselect(geoFileId, SDnametoindex(geoFileId, "GeoLatitude"));
146  lon_id = SDselect(geoFileId, SDnametoindex(geoFileId, "GeoLongitude"));
147 
148 
149  // Open the GMP file
150  //
151  // Dimensions: Block 180
152  // Row 8
153  // Col 32
154  //
155  // Camera order: DF CF BF AF AN AA BA CA DA
156  //
157 
158  // Azimuth: 0.0 to 360.0
159  // Zenith: 0.0 to 90.0
160 
161  // Fill Value: -555
162  gmp_id = SDstart(file->gmpfile, DFACC_RDONLY);
163  if (gmp_id == FAIL) {
164  fprintf(stderr, "-E- %s line %d: SDstart(%s, %d) failed.\n",
165  __FILE__, __LINE__, file->gmpfile, DFACC_RDONLY);
166  return (HDF_FUNCTION_ERROR);
167  }
168 
169  // Read Solar Azimuth
170  sds_id = SDselect(gmp_id, SDnametoindex(gmp_id, "SolarAzimuth"));
171  status = SDreaddata(sds_id, start, NULL, count,
172  (VOIDP) &private_data->SolAzimuth);
173  if (status != 0) {
174  printf("-E- %s line %d: Error reading SDS %s from %s.\n", __FILE__,
175  __LINE__, "SolAzimuth", file->gmpfile);
176  exit(1);
177  }
178  SDendaccess(sds_id);
179 
180  // Read Solar Zenith
181  sds_id = SDselect(gmp_id, SDnametoindex(gmp_id, "SolarZenith"));
182  status = SDreaddata(sds_id, start, NULL, count,
183  (VOIDP) &private_data->SolZenith);
184  if (status != 0) {
185  printf("-E- %s line %d: Error reading SDS %s from %s.\n", __FILE__,
186  __LINE__, "SolZenith", file->gmpfile);
187  exit(1);
188  }
189  SDendaccess(sds_id);
190 
191  // Read Sensor Azimuth/Zenith
192  for (i=0; i<N_CAMERAS; i++) {
193  if (sd_id[i] == -1) continue;
194 
195  strcpy(namebuf, camera_type_mc[i]);
196  strcat(namebuf, "Azimuth");
197  sds_id = SDselect(gmp_id, SDnametoindex(gmp_id, namebuf));
198  status = SDreaddata(sds_id, start, NULL, count,
199  (VOIDP) &private_data->SenAzimuth[i]);
200  if (status != 0) {
201  printf("-E- %s line %d: Error reading SDS %s from %s.\n", __FILE__,
202  __LINE__, namebuf, file->gmpfile);
203  exit(1);
204  }
205  SDendaccess(sds_id);
206 
207  strcpy(namebuf, camera_type_mc[i]);
208  strcat(namebuf, "Zenith");
209  sds_id = SDselect(gmp_id, SDnametoindex(gmp_id, namebuf));
210  status = SDreaddata(sds_id, start, NULL, count,
211  (VOIDP) &private_data->SenZenith[i]);
212  if (status != 0) {
213  printf("-E- %s line %d: Error reading SDS %s from %s.\n", __FILE__,
214  __LINE__, namebuf, file->gmpfile);
215  exit(1);
216  }
217  SDendaccess(sds_id);
218  } // camera loop
219 
220  SDend(gmp_id);
221 
222 
223  // Read start and end block numbers
224  SDreadattr(sd_id[icamera],
225  SDfindattr(sd_id[icamera], "Start_block"),
226  (VOIDP) &private_data->startBlock);
227  SDreadattr(sd_id[icamera],
228  SDfindattr(sd_id[icamera], "End block"),
229  (VOIDP) &private_data->endBlock);
230 
231  file->nbands = 4;
232  file->npix = 512;
233  file->nscan = 128*(private_data->endBlock);
234  if (single_ifile == 0) file->nscan *= N_CAMERAS;
235 
236 
237  // Read ocean block numbers (1-based)
238  SDreadattr(sd_id[icamera],
239  SDfindattr(sd_id[icamera], "Ocean_blocks.numbers"),
240  (VOIDP) private_data->ocean_block_numbers);
241  memset(&private_data->isOceanBlock, 0, 180);
242  for (i=0; i<180; i++) {
243  int j = private_data->ocean_block_numbers[i];
244  if (j != 0) private_data->isOceanBlock[j-1] = 1;
245  }
246 
247  // Compute block offsets
248  memset(&private_data->offset, 0, 180);
249  for (i=0; i<179; i++) {
250  double p1 = private_data->SolZenith[8*i+6][15];
251  double p2 = private_data->SolZenith[8*i+7][15];
252  double f1 = private_data->SolZenith[8*(i+1)+0][15];
253  //double f2 = private_data->SolZenith[8*(i+1)+1][15];
254  double f1_l = private_data->SolZenith[8*(i+1)+0][14];
255  double f1_r = private_data->SolZenith[8*(i+1)+0][16];
256  double diff1a = fabs((p2-p1)-(f1-p2));
257  double diff1b = fabs((p2-p1)-(f1_l-p2));
258  double diff1c = fabs((p2-p1)-(f1_r-p2));
259  if (diff1a < diff1b && diff1a < diff1c)
260  private_data->offset[i] = 0;
261  if (diff1b < diff1a && diff1b < diff1c)
262  private_data->offset[i] = -1;
263  if (diff1c < diff1a && diff1c < diff1b)
264  private_data->offset[i] = +1;
265  }
266 
267 
268  // Set up interpolation grid
269 
270  // 512 / 32 = 16
271  // (16-1)/2 = 7.5
272  const gsl_interp2d_type *T = gsl_interp2d_bilinear;
273  spline_misr = gsl_spline2d_alloc(T, 32, 2);
274  xacc = gsl_interp_accel_alloc();
275  yacc = gsl_interp_accel_alloc();
276 
277  for (size_t i=0; i<32; i++) xa[i] = 7.5 + 16*i;
278  ya[0] = -0.5;
279  ya[1] = 15.5;
280 
281  return 0;
282 }
283 
284 
285 int getRadScaleFactors( char *file, double rad_scl_factors[4]) {
286 
287  int i,j;
288  int32_t file_id, vg_band_ref, refn, vg_id, vd_id;
289  int32_t nObj, tag, ref;
290  char name[100];
291  char *grpTags[4]={"BlueBand", "GreenBand", "RedBand", "NIRBand"};
292 
293  file_id = Hopen(file, DFACC_RDONLY, 0);
294  Vstart (file_id);
295 
296  // Loop over bands
297  for (i=0; i<4; i++) {
298 
299  // Find "Grid Attributes" group for each band
300  vg_band_ref = Vfind(file_id, grpTags[i]);
301  refn = vg_band_ref;
302  while (1) {
303  refn = Vgetid(file_id, refn);
304  vg_id = Vattach(file_id, refn, "r");
305  Vgetname(vg_id, name);
306  if (strcmp(name, "Grid Attributes") == 0) break;
307  Vdetach(vg_id);
308  }
309  nObj = Vntagrefs(vg_id);
310 
311  // Search within"Grid Attributes" group for "Scale factor" vdata
312  for (j=0; j<nObj; j++) {
313  Vgettagref(vg_id, j, &tag, &ref);
314  vd_id = VSattach(file_id, ref, "r");
315  VSgetname(vd_id, name);
316  if (strcmp(name, "Scale factor") == 0) {
317  VSread(vd_id, (uint8 *) &rad_scl_factors[i], 1, NO_INTERLACE);
318  VSdetach(vd_id);
319  break;
320  }
321  VSdetach(vd_id);
322  }
323  rad_scl_factors[i] /= 10;
324  } // band loop
325  Vdetach(vg_id);
326  Vend(file_id);
327  Hclose(file_id);
328 
329  return 0;
330 }
331 
332 
333 int readl1b_misr(filehandle *l1file, l1str *l1rec) {
334 
335  int i,j,k, jcamera;
336 
337  int32_t start[3]={0,0,0};
338  int32_t count[3]={1,1,512};
339 
340  //static int32_t last_recnum=-1;
341  static int32_t last_recnum_gp=-1;
342 
343  //int32_t diff_offset, interp_index;
344  int32_t recnum, recnum_red, recnum_gp, block;
345 
346  ushort rad_data[4][4][2048];
347 
348  double dbl_data[2*32];
349  double dbl_xy[2*32];
350  ushort *usptr;
351  char timestring[28];
352  int32_t year, day, msec;
353  int16_t yr16, day16;
354  double sec;
355 
356  static double sla_interp_data[16][512];
357  static double slz_interp_data[16][512];
358  static double sna_interp_data[N_CAMERAS][16][512];
359  static double snz_interp_data[N_CAMERAS][16][512];
360 
361  static double xy_interp_data[2][16][512];
362  static int32_t gp_index;
363 
364  static int first=1;
365  intn status;
366 
367  misr_t *private_data = l1file->private_data;
368 
369  // Initialize to fill value
370  if (first == 1) {
371  for (i=0; i<16; i++) {
372  for (j=0; j<512; j++) {
373  sla_interp_data[i][j] = -32767;
374  slz_interp_data[i][j] = -32767;
375  }
376  }
377 
378  for (k=0; k<N_CAMERAS; k++) {
379  for (i=0; i<16; i++) {
380  for (j=0; j<512; j++) {
381  // sna_interp_data[k][i][j] = -32767;
382  //snz_interp_data[k][i][j] = -32767;
383 
384  sna_interp_data[k][i][j] = -555;
385  snz_interp_data[k][i][j] = -555;
386  }
387  }
388  }
389  }
390  first = 0;
391 
392  recnum = l1rec->iscan;
393  if (single_ifile == 0) recnum /= N_CAMERAS;
394 
395  block = recnum / 128;
396 
397  // If no ocean data set time fill and bad nav and bail
398  // if(private_data->isOceanBlock[block] == 0) {
399  // l1rec->scantime = BAD_FLT;
400  // for (i=0; i<l1rec->npix; i++) l1rec->navfail[i] = 1;
401  //return 0;
402  //}
403 
404  // Bail if record already processed
405  //if (recnum == last_recnum) last_recnum_gp = -1;
406 
407  // Get corresponding camera number for scan
408  if (single_ifile) jcamera = icamera; else jcamera = l1rec->iscan % N_CAMERAS;
409  // Get scantime (from PerBlockMetadataTime vdata)
410  //i = 0;
411  // while (1) {
412  //if (block+1 == private_data->ocean_block_numbers[i]) break;
413  //i++;
414  //}
415 
416  VSseek(private_data->blockTimeID[jcamera], block);
417  VSread(private_data->blockTimeID[jcamera], (uint8 *) timestring, 1,
418  NO_INTERLACE);
419 
420  // Convert time string (isodate) to seconds
421  isodate2ydmsec(timestring, &year, &day, &msec);
422  yr16 = year;
423  day16 = day;
424  sec = (double) msec / 1000;
425 
426  if (yr16 > 1999)
427  l1rec->scantime = yds2unix(yr16, day16, sec);
428  else
429  return 0;
431  // Read lon/lat data //
433  start[0] = block;
434  start[1] = recnum - start[0]*128;
435 
436  status = SDreaddata(lat_id, start, NULL, count, (VOIDP) l1rec->lat);
437  if (status != 0) {
438  printf("-E- %s line %d: Error reading SDS %s from %s.\n", __FILE__,
439  __LINE__, "GeoLatitude", l1file->geofile);
440  exit(1);
441  }
442 
443  status = SDreaddata(lon_id, start, NULL, count, (VOIDP) l1rec->lon);
444  if (status != 0) {
445  printf("-E- %s line %d: Error reading SDS %s from %s.\n", __FILE__,
446  __LINE__, "GeoLongitude", l1file->geofile);
447  exit(1);
448  }
449 
450 
452  // Generate interpolated Azimuth/Zenith values if necessary //
454  recnum_gp = (recnum - 8) / 16;
455  if (recnum_gp != last_recnum_gp && recnum >= 8) {
456 
457  gp_index = 0;
458 
459 // printf("recnum_gp: %d block: %d %d jcamera: %d\n",
460 // recnum_gp, block, recnum_gp % 8, jcamera);
461 
462 // interp_index = recnum_gp % 8;
463 // if (interp_index == 7) {
464 // diff_offset = private_data->offset[block];
465 // } else {
466 // diff_offset = 0;
467 // }
468 
469  if (single_ifile || (l1rec->iscan % N_CAMERAS) == 0) {
471  // Interpolate Solar Azimuth values //
473  for (i=0; i<32; i++) {
474  dbl_data[i] = private_data->SolAzimuth[recnum_gp+0][i];
475  if (dbl_data[i] >= 0 && dbl_data[i] < 180)
476  dbl_data[i] = dbl_data[i] + 360;
477  dbl_data[i+32] = private_data->SolAzimuth[recnum_gp+1][i];
478  if (dbl_data[i+32] >= 0 && dbl_data[i+32] < 180)
479  dbl_data[i+32] = dbl_data[i+32] + 360;
480  }
481  interp_values( dbl_data, sla_interp_data);
482 
484  // Interpolate Solar Zenith values //
486  for (i=0; i<32; i++) {
487  dbl_data[i] = private_data->SolZenith[recnum_gp+0][i];
488  dbl_data[i+32] = private_data->SolZenith[recnum_gp+1][i];
489  }
490  interp_values( dbl_data, slz_interp_data);
491  }
493  // Interpolate Sensor Azimuth values //
495 
496  // In order to avoid problems interpolating over 0/360 jump the
497  // unit vector xy-values will be used rather than the azimuth angle
498 
499  for (j=0; j<N_CAMERAS; j++) {
500  if (sd_id[j] == -1) continue;
501 
502  for (i=0; i<32; i++) {
503  dbl_xy[i] = -555;
504  if ( private_data->SenAzimuth[j][recnum_gp+0][i] > 0)
505  dbl_xy[i] = cos(private_data->SenAzimuth[j][recnum_gp+0][i]*D2R);
506  dbl_xy[i+32] = -555;
507  if ( private_data->SenAzimuth[j][recnum_gp+1][i] > 0)
508  dbl_xy[i+32] = cos(private_data->SenAzimuth[j][recnum_gp+1][i]*D2R);
509  }
510  interp_values( dbl_xy, xy_interp_data[0]);
511 
512  for (i=0; i<32; i++) {
513  dbl_xy[i] = -555;
514  if ( private_data->SenAzimuth[j][recnum_gp+0][i] > 0)
515  dbl_xy[i] = sin(private_data->SenAzimuth[j][recnum_gp+0][i]*D2R);
516  dbl_xy[i+32] = -555;
517  if ( private_data->SenAzimuth[j][recnum_gp+1][i] > 0)
518  dbl_xy[i+32] = sin(private_data->SenAzimuth[j][recnum_gp+1][i]*D2R);
519  }
520  interp_values( dbl_xy, xy_interp_data[1]);
521 
522  for (i=0; i<16; i++) {
523  for (k=0; k<512; k++) {
524  if ( xy_interp_data[1][i][k] != -555 &&
525  xy_interp_data[0][i][k] != -555)
526  sna_interp_data[j][i][k] = atan2(xy_interp_data[1][i][k],
527  xy_interp_data[0][i][k]) / D2R;
528  else
529  sna_interp_data[j][i][k] = -555;
530  }
531  }
532  } // camera loop
533 
534 
536  // Interpolate Sensor Zenith values //
538  for (j=0; j<N_CAMERAS; j++) {
539  if (sd_id[j] == -1) continue;
540  for (i=0; i<32; i++) {
541  dbl_data[i] = private_data->SenZenith[j][recnum_gp+0][i];
542  dbl_data[i+32] = private_data->SenZenith[j][recnum_gp+1][i];
543  }
544  interp_values( dbl_data, snz_interp_data[j]);
545  }
546 
547  last_recnum_gp = recnum_gp;
548 
549  } // Generate interpolated GMP values ... if (recnum_gp != last_recnum_gp)
550 
551 
553  // Process radiance data //
555  recnum_red = 4*recnum;
556  start[0] = recnum_red / 512;
557  start[1] = recnum_red - start[0]*512;
558  count[1] = 4;
559  count[2] = 2048;
560 
561  // printf("Reading radiance record: %d\n", recnum);
562 
563  // Red
564  status = SDreaddata(red_id[jcamera], start, NULL, count, (VOIDP) rad_data[2]);
565  if (status != 0) {
566  printf("-E- %s line %d: Error reading SDS %s from %s.\n", __FILE__,
567  __LINE__, "Red Radiance/RDQI", l1file->name);
568  exit(1);
569  }
570  usptr = &rad_data[2][0][0];
571  for (size_t i=0; i<count[1]*count[2]; i++) *usptr++ /= 4;
572 
573  reduce_res(rad_data[2]);
574 
575  if ((jcamera+1) != 5) {
576  start[0] = recnum / 128;
577  start[1] = recnum - start[0]*128;
578  count[1] = 1;
579  count[2] = 512;
580  }
581 
582  // Blue
583  status = SDreaddata(blu_id[jcamera], start, NULL, count, (VOIDP) rad_data[0]);
584  if (status != 0) {
585  printf("-E- %s line %d: Error reading SDS %s from %s.\n", __FILE__,
586  __LINE__, "Blue Radiance/RDQI", l1file->name);
587  exit(1);
588  }
589  usptr = &rad_data[0][0][0];
590  for (size_t i=0; i<count[1]*count[2]; i++) *usptr++ /= 4;
591  if ((jcamera+1) == 5) reduce_res(rad_data[0]);
592 
593 
594  // Green
595  status = SDreaddata(grn_id[jcamera], start, NULL, count, (VOIDP) rad_data[1]);
596  if (status != 0) {
597  printf("-E- %s line %d: Error reading SDS %s from %s.\n", __FILE__,
598  __LINE__, "Green Radiance/RDQI", l1file->name);
599  exit(1);
600  }
601  usptr = &rad_data[1][0][0];
602  for (size_t i=0; i<count[1]*count[2]; i++) *usptr++ /= 4;
603  if ((jcamera+1) == 5) reduce_res(rad_data[1]);
604 
605  // NIR
606  status = SDreaddata(nir_id[jcamera], start, NULL, count, (VOIDP) rad_data[3]);
607  if (status != 0) {
608  printf("-E- %s line %d: Error reading SDS %s from %s.\n", __FILE__,
609  __LINE__, "NIR Radiance/RDQI", l1file->name);
610  exit(1);
611  }
612  usptr = &rad_data[3][0][0];
613  for (size_t i=0; i<count[1]*count[2]; i++) *usptr++ /= 4;
614  if ((jcamera+1) == 5) reduce_res(rad_data[3]);
615 
616 
617  // Convert scaled radiance values to floating point and copy to Lt
618  for (size_t ip=8; ip<504; ++ip) {
619  if (rad_data[0][0][ip] < 16378)
620  l1rec->Lt[4*ip+0] = rad_data[0][0][ip]*private_data->radScaleFactors[0];
621  if (rad_data[1][0][ip] < 16378)
622  l1rec->Lt[4*ip+1] = rad_data[1][0][ip]*private_data->radScaleFactors[1];
623  if (rad_data[2][0][ip] < 16378)
624  l1rec->Lt[4*ip+2] = rad_data[2][0][ip]*private_data->radScaleFactors[2];
625  if (rad_data[3][0][ip] < 16378)
626  l1rec->Lt[4*ip+3] = rad_data[3][0][ip]*private_data->radScaleFactors[3];
627  }
628 
629  // Copy Azimuth/Zenith angles to l1rec arrays
630  for (size_t ip=8; ip<504; ++ip) {
631  if (sla_interp_data[gp_index][ip] != -555) {
632  l1rec->sola[ip] = sla_interp_data[gp_index][ip];
633  if (l1rec->sola[ip] > 360) l1rec->sola[ip] = l1rec->sola[ip] - 360;
634  if (l1rec->sola[ip] > 180) l1rec->sola[ip] = l1rec->sola[ip] - 360;
635  }
636 
637  if (slz_interp_data[gp_index][ip] != -555) {
638  l1rec->solz[ip] = slz_interp_data[gp_index][ip];
639  l1rec->csolz[ip] = cos(l1rec->solz[ip] / RADEG);
640  }
641 
642  if (sna_interp_data[jcamera][gp_index][ip] != -555) {
643  l1rec->sena[ip] = sna_interp_data[jcamera][gp_index][ip];
644  if (l1rec->sena[ip] > 360) l1rec->sena[ip] = l1rec->sena[ip] - 360;
645  if (l1rec->sena[ip] > 180) l1rec->sena[ip] = l1rec->sena[ip] - 360;
646  }
647 
648  if (snz_interp_data[jcamera][gp_index][ip] != -555) {
649  l1rec->senz[ip] = snz_interp_data[jcamera][gp_index][ip];
650  l1rec->csenz[ip] = cos(l1rec->senz[ip] / RADEG);
651  }
652 
653  if (sla_interp_data[gp_index][ip] != -555 &&
654  sna_interp_data[jcamera][gp_index][ip] != -555) {
655  l1rec->delphi[ip] = l1rec->sena[ip] - 180.0 - l1rec->sola[ip];
656 
657  if (l1rec->delphi[ip] < -180.)
658  l1rec->delphi[ip] += 360.0;
659  else if (l1rec->delphi[ip] > 180.0)
660  l1rec->delphi[ip] -= 360.0;
661  }
662  }
663 
664  if (single_ifile || (l1rec->iscan % N_CAMERAS) == 8) gp_index++;
665 
666  //last_recnum = recnum;
667 
668  return 0;
669 }
670 
671 
672 int interp_values( double *grid_values, double interpolated_values[16][512]) {
673 
674  const gsl_interp2d_type *T = gsl_interp2d_bilinear;
675  static gsl_spline2d *spline;
676  static gsl_interp_accel *xacc, *yacc;
677  static double xa[32], ya[2];
678 
679  double dbl_data[2*32];
680 
681  static int first=1;
682 
683  // 512 / 32 = 16
684  // (16-1)/2 = 7.5
685 
686  if (first) {
687  // Set up interpolation grid
688  spline = gsl_spline2d_alloc(T, 32, 2);
689  xacc = gsl_interp_accel_alloc();
690  yacc = gsl_interp_accel_alloc();
691 
692  for (size_t i=0; i<32; i++) xa[i] = 7.5 + 16*i;
693  ya[0] = -0.5;
694  ya[1] = 15.5;
695 
696  first = 0;
697  }
698 
699  for (size_t i=0; i<32; i++) {
700  gsl_spline2d_set(spline, dbl_data, i, 0, grid_values[i]);
701  gsl_spline2d_set(spline, dbl_data, i, 1, grid_values[i+32]);
702  }
703 
704  gsl_spline2d_init(spline, xa, ya, dbl_data, 32, 2);
705 
706  // -111 = Fill above data
707  // -222 = Fill below data
708  // -333 = Fill IPI invalid
709  // -444 = Fill to side of data
710  // -555 = Fill not processed
711  // -999 = Fill IPI error
712 
713  for (size_t j=0; j<16; ++j) {
714  double yi = (double) j;
715  for (size_t i=8; i<504; ++i) {
716  double xi = (double) i;
717 
718  if (grid_values[(i-8)/16] == -111 || grid_values[(i-8)/16] == -222 ||
719  grid_values[(i-8)/16] == -333 || grid_values[(i-8)/16] == -444 ||
720  grid_values[(i-8)/16] == -555 || grid_values[(i-8)/16] == -999 ||
721 
722  grid_values[(i-8)/16+1] == -111 || grid_values[(i-8)/16+1] == -222 ||
723  grid_values[(i-8)/16+1] == -333 || grid_values[(i-8)/16+1] == -444 ||
724  grid_values[(i-8)/16+1] == -555 || grid_values[(i-8)/16+1] == -999 ||
725 
726  grid_values[(i-8)/16+32] == -111 || grid_values[(i-8)/16+32] == -222 ||
727  grid_values[(i-8)/16+32] == -333 || grid_values[(i-8)/16+32] == -444 ||
728  grid_values[(i-8)/16+32] == -555 || grid_values[(i-8)/16+32] == -999 ||
729 
730  grid_values[(i-8)/16+32+1] == -111 || grid_values[(i-8)/16+32+1] == -222 ||
731  grid_values[(i-8)/16+32+1] == -333 || grid_values[(i-8)/16+32+1] == -444 ||
732  grid_values[(i-8)/16+32+1] == -555 || grid_values[(i-8)/16+32+1] == -999)
733 
734  interpolated_values[j][i] = -555;
735  else
736  interpolated_values[j][i] =
737  gsl_spline2d_eval(spline, xi, yi, xacc, yacc);
738 
739 
740  }
741  }
742 
743  return 0;
744 }
745 
746 
747 int interp_values_dbl( int32_t diff_offset, double *grid_values,
748  double interpolated_values[16][512]) {
749 
750  double dbl_data[2*32];
751 
752  if (diff_offset == 0) {
753  for (size_t i=0; i<32; i++) {
754  gsl_spline2d_set(spline_misr, dbl_data, i, 0, (double) grid_values[i]);
755  gsl_spline2d_set(spline_misr, dbl_data, i, 1, (double) grid_values[i+32]);
756  }
757 
758  gsl_spline2d_init(spline_misr, xa, ya, dbl_data, 32, 2);
759 
760  for (size_t j=0; j<16; ++j) {
761  double yi = (double) j;
762  for (size_t i=8; i<504; ++i) {
763  double xi = (double) i;
764  //printf("%d %f %d %f\n", j, yi, i, xi);
765  interpolated_values[j][i] =
766  gsl_spline2d_eval(spline_misr, xi, yi, xacc, yacc);
767  }
768  }
769  } else if (diff_offset == -1) {
770 
771  for (size_t i=0; i<32; i++)
772  gsl_spline2d_set(spline_misr, dbl_data, i, 0, (double) grid_values[i]);
773  for (size_t i=0; i<31; i++)
774  gsl_spline2d_set(spline_misr, dbl_data, i+1, 1,
775  (double) grid_values[i+32]);
776 
777  for (size_t j=0; j<8; ++j) {
778  double yi = (double) j;
779  for (size_t i=8; i<504; ++i) {
780  double xi = (double) i;
781  //printf("%d %f %d %f\n", j, yi, i, xi);
782  interpolated_values[j][i] =
783  gsl_spline2d_eval(spline_misr, xi, yi, xacc, yacc);
784  }
785  }
786 
787  for (size_t i=0; i<32; i++)
788  gsl_spline2d_set(spline_misr, dbl_data, i, 0, (double) grid_values[i]);
789  for (size_t i=0; i<32; i++)
790  gsl_spline2d_set(spline_misr, dbl_data, i, 1,
791  (double) grid_values[i+32]);
792 
793  } else {
794  for (size_t i=1; i<32; i++)
795  gsl_spline2d_set(spline_misr, dbl_data, i-1, 1,
796  (double) grid_values[i]);
797 
798  for (size_t j=0; j<16; ++j) {
799  double yi = (double) j;
800  for (size_t i=8; i<504; ++i) {
801  double xi = (double) i;
802  //printf("%d %f %d %f\n", j, yi, i, xi);
803  interpolated_values[j][i] =
804  gsl_spline2d_eval(spline_misr, xi, yi, xacc, yacc);
805  }
806  }
807 
808  }
809 
810  return 0;
811 }
812 
813 
814 int reduce_res(uint16_t rad_data[4][2048]) {
815 
816  static int first=1;
817  static gsl_matrix *X, *cov;
818  static gsl_vector *y, *w, *c;
819 
820  static gsl_multifit_linear_workspace *work;
821 
822  double chisq;
823 
824  if (first) {
825 
826  X = gsl_matrix_alloc (16, 3);
827  y = gsl_vector_alloc (16);
828  w = gsl_vector_alloc (16);
829 
830  c = gsl_vector_alloc (3);
831  cov = gsl_matrix_alloc (3, 3);
832 
833  work = gsl_multifit_linear_alloc (16, 3);
834 
835  for (size_t i=0; i<16; i++) {
836  gsl_matrix_set (X, i, 0, 1.0);
837 
838  int row, col;
839  row = i / 4;
840  col = i - row*4;
841 
842  double x_val = col - 1.5;
843  double y_val = 1.5 - row;
844 
845  gsl_matrix_set (X, i, 1, x_val);
846  gsl_matrix_set (X, i, 2, y_val);
847 
848  first = 0;
849  }
850  }
851 
852  for (size_t ip=0; ip<512; ip++) {
853  int ngood = 0;
854  for (size_t irow=0; irow<4; irow++) {
855  for (size_t icol=0; icol<4; icol++) {
856  int index = irow*4+icol;
857  double d_val = (double) rad_data[irow][4*ip+icol];
858  gsl_vector_set (y, index, d_val);
859  if (rad_data[irow][4*ip+icol] >= 16378) {
860  gsl_vector_set (w, index, 0.0);
861  } else {
862  gsl_vector_set (w, index, 1.0);
863  ngood++;
864  }
865  }
866  }
867  if (ngood >= 5) {
868 
869  /*
870  double *ptr = gsl_matrix_ptr(X,0,0);
871  for (size_t i=0; i<16; i++)
872  printf("%lf %lf %lf\n", ptr[i*3+0],ptr[i*3+1],ptr[i*3+2]);
873  printf("\n");
874 
875  ptr = gsl_vector_ptr(w,0);
876  for (size_t i=0; i<16; i++) printf("%lf\n", ptr[i]);
877  printf("\n");
878 
879  ptr = gsl_vector_ptr(y,0);
880  for (size_t i=0; i<16; i++) printf("%lf\n", ptr[i]);
881  printf("\n");
882  */
883  gsl_multifit_wlinear (X, w, y, c, cov, &chisq, work);
884  double fit_val = gsl_vector_get(c,0);
885  rad_data[0][ip] = (ushort) ( fit_val + 0.5);
886  } else {
887  rad_data[0][ip] = 16378;
888  }
889  } // i loop
890 
891  return 0;
892 }
893 
894 
895 int closel1b_misr(filehandle *file) {
896 
897  int i;
898 
899  SDendaccess(lat_id);
900  SDendaccess(lon_id);
901 
902  for (i=0; i<N_CAMERAS; i++) {
903  if (sd_id[i] == -1) continue;
904  SDendaccess(blu_id[i]);
905  SDendaccess(grn_id[i]);
906  SDendaccess(red_id[i]);
907  SDendaccess(nir_id[i]);
908 
909  SDend(sd_id[i]);
910  }
911  // VSdetach(vd_id);
912  //Vend(file_id);
913  //Hclose(file_id);
914 
915  return 0;
916 }
917 
918 
int32 l1file(int32 sdfid, int32 *nsamp, int32 *nscans, int16 *dtynum)
Definition: l1stat_chk.c:586
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 index(0-based) was previously being used the frame number(1-based) should have been used. There were only a few minor changes to the uncertainty index(maximum of 1 digit). 3. Some inefficient arrays(Sigma_RVS_norm_sq) were eliminated and some code lines in Preprocess_L1A_Data were moved into Process_OBCEng_Emiss. There were no changes to the product. Required RAM was reduced by 20 MB. Now
int j
Definition: decode_rs.h:73
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
#define N_CAMERAS
Definition: l1b_misr.h:4
float f1(float x)
#define FAIL
Definition: ObpgReadGrid.h:18
#define NULL
Definition: decode_rs.h:63
int getRadScaleFactors(char *file, double rad_scl_factors[4])
Definition: l1b_misr.c:285
read l1rec
subroutine spline(s, x, y, n, in, t, il, iu, vl, vu, e, u)
Definition: phs.f:1348
int32 * msec
Definition: l1_czcs_hdf.c:31
int interp_values(double *grid_values, double interpolated_values[16][512])
Definition: l1b_misr.c:672
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 reduce_res(uint16_t rad_data[4][2048])
Definition: l1b_misr.c:814
read recnum
#define D2R
Definition: proj_define.h:91
integer, parameter double
void isodate2ydmsec(char *date, int32_t *year, int32_t *day, int32_t *msec)
Definition: date2ydmsec.c:20
#define RADEG
Definition: czcs_ctl_pt.c:5
#define basename(s)
Definition: l0chunk_modis.c:29
int interp_values_dbl(int32_t diff_offset, double *grid_values, double interpolated_values[16][512])
Definition: l1b_misr.c:747
int closel1b_misr(filehandle *file)
Definition: l1b_misr.c:895
int openl1b_misr(filehandle *file)
Definition: l1b_misr.c:33
#define fabs(a)
Definition: misc.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 as required for compatibility with version of the SDP toolkit Corrected test output file names to end in per delivery and then split off a new MYD_PR03 pcf file for Aqua Added AssociatedPlatformInstrumentSensor to the inventory metadata in MOD01 mcf and MOD03 mcf Created new versions named MYD01 mcf and MYD03 where AssociatedPlatformShortName is rather than Terra The program itself has been changed to read the Satellite Instrument validate it against the input L1A and LUT and to use it determine the correct files to retrieve the ephemeris and attitude data from Changed to produce a LocalGranuleID starting with MYD03 if run on Aqua data Added the Scan Type file attribute to the Geolocation copied from the L1A and attitude_angels to radians rather than degrees The accumulation of Cumulated gflags was moved from GEO_validate_earth_location c to GEO_locate_one_scan c
Definition: HISTORY.txt:464
int readl1b_misr(filehandle *l1file, l1str *l1rec)
Definition: l1b_misr.c:333
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")
unsigned short ushort
Definition: l1b_viirs_nc.c:16
int k
Definition: decode_rs.h:73
#define HDF_FUNCTION_ERROR
Definition: passthebuck.h:7
int count
Definition: decode_rs.h:79