OB.DAAC Logo
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
const char * str
Definition: l1c_msi.cpp:35
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
int count
Definition: decode_rs.h:79