diff --git a/src/sorunlib/seq.py b/src/sorunlib/seq.py index 4dbdba7..6fe880c 100644 --- a/src/sorunlib/seq.py +++ b/src/sorunlib/seq.py @@ -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: @@ -19,8 +24,20 @@ 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 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 diff --git a/tests/test_seq.py b/tests/test_seq.py index 833012f..74dbaab 100644 --- a/tests/test_seq.py +++ b/tests/test_seq.py @@ -24,6 +24,14 @@ 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_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 @@ -31,7 +39,7 @@ def test_scan_no_session(patch_clients): 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.) @@ -60,6 +68,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.)