OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l0info_oci.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 
4 __version__ = '2.6.0_2023-02-09'
5 
6 __dtypes__ = ['','','_DARK','_SOL-D','_SOL-M','_LIN','_LUN','_DIAG','_STAT',
7  '_SPEC','','_SNAP-X','_SNAP-I','_SPCA','_LUN-ST']
8 
9 import numpy as np
10 from l0info_utils import read_packet, read_apid, get_anc_packet_time, is_bad_packet
11 
12 def get_band_dims(apacket):
13 
14 # extract aggregation information and compute data dimensions from ancillary packet
15 
16 # Arguments
17 #
18 # Name Type I/O Description
19 # ---- ---- --- -----------
20 # apacket byte(*) I Ancillary packet array
21 # ncp int O Number of CCD band pixels
22 # nbb int O Number of blue CCD bands
23 # nrb int O Number of red CCD bands
24 # nsp int O Number of SWIR band pixels
25 # ndc int O Number of CCD dark collect pixels
26 # nds int O Number of SWIR dark collect pixels
27 # btaps int O Blue CCD tap enable flags
28 # rtaps int O Red CCD tap enable flags
29 # itable struct O Spatial aggregation table
30 
31 # orig: Frederick S. Patt, SAIC, 1 August 2018
32 
33  # Create spatial aggregation table structure
34  itable = np.zeros(10, dtype={'names':('dtype', 'iagg', 'lines'),'formats':('i4','i4','i4')})
35 
36  # Extract spatial aggregation table and compute numbers of pixels
37  ioff = 36
38  nagg = [1,2,4,8]
39  ncp = 0
40  nsp = 0
41  ndc = 0
42  nds = 0
43  for i in range(0,10):
44  itable['dtype'][i] = apacket[ioff+3]%16
45  itable['iagg'][i] = apacket[ioff+2]%4
46  itable['lines'][i] = apacket[ioff]*256 + apacket[ioff+1]
47  ioff = ioff + 4
48  if ((itable['dtype'][i] > 0) and (itable['dtype'][i] <= 12) and (itable['dtype'][i] != 10)):
49  if (itable['dtype'][i] == 2):
50  ndc = ndc + itable['lines'][i]/nagg[itable['iagg'][i]]
51  nds = nds + itable['lines'][i]/8
52  ncp = ncp + itable['lines'][i]/nagg[itable['iagg'][i]]
53  nsp = nsp + itable['lines'][i]/8
54  if (ncp == 0):
55  ncp = 1
56  nsp = 1
57 
58  if (ndc == 0):
59  ndc = 1
60  nds = 1
61 
62  ioff = ioff + 4
63 
64  # Extract spectral aggregation and compute numbers of bands
65  # Tap enable flags
66  btap = apacket[ioff+2]*256 + apacket[ioff+3]
67  rtap = apacket[ioff]*256 + apacket[ioff+1]
68  btaps = np.zeros(16)
69  rtaps = np.zeros(16)
70 
71  # Tap aggregation factors
72  bagg = int.from_bytes(apacket[ioff+8:ioff+12],'big')
73  ragg = int.from_bytes(apacket[ioff+4:ioff+8],'big')
74 
75  baggs = np.zeros(16)
76  raggs = np.zeros(16)
77 
78  # Compute number of bands for enabled taps
79  nbb = 0
80  nrb = 0
81  ken = 1
82  kag = 3
83  lag = 1
84 
85  for i in range(15,-1,-1):
86  btaps[i] = np.bitwise_and(btap, ken)/ken
87  if (btaps[i]):
88  baggs[i] = nagg[int(np.bitwise_and(bagg, kag)/lag)]
89  nbb = nbb + 32/baggs[i]
90 
91  rtaps[i] = np.bitwise_and(rtap, ken)/ken
92  if (rtaps[i]):
93  raggs[i] = nagg[int(np.bitwise_and(ragg, kag)/lag)]
94  nrb = nrb + 32/raggs[i]
95 
96  ken = ken*2
97  kag = kag*4
98  lag = lag*4
99 
100  return ncp,nbb,nrb,nsp,ndc,nds,btaps,rtaps,itable,baggs,raggs
101 
102 def anc_compare(apacket0,apacket):
103 
104 # function to compare spatial and spectral data collection parameters
105 # from two OCI ancillary data packets
106 
107 # Arguments
108 #
109 # Name Type I/O Description
110 # ---- ---- --- -----------
111 # apacket0(*) byte I Ancillary packet from first spin
112 # apacket(*) byte I Ancillary packet from next spin
113 
114 # Returns 1 (TRUE) if packets agree, 0 if not
115 
116  anc_compare = 1
117  strmsg = ""
118  # Compare spatial data collection fields
119  ioff = 36
120  ilen = 40
121  if apacket[ioff:ioff+ilen] != apacket0[ioff:ioff+ilen]:
122  c_time = get_anc_packet_time(apacket)
123  strmsg += "\nSpatial table change at %s" % c_time.strftime('%Y-%m-%dT%H:%M:%S.%f')
124  anc_compare = 0
125 
126  # Compare spectral data collection fields
127  joff = 80
128  jlen = 12
129  if apacket[joff:joff+jlen] != apacket0[joff:joff+jlen]:
130  c_time = get_anc_packet_time(apacket)
131  strmsg += "\nSpectral table change at %s" % c_time.strftime('%Y-%m-%dT%H:%M:%S.%f')
132  anc_compare = 0
133 
134  return anc_compare, strmsg
135 
136 def is_bad_apid(apid,fh):
137  if apid == -1:
138  return False
139  if (apid < 550) or (apid > 749):
140  print("Invalid packet header at byte %d."%fh.tell())
141  return True
142  else:
143  return False
144 
145 def get_oci_data_type(fpacket):
146  # To determine the OCI data type from and ancillary packet
147  # Returns: dtype (1 - 12) if valid ancillary packet, -1 otherwise
148 
149  # Check APID
150  apid = read_apid(fpacket)
151  if (apid != 636): return -1
152 
153  dtypes = np.zeros(10)-1
154  ioff = 36
155  for i in range(0,10):
156  dtypes[i] = fpacket[ioff+3] % 16
157  ioff = ioff + 4
158  kd = np.argwhere((dtypes != 2) & (dtypes != 10)) # Exclude dark and no processing types
159  dtype = np.max(dtypes[kd])
160 
161  return int(dtype)
162 
163 
164 def l0info_oci(args, fh, output, bDSB):
165  # procedure to get start and end times from Level-0 packet files for OCI
166  print("Running l0info_oci (version: %s) \n" % __version__)
167 
168  dtype = -1
169  str_stime = ''
170  str_etime = ''
171 
172  status = 0
173  if args.verbose:
174  print("Reading OCI science data file.")
175 
176  bSPW = False
177  lpoint = 0
178  if bDSB:
179  # chead = fh.read(64)
180  lpoint = 64
181  bSPW = True
182  fh.seek(lpoint)
183 
184  # Get first ancillary packet
185  apid = 0
186  packetLength = 8
187  while (apid != 636) and (packetLength > 7):
188  try:
189  fpacket, packetLength = read_packet(fh, bSPW)
190  apid = read_apid(fpacket)
191  if is_bad_apid(apid,fh): return 104
192  except:
193  return 103
194  if is_bad_packet(packetLength,fh): return 104
195 
196  # If no ancillary packets, rewind and get times from HKT packets
197  if fpacket is None:
198  print('No science packets found in file.')
199  status = 110
200 
201  fh.seek(lpoint)
202  apid = 0
203  packetLength = 8
204  ccsec = 0
205  # while ((apid < 550) or (apid > 750) or (apid == 558)) and (packetLength > 8):
206  while (ccsec < 1900000000) and (packetLength>7):
207  fpacket, packetLength = read_packet(fh, bSPW)
208  if fpacket:
209  apid = read_apid(fpacket)
210  else:
211  continue
212  ccsec = int.from_bytes(fpacket[6:10],'big')
213  # if is_bad_packet(packetLength,fh): return 104
214  if fpacket:
215  mpacket = fpacket
216  try:
217  stime = get_anc_packet_time(mpacket[6:12],0,'msec')
218  str_stime = stime.strftime('%Y-%m-%dT%H:%M:%S.%f')
219  print("start_time=%s" % str_stime)
220  except:
221  return 120
222 
223  while fpacket and (packetLength>7):
224  fpacket, packetLength = read_packet(fh, bSPW)
225  if fpacket:
226  apid = read_apid(fpacket)
227  else:
228  continue
229  if (apid >= 550) and (apid < 750): mpacket = fpacket
230 
231  if is_bad_packet(packetLength,fh): return 104
232  etime = get_anc_packet_time(mpacket[6:12],0,'msec')
233  else:
234  if output:
235  output.write("datatype=OCI\n")
236  return status
237 
238  else:
239  # Get data type
240  dtype = get_oci_data_type(fpacket)
241  if (dtype<1) or (dtype>12):
242  print("Invalid data type %d."%dtype)
243  return 104
244 
245  # Get start time
246  try:
247  stime = get_anc_packet_time(fpacket,28,'usec')
248  str_stime = stime.strftime('%Y-%m-%dT%H:%M:%S.%f')
249  print("start_time=%s" % str_stime)
250  epacket = fpacket
251  etime = get_anc_packet_time(epacket,28,'usec')
252  except:
253  return 120
254 
255  # Read to end of file
256  apacket = fpacket
257  acomp = 0
258  nagg = np.array([1,2,4,8])
259  spnp = int.from_bytes(apacket[24:28],'big')
260 
261  while fpacket:
262  etime = get_anc_packet_time(apacket,28,'usec')
263  if args.verbose:
264  # spnum = swap_endian(long(apacket(24:27),0))
265  spnum = int.from_bytes(apacket[24:28],'big')
266  tmpstr = ""
267  if ((spnum-spnp) > 10):
268  tmpstr += "\nSpin number gap: %d, %d" % (spnp, spnum)
269  spnp = spnum
270  if (not acomp):
271  tmpstr += "\n\nInstrument configuration change at spin %d, %s" % (spnum,etime)
272  ncp,nbb,nrb,nsp,ndc,nds,btaps,rtaps,itable,baggs,raggs = get_band_dims(apacket)
273  iz = np.where((itable['dtype'] != 0) & (itable['dtype'] != 10))[0]
274  tmpstr += "\nData Type %s" % str(itable['dtype'][iz])
275  iagg = nagg[itable['iagg'][iz]]
276  tmpstr += "\nNumber of pixels %s" % str(itable['lines'][iz]/iagg)
277  tmpstr += "\nAggregation %s" % str(iagg)
278  tmpstr += "\nBlue bands: %d Red bands: %d" %(nbb, nrb)
279  tmpstr += "\nBlue aggregation per tap: %s" % str(baggs)
280  tmpstr += "\nRed aggregation per tap: %s\n" % str(raggs)
281  print(tmpstr)
282 
283  apacket = fpacket
284 
285  apid = 0
286  while (apid != 636) and (packetLength>0):
287  fpacket, packetLength = read_packet(fh, bSPW)
288  apid = read_apid(fpacket)
289  if is_bad_apid(apid,fh): return 104
290 
291  if is_bad_packet(packetLength,fh): return 104
292  if fpacket: epacket = fpacket
293 
294  try:
295  etime = get_anc_packet_time(epacket,28,'usec')
296  except:
297  return 120
298 
299  str_etime = etime.strftime('%Y-%m-%dT%H:%M:%S.%f')
300  print("stop_time=%s" % str_etime)
301 
302  datatype_name = ''
303  if dtype > 0:
304  try:
305  datatype_name = 'OCI' + __dtypes__[dtype]
306  if (datatype_name=="OCI_SPCA") or (datatype_name=="OCI_LUN-ST"):
307  print("Unexpected datatype [%s] is detected." % datatype_name)
308  status = 130
309  except:
310  print("OCI data type name reading error.")
311  status = 130
312 
313  if datatype_name=='':
314  datatype_name = 'OCI'
315 
316  print("datatype=%s" % datatype_name)
317  if output:
318  output.write("datatype=%s\n" % datatype_name)
319  if str_stime!='':
320  output.write("start_time=%s\n" % str_stime)
321  if str_etime!='':
322  output.write("stop_time=%s\n" % str_etime)
323 
324  return status
def get_band_dims(apacket)
Definition: l0info_oci.py:12
def anc_compare(apacket0, apacket)
Definition: l0info_oci.py:102
def read_apid(fpacket)
Definition: l0info_utils.py:93
def is_bad_apid(apid, fh)
Definition: l0info_oci.py:136
def get_oci_data_type(fpacket)
Definition: l0info_oci.py:145
int get_anc_packet_time(uint8_t *apacket, int32_t &iyear, int32_t &iday, double &stime)
Definition: common.cpp:97
int read_packet(FILE *infile, uint8_t packet[], int *len, long int *endfile)
Definition: read_packet.c:18
def is_bad_packet(packetLength, fh)
const char * str
Definition: l1c_msi.cpp:35
def l0info_oci(args, fh, output, bDSB)
Definition: l0info_oci.py:164