diff --git a/kadi/commands/states.py b/kadi/commands/states.py index 1e302198..635a87de 100644 --- a/kadi/commands/states.py +++ b/kadi/commands/states.py @@ -882,6 +882,9 @@ def callback(cls, date, transitions, state, idx): ``battery_connect`` is the time of the battery connect EOESTECN command, which must occur prior to this command which is eclipse entry. """ + if state["battery_connect"] is None: + return + battery_connect_time = date2secs(state["battery_connect"]) eclipse_entry_time = date2secs(date) # By definition, the battery connect time is always less than the eclipse entry. @@ -1124,6 +1127,9 @@ def update_sun_vector_state(cls, date, transitions, state, idx): current index into transitions """ if state["pcad_mode"] == "NPNT": + if any(state[key] is None for key in ("ra", "dec", "roll")): + return + ra, dec, roll = state["ra"], state["dec"], state["roll"] time = date2secs(date) sun_ra, sun_dec = ska_sun.position(time) @@ -1653,6 +1659,12 @@ def simode_callback(tlmsid, date, transitions, state, idx): # Special case for NIL SI modes elif tlmsid in NIL_SIMODES: + # Ensure that the obsid is set. When evaluating continuity the code can get + # to this point with obsid=None. Instead do nothing here and let obsid get + # defined and the code will come back here with a longer lookback. + if state["obsid"] is None: + return + si_mode = NIL_SIMODES[tlmsid] # Value of SIMODE in some cases depends on whether obsid is # an odd or even number @@ -1822,12 +1834,12 @@ def fids_callback(msid, date, transitions, state, idx): else: # Only AFLCxxDy commands can make it here from set_transitions filtering fid_id = int(msid[4:6]) - # state["fids"] could be None at the beginning - fids = state["fids"] - if fids is None: - fids = set() + # state["fids"] could be None at the beginning so wait until an AFLCRSET + # command to define it. + if state["fids"] is None: + return # Add the fid light to the ON set - state["fids"] = fids | {fid_id} + state["fids"] = state["fids"] | {fid_id} ################################################################### diff --git a/kadi/commands/tests/test_states.py b/kadi/commands/tests/test_states.py index c71a22ee..593d6aa3 100644 --- a/kadi/commands/tests/test_states.py +++ b/kadi/commands/tests/test_states.py @@ -6,6 +6,7 @@ import numpy as np import pytest +from astropy import units as u from astropy.io import ascii from astropy.table import Table from chandra_time import DateTime @@ -1856,3 +1857,37 @@ def test_sun_pos_mon_within_eclipse_no_spm_enab(monkeypatch): ] names = ["datestart"] + states.SPM_STATE_KEYS assert sts[names].pformat_all() == exp + + +def test_get_continuity_acis_cmd_requires_obsid(): + """See https://github.com/sot/kadi/issues/325. + + These are times where the requested time - lookback lands before a particular ACIS + power command that needs obsid but after the obsid command. Without the fix for #325 + this would raise an exception. + """ + for time in ["2021:205:09:35:06.322", "2021:020:07:04:40.280"]: + states.get_continuity(time) + + +def test_get_continuity_spm_eclipse(): + """Similar to above but for sun_pos_mon. + + This tests a corner case where the requested time - lookback is between the + eclipse entry and battery connect. Previously this would call + ``chandra_datetime.date2secs(None)`` which *should* fail but instead was giving a + date in 1858. The end result was OK but this was a bit accidental. + """ + cont = states.get_continuity( + CxoTime("2017:087:07:47:59.838") + 7 * u.day, state_keys=states.SPM_STATE_KEYS + ) + assert cont == { + "sun_pos_mon": "DISA", + "battery_connect": "2017:087:07:47:55.838", + "eclipse_enable_spm": True, + "__dates__": { + "sun_pos_mon": "2017:093:07:47:03.821", + "battery_connect": "2017:087:07:47:55.838", + "eclipse_enable_spm": "2017:087:07:49:55.838", + }, + }