Due to the lapse in federal government funding, NASA is not updating this website. We sincerely regret this inconvenience.
NASA Logo
Ocean Color Science Software

ocssw V2022
avirisbil2ncdf.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <string.h>
5 #include <unistd.h>
6 
7 #include <sstream>
8 #include <iomanip>
9 #include <stdint.h>
10 #include <iostream>
11 #include <fstream>
12 
13 #include "cdl_utils.h"
14 #include "netcdf.h"
15 #include "nc4utils.h"
16 #include "nc_gridutils.h"
17 #include "aviris.h"
18 #include <gsl/gsl_errno.h>
19 #include <gsl/gsl_spline.h>
20 #include <gsl/gsl_sort_double.h>
21 #include <timeutils.h>
22 
23 #define FILL -32767
24 #define BIP 0
25 #define BIL 1
26 #define SENSOR "aviris"
27 #define CDLFILE "AVIRIS_Level-1B_Data_Structure.cdl"
28 #define NBANDS 200 // number of output AVIRIS bands
29 
30 
31 using namespace std;
32 
33 
34 #define VERSION "1.00"
35 
36 size_t interpLt(size_t startJ, size_t npixels, size_t k, size_t nbMax,
37  float ncdfWavelength, size_t iwave, aviris4ocia_t* data,
38  gsl_interp_accel* acc, float* Lt) {
39  size_t j, n;
40  size_t i0 = startJ, i1 = startJ + 5;
41  float minWave, maxWave;
42 
43  double* x = (double*) (calloc(nbMax, sizeof (double)));
44  double* y = (double*) (calloc(nbMax, sizeof (double)));
45  size_t iter = 0;
46  while (i0 >= 0 && i1 < nbMax) {
47  n = 0;
48  minWave = 99999;
49  maxWave = -1;
50  for (j = i0; j < i1; j++) {
51  if (data->Lt[j * npixels + k] > 0) {
52  x[n] = data->wave[j];
53  y[n] = data->Lt[j * npixels + k];
54  n++;
55  if (minWave > data->wave[j]) minWave = data->wave[j];
56  if (maxWave < data->wave[j]) maxWave = data->wave[j];
57  }
58  }
59 
60  if (n > 2 && minWave <= ncdfWavelength && maxWave >= ncdfWavelength) break;
61  if (minWave > ncdfWavelength || n < 3)
62  i0--;
63  if (maxWave < ncdfWavelength || n < 3)
64  i1++;
65  iter++;
66  }
67  if (n > 2) {
68  // Allocate space for spline
69  gsl_spline* spline = gsl_spline_alloc(gsl_interp_cspline, n);
70  gsl_sort2(x, 1, y, 1, n);
71  if (ncdfWavelength > x[0]) {
72  // Sort wavelengths and corresponding Lt values
73  gsl_sort2(x, 1, y, 1, n);
74  // Initiate spline
75  gsl_spline_init(spline, x, y, n);
76  // Generate interpolated values
77  double yi = gsl_spline_eval(spline, ncdfWavelength, acc);
78  Lt[iwave * npixels + k] = yi;
79  } else {
80  Lt[iwave * npixels + k] = -9999;
81  }
82  iwave++;
83  gsl_spline_free(spline);
84  }
85  free(x);
86  free(y);
87  return iwave;
88 }
89 
90 // Modification history:
91 // Programmer Organization Date Ver Description of change
92 // ---------- ------------ ---- --- ---------------------
93 // Joel Gales FutureTech 12/18/14 0.01 Original development
94 // Joel Gales FutureTech 01/12/15 0.10 Add support for writing
95 // interpolated ORCA Lt values
96 // and navigation
97 // Rick Healy SAIC 06/06/16 1.00 Integrated L2gen L1 reader for Aviris
98 
99 int main(int argc, char* argv[]) {
100  int status;
101  size_t sline = 0, eline = 0;
102  char filename[FILENAME_MAX], hdrfile[FILENAME_MAX], imgfile[FILENAME_MAX],
103  navfile[FILENAME_MAX], gainfile[FILENAME_MAX];
104  char *filedir;
105  int interleave = BIL;
106  double scantime_first, scantime_last;
107  static int first_good_scantime = 0;
108  char isodatetime_first[30], isodatetime_last[30];
109 
110  cout << "avirisbil2ncdf " << VERSION << " ("
111  << __DATE__ << " " << __TIME__ << ")" << endl;
112 
113  if (argc < 3) {
114  cout << endl <<
115  "avirisbil2ncdf input_AVIRIS_file output_AVIRIS_file <sline (default=0)> <eline (default=last row,0=last row)> <img file(optional)> <nav file(optional)> <gain file(optional)>"
116  << endl;
117  return 0;
118  }
119 
120  if (argc >= 4) {
121  sscanf(argv[3], "%ld", &sline);
122  if (sline < 0) sline = 0;
123  }
124 
125  if (argc >= 5) {
126  sscanf(argv[4], "%ld", &eline);
127  if (eline < 0) eline = 0;
128  }
129  if (argc >= 6) {
130  sscanf(argv[5], "%s", imgfile);
131  if (eline < 0) eline = 0;
132  }
133  if (argc >= 7) {
134  sscanf(argv[6], "%s", navfile);
135  if (eline < 0) eline = 0;
136  }
137  if (argc >= 8) {
138  sscanf(argv[7], "%s", gainfile);
139  if (eline < 0) eline = 0;
140  }
141  // aviris4orca_t *&data;
142 
143  if ((filedir = getenv("OCDATAROOT")) == NULL) {
144  printf("-E- %s: OCDATAROOT env variable undefined.\n", __FILE__);
145  return (-1);
146  }
147  strcpy(filename, filedir);
148 
149  strcat(filename, "/");
150  strcat(filename, SENSOR);
151  strcat(filename, "/");
152 
153  strcat(filename, CDLFILE);
154 
155  aviris4ocia_t **data, *temp;
156  float fwhm[NBANDS];
157 
158  if (!checkAvProcessFile(argv[1], hdrfile, imgfile, navfile, gainfile, FILENAME_MAX))
159  strncpy(hdrfile, argv[1], FILENAME_MAX);
160 
161  data = (aviris4ocia_t **) malloc(sizeof (aviris4ocia_t *));
162  temp = open_aviris(hdrfile, imgfile, navfile, gainfile, data);
163  size_t ip, nscans, npixels = temp->npix;
164 
165  if (eline <= 0) eline = temp->nscans;
166 
167  nscans = eline - sline;
168 
169  int ncid, grpID;
170  //char** dim_names, uint32_t* dim_size, size_t n_dims
171  const char *dimNames[] = {"number_of_lines", "pixels_per_line", "number_of_bands"};
172  size_t dimSize[] = {nscans, npixels, NBANDS};
173  size_t n_dims = 3;
174  // Create ORCA output file
175  static ncdfFile ncdffile;
176  ncdffile.cdlCreateDim(argv[2], filename, dimNames, dimSize, n_dims, nscans);
177 
178  // nc_def_dim(orcafile.ncid, "number_of_lines", nscans, &dimid[0]);
179  // nc_def_dim(orcafile.ncid, "pixels_per_line", nscans, &dimid[1]);
180  //
181  // Copy AVIRIS nav fields to ORCA
182  //
183  ncid = ncdffile.getNcid();
184 
185  size_t nbands_av = temp->numBands;
186  size_t nbands_aviris = NBANDS;
187 
188  size_t n = 0, iwave = 0;
189  istringstream istr;
190  string str;
191  static int *ibndx, *ipbndx;
192  int ipb_av, ib, ibl1, ipb;
193 
194 
195  // Allocate space for AVIRIS Lt (short) values
196  gsl_interp_accel *acc = gsl_interp_accel_alloc();
197 
198  float *Lt = (float *) calloc(npixels*nbands_aviris, sizeof (float));
199  float *ncdfWavelength = (float *) calloc(nbands_aviris, sizeof (float));
200  double* utc = (double*) (calloc(nscans, sizeof (double)));
201  size_t j;
202 
203  ipbndx = (int*) malloc(npixels * nbands_aviris * sizeof (int));
204  if (!ipbndx) {
205  fprintf(stderr, "-E- %s line %d: Out of Memory allocating buffer array in readl1_aviris.\n",
206  __FILE__, __LINE__);
207  exit(1);
208 
209  }
210  ibndx = (int*) malloc(nbands_aviris * sizeof (int));
211  if (!ibndx) {
212  fprintf(stderr, "-E- %s line %d: Out of Memory allocating buffer array in readl1_aviris.\n",
213  __FILE__, __LINE__);
214  exit(1);
215 
216  }
217 
218  //use only the selected wavelengths
219  ibl1 = 0;
220  for (ib = 0; ib < 31; ib++) {
221  ibndx[ibl1] = ib;
222  ibl1++;
223  }
224  for (ib = 33; ib < 95; ib++) {
225  ibndx[ibl1] = ib;
226  ibl1++;
227  }
228  for (ib = 97; ib < 159; ib++) {
229  ibndx[ibl1] = ib;
230  ibl1++;
231  }
232  for (ib = 161; ib < 206; ib++) {
233  ibndx[ibl1] = ib;
234  ibl1++;
235  }
236 
237  // create an index array to map the Lt's to the wavelength indexes actually used
238  for (ip = 0; ip < npixels; ip++) {
239  ibl1 = 0;
240  for (ib = 0; ib < 31; ib++) {
241  ipb = ip * nbands_aviris + ibl1;
242  switch (interleave) {
243  case BIP:
244  ipb_av = ip * nbands_av + ib;
245  break;
246  case BIL:
247  ipb_av = ib * npixels + ip;
248  break;
249  }
250  ipbndx[ipb] = ipb_av;
251  ibl1++;
252  }
253  for (ib = 33; ib < 95; ib++) {
254  ipb = ip * nbands_aviris + ibl1;
255  switch (interleave) {
256  case BIP:
257  ipb_av = ip * nbands_av + ib;
258  break;
259  case BIL:
260  ipb_av = ib * npixels + ip;
261  break;
262  }
263  ipbndx[ipb] = ipb_av;
264  ibl1++;
265  }
266  for (ib = 97; ib < 159; ib++) {
267  ipb = ip * nbands_aviris + ibl1;
268  switch (interleave) {
269  case BIP:
270  ipb_av = ip * nbands_av + ib;
271  break;
272  case BIL:
273  ipb_av = ib * npixels + ip;
274  break;
275  }
276  ipbndx[ipb] = ipb_av;
277  ibl1++;
278  }
279  for (ib = 161; ib < 206; ib++) {
280  ipb = ip * nbands_aviris + ibl1;
281  switch (interleave) {
282  case BIP:
283  ipb_av = ip * nbands_av + ib;
284  break;
285  case BIL:
286  ipb_av = ib * npixels + ip;
287  break;
288  }
289  ipbndx[ipb] = ipb_av;
290  ibl1++;
291  }
292  }
293 
294  grpID = ncdffile.getGid("observation_data");
295 
296  for (size_t iscan = sline; iscan < eline; iscan++) {
297 
298 
299  // Read AVIRIS Lt's for this scan
300  if (read_aviris(temp, iscan)) {
301 
302  cout << "Can't read file " << argv[1] << endl;
303  exit(1);
304 
305  }
306 
307  for (ip = 0; ip < npixels; ip++)
308  for (iwave = 0; iwave < nbands_aviris; iwave++) Lt[iwave * npixels + ip] = FILL;
309 
310  if ((iscan % 100) == 0) {
311  cout << "Processing scan: " << iscan << " out of " << nscans << endl;
312  printf("year=%d doy=%d msec=%d month=%d day=%d hour=%d min=%d sec=%f\n ", temp->year, temp->doy, temp->msec, temp->month, temp->day, temp->hour, temp->min, temp->sec);
313  }
314  // For each pixel in scan ...
315  for (size_t k = 0; k < npixels; k++) {
316 
317  // Get number of good AVIRIS wavelengths for each pixel
318  n = 0;
319  j = 0;
320  for (j = 0; j < nbands_av; j++) {
321  if (temp->Lt[j * npixels + k] > 0) n++;
322  }
323 
324  // Bail if no good AVIRIS Lt values
325  if (n == 0) continue;
326 
327 
328  // Generate x & y arrays for spline
329  // x - AVIRIS wavelengths
330  // y - AVIRIS Lt values
331  iwave = 0;
332  for (j = 0; j < nbands_aviris; j++) {
333  ipb = k * nbands_aviris + j;
334  if (temp->Lt[ipbndx[ipb]] > 0) {
335  Lt[iwave * npixels + k] = temp->Lt[ipbndx[ipb]];
336  } else {
337  Lt[iwave * npixels + k] = FILL;
338  }
339  ncdfWavelength[iwave] = temp->wave[ibndx[j]];
340  fwhm[iwave] = temp->fwhm[ibndx[j]];
341 
342  iwave++;
343  }
344 
345 
346  } // pixel loop
347 
348  if (NBANDS != iwave) {
349  printf("Oops, something's wrong iwave (%d) != nbands (%d) \n", (int) iwave, NBANDS);
350  exit(-1);
351  }
352  // Write Lt's
353  // for (size_t iwave=0; iwave<nbands_aviris; iwave++ ) {
354  int varID;
355 
356  // printf("Lambda(%d) = %d\n",iwave+1,(int)(orcaWavelength[iwave]+.5));
357  status = nc_inq_varid(grpID, "Lt", &varID);
358  check_err(status, __LINE__, __FILE__);
359 
360  size_t start[3] = {0, iscan, 0};
361  size_t count[3] = {nbands_aviris, 1, npixels};
362  status = nc_put_vara_float(grpID, varID, start, count,
363  &Lt[0]);
364  check_err(status, __LINE__, __FILE__);
365  // }
366 
367  utc[iscan] = temp->scantime;
368  //if (utc[iscan]>0) printf("utc=%f\n",utc[iscan]);
369 
370  if (temp->scantime > 0) {
371  scantime_last = temp->scantime;
372  if (!first_good_scantime) {
373  first_good_scantime = 1;
374  scantime_first = temp->scantime;
375  }
376  }
377 
378  } // scan loop
379 
380  if (scantime_first < scantime_last) {
381  strncpy(isodatetime_first, unix2isodate(scantime_first, 'G'), 30);
382  strncpy(isodatetime_last, unix2isodate(scantime_last, 'G'), 30);
383  } else {
384  strncpy(isodatetime_last, unix2isodate(scantime_first, 'G'), 30);
385  strncpy(isodatetime_first, unix2isodate(scantime_last, 'G'), 30);
386  }
387  status = nc_put_att_text(ncid, NC_GLOBAL, "time_coverage_start", strlen(isodatetime_first) + 1, isodatetime_first);
388  if (status != NC_NOERR) {
389  printf("-E- %s %d: %s for %s\n",
390  __FILE__, __LINE__, nc_strerror(status), "time_coverage_start");
391  exit(1);
392  }
393  status = nc_put_att_text(ncid, NC_GLOBAL, "time_coverage_end", strlen(isodatetime_last) + 1, isodatetime_last);
394  if (status != NC_NOERR) {
395  printf("-E- %s %d: %s for %s\n",
396  __FILE__, __LINE__, nc_strerror(status), "time_coverage_end");
397  exit(1);
398  }
399 
400  const char *navfieldsAVIRIS[] = {"to-sensor_azimuth", "to-sensor_zenith", "to-sun_azimuth", "to-sun_zenith", "lat", "lon"};
401  const char *navfieldsNCDF[] = {"sena", "senz", "sola", "solz", "lat", "lon"};
402 
403  grpID = ncdffile.getGid("navigation_data");
404  int varID;
405 
406  size_t startNCDF[2] = {0, 0};
407  size_t countNCDF[2] = {nscans, npixels};
408  size_t i;
409 
410  for (i = 0; i < 6; i++) {
411  cout << "Copying " << navfieldsAVIRIS[i] << " to " <<
412  navfieldsNCDF[i] << endl;
413 
414  status = nc_inq_varid(grpID, navfieldsNCDF[i], &varID);
415  check_err(status, __LINE__, __FILE__);
416 
417  switch (i) {
418  case 0:
419  status = nc_put_vara_float(grpID, varID, startNCDF, countNCDF, &temp->sena[sline * npixels]);
420  check_err(status, __LINE__, __FILE__);
421  break;
422  case 1:
423  status = nc_put_vara_float(grpID, varID, startNCDF, countNCDF, &temp->senz[sline * npixels]);
424  check_err(status, __LINE__, __FILE__);
425  break;
426  case 2:
427  status = nc_put_vara_float(grpID, varID, startNCDF, countNCDF, &temp->sola[sline * npixels]);
428  check_err(status, __LINE__, __FILE__);
429  break;
430  case 3:
431  status = nc_put_vara_float(grpID, varID, startNCDF, countNCDF, &temp->solz[sline * npixels]);
432  check_err(status, __LINE__, __FILE__);
433  break;
434  case 4:
435  status = nc_put_vara_double(grpID, varID, startNCDF, countNCDF, &temp->lat[sline * npixels]);
436  check_err(status, __LINE__, __FILE__);
437  break;
438  case 5:
439  status = nc_put_vara_double(grpID, varID, startNCDF, countNCDF, &temp->lon[sline * npixels]);
440  check_err(status, __LINE__, __FILE__);
441  break;
442  default:
443  break;
444  }
445  }
446 
447  gsl_interp_accel_free(acc);
448 
449  size_t startw[2] = {0, 0};
450  size_t countw[2] = {nbands_aviris, 0};
451 
452  grpID = ncdffile.getGid("sensor_band_parameters");
453 
454  status = nc_inq_varid(grpID, "wavelength", &varID);
455 
456  status = nc_put_vara_float(grpID, varID, startw, countw, ncdfWavelength);
457  check_err(status, __LINE__, __FILE__);
458 
459  status = nc_inq_varid(grpID, "fwhm", &varID);
460 
461  status = nc_put_vara_float(grpID, varID, startw, countw, fwhm);
462  check_err(status, __LINE__, __FILE__);
463 
464  size_t starts[2] = {0, 0};
465  size_t counts[2] = {nscans, 0};
466 
467  const char *nscanfieldsAVIRIS[] = {"utc", "alt", "alt"};
468  const char *nscanfieldsNCDF[] = {"scan_start_time", "altitude", "range"};
469  short* alt = (short*) (calloc(nscans, sizeof (short)));
470 
471  grpID = ncdffile.getGid("scan_line_attributes");
472  countNCDF[1] = 0;
473  for (i = 0; i < 3; i++) {
474  cout << "Copying " << nscanfieldsAVIRIS[i] << " to " <<
475  nscanfieldsNCDF[i] << endl;
476 
477  status = nc_inq_varid(grpID, nscanfieldsNCDF[i], &varID);
478  check_err(status, __LINE__, __FILE__);
479 
480  switch (i) {
481  case 0:
482  status = nc_put_vara_double(grpID, varID, starts, counts, utc);
483  check_err(status, __LINE__, __FILE__);
484  break;
485  case 1:
486  for (i = 0; i < nscans; i++) alt[i] = temp->alt[sline + i];
487  status = nc_put_vara_short(grpID, varID, starts, counts, alt);
488  check_err(status, __LINE__, __FILE__);
489  break;
490  case 2:
491  for (i = 0; i < nscans; i++) alt[i] = temp->alt[sline + i]*1000;
492  status = nc_put_vara_short(grpID, varID, starts, counts, alt);
493  check_err(status, __LINE__, __FILE__);
494  break;
495  default:
496  break;
497  }
498  }
499 
500  // outfile.close();
501 
502  status = close_aviris(temp);
503 
504  return 0;
505 }
506 
int j
Definition: decode_rs.h:73
int status
Definition: l1_czcs_hdf.c:32
int getNcid()
Definition: cdl_utils.cpp:746
void check_err(const int stat, const int line, const char *file)
Definition: nc4utils.c:35
int close_aviris(aviris4ocia_t *data)
Definition: read_aviris.c:822
#define CDLFILE
#define NULL
Definition: decode_rs.h:63
int main(int argc, char *argv[])
subroutine spline(s, x, y, n, in, t, il, iu, vl, vu, e, u)
Definition: phs.f:1348
uint8 * counts
Definition: l1_czcs_hdf.c:30
aviris4ocia_t * open_aviris(char *filename, char *imgfile, char *navfile, char *gainfile, aviris4ocia_t **data)
Definition: read_aviris.c:175
int checkAvProcessFile(char *filename, char *hdrfile, char *imgfile, char *navfile, char *gainfile, int itemsize)
Definition: read_aviris.c:831
float fwhm[NBANDS]
Definition: atrem_corl1.h:144
#define FILL
#define BIL
#define BIP
int getGid(const char *grpName)
Definition: cdl_utils.cpp:736
int read_aviris(aviris4ocia_t *data, int32_t recnum)
Definition: read_aviris.c:710
#define VERSION
char filename[FILENAME_MAX]
Definition: atrem_corl1.h:122
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
SENSOR
Definition: DDProcess.h:81
size_t interpLt(size_t startJ, size_t npixels, size_t k, size_t nbMax, float ncdfWavelength, size_t iwave, aviris4ocia_t *data, gsl_interp_accel *acc, float *Lt)
int32_t iscan
char * unix2isodate(double dtime, char zone)
Definition: unix2isodate.c:10
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)
int cdlCreateDim(char *l1_filename, char *cdl_filename, const char **dim_names, size_t *dim_size, size_t n_dims, size_t numScans)
Definition: cdl_utils.cpp:294
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 NBANDS
#define str(s)
int count
Definition: decode_rs.h:79