Skip to content
Snippets Groups Projects
eos.py 2.21 KiB
Newer Older
Bruce Flynn's avatar
Bruce Flynn committed
""" NASA EOS mission specific data

References:
    1. MODIS Command, Telemetry, Science and Engineering Description,
       Document Number 151840, May 1997, Appendix C
       https://directreadout.sci.gsfc.nasa.gov/documents/satellite_gen/MODIS_UG.pdf
"""

packet_types = {
    0: "day",
    1: "night",
    2: "eng1",
    4: "eng2",
}

packet_sources = {
    0: "solar-diff",
    1: "srca-cal",
    2: "bb-cal",
    3: "space-cal",
}

packets_per_scan = {
    "day": 3032,
    "night": 326,
}


def sourceid(p):
    if p.data[0] >> 7 == 0:
        return "earthdata"
    return packet_sources[p.data[0] >> 5 & 0x3]


def mirrorside(p):
    return ["side1", "side2"][bytes(p.secondary_header)[8] & 0x1]


def scancount(p):
    return bytes(p.secondary_header)[8] >> 1 & 0x7


def pkttype(p):
    return packet_types[bytes(p.secondary_header)[8] >> 4 & 0x7]


def frame_count(p):
Bruce Flynn's avatar
Bruce Flynn committed
    x = int.from_bytes(b"\x00\x00" + p.data[:2], "big")
Bruce Flynn's avatar
Bruce Flynn committed
    if sourceid(p) == "earthdata":
Bruce Flynn's avatar
Bruce Flynn committed
        return x >> 4 & 0x7FF
    return x >> 4 & 0x3F

Bruce Flynn's avatar
Bruce Flynn committed

# Combination of source ids and packet types to their position within a scan.
_sort_indexes = {
    "solar-diff": 1,
    "srca-cal": 2,
    "bb-cal": 3,
    "space-cal": 4,
    "earthdata": 5,
    "eng1": 6,
    "eng2": 7,
}

Bruce Flynn's avatar
Bruce Flynn committed

Bruce Flynn's avatar
Bruce Flynn committed
def _modis_sort_key(p):
Bruce Flynn's avatar
Bruce Flynn committed
    """Return a tuple that will maintain order for this packet in a stream of
Bruce Flynn's avatar
Bruce Flynn committed
    MODIS data. Intended to be used as a key func for sorting.

    Packets are sorted in the order defined in _sort_indexes.
    """
    type_idx = _sort_indexes.get(pkttype(p), _sort_indexes[sourceid(p)])
    return (p.stamp, 64, type_idx, frame_count(p), int(p.is_last()))


def sort_modis(packets):
Bruce Flynn's avatar
Bruce Flynn committed
    return sorted(packets, key=_modis_sort_key)
Bruce Flynn's avatar
Bruce Flynn committed


def collect_modis_scans(packets):
    scan = {"scantime": None, "packets": {}}
Bruce Flynn's avatar
Bruce Flynn committed
    scantimes = set()
    for p in packets:
        if p.apid not in (64, 957):
            continue
        tp = sourceid(p) if p.apid == 64 else "gbad"
        if tp == "solar-diff" and p.stamp not in scantimes:
            scantimes.add(p.stamp)
            if scan is not None:
                yield scan
            scan = {"scantime": p.stamp, "packets": {}}
        if tp not in scan["packets"]:
            scan["packets"][tp] = []
        scan["packets"][tp].append(p)