OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l1agen_viirs.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 <unistd.h>
6 
7 #include <sstream>
8 #include <iomanip>
9 #include <getopt.h>
10 
11 #include "l1agen_viirs.h"
12 #include "netcdf.h"
13 #include "timeutils.h"
14 
15 //#define SCAN_TIME 1.779275
16 
17 #define VERSION "2.13"
18 
19 // Modification history:
20 // Programmer Organization Date Ver Description of change
21 // ---------- ------------ ---- --- ---------------------
22 // Joel Gales FutureTech 06/10/14 Original development
23 // based on IDL routines
24 // developed by F. Patt
25 //
26 // Joel Gales FutureTech 09/22/14 Define pbuffer size
27 // in header file.
28 // Set to 32768.
29 // Joel Gales FutureTech 10/22/14 0.012 Replace usds() with
30 // rice() for decryption.
31 // Joel Gales FutureTech 11/05/14 0.013 Add ADCS/Bus fields
32 // Handle day roll-over
33 // Joel Gales FutureTech 11/19/14 0.014 Include unistd.h for
34 // getpid()
35 // Joel Gales FutureTech 11/20/14 0.015 Trap tellg() = -1
36 // in read_packet()
37 // Set endfile=1
38 // Joel Gales FutureTech 12/16/14 0.016 Encoder data split into
39 // separate fields for the
40 // telescope and HAM data
41 // and stored as uint16_t
42 // Joel Gales FutureTech 12/26/14 0.017 Fix bad offsets
43 // Change 16363 to 16383.
44 // Joel Gales FutureTech 01/14/15 0.018 Add DNB_sequence and
45 // additional engineering
46 // datafields, number_of_scans
47 // global attribute
48 // Joel Gales FutureTech 02/05/15 0.019 Add support for L1B granule
49 // listing file
50 // Joel Gales FutureTech 02/21/15 0.020 Remove check for EOF after
51 // read_viirs_scan_packets()
52 // Joel Gales FutureTech 02/23/15 0.021 Add support for granules
53 // greater than 5 minutes.
54 // Add compression for EV fields.
55 // Joel Gales FutureTech 03/02/15 0.022 Add support for adsolution,
56 // Fix bugs in unpack_viirs_cal()
57 // Add support for DR data
58 // Joel Gales FutureTech 03/09/15 0.023 Store flag_values attribute
59 // as ints
60 // Joel Gales FutureTech 03/26/15 0.024 Make number of scans in
61 // "complete" file
62 // depend on granule period
63 // Joel Gales FutureTech 04/03/15 0.025 Allocate mbands, ibands, dnb,
64 // pbuffer arrays dynamically
65 // Joel Gales FutureTech 04/23/15 0.026 Fix problem with orphan
66 // packets in
67 // read_viirs_scan_packets
68 // Joel Gales FutureTech 04/30/15 0.027 Change ham_side and
69 // sensor_mode from short
70 // to ubyte. Change flt/dbl
71 // flag value from -999 to
72 // -999.9
73 // Joel Gales FutureTech 05/05/15 0.028 Change flag value for SD,
74 // SV, and BB to -999.
75 // Add support for orbit number
76 // determination
77 // Joel Gales FutureTech 05/12/15 0.029 Return from unpack_sci()
78 // if (lp == -4)
79 // Joel Gales FutureTech 05/12/15 0.030 Remove duplicate pbuffer array
80 // Check for M4 and M5 cal data
81 // replacement
82 // Joel Gales FutureTech 06/12/15 0.031 Move adsolution calculation
83 // from astore loop to bstore
84 // loop in extract_adcs_bus
85 // Joel Gales FutureTech 06/15/15 0.032 Change allocation of
86 // adsolution from nacd to nbus
87 // Joel Gales FutureTech 06/16/15 0.033 Generate output text files with
88 // Start/Stop Time,
89 // Number of Records
90 // Joel Gales FutureTech 06/24/15 0.034 Fix day used in yds2tai for
91 // stime/etime in write scan
92 // metadata
93 // Joel Gales FutureTech 06/27/15 0.035 Exit if OCVARROOT not defined
94 // Joel Gales FutureTech 07/05/15 0.036 Don't exit for short last
95 // packet.
96 // Joel Gales FutureTech 07/23/15 0.040 Modify text file to use
97 // parameter=value, Output
98 // actual start/stop time,
99 // granule name, quality flag
100 // Joel Gales FutureTech 07/27/15 0.041 Add additional range checks
101 // in unpack_viirs_scan() and
102 // unpack_cal_sci()
103 // Joel Gales FutureTech 07/30/15 0.042 Move date/time functions to
104 // libtimeutils
105 // Joel Gales FutureTech 08/04/15 0.043 Fix basename parameter in text
106 // file ('txt' -> 'nc')
107 // Joel Gales FutureTech 08/19/15 0.044 Set stop_time entry in text
108 // file to start time of last
109 // scan rather than end time
110 // Joel Gales FutureTech 08/19/15 0.045 Change NPP to SNPP
111 // Joel Gales FutureTech 08/19/15 0.046 In V0.044 forgot to change
112 // eyear, eday to syear, sday
113 // Also fix "time_coverage_start"
114 // Joel Gales FutureTech 08/31/15 0.047 Trap fill values for ibid
115 // in unpack_viirs_cal() and
116 // out-of-order/duplicate stime
117 // Joel Gales FutureTech 09/02/15 0.048 Fix typo for out-of-order fix
118 // Joel Gales FutureTech 09/04/15 0.049 Change valid_range to
119 // valid_min for SHORT & USHORT
120 // fields
121 // Joel Gales FutureTech 09/10/15 0.050 Check for end-of-file before
122 // computing stime
123 // Joel Gales FutureTech 09/21/15 0.051 Check for band number less
124 // than 1 and bad return status
125 // from unpack_cal_sci() in
126 // unpack_viirs_cal() and
127 // idat[25] less than one in
128 // unpack_cal_sci()
129 // Joel Gales FutureTech 09/21/15 0.052 Report and return rather than
130 // exit for orb, att, adcs, bus
131 // TAI time write errors
132 // Joel Gales FutureTech 09/22/15 0.053 Move sync word check in
133 // unpack_cal_sci() before memcpy
134 // Joel Gales FutureTech 09/25/15 0.054 Add sync word checks to
135 // unpack_sci()
136 // Joel Gales FutureTech 11/02/15 0.055 Read viirs orbit time data
137 // before main loop with scope
138 // throughout main program
139 // Joel Gales FutureTech 12/24/15 0.056 if npkts == 1 continue
140 // Set exit status to 101
141 // Joel Gales FutureTech 01/01/16 0.057 Fix day bug for year change
142 // Joel Gales FutureTech 01/28/16 0.990 Write most global attributes
143 // from CDL file
144 // Joel Gales FutureTech 02/25/16 0.991 Check status (not iret) after
145 // return from unpack_cal_sci()
146 // Joel Gales FutureTech 03/29/16 0.992 Remove main loop break if
147 // no records in L1A granule
148 // Joel Gales FutureTech 04/29/16 0.993 Delete 0-scan L1A granules
149 // and do not list in outlist
150 // Joel Gales FutureTech 05/18/16 0.994 Implement updated M4/M5
151 // cal view replacement logic
152 // Joel Gales FutureTech 09/06/16 0.995 Add additional checks for
153 // endfile status after
154 // calls to read_packet()
155 // Joel Gales FutureTech 10/20/16 0.996 Add support for JPSS1
156 // Joel Gales FutureTech 10/21/16 0.997 If npkts == 1 also check for
157 // EOF. Check platform when
158 // writing DNB to determine
159 // number of fields
160 // Joel Gales FutureTech 11/09/16 0.998 Fix handling of checksum
161 // errors, Flag bad mband and
162 // iband with -999, return
163 // status from unpack_sci().
164 // Joel Gales FutureTech 12/07/16 1.900 Add support for platform
165 // specific EV_APIDs, Add
166 // rounding correction to
167 // SC_records computation.
168 // Joel Gales FutureTech 02/02/17 1.910 Fix quality flag bug if early
169 // return in unpack_sci()
170 // Joel Gales FutureTech 02/17/17 1.920 Clear enddata if apid != 826
171 // Joel Gales FutureTech 02/23/17 1.930 Set engineering quantities
172 // to flag values in engineering
173 // buffer is empty (apid != 826)
174 // Joel Gales FutureTech 03/10/17 1.940 Initialize first,last to -1.
175 // Check before getting orbit
176 // direction in write_diary()
177 // Joel Gales FutureTech 04/21/17 1.950 Trap PDS granules with
178 // times incompatible with
179 // expected scan periods.
180 // Joel Gales FutureTech 05/02/17 1.96 Fix bug when mper=0
181 // (stime was being overwritten)
182 // Joel Gales FutureTech 05/25/17 1.97 Initialize sdir/edir to
183 // "Undetermined"
184 // Joel Gales FutureTech 08/03/17 1.98 Check reconstructed band flag
185 // values in unpack_viirs_scan
186 // Joel Gales FutureTech 11/28/17 1.99 Skip short period adc/bus
187 // records in write_adcs_bus()
188 // Joel Gales FutureTech 12/13/17 2.00 Add support for J1 orbitfile
189 // Joel Gales FutureTech 12/20/17 2.01 Check for M-band data in DNB
190 // packet (from F.Patt)
191 // Joel Gales FutureTech 12/22/17 2.02 Fix packet loop limit in
192 // scan_complete
193 // Joel Gales FutureTech 01/10/18 2.03 Check for SC_records_val before
194 // writing adcs_bus fields
195 // Joel Gales FutureTech 01/11/18 2.04 Initialize mbands, ibands,
196 // dnb arrays to -999
197 // Joel Gales FutureTech 01/25/18 2.05 Check if npkts exceeds 513
198 // in read_viirs_scan_packets()
199 // Sean Bailey NASA 06/27/18 2.06 Incorporated minor changes made by the LSIPS team
200 // variable initializations; dead code deletion;
201 // delete->delete[] where appropriate,
202 // i.e. no functional changes :)
203 // Fred Patt SAIC 11/18/19 2.07 Added instrument number check
204 // unpack_viirs_scan
205 // Joel Gales SAIC 06/28/21 2.10 Add support for JPSS-2
206 // Joel Gales SAIC 06/30/21 2.11 Only open GPS file for JPSS-2
207 // Gwyn Fireman SAIC 09/30/21 2.12 Add option for new naming convention
208 
209 #define MAX_PKTS_PER_SCAN 513
210 
211 int main (int argc, char* argv[])
212 {
213 
214  // SNPP
215  // VIIRS Science (vfile) P1570826
216  // S/C diary 1Hz (sfile) P1570011
217  // ADCS 1Hz (afile) P1570008
218  // bus telem (bfile) P1570000
219 
220  // JPSS-1
221  // VIIRS Science (vfile) P1590826
222  // S/C diary 1Hz (sfile) P1590011
223  // ADCS 1Hz (afile) P1590008
224  // bus telem (bfile) P1590000
225 
226  // JPSS-2
227  // VIIRS Science (vfile) P1770826
228  // S/C diary 10Hz (sfile) P1770011
229  // ADCS 10Hz (afile) P1770030
230  // bus telem (bfile) P1770037
231  // GPS (gfile) P1770034
232 
233  cout << "l1agen_viirs " << VERSION << " ("
234  << __DATE__ << " " << __TIME__ << ")" << endl;
235 
236  if ( argc == 1) {
237  cout << endl <<
238  "l1agen_viirs VIIRS_packet_file S/C_diary_packet_file " <<
239  "ADCS_file bus_telemetry_file granule_len " <<
240  "[-o|--outlist output_list_file] " <<
241  "[-g|--gpsfilename gps_file] " <<
242  "[-n|--new_naming] " <<
243  "[-d|--doi doi_string]" <<
244  endl;
245  return 0;
246  }
247 
248  int c;
249  string outlist = "";
250  string gpsfilename = "";
251  bool new_naming = false;
252  string doi = "";
253  while (1) {
254  static struct option long_options[] = {
255  {"outlist", required_argument, 0, 'o'},
256  {"gpsfilename", required_argument, 0, 'g'},
257  {"new_naming", no_argument, 0, 'n'},
258  {"doi", required_argument, 0, 'd'},
259  {0, 0, 0, 0}
260  };
261 
262  /* getopt_long stores the option index here. */
263  int option_index = 0;
264 
265  c = getopt_long( argc, argv, "o:g:n:d:", long_options, &option_index);
266 
267  /* Detect the end of the options. */
268  if (c == -1)
269  break;
270 
271  switch (c)
272  {
273  case 'o':
274  // printf ("option -o with value `%s'\n", optarg);
275  outlist.assign( optarg);
276  break;
277 
278  case 'g':
279  // printf ("option -o with value `%s'\n", optarg);
280  gpsfilename.assign( optarg);
281  break;
282 
283  case 'n':
284  new_naming = true;
285  break;
286 
287  case 'd':
288  doi.assign( optarg);
289  break;
290 
291  default:
292  abort ();
293  }
294  }
295 
296  ofstream fout;
297  if ( outlist.compare("") != 0)
298  fout.open( outlist.c_str());
299 
300  fstream vfileStream, sfileStream, afileStream, bfileStream, gfileStream;
301 
302  // VIIRS packet file
303  vfileStream.open( argv[optind+0], fstream::in | fstream::binary);
304  if ( vfileStream.fail()) {
305  cout << argv[optind+0] << " not found" << endl;
306  exit(1);
307  }
308 
309  // S/C diary file
310  sfileStream.open( argv[optind+1], fstream::in | fstream::binary);
311  if ( sfileStream.fail()) {
312  cout << argv[optind+1] << " not found" << endl;
313  exit(1);
314  }
315 
316  // Get S/C diary filesize
317  sfileStream.seekg (0, ios::end);
318  int sFileSize = sfileStream.tellg();
319  sfileStream.seekg (0, ios::beg);
320  int32_t const nscd = sFileSize/71;
321 
322  // Allocate continuous 2-dim scdpkts array
323  uint8_t **scdpkts = new uint8_t*[nscd];
324  scdpkts[0] = new uint8_t[71*nscd];
325  for (int i=1; i<nscd; i++) scdpkts[i] = scdpkts[i-1] + 71;
326 
327  // Read entire S/C diary file into buffer
328  sfileStream.read( (char *) &scdpkts[0][0], sFileSize);
329  sfileStream.close();
330 
331  // Determine platform
332  string platform;
333  string plat; // short form
334  int apktsize;
335  int bpktsize;
336  int gpktsize;
337  int EV_APIDs;
338  float scan_time;
339  int adoffsets[4];
340  switch (scdpkts[0][14]) {
341  case 157:
342  platform.assign("SNPP");
343  plat.assign("SNPP");
344  apktsize = 355;
345  bpktsize = 207;
346  gpktsize = 0;
347  EV_APIDs = 24;
348  scan_time = 1.7793;
349  adoffsets[0] = 169;
350  adoffsets[1] = 127;
351  adoffsets[2] = 255;
352  adoffsets[3] = 339;
353  break;
354 
355  case 159:
356  platform.assign("JPSS-1");
357  plat.assign("JPSS1");
358  apktsize = 393;
359  bpktsize = 183;
360  gpktsize = 0;
361  EV_APIDs = 26;
362  scan_time = 1.7864;
363  adoffsets[0] = 81;
364  adoffsets[1] = 131;
365  adoffsets[2] = 96;
366  adoffsets[3] = 163;
367  break;
368 
369  case 177:
370  platform.assign("JPSS-2");
371  plat.assign("JPSS2");
372  apktsize = 493;
373  bpktsize = 212;
374  gpktsize = 374;
375  EV_APIDs = 26;
376  scan_time = 1.7864;
377  adoffsets[0] = 33;
378  adoffsets[1] = 433;
379  adoffsets[2] = 27;
380  adoffsets[3] = 28;
381  break;
382 
383  default:
384  cout << "Unknown platform type" << endl;
385  exit(1);
386  }
387 
388  // Allocate orbit and attitude time arrays
389  double *otime = new double[nscd];
390  double *atime = new double[nscd];
391 
392  // Allocate continuous 2-dim orbit vector array
393  float **orb = new float *[nscd];
394  orb[0] = new float[6*nscd];
395  for (int i=1; i<nscd; i++) orb[i] = orb[i-1] + 6;
396 
397  // Allocate continuous 2-dim quaternion array
398  float **quat = new float *[nscd];
399  quat[0] = new float[4*nscd];
400  for (int i=1; i<nscd; i++) quat[i] = quat[i-1] + 4;
401 
402  int32_t iyrsc, idysc;
403 
404  convert_diary( nscd, (uint8_t (*)[71]) &scdpkts[0][0], &iyrsc, &idysc,
405  otime, (float (*)[6]) &orb[0][0],
406  atime, (float (*)[4]) &quat[0][0]);
407 
408  // ADCS data
409  afileStream.open( argv[optind+2], fstream::in | fstream::binary);
410  if ( afileStream.fail()) {
411  cout << argv[optind+2] << " not found" << endl;
412  exit(1);
413  }
414 
415  // Get ADCS filesize
416  afileStream.seekg (0, ios::end);
417  int aFileSize = afileStream.tellg();
418  afileStream.seekg (0, ios::beg);
419  int32_t nadc = aFileSize/apktsize;
420 
421  // Allocate continuous 2-dim adcpkts array
422  uint8_t **adcpkts = new uint8_t*[nadc];
423 
424  adcpkts[0] = new uint8_t[apktsize*nadc];
425  for (int i=1; i<nadc; i++) adcpkts[i] = adcpkts[i-1] + apktsize;
426 
427  // Read entire ADCD file into buffer
428  afileStream.read( (char *) &adcpkts[0][0], aFileSize);
429  afileStream.close();
430 
431 
432  // Bus-critical telemetry
433  bfileStream.open( argv[optind+3], fstream::in | fstream::binary);
434  if ( bfileStream.fail()) {
435  cout << argv[optind+3] << " not found" << endl;
436  exit(1);
437  }
438 
439  // Get Bus-critical telemetry filesize
440  bfileStream.seekg (0, ios::end);
441  int bFileSize = bfileStream.tellg();
442  bfileStream.seekg (0, ios::beg);
443  int32_t nbus = bFileSize/bpktsize;
444 
445  // Allocate continuous 2-dim buspkts array
446  uint8_t **buspkts = new uint8_t*[nbus];
447  buspkts[0] = new uint8_t[bpktsize*nbus];
448  for (int i=1; i<nbus; i++) buspkts[i] = buspkts[i-1] + bpktsize;
449 
450  // Read entire Bus-critical telemetry file into buffer
451  bfileStream.read( (char *) &buspkts[0][0], bFileSize);
452  bfileStream.close();
453 
454 
455  // GPS telemetry
456  int32_t ngps = 0;
457  double *gpstime = NULL;
458  uint8_t **gpspkts = NULL;
459  if ( platform.compare("JPSS-2") == 0) {
460  gfileStream.open( gpsfilename, fstream::in | fstream::binary);
461  if ( gfileStream.fail()) {
462  cout << argv[optind+3] << " not found" << endl;
463  exit(1);
464  }
465 
466  // Get GPS telemetry filesize
467  gfileStream.seekg (0, ios::end);
468  int gFileSize = gfileStream.tellg();
469  gfileStream.seekg (0, ios::beg);
470  ngps = gFileSize/gpktsize;
471 
472  // Allocate continuous 2-dim gpspkts array
473  gpspkts = new uint8_t*[ngps];
474  gpspkts[0] = new uint8_t[gpktsize*ngps];
475  for (int i=1; i<ngps; i++) gpspkts[i] = gpspkts[i-1] + gpktsize;
476 
477  // Read entire GPS telemetry file into buffer
478  gfileStream.read( (char *) &gpspkts[0][0], gFileSize);
479  gfileStream.close();
480 
481  gpstime = new double[ngps];
482  }
483 
484  int32_t iyrad, idyad;
485 
486  // Allocate orbit and attitude time arrays
487  double *adctime = new double[nadc];
488  double *bustime = new double[nbus];
489  uint8_t *adstate = new uint8_t[nbus];
490  uint8_t *adsolution = new uint8_t[nbus];
491  uint8_t *admandone = new uint8_t[nadc];
492  int16_t *adfftid = new int16_t[nadc];
493 
494  // extract_adcs_bus( nadc, (uint8_t (*)[355]) &adcpkts[0][0],
495  // nbus, (uint8_t (*)[207]) &buspkts[0][0],
496  // &iyrad, &idyad, adctime, bustime,
497  // adstate, admandone, adfftid, adsolution);
498 
499  extract_adcs_bus( adoffsets, nadc, &adcpkts[0], nbus, &buspkts[0],
500  &iyrad, &idyad, adctime, bustime,
501  adstate, admandone, adfftid, adsolution, platform,
502  ngps, gpspkts, gpstime);
503 
504  int32_t apid = 0;
505  int32_t len = 0;
506  int32_t endfile;
507  uint8_t epacket[9318];
508 
509  // Read to the first engineering packet of a scan (APID = 826)
510  while (1) {
511 
512  read_packet( &vfileStream, NULL, &len, &apid, &endfile);
513  if ( endfile) {
514  cout << "Start of scan not found in file" << endl;
515  exit(1);
516  }
517 
518  if ( apid == 826 && len == 9318) {
519  vfileStream.seekg( -6, ios_base::cur);
520  read_packet( &vfileStream, epacket, &len, NULL, &endfile);
521  break;
522  } else {
523  vfileStream.seekg( len-6, ios_base::cur);
524  }
525  }
526 
527  int vfilePos = vfileStream.tellg();
528 
529  // Determine start and end time of first granule
530  int32_t toff, iyear, iday, iyr, idy;
531 
532  double stime, ptime, etime;
533 
534  // Scan start time
535  toff = 6;
536  ccsds_to_yds( &epacket[toff], &iyear, &iday, &stime);
537 
538  // Packet time
539  toff = 20;
540  ccsds_to_yds( &epacket[toff], &iyr, &idy, &ptime);
541 
542  // Scan end time
543  toff = 38;
544  ccsds_to_yds( &epacket[toff], &iyr, &idy, &etime);
545 
546  // Get granule period in minutes
547  int32_t mper;
548  string str = argv[optind+4];
549  istringstream( str) >> mper;
550 
551  // Allocate continuous 2-dim pbuffer array
552  uint8_t **pbuffer = new uint8_t *[MAX_PKTS_PER_SCAN];
553  pbuffer[0] = new uint8_t[MAX_PKTS_PER_SCAN*PBUFFER_SIZE];
554  for (int i=1; i<MAX_PKTS_PER_SCAN; i++) {
555  pbuffer[i] = pbuffer[i-1] + PBUFFER_SIZE;
556  }
557 
558 
559  // Determine number of scans if granule period not specified
560  if ( mper == 0) {
561  cout << "Determining number of scans in " << argv[optind+0] << ": ";
562  cout << flush;
563 
564  uint8_t epacket0[9318];
565  memcpy ( epacket0, epacket, 9318);
566 
567  // Read VIIRS scans
568  int32_t isc = 0;
569  while ( !endfile) {
570  // if ((isc % 10) == 0) cout << "Processing scan " << isc << endl;
571 
572  // Read packets for that scan
573  int32_t npkts;
574  read_viirs_scan_packets( &vfileStream, epacket0,
575  (uint8_t (*)[PBUFFER_SIZE]) &pbuffer[0][0],
576  &npkts, &endfile);
577 
578  // Get scan time from next engineering packet
579  double tmptime;
580  toff = 6;
581  ccsds_to_yds( &epacket0[toff], &iyr, &idy, &tmptime);
582  // cout << "isc: " << isc << " time: " << tmptime << endl;
583 
584  if ( npkts == 1) continue;
585 
586  isc++;
587  }
588 // mper = isc * (scan_time/60) + 3;
589  mper = isc * (scan_time/60) + 1;
590  cout << isc << endl;
591  vfileStream.clear();
592  vfileStream.seekg( vfilePos, ios::beg);
593  endfile = 0;
594  }
595  // cout << vfileStream.tellg() << endl;
596 
597  // Find closest previous mper-min time for starttime
598  int32_t ltime = (((int32_t) (stime)) / 60 / mper) * (mper*60);
599  if (mper > 10) ltime = (int32_t) (stime);
600  int32_t mtime = ltime + mper*60; // scan time of last line in granule
601 
602  // Generate L1A file name
603  char datetime[NC_MAX_NAME];
604  string l1a_name;
605 
606  time_t unixtime = (time_t) yds2unix(iyear,iday,ltime);
607  struct tm* trec = gmtime(&unixtime);
608 
609  if (new_naming) {
610  strftime(datetime, NC_MAX_NAME, "%Y%m%dT%H%M%S", trec);
611  l1a_name.assign(plat + "_VIIRS." + string(datetime) + ".L1A.nc");
612  } else {
613  strftime(datetime, NC_MAX_NAME, "%Y%j%H%M%S", trec);
614  l1a_name.assign(string("V") + string(datetime) + ".L1A_" + plat + ".nc");
615  }
616  cout << endl << l1a_name.c_str() << endl;
617 
618 
619  static l1aFile outfile;
620  outfile.platform.assign(platform);
621  outfile.apktsize = apktsize;
622  outfile.bpktsize = bpktsize;
623  outfile.gpktsize = gpktsize;
624  outfile.EV_APIDs = EV_APIDs;
625 
626  int32_t maxsc = mper*60/scan_time + 1;
627  cout << "maxsc: " << maxsc << endl;
628 
629  // Initialize data arrays
630 
631  // M-band cal data
632  int16_t sdm[17][16][48], svm[17][16][48], bbm[17][16][48];
633 
634  // I-band cal data
635  int16_t sdi[5][32][96], svi[5][32][96], bbi[5][32][96];
636 
637  // DNB cal data
638  int16_t sdd[16][64], svd[16][64], bbd[16][64];
639 
640 
641  // Allocate continuous 2-dim engdata array
642  uint8_t **engdata = new uint8_t *[maxsc];
643  engdata[0] = new uint8_t[9318*maxsc];
644  for (int i=1; i<maxsc; i++) engdata[i] = engdata[i-1] + 9318;
645 
646  // Allocate continuous 2-dim p1 array
647  uint8_t **p1 = new uint8_t *[maxsc];
648  p1[0] = new uint8_t[180*maxsc];
649  for (int i=1; i<maxsc; i++) p1[i] = p1[i-1] + 180;
650 
651  // Allocate continuous 2-dim HR metadata array
652  uint8_t **hrmets = new uint8_t *[maxsc];
653  hrmets[0] = new uint8_t[146*EV_APIDs*maxsc];
654  for (int i=1; i<maxsc; i++) hrmets[i] = hrmets[i-1] + 146*EV_APIDs;
655 
656  // Allocate single-scan HR metadata array
657  uint8_t **hrmet;
658  hrmet = new uint8_t *[EV_APIDs];
659  hrmet[0] = new uint8_t[146*EV_APIDs];
660  for ( int i=1; i<EV_APIDs; i++) hrmet[i] = hrmet[i-1] + 146;
661 
662  // Allocate continuous 2-dim CAL metadata array
663  uint8_t **calmets = new uint8_t *[maxsc];
664  calmets[0] = new uint8_t[134*maxsc];
665  for (int i=1; i<maxsc; i++) calmets[i] = calmets[i-1] + 134;
666 
667  // Allocate continuous 2-dim SD M cal arrays
668  int16_t **sd_m = new int16_t *[17*maxsc];
669  sd_m[0] = new int16_t[17*maxsc*48*16];
670  for (int i=1; i<17*maxsc; i++) {
671  sd_m[i] = sd_m[i-1] + 48*16;
672  for (int j=0; j<48*16; j++) sd_m[i][j] = -999;
673  }
674 
675  // Allocate continuous 2-dim SV M cal arrays
676  int16_t **sv_m = new int16_t *[17*maxsc];
677  sv_m[0] = new int16_t[17*maxsc*48*16];
678  for (int i=1; i<17*maxsc; i++) {
679  sv_m[i] = sv_m[i-1] + 48*16;
680  for (int j=0; j<48*16; j++) sv_m[i][j] = -999;
681  }
682 
683  // Allocate continuous 2-dim BB M cal arrays
684  int16_t **bb_m = new int16_t *[17*maxsc];
685  bb_m[0] = new int16_t[17*maxsc*48*16];
686  for (int i=1; i<17*maxsc; i++) {
687  bb_m[i] = bb_m[i-1] + 48*16;
688  for (int j=0; j<48*16; j++) bb_m[i][j] = -999;
689  }
690 
691  // Allocate continuous 2-dim SD I cal arrays
692  int16_t **sd_i = new int16_t *[5*maxsc];
693  sd_i[0] = new int16_t[5*maxsc*96*32];
694  for (int i=1; i<5*maxsc; i++) {
695  sd_i[i] = sd_i[i-1] + 96*32;
696  for (int j=0; j<96*32; j++) sd_i[i][j] = -999;
697  }
698 
699  // Allocate continuous 2-dim SV I cal arrays
700  int16_t **sv_i = new int16_t *[5*maxsc];
701  sv_i[0] = new int16_t[5*maxsc*96*32];
702  for (int i=1; i<5*maxsc; i++) {
703  sv_i[i] = sv_i[i-1] + 96*32;
704  for (int j=0; j<96*32; j++) sv_i[i][j] = -999;
705  }
706 
707  // Allocate continuous 2-dim BB I cal arrays
708  int16_t **bb_i = new int16_t *[5*maxsc];
709  bb_i[0] = new int16_t[5*maxsc*96*32];
710  for (int i=1; i<5*maxsc; i++) {
711  bb_i[i] = bb_i[i-1] + 96*32;
712  for (int j=0; j<96*32; j++) bb_i[i][j] = -999;
713  }
714 
715  // Allocate continuous 2-dim SD DNB cal arrays
716  int16_t **sd_d = new int16_t *[maxsc];
717  sd_d[0] = new int16_t[maxsc*64*16];
718  for (int i=1; i<maxsc; i++) {
719  sd_d[i] = sd_d[i-1] + 64*16;
720  for (int j=0; j<64*16; j++) sd_d[i][j] = -999;
721  }
722 
723  // Allocate continuous 2-dim SV DNB cal arrays
724  int16_t **sv_d = new int16_t *[maxsc];
725  sv_d[0] = new int16_t[maxsc*64*16];
726  for (int i=1; i<maxsc; i++) {
727  sv_d[i] = sv_d[i-1] + 64*16;
728  for (int j=0; j<64*16; j++) sv_d[i][j] = -999;
729  }
730 
731  // Allocate continuous 2-dim BB DNB cal arrays
732  int16_t **bb_d = new int16_t *[maxsc];
733  bb_d[0] = new int16_t[maxsc*64*16];
734  for (int i=1; i<maxsc; i++) {
735  bb_d[i] = bb_d[i-1] + 64*16;
736  for (int j=0; j<64*16; j++) bb_d[i][j] = -999;
737  }
738 
739  typedef uint16_t mbands_array[16][6304];
740  typedef uint16_t ibands_array[32][6400];
741  typedef uint16_t dnb_array[16][4064];
742 
743  mbands_array *mbands;
744  mbands = new mbands_array[16];
745  for (int i=0; i<16; i++)
746  for (int j=0; j<16; j++)
747  for (int k=0; k<6304; k++)
748  mbands[i][j][k] = -999;
749 
750  ibands_array *ibands;
751  ibands = new ibands_array[5];
752  for (int i=0; i<5; i++)
753  for (int j=0; j<32; j++)
754  for (int k=0; k<6400; k++)
755  ibands[i][j][k] = -999;
756 
757  dnb_array *dnb;
758  dnb = new dnb_array[5];
759  for (int i=0; i<5; i++)
760  for (int j=0; j<16; j++)
761  for (int k=0; k<4064; k++)
762  dnb[i][j][k] = -999;
763 
764 
765  // Load orbit times
766  uint32_t orbitStartYearDay[128];
767  double orbitStartSecOfDay[128];
768  double orbitPeriods[128];
769  uint32_t orbitNumbers[128];
770  ifstream orbitStartTimesFile;
771 
772  char *ocvarroot_str = getenv("OCVARROOT");
773  if (ocvarroot_str == 0x0) {
774  printf("Environment variable OCVARROOT not defined.\n");
775  exit(1);
776  }
777 
778  string orbitStartTimesFilename = ocvarroot_str;
779  if ( platform.compare("SNPP") == 0) {
780  orbitStartTimesFilename += "/viirsn/viirs_orbit_times.txt";
781  } else if ( platform.compare("JPSS-1") == 0) {
782  orbitStartTimesFilename += "/viirsj1/viirs_j1_orbit_times.txt";
783  } else if ( platform.compare("JPSS-2") == 0) {
784  orbitStartTimesFilename += "/viirsj2/viirs_j2_orbit_times.txt";
785  }
786 
787  // /*
788  //JMG
789  orbitStartTimesFile.open( orbitStartTimesFilename.c_str());
790  if ( !orbitStartTimesFile.is_open()) {
791  cout << orbitStartTimesFilename.c_str() << " not found." << endl;
792  exit(1);
793  }
794  for (size_t i=0; i<128; i++) {
795  orbitStartTimesFile >> orbitNumbers[i];
796  orbitStartTimesFile >> orbitStartYearDay[i];
797  orbitStartTimesFile >> orbitStartSecOfDay[i];
798  orbitStartTimesFile >> orbitPeriods[i];
799  if ( orbitNumbers[i] == 0) break;
800  }
801  orbitStartTimesFile.close();
802  // */
803 
804  int status;
805  int iret;
806 
807  bool exit_101 = false;
808 
810  while (!endfile) {
811  outfile.createl1( (char *) l1a_name.c_str(), maxsc);
812 
813  iret = 0;
814 
815  // Read and process VIIRS scans
816  int32_t isc = 0;
817  while ( stime < mtime) {
818 
819  if ( isc == maxsc) {
820  cout << "Bad granule -- Times incompatible with scan period." << endl;
821  exit(101);
822  }
823 
824  if ((isc % 10) == 0) cout << "Processing scan " << isc << endl;
825  // cout << "Processing scan " << isc << " " << stime << endl;
826 
827  // Save engineering packet in array
828  apid = (epacket[0] % 8)*256 + epacket[1];
829  if (apid == 826)
830  memcpy( engdata[isc], epacket, 9318);
831  else
832  memset( engdata[isc], 0, 9318);
833 
834  // Read packets for that scan
835  int32_t npkts;
836  read_viirs_scan_packets( &vfileStream, epacket,
837  (uint8_t (*)[PBUFFER_SIZE]) &pbuffer[0][0],
838  &npkts, &endfile);
839 
840  // if npkts == 1 then bad scan
841  if ( npkts == 1 && endfile == 0) {
842  exit_101 = true;
843  continue;
844  }
845 
846  // Check for complete scan
847  int icmp = scan_complete( (uint8_t (*)[PBUFFER_SIZE]) &pbuffer[0][0],
848  npkts);
849 
850  iret = iret | icmp;
851 
852  int32_t ip = 1;
853  while( pbuffer[ip][0] < 8) ip++;
854  memcpy( &p1[isc][0], &pbuffer[ip][0], 180);
855 
856  //uint8_t hrmet[26][146];
857  uint8_t mqfl[16][16];
858  uint8_t iqfl[5][32];
859  uint8_t dqfl[5][16];
860 
861  for ( int i=0; i<EV_APIDs; i++) memset( &hrmet[i][0], 0, 146);
862  // memset( &hrmet, 0, 26*146);
863  memset( &mqfl, 127, 16*16);
864  memset( &iqfl, 127, 5*32);
865  memset( &dqfl, 127, 5*16);
866 
867  // Unpack science data from packets
868  status = unpack_viirs_scan( npkts,
869  (uint8_t (*)[PBUFFER_SIZE]) &pbuffer[0][0],
870  (uint16_t (*) [16][6304]) &mbands[0][0][0],
871  (uint16_t (*) [32][6400]) &ibands[0][0][0],
872  (uint16_t (*) [16][4064]) &dnb[0][0][0],
873  (uint8_t (*) [16]) &mqfl[0][0],
874  (uint8_t (*) [32]) &iqfl[0][0],
875  (uint8_t (*) [16]) &dqfl[0][0],
876  (uint8_t (*)[146]) &hrmet[0][0]);
877  iret = iret | status;
878 
879  // Write science data to file
880  outfile.write_science_data( platform, isc,
881  (uint16_t (*) [16][6304]) &mbands[0][0][0],
882  (uint16_t (*) [32][6400]) &ibands[0][0][0],
883  (uint16_t (*) [16][4064]) &dnb[0][0][0],
884  (uint8_t (*) [16]) &mqfl[0][0],
885  (uint8_t (*) [32]) &iqfl[0][0],
886  (uint8_t (*) [16]) &dqfl[0][0]);
887 
888  // Unpack science data from packets
889  uint8_t calmet[134];
890  status = unpack_viirs_cal( npkts,
891  (uint8_t (*)[PBUFFER_SIZE]) &pbuffer[0][0],
892  (int16_t (*) [16][48]) &sdm[0][0][0],
893  (int16_t (*) [16][48]) &svm[0][0][0],
894  (int16_t (*) [16][48]) &bbm[0][0][0],
895  (int16_t (*) [32][96]) &sdi[0][0][0],
896  (int16_t (*) [32][96]) &svi[0][0][0],
897  (int16_t (*) [32][96]) &bbi[0][0][0],
898  (int16_t (*) [64]) &sdd[0][0],
899  (int16_t (*) [64]) &svd[0][0],
900  (int16_t (*) [64]) &bbd[0][0],
901  calmet);
902  iret = iret | status;
903 
904  for (int i=0; i<17; i++) {
905  // cout << "i: " << i << " isc: " << isc << endl;
906  memcpy( &sd_m[i*maxsc+isc][0], &sdm[i][0][0], 48*16*sizeof(int16_t));
907  memcpy( &sv_m[i*maxsc+isc][0], &svm[i][0][0], 48*16*sizeof(int16_t));
908  memcpy( &bb_m[i*maxsc+isc][0], &bbm[i][0][0], 48*16*sizeof(int16_t));
909  }
910 
911  for (int i=0; i<5; i++) {
912  memcpy( &sd_i[i*maxsc+isc][0], &sdi[i][0][0], 96*32*sizeof(int16_t));
913  memcpy( &sv_i[i*maxsc+isc][0], &svi[i][0][0], 96*32*sizeof(int16_t));
914  memcpy( &bb_i[i*maxsc+isc][0], &bbi[i][0][0], 96*32*sizeof(int16_t));
915  }
916 
917  memcpy( &sd_d[isc][0], &sdd[0][0], 64*16*sizeof(int16_t));
918  memcpy( &sv_d[isc][0], &svd[0][0], 64*16*sizeof(int16_t));
919  memcpy( &bb_d[isc][0], &bbd[0][0], 64*16*sizeof(int16_t));
920 
921  // Save HR and cal metadata in array
922  memcpy( &hrmets[isc][0], &hrmet[0][0], 146*EV_APIDs*sizeof(uint8_t));
923  //printf("3b sd_m[0]: %p\n", sd_m[0]);
924  memcpy( &calmets[isc][0], &calmet[0], 134*sizeof(uint8_t));
925 
926 
927  // Bail if end of L0 input file
928  if ( endfile) isc++;
929  if ( endfile) break;
930 
931  double prev_stime = stime;
932 
933  // Get scan time from next engineering packet
934  toff = 6;
935  ccsds_to_yds( &epacket[toff], &iyr, &idy, &stime);
936  // cout << "isc: " << isc << " stime: " << stime << endl;
937 
938  if (stime == prev_stime) {
939  cout << "stime: " << stime << " equal to previous stime: " <<
940  prev_stime << endl;
941  stime = prev_stime;
942  continue;
943  }
944 
945  if (iday == idy && stime < prev_stime) {
946  cout << "stime: " << stime << " less than previous stime: " <<
947  prev_stime << " for same day" << endl;
948  stime = prev_stime;
949  continue;
950  }
951 
952  if (idy < iday) idy = iday + 1;
953  stime = stime + (idy-iday)*86400;
954 
955  isc++;
956 
957  } // while ( (stime < mtime) && (!endfile))
958 
959  cout << "Number of scans to write: " << isc << endl;
960 
961  // If not scans in file then break
962  // if ( isc == 0)
963  // break;
964 
965  // Set remaining cal field entries to fill (-999)
966  int16_t minus999 = -999;
967  for (int k=0; k<17; k++) {
968  for (int j=isc; j<maxsc; j++) {
969  for (int i=0; i<48*16; i++) {
970  memcpy( &sd_m[k*maxsc+j][i], &minus999, sizeof(int16_t));
971  memcpy( &sv_m[k*maxsc+j][i], &minus999, sizeof(int16_t));
972  memcpy( &bb_m[k*maxsc+j][i], &minus999, sizeof(int16_t));
973  }
974  }
975  }
976 
977  for (int k=0; k<5; k++) {
978  for (int j=isc; j<maxsc; j++) {
979  for (int i=0; i<96*32; i++) {
980  memcpy( &sd_i[k*maxsc+j][i], &minus999, sizeof(int16_t));
981  memcpy( &sv_i[k*maxsc+j][i], &minus999, sizeof(int16_t));
982  memcpy( &bb_i[k*maxsc+j][i], &minus999, sizeof(int16_t));
983  }
984  }
985  }
986 
987  for (int j=isc; j<maxsc; j++) {
988  for (int i=0; i<64*16; i++) {
989  memcpy( &sd_d[j][i], &minus999, sizeof(int16_t));
990  memcpy( &sv_d[j][i], &minus999, sizeof(int16_t));
991  memcpy( &bb_d[j][i], &minus999, sizeof(int16_t));
992  }
993  }
994 
995 
996  // Get scan metadata and write to file
997  uint8_t *mode = new uint8_t[isc];
998 
999  int mn_scn = (int) ((mper*60) / scan_time);
1000  int mx_scn = mn_scn + 1;
1001  if (isc != mn_scn && isc != mx_scn) iret = iret | 1;
1002 
1003  outfile.write_scan_metadata( isc,
1004  (uint8_t (*)[180]) &p1[0][0],
1005  (uint8_t (*)[146*26]) &hrmets[0][0],
1006  (uint8_t (*)[134]) &calmets[0][0],
1007  mode, iret, (const char *) l1a_name.c_str(),
1008  argv[optind+0]);
1009 
1010  // Unpack engineering data and write to file
1011  outfile.write_eng_data( isc, (uint8_t (*)[9318]) &engdata[0][0]);
1012 
1013  // Write calibration data to file
1014  outfile.write_cal_data( isc,
1015  (int16_t (*) [48*16]) &sd_m[0][0],
1016  (int16_t (*) [48*16]) &sv_m[0][0],
1017  (int16_t (*) [48*16]) &bb_m[0][0],
1018  (int16_t (*) [96*32]) &sd_i[0][0],
1019  (int16_t (*) [96*32]) &sv_i[0][0],
1020  (int16_t (*) [96*32]) &bb_i[0][0],
1021  (int16_t (*) [64*16]) &sd_d[0][0],
1022  (int16_t (*) [64*16]) &sv_d[0][0],
1023  (int16_t (*) [64*16]) &bb_d[0][0]);
1024 
1025 
1026  // Locate S/C diary data and write to file
1027  char sdir[16], edir[16];
1028  strcpy(sdir, "Undetermined");
1029  strcpy(edir, "Undetermined");
1030  outfile.write_diary( iyear, iday, ltime, mtime, iyrsc, idysc, nscd,
1031  otime, (float (*)[6]) &orb[0][0],
1032  atime, (float (*)[4]) &quat[0][0],
1033  sdir, edir);
1034 
1035  outfile.write_adcs_bus( iyear, iday, ltime, mtime, iyrad, idyad,
1036  nadc, nbus, ngps, adctime, admandone, adfftid,
1037  bustime, adstate, adsolution, gpstime,
1038  &adcpkts[0], &buspkts[0], &gpspkts[0]);
1039 
1040  // Compute orbit number
1041 
1042  int32_t orbit = -1;
1043  uint32_t orbitStartYearDay0 = iyear*1000+iday;
1044 
1045  double time_tai, dbl_ltime;
1046  dbl_ltime = (double) ltime;
1047  time_tai = yds2tai93( iyear, iday, dbl_ltime);
1048 
1049  for (size_t i=0; i<128; i++) {
1050 
1051  if ( orbitStartYearDay[i] > orbitStartYearDay0 ||
1052  (orbitStartYearDay[i] == orbitStartYearDay0 &&
1053  orbitStartSecOfDay[i] > ltime)) {
1054  i--;
1055 
1056  double tai;
1057  uint32_t iyr = (uint32_t) orbitStartYearDay[i]/1000;
1058  uint32_t idy = orbitStartYearDay[i] - iyr*1000;
1059  tai = yds2tai93( iyr, idy, orbitStartSecOfDay[i]);
1060 
1061  orbit = uint32_t ((time_tai - tai) / orbitPeriods[i]) +
1062  orbitNumbers[i];
1063 
1064  break;
1065  }
1066  }
1067 
1068  // Generate granule metadata and write to file
1069  outfile.write_granule_metadata( iyear, iday,
1070  ltime, mtime, orbit,
1071  (const char *) l1a_name.c_str(),
1072  sdir, edir,
1073  (uint8_t *) p1[0],
1074  isc, mode, argc, argv, doi.c_str());
1075 
1076  delete[] mode;
1077 
1078  outfile.close();
1079 
1080  // Remove 0-scan file
1081  if ( isc == 0) {
1082  int status = remove( l1a_name.c_str());
1083  if( status == 0) {
1084  cout << "Removing 0-scan file: " << l1a_name.c_str() << endl;
1085  } else {
1086  cout << "Error removing " << l1a_name.c_str() << endl;
1087  exit(1);
1088  }
1089  }
1090 
1091  // If not 0-scan file then list in outlist
1092  if ( isc > 0) {
1093  fout << l1a_name.c_str();
1094 
1095  if (isc == mn_scn || isc == mx_scn)
1096  fout << " 1" << endl;
1097  else
1098  fout << " 0" << endl;
1099  }
1100 
1101  // If not end of file, compute start and times for next granule
1102  if ( !endfile) {
1103  ltime = mtime;
1104  if ( ltime >= 86400) {
1105  ltime = ltime - 86400;
1106  stime = stime - 86400;
1107  iday = iday + 1;
1108 
1109  if (isleap(iyear)) {
1110  if (iday == 367) {
1111  iyear++;
1112  iday = 1;
1113  }
1114  } else {
1115  if (iday == 366) {
1116  iyear++;
1117  iday = 1;
1118  }
1119  }
1120  }
1121 
1122  mtime = ltime + mper*60;
1123 
1124  // Generate next L1A file name
1125  unixtime = (time_t) yds2unix(iyear,iday,ltime);
1126  trec = gmtime(&unixtime);
1127 
1128  if (new_naming) {
1129  strftime(datetime, NC_MAX_NAME, "%Y%m%dT%H%M%S", trec); // new convention
1130  l1a_name.assign(plat + "_VIIRS." + string(datetime) + ".L1A.nc");
1131  } else {
1132  strftime(datetime, NC_MAX_NAME, "%Y%j%H%M%S", trec); // old convention
1133  l1a_name.assign(string("V") + string(datetime) + ".L1A_" + plat + ".nc");
1134  }
1135  cout << endl << l1a_name.c_str() << endl;
1136 
1137  }
1138 
1139  } // while (!endfile)
1141 
1142  if ( outlist.compare("") != 0) fout.close();
1143 
1144  vfileStream.close();
1145 
1146  //Deallocate
1147  delete[] scdpkts[0];
1148  delete[] scdpkts;
1149 
1150  delete[] otime;
1151  delete[] atime;
1152 
1153  delete[] orb[0];
1154  delete[] orb;
1155 
1156  delete[] quat[0];
1157  delete[] quat;
1158 
1159  delete[] engdata[0];
1160  delete[] engdata;
1161 
1162  delete[] p1[0];
1163  delete[] p1;
1164 
1165  delete[] hrmets[0];
1166  delete[] hrmets;
1167 
1168  delete[] hrmet[0];
1169  delete[] hrmet;
1170 
1171  delete[] calmets[0];
1172  delete[] calmets;
1173 
1174  delete[] sd_m[0];
1175  delete[] sd_m;
1176 
1177  delete[] sv_m[0];
1178  delete[] sv_m;
1179 
1180  delete[] bb_m[0];
1181  delete[] bb_m;
1182 
1183  delete[] sd_i[0];
1184  delete[] sd_i;
1185 
1186  delete[] sv_i[0];
1187  delete[] sv_i;
1188 
1189  delete[] bb_i[0];
1190  delete[] bb_i;
1191 
1192  delete[] sd_d[0];
1193  delete[] sd_d;
1194 
1195  delete[] sv_d[0];
1196  delete[] sv_d;
1197 
1198  delete[] bb_d[0];
1199  delete[] bb_d;
1200 
1201  delete[] adcpkts[0];
1202  delete[] adcpkts;
1203 
1204  delete[] buspkts[0];
1205  delete[] buspkts;
1206 
1207  delete[] adctime;
1208  delete[] bustime;
1209 
1210  if ( gpstime != NULL) delete[] gpstime;
1211  if ( gpspkts != NULL) {
1212  delete[] gpspkts[0];
1213  delete[] gpspkts;
1214  }
1215 
1216  delete[] adstate;
1217  delete[] admandone;
1218  delete[] adfftid;
1219 
1220  delete[] mbands;
1221  delete[] ibands;
1222  delete[] dnb;
1223 
1224  delete[] pbuffer[0];
1225  delete[] pbuffer;
1226 
1227  if (exit_101) return 101; else return 0;
1228 }
1229 
1230 int convert_diary( int32_t npkts, uint8_t (*dstore)[71],
1231  int32_t *iyr, int32_t *iday,
1232  double *otime, float (*orb)[6],
1233  double *atime, float (*quat)[4]) {
1234 
1235  uint16_t ui16;
1236  uint32_t ui32;
1237 
1238  int io=0, ia=0;
1239  double ot, at;
1240 
1241  //Days since 1/1/1958
1242  memcpy( &ui16, (uint16_t *) &dstore[0][6], 2);
1243  int32_t jd0 = SWAP_2( ui16) + 2436205;
1244 
1245  jdate( jd0, iyr, iday);
1246 
1247  // Loop through packets
1248  for (int i=0; i<npkts; i++) {
1249 
1250  int32_t ioff;
1251 
1252  double sec;
1253  int16_t iy16, idy16;
1254  int32_t iy, idy, jd;
1255 
1256  // Get orbit time
1257  ccsds_to_yds( &dstore[i][15], &iy, &idy, &sec);
1258  iy16 = iy;
1259  idy16 = idy;
1260  jd = jday( iy16, 1, idy16);
1261  ot = sec + (jd - jd0)*86400;
1262  if ((ot > -10.e0) && (ot < 1728.0e2)) otime[io++]= ot;
1263 
1264  // Convert orbit vectors to floats
1265  ioff = 23;
1266  for (int j=0; j<=5; j++) {
1267  memcpy( &ui32, (uint32_t *) &dstore[i][ioff], 4);
1268  uint32_t k = SWAP_4( ui32);
1269  memcpy( &orb[i][j], &k, sizeof(float));
1270  ioff = ioff + 4;
1271  }
1272 
1273  // Get attitude time
1274  ccsds_to_yds( &dstore[i][47], &iy, &idy, &sec);
1275  iy16 = iy;
1276  idy16 = idy;
1277  jd = jday( iy16, 1, idy16);
1278  at = sec + (jd - jd0)*86400;
1279  if ((at > -10.e0) && (at < 1728.0e2)) atime[ia++]= at;
1280 
1281  // Convert attitude quaternion to floats
1282  ioff = 55;
1283  for (int j=0; j<=3; j++) {
1284  memcpy( &ui32, (uint32_t *) &dstore[i][ioff], 4);
1285  uint32_t k = SWAP_4( ui32);
1286  memcpy( &quat[i][j], &k, sizeof(float));
1287  ioff = ioff + 4;
1288  }
1289  }
1290 
1291  return 0;
1292 }
1293 
1294 
1295 int extract_adcs_bus( int adoffsets[4],
1296  int32_t nadc, uint8_t *astore[],
1297  int32_t nbus, uint8_t *bstore[],
1298  int32_t *iyr, int32_t *iday,
1299  double *adctime, double *bustime,
1300  uint8_t *adstate, uint8_t *admandone,
1301  int16_t *adfftid, uint8_t *adsolution,
1302  string& platform, uint16_t ngps,
1303  uint8_t *gstore[], double *gpstime) {
1304 
1305  uint16_t ui16;
1306 
1307  //Days since 1/1/1958
1308  memcpy( &ui16, (uint16_t *) &astore[0][6], 2);
1309  int32_t jd0 = SWAP_2( ui16) + 2436205;
1310 
1311  jdate( jd0, iyr, iday);
1312 
1313  double sec;
1314  int16_t iy16, idy16;
1315  int32_t iy, idy, jd;
1316 
1317  // Loop through packets (ADC)
1318  for (int i=0; i<nadc; i++) {
1319  ccsds_to_yds( &astore[i][6], &iy, &idy, &sec);
1320  iy16 = iy;
1321  idy16 = idy;
1322  jd = jday( iy16, 1, idy16);
1323  adctime[i] = sec + (jd - jd0)*86400;
1324 
1325  if (platform == "SNPP") {
1326  admandone[i] = (astore[i][adoffsets[2]] % 2);
1327  adfftid[i] = astore[i][adoffsets[3]] * 256 + astore[i][adoffsets[3]+1];
1328  } else if (platform == "JPSS-1") {
1329  admandone[i] = (astore[i][adoffsets[2]] % 32) / 16;
1330  adfftid[i] = astore[i][adoffsets[3]] * 256 + astore[i][adoffsets[3]+1];
1331  } else if (platform == "JPSS-2") {
1332  admandone[i] = astore[i][adoffsets[2]];
1333  adfftid[i] = astore[i][adoffsets[3]];
1334  }
1335  }
1336 
1337  // Loop through packets (BUS)
1338  for (int i=0; i<nbus; i++) {
1339  ccsds_to_yds( &bstore[i][6], &iy, &idy, &sec);
1340  iy16 = iy;
1341  idy16 = idy;
1342  jd = jday( iy16, 1, idy16);
1343  bustime[i] = sec + (jd - jd0)*86400;
1344 
1345  if (platform == "SNPP") {
1346  adstate[i] = (bstore[i][adoffsets[0]] % 32) / 4;
1347  adsolution[i] = (bstore[i][adoffsets[1]] % 32);
1348  } else if (platform == "JPSS-1") {
1349  adstate[i] = bstore[i][adoffsets[0]] / 32;
1350  adsolution[i] = (bstore[i][adoffsets[1]] % 64) / 2;
1351  } else if (platform == "JPSS-2") {
1352  adstate[i] = bstore[i][adoffsets[0]];
1353  adsolution[i] = (astore[i][adoffsets[1]] & 3);
1354  }
1355  }
1356 
1357  // Loop through packets (GPS) (JPSS-2 only)
1358  if (platform == "JPSS-2") {
1359  for (int i=0; i<ngps; i++) {
1360  ccsds_to_yds( &gstore[i][6], &iy, &idy, &sec);
1361  iy16 = iy;
1362  idy16 = idy;
1363  jd = jday( iy16, 1, idy16);
1364  gpstime[i] = sec + (jd - jd0)*86400;
1365  }
1366  }
1367 
1368  return 0;
1369 }
1370 
1371 
1372 int read_viirs_scan_packets( fstream *vfileStream, uint8_t *epacket,
1373  uint8_t (*pbuffer)[PBUFFER_SIZE],
1374  int32_t *npkts, int32_t *endfile) {
1375 
1376  // Get VIIRS scan number and start time from engineering packet
1377  int32_t iyear, iday;
1378  double stime;
1379  ccsds_to_yds( &epacket[6], &iyear, &iday, &stime);
1380  uint32_t ui32;
1381 
1382  uint32_t scnum;
1383  if ( epacket[1] == 58) {
1384  memcpy( &ui32, &epacket[48], 4);
1385  scnum = SWAP_4( ui32);
1386  } else {
1387  memcpy( &ui32, &epacket[34], 4);
1388  scnum = SWAP_4( ui32);
1389  }
1390 
1391  // Store the engineering packet in the buffer
1392  memcpy( &pbuffer[0], epacket, 9317);
1393  *npkts = 1;
1394 
1395  // Read all of the packets with this start time and scan number
1396  // and store in the packet buffer
1397 
1398  // Read the next packet
1399  int32_t apid, len = 0;
1400 
1401  read_packet( vfileStream, NULL, &len, &apid, endfile);
1402  if ( *endfile) return 0;
1403  if ( len > PBUFFER_SIZE) {
1404  cout << "Packet size " << len << " greater than buffer size: ";
1405  cout << PBUFFER_SIZE << endl;
1406  exit(1);
1407  }
1408  uint8_t *packet = new uint8_t[len];
1409 
1410  vfileStream->seekg( -6, ios_base::cur);
1411  read_packet( vfileStream, packet, &len, NULL, endfile);
1412 
1413  // Check for missing first packet of a group
1414  uint8_t first = (packet[0] & 8) / 8;
1415  while ( !first) {
1416  // memcpy( &pbuffer[*npkts][0], packet, len);
1417  // *npkts = *npkts + 1;
1418 
1419  read_packet( vfileStream, NULL, &len, &apid, endfile);
1420  if ( *endfile) return 0;
1421  if ( len > PBUFFER_SIZE) {
1422  cout << "Packet size " << len << " greater than buffer size: ";
1423  cout << PBUFFER_SIZE << endl;
1424  exit(1);
1425  }
1426 
1427  delete[] packet;
1428  packet = new uint8_t[len];
1429 
1430  vfileStream->seekg( -6, ios_base::cur);
1431  read_packet( vfileStream, packet, &len, NULL, endfile);
1432 
1433  first = (packet[0] & 8) / 8;
1434  }
1435 
1436  int32_t iyr, idy;
1437  double stm;
1438  memcpy( &ui32, &packet[34], 4);
1439  uint32_t scn = SWAP_4( ui32);
1440  ccsds_to_yds( &packet[6], &iyr, &idy, &stm);
1441 
1442  while ( (scn == scnum) && (stm == stime)) {
1443 
1444  // Get APID and number of packets in group and load packet into buffer
1445  apid = (packet[0] % 8)*256 + packet[1];
1446  uint8_t npkg = packet[14];
1447  if(*npkts >= MAX_PKTS_PER_SCAN)
1448  {
1449  cout << "L1A Algorithm: Number of packets exceeds in scan"<< MAX_PKTS_PER_SCAN << endl;
1450  exit(1);
1451  }
1452 
1453  memcpy( &pbuffer[*npkts][0], packet, len);
1454  (*npkts)++;
1455 
1456  // Read remaining packets in group
1457  int i = 0;
1458  while (i <= npkg) {
1459  int32_t apd;
1460 
1461  read_packet( vfileStream, NULL, &len, &apd, endfile);
1462  if ( *endfile) return 0;
1463 
1464  if ( len > PBUFFER_SIZE) {
1465  cout << "Packet size " << len << " greater than buffer size: ";
1466  cout << PBUFFER_SIZE << endl;
1467  exit(1);
1468  }
1469  delete[] packet;
1470  packet = new uint8_t[len];
1471 
1472  vfileStream->seekg( -6, ios_base::cur);
1473  read_packet( vfileStream, packet, &len, NULL, endfile);
1474 
1475  // Check APID; if not a match, missing packets
1476  if ( apd == apid) {
1477  if(MAX_PKTS_PER_SCAN <= *npkts)
1478  {
1479  cout << "L1A Algorithm: Number of packets exceeds in scan"<< MAX_PKTS_PER_SCAN << endl;
1480  exit(1);
1481  }
1482  memcpy( &pbuffer[*npkts][0], packet, len);
1483  // cout << "scn: " << scn << " i: " << i << " len: " << len <<
1484  // " npkts: " << *npkts << endl;
1485  (*npkts)++;
1486  i++;
1487  } else {
1488  i = npkg + 1;
1489  }
1490  }
1491 
1492  first = (packet[0] & 8) / 8;
1493  while ( !first) {
1494  // memcpy( &pbuffer[*npkts][0], packet, len);
1495  // *npkts = *npkts + 1;
1496 
1497  read_packet( vfileStream, NULL, &len, &apid, endfile);
1498  if ( *endfile) return 0;
1499  if ( len > PBUFFER_SIZE) {
1500  cout << "Packet size " << len << " greater than buffer size: ";
1501  cout << PBUFFER_SIZE << endl;
1502  exit(1);
1503  }
1504  delete[] packet;
1505  packet = new uint8_t[len];
1506 
1507  vfileStream->seekg( -6, ios_base::cur);
1508  read_packet( vfileStream, packet, &len, NULL, endfile);
1509  if ( *endfile) return 0;
1510  first = (packet[0] & 8) / 8;
1511  }
1512  memcpy( &ui32, &packet[34], 4);
1513  scn = SWAP_4( ui32);
1514  ccsds_to_yds( &packet[6], &iyr, &idy, &stm);
1515  }
1516 
1517  memcpy( epacket, packet, len);
1518  delete[] packet;
1519 
1520  // if ( len != 9318) memset( &epacket[len], 0, 9318-len);
1521 
1522  return 0;
1523 }
1524 
1525 
1526 int unpack_viirs_scan( int32_t npkts,
1527  uint8_t (*pbuffer)[PBUFFER_SIZE],
1528  uint16_t (*mbands)[16][6304],
1529  uint16_t (*ibands)[32][6400],
1530  uint16_t (*dnb)[16][4064],
1531  uint8_t (*mqfl)[16],
1532  uint8_t (*iqfl)[32],
1533  uint8_t (*dqfl)[16],
1534  uint8_t (*hrmet)[146]) {
1535 
1536  int iret = 0;
1537 
1538  // Set up band index array
1539  int32_t ibnds[] = {4, 5, 3, 2, 1, 6, 7, 9, 10, 8, 11, 13, 12, 34,
1540  16, 15, 14, 35, 31, 32, 33, 21, 22, 23, 24, 25};
1541 
1542  int32_t ipkt = 0;
1543  while (ipkt < npkts) {
1544 
1545  int32_t apid = (pbuffer[ipkt][0] % 8)*256 + pbuffer[ipkt][1];
1546 
1547  // Check for non-engineering packet
1548  if (apid != 825 && apid != 826) {
1549 
1550  // Look for header packet
1551  uint8_t jhd = (pbuffer[ipkt][0] & 8) / 8;
1552  if (jhd) {
1553 
1554  // Determine band number
1555  int32_t iap = apid - 800;
1556  if (iap > 23) iap = iap - 3;
1557 
1558  int32_t ibnd = ibnds[iap];
1559  //; print,apid,ibnd
1560 
1561  // Determine scan length
1562  int32_t nsamp = 3200;
1563  if (ibnd <= 5 || ibnd == 7 || ibnd == 13) nsamp = 6304;
1564  if (ibnd >= 21 && ibnd <= 25) nsamp = 4064;
1565  if (ibnd > 30) nsamp = 6400;
1566 
1567  // Extract HR metadata
1568  memcpy( &hrmet[iap][0], &pbuffer[ipkt][32], 146);
1569 
1570  // Get number of remaining packets in group and instrument number
1571  int32_t ngpk = pbuffer[ipkt][14];
1572  int32_t insno = pbuffer[ipkt][29];
1573  // int32_t lpkt = ipkt + ngpk
1574  ipkt++;
1575  int32_t idet = -1;
1576 
1577  // Check for M-band data in DNB packet (12/20/17 from F.Patt)
1578  if (ibnd >= 22 && ibnd <= 25) {
1579  if (pbuffer[ipkt][96] == 0 && pbuffer[ipkt][97] == 8) {
1580  idet = ngpk;
1581  cout << "M-band data in DNB packets" << endl;
1582  }
1583  }
1584 
1585  // Look through remaining packets and unpack science data
1586  while (idet < ngpk && ipkt < npkts) {
1587 
1588  // Verify same APID and extract science data
1589  int32_t apin = (pbuffer[ipkt][0] % 8)*256 + pbuffer[ipkt][1];
1590  if (apin == apid) {
1591  int16_t *scan = new int16_t[nsamp];
1592  for (int i=0; i<nsamp; i++) scan[i] = -999;
1593 
1594  uint8_t qfl = 0;
1595  int32_t ins = pbuffer[ipkt][19];
1596  idet = pbuffer[ipkt][25];
1597  // cout << "ipkt: " << ipkt << endl;
1598 
1599  // Check for valid detector index
1600  if ((idet >= 0) && (idet < ngpk) && (ins == insno)) {
1601  int status = unpack_sci( &pbuffer[ipkt][0], nsamp, scan, &qfl);
1602  iret = iret | status;
1603 
1604  // Load data into output array
1605  if (ibnd <= 16) {
1606  memcpy( &mbands[ibnd-1][idet][0], scan, nsamp*sizeof(int16_t));
1607  mqfl[ibnd-1][idet] = qfl;
1608  // cout << "idet qfl: " << idet << " "
1609  // << static_cast<unsigned>(qfl) << endl;
1610  }
1611  if (ibnd >= 21 && ibnd <= 25) {
1612  memcpy( &dnb[ibnd-21][idet][0], scan, nsamp*sizeof(int16_t));
1613  dqfl[ibnd-21][idet] = qfl;
1614  }
1615  if (ibnd >= 31) {
1616  memcpy( &ibands[ibnd-31][idet][0], scan, nsamp*sizeof(int16_t));
1617  iqfl[ibnd-31][idet] = qfl;
1618  }
1619  } else {
1620  if (ins != insno) {
1621  cout << "Incorrect instrument number for APID " << apid << endl;
1622  }
1623  }
1624  ipkt++;
1625  delete[] scan;
1626  } else {
1627  idet = ngpk;
1628  }
1629  }
1630  } else {
1631  ipkt++;
1632  }
1633  } else {
1634  ipkt++;
1635  }
1636  }
1637 
1638  // Reconstruct differenced bands
1639  // Set up index arrays
1640  int32_t *jj = new int32_t[3200];
1641  for ( int i=0; i<3200; i++) jj[i] = 2*i;
1642 
1643  int32_t ms1[] = {0,640,1008,1600,2192,2560}; // single-gain M-bands
1644  int32_t ms2[] = {639,1007,1599,2191,2559,3199}; // single-gain M-bands
1645  int32_t md1[] = {0,640,1376,3152,4928,5664}; // dual-gain M-bands
1646  int32_t md2[] = {639,1375,3151,4927,5663,6303}; // dual-gain M-bands
1647 
1648  int32_t i1[6], i2[6];
1649  for ( int i=0; i<6; i++) {
1650  i1[i] = ms1[i] * 2; // I-bands
1651  i2[i] = ms2[i] * 2 + 1; // I-bands
1652  }
1653 
1654  // Check for missing segments
1655  int32_t ik = 1;
1656  for ( int k=0; k<=5; k++) {
1657  for ( int i=0; i<=15; i++) {
1658  // Dual-gain M-bands
1659  // M3 and M5 using M4
1660  if ((mqfl[3][i] & ik) == 0 &&
1661  (mqfl[2][i] & ik) == 0) {
1662  for ( int kk=md1[k]; kk<=md2[k]; kk++) {
1663  mbands[2][i][kk] += (mbands[3][i][kk] - 16383);
1664  }
1665  } else {
1666  mqfl[2][i] = mqfl[2][i] | ik;
1667  for ( int kk=md1[k]; kk<=md2[k]; kk++) {
1668  mbands[2][i][kk] = -999;
1669  }
1670  }
1671 
1672  if ((mqfl[3][i] & ik) == 0 &&
1673  (mqfl[4][i] & ik) == 0) {
1674  for ( int kk=md1[k]; kk<=md2[k]; kk++) {
1675  mbands[4][i][kk] += (mbands[3][i][kk] - 16383);
1676  }
1677  } else {
1678  mqfl[4][i] = mqfl[4][i] | ik;
1679  for ( int kk=md1[k]; kk<=md2[k]; kk++) {
1680  mbands[4][i][kk] = -999;
1681  }
1682  }
1683 
1684  // M2 using M3
1685  if ((mqfl[2][i] & ik) == 0 &&
1686  (mqfl[1][i] & ik) == 0) {
1687  for ( int kk=md1[k]; kk<=md2[k]; kk++) {
1688  mbands[1][i][kk] += (mbands[2][i][kk] - 16383);
1689  }
1690  } else {
1691  mqfl[1][i] = mqfl[1][i] | ik;
1692  for ( int kk=md1[k]; kk<=md2[k]; kk++) {
1693  mbands[1][i][kk] = -999;
1694  }
1695  }
1696 
1697  // M1 using M2
1698  if ((mqfl[1][i] & ik) == 0 &&
1699  (mqfl[0][i] & ik) == 0) {
1700  for ( int kk=md1[k]; kk<=md2[k]; kk++) {
1701  mbands[0][i][kk] += (mbands[1][i][kk] - 16383);
1702  }
1703  } else {
1704  mqfl[0][i] = mqfl[0][i] | ik;
1705  for ( int kk=md1[k]; kk<=md2[k]; kk++) {
1706  mbands[0][i][kk] = -999;
1707  }
1708  }
1709 
1710 
1711  // Single-gain M-bands
1712  // M8 and M11 using M10
1713  if ((mqfl[9][i] & ik) == 0 &&
1714  (mqfl[7][i] & ik) == 0) {
1715  for ( int kk=ms1[k]; kk<=ms2[k]; kk++) {
1716  int16_t adj = mbands[9][i][kk] - 16383;
1717  mbands[ 7][i][kk] += adj;
1718  }
1719  } else {
1720  mqfl[ 7][i] = mqfl[ 7][i] | ik;
1721  for ( int kk=ms1[k]; kk<=ms2[k]; kk++) {
1722  mbands[ 7][i][kk] = -999;
1723  }
1724  }
1725 
1726 
1727  if ((mqfl[9][i] & ik) == 0 &&
1728  (mqfl[10][i] & ik) == 0) {
1729  for ( int kk=ms1[k]; kk<=ms2[k]; kk++) {
1730  int16_t adj = mbands[9][i][kk] - 16383;
1731  mbands[10][i][kk] += adj;
1732  }
1733  } else {
1734  mqfl[10][i] = mqfl[10][i] | ik;
1735  for ( int kk=ms1[k]; kk<=ms2[k]; kk++) {
1736  mbands[10][i][kk] = -999;
1737  }
1738  }
1739 
1740  // M14 using M15
1741  if ((mqfl[14][i] & ik) == 0 &&
1742  (mqfl[13][i] & ik) == 0) {
1743  for ( int kk=ms1[k]; kk<=ms2[k]; kk++) {
1744  uint16_t ii;
1745  memcpy( &ii, &mbands[14][i][kk], 2);
1746  mbands[13][i][kk] += (mbands[14][i][kk] - 16383);
1747  }
1748  } else {
1749  mqfl[13][i] = mqfl[13][i] | ik;
1750  for ( int kk=ms1[k]; kk<=ms2[k]; kk++) {
1751  mbands[13][i][kk] = -999;
1752  }
1753  }
1754 
1755  // I-bands differenced to M-bands
1756  // I4 using M12
1757  for (int p=0; p<2; p++) {
1758  if ((mqfl[11][i] & ik) == 0 &&
1759  (iqfl[3][2*i+p] & ik) == 0) {
1760  for ( int j=0; j<=1; j++) {
1761  for ( int kk=ms1[k]; kk<=ms2[k]; kk++) {
1762  int16_t adj = mbands[11][i][kk] - 16383;
1763  ibands[3][2*i+p] [jj[kk]+j] += adj;
1764  }
1765  }
1766  } else {
1767  iqfl[3][2*i+p] = iqfl[3][2*i+p] | ik;
1768  for ( int j=0; j<=1; j++) {
1769  for ( int kk=ms1[k]; kk<=ms2[k]; kk++) {
1770  ibands[3][2*i+p] [jj[kk]+j] = -999;
1771  }
1772  }
1773  }
1774  } // p-loop
1775 
1776 
1777  // I5 using M15
1778  for (int p=0; p<2; p++) {
1779  if ((mqfl[14][i] & ik) == 0 &&
1780  (iqfl[4][2*i+p] & ik) == 0) {
1781  for ( int j=0; j<=1; j++) {
1782  for ( int kk=ms1[k]; kk<=ms2[k]; kk++) {
1783  uint16_t ii;
1784  memcpy( &ii, &mbands[14][i][kk], 2);
1785  int16_t adj = mbands[14][i][kk] - 16383;
1786  ibands[4][2*i+p] [jj[kk]+j] += adj;
1787  }
1788  }
1789  } else {
1790  iqfl[4][2*i+p] = iqfl[4][2*i+p] | ik;
1791  for ( int j=0; j<=1; j++) {
1792  for ( int kk=ms1[k]; kk<=ms2[k]; kk++) {
1793  ibands[4][2*i+p] [jj[kk]+j] = -999;
1794  }
1795  }
1796  }
1797  } // p-loop
1798 
1799  } // M-detector loop
1800 
1801 
1802  // I-bands
1803  for ( int i=0; i<=31; i++) {
1804  // I2 using I1
1805  if ((iqfl[0][i] & ik) == 0 &&
1806  (iqfl[1][i] & ik) == 0) {
1807  for ( int kk=i1[k]; kk<=i2[k]; kk++) {
1808  ibands[1][i][kk] += (ibands[0][i][kk] - 16383);
1809  }
1810  } else {
1811  iqfl[1][i] = iqfl[1][i] | ik;
1812  for ( int kk=i1[k]; kk<=i2[k]; kk++) {
1813  ibands[1][i][kk] = -999;
1814  }
1815  }
1816 
1817  // I3 using I2
1818  if ((iqfl[1][i] & ik) == 0 &&
1819  (iqfl[2][i] & ik) == 0) {
1820  for ( int kk=i1[k]; kk<=i2[k]; kk++) {
1821  ibands[2][i][kk] += (ibands[1][i][kk] - 16383);
1822  }
1823  } else {
1824  iqfl[2][i] = iqfl[2][i] | ik;
1825  for ( int kk=i1[k]; kk<=i2[k]; kk++) {
1826  ibands[2][i][kk] = -999;
1827  }
1828  }
1829  }
1830 
1831  ik *= 2;
1832  }
1833  delete[] jj;
1834 
1835  return iret;
1836 }
1837 
1838 
1839 int unpack_viirs_cal( int32_t npkts,
1840  uint8_t (*pbuffer)[PBUFFER_SIZE],
1841  int16_t (*sdm)[16][48],
1842  int16_t (*svm)[16][48],
1843  int16_t (*bbm)[16][48],
1844  int16_t (*sdi)[32][96],
1845  int16_t (*svi)[32][96],
1846  int16_t (*bbi)[32][96],
1847  int16_t (*sdd)[64],
1848  int16_t (*svd)[64],
1849  int16_t (*bbd)[64],
1850  uint8_t *calmet) {
1851 
1852  int iret = 0;
1853 
1854  // Procedure to unpack VIIRS calibrator view data for a scan
1855 
1856  // sd = solar diffuser
1857  // sv = space view
1858  // bb = blackbody
1859 
1860  // m = M-band
1861  // i = I-band
1862  // d = DNB
1863 
1864  // Set to fill value (-999)
1865  for (int i=0; i<17; i++) {
1866  for (int j=0; j<16; j++) {
1867  for (int k=0; k<48; k++) {
1868  sdm[i][j][k] = -999;
1869  svm[i][j][k] = -999;
1870  bbm[i][j][k] = -999;
1871  }
1872  }
1873  }
1874 
1875  for (int i=0; i<5; i++) {
1876  for (int j=0; j<32; j++) {
1877  for (int k=0; k<96; k++) {
1878  sdi[i][j][k] = -999;
1879  svi[i][j][k] = -999;
1880  bbi[i][j][k] = -999;
1881  }
1882  }
1883  }
1884 
1885  for (int j=0; j<16; j++) {
1886  for (int k=0; k<64; k++) {
1887  sdd[j][k] = -999;
1888  svd[j][k] = -999;
1889  bbd[j][k] = -999;
1890  }
1891  }
1892 
1893  // Array of band values for VIIRS band control word
1894  int32_t ibnds[] =
1895  {0,21,1,2,4,3,31,32,7,5,6,13,12,34,33,10,11,8,9,35,16,17,15,14};
1896 
1897  // Find calibration packets
1898  int32_t ipkt = -1;
1899  int32_t apid = 0;
1900 
1901  while (ipkt < (npkts-1) && apid != 825) {
1902  ipkt++;
1903  apid = (pbuffer[ipkt][0] % 8)*256 + pbuffer[ipkt][1];
1904  }
1905 
1906  // Check for first packet
1907  memset( calmet, 255, 134); // Fill with 255
1908  if ((pbuffer[ipkt][0] & 8) == 8) {
1909  memcpy( calmet, &pbuffer[ipkt][32], 134);
1910  ipkt++;
1911  apid = (pbuffer[ipkt][0] % 8)*256 + pbuffer[ipkt][1];
1912  }
1913 
1914  int32_t lpd = 0;
1915  int32_t ipd = 0;
1916 
1917  // Process remaining cal packets
1918  while (ipkt < npkts && apid == 825) {
1919 
1920  // Get band number
1921  int32_t ibid = pbuffer[ipkt][24];
1922  if (ibid < 1 || ibid > 23) {
1923  cout << "ibid out of bounds: " << ibid << endl;
1924  break;
1925  }
1926 
1927  int32_t ibnd = ibnds[ibid];
1928 
1929  // Check for M4 and M5 cal data replacement
1930  // Need this logic because indicators are not reliable
1931  // Save length of DNB cal packet
1932  if (ibnd == 21) {
1933  lpd = pbuffer[ipkt][4]*256 + pbuffer[ipkt][5] + 7;
1934  ipd = ipkt;
1935  }
1936 
1937  // If length of M1, M2, M4 or M5 packet matches DNB, cal replacement
1938  if (ibnd == 1 || ibnd == 2 || ibnd == 4 || ibnd == 5) {
1939  int32_t lpkt = pbuffer[ipkt][4]*256 + pbuffer[ipkt][5] + 7;
1940 
1941  bool test = true;
1942  if (lpkt == lpd) {
1943  for ( int i=98; i<lpd; i++) {
1944  if (pbuffer[ipd][i] != pbuffer[ipkt][i]) {
1945  test = false;
1946  break;
1947  }
1948  }
1949  if (test) ibnd = ibnd + 21;
1950  }
1951  }
1952 
1953  int32_t nsamps;
1954  int32_t ndet;
1955  if (ibnd != 22 && ibnd != 23 && ibnd != 25 && ibnd != 26) {
1956  nsamps = 48;
1957  if (ibnd == 21) nsamps = pbuffer[ipkt][25];
1958  if (ibnd > 30) nsamps = 96;
1959 
1960  ndet = 16;
1961  if (nsamps == 96) ndet = 32;
1962 
1963  int16_t *sv = new int16_t[nsamps*ndet];
1964  int16_t *bb = new int16_t[nsamps*ndet];
1965  int16_t *sd = new int16_t[nsamps*ndet];
1966  //cout << "ipkt: " << ipkt << endl;
1967  //cout << "ibnd: " << ibnd << endl;
1968 
1969  int status = unpack_cal_sci( &pbuffer[ipkt][0],
1970  nsamps, ndet, sv, bb, sd);
1971  iret = iret | status;
1972 
1973  if (status == 0) {
1974  if (ibnd <= 17) {
1975  memcpy( &sdm[ibnd-1][0][0], sd, nsamps*ndet*sizeof(int16_t));
1976  memcpy( &svm[ibnd-1][0][0], sv, nsamps*ndet*sizeof(int16_t));
1977  memcpy( &bbm[ibnd-1][0][0], bb, nsamps*ndet*sizeof(int16_t));
1978  }
1979 
1980  if (ibnd == 21) {
1981  if ( nsamps < 64) {
1982  for (int i=0; i<ndet; i++) {
1983  memcpy( &sdd[i][0], &sd[i*nsamps], nsamps*sizeof(int16_t));
1984  memcpy( &svd[i][0], &sv[i*nsamps], nsamps*sizeof(int16_t));
1985  memcpy( &bbd[i][0], &bb[i*nsamps], nsamps*sizeof(int16_t));
1986  }
1987  } else {
1988  memcpy( &sdd[0][0], sd, nsamps*ndet*sizeof(int16_t));
1989  memcpy( &svd[0][0], sv, nsamps*ndet*sizeof(int16_t));
1990  memcpy( &bbd[0][0], bb, nsamps*ndet*sizeof(int16_t));
1991  }
1992  }
1993 
1994  if (ibnd >= 31) {
1995  memcpy( &sdi[ibnd-31][0][0], sd, nsamps*ndet*sizeof(int16_t));
1996  memcpy( &svi[ibnd-31][0][0], sv, nsamps*ndet*sizeof(int16_t));
1997  memcpy( &bbi[ibnd-31][0][0], bb, nsamps*ndet*sizeof(int16_t));
1998  }
1999  }
2000 
2001  delete[] sv;
2002  delete[] bb;
2003  delete[] sd;
2004  }
2005  memcpy( &calmet[4*ibid+18], &pbuffer[ipkt][94], 4);
2006 
2007  ipkt++;
2008  apid = (pbuffer[ipkt][0] % 8)*256 + pbuffer[ipkt][1];
2009  }
2010 
2011  return iret;
2012 }
2013 
2014 
2015 int unpack_sci( uint8_t *idat, int32_t nsamp, int16_t *scan, uint8_t *qfl) {
2016 
2017  int iret = 0;
2018 
2019  int32_t lsegs[] = {640,736,1776,1776,736,640};
2020  int32_t lsegs_3200[] = {640,368,592,592,368,640};
2021  int32_t lsegs_4064[] = {784,488,760,760,488,784};
2022  int32_t lsegs_6400[] = {1280,736,1184,1184,736,1280};
2023  if (nsamp == 3200) memcpy( lsegs, lsegs_3200, 6*sizeof(int32_t));
2024  if (nsamp == 4064) memcpy( lsegs, lsegs_4064, 6*sizeof(int32_t));
2025  if (nsamp == 6400) memcpy( lsegs, lsegs_6400, 6*sizeof(int32_t));
2026 
2027  uint8_t tmp[65536];
2028  uint8_t qflag = 63;
2029  // uint8_t fill[4] = {222,173,222,173};
2030  int32_t np = idat[4]*256 + idat[5];
2031 
2032  // Find first synch work offset
2033  int32_t ip = 96;
2034 
2035  // Find first synch work offset
2036  uint8_t synp[4];
2037  memcpy( synp, &idat[26], 4);
2038 
2039  // Loop through aggregations
2040  int32_t is = 0;
2041  for ( int id=0; id<6; id++) {
2042 
2043  int32_t lp = idat[ip]*256 + idat[ip+1] - 4;
2044  if ((ip+lp) > np || lp < 4) {
2045  *qfl = qflag;
2046  return 8;
2047  }
2048 
2049  // // Added 05/12/15 to avoid problem with memcpy
2050  //if (lp == -4) return 0;
2051 
2052 
2053  uint8_t chksm[4], sync[4];
2054  for ( int i=0; i<4; i++) sync[i] = idat[ip+lp+6+i];
2055  // Move compressed data to temporary array
2056  memcpy( tmp, &idat[ip+2], lp);
2057 
2058  // Check for invalid sync word, indicating rest of packet
2059  // is fill or zero
2060  int totchksum = 0;
2061  for ( int i=0; i<4; i++) totchksum += (sync[i] == synp[i]);
2062  if (totchksum != 4) {
2063  *qfl = qflag;
2064  return 8;
2065  }
2066 
2067  for ( int i=0; i<4; i++) chksm[i] = idat[ip+lp+2+i];
2068  uint8_t check = check_sum( lp/4, tmp, chksm);
2069  if ( !check) {
2070  iret = iret | 4;
2071  // continue;
2072  // return 4;
2073  }
2074 
2075  // Strip off trailing zeroes
2076  int32_t nbytes = lp;
2077  if ( idat[ip-2] >= 8) nbytes -= 2;
2078  if ( (tmp[nbytes-1] == 0) && (tmp[nbytes-2] == 0)) nbytes -= 2;
2079  // if ((odat(nbytes(id)-1,id) mod 64) eq 0) then nbytes(id) =
2080  // nbytes(id) - 1
2081 
2082  if ( nbytes > 5 && check) {
2083 
2084  static unsigned int packet_count=0;
2085  packet_count++;
2086 
2087  // pid_t pid = getpid();
2088  //stringstream pidstr;
2089  //pidstr << pid;
2090  // printf("lsegs[id]: %d nbytes: %d\n", lsegs[id], nbytes);
2091 
2092  // uncompress with rice.c
2093  // 128=RAW, 32=NN_MODE, 16=MSB, 2=CHIP
2094  int options_mask=128+32+2;
2095  int bits_per_pixel=15;
2096  int pixels_per_block=8;
2097  int pixels_per_scanline=lsegs[id];
2098  uint16_t *decryptArrRice = new uint16_t[lsegs[id]+32*16];
2099  // printf("RICE\n");
2100 
2101  long bytes_written =
2103  pixels_per_scanline, (const char*) tmp, nbytes,
2104  decryptArrRice, 2*(lsegs[id]+32*16));
2105 
2106  if ( bytes_written < 0) {
2107  cout << "Error in rice uncompress" << endl;
2108  exit(1);
2109  }
2110 
2111 #if 0
2112  // Compare Usds and rice output
2113  int argc = 7;
2114  char *argv[] = { (char *) "Usds",
2115  (char *) "-n", (char *) "15",
2116  (char *) "-j", (char *) "8",
2117  (char *) "-br", (char *) "128"};
2118  // printf("USDS\n");
2119  uint16_t *decryptArr = new uint16_t[lsegs[id]+32*16];
2120  usds(argc, argv, nbytes, tmp, decryptArr);
2121 
2122  for ( int i=0; i<lsegs[id]; i++) {
2123  uint16_t ui16;
2124  memcpy( &ui16, &decryptArr[i], sizeof(uint16_t));
2125  decryptArr[i] = SWAP_2( ui16);
2126  }
2127 
2128  for ( int i=0; i<lsegs[id]; i++) {
2129  if (decryptArr[i] != decryptArrRice[i]) {
2130  printf("%d %d %d %d\n",
2131  i, lsegs[id], decryptArr[i], decryptArrRice[i]);
2132  exit(1);
2133  }
2134  }
2135  delete decryptArr;
2136  // End compare Usds and rice
2137 #endif
2138 
2139  memcpy( &scan[is], decryptArrRice, lsegs[id]*sizeof(int16_t));
2140  uint8_t idpow = 1;
2141  for ( int i=0; i<id; i++) idpow *= 2;
2142  qflag -= idpow;
2143  delete[] decryptArrRice;
2144  }
2145  is += lsegs[id];
2146  ip += lp + 12;
2147  } // id loop
2148 
2149  *qfl = qflag;
2150 
2151  // cout << "qfl is ip: " << static_cast<unsigned>(qflag) << " " << is
2152  // << " " << ip << endl;
2153  return iret;
2154 }
2155 
2156 
2157 int unpack_cal_sci( uint8_t *idat, int32_t nsamp, int32_t ndet,
2158  int16_t *sp, int16_t *bl, int16_t *sd) {
2159 
2160  // This routine unpacks the 15-bit samples from a VIIRS middle or last
2161  // calibration packet and stores them right-justified in 2-byte arrays.
2162  // This requires external calls to the Rice decompression routine
2163  // szip_uncompress_memory() which replaces Usds.
2164 
2165  // Arguments
2166 
2167  // Name Type I/O Description
2168  // ---- ---- --- -----------
2169  // idat byte(*) I Input packet array
2170  // nsamp int I Number of data samples in packet
2171  // ndet int I Number of detectors
2172  // sp int(nsamps*16) O Output array of space view samples
2173  // bl int(nsamps*16) O Output array of blackbody samples
2174  // sd int(nsamps*16) O Output array of solar diffuser samples
2175  // iret int O Return code 0 = good
2176  // 4 = checksum failure
2177  // 8 = fill or corrupted pkt data
2178 
2179  uint8_t tmp[200];
2180  uint16_t *decryptArrRice = new uint16_t[nsamp+32*16];
2181 
2182  // Check for M-band cal data substitution by DNB
2183  int32_t nsamps = idat[25];
2184  if (nsamps <= 0) return 8;
2185 
2186  // uint8_t fill[4] = {222,173,222,173};
2187  int32_t np = idat[4]*256 + idat[5];
2188 
2189  // Find first synch work offset
2190  int32_t ip = 100;
2191 
2192  // Find first synch work offset
2193  uint8_t synp[4];
2194  memcpy( synp, &idat[26], 4);
2195 
2196  // Loop through detectors and views
2197  for ( int id=0; id<ndet; id++) {
2198 
2199  // Space view
2200  int32_t lp = idat[ip]*256+idat[ip+1] - 4;
2201  // cout << "SV id: " << id << " lp: " << lp << endl;
2202  if (ip+lp > np || lp < 4) return 8;
2203 
2204  // Check for invalid sync word
2205  uint8_t sync[4];
2206  for ( int i=0; i<4; i++) sync[i] = idat[ip+lp+6+i];
2207  int cnt = 0;
2208  for ( int i=0; i<4; i++) if (sync[i] == synp[i]) cnt++;
2209  if (cnt != 4) return 8;
2210 
2211  memcpy( tmp, &idat[ip+2], lp*sizeof(int8_t));
2212  int32_t nbytes = lp;
2213 
2214  if (idat[ip-2] >= 8) nbytes = nbytes - 2;
2215 
2216  uint8_t chksm[4];
2217  for ( int i=0; i<4; i++) chksm[i] = idat[ip+lp+2+i];
2218  uint8_t check = check_sum( lp/4, tmp, chksm);
2219  if ( !check) return 4;
2220 
2221 #if 0
2222  int argc = 7;
2223  char *argv_sp[] = { (char *) "Usds",
2224  (char *) "-n", (char *) "15",
2225  (char *) "-j", (char *) "8",
2226  (char *) "-br", (char *) "128"};
2227 
2228  uint16_t *decryptArr = new uint16_t[nsamp+32*16];
2229 
2230  usds(argc, argv_sp, nbytes, tmp, decryptArr);
2231 
2232  for ( int i=0; i<nsamp; i++) {
2233  uint16_t ui16;
2234  memcpy( &ui16, &decryptArr[i], sizeof(uint16_t));
2235  decryptArr[i] = SWAP_2( ui16);
2236  }
2237  delete decryptArr;
2238 #endif
2239 
2240  // uncompress with rice.c
2241  // 128=RAW, 32=NN_MODE, 16=MSB, 2=CHIP
2242  int options_mask=128+32+2;
2243  int bits_per_pixel=15;
2244  int pixels_per_block=8;
2245  int pixels_per_scanline=nsamp;
2246  long bytes_written;
2247 
2248  if (nbytes > 4 && check) {
2249  bytes_written =
2251  pixels_per_scanline, (const char*) tmp, nbytes,
2252  decryptArrRice, 200);
2253 
2254  if ( bytes_written < 0) {
2255  cout << "Error in rice uncompress" << endl;
2256  exit(1);
2257  }
2258 
2259  memcpy( &sp[id*nsamp], decryptArrRice, nsamp*sizeof(int16_t));
2260  }
2261 
2262  ip = ip + lp + 12;
2263 
2264  // Blackbody view
2265  lp = idat[ip]*256+idat[ip+1] - 4;
2266  // cout << "BB id: " << id << " lp: " << lp << endl;
2267  if ((ip+lp > np) || (lp < 4)) return 8;
2268 
2269  // Check for invalid sync word
2270  for ( int i=0; i<4; i++) sync[i] = idat[ip+lp+6+i];
2271  cnt = 0;
2272  for ( int i=0; i<4; i++) if (sync[i] == synp[i]) cnt++;
2273  if (cnt != 4) return 8;
2274 
2275  memcpy( tmp, &idat[ip+2], lp*sizeof(int8_t));
2276  nbytes = lp;
2277 
2278  if (idat[ip-2] >= 8) nbytes = nbytes - 2;
2279  for ( int i=0; i<4; i++) chksm[i] = idat[ip+lp+2+i];
2280 
2281  // Check for invalid sync word, indicating rest of packet
2282  // is fill or zero
2283  check = check_sum( lp/4, tmp, chksm);
2284  for ( int i=0; i<4; i++) chksm[i] = idat[ip+lp+2+i];
2285  if ( !check) return 4;
2286 
2287  // uncompress with rice.c
2288  if (nbytes > 4 && check) {
2289  bytes_written =
2291  pixels_per_scanline, (const char*) tmp, nbytes,
2292  decryptArrRice, 200);
2293 
2294  if ( bytes_written < 0) {
2295  cout << "Error in rice uncompress" << endl;
2296  exit(1);
2297  }
2298 
2299  memcpy( &bl[id*nsamp], decryptArrRice, nsamp*sizeof(int16_t));
2300  }
2301 
2302  ip = ip + lp + 12;
2303 
2304  // Solar diffuser view
2305  lp = idat[ip]*256+idat[ip+1] - 4;
2306  //cout << "SD id: " << id << " lp: " << lp << endl;
2307  if (ip+lp > np || lp < 4) return 8;
2308 
2309  // Check for invalid sync word
2310  for ( int i=0; i<4; i++) sync[i] = idat[ip+lp+6+i];
2311  cnt = 0;
2312  for ( int i=0; i<4; i++) if (sync[i] == synp[i]) cnt++;
2313  if (cnt != 4) return 8;
2314 
2315  memcpy( tmp, &idat[ip+2], lp*sizeof(int8_t));
2316  nbytes = lp;
2317 
2318  if (idat[ip-2] >= 8) nbytes = nbytes - 2;
2319  for ( int i=0; i<4; i++) chksm[i] = idat[ip+lp+2+i];
2320 
2321  check = check_sum( lp/4, tmp, chksm);
2322  for ( int i=0; i<4; i++) chksm[i] = idat[ip+lp+2+i];
2323  if ( !check) return 4;
2324 
2325  if (nbytes > 4 && check) {
2326  bytes_written =
2328  pixels_per_scanline, (const char*) tmp, nbytes,
2329  decryptArrRice, 200);
2330 
2331  if ( bytes_written < 0) {
2332  cout << "Error in rice uncompress" << endl;
2333  exit(1);
2334  }
2335 
2336  memcpy( &sd[id*nsamp], decryptArrRice, nsamp*sizeof(int16_t));
2337  }
2338 
2339  ip = ip + lp + 12;
2340  }
2341  delete[] decryptArrRice;
2342 
2343  return 0;
2344 }
2345 
2346 int read_packet( fstream *vfileStream, uint8_t *packet,
2347  int32_t *len, int32_t *apid, int32_t *endfile) {
2348 
2349  *endfile = 0;
2350  if ( vfileStream->eof()) {
2351  *endfile = 1;
2352  *len = 0;
2353  cout << "End of packet file" << endl;
2354  return 0;
2355  }
2356 
2357  // Read packet header
2358  uint8_t phead[6];
2359  if ( packet == NULL) {
2360  vfileStream->read( (char *) &phead, 6);
2361 
2362  // Get length of packet body and APID
2363  *len = phead[4]*256 + phead[5] + 1 + 6;
2364  *apid = (phead[0] % 8)*256 + phead[1];
2365 
2366  if ( vfileStream->tellg() == -1) *endfile = 1;
2367  return 0;
2368  }
2369 
2370  vfileStream->read( (char *) packet, *len);
2371 
2372  return 0;
2373 }
2374 
2375 
2376 uint8_t check_sum( int32_t nc, uint8_t *dat, uint8_t *chk) {
2377 
2378  // Function to check data against checksum
2379  // Checksum is 4 bytes computed by XOR
2380 
2381  uint8_t chks[4], tmp[4];
2382  memcpy( chks, &dat[0], 4);
2383 
2384  for ( int i=1; i<nc; i++) {
2385  memcpy( &tmp, &dat[4*i], 4);
2386  for ( int j=0; j<4; j++) chks[j] = chks[j] ^ tmp[j];
2387  }
2388 
2389  uint8_t check[4];
2390  for ( int i=0; i<4; i++) check[i] = (chk[i] == chks[i]);
2391 
2392  uint8_t check_sum = (check[0] & check[1] & check[2] & check[3]);
2393 
2394  return check_sum;
2395 }
2396 
2397 
2398 int scan_complete( uint8_t (*pbuffer)[PBUFFER_SIZE], int32_t npkts) {
2399 
2400  int icmp = 0;
2401  int32_t mpkts;
2402 
2403  // Find first science header packet in file
2404  int32_t i = 0;
2405  while ( (pbuffer[i][0] != 11) || (pbuffer[i][1] == 58)) i++;
2406 
2407  // Get VIIRS mode
2408  uint8_t mode = pbuffer[i][46];
2409 
2410  // If Night mode
2411  if ( mode == 5) {
2412  mpkts = 244;
2413  // Need to check for M11 and DNB MGS, LGS, HGA, HGB packets
2414  for ( int i=0; i<npkts; i++) {
2415  if (pbuffer[i][0] == 11) {
2416  if (pbuffer[i][1] == 42) mpkts = mpkts + 17; // M11
2417  if (pbuffer[i][1] == 54) mpkts = mpkts + 17; // DNB MGS
2418  if (pbuffer[i][1] == 55) mpkts = mpkts + 17; // DNB LGS
2419  if (pbuffer[i][1] == 59) mpkts = mpkts + 17; // DNB HGA
2420  if (pbuffer[i][1] == 60) mpkts = mpkts + 17; // DNB HGB
2421  }
2422  }
2423 
2424  } else {
2425  // Else assume day mode
2426  mpkts = 479;
2427  }
2428 
2429  if (npkts != mpkts) icmp = 2;
2430 
2431  return icmp;
2432 }
#define PBUFFER_SIZE
Definition: l1agen_oci.h:8
int unpack_sci(uint8_t *idat, int32_t nsamp, int16_t *scan, uint8_t *qfl)
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
int createl1(char *l1_filename, uint32_t nSC, uint32_t imgWidth, uint32_t imgHeight, uint32_t fndWidth, uint32_t fndHeight)
function jd(i, j, k)
Definition: jd.f:2
*********************************************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
int read_packet(fstream *vfileStream, uint8_t *packet, int32_t *len, int32_t *apid, int32_t *endfile)
int convert_diary(int32_t npkts, uint8_t(*dstore)[71], int32_t *iyr, int32_t *iday, double *otime, float(*orb)[6], double *atime, float(*quat)[4])
#define NULL
Definition: decode_rs.h:63
int bpktsize
Definition: l1agen_oci.h:54
MOD_PR01 Production producing one five minute granule of output data in each run It can be configured to produce as many as three five minute granules per run Each execution with one construction record and one date file for each dataset In normal these are created by which splits them out of the hour datasets For LANCE they are created by which merges all session MODIS L0 datasets overlapping the requested time and extracts from the merged data those packets which fall within that time period Each scan of data is stored in the L1A granule that covers the start time of that scan
Definition: MOD_PR01_pr.txt:19
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
#define VERSION
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
#define SWAP_4(x)
Definition: common.h:18
float tm[MODELMAX]
#define MAX_PKTS_PER_SCAN
int jdate(int32_t julian, int32_t *year, int32_t *doy)
Definition: jdate.c:5
int32_t jday(int16_t i, int16_t j, int16_t k)
Definition: jday.c:4
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 thereby resolving MODur00108 Changed header guard macro names to avoid reserved name resolving MODur00104 Maneuver list file for Terra satellite was updated to include data from Jecue DuChateu Maneuver list files for both Terra and Aqua were updated to include two maneuvers from recent IOT weekly reports The limits for Z component of angular momentum was and to set the fourth GEO scan quality flag for a scan depending upon whether or not it occurred during one of them Added _FillValue attributes to many and changed the fill value for the sector start times from resolving MODur00072 Writes boundingcoordinate metadata to L1A archived metadata For PERCENT *ECS change to treat rather resolving GSFcd01518 Added a LogReport Changed to create the Average Temperatures vdata even if the number of scans is
Definition: HISTORY.txt:301
def remove(file_to_delete)
Definition: ProcUtils.py:319
int usds(int argc, char *argv[], int32_t inBytes, uint8_t *encryptData, uint16_t *decryptData)
int ccsds_to_yds(uint8_t *cctime, int32_t *iyear, int32_t *iday, double *sec)
Definition: ccsds_to_yds.c:5
int extract_adcs_bus(int adoffsets[4], int32_t nadc, uint8_t *astore[], int32_t nbus, uint8_t *bstore[], int32_t *iyr, int32_t *iday, double *adctime, double *bustime, uint8_t *adstate, uint8_t *admandone, int16_t *adfftid, uint8_t *adsolution, string &platform, uint16_t ngps, uint8_t *gstore[], double *gpstime)
def mtime(the_file)
Definition: ProcUtils.py:344
int gpktsize
Definition: l1agen_viirs.h:30
data_t tmp
Definition: decode_rs.h:74
int pixels_per_block[8]
Definition: rice.h:242
int unpack_viirs_cal(int32_t npkts, uint8_t(*pbuffer)[PBUFFER_SIZE], int16_t(*sdm)[16][48], int16_t(*svm)[16][48], int16_t(*bbm)[16][48], int16_t(*sdi)[32][96], int16_t(*svi)[32][96], int16_t(*bbi)[32][96], int16_t(*sdd)[64], int16_t(*svd)[64], int16_t(*bbd)[64], uint8_t *calmet)
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
long szip_uncompress_memory(int new_options_mask, int new_bits_per_pixel, int new_pixels_per_block, int new_pixels_per_scanline, const char *in, long in_bytes, void *out, long out_pixels)
uint8_t check_sum(int32_t nc, uint8_t *dat, uint8_t *chk)
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 unpack_cal_sci(uint8_t *idat, int32_t nsamp, int32_t ndet, int16_t *sp, int16_t *bl, int16_t *sd)
Definition: jd.py:1
int bits_per_pixel[8]
Definition: rice.h:241
int32 ioff
int main(int argc, char *argv[])
int scan_complete(uint8_t(*pbuffer)[PBUFFER_SIZE], int32_t npkts)
subroutine stm
Definition: 6sm1.f:6698
int isleap(int year)
Definition: isleap.c:3
integer, parameter double
#define SWAP_2(x)
int write_eng_data(int32_t isc, uint8_t(*engdata)[9318])
Definition: l1aFile.cpp:835
const char * str
Definition: l1c_msi.cpp:35
int read_viirs_scan_packets(fstream *vfileStream, uint8_t *epacket, uint8_t(*pbuffer)[PBUFFER_SIZE], int32_t *npkts, int32_t *endfile)
int EV_APIDs
Definition: l1agen_oci.h:55
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
int apktsize
Definition: l1agen_oci.h:53
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
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude resolving resolving GSFcd00179 Corrected handling of fill values for[Sensor|Solar][Zenith|Azimuth] resolving MODxl01751 Changed to validate LUT version against a value retrieved from the resolving MODxl02056 Changed to calculate Solar Diffuser angles without adjustment for estimated post launch changes in the MODIS orientation relative to incidentally resolving defects MODxl01766 Also resolves MODxl01947 Changed to ignore fill values in SCI_ABNORM and SCI_STATE rather than treating them as resolving MODxl01780 Changed to use spacecraft ancillary data to recognise when the mirror encoder data is being set by side A or side B and to change calculations accordingly This removes the need for seperate LUTs for Side A and Side B data it makes the new LUTs incompatible with older versions of the and vice versa Also resolves MODxl01685 A more robust GRing algorithm is being which will create a non default GRing anytime there s even a single geolocated pixel in a granule Removed obsolete messages from seed as required for compatibility with version of the SDP toolkit Corrected test output file names to end in per delivery and then split off a new MYD_PR03 pcf file for Aqua Added AssociatedPlatformInstrumentSensor to the inventory metadata in MOD01 mcf and MOD03 mcf Created new versions named MYD01 mcf and MYD03 where AssociatedPlatformShortName is rather than Terra The program itself has been changed to read the Satellite Instrument validate it against the input L1A and LUT and to use it determine the correct files to retrieve the ephemeris and attitude data from Changed to produce a LocalGranuleID starting with MYD03 if run on Aqua data Added the Scan Type file attribute to the Geolocation copied from the L1A and attitude_angels to radians rather than degrees The accumulation of Cumulated gflags was moved from GEO_validate_earth_location c to GEO_locate_one_scan c
Definition: HISTORY.txt:464
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
int i
Definition: decode_rs.h:71
#define EV_APIDs
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
int k
Definition: decode_rs.h:73
int unpack_viirs_scan(int32_t npkts, uint8_t(*pbuffer)[PBUFFER_SIZE], 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], uint8_t(*hrmet)[146])
float p[MODELMAX]
Definition: atrem_corl1.h:131
std::string platform
Definition: l1agen_oci.h:52
subroutine bbm
Definition: 6sm1.f:3281