From bffa1775c6ff531114bad3cc5e1b6447e78db511 Mon Sep 17 00:00:00 2001 From: Greg Quinn <greg.quinn@ssec.wisc.edu> Date: Fri, 15 Sep 2017 11:26:10 -0500 Subject: [PATCH] Add packets_to_rdrs function --- edosl0util/rdrgen.py | 61 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/edosl0util/rdrgen.py b/edosl0util/rdrgen.py index 709feb5..49eb742 100644 --- a/edosl0util/rdrgen.py +++ b/edosl0util/rdrgen.py @@ -3,6 +3,7 @@ import itertools import os from collections import OrderedDict from datetime import datetime +from tempfile import TemporaryFile import attr import h5py @@ -12,6 +13,29 @@ from astropy.time import Time, TimeDelta import edosl0util from edosl0util.jpssrdr import ( StaticHeader, Apid as ApidListItem, PacketTracker, decode_rdr_blob) +from edosl0util.stream import jpss_packet_stream + + +def packets_to_rdrs(sat, pkt_files): + # FIXME: refactor!!! + rdr_pkt_files = {} + for pkt_file in pkt_files: + with open(pkt_file) as file_obj: + stream = jpss_packet_stream(file_obj) + for pkt in stream: + rdr_type = get_rdr_type(pkt.apid) + gran = calc_rdr_granule(sat, rdr_type, pkt) + if (rdr_type, gran) not in rdr_pkt_files: + rdr_pkt_files[rdr_type, gran] = TemporaryFile() + rdr_pkt_files[rdr_type, gran].write(pkt.bytes()) + for rdr_pkt_file in rdr_pkt_files.values(): + rdr_pkt_file.seek(0) + pkts = jpss_packet_stream(rdr_pkt_file) + pkts = sorted(pkts, key=(lambda p: (timecode_to_iet(p.secondary_header.timecode), + p.apid))) + blob = build_rdr_blob(sat, pkts) + write_rdr(sat, blob) + def write_rdr(sat, blob, dir_path='.', @@ -26,7 +50,7 @@ def write_rdr(sat, blob, dir_path='.', software_ver = (software_ver or edosl0util.__name__ + '-' + edosl0util.__version__) blob_info = decode_rdr_blob(blob) - rdr_type = SpacecraftDiaryRdrType() # TODO: select via APID + rdr_type = get_rdr_type(blob_info.apids[0].value) gran_iet = blob_info.header.start_boundary gran_end_iet = blob_info.header.end_boundary gran_time = iet_to_datetime(gran_iet) @@ -108,10 +132,10 @@ def set_h5_attrs(h5_obj, attrs): def build_rdr_blob(sat, pkt_stream): + pkt_stream = iter(pkt_stream) first_pkt = next(pkt_stream) # FIXME: what if there are no packets? - rdr_type = SpacecraftDiaryRdrType() # TODO: select based on first packet APID - granule_iet = calc_iet_granule(satellite_base_times[sat], rdr_type.gran_len, - timecode_to_iet(first_pkt.secondary_header.timecode)) + rdr_type = get_rdr_type(first_pkt.apid) + granule_iet = calc_rdr_granule(sat, rdr_type, first_pkt) granule_iet_end = granule_iet + rdr_type.gran_len total_pkt_size = 0 @@ -230,6 +254,27 @@ class ApidSpec(object): max_expected = attr.ib() +class RdrTypeManager(object): + def __init__(self): + self._types_by_apid = {} + + def register_type(self, cls): + for apid_spec in cls.apids: + if apid_spec.num in self._types_by_apid: + raise ValueError('each APID can only be handled by one RDR type') + self._types_by_apid[apid_spec.num] = cls + return cls + + def get_type_for_apid(self, apid): + return self._types_by_apid[apid] + + +rdr_type_mgr = RdrTypeManager() +rdr_type_spec = rdr_type_mgr.register_type +get_rdr_type = rdr_type_mgr.get_type_for_apid + + +@rdr_type_spec class CrisScienceRdrType(object): product_id = 'RCRIS' short_name = 'CRIS-SCIENCE-RDR' @@ -240,6 +285,7 @@ class CrisScienceRdrType(object): apids = get_cris_science_apids() +@rdr_type_spec class SpacecraftDiaryRdrType(object): product_id = 'RNSCA' short_name = 'SPACECRAFT-DIARY-RDR' @@ -262,7 +308,7 @@ def make_rdr_filename(prod_id, sat, gran_time, gran_end_time, orbit_num, creatio return o[:-1] + ('c' if compressed else 'u') else: return o - return '{p}_{s}_d{d:%Y%m%d}_t{b}_e{e}_b{n}_c{c:%Y%m%d%H%M%S%f}_{o}_{m}.h5'.format( + return '{p}_{s}_d{d:%Y%m%d}_t{b}_e{e}_b{n:05d}_c{c:%Y%m%d%H%M%S%f}_{o}_{m}.h5'.format( p=prod_id, s=sat_strs[sat], d=gran_time, b=format_gran_time(gran_time), e=format_gran_time(gran_end_time), n=orbit_num, c=creation_time, o=format_origin(origin), m=domain) @@ -279,6 +325,11 @@ def iet_to_datetime(iet): return (iet_epoch + TimeDelta(iet * 1e-6, format='sec')).utc.datetime +def calc_rdr_granule(sat, rdr_type, pkt): + return calc_iet_granule(satellite_base_times[sat], rdr_type.gran_len, + timecode_to_iet(pkt.secondary_header.timecode)) + + def calc_iet_granule(base_time, gran_len, iet): return (iet - base_time) // gran_len * gran_len + base_time -- GitLab