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
readL2scan.c
Go to the documentation of this file.
1 /*
2  Modification history:
3  Programmer Organization Date Description of change
4  -------------- ------------ -------- ---------------------
5  Joel Gales Futuretech 01/31/00 Original Development
6  Bryan Franz GSC 03/01/00 Add reading of LAC
7  pix start & subsamp to
8  readL2meta
9  Joel Gales Futuretech 03/03/00 Change nflag in l2_str
10  from byte to int32
11  Fix allocation
12  problem with prodlist
13 
14  Joel Gales Futuretech 03/14/00 Add "getL3units" routine
15 
16  Joel Gales Futuretech 05/25/00 Fix isalpha (Linux) bug
17  Joel Gales Futuretech 06/14/00 Fix case where there are
18  no L2 products (flags only)
19  Joel Gales Futuretech 06/15/00 Fix units problem for flag
20  products
21  Joel Gales Futuretech 06/20/00 Add read support for FLOAT32
22  data products
23  Ewa Kwiatkowska SAIC 07/28/04 Made prodtype file-dependent
24  what enables reading L2 files
25  from different sensors
26  Joel Gales Futuretech 08/26/07 Increase buffer in openL2 to
27  read "Processing_Control"
28  attribute.
29  Do not read "eng_qual",
30  "s_flags", "nflag" fields if
31  they do not exist
32  Joel Gales Futuretech 08/31/09 Check scaled value for bad
33  value.
34  Set to NaN if bad.
35  Implemented for INT16 only.
36 
37  Joel Gales Futuretech 03/14/11 Add n_cntl_pnts readjustment
38  for bad latitude control pnts
39 
40  Joel Gales Futuretech 07/30/12 Only allocate data products
41  cache at beginning or if
42  number of data products
43  increased.
44  Joel Gales Futuretech 06/14/13 Add support for NETCDF4
45  Joel Gales Futuretech 07/23/13 Fix incomplete idDS structure
46  for pixnum, eng_qual, s_flags,
47  nflag.
48 
49  Joel Gales Futuretech 02/11/14 Clear bufnum buffer in
50  getL3units before reading
51  units attribute
52  */
53 
54 #include <stdlib.h>
55 #include <stdio.h>
56 #include <netcdf.h>
57 #include <genutils.h>
58 #include "readL2scan.h"
59 #ifdef GEONAV
60 #include "navigation.h"
61 #endif
62 #include <sensorInfo.h>
63 #include <timeutils.h>
64 #include <nc4utils.h>
65 #include "find_variable.h"
66 
67 #include <hdf.h>
68 #include <mfhdf.h>
69 
70 #define TITLE "title"
71 #define TITLE_OLD "Title"
72 #define INFILES "input_sources"
73 #define INFILES_OLD "Input Files"
74 #define SENNME "instrument"
75 #define SENNME_OLD "Sensor Name"
76 #define DCENTER "project"
77 #define DCENTER_OLD "Data Center"
78 #define NFREC "Filled Scan Lines"
79 #define PCTFLAG "flag_percentages"
80 #define PCTFLAG_OLD "Flag Percentages"
81 #define NTIME "equatorCrossingDateTime"
82 #define NTIME_OLD "Node Crossing Time"
83 #define SNODE "startDirection"
84 #define SNODE_OLD "Start Node"
85 #define ENODE "endDirection"
86 #define ENODE_OLD "End Node"
87 #define MISSION "platform"
88 #define MISSION_OLD "Mission"
89 #define MSNCHAR "Mission Characteristics"
90 #define SENSOR "Sensor"
91 #define SNSCHAR "Sensor Characteristics"
92 #define ORBNUM "orbit_number"
93 #define ORBNUM_OLD "Orbit Number"
94 #define NLAT "northernmost_latitude"
95 #define NLAT_OLD "Northernmost Latitude"
96 #define SLAT "southernmost_latitude"
97 #define SLAT_OLD "Southernmost Latitude"
98 #define WLON "westernmost_longitude"
99 #define WLON_OLD "Westernmost Longitude"
100 #define ELON "easternmost_longitude"
101 #define ELON_OLD "Easternmost Longitude"
102 #define STCLAT "start_center_latitude"
103 #define STCLAT_OLD "Start Center Latitude"
104 #define STCLON "start_center_longitude"
105 #define STCLON_OLD "Start Center Longitude"
106 #define ENDCLAT "end_center_latitude"
107 #define ENDCLAT_OLD "End Center Latitude"
108 #define ENDCLON "end_center_longitude"
109 #define ENDCLON_OLD "End Center Longitude"
110 #define NODEL "equatorCrossingLongitude"
111 #define NODEL_OLD "Orbit Node Longitude"
112 #define LAC_PX_ST "LAC Pixel Start Number"
113 #define LAC_PX_SUBSAMP "LAC Pixel Subsampling"
114 #define NUM_LATLON_NAME 4
115 #define INIT_DELTA 10000
116 #define SHOW_NC_ERROR(func, err, ...) \
117  err = func; \
118  if (err != NC_NOERR) { \
119  printf(__VA_ARGS__); \
120  exit(EXIT_FAILURE); \
121  }
122 typedef struct cache_struct {
123  int32_t bscan;
124  int32_t escan;
125  int32_t dataSize;
126  void *data;
127 } cache_str;
128 
129 
130 static int32_t n_files_open = 0;
131 static char geo_location_data_grp_lat[256];
132 static char geo_location_data_grp_lon[256];
133 static int32_t scantime_grp[MAXNFILES];
134 static int32_t scantime_var[MAXNFILES];
135 static int32_t grp_id_geo_lat[MAXNFILES];
136 static int32_t grp_id_geo_lon[MAXNFILES];
137 static int32_t name_lat_nc[MAXNFILES];
138 static int32_t name_lon_nc[MAXNFILES];
139 
140 typedef idDS ds_id_prod_t[1000];
141 static ds_id_prod_t *ds_id_prod;
142 
143 typedef int32_t prodtype_t[1000];
144 static prodtype_t *prodtype;
145 
146 typedef float slope_t[1000];
147 static slope_t *slope;
148 static slope_t *intercept;
149 
150 typedef idDS ds_id_ll_t[3];
151 static ds_id_ll_t *ds_id_ll;
152 static ds_id_ll_t *ds_id_date;
153 
154 typedef idDS ds_id_geonav_t[6];
155 static ds_id_geonav_t *ds_id_geonav;
156 
157 typedef int32_t grp_id_t[6];
158 static grp_id_t *grp_id;
159 
160 static idDS *ds_id_l2_flags;
161 static idDS *ds_id_eng_qual;
162 static idDS *ds_id_s_flags;
163 static idDS *ds_id_nflag;
164 static idDS *ds_id_pixnum;
165 static idDS *ds_id_file;
166 static idDS *ds_id_wave;
167 static idDS *ds_id_wave3d;
168 
169 static int32_t *nsta;
170 static int32_t *ninc;
171 
172 static int databufSize = 0;
173 static unsigned char *databuf = NULL;
174 static char **prodlist;
175 
176 static int32_t n_cntl_pnts;
177 static int32_t prev_n_cntl_pnts = -1;
178 
179 static float geonav[6][9];
180 
181 static int32_t one = 1;
182 static int32_t zero32 = 0;
183 static int32_t l2_flags_type;
184 
185 static int32_t bandsPerPixel = 1;
186 static int32_t wavelength_3d = 1;
187 
188 static cache_str cache_l2_flags;
189 static cache_str cache_eng_qual;
190 static cache_str cache_s_flags;
191 static cache_str cache_nflag;
192 static cache_str cache_pixnum;
193 static cache_str cache_longitude;
194 static cache_str cache_latitude;
195 static int32_t cache_nprod;
196 static cache_str **cache_l2_data;
197 
198 // possible variable names for latitude, longitude
199 
200 const char *possible_latitude_names[NUM_LATLON_NAME] = {"latitude", "Latitude", "lat", "Lat"};
201 const char *possible_longitude_names[NUM_LATLON_NAME] = {"longitude", "Longitude", "lon", "Lon"};
202 
204  enum L2PixelMode_t mode; // 0=off, 1=pixel corners, 2=pixel deltas
205  int32_t lastLine; // if -1 the last line does not have good lat/lon
206 
207  int32_t nsamp;
208  float *lastLat;
209  float *lastLon;
210 };
211 static struct pixelAreaInfo_t pixelAreaInfo;
212 
214  pixelAreaInfo.mode = val;
215  pixelAreaInfo.lastLine = -1;
216 
217  pixelAreaInfo.nsamp = 0;
218  if (pixelAreaInfo.lastLat) {
219  free(pixelAreaInfo.lastLat);
220  free(pixelAreaInfo.lastLon);
221  }
222  pixelAreaInfo.lastLat = NULL;
223  pixelAreaInfo.lastLon = NULL;
224 }
225 
231 int32_t get_dtype(int32_t dtype, ds_format_t fileformat) {
232  if (fileformat == DS_NCDF) {
233  if (dtype == DFNT_INT8)
234  dtype = NC_BYTE;
235  else if (dtype == DFNT_UINT8)
236  dtype = NC_UBYTE;
237  else if (dtype == DFNT_INT16)
238  dtype = NC_SHORT;
239  else if (dtype == DFNT_UINT16)
240  dtype = NC_USHORT;
241  else if (dtype == DFNT_INT32)
242  dtype = NC_INT;
243  else if (dtype == DFNT_UINT32)
244  dtype = NC_UINT;
245  else if (dtype == DFNT_FLOAT32)
246  dtype = NC_FLOAT;
247  else if (dtype == DFNT_FLOAT64)
248  dtype = NC_DOUBLE;
249  else {
250  printf("-E- %s:%d - unknown data type.\n", __FILE__, __LINE__);
251  exit(EXIT_FAILURE);
252  }
253  }
254  return dtype;
255 }
256 //----------------------------------------------------------------
257 // free cache
258 
260  int i;
261 
262  cache_l2_flags.bscan = -1;
263  cache_eng_qual.bscan = -1;
264  cache_s_flags.bscan = -1;
265  cache_nflag.bscan = -1;
266  cache_pixnum.bscan = -1;
267  cache_longitude.bscan = -1;
268  cache_latitude.bscan = -1;
269 
270  cache_l2_flags.escan = -1;
271  cache_eng_qual.escan = -1;
272  cache_s_flags.escan = -1;
273  cache_nflag.escan = -1;
274  cache_pixnum.escan = -1;
275  cache_longitude.escan = -1;
276  cache_latitude.escan = -1;
277 
278  for (i = 0; i < cache_nprod; i++) {
279  cache_l2_data[i]->bscan = -1;
280  cache_l2_data[i]->escan = -1;
281  }
282 }
283 
284 /* init the cache structures */
285 
286 /* -------------------------- */
288  cache_str tmp_cache;
289 
290  tmp_cache.bscan = -1;
291  tmp_cache.escan = -1;
292  tmp_cache.dataSize = 0;
293  tmp_cache.data = NULL;
294 
295  cache_l2_flags = tmp_cache;
296  cache_eng_qual = tmp_cache;
297  cache_s_flags = tmp_cache;
298  cache_nflag = tmp_cache;
299  cache_pixnum = tmp_cache;
300  cache_longitude = tmp_cache;
301  cache_latitude = tmp_cache;
302 }
303 
304 void allocateDatabuf(l2_prod *l2_str, int maxThirdDim) {
305  int newSize = l2_str->nsamp * maxThirdDim * 8;
306  if (databufSize < newSize) {
307  if (databuf)
308  free(databuf);
309  databufSize = newSize;
310  databuf = (unsigned char *)malloc(databufSize);
311  }
312 }
313 
314 //----------------------------------------------------------------
315 
316 int32_t openL2(const char *fname, const char *plist, l2_prod *l2_str) {
317  int32_t i;
318  int32_t sds_id;
319  int32_t len;
320  int32_t dims[8];
321  int32_t n_l2flags;
322  int32_t tilt_start[2] = {0, 0};
323  int32_t tilt_edges[2] = {20, 2};
324  int16_t t_ranges[2 * 20];
325  int status;
326  int32_t listlen = 0;
327  int32_t fileindex;
328  idDS ds_id;
329  int dim_id;
330  size_t tmpSizet;
331 
332  char buffer[2048 * 8];
333  char *tmpStr;
334  char *numstr[] = {"01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11",
335  "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22",
336  "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33"};
337 
338  static int32_t first = 1;
339 
340  ds_format_t fileformat;
341 
342  if (Hishdf(fname) == 1) {
343  fileformat = DS_HDF;
344  } else {
345  fileformat = DS_NCDF;
346  }
347 
348  /* Copy filename and product list into L2 structure */
349  /* ------------------------------------------------ */
350  if (l2_str->nrec == 0) {
351  strcpy(l2_str->filename, fname);
352  n_files_open++;
353  fileindex = n_files_open - 1;
354  l2_str->fileindex = fileindex;
355  } else {
356  fileindex = l2_str->fileindex;
357  }
358 
359  if (first) {
360  ds_id_prod = (ds_id_prod_t *)allocateMemory(MAXNFILES * sizeof(ds_id_prod_t), "ds_id_prod");
361  prodtype = (prodtype_t *)allocateMemory(MAXNFILES * sizeof(prodtype_t), "prodtype");
362  slope = (slope_t *)allocateMemory(MAXNFILES * sizeof(slope_t), "slope");
363  intercept = (slope_t *)allocateMemory(MAXNFILES * sizeof(slope_t), "intercept");
364  ds_id_ll = (ds_id_ll_t *)allocateMemory(MAXNFILES * sizeof(ds_id_ll_t), "ds_id_ll");
365  ds_id_date = (ds_id_ll_t *)allocateMemory(MAXNFILES * sizeof(ds_id_ll_t), "ds_id_date");
366  ds_id_geonav = (ds_id_geonav_t *)allocateMemory(MAXNFILES * sizeof(ds_id_geonav_t), "ds_id_geonav");
367  grp_id = (grp_id_t *)allocateMemory(MAXNFILES * sizeof(grp_id_t), "grp_id");
368  if (get_l2_flag_use())
369  ds_id_l2_flags = (idDS *)allocateMemory(MAXNFILES * sizeof(idDS), "ds_id_l2_flags");
370  ds_id_eng_qual = (idDS *)allocateMemory(MAXNFILES * sizeof(idDS), "ds_id_eng_qual");
371  ds_id_s_flags = (idDS *)allocateMemory(MAXNFILES * sizeof(idDS), "ds_id_s_flags");
372  ds_id_nflag = (idDS *)allocateMemory(MAXNFILES * sizeof(idDS), "ds_id_nflag");
373  ds_id_pixnum = (idDS *)allocateMemory(MAXNFILES * sizeof(idDS), "ds_id_pixnum");
374  ds_id_file = (idDS *)allocateMemory(MAXNFILES * sizeof(idDS), "ds_id_file");
375  ds_id_wave = (idDS *)allocateMemory(MAXNFILES * sizeof(idDS), "ds_id_wave");
376  ds_id_wave3d = (idDS *)allocateMemory(MAXNFILES * sizeof(idDS), "ds_id_wave3d");
377 
378  nsta = (int32_t *)allocateMemory(MAXNFILES * sizeof(int32_t), "nsta");
379  ninc = (int32_t *)allocateMemory(MAXNFILES * sizeof(int32_t), "ninc");
380 
381  prodlist = (char **)allocateMemory(MAXNFILES * sizeof(char *), "prodlist");
382 
383  for (i = 0; i < MAXNFILES; i++)
384  prodlist[i] = NULL;
385  }
386 
387  /* Generate prodlist */
388  /* ----------------- */
389  if (plist != 0x0) {
390  prodlist[fileindex] = (char *)calloc(strlen(plist) + 1, sizeof(char));
391  strcpy(prodlist[fileindex], plist);
392  char *temp;
393  getProdlist(fname, &temp, &l2_flags_type); // we still need this flag. Sean asked to remove it.
394  free(temp);
395  } else {
396  getProdlist(fname, &prodlist[fileindex], &l2_flags_type); // gets original products
397  }
398  /* Parse Product list */
399  /* ------------------ */
400  l2_str->nprod = 1;
401  l2_str->prodname[0] = &prodlist[fileindex][0];
402  len = strlen(prodlist[fileindex]);
403  for (i = 0; i < len; i++) {
404  if (prodlist[fileindex][i] == ',') {
405  l2_str->prodname[l2_str->nprod] = prodlist[fileindex] + i + 1;
406  l2_str->nprod++;
407  prodlist[fileindex][i] = 0;
408  }
409  }
410  /* No L2 products in L2 file (flags only) */
411  if (strlen(prodlist[fileindex]) == 0)
412  l2_str->nprod = 0;
413  /* Start DS interface */
414  /* ------------------ */
415  ds_id = startDS(l2_str->filename, fileformat, DS_READ, 0);
416 
417  ds_id_file[fileindex] = ds_id;
418 
419  if (fileformat == DS_NCDF) {
420  //{
421  int32_t var_id;
422  const char *filename = l2_str->filename;
425  &grp_id_geo_lat[fileindex], &name_lat_nc[fileindex]),
426  status, "\n--Error--: couldn't find latitude in file %s. See %s in line %d. Exiting ... \n",
427  filename, __FILE__, __LINE__);
430  &grp_id_geo_lon[fileindex], &name_lon_nc[fileindex]),
431  status, "\n--Error--: couldn't find longitude in file %s. See %s in line %d. Exiting ... \n",
432  filename, __FILE__, __LINE__);
433 
434  if (grp_id_geo_lon[fileindex] != grp_id_geo_lat[fileindex] && status != NC_NOERR) {
435  printf("\nWaring: latitude and longitude arrays are placed in different groups");
436  }
437  SHOW_NC_ERROR(nc_inq_grpname(grp_id_geo_lat[fileindex], geo_location_data_grp_lat), status,
438  "\n--Error--: could not get the geolocation group name for latitude in file %s. See %s "
439  "in line %d. Exiting ...\n",
440  filename, __FILE__, __LINE__);
441  SHOW_NC_ERROR(nc_inq_grpname(grp_id_geo_lon[fileindex], geo_location_data_grp_lon), status,
442  "\n--Error--: could not get the geolocation group name for longitude in file %s. See "
443  "%s in line %d. Exiting ...\n",
444  filename, __FILE__, __LINE__);
445  // looking for scan attributes
447  "scantime", ds_id.fid, &scantime_var[fileindex], &scantime_grp[fileindex]);
448  if (status != NC_NOERR) {
449  scantime_grp[fileindex] = -1;
450  scantime_var[fileindex] = -1;
451  }
452 
453  nc_inq_ncid(ds_id.fid, "sensor_band_parameters", &grp_id[fileindex][0]);
454  nc_inq_ncid(ds_id.fid, "sensor_tilt", &grp_id[fileindex][1]);
455  nc_inq_ncid(ds_id.fid, "scan_line_attributes", &grp_id[fileindex][2]);
456  nc_inq_ncid(ds_id.fid, "geophysical_data", &grp_id[fileindex][3]);
457  nc_inq_ncid(ds_id.fid, "navigation_data", &grp_id[fileindex][4]);
458  nc_inq_ncid(ds_id.fid, "processing_control", &grp_id[fileindex][5]);
459  }
460 
461  /* Get # of scans and # of pixels */
462  /* ------------------------------ */
463  if (fileformat == DS_NCDF) {
464  status = nc_inq_dimid(ds_id.fid, "number_of_lines", &dim_id);
465  if (status) {
466  status = nc_inq_dimid(ds_id.fid, "Number_of_Scan_Lines", &dim_id);
467  if (status) {
468  printf("-E- %s:%d - openL2 - could not find number_of_lines.\n", __FILE__, __LINE__);
469  exit(EXIT_FAILURE);
470  }
471  }
472  nc_inq_dimlen(ds_id.fid, dim_id, &tmpSizet);
473  l2_str->nrec = tmpSizet;
474  status = nc_inq_dimid(ds_id.fid, "pixels_per_line", &dim_id);
475  if (status) {
476  status = nc_inq_dimid(ds_id.fid, "Pixels_per_Scan_Line", &dim_id);
477  if (status) {
478  printf("-E- %s:%d - openL2 - could not find pixels_per_line.\n", __FILE__, __LINE__);
479  exit(EXIT_FAILURE);
480  }
481  }
482  nc_inq_dimlen(ds_id.fid, dim_id, &tmpSizet);
483  l2_str->nsamp = tmpSizet;
484 
485  status = nc_inq_dimid(ds_id.fid, "bands_per_pixel", &dim_id);
486  if (status == 0) {
487  nc_inq_dimlen(ds_id.fid, dim_id, &tmpSizet);
488  bandsPerPixel = tmpSizet;
489  }
490  l2_str->bandsPerPixel = bandsPerPixel;
491  wavelength_3d = bandsPerPixel;
492 
493  status = nc_inq_dimid(ds_id.fid, "wavelength_3d", &dim_id);
494  if (status == 0) {
495  nc_inq_dimlen(ds_id.fid, dim_id, &tmpSizet);
496  wavelength_3d = tmpSizet;
497  }
498  l2_str->wavelength_3d = wavelength_3d; // bands_per_pixel and wavelength_3d are essentially the size
499  // of the third dimension
500  } else {
501  readAttr(ds_id, "Number of Scan Lines", (void *)&l2_str->nrec);
502  readAttr(ds_id, "Pixels per Scan Line", (void *)&l2_str->nsamp);
503  }
504 
505  /* Get start & end times, orbit number and data type */
506  /* ------------------------------------------------- */
507  if (fileformat == DS_NCDF) {
508  int32_t yr, dy, sc;
509  status = readAttr(ds_id, "orbit_number", (void *)&l2_str->orbit);
510  // not checking the return status here as there are real live cases of
511  // orbit number NOT existing in the L2 metadata (e.g. GOCI)
512 
513  tmpStr = readAttrStr(ds_id, "time_coverage_start");
514  if (!tmpStr) {
515  printf("-E- %s:%d - openL2 - could not find time_coverage_start.\n", __FILE__, __LINE__);
516  exit(EXIT_FAILURE);
517  }
518  isodate2ydmsec(tmpStr, &yr, &dy, &sc);
519  free(tmpStr);
520 
521  l2_str->syear = (int16_t)yr;
522  l2_str->sday = (int16_t)dy;
523  l2_str->smsec = sc;
524  l2_str->year = (int16_t)yr;
525  l2_str->day = (int16_t)dy;
526  l2_str->msec = sc;
527  // l2_str->smsec = 1000 * ((int32_t) scs);
528 
529  tmpStr = readAttrStr(ds_id, "time_coverage_end");
530  if (!tmpStr) {
531  printf("-E- %s:%d - openL2 - could not find time_coverage_end.\n", __FILE__, __LINE__);
532  exit(EXIT_FAILURE);
533  }
534  isodate2ydmsec(tmpStr, &yr, &dy, &sc);
535  free(tmpStr);
536 
537  l2_str->eyear = (int16_t)yr;
538  l2_str->eday = (int16_t)dy;
539  // l2_str->emsec = 1000 * ((int32_t) scs);
540  l2_str->emsec = sc;
541  } else {
542  readAttr(ds_id, "Start Year", (void *)&l2_str->syear);
543  readAttr(ds_id, "Start Day", (void *)&l2_str->sday);
544  readAttr(ds_id, "Start Millisec", (void *)&l2_str->smsec);
545  readAttr(ds_id, "End Year", (void *)&l2_str->eyear);
546  readAttr(ds_id, "End Day", (void *)&l2_str->eday);
547  readAttr(ds_id, "End Millisec", (void *)&l2_str->emsec);
548  readAttr(ds_id, "Orbit Number", (void *)&l2_str->orbit);
549  readAttr(ds_id, "Data Type", (void *)&l2_str->dtype);
550  }
551 
552  /* Allocate geoloc (lon/lat) arrays */
553  /* -------------------------------- */
554  l2_str->latitude = (float *)calloc(l2_str->nsamp, sizeof(float));
555  l2_str->longitude = (float *)calloc(l2_str->nsamp, sizeof(float));
556  if (pixelAreaInfo.mode != L2PixelOff) {
557  l2_str->lat1 = (float *)malloc((l2_str->nsamp + 1) * sizeof(float));
558  l2_str->lon1 = (float *)malloc((l2_str->nsamp + 1) * sizeof(float));
559  l2_str->lat1[l2_str->nsamp/2] = INIT_DELTA;
560  if (pixelAreaInfo.mode == L2PixelCorner) {
561  l2_str->lat2 = (float *)malloc((l2_str->nsamp + 1) * sizeof(float));
562  l2_str->lon2 = (float *)malloc((l2_str->nsamp + 1) * sizeof(float));
563  }
564  }
565 
566  /* Get longitude, latitude, & date sds ids */
567  /* --------------------------------------- */
568  if (fileformat == DS_NCDF) {
569  const char *lon_name = possible_longitude_names[name_lon_nc[fileindex]];
570  const char *lat_name = possible_latitude_names[name_lat_nc[fileindex]];
571  const char *filename = l2_str->filename;
572  ds_id.fid = grp_id_geo_lon[fileindex];
573  ds_id_ll[fileindex][0] = (idDS){ds_id.fid, selectDS(ds_id, lon_name), ds_id.fftype};
574  SHOW_NC_ERROR(getDimsDS(ds_id, lon_name, dims), status,
575  "--Error-- : could not get longitude dimensions in file %s. See %s in %d. Exiting.\n",
576  filename, __FILE__, __LINE__);
577 
578  if (ds_id_ll[fileindex][0].sid == -1) {
579  printf("--Error-- : longitude can't be read in file %s. See %s in %d. Exiting.\n", filename,
580  __FILE__, __LINE__);
581  exit(EXIT_FAILURE);
582  }
583  ds_id.fid = grp_id_geo_lat[fileindex];
584  ds_id_ll[fileindex][1] = (idDS){ds_id.fid, selectDS(ds_id, lat_name), ds_id.fftype};
585  if (ds_id_ll[fileindex][1].sid == -1) {
586  printf("--Error-- : latitude can't be read in file %s. See %s in %d. Exiting.\n", filename,
587  __FILE__, __LINE__);
588  exit(EXIT_FAILURE);
589  }
590  }
591 
592  ds_id_ll[fileindex][2] = (idDS){ds_id.fid, -1, ds_id.fftype};
593 
594  if (fileformat == DS_NCDF)
595  ds_id.fid = grp_id[fileindex][2];
596  ds_id_date[fileindex][0] = (idDS){ds_id.fid, selectDS(ds_id, "year"), ds_id.fftype};
597  ds_id_date[fileindex][1] = (idDS){ds_id.fid, selectDS(ds_id, "day"), ds_id.fftype};
598  ds_id_date[fileindex][2] = (idDS){ds_id.fid, selectDS(ds_id, "msec"), ds_id.fftype};
599 
600  l2_str->geointerp = 0;
601 
602  // Read wavelength field
603  if (fileformat == DS_NCDF)
604  ds_id.fid = grp_id[fileindex][0];
605  ds_id_wave[fileindex] = (idDS){ds_id.fid, selectDS(ds_id, "wavelength"), ds_id.fftype};
606  if (ds_id_wave[fileindex].sid != -1) {
607  readDS(ds_id_wave[fileindex], "wavelength", &zero32, NULL, &bandsPerPixel, l2_str->wavelength);
608  endaccessDS(ds_id_wave[fileindex]);
609  }
610 
611  if (fileformat == DS_NCDF)
612  ds_id.fid = grp_id[fileindex][0];
613  ds_id_wave3d[fileindex] = (idDS){ds_id.fid, selectDS(ds_id, "wavelength_3d"), ds_id.fftype};
614  if (ds_id_wave3d[fileindex].sid != -1) {
615  readDS(ds_id_wave3d[fileindex], "wavelength_3d", &zero32, NULL, &wavelength_3d,
616  l2_str->wavelengths_3d);
617  endaccessDS(ds_id_wave3d[fileindex]);
618  } else {
619  for (int i = 0; i < wavelength_3d; i++)
620  l2_str->wavelengths_3d[i] = l2_str->wavelength[i];
621  }
622  // again, essentiall we have wv3d
623 
624  /* Test if full-size lon/lat SDS */
625  /* ----------------------------- */
626  if (dims[0] != l2_str->nrec || dims[1] != l2_str->nsamp || ds_id_ll[fileindex][0].sid == -1) {
627  l2_str->geointerp = 1;
628 
629  /* Test for geonav arrays (SeaWIFS) */
630  /* -------------------------------- */
631  if (fileformat == DS_NCDF)
632  ds_id.fid = grp_id[fileindex][4];
633  ds_id_geonav[fileindex][0] = (idDS){ds_id.fid, selectDS(ds_id, "orb_vec"), ds_id.fftype};
634  ds_id_geonav[fileindex][1] = (idDS){ds_id.fid, selectDS(ds_id, "sen_mat"), ds_id.fftype};
635  ds_id_geonav[fileindex][2] = (idDS){ds_id.fid, selectDS(ds_id, "scan_ell"), ds_id.fftype};
636  ds_id_geonav[fileindex][3] = (idDS){ds_id.fid, selectDS(ds_id, "sun_ref"), ds_id.fftype};
637  // ds_sid_geonav[fileindex][4] = selectDS(ds_id, "l_vert");
638  ds_id_geonav[fileindex][4].sid = -1;
639  ds_id_geonav[fileindex][5] = (idDS){ds_id.fid, selectDS(ds_id, "att_ang"), ds_id.fftype};
640 
641  ds_id = ds_id_file[fileindex];
642  nsta[fileindex] = -1;
643  ninc[fileindex] = -1;
644  readAttr(ds_id_file[fileindex], "LAC Pixel Start Number", (void *)&nsta[fileindex]);
645  readAttr(ds_id_file[fileindex], "LAC Pixel Subsampling", (void *)&ninc[fileindex]);
646 
647  if (ds_id_geonav[fileindex][0].sid != -1 && ds_id_geonav[fileindex][1].sid != -1 &&
648  ds_id_geonav[fileindex][2].sid != -1 && ds_id_geonav[fileindex][3].sid != -1 &&
649  nsta[fileindex] != -1 && ninc[fileindex] != -1) {
650  l2_str->geointerp = 2;
651 
652  for (i = 0; i < 6; i++)
653  l2_str->geonav[i] = geonav[i];
654  } else {
655  /* Get # of control points */
656  /* ----------------------- */
657  if (fileformat == DS_NCDF) {
658  status = nc_inq_dimid(ds_id_file[fileindex].fid, "pixel_control_points", &dim_id);
659  if (status) {
660  printf("-E- %s:%d - openL2 - Could not find the dimension pixel_control_points.\n",
661  __FILE__, __LINE__);
662  exit(EXIT_FAILURE);
663  }
664  status = nc_inq_dimlen(ds_id_file[fileindex].fid, dim_id, &tmpSizet);
665  if (status) {
666  printf("-E- %s:%d - openL2 - Could not read the dimension pixel_control_points\n",
667  __FILE__, __LINE__);
668  exit(EXIT_FAILURE);
669  }
670  n_cntl_pnts = tmpSizet;
671  } else
672  readAttr(ds_id_file[fileindex], "Number of Pixel Control Points", (void *)&n_cntl_pnts);
673 
674  /* Check that all L2 files have same number of control points */
675  /* ---------------------------------------------------------- */
676  if (prev_n_cntl_pnts != -1 && prev_n_cntl_pnts != n_cntl_pnts) {
677  printf("L2 file #:%4d has %d control points.\n", fileindex, prev_n_cntl_pnts);
678  printf("L2 file #:%4d has %d control points.\n", fileindex + 1, n_cntl_pnts);
679  printf("These must be identical.\n");
680  exit(-1);
681  }
682  prev_n_cntl_pnts = n_cntl_pnts;
683 
684  /* Allocate arrays needed for lon/lat interpolation */
685  /* ------------------------------------------------ */
686  l2_str->lon_cntl = (float *)calloc(n_cntl_pnts, sizeof(float));
687  l2_str->lat_cntl = (float *)calloc(n_cntl_pnts, sizeof(float));
688  l2_str->cntl_pnts = (float *)calloc(n_cntl_pnts, sizeof(float));
689  l2_str->cntl_pnts_cache = (float *)calloc(n_cntl_pnts, sizeof(float));
690  l2_str->spline_arr = (float *)calloc(n_cntl_pnts, sizeof(float));
691 
692  /* Get control point sds id */
693  /* ------------------------ */
694  ds_id_ll[fileindex][2].sid = selectDS(ds_id, "cntl_pt_cols");
695 
696  /* Read control points array if first time through */
697  /* ----------------------------------------------- */
698  int32_t *tmpPtr = (int32_t *)l2_str->cntl_pnts;
699  readDS(ds_id_ll[fileindex][2], "cntl_pt_cols", &zero32, NULL, &n_cntl_pnts, tmpPtr);
700  endaccessDS(ds_id);
701  ds_id_ll[fileindex][2].sid = -1;
702 
703  /* Convert cntl pnts from I32 to F32 */
704  /* --------------------------------- */
705  for (i = 0; i < n_cntl_pnts; i++) {
706  l2_str->cntl_pnts_cache[i] = tmpPtr[i];
707  }
708  }
709  }
710 
711  /* Store data products info in L2 structure */
712  /* ---------------------------------------- */
713  for (i = 0; i < l2_str->nprod; i++) {
714  // change before here
715  char *l2_prd;
716  l3_l2_conversion(&l2_str->prodname[i], &l2_prd);
717  int32_t varid;
718  SHOW_NC_ERROR(find_nc_variable_parent_grp_c_interface_id_ncid(l2_prd, ds_id_file[fileindex].fid,
719  &varid, &ds_id.fid),
720  status, "--Error-- : could not find variable %s. See %s in %d. Exiting.\n", l2_prd,
721  __FILE__, __LINE__);
722  sds_id = selectDS(ds_id, l2_prd);
723  if (sds_id != -1) {
724  getTypeDS(
725  ds_id, l2_prd,
726  &(prodtype[fileindex][i])); // we need a function that converts it // it is a product index
727 
728  /* Read scaling slope and intercept */
729  /* -------------------------------- */
730  idDS ds_id0 = {-ds_id.fid, sds_id, ds_id.fftype};
731 
732  if (fileformat == DS_NCDF) {
733  if (prodtype[fileindex][i] != NC_FLOAT && prodtype[fileindex][i] != NC_DOUBLE) {
734  status = readAttr(ds_id0, "scale_factor", (void *)&(slope[fileindex][i]));
735  if (status) {
736  slope[fileindex][i] = 1.0;
737  }
738  readAttr(ds_id0, "add_offset", (void *)&(intercept[fileindex][i]));
739  if (status) {
740  intercept[fileindex][i] = 0.0;
741  }
742  } else {
743  slope[fileindex][i] = 1.0;
744  intercept[fileindex][i] = 0.0;
745  }
746  readAttr(ds_id0, "_FillValue", (void *)(&l2_str->bv_scaled[i]));
747  } else {
748  readAttr(ds_id0, "slope", (void *)&(slope[fileindex][i]));
749  readAttr(ds_id0, "intercept", (void *)&(intercept[fileindex][i]));
750  if (slope[fileindex][i] == 0.0)
751  slope[fileindex][i] = 1.0;
752 
753  if (findAttr(ds_id0, "bad_value_unscaled") != -1)
754  readAttr(ds_id0, "bad_value_unscaled", (void *)(&l2_str->bv_unscaled[i]));
755  else
756  l2_str->bv_unscaled[i] = -1e30;
757 
758  if (findAttr(ds_id0, "bad_value_scaled") != -1)
759  readAttr(ds_id0, "bad_value_scaled", (void *)(&l2_str->bv_scaled[i]));
760  else
761  l2_str->bv_scaled[i] = -32768;
762  }
763 
764  ds_id_prod[fileindex][i] = (idDS){ds_id.fid, sds_id, ds_id.fftype};
765 
766  int32_t fldDims[8] = {0, 0, 0, 0, 0, 0, 0, 0};
767  getDimsDS(ds_id, l2_prd, fldDims);
768  if (fldDims[2] == bandsPerPixel)
769  l2_str->thirdDim[i] = get_set_flag() ? 1 : bandsPerPixel; //
770  else if (fldDims[2] == wavelength_3d)
771  l2_str->thirdDim[i] =
772  get_set_flag() ? 1 : wavelength_3d; // the size of wavelenght output array
773  else
774  l2_str->thirdDim[i] = 1;
775  } else {
776  printf("Data Product: \"%s\" not found.\n", l2_prd);
777  exit(1);
778  }
779  }
780 
781  /* Allocate cache for products */
782  /* --------------------------- */
783  // Allocate cache for data products if NULL
784  if (cache_l2_data == NULL) {
785  cache_nprod = l2_str->nprod;
786  cache_l2_data = (cache_str **)malloc(sizeof(cache_str *) * cache_nprod);
787  for (i = 0; i < cache_nprod; i++) {
788  cache_l2_data[i] = (cache_str *)malloc(sizeof(cache_str));
789  cache_l2_data[i]->bscan = -1;
790  cache_l2_data[i]->escan = -1;
791  cache_l2_data[i]->dataSize = 0;
792  cache_l2_data[i]->data = NULL;
793  }
794  } else if (cache_nprod < l2_str->nprod) {
795  // Allocate cache for data products if number of products increases
796 
797  for (i = 0; i < cache_nprod; i++)
798  free(cache_l2_data[i]);
799  free(cache_l2_data);
800 
801  cache_nprod = l2_str->nprod;
802  cache_l2_data = (cache_str **)malloc(sizeof(cache_str *) * cache_nprod);
803  for (i = 0; i < cache_nprod; i++) {
804  cache_l2_data[i] = (cache_str *)malloc(sizeof(cache_str));
805  cache_l2_data[i]->bscan = -1;
806  cache_l2_data[i]->escan = -1;
807  cache_l2_data[i]->dataSize = 0;
808  cache_l2_data[i]->data = NULL;
809  }
810  }
811  /* Allocate L2 data array */
812  /* ---------------------- */
813  int maxThirdDim = 1;
814  l2_str->l2_data = (float **)malloc(l2_str->nprod * sizeof(float *));
815  for (i = 0; i < l2_str->nprod; i++) {
816  l2_str->l2_data[i] = (float *)malloc(l2_str->nsamp * l2_str->thirdDim[i] * sizeof(float));
817  if (l2_str->thirdDim[i] > maxThirdDim)
818  maxThirdDim = l2_str->thirdDim[i];
819  }
820 
821  /* Allocate databuf data array */
822  /* --------------------------- */
823  allocateDatabuf(l2_str, maxThirdDim);
824 
825  /* Allocate pixnum (if applicable) */
826  /* ------------------------------- */
827  if ((ds_id_pixnum[fileindex].sid = selectDS(ds_id, "pixnum")) != -1) {
828  l2_str->pixnum = (int32_t *)calloc(l2_str->nsamp, sizeof(int32_t));
829  } else {
830  l2_str->pixnum = NULL;
831  }
832  ds_id_pixnum[fileindex].fid = ds_id.fid;
833  ds_id_pixnum[fileindex].fftype = ds_id.fftype;
834 
835  /* Read mside, detnum (if applicable) */
836  /* ---------------------------------- */
837  if (fileformat == DS_NCDF)
838  ds_id.fid = grp_id[fileindex][2];
839  if ((ds_id.sid = selectDS(ds_id, "mside")) != -1) {
840  l2_str->mside = (byte *)calloc(l2_str->nrec, sizeof(byte));
841  if (ds_id.fftype == DS_NCDF) {
842  readDS(ds_id, "mside", &zero32, NULL, &l2_str->nrec, (void *)l2_str->mside);
843  } else {
844  int32_t rank;
845  int32_t dimsizes[3];
846  int32_t ntype;
847  int32_t num_attrs;
848 
849  SDgetinfo(ds_id.sid, NULL, &rank, dimsizes, &ntype, &num_attrs);
850  if (ntype == DFNT_INT8) {
851  readDS(ds_id, "mside", &zero32, NULL, &l2_str->nrec, (void *)l2_str->mside);
852  } else {
853  int i;
854  int32_t junk[l2_str->nrec];
855 
856  readDS(ds_id, "mside", &zero32, NULL, &l2_str->nrec, (void *)junk);
857  for (i = 0; i < l2_str->nrec; i++)
858  l2_str->mside[i] = (byte)junk[i];
859  }
860  }
861  endaccessDS(ds_id);
862  } else {
863  l2_str->mside = NULL;
864  }
865 
866  if ((ds_id.sid = selectDS(ds_id, "detnum")) != -1) {
867  l2_str->detnum = (byte *)calloc(l2_str->nrec, sizeof(byte));
868  if (ds_id.fftype == DS_NCDF) {
869  readDS(ds_id, "detnum", &zero32, NULL, &l2_str->nrec, (void *)l2_str->detnum);
870  } else {
871  int32_t rank;
872  int32_t dimsizes[3];
873  int32_t ntype;
874  int32_t num_attrs;
875 
876  SDgetinfo(ds_id.sid, NULL, &rank, dimsizes, &ntype, &num_attrs);
877  if (ntype == DFNT_INT8) {
878  readDS(ds_id, "detnum", &zero32, NULL, &l2_str->nrec, (void *)l2_str->detnum);
879  } else {
880  int i;
881  int32_t junk[l2_str->nrec];
882 
883  readDS(ds_id, "detnum", &zero32, NULL, &l2_str->nrec, (void *)junk);
884  for (i = 0; i < l2_str->nrec; i++)
885  l2_str->detnum[i] = (byte)junk[i];
886  }
887  }
888  endaccessDS(ds_id);
889  } else {
890  l2_str->detnum = NULL;
891  }
892 
893  /* Read tilt data (if applicable) */
894  /* ------------------------------ */
895  if (fileformat == DS_NCDF)
896  ds_id.fid = grp_id[fileindex][1];
897  if (selectDS(ds_id, "ntilts") != -1) {
898  ds_id.sid = selectDS(ds_id, "ntilts");
899  readDS(ds_id, "ntilts", tilt_start, NULL, &one, (void *)&l2_str->ntilts);
900  ds_id.sid = selectDS(ds_id, "tilt_flags");
901  readDS(ds_id, "tilt_flags", tilt_start, NULL, tilt_edges, (void *)l2_str->tilt_flags);
902  ds_id.sid = selectDS(ds_id, "tilt_ranges");
903  readDS(ds_id, "tilt_ranges", tilt_start, NULL, tilt_edges, (void *)t_ranges);
904 
905  for (i = 0; i < l2_str->ntilts; i++) {
906  l2_str->tilt_ranges[0][i] = t_ranges[i * 2];
907  l2_str->tilt_ranges[1][i] = t_ranges[i * 2 + 1];
908  }
909  }
910 
911  /* Open L2 flags SDS */
912  /* ----------------- */
913  if (get_l2_flag_use() > 0) {
914  if (fileformat == DS_NCDF) {
915  int32_t varid;
917  "l2_flags", ds_id_file[fileindex].fid, &varid, &ds_id.fid),
918  status, "--Error-- : could not find variable %s. See %s in %d. Exiting.\n",
919  "l2_flags", __FILE__, __LINE__);
920  ds_id_l2_flags[fileindex] = (idDS){ds_id.fid, selectDS(ds_id, "l2_flags"), ds_id.fftype};
921  idDS temp_ds_id = ds_id_l2_flags[fileindex];
922  temp_ds_id.fid *= -1;
923 
924  if (ds_id_l2_flags[fileindex].sid != -1) {
925  l2_str->l2_flags = (int32_t *)calloc(l2_str->nsamp, sizeof(int32_t));
926  l2_str->flagnames = readAttrStr(temp_ds_id, "flag_meanings");
927  size_t l2_bits_size;
928  int32_t dtype;
929  nc_inq_att(ds_id_l2_flags[fileindex].fid, ds_id_l2_flags[fileindex].sid, "flag_masks", &dtype,
930  &l2_bits_size);
931  l2_str->l2_bits = calloc(l2_bits_size, sizeof(int32_t));
932  status = nc_get_att(ds_id_l2_flags[fileindex].fid, ds_id_l2_flags[fileindex].sid,
933  "flag_masks", l2_str->l2_bits);
934  if (status != NC_NOERR) {
935  printf("-E- Could not read \"%s\" in L2 file.\n", "flag_masks");
936  exit(EXIT_FAILURE);
937  }
938  if (!l2_str->flagnames) {
939  printf("-E- %s:%d - openL2 - could not find flag_meanings.\n", __FILE__, __LINE__);
940  exit(EXIT_FAILURE);
941  }
942  for (i = 0; i < strlen(l2_str->flagnames); i++) {
943  if (l2_str->flagnames[i] == ' ')
944  l2_str->flagnames[i] = ',';
945  }
946  } else {
947  l2_str->l2_flags = 0x0;
948  }
949  } else {
950  // old HDF4 flag names
951  ds_id_l2_flags[fileindex] = (idDS){ds_id.fid, selectDS(ds_id, "l2_flags"), ds_id.fftype};
952 
953  if (ds_id_l2_flags[fileindex].sid != -1) {
954  l2_str->l2_flags = (int32_t *)calloc(l2_str->nsamp, sizeof(int32_t));
955 
956  /* Read L2 flagnames */
957  /* ----------------- */
958  n_l2flags = 0;
959  listlen = 0;
960  idDS temp_ds_id = ds_id_l2_flags[fileindex];
961  temp_ds_id.fid *= -1;
962  while (1) {
963  sprintf(buffer, "f%s_name", numstr[n_l2flags]);
964  if (findAttr(temp_ds_id, buffer) != -1) {
965  tmpStr = readAttrStr(temp_ds_id, buffer);
966  listlen += strlen(tmpStr) + 1;
967  free(tmpStr);
968  n_l2flags++;
969  } else
970  break;
971  }
972  l2_str->flagnames = (char *)calloc(listlen, sizeof(char));
973  for (i = 0; i < n_l2flags; i++) {
974  sprintf(buffer, "f%s_name", numstr[i]);
975  tmpStr = readAttrStr(temp_ds_id, buffer);
976  strcat(l2_str->flagnames, tmpStr);
977  free(tmpStr);
978  if (i < n_l2flags - 1)
979  strcat(l2_str->flagnames, ",");
980  }
981  } else {
982  l2_str->l2_flags = 0x0;
983  }
984  }
985  }
986  /* Open eng_qual SDS */
987  /* ----------------- */
988  if (checkDS(ds_id_file[fileindex], "eng_qual") != -1) {
989  ds_id_eng_qual[fileindex].sid = selectDS(ds_id, "eng_qual");
990  ds_id_eng_qual[fileindex].fid = ds_id.fid;
991  ds_id_eng_qual[fileindex].fftype = ds_id.fftype;
992  } else {
993  ds_id_eng_qual[fileindex].sid = -1;
994  }
995 
996  /* Open s_flags SDS */
997  /* ---------------- */
998  if (checkDS(ds_id_file[fileindex], "s_flags") != -1) {
999  ds_id_s_flags[fileindex].sid = selectDS(ds_id, "s_flags");
1000  ds_id_s_flags[fileindex].fid = ds_id.fid;
1001  ds_id_s_flags[fileindex].fftype = ds_id.fftype;
1002  } else {
1003  ds_id_s_flags[fileindex].sid = -1;
1004  }
1005 
1006  /* Open nflag SDS */
1007  /* -------------- */
1008  if (checkDS(ds_id_file[fileindex], "nflag") != -1) {
1009  ds_id_nflag[fileindex].sid = selectDS(ds_id, "nflag");
1010  ds_id_nflag[fileindex].fid = ds_id.fid;
1011  ds_id_nflag[fileindex].fftype = ds_id.fftype;
1012  } else {
1013  ds_id_nflag[fileindex].sid = -1;
1014  }
1015 
1016  /* Read cached date fields */
1017  /* ----------------------- */
1018  if (fileformat == DS_NCDF)
1019  ds_id.fid = grp_id[fileindex][2];
1020  if (ds_id_date[fileindex][0].sid != -1) {
1021  l2_str->year_cache = (int32_t *)malloc(sizeof(int32_t) * l2_str->nrec);
1022  readDS(ds_id_date[fileindex][0], "year", &zero32, NULL, &(l2_str->nrec), l2_str->year_cache);
1023  endaccessDS(ds_id_date[fileindex][0]);
1024  }
1025 
1026  if (ds_id_date[fileindex][1].sid != -1) {
1027  l2_str->day_cache = (int32_t *)malloc(sizeof(int32_t) * l2_str->nrec);
1028  readDS(ds_id_date[fileindex][1], "day", &zero32, NULL, &(l2_str->nrec), l2_str->day_cache);
1029  endaccessDS(ds_id_date[fileindex][1]);
1030  }
1031 
1032  if (ds_id_date[fileindex][2].sid != -1) {
1033  l2_str->msec_cache = (int32_t *)malloc(sizeof(int32_t) * l2_str->nrec);
1034  readDS(ds_id_date[fileindex][2], "msec", &zero32, NULL, &(l2_str->nrec), l2_str->msec_cache);
1035  endaccessDS(ds_id_date[fileindex][2]);
1036  }
1037  // read scan
1038  ds_id.fid = scantime_grp[fileindex];
1039  if (scantime_var[fileindex] != -1) {
1040  l2_str->scantime_cache = (double *)malloc(sizeof(double) * l2_str->nrec);
1041  idDS scan_ds = (idDS){ds_id.fid, selectDS(ds_id, "scantime"), ds_id.fftype};
1042  readDS(scan_ds, "scantime", &zero32, NULL, &(l2_str->nrec), l2_str->scantime_cache);
1043  }
1044 
1045  first = 0;
1046 
1047  return 0;
1048 }
1049 
1050 int32_t reopenL2(int32_t fileindex, l2_prod *l2_str) {
1051  int32_t i;
1052  // int32_t sd_id;
1053  idDS ds_id;
1054 
1055  ds_format_t fileformat;
1056  if (Hishdf(l2_str->filename) == 1) {
1057  fileformat = DS_HDF;
1058  } else {
1059  fileformat = DS_NCDF;
1060  }
1061 
1062  ds_id = startDS(l2_str->filename, fileformat, DS_READ, 0);
1063  ds_id_file[fileindex] = ds_id;
1064 
1065  if (fileformat == DS_NCDF) {
1066  nc_inq_ncid(ds_id.fid, "sensor_band_parameters", &grp_id[fileindex][0]);
1067  nc_inq_ncid(ds_id.fid, "sensor_tilt", &grp_id[fileindex][1]);
1068  nc_inq_ncid(ds_id.fid, "scan_line_attributes", &grp_id[fileindex][2]);
1069  nc_inq_ncid(ds_id.fid, "geophysical_data", &grp_id[fileindex][3]);
1070  nc_inq_ncid(ds_id.fid, "navigation_data", &grp_id[fileindex][4]);
1071  nc_inq_ncid(ds_id.fid, "processing_control", &grp_id[fileindex][5]);
1072  }
1073 
1074  if (fileformat == DS_NCDF) {
1075  int32_t var_id, status;
1076  const char *lat_name = possible_latitude_names[name_lat_nc[fileindex]];
1077  const char *lon_name = possible_longitude_names[name_lon_nc[fileindex]];
1078  const char *filename = l2_str->filename;
1080  &grp_id_geo_lat[fileindex]),
1081  status,
1082  "--Error--: unable to find latitude after reopening %s. See %s in %d. Exiting...",
1083  filename, __FILE__, __LINE__);
1085  &grp_id_geo_lon[fileindex]),
1086  status,
1087  "--Error--: unable to find longitude after reopening %s. See %s in %d. Exiting...",
1088  filename, __FILE__, __LINE__);
1089  ds_id.fid = grp_id_geo_lon[fileindex];
1090  ds_id_ll[fileindex][0] = (idDS){ds_id.fid, selectDS(ds_id, lon_name), ds_id.fftype};
1091  if (ds_id_ll[fileindex][0].sid == -1) {
1092  printf("--Error-- : longitude can't be read after reopening %s. See %s in %d. Exiting...",
1093  filename, __FILE__, __LINE__);
1094  exit(EXIT_FAILURE);
1095  }
1096  ds_id.fid = grp_id_geo_lat[fileindex];
1097  ds_id_ll[fileindex][1] = (idDS){ds_id.fid, selectDS(ds_id, lat_name), ds_id.fftype};
1098  if (ds_id_ll[fileindex][1].sid == -1) {
1099  printf("--Error-- : latitude can't be read after reopening %s. See %s in %d. Exiting...",
1100  filename, __FILE__, __LINE__);
1101  exit(EXIT_FAILURE);
1102  }
1103  }
1104 
1105  if (l2_str->geointerp == 2) {
1106  ds_id_geonav[fileindex][0] = (idDS){ds_id.fid, selectDS(ds_id, "orb_vec"), ds_id.fftype};
1107  ds_id_geonav[fileindex][1] = (idDS){ds_id.fid, selectDS(ds_id, "sen_mat"), ds_id.fftype};
1108  ds_id_geonav[fileindex][2] = (idDS){ds_id.fid, selectDS(ds_id, "scan_ell"), ds_id.fftype};
1109  ds_id_geonav[fileindex][3] = (idDS){ds_id.fid, selectDS(ds_id, "sun_ref"), ds_id.fftype};
1110  ds_id_geonav[fileindex][5] = (idDS){ds_id.fid, selectDS(ds_id, "att_ang"), ds_id.fftype};
1111  }
1112 
1113  for (i = 0; i < l2_str->nprod; i++) {
1114  char *l2_prd;
1115  int32_t varid, status;
1116  l3_l2_conversion(&l2_str->prodname[i], &l2_prd);
1117  SHOW_NC_ERROR(find_nc_variable_parent_grp_c_interface_id_ncid(l2_prd, ds_id_file[fileindex].fid,
1118  &varid, &ds_id.fid),
1119  status,
1120  "--Error-- : could not find variable after reopening %s. See %s in %d. Exiting.\n",
1121  l2_prd, __FILE__, __LINE__);
1122  ds_id_prod[fileindex][i] = (idDS){ds_id.fid, selectDS(ds_id, l2_prd), ds_id.fftype};
1123  }
1124  if (get_l2_flag_use() > 0) {
1125  int32_t varid, status;
1126  SHOW_NC_ERROR(find_nc_variable_parent_grp_c_interface_id_ncid("l2_flags", ds_id_file[fileindex].fid,
1127  &varid, &ds_id.fid),
1128  status,
1129  "--Error-- : could not find variable after reopening %s. See %s in %d. Exiting.\n",
1130  "l2_flags", __FILE__, __LINE__);
1131  ds_id_l2_flags[fileindex] = (idDS){ds_id.fid, selectDS(ds_id, "l2_flags"), ds_id.fftype};
1132  }
1133 
1134  ds_id_eng_qual[fileindex] = (idDS){ds_id.fid, selectDS(ds_id, "eng_qual"), ds_id.fftype};
1135 
1136  ds_id_s_flags[fileindex] = (idDS){ds_id.fid, selectDS(ds_id, "s_flags"), ds_id.fftype};
1137 
1138  ds_id_nflag[fileindex] = (idDS){ds_id.fid, selectDS(ds_id, "nflag"), ds_id.fftype};
1139 
1140  ds_id_pixnum[fileindex] = (idDS){ds_id.fid, selectDS(ds_id, "pixnum"), ds_id.fftype};
1141 
1142  return 0;
1143 }
1144 
1145 //----------------------------------------------------------------
1146 // function to cache the read data
1147 // Note: make sure there is a terminating 0 at the end of scan_in_rowgroup
1148 
1149 int32_t readdata_cached(idDS ds_id, char *name, int32_t *start, int32_t *stride, int32_t *edges, void *data,
1150  unsigned char *scan_in_rowgroup, cache_str *cache, int32_t dtype) {
1151  int32_t start2[3];
1152  int32_t edges2[3];
1153  int32_t bscan;
1154  int32_t escan;
1155  int32_t nscans;
1156  int32_t size;
1157  size_t recSize = hdf_sizeof(dtype) * edges[1];
1158  char *ptr;
1159  int32_t status;
1160 #ifdef NON_CACHED
1161  status = readDS(ds_id, name, start, stride, edges, data);
1162 #else
1163 
1164  if (ds_id.fftype == DS_NCDF) {
1165  status = nc_inq_type(ds_id.fid, dtype, NULL, &recSize);
1166  check_err(status, __LINE__, __FILE__);
1167  recSize *= edges[1];
1168  if (edges[2] != 1) {
1169  recSize *= edges[2];
1170  edges2[2] = edges[2];
1171  start2[2] = 0;
1172  }
1173  }
1174 
1175  status = 0;
1176  // see if scan line is in the cache
1177  if ((start[0] < cache->bscan) || (start[0] > cache->escan)) {
1178  // find out how many lines to cache. Note: scan_in_rowgroup was
1179  // allocated with an extra 0 at the end to mark the end of lines
1180  bscan = escan = start[0];
1181  while (scan_in_rowgroup[escan] != 0)
1182  escan++;
1183  escan--;
1184  nscans = escan - bscan + 1;
1185  size = nscans * recSize;
1186  if (size > cache->dataSize) {
1187  cache->dataSize = size;
1188  if (cache->data)
1189  free(cache->data);
1190  cache->data = malloc(size);
1191  }
1192  cache->bscan = bscan;
1193  cache->escan = escan;
1194  start2[0] = bscan;
1195  start2[1] = start[1];
1196  start2[2] = start[2];
1197  edges2[0] = nscans;
1198  edges2[1] = edges[1];
1199  edges2[2] = edges[2];
1200  status = readDS(ds_id, name, start2, stride, edges2, cache->data);
1201  } // cache miss
1202 
1203  ptr = (char *)(cache->data) + (start[0] - cache->bscan) * recSize;
1204  memcpy(data, ptr, recSize);
1205 #endif
1206 
1207  return status;
1208 }
1209 
1210 void clampDeltaLon(float *deltaLon) {
1211  if (*deltaLon > 90) {
1212  if (*deltaLon > 270)
1213  *deltaLon -= 360.0;
1214  else
1215  *deltaLon -= 180.0;
1216  } else if (*deltaLon < -90) {
1217  if (*deltaLon < -270)
1218  *deltaLon += 360.0;
1219  else
1220  *deltaLon += 180.0;
1221  }
1222 }
1223 
1236 void interpolatePixelCorners(float *lat0, float *lon0, float *lat1, float *lon1, float *latOut, float *lonOut,
1237  int32_t numPoints) {
1238  // calc the delta for first point
1239  float dLat = (lat1[0] - lat0[0] + lat0[1] - lat0[0]) / 2.0;
1240  float dLon = (lon1[0] - lon0[0] + lon0[1] - lon0[0]) / 2.0;
1241  clampDeltaLon(&dLon);
1242 
1243  // first calc 0 point
1244  latOut[0] = lat1[0] - dLat;
1245  lonOut[0] = lon1[0] - dLon;
1246 
1247  // calc the rest of the points
1248  for (int i = 0; i < numPoints - 1; i++) {
1249  dLat = (lat1[i] - lat0[i] + lat0[i + 1] - lat0[i]) / 2.0;
1250  dLon = (lon1[i] - lon0[i] + lon0[i + 1] - lon0[i]) / 2.0;
1251  clampDeltaLon(&dLon);
1252 
1253  latOut[i + 1] = lat0[i] + dLat;
1254  lonOut[i + 1] = lon0[i] + dLon;
1255  }
1256 
1257  // calc last point
1258  latOut[numPoints] = lat0[numPoints - 1] + dLat;
1259  lonOut[numPoints] = lon0[numPoints - 1] + dLon;
1260 }
1261 
1274 void extrapolatePixelCorners(float *lat0, float *lon0, float *lat1, float *lon1, float *latOut, float *lonOut,
1275  int32_t numPoints) {
1276  // calc the delta for first point
1277  float dLat = (lat1[1] - lat1[0] + lat0[0] - lat1[0]) / 2.0;
1278  float dLon = (lon1[1] - lon1[0] + lon0[0] - lon1[0]) / 2.0;
1279  clampDeltaLon(&dLon);
1280 
1281  // first calc 0 point
1282  latOut[0] = lat1[0] - dLat;
1283  lonOut[0] = lon1[0] - dLon;
1284 
1285  // calc the rest of the points
1286  for (int i = 0; i < numPoints - 1; i++) {
1287  dLat = (lat1[i] - lat0[i] + lat0[i + 1] - lat0[i]) / 2.0;
1288  dLon = (lon1[i] - lon0[i] + lon0[i + 1] - lon0[i]) / 2.0;
1289  clampDeltaLon(&dLon);
1290 
1291  latOut[i + 1] = lat1[i] + dLat;
1292  lonOut[i + 1] = lon1[i] + dLon;
1293  }
1294 
1295  // calc last point
1296  latOut[numPoints] = lat1[numPoints - 1] + dLat;
1297  lonOut[numPoints] = lon1[numPoints - 1] + dLon;
1298 }
1299 
1311 void calculatePixelDeltas(float *lat0, float *lon0, float *lat1, float *lon1, float *latOut, float *lonOut,
1312  int32_t numPoints) {
1313 
1314  // bail if the new delta is more than 2x bigger than the previous line
1315  int i_center = numPoints/2;
1316  float scale_factor = 4;
1317  if(fabs(lat0[i_center]) > 73)
1318  scale_factor = 30;
1319  if(fabsf(lat0[i_center] - lat1[i_center]) > latOut[i_center] * scale_factor && latOut[i_center]!=0)
1320  return;
1321 
1322  // calc all points except the last one
1323  for (int i = 0; i < numPoints - 1; i++) {
1324  latOut[i] = fabsf(lat0[i] - lat1[i]) / 2.0;
1325  lonOut[i] = fabsf(lon0[i] - lon0[i + 1]) / 2.0;
1326  if (lonOut[i] > 90) {
1327  lonOut[i] = 180.0 - lonOut[i];
1328  }
1329  }
1330 
1331  // calc last point
1332  latOut[numPoints - 1] = latOut[numPoints - 2];
1333  lonOut[numPoints - 1] = lonOut[numPoints - 2];
1334 }
1335 
1336 int32_t readL2(l2_prod *l2_str, int32_t ifile, int32_t recnum, int32_t iprod,
1337  unsigned char *scan_in_rowgroup) {
1338  int32_t i;
1339  int32_t start[3] = {0, 0, 0};
1340  int32_t edges[3] = {1, 1, 1};
1341  int32_t ipix;
1342  int32_t ptype;
1343  int32_t status;
1344 
1345  float slp;
1346  float itp;
1347 
1348  int32_t flag_edges[2] = {1, 4};
1349  int32_t nflag_edges[2] = {1, 8};
1350 
1351  float *tmpFloat;
1352 
1353  start[0] = recnum;
1354  start[1] = 0;
1355  edges[0] = 1;
1356  edges[1] = l2_str->nsamp;
1357 
1358  /* Read L2 flags */
1359  /* ------------- */
1360  // {
1361  // printf("Reading L2 Flags : %d", get_l2_flag_use());
1362  // }
1363  if (get_l2_flag_use() > 0) {
1364  if (ds_id_l2_flags[ifile].sid != -1) {
1365  if (scan_in_rowgroup == NULL) {
1366  status =
1367  readDS(ds_id_l2_flags[ifile], "l2_flags", start, NULL, edges, (void *)l2_str->l2_flags);
1368  } else {
1369  status = readdata_cached(ds_id_l2_flags[ifile], "l2_flags", start, NULL, edges,
1370  (void *)l2_str->l2_flags, scan_in_rowgroup, &cache_l2_flags,
1371  l2_flags_type);
1372  }
1373 
1374  /* If INT16 array then convert to INT32 */
1375  /* ------------------------------------ */
1376  if (l2_flags_type == DFNT_INT16) {
1377  int16_t *ptr16 = (int16_t *)l2_str->l2_flags;
1378  for (i = l2_str->nsamp - 1; i >= 0; i--)
1379  l2_str->l2_flags[i] = ptr16[i];
1380  }
1381  }
1382  }
1383 
1384  /* Read eng_qual */
1385  /* ------------- */
1386  if (ds_id_eng_qual[ifile].sid != -1) {
1387  if (scan_in_rowgroup == NULL) {
1388  status =
1389  readDS(ds_id_eng_qual[ifile], "eng_qual", start, NULL, flag_edges, (void *)l2_str->eng_qual);
1390  } else {
1391  status = readdata_cached(ds_id_eng_qual[ifile], "eng_qual", start, NULL, flag_edges,
1392  (void *)l2_str->eng_qual, scan_in_rowgroup, &cache_eng_qual,
1393  get_dtype(DFNT_INT8, ds_id_eng_qual[ifile].fftype));
1394  }
1395  }
1396 
1397  /* Read s_flags */
1398  /* ------------ */
1399  if (ds_id_s_flags[ifile].sid != -1) {
1400  if (scan_in_rowgroup == NULL) {
1401  status =
1402  readDS(ds_id_s_flags[ifile], "s_flags", start, NULL, flag_edges, (void *)l2_str->s_flags);
1403  } else {
1404  status = readdata_cached(ds_id_s_flags[ifile], "s_flags", start, NULL, flag_edges,
1405  (void *)l2_str->s_flags, scan_in_rowgroup, &cache_s_flags,
1406  get_dtype(DFNT_INT8, ds_id_s_flags[ifile].fftype));
1407  }
1408  }
1409 
1410  /* Read nflag */
1411  /* ---------- */
1412  if (ds_id_nflag[ifile].sid != -1) {
1413  if (scan_in_rowgroup == NULL) {
1414  status = readDS(ds_id_nflag[ifile], "nflag", start, NULL, nflag_edges, (void *)l2_str->nflag);
1415  } else {
1416  status = readdata_cached(ds_id_nflag[ifile], "nflag", start, NULL, nflag_edges,
1417  (void *)l2_str->nflag, scan_in_rowgroup, &cache_nflag,
1418  get_dtype(DFNT_INT32, ds_id_nflag[ifile].fftype));
1419  }
1420  }
1421 
1422  /* Read pixnum (if applicable) */
1423  /* --------------------------- */
1424  if (ds_id_pixnum[ifile].sid != -1) {
1425  if (scan_in_rowgroup == NULL) {
1426  status = readDS(ds_id_pixnum[ifile], "pixnum", start, NULL, edges, (void *)l2_str->pixnum);
1427  } else {
1428  status = readdata_cached(ds_id_pixnum[ifile], "pixnum", start, NULL, edges,
1429  (void *)l2_str->pixnum, scan_in_rowgroup, &cache_pixnum,
1430  get_dtype(DFNT_INT32, ds_id_pixnum[ifile].fftype));
1431  }
1432  }
1433 
1434  /* Read date fields */
1435  /* ---------------- */
1436  if (ds_id_date[ifile][0].sid != -1) {
1437  l2_str->year = l2_str->year_cache[recnum];
1438  }
1439  if (ds_id_date[ifile][1].sid != -1) {
1440  l2_str->day = l2_str->day_cache[recnum];
1441  }
1442  if (ds_id_date[ifile][2].sid != -1) {
1443  l2_str->msec = l2_str->msec_cache[recnum];
1444  }
1445  if (scantime_var[ifile] != -1) {
1446  double scantime = l2_str->scantime_cache[recnum];
1447  int16_t year, day;
1448  double sec;
1449  unix2yds(scantime, &year, &day, &sec);
1450  l2_str->msec = (int32_t)(sec * 1000.0);
1451  l2_str->day = day;
1452  l2_str->year = year;
1453  }
1454  /* Main product loop */
1455  /* ----------------- */
1456  // {
1457  // printf("Products passed to readdatacahche %d \n",l2_str->nprod);
1458  // }
1459  for (i = 0; i < l2_str->nprod; i++) {
1460  if ((iprod != -1) && (i != iprod))
1461  continue;
1462  char *l2_prd;
1463  l3_l2_conversion(&l2_str->prodname[i], &l2_prd);
1464  int i_s, i_c;
1465  i_s = start[2];
1466  l3_l2_index(&l2_str->prodname[i], &i_s, &i_c);
1467  start[2] = i_s;
1468  slp = slope[ifile][i];
1469  itp = intercept[ifile][i];
1470  edges[2] = l2_str->thirdDim[i]; // edges[2] should be a loop over wavelength
1471  // prodname should have an u
1472  /* Read into data buffer */
1473  /* --------------------- */
1474  // printf("Product data is here %s \n",l2_str->prodname[i]);
1475  if (scan_in_rowgroup == NULL) {
1476  status = readDS(ds_id_prod[ifile][i], l2_prd, start, NULL, edges, (void *)databuf);
1477  } else {
1478  status = readdata_cached(ds_id_prod[ifile][i], l2_prd, start, NULL, edges, (void *)databuf,
1479  scan_in_rowgroup, cache_l2_data[i], prodtype[ifile][i]);
1480  }
1481 
1482  if (status != 0) {
1483  printf("Read Error: %d (%s) %d\n", ifile, l2_str->filename, i);
1484  exit(-1);
1485  }
1486 
1487  if (ds_id_file[ifile].fftype == DS_HDF) {
1488  ptype = prodtype[ifile][i];
1489  } else {
1490  switch (prodtype[ifile][i]) {
1491  case NC_UBYTE:
1492  ptype = DFNT_UINT8;
1493  break;
1494  case NC_BYTE:
1495  case NC_CHAR:
1496  ptype = DFNT_INT8;
1497  break;
1498  case NC_SHORT:
1499  ptype = DFNT_INT16;
1500  break;
1501  case NC_INT:
1502  ptype = DFNT_INT32;
1503  break;
1504  case NC_FLOAT:
1505  ptype = DFNT_FLOAT32;
1506  break;
1507  default:
1508  printf("-E- %s:%d - readL2 - unknown data type.\n", __FILE__, __LINE__);
1509  exit(EXIT_FAILURE);
1510  };
1511  }
1512 
1513  /* Convert to proper data type (unscale) */
1514  /* ------------------------------------- */
1515  switch (ptype) {
1516  case DFNT_UINT8: {
1517  uint8 *tmp = (uint8 *)databuf;
1518  float *result = l2_str->l2_data[i];
1519  for (ipix = 0; ipix < l2_str->nsamp * l2_str->thirdDim[i];
1520  ipix++) {
1521  if (*tmp == (uint8)l2_str->bv_scaled[i]) {
1522  *result = BAD_FLT;
1523  } else {
1524  *result = *tmp * slp + itp;
1525  }
1526  tmp++;
1527  result++;
1528  }
1529  } break;
1530 
1531  case DFNT_INT8: {
1532  int8 *tmp = (int8 *)databuf;
1533  float *result = l2_str->l2_data[i];
1534  for (ipix = 0; ipix < l2_str->nsamp * l2_str->thirdDim[i]; ipix++) {
1535  if (*tmp == (int8)l2_str->bv_scaled[i]) {
1536  *result = BAD_FLT;
1537  } else {
1538  *result = *tmp * slp + itp;
1539  }
1540  tmp++;
1541  result++;
1542  }
1543  } break;
1544 
1545  case DFNT_INT16: {
1546  int16_t *tmp = (int16_t *)databuf;
1547  float *result = l2_str->l2_data[i];
1548  for (ipix = 0; ipix < l2_str->nsamp * l2_str->thirdDim[i]; ipix++) {
1549  if (*tmp == l2_str->bv_scaled[i]) {
1550  *result = BAD_FLT;
1551  } else {
1552  *result = *tmp * slp + itp;
1553  }
1554  tmp++;
1555  result++;
1556  }
1557  } break;
1558 
1559  case DFNT_INT32: {
1560  int32_t *tmp = (int32_t *)databuf;
1561  float *result = l2_str->l2_data[i];
1562  for (ipix = 0; ipix < l2_str->nsamp * l2_str->thirdDim[i]; ipix++) {
1563  if (*tmp == l2_str->bv_scaled[i]) {
1564  *result = BAD_FLT;
1565  } else {
1566  *result = *tmp * slp + itp;
1567  }
1568  tmp++;
1569  result++;
1570  }
1571  } break;
1572 
1573  case DFNT_FLOAT32: {
1574  float *tmp = (float *)databuf;
1575  float *result = l2_str->l2_data[i];
1576  for (ipix = 0; ipix < l2_str->nsamp * l2_str->thirdDim[i]; ipix++) {
1577  *result = *tmp;
1578  tmp++;
1579  result++;
1580  }
1581  } break;
1582 
1583  }; /* end switch */
1584 
1585  } /* product loop */
1586 
1587  // reset to a 2D product
1588  edges[2] = 1;
1589 
1590  if (pixelAreaInfo.mode != L2PixelOff) {
1591  if (pixelAreaInfo.nsamp != l2_str->nsamp) {
1592  pixelAreaInfo.nsamp = l2_str->nsamp;
1593  if (pixelAreaInfo.lastLat) {
1594  free(pixelAreaInfo.lastLat);
1595  free(pixelAreaInfo.lastLon);
1596  }
1597  pixelAreaInfo.lastLat = (float *)malloc(l2_str->nsamp * sizeof(float));
1598  pixelAreaInfo.lastLon = (float *)malloc(l2_str->nsamp * sizeof(float));
1599  }
1600 
1601  // if there is no previous line, try to read it now
1602  if (pixelAreaInfo.lastLine == -1) {
1603  if (recnum > 0) {
1604  pixelAreaInfo.lastLine = recnum - 1;
1605  scan_in_rowgroup[pixelAreaInfo.lastLine] = 1;
1606  start[0] = pixelAreaInfo.lastLine;
1607  status = readlonlat(l2_str, ifile, start, edges, scan_in_rowgroup);
1608  if (status == 1) {
1609  return 5;
1610  }
1611  start[0] = recnum;
1612  }
1613  }
1614 
1615  // save lat/lon from last line
1616  tmpFloat = pixelAreaInfo.lastLat;
1617  pixelAreaInfo.lastLat = l2_str->latitude;
1618  l2_str->latitude = tmpFloat;
1619  tmpFloat = pixelAreaInfo.lastLon;
1620  pixelAreaInfo.lastLon = l2_str->longitude;
1621  l2_str->longitude = tmpFloat;
1622  }
1623 
1624  /* Read lon/lat fields */
1625  /* ----------------------------------------------------- */
1626  status = readlonlat(l2_str, ifile, start, edges, scan_in_rowgroup);
1627  if (status == 1) {
1628  return 5;
1629  }
1630 
1631  /* Check whether lon/lat values are within range */
1632  /* --------------------------------------------- */
1633  if (get_l2_flag_use() > 0) {
1634  for (i = 0; i < l2_str->nsamp; i++) {
1635  if ((l2_str->longitude[i] > 180 || l2_str->longitude[i] < -180) &&
1636  ((l2_str->l2_flags[i] & 33554432) == 0)) {
1637  printf("Scheme: %d\n", l2_str->geointerp);
1638  printf("Pixel Longitude %d out of range (%f) for scan %d in %s.\n", i, l2_str->longitude[i],
1639  recnum, l2_str->filename);
1640  exit(-1);
1641  }
1642 
1643  if ((l2_str->latitude[i] > 180 || l2_str->latitude[i] < -180) &&
1644  ((l2_str->l2_flags[i] & 33554432) == 0)) {
1645  printf("Scheme: %d\n", l2_str->geointerp);
1646  printf("Pixel Latitude %d out of range (%f) for scan %d in %s.\n", i, l2_str->latitude[i],
1647  recnum, l2_str->filename);
1648  exit(-1);
1649  }
1650  }
1651  }
1652 
1653  if (pixelAreaInfo.mode != L2PixelOff) {
1654  // last line had valid lat/lon
1655  if (pixelAreaInfo.lastLine != -1) {
1656  // check that the line number increased by 1
1657  if (recnum - pixelAreaInfo.lastLine == 1) {
1658  // check the detector num to see if we need to invalidate the previous line
1659  // OK if detnum never allocated
1660  // OK if detnum is the same. ie only one detector
1661  // OK if last detnum is 1 different from the current detnum
1662  if (l2_str->detnum && (l2_str->detnum[pixelAreaInfo.lastLine] != l2_str->detnum[recnum]) &&
1663  (abs(l2_str->detnum[pixelAreaInfo.lastLine] - l2_str->detnum[recnum]) != 1)) {
1664  pixelAreaInfo.lastLine = -1;
1665  }
1666  } else {
1667  l2_str->lat2Valid = 0;
1668 
1669  // read the previous line
1670  if (recnum > 0) {
1671  pixelAreaInfo.lastLine = recnum - 1;
1672 
1673  // check detnum
1674  if (l2_str->detnum &&
1675  (l2_str->detnum[pixelAreaInfo.lastLine] != l2_str->detnum[recnum]) &&
1676  (abs(l2_str->detnum[pixelAreaInfo.lastLine] - l2_str->detnum[recnum]) != 1)) {
1677  pixelAreaInfo.lastLine = -1;
1678  }
1679 
1680  if (pixelAreaInfo.lastLine != -1) {
1681  // save current lat/lon
1682  tmpFloat = pixelAreaInfo.lastLat;
1683  pixelAreaInfo.lastLat = l2_str->latitude;
1684  l2_str->latitude = tmpFloat;
1685  tmpFloat = pixelAreaInfo.lastLon;
1686  pixelAreaInfo.lastLon = l2_str->longitude;
1687  l2_str->longitude = tmpFloat;
1688 
1689  // read the next line
1690  start[0] = pixelAreaInfo.lastLine;
1691  start[1] = 0;
1692  edges[0] = 1;
1693  edges[1] = l2_str->nsamp;
1694  status = readlonlat(l2_str, ifile, start, edges, scan_in_rowgroup);
1695 
1696  // swap lat/lon so latitude/longitude point to the correct line
1697  tmpFloat = pixelAreaInfo.lastLat;
1698  pixelAreaInfo.lastLat = l2_str->latitude;
1699  l2_str->latitude = tmpFloat;
1700  tmpFloat = pixelAreaInfo.lastLon;
1701  pixelAreaInfo.lastLon = l2_str->longitude;
1702  l2_str->longitude = tmpFloat;
1703  }
1704  } else {
1705  pixelAreaInfo.lastLine = -1;
1706  }
1707  }
1708  }
1709 
1710  // check if we need to read the next line to calc deltas
1711  if (pixelAreaInfo.lastLine == -1) {
1712  // if next line's detector is not the same or the next detector we need to bail.
1713  if (l2_str->detnum && (l2_str->detnum[recnum + 1] != l2_str->detnum[recnum]) &&
1714  (abs(l2_str->detnum[recnum + 1] - l2_str->detnum[recnum]) != 1)) {
1715  printf(
1716  "ERROR - %s:%d - the detector number of the next line is not from the next detector.\n",
1717  __FILE__, __LINE__);
1718  printf(" Can not do area weighting on file=%s, line=%d\n", l2_str->filename, recnum);
1719  exit(EXIT_FAILURE);
1720  }
1721 
1722  // make sure we can read the next line
1723  if (recnum + 1 >= l2_str->nrec) {
1724  printf("ERROR - %s:%d - the previous line was invalid and there are no more lines to read.\n",
1725  __FILE__, __LINE__);
1726  printf(" Can not do area weighting on file=%s, line=%d\n", l2_str->filename, recnum);
1727  exit(EXIT_FAILURE);
1728  }
1729 
1730  // save current lat/lon
1731  tmpFloat = pixelAreaInfo.lastLat;
1732  pixelAreaInfo.lastLat = l2_str->latitude;
1733  l2_str->latitude = tmpFloat;
1734  tmpFloat = pixelAreaInfo.lastLon;
1735  pixelAreaInfo.lastLon = l2_str->longitude;
1736  l2_str->longitude = tmpFloat;
1737 
1738  // read the next line
1739  start[0] = recnum + 1;
1740  start[1] = 0;
1741  edges[0] = 1;
1742  edges[1] = l2_str->nsamp;
1743  status = readlonlat(l2_str, ifile, start, edges, scan_in_rowgroup);
1744 
1745  // swap lat/lon so latitude/longitude point to the correct line
1746  tmpFloat = pixelAreaInfo.lastLat;
1747  pixelAreaInfo.lastLat = l2_str->latitude;
1748  l2_str->latitude = tmpFloat;
1749  tmpFloat = pixelAreaInfo.lastLon;
1750  pixelAreaInfo.lastLon = l2_str->longitude;
1751  l2_str->longitude = tmpFloat;
1752 
1753  if (pixelAreaInfo.mode == L2PixelCorner) {
1754  extrapolatePixelCorners(pixelAreaInfo.lastLat, pixelAreaInfo.lastLon, l2_str->latitude,
1755  l2_str->longitude, l2_str->lat1, l2_str->lon1, l2_str->nsamp);
1756  interpolatePixelCorners(l2_str->latitude, l2_str->longitude, pixelAreaInfo.lastLat,
1757  pixelAreaInfo.lastLon, l2_str->lat2, l2_str->lon2, l2_str->nsamp);
1758  } else {
1759  calculatePixelDeltas(l2_str->latitude, l2_str->longitude, pixelAreaInfo.lastLat,
1760  pixelAreaInfo.lastLon, l2_str->lat1, l2_str->lon1, l2_str->nsamp);
1761  }
1762  } else {
1763  if (pixelAreaInfo.mode == L2PixelCorner) {
1764  // see if we can use lat1/lon1 from lat2/lon2
1765  if (l2_str->lat2Valid) {
1766  // move lat2/lon2 into lat1/lon1
1767  tmpFloat = l2_str->lat1;
1768  l2_str->lat1 = l2_str->lat2;
1769  l2_str->lat2 = tmpFloat;
1770  tmpFloat = l2_str->lon1;
1771  l2_str->lon1 = l2_str->lon2;
1772  l2_str->lon2 = tmpFloat;
1773  } else {
1774  interpolatePixelCorners(pixelAreaInfo.lastLat, pixelAreaInfo.lastLon, l2_str->latitude,
1775  l2_str->longitude, l2_str->lat1, l2_str->lon1, l2_str->nsamp);
1776  }
1777  extrapolatePixelCorners(pixelAreaInfo.lastLat, pixelAreaInfo.lastLon, l2_str->latitude,
1778  l2_str->longitude, l2_str->lat2, l2_str->lon2, l2_str->nsamp);
1779  } else {
1780  calculatePixelDeltas(l2_str->latitude, l2_str->longitude, pixelAreaInfo.lastLat,
1781  pixelAreaInfo.lastLon, l2_str->lat1, l2_str->lon1, l2_str->nsamp);
1782  }
1783  }
1784 
1785  // int i = 0;
1786  // printf("lat%d = %f\n", i, l2_str->latitude[i]);
1787  // printf("lon%d = %f\n", i, l2_str->longitude[i]);
1788  // printf("lat = [%f, %f, %f, %f]\n", l2_str->lat2[i+1], l2_str->lat2[i], l2_str->lat1[i],
1789  // l2_str->lat1[i+1]); printf("lon = [%f, %f, %f, %f]\n", l2_str->lon2[i+1], l2_str->lon2[i],
1790  // l2_str->lon1[i], l2_str->lon1[i+1]); printf("plt.plot(lon%d, lat%d, \"ro\")\n", i, i);
1791  // printf("plt.plot(lon, lat)\n\n");
1792  //
1793  // i = 1;
1794  // printf("lat%d = %f\n", i, l2_str->latitude[i]);
1795  // printf("lon%d = %f\n", i, l2_str->longitude[i]);
1796  // printf("lat = [%f, %f, %f, %f]\n", l2_str->lat2[i+1], l2_str->lat2[i], l2_str->lat1[i],
1797  // l2_str->lat1[i+1]); printf("lon = [%f, %f, %f, %f]\n", l2_str->lon2[i+1], l2_str->lon2[i],
1798  // l2_str->lon1[i], l2_str->lon1[i+1]); printf("plt.plot(lon%d, lat%d, \"ro\")\n", i, i);
1799  // printf("plt.plot(lon, lat)\n\n");
1800 
1801  // i = l2_str->nsamp - 2;
1802  // printf("lat%d = %f\n", i, l2_str->latitude[i]);
1803  // printf("lon%d = %f\n", i, l2_str->longitude[i]);
1804  // printf("lat = [%f, %f, %f, %f]\n", l2_str->lat2[i+1], l2_str->lat2[i], l2_str->lat1[i],
1805  // l2_str->lat1[i+1]); printf("lon = [%f, %f, %f, %f]\n", l2_str->lon2[i+1], l2_str->lon2[i],
1806  // l2_str->lon1[i], l2_str->lon1[i+1]); printf("plt.plot(lon%d, lat%d, \"ro\")\n", i, i);
1807  // printf("plt.plot(lon, lat)\n\n");
1808  //
1809  // i++;
1810  // printf("lat%d = %f\n", i, l2_str->latitude[i]);
1811  // printf("lon%d = %f\n", i, l2_str->longitude[i]);
1812  // printf("lat = [%f, %f, %f, %f]\n", l2_str->lat2[i+1], l2_str->lat2[i], l2_str->lat1[i],
1813  // l2_str->lat1[i+1]); printf("lon = [%f, %f, %f, %f]\n", l2_str->lon2[i+1], l2_str->lon2[i],
1814  // l2_str->lon1[i], l2_str->lon1[i+1]); printf("plt.plot(lon%d, lat%d, \"ro\")\n", i, i);
1815  // printf("plt.plot(lon, lat)\n\n");
1816  //
1817  //
1818  // if(recnum > 19)
1819  // exit(0);
1820 
1821  l2_str->lat2Valid = 1;
1822  pixelAreaInfo.lastLine = recnum;
1823  }
1824 
1825  return 0;
1826 }
1827 
1828 int32_t readlonlat(l2_prod *l2_str, int32_t ifile, int32_t *start, int32_t *edges,
1829  unsigned char *scan_in_rowgroup) {
1830  int32_t i;
1831  int32_t geo_edge[6] = {3, 3, 6, 3, 3, 3};
1832  int32_t edges2[3];
1833 
1834  int32_t n_cntl_pnts_removed;
1835 
1836  float delta;
1837  float *cntl_pnt_buf1;
1838  float *cntl_pnt_buf2;
1839  float lon_lat_lim = 0.1;
1840 
1841  char *geonav_name[6] = {"orb_vec", "sen_mat", "scan_ell", "sun_ref", "l_vert", "att_ang"};
1842 
1843  switch (l2_str->geointerp) {
1844  case 0:
1845 
1846  /* Read full-size lon/lat fields */
1847  /* ----------------------------- */
1848  if (scan_in_rowgroup == NULL) {
1849  readDS(ds_id_ll[ifile][0], "longitude", start, NULL, edges, (void *)l2_str->longitude);
1850  readDS(ds_id_ll[ifile][1], "latitude", start, NULL, edges, (void *)l2_str->latitude);
1851  } else {
1852  readdata_cached(ds_id_ll[ifile][0], "longitude", start, NULL, edges,
1853  (void *)l2_str->longitude, scan_in_rowgroup, &cache_longitude, DFNT_FLOAT32);
1854  readdata_cached(ds_id_ll[ifile][1], "latitude", start, NULL, edges, (void *)l2_str->latitude,
1855  scan_in_rowgroup, &cache_latitude, DFNT_FLOAT32);
1856  }
1857  break;
1858 
1859  case 1:
1860 
1861  /* Read subsampled lon/lat fields */
1862  /* ------------------------------ */
1863  edges2[0] = edges[0];
1864  edges2[1] = n_cntl_pnts;
1865  if (scan_in_rowgroup == NULL) {
1866  readDS(ds_id_ll[ifile][0], "longitude", start, NULL, edges2, (void *)l2_str->lon_cntl);
1867  readDS(ds_id_ll[ifile][1], "latitude", start, NULL, edges2, (void *)l2_str->lat_cntl);
1868  } else {
1869  readdata_cached(ds_id_ll[ifile][0], "longitude", start, NULL, edges2,
1870  (void *)l2_str->lon_cntl, scan_in_rowgroup, &cache_longitude, DFNT_FLOAT32);
1871  readdata_cached(ds_id_ll[ifile][1], "latitude", start, NULL, edges2, (void *)l2_str->lat_cntl,
1872  scan_in_rowgroup, &cache_latitude, DFNT_FLOAT32);
1873  }
1874 
1875  /* Setup buffers used to remove bad control points */
1876  /* ----------------------------------------------- */
1877  cntl_pnt_buf1 = (float *)calloc(n_cntl_pnts, sizeof(float));
1878  cntl_pnt_buf2 = (float *)calloc(n_cntl_pnts, sizeof(float));
1879 
1880  /* Interpolate Latitude */
1881  /* -------------------- */
1882 
1883  /* Remove bad lat from lat_cntl & cntl_pnts */
1884  n_cntl_pnts_removed = 0;
1885  for (i = 0; i < n_cntl_pnts; i++) {
1886  if (l2_str->lat_cntl[i] < -91 || l2_str->lat_cntl[i] > +91) {
1887  n_cntl_pnts_removed++;
1888  } else {
1889  cntl_pnt_buf1[i - n_cntl_pnts_removed] = l2_str->lat_cntl[i];
1890  cntl_pnt_buf2[i - n_cntl_pnts_removed] = l2_str->cntl_pnts_cache[i];
1891  }
1892  }
1893 
1894  if (((float)n_cntl_pnts_removed) / n_cntl_pnts > lon_lat_lim) {
1895  fprintf(stderr, "%s (Latitude failure)\n", l2_str->filename);
1896  fprintf(stderr, "More that 10%% failure.\n");
1897 
1898  return 1;
1899  }
1900 
1901  n_cntl_pnts -= n_cntl_pnts_removed;
1902 
1903  for (i = 0; i < n_cntl_pnts; i++) {
1904  l2_str->lat_cntl[i] = cntl_pnt_buf1[i];
1905  l2_str->cntl_pnts[i] = cntl_pnt_buf2[i];
1906  }
1907 
1908  spline(l2_str->cntl_pnts, l2_str->lat_cntl, n_cntl_pnts, 1e30, 1e30, l2_str->spline_arr);
1909  for (i = 0; i < l2_str->nsamp; i++) {
1910  splint(l2_str->cntl_pnts, l2_str->lat_cntl, l2_str->spline_arr, n_cntl_pnts, i + 1.0,
1911  &l2_str->latitude[i]);
1912  }
1913 
1914  // Added JMG 03/14/11
1915  n_cntl_pnts += n_cntl_pnts_removed;
1916 
1917  /* Interpolate Longitude */
1918  /* --------------------- */
1919 
1920  /* Remove bad lon from lon_cntl & cntl_pnts */
1921  n_cntl_pnts_removed = 0;
1922  for (i = 0; i < n_cntl_pnts; i++) {
1923  if (l2_str->lon_cntl[i] < -181 || l2_str->lon_cntl[i] > +181) {
1924  n_cntl_pnts_removed++;
1925  } else {
1926  cntl_pnt_buf1[i - n_cntl_pnts_removed] = l2_str->lon_cntl[i];
1927  cntl_pnt_buf2[i - n_cntl_pnts_removed] = l2_str->cntl_pnts_cache[i];
1928  }
1929  }
1930 
1931  if (((float)n_cntl_pnts_removed) / n_cntl_pnts > lon_lat_lim) {
1932  fprintf(stderr, "%s (Longitude failure)\n", l2_str->filename);
1933  fprintf(stderr, "More that 10%% failure.\n");
1934  return 1;
1935  }
1936 
1937  n_cntl_pnts -= n_cntl_pnts_removed;
1938 
1939  for (i = 0; i < n_cntl_pnts; i++) {
1940  l2_str->lon_cntl[i] = cntl_pnt_buf1[i];
1941  l2_str->cntl_pnts[i] = cntl_pnt_buf2[i];
1942  }
1943 
1944  /* Remove any dateline discontinuity in the longitudes */
1945  /* --------------------------------------------------- */
1946  for (i = 1; i < n_cntl_pnts; i++) {
1947  delta = l2_str->lon_cntl[i] - l2_str->lon_cntl[i - 1];
1948  if (delta < -180)
1949  l2_str->lon_cntl[i] += 360;
1950  else if (delta > 180)
1951  l2_str->lon_cntl[i] -= 360;
1952  }
1953 
1954  spline(l2_str->cntl_pnts, l2_str->lon_cntl, n_cntl_pnts, 1e30, 1e30, l2_str->spline_arr);
1955 
1956  for (i = 0; i < l2_str->nsamp; i++) {
1957  splint(l2_str->cntl_pnts, l2_str->lon_cntl, l2_str->spline_arr, n_cntl_pnts, i + 1.0,
1958  &l2_str->longitude[i]);
1959 
1960  /* Put the longitudes back in the [-180,180] range */
1961  /* ----------------------------------------------- */
1962  while (l2_str->longitude[i] > 180)
1963  l2_str->longitude[i] -= 360;
1964  while (l2_str->longitude[i] < -180)
1965  l2_str->longitude[i] += 360;
1966  }
1967 
1968  n_cntl_pnts += n_cntl_pnts_removed;
1969 
1970  free(cntl_pnt_buf1);
1971  free(cntl_pnt_buf2);
1972 
1973  break;
1974 
1975  case 2:
1976  edges2[0] = edges[0];
1977  edges2[2] = 3;
1978  for (i = 0; i < 4; i++) {
1979  edges2[1] = geo_edge[i];
1980  if (ds_id_geonav[ifile][i].sid != -1) {
1981  readDS(ds_id_file[ifile], geonav_name[i], start, NULL, edges2, (void *)geonav[i]);
1982  }
1983  }
1984 #ifdef GEONAV
1985  geonav_(geonav[0], geonav[1], geonav[2], geonav[3], (int32_t *)&nsta[ifile],
1986  (int32_t *)&ninc[ifile], (int32_t *)&l2_str->nsamp, l2_str->latitude, l2_str->longitude,
1987  (float *)databuf, (float *)databuf, (float *)databuf, (float *)databuf);
1988 #endif
1989  break;
1990  }
1991 
1992  return 0;
1993 }
1994 
1995 int32_t closeL2(l2_prod *l2_str, int32_t ifile) {
1996  int32_t i;
1997  int32_t status;
1998 
1999  for (i = 0; i < l2_str->nprod; i++) {
2000  if (ds_id_prod[ifile][i].sid != -1) {
2001  status = endaccessDS(ds_id_prod[ifile][i]);
2002  if (status != 0) {
2003  printf("Error ending access to product sds: %d for file: %d\n", i, ifile);
2004  exit(-1);
2005  }
2006  }
2007  }
2008 
2009  for (i = 0; i < 3; i++) {
2010  if (ds_id_ll[ifile][i].sid != -1) {
2011  ds_id_file[ifile].sid = ds_id_ll[ifile][i].sid;
2012  status = endaccessDS(ds_id_file[ifile]);
2013  if (status != 0) {
2014  printf("Error ending access to ll sds: %d for file: %d\n", i, ifile);
2015  exit(-1);
2016  }
2017  }
2018  }
2019 
2020  if (l2_str->geointerp == 2) {
2021  for (i = 0; i < 6; i++) {
2022  ds_id_file[ifile].sid = ds_id_geonav[ifile][i].sid;
2023  if (ds_id_geonav[ifile][i].sid != -1)
2024  status = endaccessDS(ds_id_file[ifile]);
2025  if (status != 0) {
2026  printf("Error ending access to geonav sds: %d for file: %d\n", i, ifile);
2027  exit(-1);
2028  }
2029  }
2030  }
2031 
2032  if (get_l2_flag_use() > 0) {
2033  if (ds_id_l2_flags[ifile].sid != -1) {
2034  status = endaccessDS(ds_id_l2_flags[ifile]);
2035  if (status != 0) {
2036  printf("Error ending access to l2_flags sds for file: %d\n", ifile);
2037  exit(-1);
2038  }
2039  }
2040  }
2041 
2042  if (ds_id_eng_qual[ifile].sid != -1) {
2043  status = endaccessDS(ds_id_eng_qual[ifile]);
2044  if (status != 0) {
2045  printf("Error ending access to eng_qual sds for file: %d\n", ifile);
2046  exit(-1);
2047  }
2048  }
2049 
2050  if (ds_id_s_flags[ifile].sid != -1) {
2051  status = endaccessDS(ds_id_s_flags[ifile]);
2052  if (status != 0) {
2053  printf("Error ending access to s_flags sds for file: %d\n", ifile);
2054  exit(-1);
2055  }
2056  }
2057 
2058  if (ds_id_nflag[ifile].sid != -1) {
2059  status = endaccessDS(ds_id_nflag[ifile]);
2060  if (status != 0) {
2061  printf("Error ending access to n_flag sds for file: %d\n", ifile);
2062  exit(-1);
2063  }
2064  }
2065 
2066  if (ds_id_pixnum[ifile].sid != -1) {
2067  status = endaccessDS(ds_id_pixnum[ifile]);
2068  if (status != 0) {
2069  printf("Error ending access to pixnum sds for file: %d\n", ifile);
2070  exit(-1);
2071  }
2072  }
2073 
2074  status = endDS(ds_id_file[ifile]);
2075  if (status != 0) {
2076  printf("Error ending access to file: %d\n", ifile);
2077  exit(-1);
2078  }
2079 
2080  return 0;
2081 }
2082 
2083 int32_t freeL2(l2_prod *l2_str) {
2084  int32_t i;
2085 
2086  if (l2_str == NULL) {
2087  for (i = 0; i < MAXNFILES; i++) {
2088  if (prodlist[i] != NULL)
2089  free(prodlist[i]);
2090  }
2091  } else {
2092  if (l2_str->geointerp == 1) {
2093  free(l2_str->lon_cntl);
2094  free(l2_str->lat_cntl);
2095  free(l2_str->spline_arr);
2096  free(l2_str->cntl_pnts);
2097  }
2098 
2099  for (i = 0; i < l2_str->nprod; i++) {
2100  free(l2_str->l2_data[i]);
2101  }
2102  free(l2_str->l2_data);
2103  free(l2_str->latitude);
2104  free(l2_str->longitude);
2105 
2106  if (l2_str->l2_flags)
2107  free(l2_str->l2_flags);
2108  if (l2_str->flagnames)
2109  free(l2_str->flagnames);
2110  if (l2_str->l2_bits)
2111  free(l2_str->l2_bits);
2112  if (l2_str->pixnum)
2113  free(l2_str->pixnum);
2114  if (l2_str->mside)
2115  free(l2_str->mside);
2116  if (l2_str->detnum)
2117  free(l2_str->detnum);
2118  if (l2_str->year_cache)
2119  free(l2_str->year_cache);
2120  if (l2_str->day_cache)
2121  free(l2_str->day_cache);
2122  if (l2_str->msec_cache)
2123  free(l2_str->msec_cache);
2124  if (l2_str->scantime_cache)
2125  free(l2_str->scantime_cache);
2126  // free area weighting variables
2127  if (l2_str->lat1)
2128  free(l2_str->lat1);
2129  if (l2_str->lon1)
2130  free(l2_str->lon1);
2131  if (l2_str->lat2)
2132  free(l2_str->lat2);
2133  if (l2_str->lon2)
2134  free(l2_str->lon2);
2135  }
2136 
2137  return 0;
2138 }
2139 
2140 int32_t findprod(l2_prod *l2_str, char *prodname) {
2141  int32_t i;
2142 
2143  for (i = 0; i < l2_str->nprod; i++) {
2144  if (strcmp(l2_str->prodname[i], prodname) == 0)
2145  return i;
2146  }
2147 
2148  return -1;
2149 }
2150 
2151 int32_t readL2meta(meta_l2Type *meta_l2, int32_t ifile) {
2152  int32_t dtype;
2153  int32_t count;
2154  idDS ds_id;
2155  int status;
2156  char *titleStr;
2157  char *infilesStr;
2158  char *sennmeStr;
2159  char *dcenterStr;
2160  char *ntimeStr;
2161  char *snodeStr;
2162  char *enodeStr;
2163  char *missionStr;
2164  char *orbnumStr;
2165  char *nlatStr;
2166  char *slatStr;
2167  char *elonStr;
2168  char *wlonStr;
2169  char *stclatStr;
2170  char *stclonStr;
2171  char *endclatStr;
2172  char *endclonStr;
2173  char *nodelStr;
2174 
2175  ds_id = ds_id_file[ifile];
2176 
2177  meta_l2->title = NULL;
2178  meta_l2->infiles = NULL;
2179  meta_l2->sensor_name = NULL;
2180  meta_l2->data_center = NULL;
2181  meta_l2->ctime = NULL;
2182  meta_l2->ntime = NULL;
2183  meta_l2->snode = NULL;
2184  meta_l2->enode = NULL;
2185  meta_l2->mission = NULL;
2186  meta_l2->mission_char = NULL;
2187  meta_l2->sensor = NULL;
2188  meta_l2->sensor_char = NULL;
2189 
2190  // fill up metadata names
2191  if (ds_id.fftype == DS_NCDF) {
2192  titleStr = TITLE;
2193  infilesStr = INFILES;
2194  sennmeStr = SENNME;
2195  dcenterStr = DCENTER;
2196  ntimeStr = NTIME;
2197  snodeStr = SNODE;
2198  enodeStr = ENODE;
2199  missionStr = MISSION;
2200  orbnumStr = ORBNUM;
2201  nlatStr = NLAT;
2202  slatStr = SLAT;
2203  elonStr = ELON;
2204  wlonStr = WLON;
2205  stclatStr = STCLAT;
2206  stclonStr = STCLON;
2207  endclatStr = ENDCLAT;
2208  endclonStr = ENDCLON;
2209  nodelStr = NODEL;
2210  } else {
2211  titleStr = TITLE_OLD;
2212  infilesStr = INFILES_OLD;
2213  sennmeStr = SENNME_OLD;
2214  dcenterStr = DCENTER_OLD;
2215  ntimeStr = NTIME_OLD;
2216  snodeStr = SNODE_OLD;
2217  enodeStr = ENODE_OLD;
2218  missionStr = MISSION_OLD;
2219  orbnumStr = ORBNUM_OLD;
2220  nlatStr = NLAT_OLD;
2221  slatStr = SLAT_OLD;
2222  elonStr = ELON_OLD;
2223  wlonStr = WLON_OLD;
2224  stclatStr = STCLAT_OLD;
2225  stclonStr = STCLON_OLD;
2226  endclatStr = ENDCLAT_OLD;
2227  endclonStr = ENDCLON_OLD;
2228  nodelStr = NODEL_OLD;
2229  }
2230 
2231  status = infoAttr(ds_id, titleStr, &dtype, &count);
2232  if (status != 0) {
2233  printf("Error - Could not find global attribute \"%s\" in file: %d\n", titleStr, ifile);
2234  exit(-1);
2235  }
2236  meta_l2->title = readAttrStr(ds_id, titleStr);
2237 
2238  if (ds_id.fftype == DS_NCDF)
2239  ds_id.fid = grp_id[ifile][5];
2240  if (findAttr(ds_id, infilesStr) != -1) {
2241  meta_l2->infiles = readAttrStr(ds_id, infilesStr);
2242  } else {
2243  if (findAttr(ds_id, "source") != -1) {
2244  meta_l2->infiles = readAttrStr(ds_id, "source");
2245  }
2246  }
2247  if (ds_id.fftype == DS_NCDF)
2248  ds_id = ds_id_file[ifile];
2249 
2250  if (findAttr(ds_id, dcenterStr) != -1) {
2251  meta_l2->data_center = readAttrStr(ds_id, dcenterStr);
2252  }
2253 
2254  if (findAttr(ds_id, NFREC) != -1)
2255  readAttr(ds_id, NFREC, (void *)&meta_l2->nfrec);
2256 
2257  if (findAttr(ds_id, PCTFLAG_OLD) != -1)
2258  readAttr(ds_id, PCTFLAG_OLD, (void *)meta_l2->flags_pc);
2259 
2260  if (findAttr(ds_id, ntimeStr) != -1) {
2261  meta_l2->ntime = readAttrStr(ds_id, ntimeStr);
2262  }
2263 
2264  if (findAttr(ds_id, snodeStr) != -1) {
2265  meta_l2->snode = readAttrStr(ds_id, snodeStr);
2266  }
2267 
2268  if (findAttr(ds_id, enodeStr) != -1) {
2269  meta_l2->enode = readAttrStr(ds_id, enodeStr);
2270  }
2271 
2272  if (ds_id.fftype == DS_HDF) {
2273  if (findAttr(ds_id, sennmeStr) != -1) {
2274  meta_l2->sensor_name = readAttrStr(ds_id, sennmeStr);
2275  }
2276 
2277  if (findAttr(ds_id, missionStr) != -1) {
2278  meta_l2->mission = readAttrStr(ds_id, missionStr);
2279  }
2280 
2281  int sensorID = sensorName2SensorId(meta_l2->sensor_name);
2282  if (sensorID < 0)
2283  meta_l2->sensor = NULL;
2284  else
2285  meta_l2->sensor = strdup(sensorId2InstrumentName(sensorID));
2286  } else {
2287  if (findAttr(ds_id, sennmeStr) != -1) {
2288  meta_l2->sensor = readAttrStr(ds_id, sennmeStr);
2289  }
2290 
2291  if (findAttr(ds_id, missionStr) != -1) {
2292  meta_l2->mission = readAttrStr(ds_id, missionStr);
2293  }
2294 
2295  meta_l2->sensor_name = strdup(instrumentPlatform2SensorName(meta_l2->sensor, meta_l2->mission));
2296  }
2297 
2298  if (findAttr(ds_id, MSNCHAR) != -1) {
2299  meta_l2->mission_char = readAttrStr(ds_id, MSNCHAR);
2300  }
2301 
2302  if (findAttr(ds_id, SNSCHAR) != -1) {
2303  meta_l2->sensor_char = readAttrStr(ds_id, SNSCHAR);
2304  }
2305 
2306  readAttr(ds_id, orbnumStr, (void *)&meta_l2->orbnum);
2307  readAttr(ds_id, nlatStr, (void *)&meta_l2->northlat);
2308  readAttr(ds_id, slatStr, (void *)&meta_l2->southlat);
2309  readAttr(ds_id, wlonStr, (void *)&meta_l2->westlon);
2310  readAttr(ds_id, elonStr, (void *)&meta_l2->eastlon);
2311  readAttr(ds_id, stclatStr, (void *)&meta_l2->startclat);
2312  readAttr(ds_id, stclonStr, (void *)&meta_l2->startclon);
2313  readAttr(ds_id, endclatStr, (void *)&meta_l2->endclat);
2314  readAttr(ds_id, endclonStr, (void *)&meta_l2->endclon);
2315  readAttr(ds_id, nodelStr, (void *)&meta_l2->nodel);
2316 
2317  if (findAttr(ds_id, LAC_PX_ST) != -1)
2318  readAttr(ds_id, LAC_PX_ST, (void *)&meta_l2->pix_start);
2319  if (findAttr(ds_id, LAC_PX_SUBSAMP) != -1)
2320  readAttr(ds_id, LAC_PX_SUBSAMP, (void *)&meta_l2->pix_sub);
2321 
2322  return 0;
2323 }
2324 
2325 int32_t freeL2meta(meta_l2Type *meta_l2) {
2326 #define FREE(ptr) \
2327  if ((ptr) != 0x0) \
2328  free(ptr);
2329 
2330  FREE(meta_l2->title);
2331  FREE(meta_l2->infiles);
2332  FREE(meta_l2->sensor_name);
2333  FREE(meta_l2->data_center);
2334  FREE(meta_l2->ctime);
2335  FREE(meta_l2->ntime);
2336  FREE(meta_l2->snode);
2337  FREE(meta_l2->enode);
2338  FREE(meta_l2->mission);
2339  FREE(meta_l2->mission_char);
2340  FREE(meta_l2->sensor);
2341  FREE(meta_l2->sensor_char);
2342 
2343  return 0;
2344 }
2345 
2346 int32_t getL3units(l2_prod *l2_str, int32_t ifile, char *l3b_prodname, char *units) {
2347  intn i;
2348 
2349  char bufnum[128];
2350  char bufden[128];
2351  char *char_ptr;
2352  char *tmpStr;
2353 
2354  char_ptr = strchr(l3b_prodname, '/');
2355  if (char_ptr != NULL)
2356  *char_ptr = 0;
2357 
2358  memset(bufnum, 0, 128);
2359  memset(bufden, 0, 128);
2360  for (i = 0; i < l2_str[ifile].nprod; i++) {
2361  if (strcmp(l3b_prodname, l2_str[ifile].prodname[i]) == 0) {
2362  idDS ds_id0 = {-ds_id_prod[ifile][i].fid, ds_id_prod[ifile][i].sid, ds_id_prod[ifile][i].fftype};
2363  tmpStr = readAttrStr(ds_id0, "units");
2364  if (tmpStr) {
2365  strncpy(bufnum, tmpStr, 127);
2366  free(tmpStr);
2367  } else
2368  strcpy(bufnum, "undefined");
2369  break;
2370  }
2371  }
2372 
2373  if (char_ptr != NULL) {
2374  for (i = 0; i < l2_str[ifile].nprod; i++) {
2375  if (strcmp(char_ptr + 1, l2_str[ifile].prodname[i]) == 0) {
2376  idDS ds_id0 = {-ds_id_prod[ifile][i].fid, ds_id_prod[ifile][i].sid,
2377  ds_id_prod[ifile][i].fftype};
2378  tmpStr = readAttrStr(ds_id0, "units");
2379  if (tmpStr) {
2380  strncpy(bufden, tmpStr, 127);
2381  free(tmpStr);
2382  } else
2383  strcpy(bufden, "undefined");
2384  break;
2385  }
2386  }
2387 
2388  if (strcmp(bufnum, bufden) == 0) {
2389  if (strcmp(bufnum, "undefined") == 0)
2390  strcpy(units, "undefined");
2391  else
2392  strcpy(units, "dimensionless");
2393  } else if (strcmp(bufnum, "dimensionless") == 0) {
2394  strcpy(units, "1 / ");
2395  strcat(units, bufden);
2396  } else if (strcmp(bufden, "dimensionless") == 0) {
2397  strcpy(units, bufnum);
2398  } else {
2399  strcpy(units, bufnum);
2400  strcat(units, " / ");
2401  strcat(units, bufden);
2402  }
2403 
2404  *char_ptr = '_';
2405  } else {
2406  strcpy(units, bufnum);
2407  }
2408 
2409  return 0;
2410 }
@ L2PixelOff
Definition: readL2scan.h:163
@ DS_READ
Definition: dfutils.h:24
#define SLAT
Definition: readL2scan.c:96
#define ELON_OLD
Definition: readL2scan.c:101
int32_t readdata_cached(idDS ds_id, char *name, int32_t *start, int32_t *stride, int32_t *edges, void *data, unsigned char *scan_in_rowgroup, cache_str *cache, int32_t dtype)
Definition: readL2scan.c:1149
int32_t reopenL2(int32_t fileindex, l2_prod *l2_str)
Definition: readL2scan.c:1050
#define NTIME
Definition: readL2scan.c:81
int getDimsDS(idDS ds_id, const char sdsname[], int32_t dims[])
#define NFREC
Definition: readL2scan.c:78
int32_t day
void allocateDatabuf(l2_prod *l2_str, int maxThirdDim)
Definition: readL2scan.c:304
int status
Definition: l1_czcs_hdf.c:32
int infoAttr(idDS ds_id, const char *nam, int32_t *dtype, int32_t *count)
Definition: wrapper.c:188
#define NODEL_OLD
Definition: readL2scan.c:111
const char * possible_latitude_names[NUM_LATLON_NAME]
Definition: readL2scan.c:200
void check_err(const int stat, const int line, const char *file)
Definition: nc4utils.c:35
#define NODEL
Definition: readL2scan.c:110
int32_t lastLine
Definition: readL2scan.c:205
#define PCTFLAG_OLD
Definition: readL2scan.c:80
#define LAC_PX_SUBSAMP
Definition: readL2scan.c:113
int32_t selectDS(idDS ds_id, const char *l2_prod_names)
Definition: wrapper.c:435
int32_t hdf_sizeof(int32_t dtype)
return the sizeof dtype in bytes
Definition: hdf_utils.c:28
@ L2PixelCorner
Definition: readL2scan.h:163
#define ENDCLON
Definition: readL2scan.c:108
int32_t find_nc_variable_parent_grp_c_interface_id_ncid(const char *var_name, int32_t ncid, int32_t *netcdf_c_var_id, int32_t *netcdf_c_grp_id)
Recursively searches for a netcdf variable within an NC file or group. Search is recursive ( DFS tree...
Definition: find_variable.c:4
void * allocateMemory(size_t numBytes, const char *name)
Definition: allocateMemory.c:7
enum L2PixelMode_t mode
Definition: readL2scan.c:204
int32_t prodtype_t[1000]
Definition: readL2scan.c:143
#define NULL
Definition: decode_rs.h:63
#define ENODE_OLD
Definition: readL2scan.c:86
int32_t escan
Definition: readL2scan.c:124
int32_t readL2meta(meta_l2Type *meta_l2, int32_t ifile)
Definition: readL2scan.c:2151
#define STCLON
Definition: readL2scan.c:104
#define ENDCLAT_OLD
Definition: readL2scan.c:107
int32_t find_nc_variable_possible_names(const char *possible_names[], int32_t number_of_names, int32_t ncid, int32_t *netcdf_c_var_id, int32_t *netcdf_c_grp_id, int32_t *file_index_name)
Definition: find_variable.c:29
#define SNSCHAR
Definition: readL2scan.c:91
int geonav_(FLOAT32 pos[3], FLOAT32 rm[3][3], FLOAT32 coef[6], FLOAT32 sunref[3], INT32 *spix, INT32 *ipix, INT32 *npix, FLOAT32 lat[], FLOAT32 lon[], FLOAT32 solz[], FLOAT32 sola[], FLOAT32 senz[], FLOAT32 sena[])
#define NLAT
Definition: readL2scan.c:94
#define WLON_OLD
Definition: readL2scan.c:99
int sensorName2SensorId(const char *name)
Definition: sensorInfo.c:371
int getTypeDS(idDS ds_id, const char sdsname[HDF4_UTILS_MAX_NAME], int32_t *dtype)
subroutine spline(s, x, y, n, in, t, il, iu, vl, vu, e, u)
Definition: phs.f:1348
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT32
int32_t freeL2meta(meta_l2Type *meta_l2)
Definition: readL2scan.c:2325
#define SHOW_NC_ERROR(func, err,...)
Definition: readL2scan.c:116
#define ENDCLON_OLD
Definition: readL2scan.c:109
int32_t readL2(l2_prod *l2_str, int32_t ifile, int32_t recnum, int32_t iprod, unsigned char *scan_in_rowgroup)
Definition: readL2scan.c:1336
ds_format_t fftype
Definition: dfutils.h:31
#define DCENTER
Definition: readL2scan.c:76
int32_t closeL2(l2_prod *l2_str, int32_t ifile)
Definition: readL2scan.c:1995
int get_set_flag()
Definition: expand3D.cpp:434
#define LAC_PX_ST
Definition: readL2scan.c:112
#define SNODE
Definition: readL2scan.c:83
int readAttr(idDS ds_id, const char *nam, void *data)
#define ORBNUM_OLD
Definition: readL2scan.c:93
int endaccessDS(idDS ds_id)
Definition: wrapper.c:617
int32_t bscan
Definition: readL2scan.c:123
void l3_l2_conversion(char **inp3, char **out2)
Definition: expand3D.cpp:413
void init_rowgroup_cache()
Definition: readL2scan.c:287
void l3_l2_index(char **inp3, int *start, int *count)
Definition: expand3D.cpp:428
#define MISSION_OLD
Definition: readL2scan.c:88
def cache(filename, recache=False)
Definition: utils.py:145
void enableL2PixelArea(enum L2PixelMode_t val)
Definition: readL2scan.c:213
data_t tmp
Definition: decode_rs.h:74
#define WLON
Definition: readL2scan.c:98
read recnum
char * readAttrStr(idDS ds_id, const char *name)
Definition: wrapper.c:99
idDS ds_id_geonav_t[6]
Definition: readL2scan.c:154
#define NLAT_OLD
Definition: readL2scan.c:95
#define SNODE_OLD
Definition: readL2scan.c:84
int32_t openL2(const char *fname, const char *plist, l2_prod *l2_str)
Definition: readL2scan.c:316
#define NTIME_OLD
Definition: readL2scan.c:82
int32_t get_dtype(int32_t dtype, ds_format_t fileformat)
Definition: readL2scan.c:231
int getProdlist(const char *fname, char **prodlist, int32_t *l2_flags_type)
Definition: wrapper.c:711
char * strdup(const char *)
idDS startDS(const char *filename, ds_format_t format, ds_access_t accessmode, int32_t deflate)
Definition: wrapper.c:558
float slope_t[1000]
Definition: readL2scan.c:146
float32 slope[]
Definition: l2lists.h:30
int8_t findAttr(idDS ds_id, const char *nam)
Definition: wrapper.c:46
void free_rowgroup_cache()
Definition: readL2scan.c:259
int32_t checkDS(idDS ds_id, const char *l2_prod_name)
Definition: wrapper.c:452
#define TITLE_OLD
Definition: readL2scan.c:71
#define SLAT_OLD
Definition: readL2scan.c:97
const double delta
#define MISSION
Definition: readL2scan.c:87
#define ORBNUM
Definition: readL2scan.c:92
void unix2yds(double usec, short *year, short *day, double *secs)
char filename[FILENAME_MAX]
Definition: atrem_corl1.h:122
#define DCENTER_OLD
Definition: readL2scan.c:77
idDS ds_id_prod_t[1000]
Definition: readL2scan.c:140
float32 intercept[]
Definition: l2lists.h:44
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT16
float * lastLon
Definition: readL2scan.c:209
void isodate2ydmsec(char *date, int32_t *year, int32_t *day, int32_t *msec)
Definition: date2ydmsec.c:20
@ DS_NCDF
Definition: dfutils.h:20
#define MAXNFILES
Definition: l3bin.cpp:20
int readDS(idDS ds_id, const char *name, int32_t *start, int32_t *stride, int32_t *count, void *data)
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
int32_t sid
Definition: dfutils.h:30
#define BAD_FLT
Definition: jplaeriallib.h:19
L2PixelMode_t
Definition: readL2scan.h:163
float * lastLat
Definition: readL2scan.c:208
idDS ds_id_ll_t[3]
Definition: readL2scan.c:150
#define TITLE
Definition: readL2scan.c:70
#define INFILES
Definition: readL2scan.c:72
#define STCLON_OLD
Definition: readL2scan.c:105
int32_t dataSize
Definition: readL2scan.c:125
dtype
Definition: DDataset.hpp:31
#define fabs(a)
Definition: misc.h:93
void calculatePixelDeltas(float *lat0, float *lon0, float *lat1, float *lon1, float *latOut, float *lonOut, int32_t numPoints)
Definition: readL2scan.c:1311
#define SENNME
Definition: readL2scan.c:74
int32_t fid
Definition: dfutils.h:29
Extra metadata that will be written to the HDF4 file l2prod rank
void clampDeltaLon(float *deltaLon)
Definition: readL2scan.c:1210
const char * sensorId2InstrumentName(int sensorId)
Definition: sensorInfo.c:287
#define INIT_DELTA
Definition: readL2scan.c:115
subroutine splint(xa, ya, y2a, n, x, y)
PARAM_TYPE_NONE Default value No parameter is buried in the product name name_prefix is case insensitive string compared to the product name PARAM_TYPE_VIS_WAVE The visible wavelength bands from the sensor are buried in the product name The product name is compared by appending and name_suffix ie aph_412_giop where prod_ix will be set to PARAM_TYPE_IR_WAVE same search method as PARAM_TYPE_VIS_WAVE except only wavelength above are looped through but prod_ix is still based ie aph_2_giop for the second and prod_ix set to PARAM_TYPE_INT name_prefix is compared with the beginning of the product name If name_suffix is not empty the it must match the end of the product name The characters right after the prefix are read as an integer and prod_ix is set to that number strncpy(l2prod->name_prefix, "myprod", UNITLEN)
const char * possible_longitude_names[NUM_LATLON_NAME]
Definition: readL2scan.c:201
@ DS_HDF
Definition: dfutils.h:19
Definition: dfutils.h:28
#define ELON
Definition: readL2scan.c:100
#define ENODE
Definition: readL2scan.c:85
for(i=0;i< NROOTS;i++) s[i]
Definition: decode_rs.h:85
#define STCLAT
Definition: readL2scan.c:102
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_FLOAT32
ds_format_t
Definition: dfutils.h:18
void * data
Definition: readL2scan.c:126
int32_t getL3units(l2_prod *l2_str, int32_t ifile, char *l3b_prodname, char *units)
Definition: readL2scan.c:2346
void extrapolatePixelCorners(float *lat0, float *lon0, float *lat1, float *lon1, float *latOut, float *lonOut, int32_t numPoints)
Definition: readL2scan.c:1274
int endDS(idDS ds_id)
Definition: wrapper.c:624
#define SENNME_OLD
Definition: readL2scan.c:75
#define abs(a)
Definition: misc.h:90
int i
Definition: decode_rs.h:71
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
const char * instrumentPlatform2SensorName(const char *instrument, const char *platform)
Definition: sensorInfo.c:473
int32_t sensorID[MAXNFILES]
Definition: l2bin.cpp:91
int32_t freeL2(l2_prod *l2_str)
Definition: readL2scan.c:2083
#define INFILES_OLD
Definition: readL2scan.c:73
#define ENDCLAT
Definition: readL2scan.c:106
void interpolatePixelCorners(float *lat0, float *lon0, float *lat1, float *lon1, float *latOut, float *lonOut, int32_t numPoints)
Definition: readL2scan.c:1236
int32_t grp_id_t[6]
Definition: readL2scan.c:157
#define NUM_LATLON_NAME
Definition: readL2scan.c:114
#define MSNCHAR
Definition: readL2scan.c:89
int get_l2_flag_use()
Definition: expand3D.cpp:437
int32_t findprod(l2_prod *l2_str, char *prodname)
Definition: readL2scan.c:2140
#define STCLAT_OLD
Definition: readL2scan.c:103
#define FREE(ptr)
int count
Definition: decode_rs.h:79
int32_t readlonlat(l2_prod *l2_str, int32_t ifile, int32_t *start, int32_t *edges, unsigned char *scan_in_rowgroup)
Definition: readL2scan.c:1828