OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
common.cpp
Go to the documentation of this file.
1 #include <algorithm>
2 #include <iterator>
3 
4 #include "common.h"
5 
6 using namespace std;
7 
8 // Modification history:
9 // Programmer Organization Date Ver Description of change
10 // ---------- ------------ ---- --- ---------------------
11 // Joel Gales FutureTech 08/02/19 0.10 Original development
12 // Liang Hong SAIC 04/14/22 0.20 l1agen_oci v1.03.00
13 // Liang Hong SAIC 04/24/22 0.21 l1agen_oci v1.03.02
14 // Liang Hong SAIC 05/05/22 0.30 l1agen_oci v1.04.00
15 
16 
17 int get_band_dims( uint8_t *apacket,
18  uint16_t &ncp, uint16_t &nbb, uint16_t &nrb,
19  uint16_t &nsp, uint16_t &ndc, uint16_t &nds,
20  uint16_t *btaps, uint16_t *rtaps, itab *itable) {
21 
22  // Extract spatial aggregation table and compute numbers of pixels
23  short ioff = 36;
24  short nagg[4] = {1,2,4,8};
25  ncp = 0;
26  nsp = 0;
27  ndc = 0;
28  nds = 0;
29 
30  for (size_t i=0; i<10; i++) {
31  itable[i].dtype = apacket[ioff+3] % 16;
32  itable[i].iagg = apacket[ioff+2] % 4;
33  itable[i].lines = apacket[ioff]*256 + apacket[ioff+1];
34  ioff += 4;
35 
36  if (itable[i].dtype > 0 && itable[i].dtype <= 14 && itable[i].dtype != 10) { // Changed dtype<=12 to 14, LH, 3/30/2022
37  if (itable[i].dtype == 2) {
38  ndc += itable[i].lines / nagg[itable[i].iagg];
39  nds += itable[i].lines / 8;
40  } // else { Changed to include dark pixels, Liang Hong, 5/12/2020
41  ncp += itable[i].lines / nagg[itable[i].iagg];
42  nsp += itable[i].lines / 8;
43  // }
44  }
45  }
46 
47  // to ensure that the science and dark count arrays will be created with at least one pixel
48  if (ncp == 0) {
49  ncp = 1;
50  nsp = 1;
51  }
52 
53  if (ndc == 0) {
54  ndc = 1;
55  nds = 1;
56  }
57 
58 
59  ioff += 4;
60 
61  // Extract spectral aggregation and compute numbers of bands
62  // Tap enable flags
63  short btap = apacket[ioff+2]*256 + apacket[ioff+3];
64  short rtap = apacket[ioff]*256 + apacket[ioff+1];
65 
66  // Tap aggregation factors
67  uint32_t bagg;
68  uint32_t ragg;
69  memcpy( &bagg, &apacket[ioff+8], sizeof(uint32_t));
70  memcpy( &ragg, &apacket[ioff+4], sizeof(uint32_t));
71  bagg = SWAP_4( bagg);
72  ragg = SWAP_4( ragg);
73 
74  // Compute number of bands for enabled taps
75  // Bands are in reverse spectral order
76  nbb = 0;
77  nrb = 0;
78  uint16_t ken = 1;
79  uint32_t kag = 3;
80  uint32_t lag = 1;
81 
82  // for (size_t i=0; i<16; i++) {
83  for (int i=15; i>=0; i--) {
84  btaps[i] = (btap & ken) / ken;
85  if (btaps[i]) nbb += 32 / nagg[(bagg & kag) / lag];
86  rtaps[i] = (rtap & ken) / ken;
87  if (rtaps[i]) nrb += 32 / nagg[(ragg & kag) / lag];
88  ken *= 2;
89  kag *= 4;
90  lag *= 4;
91  }
92 
93  return 0;
94 }
95 
96 
97 int get_anc_packet_time( uint8_t *apacket, int32_t &iyear, int32_t &iday,
98  double &stime) {
99 
100  // Unpack and convert the CCSDS segmented time code
101  // from the OCI ancillary packet
102 
103  // Get day count since Jan. 1, 1958 (Julian day 2436205)
104  // sec58 = seconds since 0 UT Jan. 1, 1958
105  short int toff = 28;
106  uint32_t sec58;
107  memcpy( &sec58, &apacket[toff], sizeof(uint32_t));
108  sec58 = SWAP_4( sec58);
109 
110  double dbl58 = (double) sec58;
111  int leap = leapseconds_since_1993(dbl58) + 27;
112  sec58 -= leap;
113 
114  // Convert to year and day
115  iday = sec58 / 86400;
116  int32_t jd = iday + 2436205; // Jan. 1, 1958 is Julian day 2436205
117  jdate( jd, &iyear, &iday);
118 
119  // Get microseconds
120  uint32_t usec;
121  memcpy( &usec, &apacket[toff+4], sizeof(uint32_t));
122  usec = SWAP_4( usec);
123  usec = usec / 4096; // 20 MSBs used, last 12 are spares
124 
125  uint32_t isec = sec58 % 86400;
126  stime = isec + ((double) usec) * 1e-6;
127 
128  return 0;
129 }
130 
131 
132 int read_oci_scan_packets( fstream *tfileStream, uint8_t *apacket,
133  uint8_t (*pbuffer)[PKTSIZE],
134  uint32_t &npkts, int32_t &spnum,
135  int32_t &ancind, vector<int32_t> &tlmind,
136  uint8_t &seqerr, int32_t &endfile) {
137 
138  // int pos = tfileStream->tellg();
139 
140  uint32_t apidmin = 636; // ver
141  uint32_t apidmax = 745; // ver 1.00.00, LH, 1/7/2022
142  uint32_t ui32;
143  uint32_t len;
144  uint32_t maxpkts = 30000; // ver 0.20, LH, 4/14/2022
145 
146  // Ancillary packet APID
147  static uint32_t apida = 636;
148 
149  // APIDs with time fields and spin numbers
150  static uint32_t apidt[8] = {711,712,713,715,716,717,721,723}; // telemetry APIDs with time fields and spin numbers, ver 0.30, LH, 5/5/2022
151 
152  // APIDs with spin numbers but no time fields
153  static uint32_t apidn[2] = {700,720};
154 
155  // Get OCI spin number from first packet of next scan
156  uint32_t apid = (apacket[0] % 8) * 256 + apacket[1];
157 
158  npkts = 0;
159  tlmind.clear();
160  ancind = -1;
161  //int spne = 0;
162 
163  if ( endfile) return 0; // LH, 4/24/2022, v1.03.02
164 
165  if (apid == apida) {
166  // Ancillary packet
167  memcpy( &ui32, &apacket[24], 4);
168  spnum = SWAP_4( ui32);
169  } else if (apid == apidn[0] || apid == apidn[1]) {
170  // Science Packet without time field, ignore SWIR packets for now
171  memcpy( &ui32, &apacket[6], 4);
172  spnum = SWAP_4( ui32);
173  // } else if (apid == apidt[0] || apid == apidt[1] || apid == apidt[2] ||apid == apidt[3]) {
174  } else if (std::find(std::begin(apidt), std::end(apidt), apid) != std::end(apidt)) {
175  // Packet with time field
176  memcpy( &ui32, &apacket[12], 4);
177  spnum = SWAP_4( ui32);
178  }
179 
180  // uint32_t spn = spnum;
181  // uint32_t spnt = spnum;
182  int32_t spn = spnum;
183  int32_t spnt = spnum;
184  uint8_t *packet = apacket;
185 
186  len = apacket[4] * 256 + apacket[5] + 7;
187 
188  int prev_pseq = 0;
189  seqerr = 0;
190 
191  // Read all of the packets with this spin number
192  // and store in the packet buffer
193  while (spn <= spnum && spnt <= (spnum+1) && (npkts < maxpkts)) {
194 
195  // Check for packet out of order
196  // Load packet into buffer
197  memcpy( &pbuffer[npkts][0], packet, len);
198  apid = (packet[0] % 8) * 256 + packet[1];
199 
200  // Check science packet sequence numbers, LH 11/20/2020
201  if (apid==apidn[0]) {
202  int pseq = (pbuffer[npkts][2] % 64)*256 + pbuffer[npkts][3];
203  if ( (prev_pseq>0) && ((pseq-prev_pseq) != 1 && (pseq-prev_pseq) != -16383)) {
204  // cout<<"npkts="<<npkts<<"pseq,pseq-prev_pseq="<<pseq<<","<<pseq-prev_pseq<<endl;
205  seqerr = 1;
206  }
207  prev_pseq = pseq;
208  }
209 
210  if (apid == apida) ancind = npkts;
211  // if (pos >= 527223898) {
212  // pos = tfileStream->tellg();
213  // cout << pos << " " << apid << " " << apida << " " << ancind
214  // << spnum << " " << spn << " " << spnt << endl;
215  //}
216 
217  if (apid >= apidmin & apid <= apidmax &&
218  apid != apidn[0] && apid != apidn[1]) {
219  tlmind.push_back(npkts);
220  }
221  npkts++;
222  if (npkts == maxpkts) {
223  cout << "Maximum number of packets: " << maxpkts
224  << " exceeded." << endl;
225  // exit (1); // Liang Hong, 08/19/2020
226  }
227  //cout << apid << " " << npkts << endl;
228 
229  // Read next packet
230  read_packet( tfileStream, NULL, len, apid, endfile);
231  if ( endfile) return 0;
232 
233  if ( len > PKTSIZE) {
234  cout << "Packet size > " << PKTSIZE << " (" << len << ")" << endl;
235  uint8_t *dummy_buf = new uint8_t[len];
236  read_packet( tfileStream, dummy_buf, len, apid, endfile);
237  delete[] dummy_buf;
238  // exit(1);
239  } else {
240  read_packet( tfileStream, packet, len, apid, endfile);
241  apid = (packet[0] % 8) * 256 + packet[1];
242  }
243 
244  while (apid < apidmin || apid > apidmax) {
245  read_packet( tfileStream, NULL, len, apid, endfile);
246  if ( endfile) return 0;
247 
248  if ( len > PKTSIZE) {
249  cout << "Packet size > " << PKTSIZE << " (" << len << ")" << endl;
250  uint8_t *dummy_buf = new uint8_t[len];
251  read_packet( tfileStream, dummy_buf, len, apid, endfile);
252  delete[] dummy_buf;
253  // exit(1);
254  } else {
255  read_packet( tfileStream, packet, len, apid, endfile);
256  apid = (packet[0] % 8) * 256 + packet[1];
257  }
258  }
259 
260  // Get spin number
261  if (apid == apida) {
262  memcpy( &ui32, &packet[24], 4);
263  spn = SWAP_4( ui32);
264  } else if (apid == apidn[0] || apid == apidn[1]) { // ver 1.00.01
265  memcpy( &ui32, &packet[6], 4);
266  spn = SWAP_4( ui32);
267 // } else if (apid == apidt[0] || apid == apidt[1] || apid == apidt[2] || apid == apidt[3]) {
268  } else if (std::find(std::begin(apidt), std::end(apidt), apid) != std::end(apidt)) {
269  memcpy( &ui32, &packet[12], 4);
270  spnt = SWAP_4( ui32);
271  } // if (apid == apidn[0] || apid == apidn[1]) {
272 
273  } // while (spn <= spnum && spnt <= spnum)
274 
275  // Report spin out of order
276  // if (spn < spnum)
277  // cout << "Next packet spin number: " << spn
278  // << " out of order for spin: " << spnum << endl;
279  // cout << "npkts: " << npkts << endl;
280 
281  return 0;
282 }
283 
284 
285 int anc_compare( uint8_t *apacket0, uint8_t *apacket) {
286  int anc_compare = 1;
287 
288  double stime;
289  int32_t iyear, iday;
290  uint32_t ui32;
291 
292  if (apacket[15] > 0) return anc_compare; // ancillary packet without valid mode table, v0.20
293 
294  // Compare spatial data collection fields
295  int ioff = 36;
296  size_t ilen = 40;
297 
298  uint16_t aggi = 0;
299  for (size_t i=0; i<ilen; i++)
300  if (apacket[ioff+i] != apacket0[ioff+i]) aggi++;
301 
302  if (aggi > 0) {
303  get_anc_packet_time( apacket, iyear, iday, stime);
304  memcpy( &ui32, &apacket[24], 4);
305  int32_t spn = SWAP_4( ui32);
306  uint16_t ih = (uint16_t) floor(stime/3600);
307  uint16_t mn = (uint16_t) floor((stime - ih*3600)/60);
308  uint16_t sec = (uint16_t) floor(stime - ih*3600 - mn*60);
309  cout << "Spatial table change at: spin="<<spn<<", "
310  << ih << ":" << mn << ":" << sec << endl;
311  anc_compare = 0;
312  }
313 
314  // Compare spectral data collection fields
315  // int joff = 76;
316  //size_t jlen = 16;
317  int joff = 80;
318  size_t jlen = 12;
319 
320  uint16_t aggj = 0;
321  for (size_t i=0; i<jlen; i++)
322  if (apacket[joff+i] != apacket0[joff+i]) aggj++;
323 
324  if (aggj > 0) {
325  get_anc_packet_time( apacket, iyear, iday, stime);
326  memcpy( &ui32, &apacket[24], 4);
327  int32_t spn = SWAP_4( ui32);
328  uint16_t ih = (uint16_t) floor(stime/3600);
329  uint16_t mn = (uint16_t) floor((stime - ih*3600)/60);
330  uint16_t sec = (uint16_t) floor(stime - ih*3600 - mn*60);
331  cout << "Spectral table change at: spin="<<spn<<", "
332  << ih << ":" << mn << ":" << sec << endl;
333  anc_compare = 0;
334  }
335 
336  return anc_compare;
337 }
338 
339 
340 int read_packet( fstream *tfileStream, uint8_t *packet,
341  uint32_t &len, uint32_t &apid, int32_t &endfile) {
342 
343  if ( tfileStream->eof()) {
344  endfile = 1;
345  len = 0;
346  cout << "End of packet file" << endl;
347  return 0;
348  }
349 
350  // Read packet header
351  uint8_t phead[6];
352  if ( packet == NULL) {
353  tfileStream->read( (char *) &phead, 6);
354 
355  // Get length of packet body and APID
356  len = phead[4]*256 + phead[5] + 1 + 6;
357  apid = (phead[0] % 8)*256 + phead[1];
358 
359  if ( tfileStream->tellg() == -1) endfile = 1;
360  tfileStream->seekg( -6, ios_base::cur);
361  return 0;
362  }
363  tfileStream->read( (char *) packet, len);
364  //cout << tfileStream->tellg() << endl;
365 
366  return 0;
367 }
368 
369 
370 int get_swir_mode( uint8_t (*pbuffer)[PKTSIZE],
371  uint32_t npkts, uint16_t &smode) {
372 
373  // Look for a SWIR band packet
374 
375  // smode = 0;
376  for (size_t ipkt=0; ipkt<npkts; ipkt++) {
377  uint32_t apid = (pbuffer[ipkt][0] % 8) * 256 + pbuffer[ipkt][1];
378  // if (npkts == 5) cout << "apid: " << apid << endl;
379  if ( apid == 720) {
380  // Get mode from packet
381  uint8_t smeta = pbuffer[ipkt][12];
382  smode = (smeta % 64) / 16;
383  return 0;
384  }
385  }
386 
387  return 0;
388  // cout << "SWIR mode not found" << endl;
389  //exit(1);
390 }
391 
int get_swir_mode(uint8_t(*pbuffer)[PKTSIZE], uint32_t npkts, uint16_t &smode)
Definition: common.cpp:370
short lines
Definition: common.h:12
#define NULL
Definition: decode_rs.h:63
short dtype
Definition: common.h:10
#define SWAP_4(x)
Definition: common.h:18
int jdate(int32_t julian, int32_t *year, int32_t *doy)
Definition: jdate.c:5
int leapseconds_since_1993(double tai93time)
Definition: leapsecond.c:58
int read_packet(fstream *tfileStream, uint8_t *packet, uint32_t &len, uint32_t &apid, int32_t &endfile)
Definition: common.cpp:340
int get_anc_packet_time(uint8_t *apacket, int32_t &iyear, int32_t &iday, double &stime)
Definition: common.cpp:97
Definition: jd.py:1
int32 ioff
integer, parameter double
int32_t ih
Definition: atrem_corl1.h:161
int anc_compare(uint8_t *apacket0, uint8_t *apacket)
Definition: common.cpp:285
dtype
Definition: DDataset.hpp:31
int read_oci_scan_packets(fstream *tfileStream, uint8_t *apacket, uint8_t(*pbuffer)[PKTSIZE], uint32_t &npkts, int32_t &spnum, int32_t &ancind, vector< int32_t > &tlmind, uint8_t &seqerr, int32_t &endfile)
Definition: common.cpp:132
Definition: common.h:9
short iagg
Definition: common.h:11
logical function leap(YEAR)
Definition: leap.f:10
int i
Definition: decode_rs.h:71
#define PKTSIZE
Definition: common.h:7
int get_band_dims(uint8_t *apacket, uint16_t &ncp, uint16_t &nbb, uint16_t &nrb, uint16_t &nsp, uint16_t &ndc, uint16_t &nds, uint16_t *btaps, uint16_t *rtaps, itab *itable)
Definition: common.cpp:17