Source code for majis.itl.reader

"""ITL reader module."""

import re
from pathlib import Path

from planetary_coverage.events import EventsDict, EventWindow

from ..misc import get_datetime
from ..misc.events import flatten, group

# ITL prefix pattern: # INST - KEY=VALUE ... or # INST - COMMENTS : VALUE
ATTRIBUTES = re.compile(r'^#\s+\w+\s+-\s+(?P<values>.*)')
COMMENTS = re.compile(r'^#\s+\w+\s+-\s+COMMENTS\s*:\s*(?P<value>.*)')
OBS_START = re.compile(r'(?P<inst>\w+)\s+OBS_START\s+(?P<key>\w*[a-zA-Z])(?:_\d+)?\s*')
OBS_END = re.compile(r'(?P<inst>\w+)\s+OBS_END\s+(?P<key>\w*[a-zA-Z])(?:_\d+)?$')


[docs] def read_itl( fname: str | Path, refs: dict | str | list | None = None, flat: bool = False, ) -> EventsDict | list: """Read ITL file. Note ---- - The blocks can be prefixed with additional instrument parameters. - Blocks must be continuous, ie. consecutive OBS_START and OBS_END lines should have the same instrument observation name. If not an ValueError will be raised """ lines = Path(fname).read_text().splitlines() events = _parse_itl(lines, refs=refs, filename=fname) return flatten(events) if flat else group(events)
def _parse_itl( lines: list[str], refs: dict | str | list | None = None, filename: str | Path | None = None, ) -> list[EventWindow]: """Parse ITL content as EventWindows list.""" events = [] attrs, header, comments, inst, key = {}, [], [], None, None for line in lines: if line.startswith('#'): header.append(line) if match := COMMENTS.match(line): comments.append(match.group('value').strip()) elif match := ATTRIBUTES.match(line): attrs |= dict( field.split('=', 1) for field in match.group('values').split(' ') ) continue if match := OBS_START.search(line): start = get_datetime(line, refs=refs) inst = match.group('inst') key = match.group('key') attrs['PRIME'] = '(PRIME=TRUE)' in line continue if match := OBS_END.search(line): end = get_datetime(line, refs=refs) if inst != match.group('inst'): raise ValueError( f"Instrument block mismatch: `{inst}` / `{match.group('inst')}`" ) if key != match.group('key'): raise ValueError( f"Obs name block mismatch: `{key}` / `{match.group('key')}`" ) attrs['COMMENTS'] = ' / '.join(comments) if comments else None attrs['ITL'] = Path(filename) if filename else None event = EventWindow(key, t_start=start, t_end=end, INSTRUMENT=inst, **attrs) event.comments = header events.append(event) attrs, header, comments, inst, key = {}, [], [], None, None return events