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 #include "nc4utils.h"
7 
8 int read_mce_tlm( NcFile *l1afile, geo_struct& geo_lut, NcGroup egid,
9  uint32_t nmcescan, uint32_t nenc, int32_t& ppr_off,
10  double& revpsec, double&secpline,
11  int16_t& board_id, int32_t *mspin, int32_t *ot_10us,
12  uint8_t *enc_count, float **hamenc, float **rtaenc,
13  int16_t &iret) {
14 
15  iret = 0;
16 
17  NcDim mce_dim = l1afile->getDim("MCE_block");
18  uint32_t mce_blk = mce_dim.getSize();
19  NcDim ddc_dim = l1afile->getDim("DDC_tlm");
20  uint32_t nddc = ddc_dim.getSize();
21  NcDim tlm_dim = l1afile->getDim("tlm_packets");
22  uint32_t ntlmpack = tlm_dim.getSize();
23 
24  uint8_t **mtlm = new uint8_t *[nmcescan];
25  mtlm[0] = new uint8_t[mce_blk*nmcescan];
26  for (size_t i=1; i<nmcescan; i++) mtlm[i] = mtlm[i-1] + mce_blk;
27 
28  int16_t **enc = new int16_t *[nmcescan];
29  enc[0] = new int16_t[4*nenc*nmcescan];
30  for (size_t i=1; i<nmcescan; i++) enc[i] = enc[i-1] + 4*nenc;
31 
32  uint8_t **ddctlm = new uint8_t *[ntlmpack];
33  ddctlm[0] = new uint8_t[nddc*ntlmpack];
34  for (size_t i=1; i<ntlmpack; i++) ddctlm[i] = ddctlm[i-1] + nddc;
35 
36  NcVar var;
37  vector<size_t> start, count;
38  start.push_back(0);
39  start.push_back(0);
40  count.push_back(1);
41 
42  var = egid.getVar( "MCE_telemetry");
43  var.getVar( &mtlm[0][0]);
44 
45  var = egid.getVar( "MCE_encoder_data");
46  count.pop_back();
47  count.push_back(4*nenc);
48  var.getVar( &enc[0][0]);
49 
50  var = egid.getVar( "MCE_spin_ID");
51  var.getVar( mspin);
52 
53  var = egid.getVar( "DDC_telemetry");
54  var.getVar( &ddctlm[0][0]);
55 
56  // Check for missing MCE telemetry
57  bool noMCE = true;
58  for (size_t i=0; i<nmcescan; i++) {
59  if (mspin[i] >= 0) {
60  noMCE = false;
61  break;
62  }
63  }
64 
65  if (noMCE == true) {
66  cout << "No MCE telemetry in L1A file" << endl;
67  exit(1);
68  }
69 
70  int32_t max_enc_cts = 131072; // 2^17
71  double clock[2];
72  clock[0] = geo_lut.master_clock;
73  clock[1] = geo_lut.MCE_clock;
74 
75  // Get ref_pulse_divider and compute commanded rotation rate
76  uint32_t ui32;
77  uint32_t ref_pulse_div[2];
78  memcpy( &ui32, &mtlm[0][0], 4);
79  ref_pulse_div[0] = SWAP_4( ui32) % 16777216; // 2^24
80  memcpy( &ui32, &mtlm[0][4], 4);
81  ref_pulse_div[1] = SWAP_4( ui32) % 16777216; // 2^24
82 
83  int32_t ref_pulse_sel = mtlm[0][9] / 128;
84 
85  revpsec = clock[ref_pulse_sel] / 2 / max_enc_cts /
86  (ref_pulse_div[ref_pulse_sel]/256.0 + 1);
87 
88  // Check for static or reverse scan
89  int32_t avg_step_spd = mtlm[0][428]*256+mtlm[0][429];
90  if (abs(avg_step_spd) < 1000) {
91  // Static mode
92  iret = 2;
93  revpsec = 0.0;
94  cout << "OCI static mode" << endl;
95  } else if (avg_step_spd < 0) {
96  // Reverse spin
97  revpsec = -revpsec;
98  iret = 3;
99  cout << "OCI reverse scan" << endl;
100  }
101 
102  // Get PPR offset and on-time_10us
103  memcpy( &ui32, &mtlm[0][8], 4);
104  ppr_off = SWAP_4( ui32) % max_enc_cts;
105  for (size_t i=0; i<nmcescan; i++) {
106  memcpy( &ui32, &mtlm[i][368], 4);
107  ot_10us[i] = SWAP_4( ui32) % 4;
108  }
109 
110  // Get MCE board ID
111  board_id = (int16_t) mtlm[0][322] / 16;
112 
113  // Get TDI time and compute time increment per line
114  uint16_t ui16;
115  memcpy( &ui16, &ddctlm[0][346], 2);
116  int32_t tditime = SWAP_2( ui16);
117  secpline = (tditime+1) / clock[0];
118 
119  // Get valid encoder count, HAM and RTA encoder data
120  for (size_t i=0; i<nmcescan; i++) enc_count[i] = mtlm[i][475];
121  // float enc_s = 81.0 / 2560;
122  for (size_t i=0; i<nmcescan; i++) {
123  for (size_t j=0; j<nenc; j++) {
124  hamenc[i][j] = enc[i][4*j+0] * geo_lut.ham_enc_scale;
125  rtaenc[i][j] = enc[i][4*j+1] * geo_lut.rta_enc_scale;
126  }
127  }
128 
129  delete[] mtlm[0];
130  delete[] mtlm;
131 
132  delete [] enc[0];
133  delete [] enc;
134 
135  delete [] ddctlm[0];
136  delete [] ddctlm;
137 
138  return 0;
139 }
140 
141 
142 int get_ev( double secpline, int16_t *dtype, int16_t *lines, int16_t *iagg,
143  uint16_t& pcdim, uint16_t& psdim, double& ev_toff,
144  float *clines, float *slines, double *deltc, double *delts,
145  bool dark, int16_t &iret) {
146 
147  // Find end of no-data zone
148  int16_t iz=0, line0=0;
149  iret = -1;
150  while ( dtype[iz] == 0) {
151  line0 += lines[iz];
152  iz++;
153  }
154  if (iz == 10) return 0;
155 
156  // Find number of pixels in Earth views
157  pcdim = 0;
158  psdim = 0;
159  int16_t linen = line0;
160 
161  uint8_t ltype[] = {0,1,0,1,1,1,1,1,1,1,0,0,0};
162  if (dark) ltype[2] = 1;
163 
164  for (size_t i=iz; i<9; i++) {
165  // Check for not dark or no-data
166  if ( ltype[dtype[i]] == 1) {
167  // if ( dtype[i] != 0 && dtype[i] != 2 && dtype[i] < 10) {
168 
169  uint16_t np = lines[i] / iagg[i];
170  for (size_t j=0; j<np; j++) {
171  clines[pcdim+j] = linen + j*iagg[i] + 0.5*iagg[i] - 64;
172  }
173  pcdim += np;
174  uint16_t ns = lines[i] / 8;
175  for (size_t j=0; j<ns; j++) {
176  slines[psdim+j] = linen + j*8 + 4 - 64;
177  }
178  psdim += ns;
179  iret = 0;
180  }
181  linen += lines[i];
182  }
183 
184  // Calculate times
185  for (size_t i=0; i<(size_t) pcdim; i++) deltc[i] = secpline * clines[i];
186  ev_toff = 0.5 * (deltc[0] + deltc[pcdim-1]);
187  for (size_t i=0; i<(size_t) pcdim; i++) deltc[i] -= ev_toff;
188 
189  for (size_t i=0; i<(size_t) psdim; i++)
190  delts[i] = secpline * slines[i] - ev_toff;
191 
192  return 0;
193 }
194 
195 int get_oci_vecs( uint32_t nscan, uint16_t pdim, double as_planarity[5],
196  double at_planarity[5], int32_t *rta_nadir,
197  double ham_ct_angles[2], double ev_toff, int32_t spin,
198  uint8_t hside, float *clines,
199  double *delt, double revpsec, int32_t ppr_off,
200  int16_t board_id, uint32_t nmcescan, int32_t *mspin,
201  uint8_t *enc_count, float **hamenc, float **rtaenc,
202  float **pview, double *theta, int16_t& iret) {
203 
204  // This program generates the OCI Earth view vectors for one spin.
205  // It uses MCE telemetry and encoder data. Further refinements will be made
206  // as the instrument optics model and test results become available.
207  // Reference: "Use of OCI Telemetry to Determine Pixel Line-of-Sight",
208  // F. Patt, 2020-05-18
209 
210  int32_t max_enc_cts = 131072; // 2^17
211  double dtenc = 0.001;
212  constexpr double pi = 3.14159265358979323846;
213  int16_t bd_id = board_id % 2;
214 
215  double rad2asec = (180/pi) * 3600;
216  iret = 0;
217 
218  // Compute scan angle corresponding to PPR
219  // float pprang = 2 * pi * (ppr_off - geoLUT.rta_nadir[bd_id]) / max_enc_cts;
220  float pprang = 2 * pi * (ppr_off - rta_nadir[bd_id]) / max_enc_cts;
221  if (pprang > pi) pprang -= 2*pi;
222 
223  // Compute ideal scan angles for science pixels
224  double *toff = new double[pdim];
225  for (size_t i=0; i<pdim; i++) toff[i] = delt[i] + ev_toff;
226 
227  for (size_t i=0; i<pdim; i++)
228  theta[i] = pprang + 2 * pi * revpsec * toff[i];
229  // Interpolate encoder data to pixel times and add to scan angles
230  // RTA only for now, include HAM when we know how.
231 
232  double *thetacor = new double[pdim];
233 
234  int isp = -1;
235  for (size_t i=0; i<nmcescan; i++) {
236  if ( mspin[i] == spin) {
237  isp = (int) i;
238  break;
239  }
240  }
241 
242  // Interpolate encoder data to pixel times and add to scan angles
243  // RTA only for now, include HAM when we know how.
244  if ( isp == -1) {
245  cout << "No MCE encoder data for spin: " << spin << endl;
246  iret = 1;
247  } else {
248  size_t ip = 0, ke;
249  double tenc_ke;
250  while ( ip < pdim) {
251  // Encoder sample times at 1 KHz
252  // ke = where(tenc le toff[ip] AND tenc[1:*] gt toff[ip])
253  bool found=false;
254  for (size_t j=0; j<enc_count[isp]; j++) {
255  double tenc = j*dtenc;
256  if ( tenc <= toff[ip] && (tenc+dtenc) > toff[ip]) {
257  ke = j;
258  tenc_ke = tenc;
259  found = true;
260  break;
261  }
262  }
263 
264  size_t njp=0;
265  if (found) {
266  for (size_t i=0; i<pdim; i++) {
267  if ( toff[i] >= tenc_ke && toff[i] < tenc_ke+dtenc) {
268  double ft = (toff[i] - tenc_ke) / dtenc;
269  thetacor[i] =
270  (1-ft)*rtaenc[isp][ke] + ft*rtaenc[isp][ke+1] -
271  ((1-ft)*hamenc[isp][ke] + ft*hamenc[isp][ke+1] +
272  ham_ct_angles[hside])*0.236;
273 
274  njp++;
275  }
276  }
277  } else {
278  cout << "Encoder interpolation error" << endl;
279  exit(-1);
280  }
281  ip += njp;
282  } // while ( ip < pdim)
283 
284  // Calculate planarity deviations and view vectors
285  double *ascan = new double[pdim];
286  double *atrack = new double[pdim];
287  for (size_t i=0; i<pdim; i++) {
288  theta[i] = theta[i] - thetacor[i] / rad2asec;
289 
290  ascan[i] = as_planarity[0];
291  atrack[i] = at_planarity[0];
292  for (size_t k=1; k<5; k++) {
293  ascan[i] += as_planarity[k]*pow(theta[i], k);
294  atrack[i] += at_planarity[k]*pow(theta[i], k);
295  }
296 
297  pview[i][0] = -sin(atrack[i]/rad2asec);
298  pview[i][1] = sin(theta[i] - ascan[i]/rad2asec);
299  pview[i][2] = cos(theta[i] - ascan[i]/rad2asec);
300  }
301 
302  delete [] ascan;
303  delete [] atrack;
304  }
305 
306  delete [] thetacor;
307  delete [] toff;
308 
309  return 0;
310 }
311 
312 int createField( NcGroup &ncGrp, const char *sname, const char *lname,
313  const char *standard_name, const char *units,
314  const char *description,
315  void *fill_value, const char *flag_masks,
316  const char *flag_meanings,
317  double low, double high,
318  double scale, double offset,
319  int nt, vector<NcDim>& varVec, string coordinates) {
320 
321  /* Create the NCDF dataset */
322  NcVar ncVar;
323 
324  try {
325  ncVar = ncGrp.addVar(sname, nt, varVec);
326  }
327  catch ( NcException& e) {
328  cout << e.what() << endl;
329  cerr << "Failure creating variable: " << sname << endl;
330  exit(1);
331  }
332  int var_id = ncVar.getId();
333  int nc_id = ncVar.getParentGroup().getId();
334  std::string grp_name = ncVar.getParentGroup().getName();
335  int32_t dimids[5];
336  for (size_t idim = 0 ; idim < ncVar.getDims().size(); idim ++){
337  dimids[idim] = ncVar.getDims()[idim].getId();
338  }
339  // Set fill value
340  double fill_value_dbl;
341  memcpy( &fill_value_dbl, fill_value, sizeof(double));
342 
343  int8_t i8;
344  uint8_t ui8;
345  int16_t i16;
346  uint16_t ui16;
347  int32_t i32;
348  uint32_t ui32;
349  float f32;
350 
351  if ( low != fill_value_dbl) {
352  if ( nt == NC_BYTE) {
353  i8 = fill_value_dbl;
354  ncVar.setFill(true, (void *) &i8);
355  } else if ( nt == NC_UBYTE) {
356  ui8 = fill_value_dbl;
357  ncVar.setFill(true, (void *) &ui8);
358  } else if ( nt == NC_SHORT) {
359  i16 = fill_value_dbl;
360  ncVar.setFill(true, (void *) &i16);
361  } else if ( nt == NC_USHORT) {
362  ui16 = fill_value_dbl;
363  ncVar.setFill(true, (void *) &ui16);
364  } else if ( nt == NC_INT) {
365  i32 = fill_value_dbl;
366  ncVar.setFill(true, (void *) &i32);
367  } else if ( nt == NC_UINT) {
368  ui32 = fill_value_dbl;
369  ncVar.setFill(true, (void *) &ui32);
370  } else if ( nt == NC_FLOAT) {
371  f32 = fill_value_dbl;
372  ncVar.setFill(true, (void *) &f32);
373  } else {
374  ncVar.setFill(true, (void *) &fill_value_dbl);
375  }
376  }
377 
378  /* vary chunck size based on dimensions */
379  int deflate_level = 5;
380  std::vector<size_t> chunkVec;
381  bool set_compression = (grp_name == "geolocation_data") || (grp_name == "observation_data");
382  if (set_compression) {
383  if(varVec.size() == 2)
384  chunkVec = {512, 1272}; // 256 lines, all pixels(1272)
385  if(varVec.size() == 3)
386  chunkVec = {40, 16, 1272}; // 40 bands, 16 lines, all pixels(1272)
387  nc_init_compress(nc_id, var_id, dimids, varVec.size(),
388  chunkVec.data(), deflate_level);
389 
390  }
391 
392  /* Add a "long_name" attribute */
393  try {
394  ncVar.putAtt("long_name", lname);
395  }
396  catch ( NcException& e) {
397  e.what();
398  cerr << "Failure creating 'long_name' attribute: " << lname << endl;
399  exit(1);
400  }
401 
402  if ( strcmp( flag_masks, "") != 0) {
403 
404  size_t curPos=0;
405 
406  string fv;
407  fv.assign( flag_masks);
408  size_t pos = fv.find("=", curPos);
409  fv = fv.substr(pos+1);
410 
411  size_t semicln = fv.find(";");
412  pos = 0;
413 
414  int8_t vec[1024];
415  int n = 0;
416  while(pos != semicln) {
417  pos = fv.find(",", curPos);
418  if ( pos == string::npos)
419  pos = semicln;
420 
421  string flag_mask;
422  istringstream iss(fv.substr(curPos, pos-curPos));
423  iss >> skipws >> flag_mask;
424  vec[n++] = atoi( flag_mask.c_str());
425  curPos = pos + 1;
426  }
427 
428  try {
429  ncVar.putAtt("flag_masks", nt, n, vec);
430  }
431  catch ( NcException& e) {
432  e.what();
433  cerr << "Failure creating 'flag_masks' attribute: " << lname << endl;
434  exit(1);
435  }
436  }
437 
438  /* Add a "flag_meanings" attribute if specified*/
439  if ( strcmp( flag_meanings, "") != 0) {
440 
441  try {
442  ncVar.putAtt("flag_meanings", flag_meanings);
443  }
444  catch ( NcException& e) {
445  e.what();
446  cerr << "Failure creating 'flag_meanings' attribute: "
447  << flag_meanings << endl;
448  exit(1);
449  }
450  }
451 
452  /* Add "valid_min/max" attributes if specified */
453  if (low < high) {
454  switch(nt) { /* Use the appropriate number type */
455  case NC_BYTE:
456  {
457  uint8_t vr[2];
458  vr[0] = (uint8_t)low;
459  vr[1] = (uint8_t)high;
460 
461  try {
462  ncVar.putAtt("valid_min", NC_BYTE, 1, &vr[0]);
463  }
464  catch ( NcException& e) {
465  e.what();
466  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
467  exit(1);
468  }
469 
470  try {
471  ncVar.putAtt("valid_max", NC_BYTE, 1, &vr[1]);
472  }
473  catch ( NcException& e) {
474  e.what();
475  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
476  exit(1);
477  }
478  }
479  break;
480  case NC_UBYTE:
481  {
482  uint8_t vr[2];
483  vr[0] = (uint8_t)low;
484  vr[1] = (uint8_t)high;
485 
486  try {
487  ncVar.putAtt("valid_min", NC_UBYTE, 1, &vr[0]);
488  }
489  catch ( NcException& e) {
490  e.what();
491  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
492  exit(1);
493  }
494 
495  try {
496  ncVar.putAtt("valid_max", NC_UBYTE, 1, &vr[1]);
497  }
498  catch ( NcException& e) {
499  e.what();
500  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
501  exit(1);
502  }
503  }
504  break;
505  case NC_SHORT:
506  {
507  int16_t vr[2];
508  vr[0] = (int16_t)low;
509  vr[1] = (int16_t)high;
510 
511  try {
512  ncVar.putAtt("valid_min", NC_SHORT, 1, &vr[0]);
513  }
514  catch ( NcException& e) {
515  e.what();
516  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
517  exit(1);
518  }
519 
520  try {
521  ncVar.putAtt("valid_max", NC_SHORT, 1, &vr[1]);
522  }
523  catch ( NcException& e) {
524  e.what();
525  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
526  exit(1);
527  }
528  }
529  break;
530  case NC_USHORT:
531  {
532  uint16_t vr[2];
533  vr[0] = (uint16_t)low;
534  vr[1] = (uint16_t)high;
535 
536  try {
537  ncVar.putAtt("valid_min", NC_USHORT, 1, &vr[0]);
538  }
539  catch ( NcException& e) {
540  e.what();
541  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
542  exit(1);
543  }
544 
545  try {
546  ncVar.putAtt("valid_max", NC_USHORT, 1, &vr[1]);
547  }
548  catch ( NcException& e) {
549  e.what();
550  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
551  exit(1);
552  }
553  }
554  break;
555  case NC_INT:
556  {
557  int32_t vr[2];
558  vr[0] = (int32_t)low;
559  vr[1] = (int32_t)high;
560 
561  try {
562  ncVar.putAtt("valid_min", NC_INT, 1, &vr[0]);
563  }
564  catch ( NcException& e) {
565  e.what();
566  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
567  exit(1);
568  }
569 
570  try {
571  ncVar.putAtt("valid_max", NC_INT, 1, &vr[1]);
572  }
573  catch ( NcException& e) {
574  e.what();
575  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
576  exit(1);
577  }
578 
579  }
580  break;
581  case NC_UINT:
582  {
583  uint32_t vr[2];
584  vr[0] = (uint32_t)low;
585  vr[1] = (uint32_t)high;
586 
587  try {
588  ncVar.putAtt("valid_min", NC_UINT, 1, &vr[0]);
589  }
590  catch ( NcException& e) {
591  e.what();
592  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
593  exit(1);
594  }
595 
596  try {
597  ncVar.putAtt("valid_max", NC_UINT, 1, &vr[1]);
598  }
599  catch ( NcException& e) {
600  e.what();
601  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
602  exit(1);
603  }
604 
605  }
606  break;
607  case NC_FLOAT:
608  {
609  float vr[2];
610  vr[0] = (float)low;
611  vr[1] = (float)high;
612 
613  try {
614  ncVar.putAtt("valid_min", NC_FLOAT, 1, &vr[0]);
615  }
616  catch ( NcException& e) {
617  e.what();
618  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
619  exit(1);
620  }
621 
622  try {
623  ncVar.putAtt("valid_max", NC_FLOAT, 1, &vr[1]);
624  }
625  catch ( NcException& e) {
626  e.what();
627  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
628  exit(1);
629  }
630  }
631  break;
632  case NC_DOUBLE:
633  {
634  double vr[2];
635  vr[0] = low;
636  vr[1] = high;
637 
638  try {
639  ncVar.putAtt("valid_min", NC_DOUBLE, 1, &vr[0]);
640  }
641  catch ( NcException& e) {
642  e.what();
643  cerr << "Failure creating 'valid_min' attribute: " << vr[0] << endl;
644  exit(1);
645  }
646 
647  try {
648  ncVar.putAtt("valid_max", NC_DOUBLE, 1, &vr[1]);
649  }
650  catch ( NcException& e) {
651  e.what();
652  cerr << "Failure creating 'valid_max' attribute: " << vr[1] << endl;
653  exit(1);
654  }
655  }
656  break;
657  default:
658  fprintf(stderr,"-E- %s line %d: ",__FILE__,__LINE__);
659  fprintf(stderr,"Got unsupported number type (%d) ",nt);
660  fprintf(stderr,"while trying to create NCDF variable, \"%s\", ",sname);
661  return(1);
662  }
663  }
664 
665  /* Add "scale_factor" and "add_offset" attributes if specified */
666  if(scale != 1.0 || offset != 0.0) {
667  try {
668  ncVar.putAtt("scale_factor", NC_DOUBLE, 1, &scale);
669  }
670  catch ( NcException& e) {
671  e.what();
672  cerr << "Failure creating 'scale_factor' attribute: " << scale << endl;
673  exit(1);
674  }
675 
676  try {
677  ncVar.putAtt("add_offset", NC_DOUBLE, 1, &offset);
678  }
679  catch ( NcException& e) {
680  e.what();
681  cerr << "Failure creating 'add_offset' attribute: " << offset << endl;
682  exit(1);
683  }
684  }
685 
686  /* Add a "units" attribute if one is specified */
687  if(units != NULL && *units != 0) {
688 
689  try {
690  ncVar.putAtt("units", units);
691  }
692  catch ( NcException& e) {
693  e.what();
694  cerr << "Failure creating 'units' attribute: " << units << endl;
695  exit(1);
696  }
697  }
698 
699  /* Add a "description" attribute if one is specified */
700  if(description != NULL && *description != 0) {
701 
702  try {
703  ncVar.putAtt("description", description);
704  }
705  catch ( NcException& e) {
706  e.what();
707  cerr << "Failure creating 'description' attribute: " << description << endl;
708  exit(1);
709  }
710  }
711 
712  /* Add a "standard_name" attribute if one is specified */
713  if(standard_name != NULL && *standard_name != 0) {
714  try {
715  ncVar.putAtt("standard_name", standard_name);
716  }
717  catch ( NcException& e) {
718  e.what();
719  cerr << "Failure creating 'standard_name' attribute: "
720  << standard_name << endl;
721  exit(1);
722  }
723  }
724 
725  /* Add a "coordinates" attribute if specified*/
726  if ( !coordinates.empty()) {
727 
728  try {
729  ncVar.putAtt("coordinates", coordinates);
730  }
731  catch ( NcException& e) {
732  e.what();
733  cerr << "Failure creating 'coordinates' attribute: "
734  << coordinates << endl;
735  exit(1);
736  }
737  }
738 
739  return 0;
740 }
741 
742 int get_nib_nbb( uint32_t ntaps, size_t *ia, uint32_t ntb[16], int16_t jagg[16],
743  uint32_t& nib, uint32_t& nbb) {
744 
745  uint32_t iia;
746 
747  iia=0;
748  for (size_t i=0; i<ntaps; i++) {
749  if ( jagg[i] > 0) {
750  ia[iia] = i;
751  iia++;
752  }
753  }
754 
755  if ( iia == 0) {
756  return 2;
757  } else {
758  for (size_t i=0; i<16; i++) ntb[i] = 0;
759  for (size_t i=0; i<iia; i++) ntb[ia[i]] = 32 / jagg[ia[i]];
760  nib = 0;
761  for (size_t i=0; i<16; i++) nib += ntb[i];
762  }
763 
764  // Compute number of bands for 8x aggregation with overlapping bands
765  nbb = (ntb[ia[0]]*3) / 4 + 1;
766  //amat(nbb,nib)
767  for (size_t i=1; i<iia; i++) {
768  if (jagg[ia[i]] >= jagg[ia[i]-1])
769  nbb += ntb[ia[i]];
770  else
771  nbb += (ntb[ia[i]]*3) / 4 + ntb[ia[i]-1]/4;
772  }
773 
774  return 0;
775 }
776 
777 int get_agg_mat( size_t *ia, int16_t jagg[16], uint32_t ntb[16],
778  uint32_t nib, uint32_t nbb, float **amat, float **gmat) {
779 
780  for (size_t i=0; i<512; i++) {
781  gmat[i] = new float[nib];
782  for (size_t j=0; j<nib; j++) gmat[i][j] = 0.0;
783  }
784 
785  // Populate gain aggregation matrix
786  int16_t ii = 0;
787  int16_t itt[16][2];
788  for (size_t i=0; i<16; i++) {
789  itt[i][0] = itt[i][1] = 0;
790  if ( jagg[i] > 0) {
791  for (size_t k=0; k<ntb[i]; k++) {
792  size_t ic = 32*i;
793  size_t kj = k*jagg[i];
794  for (size_t j=0; j<(size_t) jagg[i]; j++)
795  gmat[ic+kj+j][ii+k] = (1.0/jagg[i]);
796  }
797  itt[i][0] = ii;
798  ii += ntb[i];
799  itt[i][1] = ii - 1;
800  }
801  }
802 
803  for (size_t i=0; i<nib; i++) {
804  amat[i] = new float[nbb];
805  for (size_t j=0; j<nbb; j++) amat[i][j] = 0;
806  }
807 
808  // First tap
809  int16_t ib;
810  for (size_t k=0; k<=(ntb[ia[0]]*3)/4; k++) {
811  for (size_t l=0; l<=ntb[ia[0]]/4-1; l++) amat[k+l][k] = jagg[ia[0]]/8.0;
812  }
813  ib = (ntb[ia[0]]*3)/4 + 1;
814 
815  // Remaining taps
816  uint16_t nr;
817  for (size_t i=ia[1]; i<16; i++) {
818  if (ntb[i] > 0) {
819  if (ntb[i] >= ntb[i-1]) {
820  // Transition resolution determined by preceding tap
821  nr = ntb[i-1]/4 - 1;
822  // Remaining bands using preceding tap
823  if (nr > 0) {
824  for (size_t k=0; k<nr; k++) {
825  uint16_t k1 = nr - k - 1;
826  uint16_t k2 = ((k+1)*ntb[i]) / ntb[i-1] - 1;
827  for (size_t j=0; j<=k1; j++)
828  amat[itt[i-1][1]-k1+j][ib+k] = jagg[i-1] / 8.0;
829  for (size_t j=0; j<=k2; j++)
830  amat[itt[i][0]+j][ib+k] = jagg[i] / 8.0;
831  }
832  ib += nr;
833  }
834  } else {
835  // Transition resolution determined using current tap
836  nr = ntb[i]/4 - 1;
837  // Remaining bands using previous tap
838  if (nr > 0) {
839  for (size_t k=0; k<nr; k++) {
840  uint16_t k1 = ((nr-k)*ntb[i-1]) / ntb[i] - 1;
841  uint16_t k2 = k;
842  for (size_t j=0; j<=k1; j++)
843  amat[itt[i-1][1]-k1+j][ib+k] = jagg[i-1] / 8.0;
844  for (size_t j=0; j<=k2; j++)
845  amat[itt[i][0]+j][ib+k] = jagg[i] / 8.0;
846  }
847  ib += nr;
848  }
849  }
850  // Remaining bands using this tap
851  for (size_t k=0; k<=(ntb[i]*3)/4; k++) {
852  for (size_t j=0; j<ntb[i]/4; j++)
853  amat[itt[i][0]+k+j][ib+k] = jagg[i] / 8.0;
854  }
855  ib += (ntb[i]*3) / 4 + 1;
856  }
857  }
858 
859  return 0;
860 }
861 
862 // sfl = array of scan qual flags 2 = missu=ing time
863 int check_scan_times( uint32_t nscan, double *sstime, short *sfl) {
864 
865  vector<uint32_t> kf, kv;
866  for (size_t i=0; i<nscan; i++) {
867  if (sstime[i] == -999 || sstime[i] == -32767)
868  kf.push_back(i);
869  else
870  kv.push_back(i);
871  }
872 
873  size_t nf = kf.size();
874  if ( nf == 0) return 0;
875 
876  size_t nv = kv.size();
877 
878  // Interpolate valid times to fill missing values
879  for (size_t i=0; i<nf; i++) {
880 
881  // Check for missing time before valid time
882  if (kf[i] < kv[0]) { //if there are no good previous times
883  sstime[kf[i]] = sstime[kv[0]] -
884  (sstime[kv[1]]-sstime[kv[0]])*(kv[0]-kf[i])/(kv[1]-kv[0]);
885  } else if (kf[i] > kv[nv-1]) { //if there are no good next times
886  sstime[kf[i]] = sstime[kv[nv-1]] +
887  (sstime[kv[nv-1]]-sstime[kv[nv-2]])*(kf[i]-kv[nv-1])/
888  (kv[nv-1]-kv[nv-2]);
889  } else {
890  size_t iv=0;
891  for (int j=nv-1; j>=0; j--) {
892  if (kv[j] < kf[i]) {
893  iv = j;
894  break;
895  }
896  }
897  sstime[kf[i]] = sstime[kv[iv]] +
898  (sstime[kv[iv+1]]-sstime[kv[iv]])*(kf[i]-kv[iv])/(kv[iv+1]-kv[iv]);
899  }
900  *(sfl+kf[i]) |= 2; // set missing time flag for all nf(ailed)
901  }
902  return 0;
903 
904 }
int j
Definition: decode_rs.h:73
void nc_init_compress(int32_t nc_id, int32_t var_id, int32_t *dimids, int32_t rank, size_t *chunksize, int deflate_level)
#define NULL
Definition: decode_rs.h:63
void spin(double st, double *pos1, double *pos2)
int check_scan_times(uint32_t nscan, double *sstime, short *sfl)
Definition: common.cpp:863
const double pi
float32 * pos
Definition: l1_czcs_hdf.c:35
#define SWAP_4(x)
Definition: common.h:18
int32 nscan
Definition: l1_czcs_hdf.c:19
@ string
int createField(NcGroup &ncGrp, const char *sname, const char *lname, const char *standard_name, const char *units, const char *description, void *fill_value, const char *flag_masks, const char *flag_meanings, double low, double high, double scale, double offset, int nt, vector< NcDim > &varVec, string coordinates)
Definition: common.cpp:312
double ham_enc_scale
Definition: common.h:40
int get_oci_vecs(uint32_t nscan, uint16_t pdim, double as_planarity[5], double at_planarity[5], int32_t *rta_nadir, double ham_ct_angles[2], double ev_toff, int32_t spin, uint8_t hside, float *clines, double *delt, double revpsec, int32_t ppr_off, int16_t board_id, uint32_t nmcescan, int32_t *mspin, uint8_t *enc_count, float **hamenc, float **rtaenc, float **pview, double *theta, int16_t &iret)
Definition: common.cpp:195
double rta_enc_scale
Definition: common.h:39
double MCE_clock
Definition: common.h:27
int get_nib_nbb(uint32_t ntaps, size_t *ia, uint32_t ntb[16], int16_t jagg[16], uint32_t &nib, uint32_t &nbb)
Definition: common.cpp:742
#define SWAP_2(x)
double master_clock
Definition: common.h:26
description
Definition: setup.py:16
dtype
Definition: DDataset.hpp:31
int read_mce_tlm(NcFile *l1afile, geo_struct &geo_lut, NcGroup egid, uint32_t nmcescan, uint32_t nenc, int32_t &ppr_off, double &revpsec, double &secpline, int16_t &board_id, int32_t *mspin, int32_t *ot_10us, uint8_t *enc_count, float **hamenc, float **rtaenc, int16_t &iret)
Definition: common.cpp:8
l2prod offset
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]
#define abs(a)
Definition: misc.h:90
int i
Definition: decode_rs.h:71
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, bool dark, int16_t &iret)
Definition: common.cpp:142
int k
Definition: decode_rs.h:73
float32 f32
Definition: l2bin.cpp:98
int get_agg_mat(size_t *ia, int16_t jagg[16], uint32_t ntb[16], uint32_t nib, uint32_t nbb, float **amat, float **gmat)
Definition: common.cpp:777
int count
Definition: decode_rs.h:79