OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l1_aviris.c
Go to the documentation of this file.
1 /*
2  * l1_aviris.c
3  *
4  * Created on: May 18, 2015
5  * Author: Rick Healy SAIC
6  * NASA-GSFC OBPG
7  */
8 #include <stdlib.h>
9 #include <stdio.h>
10 
11 #include "l1.h"
12 #include "jplaeriallib.h"
13 #include "l1_aviris.h"
14 #include <math.h>
15 
16 #include <libnav.h>
17 #include <proj.h>
18 
19 #define SKIP -9999
20 static const int maxBands = 224;
21 
22 /*
23  * RJH - 11/14/2016 - Added code for processing preprocessed hdr data for old Aviris files
24  * RJH - 10/24/2016 - If gain file is missing, assume values are the same as every scene seems to be
25  * Removed unused commented code
26  * Todo: 7/6/2016 - rjh
27  * 1) remove repeating and overlapping bands (wait for Bryan's rayleigh files)
28  * 2) Add Atrem files for gas correction
29  */
30 aviris_t* createPrivateData_aviris(int numBands) {
31 
32  aviris_t* data = (aviris_t*) calloc(1, sizeof (aviris_t));
33  if (data == NULL) {
34  fprintf(stderr, "-E- %s line %d: unable to allocate private data for aviris\n",
35  __FILE__, __LINE__);
36  exit(1);
37  }
38 
39  data->wave = (double *) malloc(numBands * sizeof (double));
40  data->fwhm = (double *) malloc(numBands * sizeof (double));
41  if (data->wave == NULL || data->fwhm == NULL) {
42  fprintf(stderr, "-E- %s line %d: unable to allocate scale/offset data for aviris\n",
43  __FILE__, __LINE__);
44  exit(1);
45  }
46 
47  data->have_nav = 0;
48  data->have_gain = 0;
49 
50  return data;
51 }
52 
53 void freePrivateData_aviris(aviris_t* data) {
54  free(data->wave);
55  free(data->fwhm);
56  free(data->gain);
57  free(data->sena);
58  free(data->senz);
59  free(data->sola);
60  free(data->solz);
61  free(data->utc);
62  gsl_interp_accel_free(data->spl_acc);
63 
64 }
65 
66 void get_aviris_nav_data(char* navfile, int32_t nscans, int32_t npix, aviris_t* data) {
67 
68  FILE* ptr;
69  double sec;
70  char line[itemSize];
71  float sunpos[3];
72  float latitude, longitude;
73  double secondOfDay;
74  float sunDist;
75  int i, k, ip;
76  int16_t year, hour, minute, doy;
77  char* result;
78  int32_t iyear, idoy;
79  static double *range, *lon, *lat;
80  double c0, c1, d0, d1, cov00, cov01, cov11, chisq, dth = 0.00087, th;
81  float xlon, xlat, vel[3], pos[3], pview[3], att[3] = {0, 0, 0}, coef[10],
82  *smat[3];
83  float sena, senz, sola, solz;
84 
85  if (nscans < 2) {
86  fprintf(stderr,
87  "-E- %s line %d: Navigation needs at least 2 scan lines\n",
88  __FILE__, __LINE__);
89  exit(-1);
90  }
91  if ((ptr = fopen(navfile, "r")) == NULL) {
92  fprintf(stderr, "-E- %s line %d: unable to open %s\n", __FILE__,
93  __LINE__, navfile);
94  exit(-1);
95  }
96 
97  if (!data->lon)
98  data->lon = (double*) malloc(npix * nscans * sizeof (double));
99  if (!data->lat)
100  data->lat = (double*) malloc(npix * nscans * sizeof (double));
101  if (!range) range = (double*) malloc(nscans * sizeof (double));
102  if (!lon) lon = (double*) malloc(nscans * sizeof (double));
103  if (!lat) lat = (double*) malloc(nscans * sizeof (double));
104  for (i = 0; i < 3; i++)
105  smat[i] = (float*) malloc(3 * sizeof (float));
106  i = 0;
107  while ((result = fgets(line, itemSize, ptr)) && i < nscans) {
108  if (result == NULL) {
109  fprintf(stderr,
110  "-E- %s line %d: unable to read all of the navigation data from AVIRIS nav file\n",
111  __FILE__, __LINE__);
112  exit(1);
113  }
114  trimBlanks(line);
115  sscanf(line, "%lf %f %lf %lf ", &data->utc[i], &data->alt[i], &lat[i],
116  &lon[i]);
117  range[i] = i;
118  i++;
119  }
120  // smooth the digitized lon/lat's
121  gsl_fit_linear(range, 1, lon, 1, nscans, &c0, &c1, &cov00, &cov01, &cov11,
122  &chisq);
123  gsl_fit_linear(range, 1, lat, 1, nscans, &d0, &d1, &cov00, &cov01, &cov11,
124  &chisq);
125  //Get the velocity vector
126  nav_get_vel(d0, d1, c0, c1, vel);
127  for (i = 0; i < nscans; i++) {
128  longitude = c0 + c1 * i;
129  latitude = d0 + d1 * i;
130  hour = (int) (data->utc[i]);
131  minute = (data->utc[i] - hour) * 60;
132  sec = ((data->utc[i] - hour) * 60 - minute) * 60;
133  //getPosVecR(latitude,longitude, data->alt[i], pos); // get position vector of sensor
134  unix2yds(ymds2unix(data->year, data->month, data->day,
135  (hour * 3600. + minute * 60. + sec)), &year, &doy, &secondOfDay);
137  nav_gd_orient(pos, vel, att, smat, coef);
138  iyear = (int32_t) year;
139  idoy = (int32_t) doy;
140  l_sun_(&iyear, &idoy, &secondOfDay, sunpos, &sunDist); // get position vector for the sun
141  for (k = 0; k < 3; k++) {
142  sunpos[k] *= 1.496e8; //convert to km for call to get_zenaz
143  //epos[k] = pos[k];
144  }
145  //get_zenaz (epos, longitude, latitude, &data->senz[i*npix], &data->sena[i*npix]);
146  //get_zenaz(sunpos, longitude, latitude, &data->solz[i*npix], &data->sola[i*npix]);
147  for (ip = 0; ip < npix; ip++) {
148  th = (ip - (npix - 1) / 2) * dth;
149  pview[0] = 0;
150  pview[1] = -sin(th);
151  pview[2] = cos(th);
152  nav_get_geonav(sunpos, pos, pview, coef, smat, &xlon, &xlat, &solz,
153  &sola, &senz, &sena);
154  data->lon[i * npix + ip] = xlon;
155  data->lat[i * npix + ip] = xlat;
156  data->senz[i * npix + ip] = senz;
157  data->sena[i * npix + ip] = sena;
158  data->solz[i * npix + ip] = solz;
159  data->sola[i * npix + ip] = sola;
160  // if (ip == 0 || ip == npix/2 || ip == npix-1)
161  // printf("RJH: %d %d %f senz=%f sena=%f solz=%f sola=%f\n", i, ip,
162  // th, data->senz[i * npix + ip],
163  // data->sena[i * npix + ip], data->solz[i * npix + ip],
164  // data->sola[i * npix + ip]);
165  }
166  //if (i % 100 == 0) printf("Calculated Geometry for scan = %d of %d\n",i,nscans);
167  }
168  data->have_nav = 1;
169  return;
170 }
171 
172 int openl1_aviris(filehandle *file) {
173 
174  FILE *ptr;
175  char tag[itemSize];
176  char *val0;
177  char val[itemSize];
178  char *inbasename, *infile;
179  int i, j, k, status, pos;
180  double *indata, *elev;
181  float *indataf;
182  float rotation;
183  int numBands, num;
184  char* result;
185  char line[itemSize];
186  int year, month, day, hour, minute;
187 
188  int isec = 0;
189  double sec;
190 
191  char projStr[1024];
192 
193  aviris_t* data = file->private_data;
194 
195  cdata_(); // initialize global FORTRAN common block data for l_sun call
196 
197  data->isnetcdf = 0;
198  inbasename = getinbasename_av(data->hdrfile);
199  pos = strlen(inbasename);
200  if (pos <= 0) {
201  fprintf(stderr, "-E- %s line %d: Not a avalid AVIRIS file %s\n",
202  __FILE__, __LINE__, data->hdrfile);
203  exit(-1);
204  }
205 
206  data->wave = (double *) malloc(maxBands * sizeof (double));
207  data->fwhm = (double *) malloc(maxBands * sizeof (double));
208  data->gain = (double *) malloc(maxBands * sizeof (double));
209 
210  sscanf(inbasename, "f%2d%2d%2d", &year, &month, &day);
211 
212  if (year >= 92) year = year + 1900;
213  else year = year + 2000;
214 
215  sec = 0;
216  hour = 0;
217  minute = 0;
218  isec = (int) sec;
219 
220  data->month = month;
221  data->day = day;
222 
223  ymdhms2ydmsec(year, month, day, hour, minute, isec,
224  &data->year, &data->doy, &data->msec);
225 
226  sec -= isec;
227  data->msec += sec * 1000;
228 
229  printf("Date of AVIRIS flight: Y-%d M-%d D-%d\n", year, month, day);
230 
231  if ((ptr = fopen(data->hdrfile, "r")) == NULL) {
232  fprintf(stderr, "-E- %s line %d: unable to open %s\n",
233  __FILE__, __LINE__, data->hdrfile);
234  exit(-1);
235  }
236 
237 
238  int numLinesNeeded = 1;
239  int numSamplesNeeded = 1;
240  int bandsNeeded = 1;
241  int waveLengthNeeded = 1;
242  int fwhmNeeded = 1;
243  int utmZoneNeeded = 1;
244  int eastingNeeded = 1;
245  int northingNeeded = 1;
246  int pixelSizeNeeded = 1;
247  int interleaveNeeded = 1;
248  int rotationAngNeeded = 1;
249 
250  // loop metadata
251  result = fgets(line, itemSize, ptr); // Skip ENVI line and set result
252  while ((numLinesNeeded ||
253  numSamplesNeeded ||
254  bandsNeeded ||
255  fwhmNeeded ||
256  pixelSizeNeeded ||
257  utmZoneNeeded ||
258  eastingNeeded ||
259  northingNeeded ||
260  waveLengthNeeded ||
261  rotationAngNeeded ||
262  interleaveNeeded) && result) {
263 
264  result = fgets(line, itemSize, ptr);
265  if (!result) continue;
266  // if(result == NULL) {
267  // fprintf(stderr,"-E- %s line %d: unable to read all of the required metadata from AVIRIS file\n",
268  // __FILE__,__LINE__);
269  // exit(1);
270  // }
271  trimBlanks(line);
272 
273  if ((val0 = checkTagLine(line, "lines"))) {
274  numLinesNeeded = 0;
275  file->nscan = atoi(val0);
276  data->nscan = file->nscan;
277  }
278  if ((val0 = checkTagLine(line, "samples"))) {
279  numSamplesNeeded = 0;
280  file->npix = atoi(val0);
281  data->npix = file->npix;
282  }
283  if ((val0 = checkTagLine(line, "bands"))) {
284  bandsNeeded = 0;
285  numBands = atoi(val0);
286  data->numBands = numBands;
287  if (numBands > AV_MAXBANDS) {
288  fprintf(stderr, "-E- %s line %d: number of bands (%d) from AVIRIS file > maxBands (%d)\n",
289  __FILE__, __LINE__, numBands, AV_MAXBANDS);
290  exit(1);
291  }
292  }
293  if ((val0 = checkTagLine(line, "interleave"))) {
294  interleaveNeeded = 0;
295  if (strstr(val0, "bip")) {
296  data->interleave = BIP;
297  } else if (strstr(val0, "bil")) {
298  data->interleave = BIL;
299  } else {
300  fprintf(stderr, "Interleave = %s is not supported\n", val0);
301  exit(1);
302  }
303  }
304 
305  if ((val0 = checkTagLine(line, "rotation angle"))) {
306  rotationAngNeeded = 0;
307  rotation = atof(val0);
308  data->rotation = rotation;
309  if (rotation > 45)
310  data->eastbyscan = -1;
311  else if (rotation < -45)
312  data->eastbyscan = 1;
313  else
314  data->eastbyscan = 0;
315  }
316 
317  if ((val0 = checkTagLine(line, "pixel size"))) {
318  pixelSizeNeeded = 0;
319  data->pixelSize = atof(val0);
320  }
321  if ((val0 = checkTagLine(line, "Northing"))) {
322  northingNeeded = 0;
323  data->northing = atof(val0);
324  }
325  if ((val0 = checkTagLine(line, "Easting"))) {
326  eastingNeeded = 0;
327  data->easting = atof(val0);
328  }
329  if ((val0 = checkTagLine(line, "UTM zone"))) {
330  utmZoneNeeded = 0;
331  data->utmZone = atoi(val0);
332  }
333 
334  if ((val0 = checkTagLine(line, "wavelength"))) {
335  waveLengthNeeded = 0;
336  i = 0;
337  readWavInfo_jpl(ptr, tag, val);
338  while (i < AV_MAXBANDS && strcmp(tag, "}")) {
339  data->wave[i] = atof(val);
340  readWavInfo_jpl(ptr, tag, val);
341  i++;
342  }
343 
344  if (!strcmp(tag, "}") && i <= AV_MAXBANDS) {
345  data->wave[i] = atof(val);
346  i++;
347  } else { // if (i> AV_MAXBANDS) {
348 
349  fprintf(stderr, "-E- %s line %d: number of bands (%d) from AVIRIS file > AV_MAXBANDS (%d)\n",
350  __FILE__, __LINE__, file->nbands, AV_MAXBANDS);
351  exit(1);
352  }
353  numBands = i - 1;
354  }
355  if ((val0 = checkTagLine(line, "data gain values"))) {
356  data->gain = (double *) malloc(AV_MAXBANDS * sizeof (double));
357  i = 0;
358  readWavInfo_jpl(ptr, tag, val);
359  while (i < AV_MAXBANDS && strcmp(tag, "}")) {
360  data->gain[i] = atof(val);
361  readWavInfo_jpl(ptr, tag, val);
362  i++;
363  }
364 
365  if (!strcmp(tag, "}") && i <= AV_MAXBANDS) {
366  data->gain[i] = atof(val);
367  i++;
368  } else { // if (i> AV_MAXBANDS) {
369 
370  fprintf(stderr, "-E- %s line %d: number of bands (%d) from AVIRIS file > AV_MAXBANDS (%d)\n",
371  __FILE__, __LINE__, file->nbands, AV_MAXBANDS);
372  exit(1);
373  }
374  numBands = i - 1;
375  data->have_gain = 1;
376  }
377 
378 
379  if ((val0 = checkTagLine(line, "fwhm"))) {
380  fwhmNeeded = 0;
381  i = 0;
382  readWavInfo_jpl(ptr, tag, val);
383  while (i < AV_MAXBANDS && strcmp(tag, "}")) {
384  data->fwhm[i] = atof(val);
385  readWavInfo_jpl(ptr, tag, val);
386  i++;
387  }
388  if (!strcmp(tag, "}") && i < AV_MAXBANDS) {
389  data->fwhm[i] = atof(val);
390  i++;
391  } else {
392  fprintf(stderr, "-E- %s line %d: number of bands (%d) from AVIRIS file > AV_MAXBANDS (%d)\n",
393  __FILE__, __LINE__, file->nbands, AV_MAXBANDS);
394  exit(1);
395  }
396  }
397  }
398 
399  fclose(ptr);
400 
401  if ((numLinesNeeded ||
402  numSamplesNeeded ||
403  bandsNeeded ||
404  fwhmNeeded ||
405  waveLengthNeeded)) {
406 
407  fprintf(stderr, "-E- %s line %d: unable to read all of the required metadata from AVIRIS file\n",
408  __FILE__, __LINE__);
409  exit(1);
410  }
411  int nscans = file->nscan;
412  int npix = file->npix;
413 
414  data->sena = (double *) malloc(nscans * npix * sizeof (double));
415  data->senz = (double *) malloc(nscans * npix * sizeof (double));
416  data->solz = (double *) malloc(nscans * npix * sizeof (double));
417  data->sola = (double *) malloc(nscans * npix * sizeof (double));
418  data->utc = (double *) malloc(nscans * npix * sizeof (double));
419  data->alt = (float *) malloc(nscans * sizeof (float));
420 
421  if (data->sena == NULL || data->senz == NULL || data->sola == NULL || data->solz == NULL) {
422  fprintf(stderr, "-E- %s line %d: unable to allocate sensor and solar angle data for AVIRIS\n",
423  __FILE__, __LINE__);
424  exit(1);
425  }
426 
427  if (data->navfile[0] != '\0') get_aviris_nav_data(data->navfile, nscans, npix, data);
428 
429  if (data->gainfile[0] != '\0') {
430  if ((ptr = fopen(data->gainfile, "r")) == NULL) {
431  fprintf(stderr, "-E- %s line %d: unable to open %s\n",
432  __FILE__, __LINE__, data->gainfile);
433  exit(-1);
434 
435  }
436  i = 0;
437  while ((result = fgets(line, itemSize, ptr)) && i < numBands) {
438 
439  if (result == NULL) {
440  fprintf(stderr, "-E- %s line %d: unable to read all of the gain data from AVIRIS gain file\n",
441  __FILE__, __LINE__);
442  exit(1);
443  }
444  trimBlanks(line);
445 
446  sscanf(line, "%lf", &data->gain[i]);
447  i++;
448  }
449  data->have_gain = 1;
450  }
451 
452  if (data->navfile[0] == '\0') {
453  // Get info about the WGS84 data
454  // Get the lat/lon/elev
455  numLinesNeeded = 1;
456  numSamplesNeeded = 1;
457 
458  infile = malloc((pos + strlen("_obs.hdr")) * sizeof (char));
459  strcpy(infile, inbasename);
460  strcat(infile, "_obs.hdr");
461 
462  if ((ptr = fopen(infile, "r")) == NULL) {
463  fprintf(stderr, "-E- %s line %d: unable to open %s\n",
464  __FILE__, __LINE__, infile);
465  exit(-1);
466 
467  }
468  // loop metadata
469  while (numLinesNeeded ||
470  numSamplesNeeded) {
471 
472  readNextLine_jpl(ptr, tag, val);
473  // skip blank lines
474  if (tag[0] == 0)
475  continue;
476 
477  // get date
478  if (!strcmp(tag, "lines")) {
479  numLinesNeeded = 0;
480  data->wgs_nscan = atoi(val);
481  }
482  if (!strcmp(tag, "samples")) {
483  numSamplesNeeded = 0;
484  data->wgs_npix = atoi(val);
485  }
486  }
487 
488  fclose(ptr);
489 
490  //Get the lat/lon/elev
491 
492  infile = malloc((pos + strlen("_lonlat_eph")) * sizeof (char));
493  strcpy(infile, inbasename);
494  strcat(infile, "_lonlat_eph");
495 
496  printf("Reading lon/lat/elev information from file %s\n", infile);
497 
498  num = 6;
499  elev = (double *) malloc(data->wgs_nscan * sizeof (double));
500  indata = (double *) malloc(data->wgs_nscan * num * sizeof (double));
501 
502  if (elev == NULL || indata == NULL) {
503  fprintf(stderr, "-E- %s line %d: unable to allocate lat/lon data for aviris\n",
504  __FILE__, __LINE__);
505  exit(1);
506  }
507 
508  if ((ptr = fopen(infile, "rb")) == NULL) {
509  fprintf(stderr, "-E- %s line %d: unable to open %s\n",
510  __FILE__, __LINE__, infile);
511  exit(-1);
512 
513  }
514  status = fread(indata, sizeof (double), data->wgs_nscan*num, ptr);
515  if (status != data->wgs_nscan * num) {
516  printf("Wrong data read size: want %d got %d in file %s\n", data->wgs_nscan*num, status, infile);
517  exit(1);
518  }
519 
520  i = 0;
521 
522  gsl_spline *spline = gsl_spline_alloc(gsl_interp_cspline, data->wgs_nscan);
523 
524  double *dist = (double *) calloc(data->wgs_nscan, sizeof (double));
525  double *xlon = (double *) calloc(data->wgs_nscan, sizeof (double));
526  double *xlat = (double *) calloc(data->wgs_nscan, sizeof (double));
527 
528  data->spl_acc = gsl_interp_accel_alloc();
529  data->lon0 = indata[0];
530  data->lat0 = indata[1];
531  data->distmin = 999;
532  data->distmax = -999;
533  while (i < data->wgs_nscan * num) {
534  j = i / num;
535  xlon[j] = indata[i];
536  xlat[j] = indata[i + 1];
537  elev[j] = indata[i + 2];
538  dist[j] = (double) angular_distance((double) xlat[j], (double) xlon[j], (double) data->lat0, (double) data->lon0);
539  i += num;
540  }
541  i = num;
542  // Sort distances and corresponding elevation values
543  gsl_sort2(dist, 1, elev, 1, data->wgs_nscan);
544  data->distmin = dist[0];
545  data->distmax = dist[data->wgs_nscan - 2];
546 
547  // Initiate spline
548  gsl_spline_init(spline, dist, elev, data->wgs_nscan);
549 
550  data->spline = spline;
551 
552  free(indata);
553  fclose(ptr);
554 
555 
556  // Get the sensor and solar data
557 
558  num = 10;
559  indataf = (float *) malloc(file->npix * sizeof (float)*num);
560 
561  if (data->sena == NULL || data->senz == NULL || data->sola == NULL || data->solz == NULL || indataf == NULL) {
562  fprintf(stderr, "-E- %s line %d: unable to allocate sensor and solar angle data for AVIRIS\n",
563  __FILE__, __LINE__);
564  exit(1);
565  }
566 
567  infile = malloc((pos + strlen("_obs_ort")) * sizeof (char));
568  strcpy(infile, inbasename);
569  strcat(infile, "_obs_ort");
570 
571  printf("Reading sensor and solar angles information from file %s\n", infile);
572 
573  if ((ptr = fopen(infile, "rb")) == NULL) {
574  fprintf(stderr, "-E- %s line %d: unable to open %s\n",
575  __FILE__, __LINE__, infile);
576  exit(-1);
577 
578  }
579  for (j = 0; j < file->nscan; j++) {
580  status = fread(indataf, sizeof (float), num * file->npix, ptr);
581  if (status != num * file->npix) {
582  fprintf(stderr, "-E- %s line %d: AVIRIS Wrong sensor and solar data read size: want %d got %d\n",
583  __FILE__, __LINE__, file->npix*num, status);
584  exit(1);
585  }
586 
587  for (k = 0; k < file->npix; k++) {
588  data->sena[j * file->npix + k] = indataf[1 * file->npix + k];
589  data->senz[j * file->npix + k] = indataf[2 * file->npix + k];
590  data->sola[j * file->npix + k] = indataf[3 * file->npix + k];
591  data->solz[j * file->npix + k] = indataf[4 * file->npix + k];
592  data->utc [j * file->npix + k] = indataf[9 * file->npix + k];
593  }
594  }
595 
596  free(indataf);
597  fclose(ptr);
598 
599  PJ *pj;
600  sprintf(projStr, "+proj=utm +zone=%d +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
601  data->utmZone);
602 
603  // init the proj4 projections
604  pj = proj_create_crs_to_crs(PJ_DEFAULT_CTX,
605  projStr,
606  "+proj=longlat +ellps=WGS84 +datum=WGS84",
607  NULL);
608  if(pj == NULL) {
609  printf("Error - AVIRIS first PROJ projection failed to init\n");
610  exit(1);
611  }
612  data->pj = proj_normalize_for_visualization(PJ_DEFAULT_CTX, pj);
613  if(data->pj == NULL) {
614  printf("Error - AVIRIS visualization PROJ projection failed to init\n");
615  exit(1);
616  }
617  proj_destroy(pj);
618 
619  free(infile);
620  } // no input navfile
621 
622 
623  // Get the gain data
624  if (!data->have_gain) {
625  infile = malloc((pos + strlen(".gain")) * sizeof (char));
626  strcpy(infile, inbasename);
627  strcat(infile, ".gain");
628 
629  printf("Attempting to read gain information from file %s\n", infile);
630 
631  if ((ptr = fopen(infile, "r")) == NULL) {
632  fprintf(stderr, "-E- %s line %d: unable to open %s\n Will assume gains.\n",
633  __FILE__, __LINE__, infile);
634  for (k = 0; k < numBands; k++) {
635  if (k < 110) data->gain[i] = 300;
636  else if (k < 160) data->gain[i] = 600;
637  else data->gain[i] = 1200;
638 
639  }
640  } else {
641 
642  if (data->gain == NULL) {
643  fprintf(stderr, "-E- %s line %d: unable to allocate gain data for AVIRIS\n",
644  __FILE__, __LINE__);
645  exit(1);
646  }
647  for (i = 0; i < numBands && fscanf(ptr, "%lf %d", (data->gain + i), &k); i++) {
648  // printf("gain: %lf %d\n",*(data->gain+i),k);
649  }
650  fclose(ptr);
651  }
652 
653  data->have_gain = 1;
654  free(infile);
655  }
656  infile = malloc(FILENAME_MAX * sizeof (char));
657  if (data->imgfile[0] == '\0') {
658  strcpy(infile, inbasename);
659  strcat(infile, "_sc01_ort_img");
660  } else {
661  strcpy(infile, data->imgfile);
662  }
663  printf("Opening AVIRIS image file %s\n", infile);
664 
665  if ((data->av_fp = fopen(infile, "rb")) == NULL) {
666  fprintf(stderr, "-E- %s line %d: unable to open %s\n",
667  __FILE__, __LINE__, infile);
668  exit(-1);
669 
670  }
671 
672  return (0);
673 
674 }
675 
676 int readl1_aviris(filehandle *file, int32_t recnum, l1str *l1rec)
677 /*
678  * fill standard record with L1B line of data
679  */ {
680 
681  static double last_good_hour = 18;
682  static int firstCall = 1;
683  double sec;
684  int hour, minute;
685  double dist;
686  int npix = file->npix, ip, ib, ipb;
687  static int swap, *ibndx, *ipbndx;
688  static float *Lt;
689 
690 
691  aviris_t* data = (aviris_t*) file->private_data;
692  int ipb_av, ibl1;
693 
694  if (firstCall) {
695  if (want_verbose)
696  printf("l1file->nbands = %d\n", (int) file->nbands);
697  firstCall = 0;
698 
699  for (ip = 0; ip < npix; ip++) {
700  l1rec->pixnum[ip] = ip;
701  l1rec->flags[ip] = 0;
702  }
703 
704  if (endianess() == 1)
705  swap = 1;
706  else
707  swap = 0;
708 
709  Lt = (float*) malloc(npix * data->numBands * sizeof (float));
710  if (!Lt) {
711  fprintf(stderr, "-E- %s line %d: Out of Memory allocating buffer array in readl1_aviris.\n",
712  __FILE__, __LINE__);
713  exit(1);
714 
715  }
716  ipbndx = (int*) malloc(npix * file->nbands * sizeof (int));
717  if (!ipbndx) {
718  fprintf(stderr, "-E- %s line %d: Out of Memory allocating buffer array in readl1_aviris.\n",
719  __FILE__, __LINE__);
720  exit(1);
721 
722  }
723  ibndx = (int*) malloc(file->nbands * sizeof (int));
724  if (!ibndx) {
725  fprintf(stderr, "-E- %s line %d: Out of Memory allocating buffer array in readl1_aviris.\n",
726  __FILE__, __LINE__);
727  exit(1);
728 
729  }
730 
731  ibl1 = 0;
732  for (ib = 0; ib < 31; ib++) {
733  ibndx[ibl1] = ib;
734  ibl1++;
735  }
736  for (ib = 33; ib < 95; ib++) {
737  ibndx[ibl1] = ib;
738  ibl1++;
739  }
740  for (ib = 97; ib < 159; ib++) {
741  ibndx[ibl1] = ib;
742  ibl1++;
743  }
744  for (ib = 161; ib < 206; ib++) {
745  ibndx[ibl1] = ib;
746  ibl1++;
747  }
748  file->fwhm = (float*) malloc(data->numBands * sizeof (float));
749  if (!file->fwhm) {
750  fprintf(stderr, "-E- %s line %d: Out of Memory allocating fwhm array in readl1_aviris.\n",
751  __FILE__, __LINE__);
752  exit(1);
753 
754  }
755  for (ib = 0; ib < ibl1; ib++) file->fwhm[ib] = data->fwhm[ibndx[ib]] / 1000.; // convert from nm to microns
756 
757  // create an index array to map the Lt's to the wavelength indexes actually used
758  for (ip = 0; ip < npix; ip++) {
759  ibl1 = 0;
760  for (ib = 0; ib < 31; ib++) {
761  ipb = ip * file->nbands + ibl1;
762  switch (data->interleave) {
763  case BIP:
764  ipb_av = ip * data->numBands + ib;
765  break;
766  case BIL:
767  ipb_av = ib * npix + ip;
768  break;
769  }
770  ipbndx[ipb] = ipb_av;
771  ibl1++;
772  }
773  for (ib = 33; ib < 95; ib++) {
774  ipb = ip * file->nbands + ibl1;
775  switch (data->interleave) {
776  case BIP:
777  ipb_av = ip * data->numBands + ib;
778  break;
779  case BIL:
780  ipb_av = ib * npix + ip;
781  break;
782  }
783  ipbndx[ipb] = ipb_av;
784  ibl1++;
785  }
786  for (ib = 97; ib < 159; ib++) {
787  ipb = ip * file->nbands + ibl1;
788  switch (data->interleave) {
789  case BIP:
790  ipb_av = ip * data->numBands + ib;
791  break;
792  case BIL:
793  ipb_av = ib * npix + ip;
794  break;
795  }
796  ipbndx[ipb] = ipb_av;
797  ibl1++;
798  }
799  for (ib = 161; ib < 206; ib++) {
800  ipb = ip * file->nbands + ibl1;
801  switch (data->interleave) {
802  case BIP:
803  ipb_av = ip * data->numBands + ib;
804  break;
805  case BIL:
806  ipb_av = ib * npix + ip;
807  break;
808  }
809  ipbndx[ipb] = ipb_av;
810  ibl1++;
811  }
812  }
813 
814  }
815 
816  // set information about data
817  l1rec->npix = file->npix;
818  l1rec->l1file->sensorID = file->sensorID;
819 
820  if (!data->have_nav) {
821 
822  int k = 0;
823  while ((hour = (int) (data->utc[recnum * npix + k])) < 0 && k < npix) k++;
824 
825  if (hour < 0) hour = last_good_hour;
826 
827  last_good_hour = hour;
828 
829  minute = (data->utc[recnum * npix + k] - hour)*60;
830  sec = ((data->utc[recnum * npix + k] - hour)*60 - minute)*60;
831 
832  l1rec->scantime = ymds2unix(data->year, data->month, data->day, (hour * 3600 + minute * 60 + sec));
833 
834  PJ_COORD c, c_out;
835 
836  // set default z and t
837  c.xyzt.z = 0.0;
838  c.xyzt.t = HUGE_VAL;
839 
840  for (ip = 0; ip < npix; ip++) {
841 
842  l1rec->pixnum[ip] = ip;
843 
844  c.xy.x = data->easting + ip * cos(deg2rad(data->rotation)) * data->pixelSize - recnum * sin(deg2rad(data->rotation)) * data->pixelSize; // starts in upper left corner
845  c.xy.y = data->northing - ip * sin(deg2rad(data->rotation)) * data->pixelSize - recnum * cos(deg2rad(data->rotation)) * data->pixelSize;
846  c_out = proj_trans(data->pj, PJ_FWD, c);
847 
848  if(isfinite(c_out.xy.x) && isfinite(c_out.xy.y)) {
849  l1rec->lon[ip] = c_out.xy.x;
850  l1rec->lat[ip] = c_out.xy.y;
851  } else {
852  l1rec->lon[ip] = -999.0;
853  l1rec->lat[ip] = -999.0;
854  }
855 
856  if (l1rec->lon[ip] < -181.0 || l1rec->lon[ip] > 181.0 ||
857  l1rec->lat[ip] < -91.0 || l1rec->lat[ip] > 91.0)
858  l1rec->navfail[ip] = 1;
859 
860  if (data->senz[recnum * npix + ip] > SKIP)
861  l1rec->senz[ip] = data->senz[recnum * npix + ip];
862  else
863  l1rec->senz[ip] = getValidAngle(&data->senz[recnum * npix], npix, SKIP);
864 
865  if (data->sena[recnum * npix + ip] > SKIP)
866  l1rec->sena[ip] = data->sena[recnum * npix + ip];
867  else
868  l1rec->sena[ip] = getValidAngle(&data->sena[recnum * npix], npix, SKIP);
869 
870  if (data->solz[recnum * npix + ip] > SKIP)
871  l1rec->solz[ip] = data->solz[recnum * npix + ip];
872  else
873  l1rec->solz[ip] = getValidAngle(&data->solz[recnum * npix], npix, SKIP);
874 
875  if (data->sola[recnum * npix + ip] > SKIP)
876  l1rec->sola[ip] = data->sola[recnum * npix + ip];
877  else
878  l1rec->sola[ip] = getValidAngle(&data->sola[recnum * npix], npix, SKIP);
879 
880 
881  }
882  // find interpolated elevation from wgs-84 lat/lon
883  ip = npix / 2;
884  dist = (double) angular_distance((double) l1rec->lat[ip], (double) l1rec->lon[ip], (double) data->lat0, (double) data->lon0);
885  if (dist > data->distmax) {
886  printf("lat/lon > range of wgs coordinates - using altitude of nearest neighbor\n");
887  dist = data->distmax;
888  } else if (dist < data->distmin) {
889  printf("lat/lon < range of wgs coordinates - using altitude of nearest neighbor\n");
890  dist = data->distmin;
891  }
892  l1rec->alt = (float) gsl_spline_eval(data->spline, dist, data->spl_acc) / 1000.; // and convert to km
893 
894  } else { // have_nav
895  l1rec->alt = data->alt[recnum];
896  for (ip = 0; ip < npix; ip++) {
897  l1rec->senz[ip] = data->senz[recnum * npix + ip];
898  l1rec->sena[ip] = data->sena[recnum * npix + ip];
899  l1rec->solz[ip] = data->solz[recnum * npix + ip];
900  l1rec->sola[ip] = data->sola[recnum * npix + ip];
901  l1rec->lon[ip] = data->lon[recnum * npix + ip];
902  l1rec->lat[ip] = data->lat[recnum * npix + ip];
903  if (l1rec->lon[ip] < -181.0 || l1rec->lon[ip] > 181.0 ||
904  l1rec->lat[ip] < -91.0 || l1rec->lat[ip] > 91.0)
905  l1rec->navfail[ip] = 1;
906  }
907  hour = (int) (data->utc[recnum]);
908  minute = (data->utc[recnum] - hour) * 60;
909  sec = ((data->utc[recnum] - hour) * 60 - minute) * 60;
910  l1rec->scantime = ymds2unix(data->year, data->month, data->day,
911  (hour * 3600. + minute * 60. + sec));
912  }
913  readBinScanLine_int2(Lt, recnum, l1rec->npix, data->gain, data->numBands, data->interleave, swap, data->av_fp);
914 
915  for (ipb = 0; ipb < npix * file->nbands; ipb++)
916  l1rec->Lt[ipb] = Lt[ipbndx[ipb]];
917 
918  return (LIFE_IS_GOOD);
919 }
920 
921 int closel1_aviris(filehandle *file) {
922  aviris_t* data = (aviris_t*) file->private_data;
923 
924  // undo what open allocated
925 
927  free(file->private_data);
928 
929  return 0;
930 }
931 
932 
#define SKIP
Definition: l1_aviris.c:19
int j
Definition: decode_rs.h:73
int32_t day
int status
Definition: l1_czcs_hdf.c:32
real(single), dimension(:,:), allocatable longitude
void nav_gd_orient(float *pos, float *vel, float *att, float *smat[], float *coef)
Definition: get_zenaz.c:160
#define NULL
Definition: decode_rs.h:63
void nav_get_geonav(float *sunr, float *pos, float *pview, float *coef, float *smat[], float *xlon, float *xlat, float *solz, float *sola, float *senz, float *sena)
Definition: get_zenaz.c:310
const double deg2rad
read l1rec
void trimBlanks(char *str)
Definition: trimBlanks.c:10
real(single), dimension(:,:), allocatable latitude
subroutine spline(s, x, y, n, in, t, il, iu, vl, vu, e, u)
Definition: phs.f:1348
void readNextLine_jpl(FILE *fp, char *tag, char *val)
Definition: jplaeriallib.c:90
float32 * pos
Definition: l1_czcs_hdf.c:35
float * lat
int readl1_aviris(filehandle *file, int32_t recnum, l1str *l1rec)
Definition: l1_aviris.c:676
#define AV_MAXBANDS
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 endianess(void)
determine endianess
Definition: endianess.c:10
character(len=1000) if
Definition: names.f90:13
#define LIFE_IS_GOOD
Definition: passthebuck.h:4
char * getinbasename_av(char *file)
Definition: jplaeriallib.c:17
#define BIL
int readBinScanLine_int2(float *Lt, int32_t recnum, int32_t npix, double *gain, int nbands, int interleave, int swap, FILE *ptr)
Definition: jplaeriallib.c:307
read recnum
#define BIP
void get_aviris_nav_data(char *navfile, int32_t nscans, int32_t npix, aviris_t *data)
Definition: l1_aviris.c:66
void cdata_()
int want_verbose
void unix2yds(double usec, short *year, short *day, double *secs)
int openl1_aviris(filehandle *file)
Definition: l1_aviris.c:172
integer, parameter double
instead the metadata field ProcessingEnvinronment is filled in from the output of a call to the POSIX compliant function uname from within the L1B code A small bug in L1B_Tables an incorrect comparison of RVS coefficients for TEBs to RVS coefficients for RSBs was being made This was replaced with a comparison between TEB coefficients This error never resulted in an incorrect RVS correction but did lead to recalculating the coefficients for each detector in a thermal band even if the coefficients were the same for all detectors To reduce to overall size of the reflective LUT HDF fill values were eliminated from all LUTs previously dimensioned where and where NUM_TIMES is the number of time dependent table pieces In Preprocess a small error where the trailing dropped scan counter was incremented when the leading dropped scan counter should have been was fixed This counter is internal only and is not yet used for any chiefly to casting of were added to make it LINUX compatible Output of code run on LINUX machines displays differences of at most scaled sector rotation
Definition: HISTORY.txt:575
aviris_t * createPrivateData_aviris(int numBands)
Definition: l1_aviris.c:30
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
float xlon[LAC_PIXEL_NUM]
Definition: l1a_seawifs.c:93
void ymdhms2ydmsec(int yy, int mm, int dd, int hh, int mn, int sc, int32_t *year, int32_t *day, int32_t *msec)
Definition: ydhms2ydmsec.c:3
int closel1_aviris(filehandle *file)
Definition: l1_aviris.c:921
char * checkTagLine(char *line, char *tag)
Definition: jplaeriallib.c:433
double angular_distance(double lat1, double lon1, double lat2, double lon2)
Definition: read_prism.c:537
float * lon
double ymds2unix(short year, short month, short day, double secs)
for(i=0;i< NROOTS;i++) s[i]
Definition: decode_rs.h:85
void nav_get_pos(float lat, float lon, float alt, float *p)
Definition: get_zenaz.c:134
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
double getValidAngle(double *ang, int32_t npix, int32_t skip)
Definition: jplaeriallib.c:423
void freePrivateData_aviris(aviris_t *data)
Definition: l1_aviris.c:53
int i
Definition: decode_rs.h:71
msiBandIdx val
Definition: l1c_msi.cpp:34
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
#define maxBands
int sunpos(double tjd, double r[3], char **errstr)
int k
Definition: decode_rs.h:73
void nav_get_vel(float ilat, float mlat, float ilon, float mlon, float *vel)
Definition: get_zenaz.c:105
int npix
Definition: get_cmp.c:27
void l_sun_(int *iyr, int *iday, double *sec, float *sunr, float *rs)
void readWavInfo_jpl(FILE *fp, char *tag, char *val)
Definition: jplaeriallib.c:65