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