OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
common.cpp
Go to the documentation of this file.
1 #include "common.h"
2 
3 using namespace std;
4 using namespace netCDF;
5 using namespace netCDF::exceptions;
6 
7 int get_ev( double secpline, int16_t *dtype, int16_t *lines, int16_t *iagg,
8  uint16_t& pcdim, uint16_t& psdim, double& ev_toff,
9  float *clines, float *slines, double *deltc, double *delts,
10  int16_t &iret) {
11 
12  // Find end of no-data zone
13  int16_t iz=0, line0=0;
14  iret = -1;
15  while ( dtype[iz] == 0) {
16  line0 += lines[iz];
17  iz++;
18  }
19  if (iz == 10) return 0;
20 
21  // Find number of pixels in Earth views
22  pcdim = 0;
23  psdim = 0;
24  int16_t linen = line0;
25  for (size_t i=iz; i<9; i++) {
26  // Check for Earth, solar, lunar or diagnostic mode
27  if ( dtype[i] == 1 || dtype[i] == 3 || dtype[i] == 4 || dtype[i] == 6 ||
28  dtype[i] == 7 || dtype[i] == 9) {
29  uint16_t np = lines[i] / iagg[i];
30  for (size_t j=0; j<np; j++) {
31  clines[pcdim+j] = linen + j*iagg[i] + 0.5*iagg[i] - 64;
32  }
33  pcdim += np;
34  uint16_t ns = lines[i] / 8;
35  for (size_t j=0; j<ns; j++) {
36  slines[psdim+j] = linen + j*8 + 3.5;
37  }
38  psdim += ns;
39  iret = 0;
40  }
41  linen += lines[i];
42  }
43 
44  // Calculate times
45  for (size_t i=0; i<(size_t) pcdim; i++) deltc[i] = secpline * clines[i];
46  ev_toff = 0.5 * (deltc[0] + deltc[pcdim-1]);
47  for (size_t i=0; i<(size_t) pcdim; i++) deltc[i] -= ev_toff;
48 
49  for (size_t i=0; i<(size_t) psdim; i++)
50  delts[i] = secpline * slines[i] - ev_toff;
51 
52  return 0;
53 }
54 
55 
56 int get_oci_vecs( uint32_t nscan, uint16_t pdim, geo_struct& geoLUT,
57  double ev_toff, int32_t spin, float *slines, double *delt,
58  double revpsec, int32_t ppr_off, int32_t *mspin,
59  int32_t *ot_10us, uint8_t *enc_count, float **hamenc,
60  float **rtaenc, float **pview, double *theta, int16_t& iret) {
61 
62  // This program generates the OCI Earth view vectors for one spin.
63  // It uses MCE telemetry and encoder data. Further refinements will be made
64  // as the instrument optics model and test results become available.
65  // Reference: "Use of OCI Telemetry to Determine Pixel Line-of-Sight",
66  // F. Patt, 2020-05-18
67 
68  int32_t max_enc_cts = 131072; // 2^17
69  double dtenc = 0.001;
70  constexpr double pi = 3.14159265358979323846;
71 
72  double rad2asec = (180/pi) * 3600;
73 
74  // Compute scan angle corresponding to PPR
75  float pprang = 2 * pi * (ppr_off - geoLUT.rta_nadir) / max_enc_cts;
76  if (pprang > pi) pprang -= 2*pi;
77 
78  // Compute ideal scan angles for science pixels
79  double *toff = new double[pdim];
80  for (size_t i=0; i<pdim; i++) toff[i] = delt[i] + ev_toff;
81 
82  for (size_t i=0; i<pdim; i++)
83  theta[i] = pprang + 2 * pi * revpsec * toff[i];
84  // Interpolate encoder data to pixel times and add to scan angles
85  // RTA only for now, include HAM when we know how.
86 
87  double *thetacor = new double[pdim];
88 
89  int isp = -1;
90  for (size_t i=0; i<nscan; i++) {
91  if ( mspin[i] == spin) {
92  isp = (int) i;
93  break;
94  }
95  }
96  if ( isp == -1) {
97  cout << "No MCE encoder data for spin: " << spin << endl;
98  iret = 1;
99  }
100  size_t ip = 0, ke;
101  double tenc_ke;
102  while ( ip < pdim) {
103  // Encoder sample times at 1 KHz
104  for (size_t j=0; j<enc_count[isp]; j++) {
105  double tenc = j*dtenc;
106  if ( tenc < toff[ip] && (tenc+dtenc) > toff[ip]) {
107  ke = j;
108  tenc_ke = tenc;
109  break;
110  }
111  }
112  size_t njp=0;
113  for (size_t i=0; i<pdim; i++) {
114  if ( toff[i] >= tenc_ke && toff[i] < tenc_ke+dtenc) {
115  double ft = (toff[i] - tenc_ke) / dtenc;
116  thetacor[i] = (1-ft)*rtaenc[isp][ke] + ft*rtaenc[isp][ke+1];
117  njp++;
118  }
119  }
120  ip += njp;
121  }
122 
123  // Simple, planar view vector model to start
124  // Update when optical model is available.
125  for (size_t i=0; i<pdim; i++) {
126  theta[i] = theta[i] + thetacor[i] / rad2asec;
127  pview[i][1] = sin(theta[i]);
128  pview[i][2] = cos(theta[i]);
129  }
130 
131  delete [] thetacor;
132  delete [] toff;
133 
134  return 0;
135 }
136 
137 
138 int createField( NcGroup &ncGrp, const char *sname, const char *lname,
139  const char *standard_name, const char *units,
140  void *fill_value, const char *flag_values,
141  const char *flag_meanings,
142  double low, double high, int nt, vector<NcDim>& varVec) {
143 
144  size_t dimlength;
145 
146 
147  /* Create the NCDF dataset */
148  NcVar ncVar;
149  try {
150  ncVar = ncGrp.addVar(sname, nt, varVec);
151  }
152  catch ( NcException& e) {
153  cout << e.what() << endl;
154  cerr << "Failure creating variable: " << sname << endl;
155  exit(1);
156  }
157 
158  // Set fill value
159  double fill_value_dbl;
160  memcpy( &fill_value_dbl, fill_value, sizeof(double));
161 
162  int8_t i8;
163  uint8_t ui8;
164  int16_t i16;
165  uint16_t ui16;
166  int32_t i32;
167  uint32_t ui32;
168  float f32;
169 
170  if ( low != fill_value_dbl) {
171  if ( nt == NC_BYTE) {
172  i8 = fill_value_dbl;
173  ncVar.setFill(true, (void *) &i8);
174  } else if ( nt == NC_UBYTE) {
175  ui8 = fill_value_dbl;
176  ncVar.setFill(true, (void *) &ui8);
177  } else if ( nt == NC_SHORT) {
178  i16 = fill_value_dbl;
179  ncVar.setFill(true, (void *) &i16);
180  } else if ( nt == NC_USHORT) {
181  ui16 = fill_value_dbl;
182  ncVar.setFill(true, (void *) &ui16);
183  } else if ( nt == NC_INT) {
184  i32 = fill_value_dbl;
185  ncVar.setFill(true, (void *) &i32);
186  } else if ( nt == NC_UINT) {
187  ui32 = fill_value_dbl;
188  ncVar.setFill(true, (void *) &ui32);
189  } else if ( nt == NC_FLOAT) {
190  f32 = fill_value_dbl;
191  ncVar.setFill(true, (void *) &f32);
192  } else {
193  ncVar.setFill(true, (void *) &fill_value_dbl);
194  }
195  }
196 
197  /* vary chunck size based on dimensions */
198  int do_deflate = 0;
199  vector<size_t> chunkVec;
200  if ( varVec.size() == 3 && (strncmp(sname, "EV_", 3) == 0)) {
201  dimlength = varVec[2].getSize();
202 
203  chunkVec.push_back(1);
204  chunkVec.push_back(16);
205  chunkVec.push_back(dimlength/10);
206 
207  do_deflate = 1;
208  }
209 
210  /* Set compression */
211  if ( do_deflate) {
212  /* First set chunking */
213  try {
214  ncVar.setChunking(ncVar.nc_CHUNKED, chunkVec);
215  }
216  catch ( NcException& e) {
217  e.what();
218  cerr << "Failure setting chunking: " << sname << endl;
219  exit(1);
220  }
221 
222  try {
223  ncVar.setCompression(true, true, 5);
224  }
225  catch ( NcException& e) {
226  e.what();
227  cerr << "Failure setting compression: " << sname << endl;
228  exit(1);
229  }
230  }
231 
232 
233  /* Add a "long_name" attribute */
234  try {
235  ncVar.putAtt("long_name", lname);
236  }
237  catch ( NcException& e) {
238  e.what();
239  cerr << "Failure creating 'long_name' attribute: " << lname << endl;
240  exit(1);
241  }
242 
243  if ( strcmp( flag_values, "") != 0) {
244 
245  size_t curPos=0;
246 
247  string fv;
248  fv.assign( flag_values);
249  size_t pos = fv.find("=", curPos);
250  fv = fv.substr(pos+1);
251 
252  size_t semicln = fv.find(";");
253  pos = 0;
254 
255  int8_t vec[1024];
256  int n = 0;
257  while(pos != semicln) {
258  pos = fv.find(",", curPos);
259  if ( pos == string::npos)
260  pos = semicln;
261 
262  string flag_value;
263  istringstream iss(fv.substr(curPos, pos-curPos));
264  iss >> skipws >> flag_value;
265  vec[n++] = atoi( flag_value.c_str());
266  curPos = pos + 1;
267  }
268 
269  try {
270  ncVar.putAtt("flag_values", NC_BYTE, n, vec);
271  }
272  catch ( NcException& e) {
273  e.what();
274  cerr << "Failure creating 'flag_values' attribute: " << lname << endl;
275  exit(1);
276  }
277  }
278 
279  /* Add a "flag_meanings" attribute if specified*/
280  if ( strcmp( flag_meanings, "") != 0) {
281 
282  try {
283  ncVar.putAtt("flag_meanings", flag_meanings);
284  }
285  catch ( NcException& e) {
286  e.what();
287  cerr << "Failure creating 'flag_meanings' attribute: "
288  << flag_meanings << endl;
289  exit(1);
290  }
291  }
292 
293  /* Add "valid_min/max" attributes if specified */
294  if (low < high) {
295  switch(nt) { /* Use the appropriate number type */
296  case NC_BYTE:
297  {
298  uint8_t vr[2];
299  vr[0] = (uint8_t)low;
300  vr[1] = (uint8_t)high;
301 
302  try {
303  ncVar.putAtt("valid_min", NC_BYTE, 1, &vr[0]);
304  }
305  catch ( NcException& e) {
306  e.what();
307  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
308  exit(1);
309  }
310 
311  try {
312  ncVar.putAtt("valid_max", NC_BYTE, 1, &vr[1]);
313  }
314  catch ( NcException& e) {
315  e.what();
316  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
317  exit(1);
318  }
319  }
320  break;
321  case NC_UBYTE:
322  {
323  uint8_t vr[2];
324  vr[0] = (uint8_t)low;
325  vr[1] = (uint8_t)high;
326 
327  try {
328  ncVar.putAtt("valid_min", NC_UBYTE, 1, &vr[0]);
329  }
330  catch ( NcException& e) {
331  e.what();
332  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
333  exit(1);
334  }
335 
336  try {
337  ncVar.putAtt("valid_max", NC_UBYTE, 1, &vr[1]);
338  }
339  catch ( NcException& e) {
340  e.what();
341  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
342  exit(1);
343  }
344  }
345  break;
346  case NC_SHORT:
347  {
348  int16_t vr[2];
349  vr[0] = (int16_t)low;
350  vr[1] = (int16_t)high;
351 
352  try {
353  ncVar.putAtt("valid_min", NC_SHORT, 1, &vr[0]);
354  }
355  catch ( NcException& e) {
356  e.what();
357  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
358  exit(1);
359  }
360 
361  try {
362  ncVar.putAtt("valid_max", NC_SHORT, 1, &vr[1]);
363  }
364  catch ( NcException& e) {
365  e.what();
366  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
367  exit(1);
368  }
369  }
370  break;
371  case NC_USHORT:
372  {
373  uint16_t vr[2];
374  vr[0] = (uint16_t)low;
375  vr[1] = (uint16_t)high;
376 
377  try {
378  ncVar.putAtt("valid_min", NC_USHORT, 1, &vr[0]);
379  }
380  catch ( NcException& e) {
381  e.what();
382  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
383  exit(1);
384  }
385 
386  try {
387  ncVar.putAtt("valid_max", NC_USHORT, 1, &vr[1]);
388  }
389  catch ( NcException& e) {
390  e.what();
391  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
392  exit(1);
393  }
394  }
395  break;
396  case NC_INT:
397  {
398  int32_t vr[2];
399  vr[0] = (int32_t)low;
400  vr[1] = (int32_t)high;
401 
402  try {
403  ncVar.putAtt("valid_min", NC_INT, 1, &vr[0]);
404  }
405  catch ( NcException& e) {
406  e.what();
407  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
408  exit(1);
409  }
410 
411  try {
412  ncVar.putAtt("valid_max", NC_INT, 1, &vr[1]);
413  }
414  catch ( NcException& e) {
415  e.what();
416  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
417  exit(1);
418  }
419 
420  }
421  break;
422  case NC_UINT:
423  {
424  uint32_t vr[2];
425  vr[0] = (uint32_t)low;
426  vr[1] = (uint32_t)high;
427 
428  try {
429  ncVar.putAtt("valid_min", NC_UINT, 1, &vr[0]);
430  }
431  catch ( NcException& e) {
432  e.what();
433  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
434  exit(1);
435  }
436 
437  try {
438  ncVar.putAtt("valid_max", NC_UINT, 1, &vr[1]);
439  }
440  catch ( NcException& e) {
441  e.what();
442  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
443  exit(1);
444  }
445 
446  }
447  break;
448  case NC_FLOAT:
449  {
450  float vr[2];
451  vr[0] = (float)low;
452  vr[1] = (float)high;
453 
454  try {
455  ncVar.putAtt("valid_min", NC_FLOAT, 1, &vr[0]);
456  }
457  catch ( NcException& e) {
458  e.what();
459  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
460  exit(1);
461  }
462 
463  try {
464  ncVar.putAtt("valid_max", NC_FLOAT, 1, &vr[1]);
465  }
466  catch ( NcException& e) {
467  e.what();
468  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
469  exit(1);
470  }
471  }
472  break;
473  case NC_DOUBLE:
474  {
475  double vr[2];
476  vr[0] = low;
477  vr[1] = high;
478 
479  try {
480  ncVar.putAtt("valid_min", NC_DOUBLE, 1, &vr[0]);
481  }
482  catch ( NcException& e) {
483  e.what();
484  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
485  exit(1);
486  }
487 
488  try {
489  ncVar.putAtt("valid_max", NC_DOUBLE, 1, &vr[1]);
490  }
491  catch ( NcException& e) {
492  e.what();
493  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
494  exit(1);
495  }
496  }
497  break;
498  default:
499  fprintf(stderr,"-E- %s line %d: ",__FILE__,__LINE__);
500  fprintf(stderr,"Got unsupported number type (%d) ",nt);
501  fprintf(stderr,"while trying to create NCDF variable, \"%s\", ",sname);
502  return(1);
503  }
504  }
505 
506  /* Add a "units" attribute if one is specified */
507  if(units != NULL && *units != 0) {
508 
509  try {
510  ncVar.putAtt("units", units);
511  }
512  catch ( NcException& e) {
513  e.what();
514  cerr << "Failure creating 'units' attribute: " << units << endl;
515  exit(1);
516  }
517  }
518 
519  /* Add a "standard_name" attribute if one is specified */
520  if(standard_name != NULL && *standard_name != 0) {
521  try {
522  ncVar.putAtt("standard_name", units);
523  }
524  catch ( NcException& e) {
525  e.what();
526  cerr << "Failure creating 'standard_name' attribute: "
527  << standard_name << endl;
528  exit(1);
529  }
530  }
531 
532  return 0;
533 }
534 
535 /*
536 int l1bFile::parseDims( string dimString, vector<NcDim>& varDims) {
537 
538  size_t curPos=0;
539  // char dimName[NC_MAX_NAME+1];
540  string dimName;
541 
542  while(1) {
543  size_t pos = dimString.find(",", curPos);
544  if ( pos == string::npos)
545  pos = dimString.find(")");
546 
547  string varDimName;
548  istringstream iss(dimString.substr(curPos, pos-curPos));
549  iss >> skipws >> varDimName;
550 
551  for (int i=0; i<ndims; i++) {
552 
553  try {
554  dimName = ncDims[i].getName();
555  }
556  catch ( NcException& e) {
557  e.what();
558  cerr << "Failure accessing dimension: " + dimName << endl;
559  exit(1);
560  }
561 
562  if ( varDimName.compare(dimName) == 0) {
563  cout << " " << dimName << " " << ncDims[i].getSize() << endl;
564  varDims.push_back(ncDims[i]);
565  break;
566  }
567  }
568  if ( dimString.substr(pos, 1).compare(")") == 0) break;
569 
570  curPos = pos + 1;
571  }
572 
573  return 0;
574 }
575 
576 */
int j
Definition: decode_rs.h:73
#define NULL
Definition: decode_rs.h:63
void spin(double st, double *pos1, double *pos2)
const double pi
float32 * pos
Definition: l1_czcs_hdf.c:35
int32 nscan
Definition: l1_czcs_hdf.c:19
int get_oci_vecs(uint32_t nscan, uint16_t pdim, geo_struct &geoLUT, double ev_toff, int32_t spin, float *slines, double *delt, double revpsec, int32_t ppr_off, int32_t *mspin, int32_t *ot_10us, uint8_t *enc_count, float **hamenc, float **rtaenc, float **pview, double *theta, int16_t &iret)
Definition: common.cpp:56
int32_t rta_nadir
Definition: common.h:25
dtype
Definition: DDataset.hpp:31
int get_ev(double secpline, int16_t *dtype, int16_t *lines, int16_t *iagg, uint16_t &pcdim, uint16_t &psdim, double &ev_toff, float *clines, float *slines, double *deltc, double *delts, int16_t &iret)
Definition: common.cpp:7
These two strings are used for the product XML output If product_id is not set then prefix is used If the last char of the name_prefix is _ then it is removed If algorithm_id is not set then name_suffix is used If the first char is _ then it is removed l2prod standard_name[0]
int i
Definition: decode_rs.h:71
float32 f32
Definition: l2bin.cpp:104
int createField(NcGroup &ncGrp, const char *sname, const char *lname, const char *standard_name, const char *units, void *fill_value, const char *flag_values, const char *flag_meanings, double low, double high, int nt, vector< NcDim > &varVec)
Definition: common.cpp:138