NASA Logo
Ocean Color Science Software

ocssw V2022
l2_str.cpp
Go to the documentation of this file.
1 //
2 // l2_str.cpp
3 //
4 //
5 // Created by Martin Montes on 2/11/2022
6 #include "l2_str.h"
7 #include <iostream>
8 #include <string>
9 #include "l1c_filehandle.h"
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <math.h>
13 #include <stdbool.h>
14 #include <stdint.h>
15 #include <netcdf.h>
16 #include <nc4utils.h>
17 #include "libnav.h"
18 #include <timeutils.h>
19 #include <genutils.h>
20 
21 #include "allocate4d.h"
22 #include <allocate3d.h>
23 #include <allocate2d.h>
24 
25 #include <boost/foreach.hpp>
26 #include <boost/algorithm/string.hpp>
27 
28 static short *tmpShort;
29 
30 // whole file stuff
31 static size_t expected_number_of_bands = 239; // OCIS
32 static size_t nviews;
33 static size_t num_scans, num_pixels, number_of_bands;
34 static int ncid_L1B;
35 
36 // scan line attributes
37 static double *scan_time; // seconds of day
38 static int32_t scan_time_year, scan_time_month, scan_time_day;
39 
40 // static uint_8 *scan_quality;
41 
42 // geolocation data
43 static int geolocationGrp;
44 static int tiltId, lonId, latId, prodims[345]; // #345 of potential L2 products is from product.h
45 static float latFillValue = -999.0;
46 static float lonFillValue = -999.0;
47 
48 static float tiltmin = 0.0, tiltmax = 0.0;
49 static float tiltFillValue = -999.0;
50 
51 // Observation data
52 static int observationGrp;
53 
54 // Navigation data
55 static int status, dimid;
56 
57 using namespace std;
58 
59 namespace l1c {
60 
61 l2_str::l2_str()
62  : att_ang{-999.0, -999.0, -999.0}, orb_pos{-999.0, -999.0, -999.0}, orb_vel{-999.0, -999.0, -999.0} {
63  // init constructor
64  // global attributes
65  npix = -1;
66  iscan = 0;
67  nscan = -1;
68  // scan line attributes--
69  ev_mid_time = nullptr;
70  scan_quality_flag = nullptr;
71  spix = -1;
72  epix = -1;
73  dpix = -1;
74 
75  // structure--pointers to data arrays
76  Lt = nullptr; // dim depends between sensors--OCI is bands x pixels --
77  Lt_blue = nullptr; //[num_views][num_pol][num_blue_bands][num_pixels]
78  Lt_red = nullptr;
79  Lt_SWIR = nullptr;
80 
81  l2prod = nullptr;
82  nl2prod = -1;
83  slopeprod = nullptr;
84  offsetprod = nullptr;
85  tilt = nullptr;
86 
87  // sensor/sun geometry
88  senz = nullptr;
89  sena = nullptr;
90  solz = nullptr;
91  sola = nullptr;
92  delphi = nullptr;
93  scattang = nullptr;
94 
95  // geolocation--
96  senazpix = nullptr;
97  latpix = nullptr;
98  lonpix = nullptr;
99  latpix2 = nullptr;
100  lonpix2 = nullptr;
101 
102  l1cfile = nullptr;
103 
104  // ancill info?
105 }
106 
108 }
109 
110 int32_t l2_str::openl2_ocis_l1c(L1C_input *l1cinput, l2_str *l2str, l1c_filehandle *l1cfile,
111  int16_t *file_id) {
113  const char *ptstr;
114 
115  string delim1 = ":, "; // product delimiters
116  string l2prod_str = l1cinput->l2prod;
117  boost::trim_if(l2prod_str, boost::is_any_of(delim1));
118  vector<string> prodparam;
119  boost::algorithm::split(prodparam, l2prod_str, boost::is_any_of(delim1));
120  if(l1cinput->verbose) cout << "number of L2 products to be processed...................#:..." << prodparam.size() << endl;
121  for (size_t iprod = 0; iprod < prodparam.size(); iprod++) {
122  if(l1cinput->verbose) cout << "selected L2 ----------- prodparam...." << prodparam[iprod] << endl;
123  }
124 
125  // nl2prod member of l2_str
126  nl2prod = prodparam.size(); // number of selected l2 products
127 
128  str = l1cfile->l1b_name;
129  ptstr = str.c_str();
130  printf("Opening OCIS L2 file\n");
131  cout << str << endl;
132 
133  status = nc_open(ptstr, NC_NOWRITE, &ncid_L1B);
134  if (status != NC_NOERR) {
135  fprintf(stderr, "-E- %s line %d: nc_open(%s) failed.\n", __FILE__, __LINE__, ptstr);
136  return (1);
137  }
138 
139  // num_scans
140  status = nc_inq_dimid(ncid_L1B, "number_of_lines", &dimid);
141  if (status != NC_NOERR) {
142  fprintf(stderr, "-E- Error reading number_of_scans.\n");
143  exit(EXIT_FAILURE);
144  }
145  nc_inq_dimlen(ncid_L1B, dimid, &num_scans);
146  l2str->nscan = num_scans;
147 
148  // num_pixels
149  status = nc_inq_dimid(ncid_L1B, "pixels_per_line", &dimid);
150  if (status != NC_NOERR) {
151  fprintf(stderr, "-E- Error reading num_pixels.\n");
152  exit(EXIT_FAILURE);
153  }
154  nc_inq_dimlen(ncid_L1B, dimid, &num_pixels);
155  l2str->npix = num_pixels;
156 
157  // number of bands
158  status = nc_inq_dimid(ncid_L1B, "number_of_bands", &dimid);
159  if (status != NC_NOERR) {
160  fprintf(stderr, "-E- Error reading number of_bands.\n");
161  exit(EXIT_FAILURE);
162  }
163  nc_inq_dimlen(ncid_L1B, dimid, &number_of_bands);
164  if (number_of_bands < expected_number_of_bands) {
165  fprintf(stderr, "-E- Not enough bands, expecting %d, found %d.\n", (int)expected_number_of_bands,
166  (int)number_of_bands);
167  exit(EXIT_FAILURE);
168  }
169 
170  // if (want_verbose) {
171  printf("OCI L2 Npix :%d Nlines:%d\n", (int)num_pixels, (int)num_scans);
172  // } // want_verbose
173 
174  // allocate all of the data
175  tmpShort = (short *)calloc(num_pixels, sizeof(short));
176  scan_time = (double *)calloc(num_scans, sizeof(double));
177  l2str->tilt = (float *)calloc(num_scans, sizeof(float));
178  l2str->latpix = (float *)calloc(num_pixels, sizeof(float));
179  l2str->lonpix = (float *)calloc(num_pixels, sizeof(float));
180  l2str->l2prod = allocate2d_float(nl2prod, num_pixels);
181 
182  // Get group id from L1B file for GROUP scan_line_attributes.
183  int groupid;
184  if ((nc_inq_grp_ncid(ncid_L1B, "scan_line_attributes", &groupid)) == NC_NOERR) {
185  } else {
186  fprintf(stderr, "-E- Error finding scan_line_attributes.\n");
187  exit(EXIT_FAILURE);
188  }
189  int varid;
190  double scan_timeFillValue = -999.9;
191  status = nc_inq_varid(groupid, "time", &varid);
192  if (status == NC_NOERR) {
193  status = nc_inq_var_fill(groupid, varid, NULL, &scan_timeFillValue);
194  check_err(status, __LINE__, __FILE__);
195  status = nc_get_var_double(groupid, varid, scan_time);
196  check_err(status, __LINE__, __FILE__);
197  status = nc_get_att_int(groupid, varid, "year", &scan_time_year);
198  check_err(status, __LINE__, __FILE__);
199  status = nc_get_att_int(groupid, varid, "month", &scan_time_month);
200  check_err(status, __LINE__, __FILE__);
201  status = nc_get_att_int(groupid, varid, "day", &scan_time_day);
202  check_err(status, __LINE__, __FILE__);
203  } else {
204  status = nc_inq_varid(groupid, "msec", &varid);
205  check_err(status, __LINE__, __FILE__);
206  status = nc_inq_var_fill(groupid, varid, NULL, &scan_timeFillValue);
207  check_err(status, __LINE__, __FILE__);
208  status = nc_get_var_double(groupid, varid, scan_time);
209  check_err(status, __LINE__, __FILE__);
210 
211  // get start time
212  size_t att_len;
213  status = nc_inq_attlen(ncid_L1B, NC_GLOBAL, "time_coverage_start", &att_len);
214  check_err(status, __LINE__, __FILE__);
215 
216  // allocate required space before retrieving values
217  char *time_str = (char *)malloc(att_len + 1); // + 1 for trailing null
218 
219  // get attribute values
220  status = nc_get_att_text(ncid_L1B, NC_GLOBAL, "time_coverage_start", time_str);
221  check_err(status, __LINE__, __FILE__);
222  time_str[att_len] = '\0';
223 
224  double start_time = isodate2unix(time_str);
225  int16_t syear, smon, sday;
226  double secs;
227  unix2ymds(start_time, &syear, &smon, &sday, &secs);
228  scan_time_year = syear;
229  scan_time_month = smon;
230  scan_time_day = sday;
231  }
232 
233  for (size_t i = 0; i < num_scans; i++) {
234  if (scan_time[i] == scan_timeFillValue)
235  scan_time[i] = BAD_FLT;
236  }
237 
238  // read the orbit#
239  int orbit_number;
240  status = nc_get_att_int(ncid_L1B, NC_GLOBAL, "orbit_number", &orbit_number);
241  check_err(status, __LINE__, __FILE__);
242 
243  // Setup geofile pointers
244  status = nc_inq_grp_ncid(ncid_L1B, "navigation_data", &geolocationGrp);
245  check_err(status, __LINE__, __FILE__);
246  status = nc_inq_varid(geolocationGrp, "longitude", &lonId);
247  check_err(status, __LINE__, __FILE__);
248 
249  status = nc_inq_var_fill(geolocationGrp, lonId, NULL, &lonFillValue);
250  check_err(status, __LINE__, __FILE__);
251  status = nc_inq_varid(geolocationGrp, "latitude", &latId);
252  check_err(status, __LINE__, __FILE__);
253  status = nc_inq_var_fill(geolocationGrp, latId, NULL, &latFillValue);
254  check_err(status, __LINE__, __FILE__);
255 
256  status = nc_inq_varid(geolocationGrp, "tilt", &tiltId); // number of lines
257  check_err(status, __LINE__, __FILE__);
258  status = nc_inq_var_fill(geolocationGrp, tiltId, NULL, &tiltFillValue);
259  check_err(status, __LINE__, __FILE__);
260  status = nc_get_att_float(geolocationGrp, tiltId, "valid_min", &tiltmin);
261  check_err(status, __LINE__, __FILE__);
262  status = nc_get_att_float(geolocationGrp, tiltId, "valid_max", &tiltmax);
263  check_err(status, __LINE__, __FILE__);
264 
265  // get IDs for the observations
266  status = nc_inq_grp_ncid(ncid_L1B, "geophysical_data", &observationGrp);
267  check_err(status, __LINE__, __FILE__);
268 
269  for (size_t iprod = 0; iprod < nl2prod; iprod++) {
270  if(l1cinput->verbose) cout << "getting sds id for product.." << prodparam[iprod].c_str() << endl;
271  status = nc_inq_varid(observationGrp, prodparam[iprod].c_str(), &prodims[iprod]);
272  check_err(status, __LINE__, __FILE__);
273  }
274 
275  // slope offset of products
276  l2str->slopeprod = (float *)calloc(nl2prod, sizeof(float));
277  l2str->offsetprod = (float *)calloc(nl2prod, sizeof(float));
278 
279  string ATT_NAME1 = "scale_factor", ATT_NAME2 = "add_offset";
280  for (size_t iprod = 0; iprod < nl2prod; iprod++) {
281  if (nc_get_att_float(observationGrp, prodims[iprod], ATT_NAME1.c_str(), &l2str->slopeprod[iprod]))
282  check_err(status, __LINE__, __FILE__);
283  if (nc_get_att_float(observationGrp, prodims[iprod], ATT_NAME2.c_str(), &l2str->offsetprod[iprod]))
284  check_err(status, __LINE__, __FILE__);
285  }
286 
287  // tilt
288  status = nc_get_var_float(geolocationGrp, tiltId, l2str->tilt);
289  check_err(status, __LINE__, __FILE__);
290 
291  // l1cfile class---
292  l1cfile->sd_id = ncid_L1B;
293  l1cfile->nbands = number_of_bands;
294  nviews = 2;
295  l1cfile->n_views = nviews;
296 
297  cout << "number of bands =" << l1cfile->nbands << endl;
298 
299  l1cfile->npix = num_pixels;
300  l1cfile->nadpix = (num_pixels - 1) / 2; // nadir pixel index
301  l1cfile->nscan = num_scans;
302  l1cfile->ndets = 1;
303  l1cfile->terrain_corrected = 1; // presumed.
304  l1cfile->orbit_number = orbit_number;
305 
306  return 0;
307 }
308 
309 int32_t l2_str::readl2_ocis_l1c(l2_str *l2str, l1c_filehandle *l1cfile, int16_t *file_id, int32_t sline) {
310  size_t start[] = {0, 0};
311  size_t count[] = {1, 1};
312 
313  string str;
314  str = l1cfile->l1b_name;
315  printf("Reading OCIS L2 file\n");
316  cout << str << endl;
317 
318  // assigning mem for Lt of different bands **********************
319 
320  // GEOLOCATION
321  l2str->iscan = sline;
322  start[0] = sline;
323  start[1] = 0;
324  count[0] = 1;
325  count[1] = num_pixels; // 1 line at a time
326 
327  status = nc_get_vara_float(geolocationGrp, latId, start, count, l2str->latpix);
328  check_err(status, __LINE__, __FILE__);
329  status = nc_get_vara_float(geolocationGrp, lonId, start, count, l2str->lonpix);
330  check_err(status, __LINE__, __FILE__);
331 
332  // L2 products
333  for (size_t iprod = 0; iprod < nl2prod; iprod++) {
334  status = nc_get_vara_float(observationGrp, prodims[iprod], start, count, l2str->l2prod[iprod]);
335  check_err(status, __LINE__, __FILE__);
336  }
337 
338  return 0;
339 }
340 
341 int32_t l2_str::closel2_ocis_l1c(l2_str *l2str, l1c_filehandle *l1cfile) {
342  string str;
343  str = l1cfile->l1b_name;
344 
345  printf("Closing ocis L2 file\n");
346  cout << str << endl;
347  status = nc_close(l1cfile->sd_id);
348  check_err(status, __LINE__, __FILE__);
349  // Free memory
350 
351  if (l2str->latpix != nullptr)
352  free (l2str->latpix);
353  if (l2str->lonpix != nullptr)
354  free (l2str->lonpix);
355  if (l2str->slopeprod != nullptr)
356  free (l2str->slopeprod);
357  if (l2str->offsetprod != nullptr)
358  free (l2str->offsetprod);
359  if (l2str->tilt != nullptr)
360  free (l2str->tilt);
361  if (l2str->l2prod != nullptr)
362  free (l2str->l2prod);
363 
364  if (tmpShort)
365  free(tmpShort);
366  if (scan_time)
367  free(scan_time);
368 
369  l2str->latpix = nullptr;
370  l2str->slopeprod = nullptr;
371  l2str->lonpix = nullptr;
372  l2str->offsetprod = nullptr;
373  l2str->tilt = nullptr;
374  return 0;
375 }
376 
377 } // namespace l1c
float * offsetprod
Definition: l2_str.h:52
Utility functions for allocating and freeing three-dimensional arrays of various types.
int status
Definition: l1_czcs_hdf.c:32
void check_err(const int stat, const int line, const char *file)
Definition: nc4utils.c:35
float ** l2prod
Definition: l2_str.h:49
char l2prod[2048]
Definition: l1c_input.h:41
std::string l1b_name
size_t nl2prod
Definition: l2_str.h:50
#define NULL
Definition: decode_rs.h:63
size_t nscan
Definition: l2_str.h:34
float * tilt
Definition: l2_str.h:53
void unix2ymds(double usec, int16_t *year, int16_t *mon, int16_t *day, double *secs)
Definition: unix2ymds.c:8
float * slopeprod
Definition: l2_str.h:51
virtual int32_t closel2_ocis_l1c(l2_str *l2str, l1c_filehandle *l1cfile)
Definition: l2_str.cpp:341
int syear
Definition: l1_czcs_hdf.c:15
l1c_filehandle * l1cfile
Definition: l2_str.h:75
int32 nscan
Definition: l1_czcs_hdf.c:19
@ string
int sday
Definition: l1_czcs_hdf.c:15
int time_str(short, short, int, char *)
Definition: time_str.c:3
virtual ~l2_str()
Definition: l2_str.cpp:107
virtual int32_t openl2_ocis_l1c(L1C_input *l1cinput, l2_str *l2str, l1c_filehandle *l1cfile, int16_t *file_id)
Definition: l2_str.cpp:110
size_t npix
Definition: l2_str.h:32
Utility functions for allocating and freeing four-dimensional arrays of various types.
virtual int32_t readl2_ocis_l1c(l2_str *l2str, l1c_filehandle *l1cfile, int16_t *file_id, int32_t recnum)
Definition: l2_str.cpp:309
float * lonpix
Definition: l2_str.h:71
Definition: l1c.cpp:71
Utility functions for allocating and freeing two-dimensional arrays of various types.
#define BAD_FLT
Definition: jplaeriallib.h:19
float * latpix
Definition: l2_str.h:70
size_t iscan
Definition: l2_str.h:33
int32 dpix
Definition: l1_czcs_hdf.c:22
int32 spix
Definition: l1_czcs_hdf.c:21
int32_t iscan
int32 epix
Definition: l1_czcs_hdf.c:23
float ** allocate2d_float(size_t h, size_t w)
Allocate a two-dimensional array of type float of a given size.
Definition: allocate2d.c:123
float32 * att_ang
Definition: l1_czcs_hdf.c:34
int16_t * tilt
Definition: l2bin.cpp:80
int i
Definition: decode_rs.h:71
Definition: aerosol.c:136
int npix
Definition: get_cmp.c:28
#define str(s)
double isodate2unix(const char *isodate)
Definition: unix2isodate.c:61
int count
Definition: decode_rs.h:79