Skip to content

Commit

Permalink
Merge pull request #181 from simonsobs/koopman/min-scan-duration
Browse files Browse the repository at this point in the history
Check there is enough time before starting `seq.scan()`
  • Loading branch information
BrianJKoopman authored Oct 18, 2024
2 parents 3790428 + 1f0babb commit 538b615
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
23 changes: 22 additions & 1 deletion src/sorunlib/seq.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import datetime as dt

import sorunlib as run

from sorunlib.commands import _timestamp_to_utc_datetime
from sorunlib._internal import check_response, check_started, monitor_process


OP_TIMEOUT = 60


def scan(description, stop_time, width, az_drift=0, tag=None, subtype=None):
def scan(description, stop_time, width, az_drift=0, tag=None, subtype=None,
min_duration=None):
"""Run a constant elevation scan, collecting detector data.
Args:
Expand All @@ -19,8 +24,24 @@ def scan(description, stop_time, width, az_drift=0, tag=None, subtype=None):
tag (str, optional): Tag or comma-separated listed of tags to attach to
the operation. Passed through to the smurf stream command.
subtype (str, optional): Operation subtype used to tag the stream.
min_duration (float, optional): Minimum duration required to scan,
specified in seconds. If not enough time exists between now and the
``stop_time`` the scan is not executed. Defaults to None.
"""
now = dt.datetime.now(dt.timezone.utc)
scan_stop = _timestamp_to_utc_datetime(stop_time)

# Check stop time has not already passed
if now > scan_stop:
return

# Check there is enough time to perform scan
if min_duration is not None:
start_by_time = scan_stop - dt.timedelta(seconds=min_duration)
if now > start_by_time:
return

acu = run.CLIENTS['acu']

# Enable SMuRF streams
Expand Down
20 changes: 18 additions & 2 deletions tests/test_seq.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,30 @@ def test_scan(patch_clients):
seq.scan(description='test', stop_time=target.isoformat(), width=20.)


@patch('sorunlib._internal.time.sleep', MagicMock())
def test_scan_passed_stop_time(patch_clients):
# This affects test runtime duration keep it short
target = dt.datetime.now(dt.timezone.utc) - dt.timedelta(seconds=10)
seq.scan(description='test', stop_time=target.isoformat(), width=20.)
seq.run.CLIENTS['acu'].generate_scan.start.assert_not_called()


@patch('sorunlib._internal.time.sleep', MagicMock())
def test_scan_passed_min_duration(patch_clients):
# This affects test runtime duration keep it short
target = dt.datetime.now(dt.timezone.utc) + dt.timedelta(seconds=10)
seq.scan(description='test', stop_time=target.isoformat(), width=20., min_duration=60)
seq.run.CLIENTS['acu'].generate_scan.start.assert_not_called()


@patch('sorunlib.commands.time.sleep', MagicMock())
def test_scan_no_session(patch_clients):
# Setup mock OCSReply without session object
mock_reply = MagicMock()
mock_reply.session = None
sorunlib.CLIENTS['acu'].generate_scan.start = MagicMock(return_value=mock_reply)

target = dt.datetime.now() + dt.timedelta(seconds=1)
target = dt.datetime.now(dt.timezone.utc) + dt.timedelta(seconds=1)
with pytest.raises(Exception):
seq.scan(description='test', stop_time=target.isoformat(), width=20.)

Expand Down Expand Up @@ -60,6 +76,6 @@ def test_scan_failed_to_start(patch_clients):
# other keys in .session: op_code, data
print(mock_reply)

target = dt.datetime.now() + dt.timedelta(seconds=1)
target = dt.datetime.now(dt.timezone.utc) + dt.timedelta(seconds=10)
with pytest.raises(RuntimeError):
seq.scan(description='test', stop_time=target.isoformat(), width=20.)

0 comments on commit 538b615

Please sign in to comment.