OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l1aFile.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <string.h>
5 #include <limits.h>
6 #include <libgen.h>
7 
8 #include <sstream>
9 #include <iomanip>
10 #include "l1agen_viirs.h"
11 #include "nc4utils.h"
12 #include "netcdf.h"
13 #include "passthebuck.h"
14 #include <timeutils.h>
15 
16 
18  ncid = -1;
19  SC_records_val = 0;
20  SC_10hz_records_val = 0;
21 }
22 
23 
25 
26 }
27 
28  /*----------------------------------------------------------------- */
29  /* Create an Generic NETCDF4 level1 file */
30  /* ---------------------------------------------------------------- */
31 int l1aFile::createl1( char* l1_filename, int32_t sscan, int32_t escan,
32  int32_t spixl, int32_t epixl, int32_t iopt_extract) {
33 
34  int status;
35  status = nc_create( l1_filename, NC_NETCDF4, &ncid);
36  check_err(status,__LINE__,__FILE__);
37 
38  ifstream viirs_l1a_data_structure;
39  string line;
40  string dataStructureFile;
41 
42  if ( this->platform == "JPSS-1")
43  dataStructureFile.assign("$OCDATAROOT/viirs/j1/VIIRS_Level-1A_Data_Structure_J1.cdl");
44  else if ( this->platform == "JPSS-2")
45  dataStructureFile.assign("$OCDATAROOT/viirs/j2/VIIRS_Level-1A_Data_Structure_J2.cdl");
46  else
47  dataStructureFile.assign("$OCDATAROOT/viirs/npp/VIIRS_Level-1A_Data_Structure.cdl");
48  expandEnvVar( &dataStructureFile);
49 
50  viirs_l1a_data_structure.open( dataStructureFile.c_str(), ifstream::in);
51  if ( viirs_l1a_data_structure.fail() == true) {
52  cout << "\"" << dataStructureFile.c_str() << "\" not found" << endl;
53  exit(1);
54  }
55 
56  // Find "dimensions" section of CDL file
57  while(1) {
58  getline( viirs_l1a_data_structure, line);
59  size_t pos = line.find("dimensions:");
60  if ( pos == 0) break;
61  }
62 
63  // Define dimensions from "dimensions" section of CDL file
64  ndims = 0;
65  int32_t numScans = escan - sscan + 1;
66  while(1) {
67  getline( viirs_l1a_data_structure, line);
68  size_t pos = line.find(" = ");
69  if ( pos == string::npos) break;
70 
71  uint32_t dimSize;
72  istringstream iss(line.substr(pos+2, string::npos));
73  iss >> dimSize;
74 
75  iss.clear();
76  iss.str( line);
77  iss >> skipws >> line;
78 
79  // cout << "Dimension Name: " << line.c_str() << " Dimension Size: "
80  // << dimSize << endl;
81 
82  if (line.compare("number_of_scans") == 0 && numScans > 0) {
83  dimSize = numScans;
84  }
85 
86  // Add 0.5 to correct rounding error JMG 12/07/16
87  if ((line.compare("SC_records") == 0 ||
88  line.compare("SC_1hz_records") == 0)
89  && numScans > 0) {
90  dimSize = (int32_t) (numScans*1.78 + 0.5) + 20;
91  // cout << "SC_records_val: " << dimSize << endl;
92  SC_records_val = dimSize;
93  }
94 
95  if (line.compare("SC_10hz_records") == 0 && numScans > 0) {
96  // dimSize = (int32_t) (numScans*1.78 + 0.5) + 20;
97  // cout << "SC_records_val: " << dimSize << endl;
98  SC_10hz_records_val = dimSize;
99  }
100 
101  // 0 - 639 pixel_offset
102  // 640 - 1007 640 + 2*(pixel_offset - 640)
103  // 1008 - 2191 1376 + 3*(pixel_offset - 1008)
104  // 2192 - 2559 4928 + 2*(pixel_offset - 2192)
105  // 2560 - 3199 5664 + (pixel_offset - 2560)
106 
107  if ( spixl != 0 || epixl != 3199) {
108  if (line.compare("Mband_pixels") == 0) {
109  dimSize = epixl - spixl + 1;
110  } else if (line.compare("Iband_pixels") == 0) {
111  dimSize = 2*(epixl - spixl + 1);
112  } else if (line.compare("Mband_samples") == 0) {
113  if ( spixl <= 639) {
114  dimSize = spixl;
115  } else if ( spixl > 639 && spixl <= 1007) {
116  dimSize = 640 + 2*(spixl - 640);
117  } else if ( spixl > 1007 && spixl <= 2191) {
118  dimSize = 1376 + 3*(spixl - 1008);
119  } else if ( spixl > 2191 && spixl <= 2559) {
120  dimSize = 4928 + 2*(spixl - 2192);
121  } else if ( spixl > 2559) {
122  dimSize = 5664 + (spixl - 2560);
123  }
124 
125  int32_t epixl0;
126  if ( epixl <= 639) {
127  epixl0 = epixl;
128  } else if ( epixl > 639 && epixl <= 1007) {
129  epixl0 = 641 + 2*(epixl - 640);
130  } else if ( epixl > 1007 && epixl <= 2191) {
131  epixl0 = 1378 + 3*(epixl - 1008);
132  } else if ( epixl > 2191 && epixl <= 2559) {
133  epixl0 = 4929 + 2*(epixl - 2192);
134  } else if ( epixl > 2559) {
135  epixl0 = 5664 + (epixl - 2560);
136  }
137  dimSize = epixl0 - dimSize + 1;
138  }
139  }
140 
141  status = nc_def_dim( ncid, line.c_str(), dimSize, &dimid[ndims++]);
142  check_err(status,__LINE__,__FILE__);
143  } // while loop
144 
145  // Read global attributes (string attributes only)
146  while(1) {
147  getline( viirs_l1a_data_structure, line);
148  size_t pos = line.find("// global attributes");
149  if ( pos == 0) break;
150  }
151 
152  while(1) {
153  getline( viirs_l1a_data_structure, line);
154  size_t pos = line.find(" = ");
155  if ( pos == string::npos) break;
156 
157  string attValue;
158 
159  // Remove leading and trailing quotes
160  attValue.assign(line.substr(pos+4));
161  size_t posQuote = attValue.find("\"");
162  attValue.assign(attValue.substr(0, posQuote));
163 
164  istringstream iss(line.substr(pos+2));
165  iss.clear();
166  iss.str( line);
167  iss >> skipws >> line;
168 
169  // Skip commented out attributes
170  if (line.compare("//") == 0) continue;
171 
172  string attName;
173  attName.assign(line.substr(1).c_str());
174 
175  // Skip non-string attributes
176  if (attName.compare("orbit_number") == 0) continue;
177  if (attName.compare("history") == 0) continue;
178  if (attName.compare("format_version") == 0) continue;
179  if (attName.compare("instrument_number") == 0) continue;
180  if (attName.compare("pixel_offset") == 0) continue;
181  if (attName.compare("number_of_filled_scans") == 0) continue;
182 
183  // cout << attName.c_str() << " " << attValue.c_str() << endl;
184 
185  status = nc_put_att_text(ncid, NC_GLOBAL, attName.c_str(),
186  strlen(attValue.c_str()), attValue.c_str());
187  check_err(status,__LINE__,__FILE__);
188 
189  }
190 
191  ngrps = 0;
192  // Loop through groups
193  while(1) {
194  getline( viirs_l1a_data_structure, line);
195 
196  // Check if end of CDL file
197  // If so then close CDL file and return
198  if (line.substr(0,1).compare("}") == 0) {
199  viirs_l1a_data_structure.close();
200  return 0;
201  }
202 
203  // Check for beginning of new group
204  size_t pos = line.find("group:");
205 
206  // If found then create new group and variables
207  if ( pos == 0) {
208 
209  // Parse group name
210  istringstream iss(line.substr(6, string::npos));
211  iss >> skipws >> line;
212 
213  // Create NCDF4 group
214  status = nc_def_grp( ncid, line.c_str(), &this->gid[ngrps]);
215  check_err(status,__LINE__,__FILE__);
216 
217  ngrps++;
218 
219  int numDims=0;
220  int varDims[NC_MAX_DIMS];
221  size_t dimSize[NC_MAX_DIMS];
222  char dimName[NC_MAX_NAME+1];
223  string sname;
224  string lname;
225  string standard_name;
226  string units;
227  string flag_values;
228  string flag_meanings;
229  double valid_min=0.0;
230  double valid_max=0.0;
231  double fill_value=0.0;
232 
233  int ntype=0;
234 
235  // Loop through datasets in group
236  getline( viirs_l1a_data_structure, line); // skip "variables:"
237  while(1) {
238  getline( viirs_l1a_data_structure, line);
239 
240  if (line.length() == 0) continue;
241  if (line.substr(0,1).compare("\r") == 0) continue;
242  if (line.substr(0,1).compare("\n") == 0) continue;
243 
244  size_t found = line.find("DNB");
245  if (found != string::npos && iopt_extract == 1) {
246  continue;
247  }
248 
249  size_t pos = line.find(":");
250 
251  // No ":" found, new dataset or empty line or end-of-group
252  if ( pos == string::npos) {
253 
254  if ( numDims > 0) {
255  // Create previous dataset
256  createNCDF( gid[ngrps-1],
257  sname.c_str(), lname.c_str(),
258  standard_name.c_str(), units.c_str(),
259  (void *) &fill_value,
260  flag_values.c_str(), flag_meanings.c_str(),
261  valid_min, valid_max, ntype, numDims, varDims);
262 
263  flag_values.assign("");
264  flag_meanings.assign("");
265  units.assign("");
266  }
267 
268  valid_min=0.0;
269  valid_max=0.0;
270  fill_value=0.0;
271 
272  if (line.substr(0,10).compare("} // group") == 0) break;
273 
274  // Parse variable type
275  string varType;
276  istringstream iss(line);
277  iss >> skipws >> varType;
278 
279  // Get corresponding NC variable type
280  if ( varType.compare("char") == 0) ntype = NC_CHAR;
281  else if ( varType.compare("byte") == 0) ntype = NC_BYTE;
282  else if ( varType.compare("short") == 0) ntype = NC_SHORT;
283  else if ( varType.compare("int") == 0) ntype = NC_INT;
284  else if ( varType.compare("long") == 0) ntype = NC_INT;
285  else if ( varType.compare("float") == 0) ntype = NC_FLOAT;
286  else if ( varType.compare("real") == 0) ntype = NC_FLOAT;
287  else if ( varType.compare("double") == 0) ntype = NC_DOUBLE;
288  else if ( varType.compare("ubyte") == 0) ntype = NC_UBYTE;
289  else if ( varType.compare("ushort") == 0) ntype = NC_USHORT;
290  else if ( varType.compare("uint") == 0) ntype = NC_UINT;
291  else if ( varType.compare("int64") == 0) ntype = NC_INT64;
292  else if ( varType.compare("uint64") == 0) ntype = NC_UINT64;
293 
294  // Parse short name (sname)
295  pos = line.find("(");
296  size_t posSname = line.substr(0, pos).rfind(" ");
297  sname.assign(line.substr(posSname+1, pos-posSname-1));
298  // cout << "sname: " << sname.c_str() << endl;
299 
300  // Parse variable dimension info
301  this->parseDims( line.substr(pos+1, string::npos),
302  &numDims, varDims);
303  for (int i=0; i<numDims; i++) {
304  nc_inq_dim( ncid, varDims[i], dimName, &dimSize[i]);
305  //cout << line.c_str() << " " << i << " " << dimName
306  // << " " << dimSize[i] << endl;
307  }
308 
309  } else {
310  // Parse variable attributes
311  size_t posEql = line.find("=");
312  size_t pos1qte = line.find("\"");
313  size_t pos2qte = line.substr(pos1qte+1, string::npos).find("\"");
314  // cout << line.substr(pos+1, posEql-pos-2).c_str() << endl;
315 
316  string attrName = line.substr(pos+1, posEql-pos-2);
317 
318  // Get long_name
319  if ( attrName.compare("long_name") == 0) {
320  lname.assign(line.substr(pos1qte+1, pos2qte));
321  // cout << "lname: " << lname.c_str() << endl;
322  }
323 
324  // Get units
325  else if ( attrName.compare("units") == 0) {
326  units.assign(line.substr(pos1qte+1, pos2qte));
327  // cout << "units: " << units.c_str() << endl;
328  }
329 
330  // Get _FillValue
331  else if ( attrName.compare("_FillValue") == 0) {
332  iss.clear();
333  iss.str( line.substr(posEql+1, string::npos));
334  iss >> fill_value;
335  // cout << "_FillValue: " << fill_value << endl;
336  }
337 
338  // Get flag_values
339  else if ( attrName.compare("flag_values") == 0) {
340  flag_values.assign(line.substr(pos1qte+1, pos2qte));
341  }
342 
343  // Get flag_meanings
344  else if ( attrName.compare("flag_meanings") == 0) {
345  flag_meanings.assign(line.substr(pos1qte+1, pos2qte));
346  }
347 
348  // Get valid_min
349  else if ( attrName.compare("valid_min") == 0) {
350  iss.clear();
351  iss.str( line.substr(posEql+1, string::npos));
352  iss >> valid_min;
353  // cout << "valid_min: " << valid_min << endl;
354  }
355 
356  // Get valid_max
357  else if ( attrName.compare("valid_max") == 0) {
358  iss.clear();
359  iss.str( line.substr(posEql+1, string::npos));
360  iss >> valid_max;
361  // cout << "valid_max: " << valid_max << endl;
362  }
363 
364  } // if ( pos == string::npos)
365  } // datasets in group loop
366  } // New Group loop
367  } // Main Group loop
368 
369 
370  return 0;
371 }
372 
373 
374 int l1aFile::createl1( char* l1_filename, int32_t numScans) {
375  this -> createl1( l1_filename, (int32_t) 0, numScans-1,
376  (int32_t) 0, (int32_t) 3199, (int32_t) 0);
377 
378  return 0;
379 }
380 
381 int l1aFile::parseDims( string dimString, int *numDims, int *varDims) {
382 
383  size_t dimSize, curPos=0;
384  char dimName[NC_MAX_NAME+1];
385 
386  *numDims = 0;
387 
388  while(1) {
389  size_t pos = dimString.find(",", curPos);
390  if ( pos == string::npos)
391  pos = dimString.find(")");
392 
393  string varDimName;
394  istringstream iss(dimString.substr(curPos, pos-curPos));
395  iss >> skipws >> varDimName;
396 
397  for (int i=0; i<ndims; i++) {
398  int status = nc_inq_dim( ncid, dimid[i], dimName, &dimSize);
399  if (status != NC_NOERR) {
400  printf("-E - failed to retrieve dim: %s\n",dimName);
401  }
402  if ( varDimName.compare(dimName) == 0) {
403  varDims[(*numDims)++] = dimid[i];
404  break;
405  }
406  }
407  if ( dimString.substr(pos, 1).compare(")") == 0) break;
408 
409  curPos = pos + 1;
410  }
411 
412  return 0;
413 }
414 
415 
416 int l1aFile::write_science_data( string platform, int32_t isc,
417  uint16_t (*mbands)[16][6304],
418  uint16_t (*ibands)[32][6400],
419  uint16_t (*dnb)[16][4064],
420  uint8_t (*mqfl)[16],
421  uint8_t (*iqfl)[32],
422  uint8_t (*dqfl)[16]) {
423 
424  int groupid;
425  int status = nc_inq_grp_ncid( ncid, "earth_view_data", &groupid);
426  check_err(status,__LINE__,__FILE__);
427 
428  size_t start[3]={(size_t)isc, 0, 0};
429  size_t count[3]={1, 0, 0};
430 
431  // Write M-band data
432  for ( int i=0; i<=15; i++) {
433  count[2] = 3200;
434  if (i < 5 or i == 6 or i == 12) count[2] = 6304;
435 
436  // Check if any missing detectors
437  uint8_t m[16];
438  for ( int j=0; j<16; j++) {
439  if ( mqfl[i][j] >= 64) {
440  m[j] = 1;
441  } else {
442  m[j] = 0;
443  }
444  }
445 
446  stringstream varstr;
447  varstr << "EV_M" << setfill('0') << setw(2) << i+1;
448 
449  int varid;
450  status = nc_inq_varid( groupid, varstr.str().c_str(), &varid);
451  check_err(status,__LINE__,__FILE__);
452 
453  count[1] = 1;
454  for ( int j=0; j<16; j++) {
455  if ( m[j] == 0) {
456  start[1] = j;
457  status = nc_put_vara_short( groupid, varid, start, count,
458  (const short int*) &mbands[i][j][0]);
459  check_err(status,__LINE__,__FILE__);
460  }
461  }
462  }
463 
464 
465  // Write I-band data
466  count[2] = 6400;
467  for ( int i=0; i<=4; i++) {
468 
469  // Check if any missing detectors
470  uint8_t m[32];
471  uint8_t missing = 0;
472  for ( int j=0; j<32; j++) {
473  if ( iqfl[i][j] >= 64) {
474  m[j] = 1;
475  missing = 1;
476  } else {
477  m[j] = 0;
478  }
479  }
480 
481  stringstream varstr;
482  varstr << "EV_I" << setfill('0') << setw(2) << i+1;
483  // cout << varstr.str() << endl;
484 
485  int varid, status;
486  status = nc_inq_varid( groupid, varstr.str().c_str(), &varid);
487  check_err(status,__LINE__,__FILE__);
488 
489  if ( missing == 0) {
490  count[1] = 32;
491  start[1] = 0;
492  status = nc_put_vara_short( groupid, varid, start, count,
493  (const short int*) &ibands[i][0][0]);
494  check_err(status,__LINE__,__FILE__);
495 
496  } else {
497  count[1] = 1;
498  for ( int j=0; j<16; j++) {
499  if ( m[j] == 0) {
500  start[1] = j;
501  status = nc_put_vara_short( groupid, varid, start, count,
502  (const short int*) &ibands[i][j][0]);
503  check_err(status,__LINE__,__FILE__);
504  }
505  }
506  }
507  }
508 
509 
510  // Write DNB
511  int nDNB=0;
512  if ( platform.compare("SNPP") == 0)
513  nDNB = 3;
514  else if ( platform.compare("JPSS-1") == 0)
515  nDNB = 5;
516  else if ( platform.compare("JPSS-2") == 0)
517  nDNB = 5;
518 
519  for ( int i=0; i<nDNB; i++) {
520  count[2] = 4064;
521 
522  // Check if any missing detectors
523  uint8_t m[16];
524  uint8_t missing = 0;
525  for ( int j=0; j<16; j++) {
526  if ( dqfl[i][j] >= 64) {
527  m[j] = 1;
528  missing = 1;
529  } else {
530  m[j] = 0;
531  }
532  }
533 
534  stringstream varstr;
535  string dnb_tag[5]={"HGS", "MGS", "LGS", "HGA", "HGB"};
536  varstr << "EV_DNB_" << dnb_tag[i];
537  //cout << varstr.str() << endl;
538 
539  int varid, status;
540  status = nc_inq_varid( groupid, varstr.str().c_str(), &varid);
541  check_err(status,__LINE__,__FILE__);
542 
543  if ( missing == 0) {
544  count[1] = 16;
545  start[1] = 0;
546  status = nc_put_vara_short( groupid, varid, start, count,
547  (const short int*) &dnb[i][0][0]);
548  check_err(status,__LINE__,__FILE__);
549 
550  } else {
551  count[1] = 1;
552  for ( int j=0; j<16; j++) {
553  if ( m[j] == 0) {
554  start[1] = j;
555  status = nc_put_vara_short( groupid, varid, start, count,
556  (const short int*) &dnb[i][j][0]);
557  check_err(status,__LINE__,__FILE__);
558  }
559  }
560  }
561  } // nDNB loop
562 
563  return 0;
564 }
565 
566 
568  uint8_t (*p1)[180],
569  uint8_t (*hrmets)[146*26],
570  uint8_t (*calmets)[134],
571  uint8_t *mode, int iret,
572  const char* l1a_name,
573  char* VIIRS_packet_file) {
574 
575  cout << "Writing scan-level metadata" << endl;
576 
577  static char initial_L0_time[32] = "9999";
578  static char final_L0_time[32] = "0000";
579  static int32_t total_isc = 0;
580  static int total_iret = 0;
581 
582  total_isc += isc;
583  total_iret |= iret;
584 
585  char buf[1000];
586  strcpy( buf, (char *) l1a_name);
587  ofstream fout;
588  char *last_dot = strrchr( buf, '.');
589  if (!last_dot) {
590  last_dot = buf + strlen(buf);
591  strcat(buf, ".txt");
592  } else {
593  strcpy( last_dot, ".txt");
594  }
595  fout.open( buf);
596  *last_dot = 0;
597  strcat( buf, ".nc");
598  fout << "basename=" << basename(buf) << endl;
599 
600  int groupid;
601  int status = nc_inq_grp_ncid( ncid, "scan_line_attributes", &groupid);
602  check_err(status,__LINE__,__FILE__);
603 
604  // Extract and convert times
605  double *scs = new double[isc];
606  double *sce = new double[isc];
607  int16_t *scsd = new int16_t[isc];
608  int32_t *scsm = new int32_t[isc];
609  int16_t *scsu = new int16_t[isc];
610  int16_t *sced = new int16_t[isc];
611  int32_t *scem = new int32_t[isc];
612  int16_t *sceu = new int16_t[isc];
613 
614  uint16_t ui16;
615  uint32_t ui32;
616 
617  for ( int i=0; i<isc; i++) {
618  // Convert scan start and end times to TAI93
619 
620  int32_t toff, syear, sday, eyear, eday, iyear, iday;
621  double stime, ptime, etime;
622 
623  // Scan start time
624  toff = 6;
625  ccsds_to_yds( &p1[i][toff], &syear , &sday, &stime);
626 
627  // Packet time
628  toff = 20;
629  ccsds_to_yds( &p1[i][toff], &iyear, &iday, &ptime);
630 
631  // Scan end time
632  toff = 38;
633  ccsds_to_yds( &p1[i][toff], &eyear, &eday, &etime);
634 
635  scs[i] = yds2tai93( syear, sday, stime);
636  sce[i] = yds2tai93( eyear, eday, etime);
637 
638  char datebuf[32];
639  if ( i == 0) {
640  double dsec = (double) stime;
641  double myUnixTime= yds2unix(syear, sday, dsec);
642  strcpy( datebuf, unix2isodate(myUnixTime, 'G'));
643  // cout << datebuf << endl;
644  fout << "start_time=" << datebuf << endl;
645  if ( strcmp( datebuf, initial_L0_time) < 0)
646  strcpy( initial_L0_time, datebuf);
647  }
648 
649  if ( i == (isc-1)) {
650  // Change from etime 08/19/15 JMG
651  // Change eyear,eday to syear,sday 08/24/15 JMG
652  double dsec = (double) stime;
653  double myUnixTime= yds2unix(syear, sday, dsec);
654  strcpy( datebuf, unix2isodate(myUnixTime, 'G'));
655  // cout << datebuf << endl;
656  fout << "stop_time=" << datebuf << endl;
657  if ( strcmp( datebuf, final_L0_time) > 0)
658  strcpy( final_L0_time, datebuf);
659  }
660 
661  memcpy( &ui16, (uint16_t *) &p1[i][6], 2);
662  scsd[i] = SWAP_2( ui16);
663 
664  memcpy( &ui32, (uint32_t *) &p1[i][8], 4);
665  scsm[i] = SWAP_4( ui32);
666 
667  memcpy( &ui16, (uint16_t *) &p1[i][12], 2);
668  scsu[i] = SWAP_2( ui16);
669 
670  memcpy( &ui16, (uint16_t *) &p1[i][38], 2);
671  sced[i] = SWAP_2( ui16);
672 
673  memcpy( &ui32, (uint32_t *) &p1[i][40], 4);
674  scem[i] = SWAP_4( ui32);
675 
676  memcpy( &ui16, (uint16_t *) &p1[i][44], 2);
677  sceu[i] = SWAP_2( ui16);
678  }
679 
680  int varid;
681  size_t start[3]={0, 0, 0};
682  size_t count[3];
683  count[0] = (size_t) isc;
684  count[1] = this->EV_APIDs;
685  count[2] = 146;
686 
687  // Scan start time (TAI93)
688  status = nc_inq_varid( groupid, "scan_start_time", &varid);
689  check_err(status,__LINE__,__FILE__);
690  status = nc_put_vara( groupid, varid, start, count, (double *) scs);
691  check_err(status,__LINE__,__FILE__);
692 
693  // Scan end time (TAI93)
694  status = nc_inq_varid( groupid, "scan_end_time", &varid);
695  check_err(status,__LINE__,__FILE__);
696  status = nc_put_vara( groupid, varid, start, count, (double *) sce);
697  check_err(status,__LINE__,__FILE__);
698 
699 
700  // Scan start time (CCSDS)
701  // Day
702  status = nc_inq_varid( groupid, "scan_start_CCSDS_day", &varid);
703  check_err(status,__LINE__,__FILE__);
704  status = nc_put_vara( groupid, varid, start, count, (int16_t *) scsd);
705  check_err(status,__LINE__,__FILE__);
706 
707  // Milliseconds
708  status = nc_inq_varid( groupid, "scan_start_CCSDS_msec", &varid);
709  check_err(status,__LINE__,__FILE__);
710  status = nc_put_vara( groupid, varid, start, count, (int32_t *) scsm);
711  check_err(status,__LINE__,__FILE__);
712 
713  status = nc_inq_varid( groupid, "scan_start_CCSDS_usec", &varid);
714  check_err(status,__LINE__,__FILE__);
715  status = nc_put_vara( groupid, varid, start, count, (int16_t *) scsu);
716  check_err(status,__LINE__,__FILE__);
717 
718 
719  // Scan end time (CCSDS)
720  // Day
721  status = nc_inq_varid( groupid, "scan_end_CCSDS_day", &varid);
722  check_err(status,__LINE__,__FILE__);
723  status = nc_put_vara( groupid, varid, start, count, (int16_t *) sced);
724  check_err(status,__LINE__,__FILE__);
725 
726  // Milliseconds
727  status = nc_inq_varid( groupid, "scan_end_CCSDS_msec", &varid);
728  check_err(status,__LINE__,__FILE__);
729  status = nc_put_vara( groupid, varid, start, count, (int32_t *) scem);
730  check_err(status,__LINE__,__FILE__);
731 
732  status = nc_inq_varid( groupid, "scan_end_CCSDS_usec", &varid);
733  check_err(status,__LINE__,__FILE__);
734  status = nc_put_vara( groupid, varid, start, count, (int16_t *) sceu);
735  check_err(status,__LINE__,__FILE__);
736 
737 
738  // Extract and write HAM side, instrument scan number and sensor mode
739  uint8_t *ham = new uint8_t[isc];
740  for ( int i=0; i<isc; i++) ham[i] = (p1[i][32] & 128) / 128;
741 
742  for ( int i=0; i<isc; i++) mode[i] = p1[i][46];
743 
744  uint32_t *scnum = new uint32_t[isc];
745  for ( int i=0; i<isc; i++) {
746  memcpy( &ui32, (uint32_t *) &p1[i][34], 4);
747  scnum[i] = SWAP_4( ui32);
748  }
749 
750  status = nc_inq_varid( groupid, "HAM_side", &varid);
751  check_err(status,__LINE__,__FILE__);
752  status = nc_put_vara( groupid, varid, start, count, (uint8_t *) ham);
753  check_err(status,__LINE__,__FILE__);
754 
755  status = nc_inq_varid( groupid, "VIIRS_scan_number", &varid);
756  check_err(status,__LINE__,__FILE__);
757  status = nc_put_vara( groupid, varid, start, count, (int32_t *) scnum);
758  check_err(status,__LINE__,__FILE__);
759 
760  status = nc_inq_varid( groupid, "sensor_mode", &varid);
761  check_err(status,__LINE__,__FILE__);
762  status = nc_put_vara( groupid, varid, start, count, (uint8_t *) mode);
763  check_err(status,__LINE__,__FILE__);
764 
765  // Write HR metadata and cal metadata
766  status = nc_inq_varid( groupid, "HR_metadata", &varid);
767  check_err(status,__LINE__,__FILE__);
768  status = nc_put_vara( groupid, varid, start, count,
769  (uint8_t *) &hrmets[0][0]);
770  check_err(status,__LINE__,__FILE__);
771 
772  count[1] = 134;
773  status = nc_inq_varid( groupid, "cal_metadata", &varid);
774  check_err(status,__LINE__,__FILE__);
775  status = nc_put_vara( groupid, varid, start, count,
776  (uint8_t *) &calmets[0][0]);
777  check_err(status,__LINE__,__FILE__);
778 
779 
780  // Write DNB_sequence
781  status = nc_inq_grp_ncid( ncid, "onboard_calibration_data", &groupid);
782  check_err(status,__LINE__,__FILE__);
783 
784  uint8_t *dnb_seq = (uint8_t *) calloc( isc, sizeof(uint8_t));
785  for ( int i=0; i<isc; i++) {
786  dnb_seq[i] = (calmets[i][0] % 4)*16 + calmets[i][1]/16;
787  }
788 
789  status = nc_inq_varid( groupid, "DNB_sequence", &varid);
790  check_err(status,__LINE__,__FILE__);
791  status = nc_put_vara( groupid, varid, start, count,
792  (uint8_t *) dnb_seq);
793  check_err(status,__LINE__,__FILE__);
794 
795  free( dnb_seq);
796 
797  delete[] scs;
798  delete[] sce;
799  delete[] scsd;
800  delete[] scsm;
801  delete[] scsu;
802  delete[] sced;
803  delete[] scem;
804  delete[] sceu;
805 
806  delete[] ham;
807  delete[] scnum;
808 
809  fout << "number_of_records=" << isc << endl;
810  fout << "quality_flag=" << iret << endl;
811  fout.close();
812 
813  strcpy( buf, (char *) VIIRS_packet_file);
814  last_dot = strrchr( buf, '.');
815  if (!last_dot) {
816  last_dot = buf + strlen(buf);
817  strcat(buf, ".txt");
818  } else {
819  strcpy( last_dot, ".txt");
820  }
821  fout.open( buf);
822  *last_dot = 0;
823  strcat( buf, ".PDS");
824  fout << "basename=" << basename(buf) << endl;
825  fout << "start_time=" << initial_L0_time << endl;
826  fout << "stop_time=" << final_L0_time << endl;
827  fout << "number_of_records=" << total_isc << endl;
828  fout << "quality_flag=" << total_iret << endl;
829  fout.close();
830 
831  return 0;
832 }
833 
834 
835 int l1aFile::write_eng_data( int32_t isc, uint8_t (*engdata)[9318]) {
836 
837  cout << "Writing engineering data" << endl;
838 
839  int groupid;
840  int status = nc_inq_grp_ncid( ncid, "engineering_data", &groupid);
841  check_err(status,__LINE__,__FILE__);
842 
843  string engdataName[] = {"engineering_status",
844  "DPP_config",
845  "ASP_config",
846  "DNB_config",
847  "ASP_offsets",
848  "ASP_analog",
849  "analog_temperature",
850  "SDSM_data",
851  "eng_reserved"};
852 
853  int engdataOffset[] = {52, 60, 188, 316, 444, 3516, 3644, 3772, 9188};
854 
855  int varid;
856 
857  int dimids[2];
858  size_t start[2]={0, 0};
859  size_t count[2]={1, 0};
860 
861  // Check for "empty" enginnering buffers
862  bool *empty = new bool[isc];
863  for ( int j=0; j<isc; j++) {
864  uint8_t non_zero = 0;
865  for ( int i=0; i<9318; i++) {
866  if ( engdata[j][i] != 0) {
867  non_zero = 1;
868  break;
869  }
870  } // i-loop
871  if ( non_zero == 1)
872  empty[j] = false;
873  else
874  empty[j] = true;
875  } // j-loop
876 
877  for ( int i=0; i<9; i++) {
878 
879  status = nc_inq_varid( groupid, engdataName[i].c_str(), &varid);
880  check_err(status,__LINE__,__FILE__);
881 
882  status = nc_inq_var( groupid, varid, NULL, NULL, NULL, dimids, NULL);
883  check_err(status,__LINE__,__FILE__);
884 
885  status = nc_inq_dimlen( groupid, dimids[1], &count[1]);
886  check_err(status,__LINE__,__FILE__);
887 
888  for ( int j=0; j<isc; j++) {
889  start[0] = j;
890  status = nc_put_vara( groupid, varid, start, count,
891  (uint8_t *) &engdata[j][engdataOffset[i]]);
892  check_err(status,__LINE__,__FILE__);
893  }
894  }
895 
896  uint16_t encoder_data[1290];
897  count[1] = 1290;
898 
899  string encoderName[] = {"tel_encoder", "HAM_encoder"};
900  int encoderOffset[] = {4028, 4028+2580};
901 
902  for ( int i=0; i<2; i++) {
903  status = nc_inq_varid( groupid, encoderName[i].c_str(), &varid);
904  check_err(status,__LINE__,__FILE__);
905 
906  for ( int j=0; j<isc; j++) {
907  start[0] = j;
908 
909  for ( size_t k=0; k<count[1]; k++) {
910  encoder_data[k] =
911  engdata[j][encoderOffset[i]+2*k]*256 +
912  engdata[j][encoderOffset[i]+2*k+1];
913 
914  // if empty buffer then overwrite with fill value (65535)
915  if ( empty[j]) encoder_data[k] = USHRT_MAX;
916  }
917 
918  status = nc_put_vara( groupid, varid, start, count,
919  (uint16_t *) encoder_data);
920  check_err(status,__LINE__,__FILE__);
921  }
922  }
923 
924  int16_t *i16_buffer = (int16_t *) calloc( isc, sizeof(int16_t));
925 
926  string start_deltaName[] = {"tel_start_enc",
927  "HAM_start_enc",
928  "scan_encoder_delta"};
929 
930  int start_deltaOffset[] = {9188, 9188+2, 60+11};
931 
932  size_t zero=0;
933  size_t isc_size_t = isc;
934 
935  for ( int i=0; i<3; i++) {
936  status = nc_inq_varid( groupid, start_deltaName[i].c_str(), &varid);
937  check_err(status,__LINE__,__FILE__);
938 
939  for ( int j=0; j<isc; j++) {
940  i16_buffer[j] =
941  engdata[j][start_deltaOffset[i]]*256 +
942  engdata[j][start_deltaOffset[i]+1];
943 
944  // Extend 14-bit 2's complement sign bit if set
945  // for "scan_encoder_delta"
946  if (i == 2)
947  if (i16_buffer[j] >= 8192) i16_buffer[j] -= 16384;
948 
949  // if empty buffer then overwrite with fill value (-999)
950  if ( empty[j]) {
951  if ( strcmp( start_deltaName[i].c_str(), "scan_encoder_delta") == 0)
952  i16_buffer[j] = -32768;
953  else
954  i16_buffer[j] = -999;
955  }
956 
957  status = nc_put_vara( groupid, varid, &zero, &isc_size_t,
958  (int16_t *) i16_buffer);
959  check_err(status,__LINE__,__FILE__);
960  }
961  }
962 
963  free ( i16_buffer);
964 
965 
966  uint8_t *ui8_buffer = (uint8_t *) calloc( isc, sizeof(uint8_t));
967 
968  string seName[] = {"se_a_teleHAM_scansyn",
969  "se_b_teleHAM_scansyn",
970  "se_a_anlg_pwr_on",
971  "se_b_anlg_pwr_on",
972  "servo_in_use",
973  "se_a_tele_pos_known",
974  "se_b_tele_pos_known",
975  "se_a_mtrs_stopped",
976  "se_b_mtrs_stopped"};
977 
978  int seOffset[] = {52+1, 52+1, 60+9, 60+9, 60+8, 60+9, 60+9, 60+9, 60+9};
979 
980  uint8_t andFac[] = {2, 1, 128, 8, 16, 16, 1, 32, 2};
981 
982  for ( int i=0; i<9; i++) {
983  status = nc_inq_varid( groupid, seName[i].c_str(), &varid);
984  check_err(status,__LINE__,__FILE__);
985 
986  for ( int j=0; j<isc; j++) {
987  ui8_buffer[j] = (engdata[j][seOffset[i]] & andFac[i]) / andFac[i];
988 
989  // if empty buffer then overwrite with fill value (255)
990  if ( empty[j]) ui8_buffer[j] = 255;
991  }
992 
993  status = nc_put_vara( groupid, varid, &zero, &isc_size_t,
994  (uint8_t *) ui8_buffer);
995  check_err(status,__LINE__,__FILE__);
996  }
997 
998  free ( ui8_buffer);
999 
1000  delete[] empty;
1001 
1002  return 0;
1003 }
1004 
1005  int l1aFile::write_cal_data( int32_t isc,
1006  int16_t (*sd_m)[48*16],
1007  int16_t (*sv_m)[48*16],
1008  int16_t (*bb_m)[48*16],
1009  int16_t (*sd_i)[96*32],
1010  int16_t (*sv_i)[96*32],
1011  int16_t (*bb_i)[96*32],
1012  int16_t (*sd_d)[64*16],
1013  int16_t (*sv_d)[64*16],
1014  int16_t (*bb_d)[64*16]) {
1015 
1016  cout << "Writing calibration data" << endl;
1017 
1018  int groupid;
1019  int status = nc_inq_grp_ncid( ncid, "onboard_calibration_data", &groupid);
1020  check_err(status,__LINE__,__FILE__);
1021 
1022  int varid;
1023 
1024  // M-band data
1025 
1026  // Solar diffuser
1027  status = nc_inq_varid( groupid, "SD_M", &varid);
1028  check_err(status,__LINE__,__FILE__);
1029  status = nc_put_var( groupid, varid, (int16_t *) sd_m);
1030  check_err(status,__LINE__,__FILE__);
1031 
1032  // Space view
1033  status = nc_inq_varid( groupid, "SV_M", &varid);
1034  check_err(status,__LINE__,__FILE__);
1035  status = nc_put_var( groupid, varid, (int16_t *) sv_m);
1036  check_err(status,__LINE__,__FILE__);
1037 
1038  // Blackbody
1039  status = nc_inq_varid( groupid, "BB_M", &varid);
1040  check_err(status,__LINE__,__FILE__);
1041  status = nc_put_var( groupid, varid, (int16_t *) bb_m);
1042  check_err(status,__LINE__,__FILE__);
1043 
1044 
1045  // I-band data
1046 
1047  // Solar diffuser
1048  status = nc_inq_varid( groupid, "SD_I", &varid);
1049  check_err(status,__LINE__,__FILE__);
1050  status = nc_put_var( groupid, varid, (int16_t *) sd_i);
1051  check_err(status,__LINE__,__FILE__);
1052 
1053  // Space view
1054  status = nc_inq_varid( groupid, "SV_I", &varid);
1055  check_err(status,__LINE__,__FILE__);
1056  status = nc_put_var( groupid, varid, (int16_t *) sv_i);
1057  check_err(status,__LINE__,__FILE__);
1058 
1059  // Blackbody
1060  status = nc_inq_varid( groupid, "BB_I", &varid);
1061  check_err(status,__LINE__,__FILE__);
1062  status = nc_put_var( groupid, varid, (int16_t *) bb_i);
1063  check_err(status,__LINE__,__FILE__);
1064 
1065 
1066  // DNB data
1067 
1068  // Solar diffuser
1069  status = nc_inq_varid( groupid, "SD_DNB", &varid);
1070  check_err(status,__LINE__,__FILE__);
1071  status = nc_put_var( groupid, varid, (int16_t *) sd_d);
1072  check_err(status,__LINE__,__FILE__);
1073 
1074  // Space view
1075  status = nc_inq_varid( groupid, "SV_DNB", &varid);
1076  check_err(status,__LINE__,__FILE__);
1077  status = nc_put_var( groupid, varid, (int16_t *) sv_d);
1078  check_err(status,__LINE__,__FILE__);
1079 
1080  // Blackbody
1081  status = nc_inq_varid( groupid, "BB_DNB", &varid);
1082  check_err(status,__LINE__,__FILE__);
1083  status = nc_put_var( groupid, varid, (int16_t *) bb_d);
1084  check_err(status,__LINE__,__FILE__);
1085 
1086  return 0;
1087 }
1088 
1089 
1090 int l1aFile::write_diary( int32_t iyear, int32_t iday,
1091  int32_t ltime, int32_t mtime,
1092  int32_t iyrsc, int32_t idysc, int32_t nscd,
1093  double *otime, float (*orb)[6],
1094  double *atime, float (*quat)[4],
1095  char *sdir, char *edir) {
1096 
1097  int groupid;
1098  int status = nc_inq_grp_ncid( ncid, "navigation_data", &groupid);
1099  check_err(status,__LINE__,__FILE__);
1100 
1101  int varid;
1102  size_t start[2]={0, 0};
1103  size_t count[2]={1, 0};
1104  size_t cnt;
1105 
1106  double tai;
1107  int16_t iyr16 = (int16_t) iyear;
1108  int16_t idy16 = (int16_t) iday;
1109  int16_t iyrsc16 = (int16_t) iyrsc;
1110  int16_t idysc16 = (int16_t) idysc;
1111  int32_t jdg = jday( iyr16, 1, idy16);
1112  int32_t jds = jday( iyrsc16, 1, idysc16);
1113 
1114  uint8_t *k = new uint8_t[nscd];
1115  int32_t nk=0;
1116  int32_t first=-1, last=-1;
1117  for ( int i=0; i<nscd; i++) {
1118  double otm = otime[i] + (jds - jdg)*86400;
1119 
1120  if ( otm > (ltime-10) && otm < (mtime+10)) {
1121  k[i] = 1;
1122  nk++;
1123  if ( first == -1) first = i;
1124  last = i;
1125  } else {
1126  k[i] = 0;
1127  }
1128  }
1129  cout << nk << " orbit vectors in time range" << endl;
1130 
1131  // Write orbit times
1132  if (k[0] != -1) {
1133  cout << "Writing orbit data" << endl;
1134  status = nc_inq_varid( groupid, "orb_time", &varid);
1135  check_err(status,__LINE__,__FILE__);
1136 
1137  cnt = 0;
1138  for ( int i=0; i<nscd; i++) {
1139  if ( k[i] == 1) {
1140  start[0] = cnt;
1141 
1142  tai = yds2tai93( iyrsc16, idysc16, otime[i]);
1143 
1144  // Write TAI93 time
1145  status = nc_put_vara_double( groupid, varid, start, count, &tai);
1146  if (status != NC_NOERR) {
1147  check_err(status,__LINE__,__FILE__);
1148  //report_err(status,__LINE__,__FILE__);
1149  //return 1;
1150  }
1151  // check_err(status,__LINE__,__FILE__);
1152 
1153  cnt++;
1154  }
1155  }
1156 
1157  // Write orbit position and velocity vectors
1158  status = nc_inq_varid( groupid, "orb_pos", &varid);
1159  check_err(status,__LINE__,__FILE__);
1160 
1161  cnt = 0;
1162  for ( int i=0; i<nscd; i++) {
1163  if ( k[i] == 1) {
1164  start[0] = cnt;
1165  count[1] = 3;
1166 
1167  status = nc_put_vara_float( groupid, varid, start, count, &orb[i][0]);
1168  check_err(status,__LINE__,__FILE__);
1169 
1170  cnt++;
1171  }
1172  }
1173 
1174  status = nc_inq_varid( groupid, "orb_vel", &varid);
1175  check_err(status,__LINE__,__FILE__);
1176 
1177  cnt = 0;
1178  for ( int i=0; i<nscd; i++) {
1179  if ( k[i] == 1) {
1180  start[0] = cnt;
1181  count[1] = 3;
1182 
1183  status = nc_put_vara_float( groupid, varid, start, count, &orb[i][3]);
1184  check_err(status,__LINE__,__FILE__);
1185 
1186  cnt++;
1187  }
1188  }
1189  }
1190 
1191  // Get orbit direction for granule-level netadata
1192  if ( first != -1) {
1193  if ( orb[first][5] > 0.0) {
1194  strcpy( sdir, "Ascending");
1195  } else {
1196  strcpy( sdir, "Descending");
1197  }
1198  }
1199 
1200  if ( last != -1) {
1201  if ( orb[last][5] > 0.0) {
1202  strcpy( edir, "Ascending");
1203  } else {
1204  strcpy( edir, "Descending");
1205  }
1206  }
1207 
1208  // Identify attitude times within granule range +/-10 seconds
1209  nk=0;
1210  for ( int i=0; i<nscd; i++) {
1211  double atm = atime[i] + (jds - jdg)*86400;
1212  if ( atm > (ltime-10) && atm < (mtime+10)) {
1213  k[i] = 1;
1214  nk++;
1215  } else {
1216  k[i] = 0;
1217  }
1218  }
1219  cout << nk << " attitude quaternions in time range" << endl;
1220 
1221  // Write attitude times
1222  if (k[0] != -1) {
1223  cout << "Writing attitude data" << endl;
1224  status = nc_inq_varid( groupid, "att_time", &varid);
1225  check_err(status,__LINE__,__FILE__);
1226 
1227  cnt = 0;
1228  for ( int i=0; i<nscd; i++) {
1229  if ( k[i] == 1) {
1230  start[0] = cnt;
1231 
1232  tai = yds2tai93( iyrsc16, idysc16, atime[i]);
1233 
1234  // Write TAI93 time
1235  status = nc_put_vara_double( groupid, varid, start, count, &tai);
1236  if (status != NC_NOERR) {
1237  check_err(status,__LINE__,__FILE__);
1238  // report_err(status,__LINE__,__FILE__);
1239  //return 1;
1240  }
1241  // check_err(status,__LINE__,__FILE__);
1242 
1243  cnt++;
1244  }
1245  }
1246 
1247  status = nc_inq_varid( groupid, "att_quat", &varid);
1248  check_err(status,__LINE__,__FILE__);
1249 
1250  cnt = 0;
1251  for ( int i=0; i<nscd; i++) {
1252  if ( k[i] == 1) {
1253  start[0] = cnt;
1254  count[1] = 4;
1255 
1256  status = nc_put_vara_float( groupid, varid, start, count, &quat[i][0]);
1257  check_err(status,__LINE__,__FILE__);
1258 
1259  cnt++;
1260  }
1261  }
1262  }
1263 
1264  delete[] k;
1265 
1266  return 0;
1267 }
1268 
1269 
1270 int l1aFile::write_adcs_bus( int32_t iyear, int32_t iday,
1271  int32_t ltime, int32_t mtime,
1272  int32_t iyrad, int32_t idyad,
1273  int32_t nadc, int32_t nbus, int32_t ngps,
1274  double *adctime, uint8_t *admandone,
1275  int16_t *adfftid,
1276  double *bustime, uint8_t *adstate,
1277  uint8_t *adsolution,
1278  double *gpstime,
1279  uint8_t *adcpkts[],
1280  uint8_t *buspkts[],
1281  uint8_t *gpspkts[]) {
1282 
1283  int groupid;
1284  int status = nc_inq_grp_ncid( ncid, "navigation_data", &groupid);
1285  check_err(status,__LINE__,__FILE__);
1286 
1287  int varid;
1288  size_t start[2]={0, 0};
1289  size_t count[2]={1, 0};
1290  size_t cnt;
1291 
1292  double tai;
1293  int16_t iyr16 = (int16_t) iyear;
1294  int16_t idy16 = (int16_t) iday;
1295  int16_t iyrad16 = (int16_t) iyrad;
1296  int16_t idyad16 = (int16_t) idyad;
1297  int32_t jdg = jday( iyr16, 1, idy16);
1298  int32_t jds = jday( iyrad16, 1, idyad16);
1299 
1300  uint8_t *k;
1301  k = new uint8_t[nadc];
1302  uint32_t nk=0;
1303  int32_t first=-1;
1304  double prevtime=0;
1305  for ( int i=0; i<nadc; i++) {
1306  double atm = adctime[i] + (jds - jdg)*86400;
1307 
1308  if ( atm > (ltime-10) && atm < (mtime+10)) {
1309  if ( (atm - prevtime) < 0.01) {
1310  cout << "Removing short adc period record: "
1311  << i << " " << fixed << setprecision(4)
1312  << atm << " " << prevtime << endl;
1313  prevtime = atm;
1314  k[i] = 0;
1315  continue;
1316  }
1317  k[i] = 1;
1318  nk++;
1319  if ( first == -1) first = i;
1320 
1321  if ( this->platform == "JPSS-2") {
1322  if ( nk > SC_10hz_records_val) {
1323  nk = SC_10hz_records_val;
1324  break;
1325  }
1326  } else {
1327  if ( nk > SC_records_val) {
1328  nk = SC_records_val;
1329  break;
1330  }
1331  }
1332 
1333  } else {
1334  k[i] = 0;
1335  }
1336  prevtime = atm;
1337  }
1338  cout << nk << " adc records in time range" << endl;
1339 
1340  uint32_t SC_rec_val;
1341 
1342  // Write adc times
1343  cout << "Writing adc data" << endl;
1344  if ( this->platform == "JPSS-2") {
1345  status = nc_inq_varid( groupid, "ADCS_10Hz_time", &varid);
1346  SC_rec_val = SC_10hz_records_val;
1347  } else {
1348  status = nc_inq_varid( groupid, "adcs_time", &varid);
1349  SC_rec_val = SC_records_val;
1350  }
1351  check_err(status,__LINE__,__FILE__);
1352 
1353  cnt = 0;
1354  for ( int i=0; i<nadc; i++) {
1355  if ( k[i] == 1 && cnt < SC_rec_val) {
1356  start[0] = cnt;
1357 
1358  tai = yds2tai93( iyrad16, idyad16, adctime[i]);
1359 
1360  // Write TAI93 time
1361  status = nc_put_vara_double( groupid, varid, start, count, &tai);
1362  if (status != NC_NOERR) {
1363  check_err(status,__LINE__,__FILE__);
1364  // report_err(status,__LINE__,__FILE__);
1365  //return 1;
1366  }
1367  // check_err(status,__LINE__,__FILE__);
1368 
1369  cnt++;
1370  }
1371  }
1372 
1373  // Write admandone & adfftid
1374  status = nc_inq_varid( groupid, "admandone", &varid);
1375  check_err(status,__LINE__,__FILE__);
1376 
1377  cnt = 0;
1378  for ( int i=0; i<nadc; i++) {
1379  if ( k[i] == 1 && cnt < SC_rec_val) {
1380  start[0] = cnt;
1381 
1382  status = nc_put_vara_uchar( groupid, varid, start, count, &admandone[i]);
1383  check_err(status,__LINE__,__FILE__);
1384 
1385  cnt++;
1386  }
1387  }
1388 
1389  status = nc_inq_varid( groupid, "adfftid", &varid);
1390  check_err(status,__LINE__,__FILE__);
1391 
1392  cnt = 0;
1393  for ( int i=0; i<nadc; i++) {
1394  if ( k[i] == 1 && cnt < SC_rec_val) {
1395  start[0] = cnt;
1396 
1397  status = nc_put_vara_short( groupid, varid, start, count, &adfftid[i]);
1398  check_err(status,__LINE__,__FILE__);
1399 
1400  cnt++;
1401  }
1402  }
1403 
1404  // Write ADCS_tlm
1405  if ( this->platform == "JPSS-2")
1406  status = nc_inq_varid( groupid, "ADCS_10Hz_tlm", &varid);
1407  else
1408  status = nc_inq_varid( groupid, "ADCS_tlm", &varid);
1409  check_err(status,__LINE__,__FILE__);
1410 
1411  cnt = 0;
1412  for ( int i=0; i<nadc; i++) {
1413  if ( k[i] == 1 && cnt < SC_rec_val) {
1414  start[0] = cnt;
1415  count[1] = this->apktsize-14;
1416  status = nc_put_vara( groupid, varid, start, count, &adcpkts[i][14]);
1417  check_err(status,__LINE__,__FILE__);
1418 
1419  cnt++;
1420  }
1421  }
1422 
1423  delete[] k;
1424 
1425 
1426  // Identify bus times within granule range +/-10 seconds
1427  k = new uint8_t[nbus];
1428  nk=0;
1429  first=-1;
1430  prevtime = 0;
1431  for ( int i=0; i<nbus; i++) {
1432  double btm = bustime[i] + (jds - jdg)*86400;
1433 
1434  if ( btm > (ltime-10) && btm < (mtime+10)) {
1435  if ( (btm - prevtime) < 0.01) {
1436  cout << "Removing short bus period record: "
1437  << i << " " << fixed << setprecision(4)
1438  << btm << " " << prevtime << endl;
1439  prevtime = btm;
1440  k[i] = 0;
1441  continue;
1442  }
1443  k[i] = 1;
1444  nk++;
1445  if ( first == -1) first = i;
1446 
1447  if ( nk > SC_records_val) {
1448  nk = SC_records_val;
1449  break;
1450  }
1451 
1452  } else {
1453  k[i] = 0;
1454  }
1455  prevtime = btm;
1456  }
1457  cout << nk << " bus records in time range" << endl;
1458 
1459  // Write bus times
1460  cout << "Writing bus data" << endl;
1461  if ( this->platform == "JPSS-2")
1462  status = nc_inq_varid( groupid, "ADCS_1Hz_time", &varid);
1463  else
1464  status = nc_inq_varid( groupid, "bus_time", &varid);
1465  check_err(status,__LINE__,__FILE__);
1466 
1467  cnt = 0;
1468  for ( int i=0; i<nbus; i++) {
1469  if ( k[i] == 1 && cnt < SC_records_val) {
1470  start[0] = cnt;
1471 
1472  tai = yds2tai93( iyrad16, idyad16, bustime[i]);
1473 
1474  // Write TAI93 time
1475  status = nc_put_vara_double( groupid, varid, start, count, &tai);
1476  if (status != NC_NOERR) {
1477  check_err(status,__LINE__,__FILE__);
1478  // report_err(status,__LINE__,__FILE__);
1479  //return 1;
1480  }
1481  // check_err(status,__LINE__,__FILE__);
1482 
1483  cnt++;
1484  }
1485  }
1486 
1487  // Write adstate
1488  status = nc_inq_varid( groupid, "adstate", &varid);
1489  check_err(status,__LINE__,__FILE__);
1490 
1491  cnt = 0;
1492  for ( int i=0; i<nbus; i++) {
1493  if ( k[i] == 1 && cnt < SC_records_val) {
1494  start[0] = cnt;
1495 
1496  status = nc_put_vara_uchar( groupid, varid, start, count, &adstate[i]);
1497  check_err(status,__LINE__,__FILE__);
1498 
1499  cnt++;
1500  }
1501  }
1502 
1503  // Write adsolution
1504  status = nc_inq_varid( groupid, "adsolution", &varid);
1505  check_err(status,__LINE__,__FILE__);
1506 
1507  cnt = 0;
1508  for ( int i=0; i<nbus; i++) {
1509  if ( k[i] == 1 && cnt < SC_records_val) {
1510  start[0] = cnt;
1511 
1512  status = nc_put_vara_uchar( groupid, varid, start, count, &adsolution[i]);
1513  check_err(status,__LINE__,__FILE__);
1514 
1515  cnt++;
1516  }
1517  }
1518 
1519  // Write bus_critical_tlm
1520  if ( this->platform == "JPSS-2")
1521  status = nc_inq_varid( groupid, "ADCS_1Hz_tlm", &varid);
1522  else
1523  status = nc_inq_varid( groupid, "bus_critical_tlm", &varid);
1524  check_err(status,__LINE__,__FILE__);
1525 
1526  cnt = 0;
1527  for ( int i=0; i<nbus; i++) {
1528  if ( k[i] == 1 && cnt < SC_records_val) {
1529  start[0] = cnt;
1530  count[1] = this->bpktsize-14;
1531  status = nc_put_vara( groupid, varid, start, count, &buspkts[i][14]);
1532  check_err(status,__LINE__,__FILE__);
1533 
1534  cnt++;
1535  }
1536  }
1537 
1538  delete[] k;
1539 
1540 
1541  // GPS
1542  if ( this->platform == "JPSS-2") {
1543  // Identify gps times within granule range +/-10 seconds
1544  k = new uint8_t[ngps];
1545  nk=0;
1546  first=-1;
1547  prevtime = 0;
1548  for ( int i=0; i<ngps; i++) {
1549  double gtm = gpstime[i] + (jds - jdg)*86400;
1550 
1551  if ( gtm > (ltime-10) && gtm < (mtime+10)) {
1552  if ( (gtm - prevtime) < 0.01) {
1553  cout << "Removing short gps period record: "
1554  << i << " " << fixed << setprecision(4)
1555  << gtm << " " << prevtime << endl;
1556  prevtime = gtm;
1557  k[i] = 0;
1558  continue;
1559  }
1560  k[i] = 1;
1561  nk++;
1562  if ( first == -1) first = i;
1563 
1564  if ( nk > SC_records_val) {
1565  nk = SC_records_val;
1566  break;
1567  }
1568 
1569  } else {
1570  k[i] = 0;
1571  }
1572  prevtime = gtm;
1573  }
1574  cout << nk << " gps records in time range" << endl;
1575 
1576  // Write gps times
1577  cout << "Writing gps data" << endl;
1578  status = nc_inq_varid( groupid, "GPS_time", &varid);
1579  check_err(status,__LINE__,__FILE__);
1580 
1581  cnt = 0;
1582  for ( int i=0; i<ngps; i++) {
1583  if ( k[i] == 1 && cnt < SC_records_val) {
1584  start[0] = cnt;
1585 
1586  tai = yds2tai93( iyrad16, idyad16, gpstime[i]);
1587 
1588  // Write TAI93 time
1589  status = nc_put_vara_double( groupid, varid, start, count, &tai);
1590  if (status != NC_NOERR) {
1591  check_err(status,__LINE__,__FILE__);
1592  }
1593 
1594  cnt++;
1595  }
1596  }
1597 
1598  // Write gps tlm
1599  status = nc_inq_varid( groupid, "GPS_tlm", &varid);
1600  check_err(status,__LINE__,__FILE__);
1601 
1602  cnt = 0;
1603  for ( int i=0; i<ngps; i++) {
1604  if ( k[i] == 1 && cnt < SC_records_val) {
1605  start[0] = cnt;
1606  count[1] = this->gpktsize-14;
1607  status = nc_put_vara( groupid, varid, start, count, &gpspkts[i][14]);
1608  check_err(status,__LINE__,__FILE__);
1609 
1610  cnt++;
1611  }
1612  }
1613  } // if ( this->platform == "JPSS-2")
1614 
1615  return 0;
1616 }
1617 
1618 
1619 int l1aFile::write_granule_metadata( int32_t iyear, int32_t iday,
1620  int32_t ltime, int32_t mtime,
1621  int32_t orbit,
1622  const char* l1a_name,
1623  char *sdir, char *edir,
1624  uint8_t *p1,
1625  int32_t isc, uint8_t *mode,
1626  int argc, char *argv[],
1627  const char* doi) {
1628 
1629  int status;
1630  char buf[2048];
1631 
1632  int16_t year, doy;
1633 
1634  stringstream timestr, datestr;
1635 
1636  status = nc_put_att_int(ncid, NC_GLOBAL, "orbit_number", NC_INT,
1637  1, &orbit);
1638  check_err(status,__LINE__,__FILE__);
1639 
1640  // Write history attribute
1641  strcpy( buf, basename(argv[0]));
1642  for (int i=1; i<argc; i++) {
1643  strcat( buf, " ");
1644  strcat( buf, argv[i]);
1645  }
1646  status = nc_put_att_text(ncid, NC_GLOBAL, "history", strlen(buf), buf);
1647  check_err(status,__LINE__,__FILE__);
1648 
1649  // Write format version and instrument number attributes
1650  uint8_t fmtver = p1[28];
1651  uint8_t insnum = p1[29];
1652 
1653  status = nc_put_att_uchar(ncid, NC_GLOBAL, "format_version", NC_BYTE,
1654  1, &fmtver);
1655  check_err(status,__LINE__,__FILE__);
1656 
1657  status = nc_put_att_uchar(ncid, NC_GLOBAL, "instrument_number", NC_BYTE,
1658  1, &insnum);
1659  check_err(status,__LINE__,__FILE__);
1660 
1661  // time_coverage_start
1662  year = iyear;
1663  doy = iday;
1664 
1665  double dsec = (double) ltime;
1666  double myUnixTime= yds2unix(year, doy, dsec);
1667  strcpy( buf, unix2isodate(myUnixTime, 'G'));
1668 
1669  status = nc_put_att_text(ncid, NC_GLOBAL, "time_coverage_start",
1670  strlen(buf), buf);
1671  check_err(status,__LINE__,__FILE__);
1672 
1673 
1674  // time_coverage_end
1675  dsec = (double) mtime;
1676 
1677  if ( dsec >= 86400) {
1678  dsec -= 86400.0;
1679  doy = doy + 1;
1680 
1681  if (isleap(iyear)) {
1682  if (doy == 367) {
1683  year++;
1684  doy = 1;
1685  }
1686  } else {
1687  if (doy == 366) {
1688  year++;
1689  doy = 1;
1690  }
1691  }
1692  }
1693 
1694  myUnixTime= yds2unix(year, doy, dsec);
1695  strcpy( buf, unix2isodate(myUnixTime, 'G'));
1696 
1697  status = nc_put_att_text(ncid, NC_GLOBAL, "time_coverage_end",
1698  strlen(buf), buf);
1699  check_err(status,__LINE__,__FILE__);
1700 
1701  strcpy( buf, unix2isodate(now(), 'G'));
1702  status = nc_put_att_text(ncid, NC_GLOBAL, "date_created", strlen(buf), buf);
1703  check_err(status,__LINE__,__FILE__);
1704 
1705  strcpy( buf, sdir);
1706  status = nc_put_att_text(ncid, NC_GLOBAL, "startDirection", strlen(buf), buf);
1707  check_err(status,__LINE__,__FILE__);
1708 
1709  strcpy( buf, edir);
1710  status = nc_put_att_text(ncid, NC_GLOBAL, "endDirection", strlen(buf), buf);
1711  check_err(status,__LINE__,__FILE__);
1712 
1713 
1714  // Determine sensor mode for granule and write
1715  int32_t nday=0, nngt=0;
1716  for (int i=0; i<isc; i++) {
1717  if ( mode[i] == 4) nday++;
1718  if ( mode[i] == 5) nngt++;
1719  }
1720  if ( nday == isc) strcpy( buf, "Day");
1721  else if ( nngt == isc) strcpy( buf, "Night");
1722  else if ( (nday + nngt) == isc) strcpy( buf, "Mixed");
1723  else strcpy( buf, "Other");
1724  status = nc_put_att_text(ncid, NC_GLOBAL, "day_night_flag", strlen(buf), buf);
1725  check_err(status,__LINE__,__FILE__);
1726 
1727 
1728  // Write number of scans
1729  status = nc_put_att_int(ncid, NC_GLOBAL, "number_of_filled_scans",
1730  NC_INT, 1, &isc);
1731  check_err(status,__LINE__,__FILE__);
1732 
1733  // add DOI if given
1734  if(doi && (strlen(doi) > 0)) {
1735  status = nc_put_att_text(ncid, NC_GLOBAL, "identifier_product_doi_authority",
1736  strlen("http://dx.doi.org"), "http://dx.doi.org");
1737  check_err(status,__LINE__,__FILE__);
1738 
1739  status = nc_put_att_text(ncid, NC_GLOBAL, "identifier_product_doi",
1740  strlen(doi), doi);
1741  check_err(status,__LINE__,__FILE__);
1742  }
1743 
1744  return 0;
1745 }
1746 
1747 int l1aFile::openl1(char* l1_filename) {
1748 
1749  int status;
1750  size_t t_len; /* attribute lengths */
1751  char dimname[256];
1752 
1753  status = nc_open(l1_filename, NC_NOWRITE, &this->ncid);
1754  check_err(status, __LINE__, __FILE__);
1755  status = nc_inq_grps(ncid, &ngrps, gid);
1756  check_err(status, __LINE__, __FILE__);
1757 
1758 
1759  /* find out how much space is needed for attribute values */
1760  status = nc_inq_attlen(ncid, NC_GLOBAL, "platform", &t_len);
1761  check_err(status, __LINE__, __FILE__);
1762 
1763  char *platform;
1764  platform = (char *) malloc(t_len + 1);
1765 
1766  status = nc_get_att_text(ncid, NC_GLOBAL, "platform", platform);
1767  check_err(status, __LINE__, __FILE__);
1768  platform[t_len] = '\0';
1769  this->platform.assign(platform);
1770  free(platform);
1771 
1772  status = nc_inq_ndims(ncid, &ndims);
1773  check_err(status, __LINE__, __FILE__);
1774  for (int i = 0; i < ndims; i++) {
1775  this->dimid[i] = i;
1776  nc_inq_dimname(ncid, i, dimname);
1777  if (strcmp(dimname, "SC_records") == 0) {
1778  size_t dimlen;
1779  nc_inq_dimlen(ncid, i, &dimlen);
1780  SC_records_val = dimlen;
1781  }
1782  }
1783 
1784  return 0;
1785 }
1786 
1787 
1788 int l1aFile::copyl1( char *ifilename, char *ofilename, l1aFile* l1_ofile,
1789  int32_t sscan, int32_t escan,
1790  int32_t spixl, int32_t epixl) {
1791 
1792  int status;
1793 
1794  ifstream viirs_l1a_data_structure;
1795  string line;
1796  string dataStructureFile;
1797 
1798  if ( this->platform == "JPSS-1")
1799  dataStructureFile.assign("$OCDATAROOT/viirs/j1/VIIRS_Level-1A_Data_Structure_J1.cdl");
1800  else
1801  dataStructureFile.assign("$OCDATAROOT/viirs/npp/VIIRS_Level-1A_Data_Structure.cdl");
1802  expandEnvVar( &dataStructureFile);
1803 
1804  viirs_l1a_data_structure.open( dataStructureFile.c_str(), ifstream::in);
1805  if ( viirs_l1a_data_structure.fail() == true) {
1806  cout << "\"" << dataStructureFile.c_str() << "\" not found" << endl;
1807  exit(1);
1808  }
1809 
1810  size_t start[4], count[4], ofile_start[4]={0,0,0,0};
1811  int varid;
1812  double scan_start_time=FP_NAN, scan_end_time=FP_NAN;
1813 
1814  // Find "dimensions" section of CDL file
1815  while(1) {
1816  getline( viirs_l1a_data_structure, line);
1817  size_t pos = line.find("dimensions:");
1818  if ( pos == 0) break;
1819  }
1820 
1821  while(1) {
1822  getline( viirs_l1a_data_structure, line);
1823  size_t pos = line.find(" = ");
1824  if ( pos == string::npos) break;
1825 
1826  } // while loop
1827 
1828  ngrps = 0;
1829  // Loop through groups
1830  while(1) {
1831  getline( viirs_l1a_data_structure, line);
1832 
1833  // Check if end of CDL file
1834  // If so then close CDL file and break
1835  if (line.substr(0,1).compare("}") == 0) {
1836  viirs_l1a_data_structure.close();
1837  break;
1838  }
1839 
1840  // Check for beginning of new group
1841  size_t pos = line.find("group:");
1842 
1843  // If found then create new group and variables
1844  if ( pos == 0) {
1845 
1846  int numDims=0;
1847  int varDims[NC_MAX_DIMS];
1848  size_t dimSize[NC_MAX_DIMS];
1849  char dimName[NC_MAX_NAME+1];
1850  string sname;
1851 
1852  char *buffer = NULL;
1853 
1854  // Loop through datasets in group
1855  getline( viirs_l1a_data_structure, line); // skip "variables:"
1856  while(1) {
1857  getline( viirs_l1a_data_structure, line);
1858 
1859  if (line.length() == 0) continue;
1860  if (line.substr(0,1).compare("\r") == 0) continue;
1861  if (line.substr(0,1).compare("\n") == 0) continue;
1862 
1863  size_t found = line.find("DNB");
1864  if (found != string::npos) {
1865  continue;
1866  }
1867 
1868  size_t pos = line.find(":");
1869 
1870  // No ":" found, new dataset or empty line or end-of-group
1871  if ( pos == string::npos) {
1872 
1873  // Note: scan_start_time & scan_end_time are for the extract
1874 
1875  if ( numDims > 0) {
1876  status = nc_get_vara( gid[ngrps], varid,
1877  start, count, (void *) buffer);
1878  check_err(status,__LINE__,__FILE__);
1879 
1880  if ( sname.compare( "scan_start_time") == 0) {
1881  memcpy( &scan_start_time, buffer, 8);
1882  cout << scan_start_time << endl;
1883  scan_end_time = scan_start_time + l1_ofile->SC_records_val-20;
1884  cout << scan_end_time << endl;
1885  }
1886 
1887  int ofile_varid;
1888  status = nc_inq_varid( l1_ofile->gid[ngrps],
1889  sname.c_str(), &ofile_varid);
1890  check_err(status,__LINE__,__FILE__);
1891 
1892  status = nc_put_vara( l1_ofile->gid[ngrps], ofile_varid,
1893  ofile_start, count, (void *) buffer);
1894  check_err(status,__LINE__,__FILE__);
1895 
1896  free (buffer);
1897  buffer = NULL;
1898  }
1899 
1900  if (line.substr(0,10).compare("} // group") == 0) break;
1901 
1902  // Parse short name (sname)
1903  pos = line.find("(");
1904  size_t posSname = line.substr(0, pos).rfind(" ");
1905  sname.assign(line.substr(posSname+1, pos-posSname-1));
1906  cout << "Extracting: " << sname.c_str() << endl;
1907 
1908  // Parse variable dimension info
1909  this->parseDims( line.substr(pos+1, string::npos),
1910  &numDims, varDims);
1911 
1912  size_t bufcnt = 1;
1913  for (int i=0; i<numDims; i++) {
1914  nc_inq_dim( ncid, varDims[i], dimName, &dimSize[i]);
1915  if ( strcmp(dimName, "number_of_scans") == 0) {
1916  start[i] = sscan;
1917  count[i] = escan - sscan + 1;
1918  } else if ( strcmp(dimName, "SC_records") == 0) {
1919  if ( strcmp(sname.c_str(), "att_time") == 0) {
1920  double *time = new double[dimSize[i]];
1921  status = nc_inq_varid( gid[ngrps], sname.c_str(), &varid);
1922  check_err(status,__LINE__,__FILE__);
1923 
1924  status = nc_get_var_double( gid[ngrps], varid, time);
1925  check_err(status,__LINE__,__FILE__);
1926 
1927  // Note: scan_start_time & scan_end_time are for the extract
1928 
1929  bool found = false;
1930  count[i] = 0;
1931  for (uint32_t j=0; j<dimSize[i]; j++) {
1932  if (time[j] > scan_start_time-10 &&
1933  time[j] < scan_end_time+10) {
1934  count[i]++;
1935  if (!found) start[i] = j;
1936  found = true;
1937  }
1938  }
1939  if(!found) {
1940  printf("-E- %s %d: could not find starting record for att_time.\n",
1941  __FILE__, __LINE__);
1942  exit(1);
1943  }
1944 
1945  if (count[i] == l1_ofile->SC_records_val+1)
1946  count[i] = l1_ofile->SC_records_val;
1947 
1948  if (count[i] > l1_ofile->SC_records_val) {
1949  cout << "Insufficient allocation for extracted SC_records dimension" << endl;
1950  cout <<
1951  "Allocated: " << l1_ofile->SC_records_val <<
1952  " Required: " << count[i] << endl;
1953  // exit(1);
1954  cout << "Changing 'Required' to 'Allocated'" << endl;
1955  count[i] = l1_ofile->SC_records_val;
1956  }
1957  delete(time);
1958  }
1959  } else if ( strcmp(dimName, "Mband_pixels") == 0) {
1960  // Mband_pixels = 3200
1961  start[i] = spixl;
1962  count[i] = epixl - spixl + 1;
1963  } else if ( strcmp(dimName, "Iband_pixels") == 0) {
1964  // Iband_pixels = 6400
1965  start[i] = 2*spixl;
1966  count[i] = 2*(epixl - spixl + 1);
1967  } else if ( strcmp(dimName, "Mband_samples") == 0) {
1968  /*
1969  Mband_samples = 6304 ;
1970 
1971  pixel_offset range sample_offset
1972 
1973  0 - 639 pixel_offset
1974  640 - 1007 640 + 2*(pixel_offset - 640)
1975  1008 - 2191 1376 + 3*(pixel_offset - 1008)
1976  2192 - 2559 4928 + 2*(pixel_offset - 2192)
1977  2560 - 3199 5664 + (pixel_offset - 2560)
1978 
1979 
1980  */
1981  if ( spixl < 639) {
1982  start[i] = spixl;
1983  } else if ( spixl > 639 && spixl <= 1007) {
1984  start[i] = 640 + 2*(spixl - 640);
1985  } else if ( spixl > 1007 && spixl <= 2191) {
1986  start[i] = 1376 + 3*(spixl - 1008);
1987  } else if ( spixl > 2191 && spixl <= 2559) {
1988  start[i] = 4928 + 2*(spixl - 2192);
1989  } else if ( spixl > 2559) {
1990  start[i] = 5664 + (spixl - 2560);
1991  }
1992 
1993  if ( epixl <= 639) {
1994  count[i] = epixl;
1995  } else if ( epixl > 639 && epixl <= 1007) {
1996  count[i] = 641 + 2*(epixl - 640);
1997  } else if ( epixl > 1007 && epixl <= 2191) {
1998  count[i] = 1378 + 3*(epixl - 1008);
1999  } else if ( epixl > 2191 && epixl <= 2559) {
2000  count[i] = 4929 + 2*(epixl - 2192);
2001  } else if ( epixl > 2559) {
2002  count[i] = 5664 + (epixl - 2560);
2003  }
2004  count[i] = count[i] - start[i] + 1;
2005  } else {
2006  start[i] = 0;
2007  count[i] = dimSize[i];
2008  }
2009  bufcnt *= count[i];
2010  // cout << line.c_str() << " " << i << " " << dimName
2011  // << " " << dimSize[i] << endl;
2012  }
2013 
2014  status = nc_inq_varid( gid[ngrps], sname.c_str(), &varid);
2015  check_err(status,__LINE__,__FILE__);
2016 
2017  nc_type dtype;
2018  size_t typesz;
2019  status = nc_inq_vartype( gid[ngrps], varid, &dtype);
2020  check_err(status,__LINE__,__FILE__);
2021 
2022  status = nc_inq_type( gid[ngrps], dtype, NULL, &typesz);
2023  check_err(status,__LINE__,__FILE__);
2024 
2025  buffer = (char *) calloc( bufcnt, typesz);
2026  } // if ( pos == string::npos)
2027  } // datasets in group loop
2028 
2029  ngrps++;
2030 
2031  } // New Group loop
2032  } // Main Group loop
2033 
2034  int ngatts;
2035  nc_type type;
2036  size_t attlen, typesz;
2037 
2038  char name[NC_MAX_NAME], databuf[1024];
2039 
2040  status = nc_inq_natts(ncid, &ngatts);
2041  check_err(status,__LINE__,__FILE__);
2042 
2043  stringstream history;
2044  history << "l1aextract_viirs " << basename(ifilename) << " "
2045  << (spixl+1) << " " << (epixl+1) << " "
2046  << (sscan+1) << " " << (escan+1) << " "
2047  << basename(ofilename);
2048 
2049  for (int i=0; i<ngatts; i++) {
2050  status = nc_inq_attname( ncid, NC_GLOBAL, i, name);
2051  status = nc_inq_att( ncid, NC_GLOBAL, name, &type, &attlen);
2052  status = nc_inq_type( ncid, type, NULL, &typesz);
2053  status = nc_get_att( ncid, NC_GLOBAL, name, (void *) databuf);
2054 
2055  if ( strcmp(name, "product_name") == 0) {
2056  strcpy(databuf, basename(ofilename));
2057  attlen = strlen(databuf);
2058  }
2059 
2060  if ( strcmp(name, "history") == 0) {
2061  strcpy(databuf, history.str().c_str());
2062  attlen = strlen(databuf);
2063  }
2064 
2065  if ( strcmp(name, "time_coverage_start") == 0) {
2067  uint32_t int_scan_start_time =
2068  (uint32_t) (scan_start_time - nleap + 0.5);
2069  double sec = (double) (int_scan_start_time % 86400);
2070 
2071  int16_t iyr, imn, idy;
2072  sscanf ( databuf,"%hu-%hu-%hu%*s", &iyr, &imn, &idy);
2073 
2074  double myUnixTime= ymds2unix( iyr, imn, idy, sec);
2075  strcpy( databuf, unix2isodate(myUnixTime, 'G'));
2076 
2077  }
2078 
2079  if ( strcmp(name, "time_coverage_end") == 0) {
2080  int nleap = leapseconds_since_1993( scan_end_time);
2081  uint32_t int_scan_end_time =
2082  (uint32_t) (scan_end_time - nleap + 0.5);
2083  double sec = (double) (int_scan_end_time % 86400);
2084 
2085  int16_t iyr, imn, idy;
2086  sscanf ( databuf,"%hu-%hu-%hu%*s", &iyr, &imn, &idy);
2087 
2088  double myUnixTime= ymds2unix( iyr, imn, idy, sec);
2089  strcpy( databuf, unix2isodate(myUnixTime, 'G'));
2090 
2091  }
2092 
2093  if ( strcmp(name, "date_created") == 0) {
2094  strcpy( databuf, unix2isodate(now(), 'G'));
2095  }
2096 
2097  if ( strcmp(name, "number_of_filled_scans") == 0) {
2098  int32_t filled_scans = escan - sscan + 1;
2099  memcpy( databuf, &filled_scans, sizeof(int32_t));
2100  }
2101 
2102  status = nc_put_att( l1_ofile->ncid, NC_GLOBAL,
2103  name, type, attlen, databuf);
2104  if (status != NC_NOERR)
2105  {
2106  printf("-E - nc_put_att failed for ncid: %i\n",ncid);
2107  }
2108 
2109  }
2110 
2111  if (spixl != 0 || epixl != 3199) {
2112  int i;
2113  i = spixl + 1;
2114  status = nc_put_att_int( l1_ofile->ncid, NC_GLOBAL, "extract_pixel_start",
2115  NC_INT, 1, &i);
2116  i = epixl + 1;
2117  status = nc_put_att_int( l1_ofile->ncid, NC_GLOBAL, "extract_pixel_stop",
2118  NC_INT, 1, &i);
2119  }
2120 
2121 
2122  return 0;
2123 }
2124 
2125 
2126 int l1aFile::close() {
2127 
2128  int status = nc_close(ncid);
2129 
2130  if (status != NC_NOERR)
2131  {
2132  printf("-E - nc_close failed for ncid: %i\n",ncid);
2133  }
2134  return 0;
2135 }
2136 
2137 int createNCDF( int ncid, const char *sname, const char *lname,
2138  const char *standard_name, const char *units,
2139  void *fill_value,
2140  const char *flag_values, const char *flag_meanings,
2141  double low, double high, int nt,
2142  int rank, int *dimids) {
2143 
2144  int32_t varid;
2145  int status;
2146  size_t dimlength;
2147  size_t chunksize[3];
2148 
2149  /* Create the NCDF dataset */
2150  status = nc_def_var(ncid, sname, nt, rank, dimids, &varid);
2151  if( status != NC_NOERR) {
2152  printf("-E- %s %d: %s for %s\n",
2153  __FILE__, __LINE__, nc_strerror(status), sname);
2154  exit(1);
2155  }
2156 
2157  // Set fill value
2158  double fill_value_dbl;
2159  memcpy( &fill_value_dbl, fill_value, sizeof(double));
2160 
2161  int8_t i8;
2162  uint8_t ui8;
2163  int16_t i16;
2164  int32_t i32;
2165  float f32;
2166 
2167  // if ( (low < high) && (low != fill_value_dbl)) {
2168  if ( low != fill_value_dbl) {
2169  if ( nt == NC_BYTE) {
2170  i8 = fill_value_dbl;
2171  status = nc_def_var_fill( ncid, varid, 0, (void *) &i8);
2172  } else if ( nt == NC_UBYTE) {
2173  ui8 = fill_value_dbl;
2174  status = nc_def_var_fill( ncid, varid, 0, (void *) &ui8);
2175  } else if ( nt == NC_SHORT) {
2176  i16 = fill_value_dbl;
2177  status = nc_def_var_fill( ncid, varid, 0, (void *) &i16);
2178  } else if ( nt == NC_INT) {
2179  i32 = fill_value_dbl;
2180  status = nc_def_var_fill( ncid, varid, 0, (void *) &i32);
2181  } else if ( nt == NC_FLOAT) {
2182  f32 = fill_value_dbl;
2183  status = nc_def_var_fill( ncid, varid, 0, (void *) &f32);
2184  } else {
2185  status = nc_def_var_fill( ncid, varid, 0, (void *) &fill_value_dbl);
2186  }
2187  check_err(status,__LINE__,__FILE__);
2188  }
2189 
2190  /* vary chunck size based on dimensions */
2191  int do_deflate = 0;
2192  if ( rank == 3 && (strncmp(sname, "EV_", 3) == 0)) {
2193  status = nc_inq_dimlen(ncid, dimids[2], &dimlength);
2194  chunksize[0] = 1;
2195  chunksize[1] = 16;
2196  chunksize[2] = dimlength/10;
2197  do_deflate = 1;
2198  }
2199 
2200  /* Set compression */
2201  if ( do_deflate) {
2202  /* First set chunking */
2203  status = nc_def_var_chunking(ncid, varid, NC_CHUNKED, chunksize);
2204  if (status != NC_NOERR) {
2205  printf("-E- %s %d: %s for %s\n", __FILE__, __LINE__,
2206  nc_strerror(status), sname);
2207  exit(1);
2208  }
2209 
2210  /* Now we can set compression */
2211  // status = nc_def_var_deflate(ncid, varid, NC_NOSHUFFLE, 1, 5);
2212  status = nc_def_var_deflate(ncid, varid, NC_SHUFFLE, 1, 5);
2213  if (status != NC_NOERR) {
2214  printf("-E- %s %d: %s for %s\n", __FILE__, __LINE__,
2215  nc_strerror(status), sname);
2216  exit(1);
2217  }
2218  }
2219 
2220 
2221  /* Add a "long_name" attribute */
2222  status = nc_put_att_text(ncid, varid, "long_name", strlen(lname), lname);
2223  if( status != NC_NOERR) {
2224  printf("-E- %s %d: %s for %s\n",
2225  __FILE__, __LINE__, nc_strerror(status), "long_name");
2226  exit(1);
2227  }
2228 
2229  /* Add a "flag_values" attribute if specified*/
2230  // Parse string and save as signed bytes
2231  if ( strcmp( flag_values, "") != 0) {
2232 
2233  size_t curPos=0;
2234 
2235  string fv;
2236  fv.assign( flag_values);
2237  size_t pos = fv.find("=", curPos);
2238  fv = fv.substr(pos+1);
2239 
2240  size_t semicln = fv.find(";");
2241  pos = 0;
2242 
2243  int8_t vec[1024];
2244  int n = 0;
2245  while(pos != semicln) {
2246  pos = fv.find(",", curPos);
2247  if ( pos == string::npos)
2248  pos = semicln;
2249 
2250  string flag_value;
2251  istringstream iss(fv.substr(curPos, pos-curPos));
2252  iss >> skipws >> flag_value;
2253  vec[n++] = atoi( flag_value.c_str());
2254  curPos = pos + 1;
2255  }
2256 
2257  status = nc_put_att_schar(ncid, varid, "flag_values", NC_BYTE, n, vec);
2258  if( status != NC_NOERR) {
2259  printf("-E- %s %d: %s for %s\n",
2260  __FILE__, __LINE__, nc_strerror(status), "flag_values");
2261  exit(1);
2262  }
2263  }
2264 
2265  /* Add a "flag_meanings" attribute if specified*/
2266  if ( strcmp( flag_meanings, "") != 0) {
2267  status = nc_put_att_text(ncid, varid, "flag_meanings",
2268  strlen(flag_meanings), flag_meanings);
2269  if( status != NC_NOERR) {
2270  printf("-E- %s %d: %s for %s\n",
2271  __FILE__, __LINE__, nc_strerror(status), "flag_meanings");
2272  exit(1);
2273  }
2274  }
2275 
2276  /* Add "valid_min/max" attributes if specified */
2277  if (low < high) {
2278  switch(nt) { /* Use the appropriate number type */
2279  case NC_BYTE:
2280  {
2281  uint8_t vr[2];
2282  vr[0] = (uint8_t)low;
2283  vr[1] = (uint8_t)high;
2284  status = nc_put_att_uchar(ncid, varid,"valid_min",NC_BYTE,1,&vr[0]);
2285  if( status != NC_NOERR) {
2286  printf("-E- %s %d: %s for %s\n",
2287  __FILE__, __LINE__, nc_strerror(status), "valid_min");
2288  exit(1);
2289  }
2290  status = nc_put_att_uchar(ncid, varid,"valid_max",NC_BYTE,1,&vr[1]);
2291  if( status != NC_NOERR) {
2292  printf("-E- %s %d: %s for %s\n",
2293  __FILE__, __LINE__, nc_strerror(status), "valid_max");
2294  exit(1);
2295  }
2296  }
2297  break;
2298  case NC_UBYTE:
2299  {
2300  uint8_t vr[2];
2301  vr[0] = (uint8_t)low;
2302  vr[1] = (uint8_t)high;
2303  status = nc_put_att_uchar(ncid, varid,"valid_min",NC_UBYTE,1,&vr[0]);
2304  if( status != NC_NOERR) {
2305  printf("-E- %s %d: %s for %s\n",
2306  __FILE__, __LINE__, nc_strerror(status), "valid_min");
2307  exit(1);
2308  }
2309  status = nc_put_att_uchar(ncid, varid,"valid_max",NC_UBYTE,1,&vr[1]);
2310  if( status != NC_NOERR) {
2311  printf("-E- %s %d: %s for %s\n",
2312  __FILE__, __LINE__, nc_strerror(status), "valid_max");
2313  exit(1);
2314  }
2315  }
2316  break;
2317  case NC_SHORT:
2318  {
2319  int16_t vr[2];
2320  vr[0] = (int16_t)low;
2321  vr[1] = (int16_t)high;
2322  status = nc_put_att_short(ncid, varid,"valid_min",NC_SHORT,1,&vr[0]);
2323  if( status != NC_NOERR) {
2324  printf("-E- %s %d: %s for %s\n",
2325  __FILE__, __LINE__, nc_strerror(status), "valid_min");
2326  exit(1);
2327  }
2328  status = nc_put_att_short(ncid, varid,"valid_max",NC_SHORT,1,&vr[1]);
2329  if( status != NC_NOERR) {
2330  printf("-E- %s %d: %s for %s\n",
2331  __FILE__, __LINE__, nc_strerror(status), "valid_max");
2332  exit(1);
2333  }
2334  }
2335  break;
2336  case NC_USHORT:
2337  {
2338  uint16_t vr[2];
2339  vr[0] = (uint16_t)low;
2340  vr[1] = (uint16_t)high;
2341  status = nc_put_att_ushort(ncid, varid,"valid_min",NC_USHORT,1,&vr[0]);
2342  if( status != NC_NOERR) {
2343  printf("-E- %s %d: %s for %s\n",
2344  __FILE__, __LINE__, nc_strerror(status), "valid_min");
2345  exit(1);
2346  }
2347  status = nc_put_att_ushort(ncid, varid,"valid_max",NC_USHORT,1,&vr[1]);
2348  if( status != NC_NOERR) {
2349  printf("-E- %s %d: %s for %s\n",
2350  __FILE__, __LINE__, nc_strerror(status), "valid_max");
2351  exit(1);
2352  }
2353  }
2354  break;
2355  case NC_INT:
2356  {
2357  int32_t vr[2];
2358  vr[0] = (int32_t)low;
2359  vr[1] = (int32_t)high;
2360  status = nc_put_att_int(ncid, varid,"valid_min",NC_INT,1,&vr[0]);
2361  if( status != NC_NOERR) {
2362  printf("-E- %s %d: %s for %s\n",
2363  __FILE__, __LINE__, nc_strerror(status), "valid_min");
2364  exit(1);
2365  }
2366  status = nc_put_att_int(ncid, varid,"valid_max",NC_INT,1,&vr[1]);
2367  if( status != NC_NOERR) {
2368  printf("-E- %s %d: %s for %s\n",
2369  __FILE__, __LINE__, nc_strerror(status), "valid_max");
2370  exit(1);
2371  }
2372  }
2373  break;
2374  case NC_FLOAT:
2375  {
2376  float vr[2];
2377  vr[0] = (float)low;
2378  vr[1] = (float)high;
2379  status = nc_put_att_float(ncid, varid,"valid_min",NC_FLOAT,1,&vr[0]);
2380  if( status != NC_NOERR) {
2381  printf("-E- %s %d: %s for %s\n",
2382  __FILE__, __LINE__, nc_strerror(status), "valid_min");
2383  exit(1);
2384  }
2385  status = nc_put_att_float(ncid, varid,"valid_max",NC_FLOAT,1,&vr[1]);
2386  if( status != NC_NOERR) {
2387  printf("-E- %s %d: %s for %s\n",
2388  __FILE__, __LINE__, nc_strerror(status), "valid_max");
2389  exit(1);
2390  }
2391  }
2392  break;
2393  case NC_DOUBLE:
2394  {
2395  double vr[2];
2396  vr[0] = low;
2397  vr[1] = high;
2398  status = nc_put_att_double(ncid, varid,"valid_min",NC_DOUBLE,1,&vr[0]);
2399  if( status != NC_NOERR) {
2400  printf("-E- %s %d: %s for %s\n",
2401  __FILE__, __LINE__, nc_strerror(status), "valid_min");
2402  exit(1);
2403  }
2404  status = nc_put_att_double(ncid, varid,"valid_max",NC_DOUBLE,1,&vr[1]);
2405  if( status != NC_NOERR) {
2406  printf("-E- %s %d: %s for %s\n",
2407  __FILE__, __LINE__, nc_strerror(status), "valid_max");
2408  exit(1);
2409  }
2410  }
2411  break;
2412  default:
2413  fprintf(stderr,"-E- %s line %d: ",__FILE__,__LINE__);
2414  fprintf(stderr,"Got unsupported number type (%d) ",nt);
2415  fprintf(stderr,"while trying to create NCDF variable, \"%s\", ",sname);
2416  return(PROGRAMMER_BOOBOO);
2417  }
2418  }
2419 
2420  /* Add a "units" attribute if one is specified */
2421  if(units != NULL && *units != 0) {
2422  status = nc_put_att_text(ncid, varid, "units", strlen(units), units);
2423  if( status != NC_NOERR) {
2424  printf("-E- %s %d: %s for %s\n",
2425  __FILE__, __LINE__, nc_strerror(status), "units");
2426  exit(1);
2427  }
2428  }
2429 
2430  /* Add a "standard_name" attribute if one is specified */
2431  if(standard_name != NULL && *standard_name != 0) {
2432  status = nc_put_att_text(ncid, varid, "standard_name",
2433  strlen(standard_name), standard_name);
2434  if( status != NC_NOERR) {
2435  printf("-E- %s %d: %s for %s\n",
2436  __FILE__, __LINE__, nc_strerror(status), "standard_name");
2437  exit(1);
2438  }
2439  }
2440 
2441  return 0;
2442 }
2443 
2444 
2445 int jgleap( int32_t jday, int32_t *leap) {
2446 
2447  // NO LONGER USED
2448 
2449  // Determines leap seconds since GPS epoch (6 January 1980)
2450  // for a specified Astronomical Julian Day
2451 
2452  // Updated for 2015 JUL 1 leapsec 02/11/15 JMG
2453  // Julian days of leap second epochs
2454  int32_t jdleap[17] = {2444787, 2445152, 2445517, 2446248,
2455  2447162, 2447893, 2448258, 2448805,
2456  2449170, 2449535, 2450084, 2450631,
2457  2451180, 2453737, 2454833, 2456110,
2458  2457205};
2459 
2460  int32_t cnt=0;
2461  for ( int i=0; i<17; i++) {
2462  if ( jday >= jdleap[i]) cnt++;
2463  }
2464 
2465  *leap = cnt;
2466 
2467  return 0;
2468 }
int32_t imn
Definition: atrem_corl1.h:161
int gid[10]
int16 eday
Definition: l1_czcs_hdf.c:17
int j
Definition: decode_rs.h:73
int status
Definition: l1_czcs_hdf.c:32
double yds2unix(int16_t year, int16_t day, double secs)
Definition: yds2unix.c:7
void check_err(const int stat, const int line, const char *file)
Definition: nc4utils.c:35
int createl1(char *l1_filename, uint32_t nSC, uint32_t imgWidth, uint32_t imgHeight, uint32_t fndWidth, uint32_t fndHeight)
*********************************************HISTORY FILE for MOD_PR02AQUA **Version ****Point of no algorithm change is made in this so the and when the blackbody temperature is above a threshold Since the LWIR FPA temperature oscillates on orbit
Definition: HISTORY.txt:106
#define NULL
Definition: decode_rs.h:63
int bpktsize
Definition: l1agen_oci.h:54
int createNCDF(int ncid, 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, int rank, int *dimids)
Definition: l1aFile.cpp:2137
int write_diary(int32_t iyear, int32_t iday, int32_t ltime, int32_t mtime, int32_t iyrsc, int32_t idysc, int32_t nscd, double *otime, float(*orb)[6], double *atime, float(*quat)[4], char *sdir, char *edir)
Definition: l1aFile.cpp:1090
double yds2tai93(int16_t iyr, int16_t idy, double sec)
Definition: yds2tai.c:4
README for MOD_PR02AQUA(AQUA) Version to set to For disabling creating and output data sets when in night mode
Definition: README.txt:96
float32 * pos
Definition: l1_czcs_hdf.c:35
#define SWAP_4(x)
Definition: common.h:18
int16 eyear
Definition: l1_czcs_hdf.c:17
int syear
Definition: l1_czcs_hdf.c:15
int32_t jday(int16_t i, int16_t j, int16_t k)
Definition: jday.c:4
int ccsds_to_yds(uint8_t *cctime, int32_t *iyear, int32_t *iday, double *sec)
Definition: ccsds_to_yds.c:5
def mtime(the_file)
Definition: ProcUtils.py:344
int sday
Definition: l1_czcs_hdf.c:15
int gpktsize
Definition: l1agen_viirs.h:30
int leapseconds_since_1993(double tai93time)
Definition: leapsecond.c:58
int write_adcs_bus(int32_t iyear, int32_t iday, int32_t ltime, int32_t mtime, int32_t iyrad, int32_t idyad, int32_t nadc, int32_t nbus, int32_t ngps, double *adctime, uint8_t *admandone, int16_t *adfftid, double *bustime, uint8_t *adstate, uint8_t *adsolution, double *gpstime, uint8_t *adcpkts[], uint8_t *buspkts[], uint8_t *gpspkts[])
Definition: l1aFile.cpp:1270
int write_scan_metadata(int32_t isc, uint8_t(*p1)[180], uint8_t(*hrmets)[146 *26], uint8_t(*calmets)[134], uint8_t *mode, int iret, const char *l1a_name, char *VIIRS_packet_file)
Definition: l1aFile.cpp:567
int parseDims(string dimString, int *numDims, int *varDims)
int expandEnvVar(string *sValue)
Definition: hawkeyeUtil.h:41
int isleap(int year)
Definition: isleap.c:3
integer, parameter double
#define SWAP_2(x)
int jgleap(int32_t jday, int32_t *leap)
Definition: l1aFile.cpp:2445
string history
Definition: ncattredit.py:30
#define basename(s)
Definition: l0chunk_modis.c:29
int write_eng_data(int32_t isc, uint8_t(*engdata)[9318])
Definition: l1aFile.cpp:835
dtype
Definition: DDataset.hpp:31
this program makes no use of any feature of the SDP Toolkit that could generate such a then geolocation is calculated at that and then aggregated up to Resolved feature request Bug by adding three new int8 SDSs for each high resolution offsets between the high resolution geolocation and a bi linear interpolation extrapolation of the positions This can be used to reconstruct the high resolution geolocation Resolved Bug by delaying cumulation of gflags until after validation of derived products Resolved Bug by setting Latitude and Longitude to the correct fill resolving to support Near Real Time because they may be unnecessary if use of entrained ephemeris and attitude data is turned resolving bug report Corrected to filter out Aqua attitude records with missing status helping resolve bug MOD_PR03 will still correctly write scan and pixel data that does not depend upon the start time
Definition: HISTORY.txt:248
int EV_APIDs
Definition: l1agen_oci.h:55
Extra metadata that will be written to the HDF4 file l2prod rank
u5 which has been done in the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT production Changes from v6 which may affect scientific the sector rotation may actually occur during one of the scans earlier than the one where it is first reported As a the b1 values are about the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT to fill pixels affected by dead subframes with a special value Output the metadata of noisy and dead subframe Dead Subframe EV and Detector Quality Flag2 Removed the function call of Fill_Dead_Detector_SI to stop interpolating SI values for dead but also for all downstream products for science test only Changes from v5 which will affect scientific to conform to MODIS requirements Removed the Mixed option from the ScanType in the code because the L1A Scan Type is never Mixed Changed for ANSI C compliance and comments to better document the fact that when the HDF_EOS metadata is stricly the and products are off by and in the track respectively Corrected some misspelling of RCS swir_oob_sending_detector to the Reflective LUTs to enable the SWIR OOB correction detector so that if any of the sending detectors becomes noisy or non near by good detectors from the same sending band can be specified as the substitute in the new look up table Code change for adding an additional dimension of mirror side to the Band_21_b1 LUT to separate the coefficient of the two mirror sides for just like other thermal emissive so that the L1B code can calibrate Band scan to scan with mirror side dependency which leads better calibration result Changes which do not affect scientific when the EV data are not provided in this Crosstalk Correction will not be performed to the Band calibration data Changes which do not affect scientific and BB_500m in L1A Logic was added to turn off the or to spatial aggregation processes and the EV_250m_Aggr1km_RefSB and EV_500m_Aggr1km_RefSB fields were set to fill values when SDSs EV_250m and EV_500m are absent in L1A file Logic was added to skip the processing and turn off the output of the L1B QKM and HKM EV data when EV_250m and EV_500m are absent from L1A In this the new process avoids accessing and reading the and L1A EV skips and writing to the L1B and EV omits reading and subsampling SDSs from geolocation file and writing them to the L1B and omits writing metadata to L1B and EV and skips closing the L1A and L1B EV and SDSs Logic was added to turn off the L1B OBC output when the high resolution OBC SDSs are absent from L1A This is accomplished by skipping the openning the writing of metadata and the closing of the L1B OBC hdf which is Bit in the scan by scan bit QA has been changed Until now
Definition: HISTORY.txt:361
char * unix2isodate(double dtime, char zone)
Definition: unix2isodate.c:10
int write_cal_data(int32_t isc, int16_t(*sd_m)[48 *16], int16_t(*sv_m)[48 *16], int16_t(*bb_m)[48 *16], int16_t(*sd_i)[96 *32], int16_t(*sv_i)[96 *32], int16_t(*bb_i)[96 *32], int16_t(*sd_d)[64 *16], int16_t(*sv_d)[64 *16], int16_t(*bb_d)[64 *16])
Definition: l1aFile.cpp:1005
double scan_start_time[MAX_SCAN_NUMBER]
int apktsize
Definition: l1agen_oci.h:53
double ymds2unix(short year, short month, short day, double secs)
int copyl1(char *ifilename, char *ofilename, l1aFile *l1_ofile, int32_t sscan, int32_t escan, int32_t spixl, int32_t epixl)
Definition: l1aFile.cpp:1788
int write_granule_metadata(int32_t iyear, int32_t iday, int32_t ltime, int32_t mtime, int32_t orbit, const char *l1a_name, char *sdir, char *edir, uint8_t *p1, int32_t isc, uint8_t *mode, int argc, char *argv[], const char *doi)
Definition: l1aFile.cpp:1619
logical function leap(YEAR)
Definition: leap.f:10
int write_science_data(string platform, int32_t isc, uint16_t(*mbands)[16][6304], uint16_t(*ibands)[32][6400], uint16_t(*dnb)[16][4064], uint8_t(*mqfl)[16], uint8_t(*iqfl)[32], uint8_t(*dqfl)[16])
Definition: l1aFile.cpp:416
int32_t idy
Definition: atrem_corl1.h:161
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
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int32_t iyr
Definition: atrem_corl1.h:161
#define PROGRAMMER_BOOBOO
Definition: passthebuck.h:8
int k
Definition: decode_rs.h:73
float32 f32
Definition: l2bin.cpp:104
std::string platform
Definition: l1agen_oci.h:52
int openl1(char *l1_filename)
Definition: l1aFile.cpp:1747
int count
Definition: decode_rs.h:79