OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l0info_utils.py
Go to the documentation of this file.
1 from datetime import datetime, timezone, timedelta
2 from seadasutils.time_utils import get_leap_seconds
3 import julian
4 
5 __version__ = '1.3.0_2022-12-23'
6 
7 # seconds between 1970-01-01 and 1958-01-01
8 epoch_offset = (datetime(1958,1,1,0,0,0,tzinfo=timezone.utc) - datetime(1970,1,1,0,0,0,tzinfo=timezone.utc)).total_seconds()
9 
11  print("Running l0info_utils (version: %s) \n" % __version__)
12 
13 def read_cfe_header(filehandle, bVerbose=False):
14  # read header from a DSB file and print contents
15  # Reference PACE-SYS-ICD_0010, :Observatory to Ground Data Interface Requirements/Control Document:
16  # Volume II S-band CFDP Specification, section 3.5.1
17 
18  chead = filehandle.read(64)
19 
20  ftime = int.from_bytes(chead[24:28],'big') + int.from_bytes(chead[28:32],'big')/2**32
21  ctime = (datetime.utcfromtimestamp(ftime+epoch_offset) - timedelta(seconds=get_leap_seconds(ftime))).isoformat(sep='T', timespec='microseconds')
22  if bVerbose: print('File creation date/time: %s' % ctime)
23 
24  # Check for valid cFE header
25  dtype = -1
26  scid = "".join([chr(x) for x in chead[12:16]])
27  if scid != 'PACE':
28  print,'Not a valid PACE L0 file'
29  return ctime, dtype
30 
31  # Check for science data file and determine instrument
32  subtype = "".join([chr(x) for x in chead[4:8]])
33  if subtype == ' SCI':
34  instid = "".join([chr(x) for x in chead[20:24]])
35  instids = ['',' OCI','HARP','SPEX']
36  dtype = instids.index(instid)
37  else:
38  # Check for S-band file subtype
39  subtype = int(chead[7])
40  if subtype == 101: dtype = 0
41 
42  return ctime, dtype
43 
44 def read_dsb_header(filehandle, bVerbose=False):
45  # Routine to read header from a DSB file and print contents
46  # Reference PACE-SYS-ICD_0010, :Observatory to Ground Data Interface Requirements/Control Document:
47  # Volume II S-band CFDP Specification, section 3.5.2
48 
49  dhead = filehandle.read(76)
50 
51  ftime = int.from_bytes(dhead[0:4],'big') + int.from_bytes(dhead[4:8],'big')/2**32
52  etime = (datetime.utcfromtimestamp(ftime+epoch_offset) - timedelta(seconds=get_leap_seconds(ftime))).isoformat(sep='T', timespec='microseconds')
53  if bVerbose:
54  print('File close date/time: %s' % etime)
55  print('File path/name: %s'% "".join([chr(x) for x in dhead[12:44]]))
56 
57  return etime
58 
59 def read_packet(filehandle, bSPW = True):
60  # procedure to read a single CCSDS packet from a file.
61  # bSPW to read spacewire header
62 
63  # Read spacewire header if needed
64  if bSPW:
65  spwh = filehandle.read(2)
66  if not spwh: # EOF
67  return None, 0
68 
69  # Read packet header
70  phead = filehandle.read(6)
71  if not phead: # EOF
72  return None, 0
73  elif len(phead)<6:
74  return None, 0
75 
76  # Get length of packet body
77  packetLength = phead[4]*256 + phead[5] + 1
78  try:
79  pbod = filehandle.read(packetLength)
80  if not pbod:
81  return None, 0
82  except:
83  print('Packet reading error.')
84  return None, 0
85 
86  # Concatenate header and body
87 
88  packet = phead+pbod
89  packetLength = packetLength + 6
90 
91  return packet, packetLength
92 
93 def read_apid(fpacket):
94  if fpacket:
95  return fpacket[1] + 256*(fpacket[0] % 8)
96  else:
97  return -1
98 
99 def get_anc_packet_time(apacket,toff,str_subsec):
100  # procedure to unpack and convert the CCSDS segmented time code from the OCI ancillary packet
101 
102  # Get day count since Jan. 1, 1958 (Julian day 2436205)
103  # toff = 28
104  sec58 = int.from_bytes(apacket[toff:toff+4],'big')
105  sec58 -= get_leap_seconds(sec58)
106 
107  day58 = int(sec58/86400)
108  sec58 -= day58*86400
109 
110  usec = 0
111  msec = 0
112 
113  if str_subsec == 'usec':
114  # Get microseconds
115  usec = int.from_bytes(apacket[toff+4:toff+8],'big')
116  usec = usec/4096.0/1000000. #20 MSBs used, last 12 are spares
117  elif str_subsec == 'msec':
118  # Get milliseconds
119  msec = int.from_bytes(apacket[toff+4:toff+6],'big')
120  msec = msec/65536.0
121 
122  dt = julian.from_jd(day58 + 2436205.0) - timedelta(hours=12)
123  dt += timedelta(seconds= sec58 + msec + usec)
124  return dt
125 
126 def is_bad_packet(packetLength,fh):
127  if (packetLength>0) and (packetLength<8):
128  print(f"packetLength={packetLength}") # debug LH
129  print("Invalid packet header at byte %d."%fh.tell())
130  return True
131  else:
132  return False
def read_cfe_header(filehandle, bVerbose=False)
Definition: l0info_utils.py:13
def get_anc_packet_time(apacket, toff, str_subsec)
Definition: l0info_utils.py:99
def read_apid(fpacket)
Definition: l0info_utils.py:93
def read_dsb_header(filehandle, bVerbose=False)
Definition: l0info_utils.py:44
def read_packet(filehandle, bSPW=True)
Definition: l0info_utils.py:59
def print_utils_version()
Definition: l0info_utils.py:10
def is_bad_packet(packetLength, fh)
def get_leap_seconds(taitime, epochyear=1958)
Definition: time_utils.py:17