NASA Logo
Ocean Color Science Software

ocssw V2022
l0info_harp.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 # procedure to get start and end times from Level-0 fpacket files for HARP2
4 # The times are extracted from the detector image headers. The detector number
5 # (1, 2, 3 or All) is also determined
6 # Reference: HARP2 Telemetry Manual
7 
8 __version__ = '1.5.6_2024-03-06'
9 
10 import numpy as np
11 import os
12 import copy
13 from datetime import datetime, timedelta
14 from l0info_utils import read_packet, read_apid, get_anc_packet_time, is_bad_packet
15 
16 # str_imhead = "HARP" # [72, 65, 82, 80] # Header start mark ASCII "HARP", \x48\x41\x52\x50
17 b_imhead = b'HARP'
18 
19 def is_fill_image(fpacket,packetLength,fh,firstfill):
20  if not np.any(np.frombuffer(fpacket[22:packetLength-1],dtype=np.uint8)-255):
21  # Routine to output location of first HARP2 image fill data
22  if firstfill:
23  firstfill = False
24  print("Image fill data at byte %d."%fh.tell())
25  return True, firstfill
26  else:
27  return False, firstfill
28 
29 def is_bad_apid(apid,fh):
30  if apid == -1:
31  return False
32  if (apid < 750) or (apid > 799):
33  print("Invalid packet or header at byte %d."%fh.tell())
34  return True
35  else:
36  return False
37 
38 def l0info_harp(args, fh, output):
39  print("Running l0info_harp (version: %s) \n" % __version__)
40 
41  status = 0
42  if args.verbose:
43  print("Reading HARP2 science data file.")
44 
45  file_size = os.fstat(fh.fileno()).st_size
46 
47  # Skip CFE header
48  fh.seek(64)
49  bSPW = True
50 
51  # Find first science fpacket (APID 751)
52  apid = 0
53  packetLength = 8
54  firstfill = True
55 
56 
57  while (apid != 751) and (packetLength > 7):
58  fpacket, packetLength = read_packet(fh, bSPW)
59  apid = read_apid(fpacket)
60  if is_bad_apid(apid,fh): return 104
61 
62  if packetLength > 7:
63  if is_bad_packet(packetLength,fh): return 104
64  isFillImage, firstfill = is_fill_image(fpacket,packetLength,fh,firstfill)
65 
66  # Get detector number from AP header
67  detnum = (fpacket[12] & 48)>>4
68 
69  # Find an image header
70  imhp = -1
71  while (imhp == -1) and (fh.tell() < file_size):
72  imhp = fpacket.find(b_imhead)
73 
74  if imhp == -1: # If no header in current fpacket, find next science fpacket
75  apid = 0
76  packetLength = 8
77  while (apid != 751) and (packetLength > 7):
78  fpacket, packetLength = read_packet(fh, bSPW)
79  apid = read_apid(fpacket)
80  if is_bad_apid(apid,fh): return 101
81 
82  if packetLength > 7:
83  if is_bad_packet(packetLength,fh): return 104
84  isFillImage, firstfill = is_fill_image(fpacket,packetLength,fh,firstfill)
85 
86  # Check for more than one detector in file
87  detn = (fpacket[12] & 48)>>4
88  if detn != detnum: detnum = 999
89 
90  if fh.tell() >= file_size:
91  print('No image headers found in file.')
92 
93  if args.verbose:
94  pctr = (fpacket[2] % 64)*256 + fpacket[3]
95  print(f"Image pointer {imhp}, detector {detnum} in packet {pctr}")
96  else:
97  print("No stored science packets found in file.")
98 
99  # If no stored science packets, check for real-time
100  if fh.tell() >= file_size:
101  status = 110
102  etime = datetime(2000,1,1)
103  stime = datetime(3000,1,1)
104 
105  fh.seek(64)
106  apid = 0
107  packetLength = 8
108  while (fh.tell() < file_size) and (apid != 757) and (packetLength > 7):
109  fpacket, packetLength = read_packet(fh, bSPW)
110  apid = read_apid(fpacket)
111  if is_bad_apid(apid,fh): return 101
112 
113  if is_bad_packet(packetLength,fh): return 104
114 
115  if fpacket:
116  mpacket = fpacket
117  isRealTime = False
118  try:
119  ctime = get_anc_packet_time(fpacket[19:25],0,'msec')
120  if ctime<stime:
121  stime = ctime
122  except Exception as e:
123  print(e)
124  return 120
125 
126  while fpacket and (packetLength > 7):
127  fpacket, packetLength = read_packet(fh, bSPW)
128  apid = read_apid(fpacket)
129  if is_bad_apid(apid,fh): return 101
130 
131  if apid == 757:
132  mpacket = fpacket
133  isRealTime = True
134  ctime = get_anc_packet_time(mpacket[19:25],0,'msec')
135  # print(f"ctime={ctime.strftime('%Y-%m-%dT%H:%M:%S.%f')}")
136  if ctime<stime:
137  stime = ctime
138  if ctime>etime:
139  etime = ctime
140 
141  if is_bad_packet(packetLength,fh): return 104
142 
143  if isRealTime:
144  try:
145  print("detector=REAL\n")
146  print("start_time=%s" % stime.strftime('%Y-%m-%dT%H:%M:%S.%f'))
147  print("stop_time=%s" % etime.strftime('%Y-%m-%dT%H:%M:%S.%f'))
148  if output:
149  output.write("start_time=%s\n" % stime.strftime('%Y-%m-%dT%H:%M:%S.%f'))
150  output.write("stop_time=%s\n" % etime.strftime('%Y-%m-%dT%H:%M:%S.%f'))
151  output.write("detector=REAL\n")
152  except Exception as e:
153  print(e)
154  return 120
155  #print(f"status={status}")
156  return status
157 
158  # If no science packets, rewind and get times from HKT packets (APID 750)
159  if fh.tell() >= file_size:
160  status = 110
161  etime = datetime(2000,1,1)
162  stime = datetime(3000,1,1)
163 
164  fh.seek(64)
165  apid = 0
166  packetLength = 8
167  ccsec = 0
168  while ((fh.tell() < file_size) and (apid != 750) and (packetLength > 7)) or (ccsec < 2000000000):
169  fpacket, packetLength = read_packet(fh, bSPW)
170  apid = read_apid(fpacket)
171  if is_bad_apid(apid,fh): return 101
172 
173  # Check for invalid time stamp
174  ccsec = int.from_bytes(fpacket[6:10],'big') # swap_endian(long(packet[6:9],0))
175 
176  if is_bad_packet(packetLength,fh): return 104
177 
178  if fpacket:
179  mpacket = fpacket
180  try:
181  ctime = get_anc_packet_time(mpacket[6:12],0,'msec')
182  if ctime<stime:
183  stime = ctime
184  except Exception as e:
185  print(e)
186  return 120
187 
188  while fpacket and (packetLength > 7):
189  fpacket, packetLength = read_packet(fh, bSPW)
190  apid = read_apid(fpacket)
191  if apid == 750: mpacket = fpacket
192  ctime = get_anc_packet_time(mpacket[6:12],0,'msec')
193  # print(f"ctime={ctime.strftime('%Y-%m-%dT%H:%M:%S.%f')}")
194  if ctime<stime:
195  stime = ctime
196  if ctime>etime:
197  etime = ctime
198 
199  if is_bad_packet(packetLength,fh): return 104
200 
201  try:
202  print("start_time=%s" % stime.strftime('%Y-%m-%dT%H:%M:%S.%f'))
203  if output:
204  output.write("start_time=%s\n" % stime.strftime('%Y-%m-%dT%H:%M:%S.%f'))
205  print("stop_time=%s" % etime.strftime('%Y-%m-%dT%H:%M:%S.%f'))
206  if output:
207  output.write("stop_time=%s\n" % etime.strftime('%Y-%m-%dT%H:%M:%S.%f'))
208  except Exception as e:
209  print(e)
210  return 120
211  #print(f"status={status}")
212  return status
213 
214  # Get start time
215  try:
216  stime = get_anc_packet_time(fpacket[imhp+7:imhp+13],0,'msec')
217  detnum = (fpacket[12] & 48)>>4
218  except:
219  return 120
220 
221  # Read to end of file
222  # Look for next image header
223  packetLength = 8
224  last_pct = 0
225  etime = stime
226 
227  # when updating end time based on new image header's time,
228  # new - curr should not exceed 1 day. Average time
229  # diff between images is ~ 0:00:00.221710. You can lower the
230  # threshold more if needed
231  MAX_TIME_DIFF = timedelta(days=1.0)
232 
233  while fh.tell() < file_size:
234  apid = 0
235 
236  # Find next science fpacket
237  while (fh.tell() < file_size) and (apid != 751) and (packetLength > 7):
238  fpacket, packetLength = read_packet(fh, bSPW)
239  apid = read_apid(fpacket)
240  if is_bad_apid(apid,fh): return 104
241 
242  if fpacket:
243  if is_bad_packet(packetLength,fh): return 104
244  isFillImage, firstfill = is_fill_image(fpacket,packetLength,fh,firstfill)
245 
246  # Look for image header
247  imh = -1
248  while (imh == -1) and fh.tell() < file_size:
249  if args.verbose:
250  imh_pct = int(fh.tell()/file_size*100)
251  if imh_pct - last_pct > 9:
252  print("%d%% of packets read." % imh_pct)
253  last_pct = imh_pct
254  imh = fpacket.find(b_imhead)
255 
256  if (imh == -1): # If no header in current fpacket, find next science fpacket
257  apid = 0
258  while (fh.tell() < file_size) and (apid != 751) and (packetLength > 7):
259  fpacket, packetLength = read_packet(fh, bSPW)
260  apid = read_apid(fpacket)
261  if is_bad_apid(apid,fh): return 104
262  if (fh.tell() < file_size):
263  if is_bad_packet(packetLength,fh): return 104
264  isFillImage, firstfill = is_fill_image(fpacket,packetLength,fh,firstfill)
265 
266  # if is_bad_image(fpacket,packetLength,fh): return 111
267  if fpacket and (imh > -1): # fh.tell() < file_size:
268  # Check for more than one detector in file
269  detn = (fpacket[12] & 48)>>4
270  if detn != detnum: detnum = 999
271 
272  imhp = imh
273  if args.verbose:
274  pctr = (fpacket[2] % 64)*256 + fpacket[3]
275  print(f"Image pointer {imhp}, detector {detn} in packet {pctr}")
276 
277  if imhp < 8202:
278  ctime = get_anc_packet_time(fpacket[imhp+7:imhp+13],0,'msec')
279  # if ctime<stime:
280  # stime = ctime
281  if ctime>etime and (ctime - etime) < MAX_TIME_DIFF:
282  etime = ctime
283 
284 
285 
286  if args.verbose:
287  print("100% of packets read.")
288 
289  try:
290  if imhp <0:
291  status = 110
292  print("start_time=%s" % stime.strftime('%Y-%m-%dT%H:%M:%S.%f'))
293  print("stop_time=%s" % etime.strftime('%Y-%m-%dT%H:%M:%S.%f'))
294  if output:
295  output.write("start_time=%s\n" % stime.strftime('%Y-%m-%dT%H:%M:%S.%f'))
296  output.write("stop_time=%s\n" % etime.strftime('%Y-%m-%dT%H:%M:%S.%f'))
297  except Exception as e:
298  print(e)
299  return 120
300 
301  if detnum == 999:
302  print("detector=all")
303  if output:
304  output.write("detector=all\n")
305  else:
306  print("detector=%d"%detnum)
307  if output:
308  output.write("detector=%d\n"%detnum)
309 
310  return status
311 
def read_apid(fpacket)
Definition: l0info_utils.py:93
def is_bad_apid(apid, fh)
Definition: l0info_harp.py:29
def l0info_harp(args, fh, output)
Definition: l0info_harp.py:38
void print(std::ostream &stream, const char *format)
Definition: PrintDebug.hpp:38
int get_anc_packet_time(uint8_t *apacket, int32_t &iyear, int32_t &iday, double &stime)
Definition: common.cpp:104
int read_packet(FILE *infile, uint8_t packet[], int *len, long int *endfile)
Definition: read_packet.c:18
def is_bad_packet(packetLength, fh)
def is_fill_image(fpacket, packetLength, fh, firstfill)
Definition: l0info_harp.py:19