Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
f5fc5c8
add time_constant function
d-hoshino2626 Oct 17, 2024
f1e1157
add stream during insert/eject and sleep time before and after insert…
d-hoshino2626 Oct 21, 2024
e7610ef
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 21, 2024
58870ff
Merge branch 'main' of github.com:simonsobs/sorunlib into wiregrid_ti…
d-hoshino2626 Nov 8, 2024
b344f77
Merge branch 'main' into wiregrid_time_constant
d-hoshino2626 Mar 10, 2025
04218dd
edit time constant function and related internal functions
d-hoshino2626 Mar 25, 2025
4116360
Update wiregrid.py
sadachi5 Apr 16, 2025
f51a267
Update wiregrid.py
sadachi5 Apr 16, 2025
168c5e8
Update wiregrid.py
sadachi5 Apr 16, 2025
164fd38
Update tests/test_wiregrid.py
sadachi5 Apr 16, 2025
5b78c31
Merge branch 'main' into wiregrid_time_constant
BrianJKoopman Apr 16, 2025
c859f2e
Remove unused variable assignment
BrianJKoopman Apr 16, 2025
52b31f8
Fix failing tests
BrianJKoopman Apr 16, 2025
43ed057
Update wiregrid.py to split stream before & after hwp stopping
sadachi5 Apr 21, 2025
c720215
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 21, 2025
70fca8c
update streaming (add try & finally to make it sure to stop the strea…
sadachi5 Apr 24, 2025
857e8c2
update hwp.py to add `get_direction()` function.
sadachi5 Apr 24, 2025
c53b903
update hwp.py to add `get_direction()` function.
sadachi5 Apr 24, 2025
d483868
remove `_reverse_hwp_direction()` function in wiregrid.py
sadachi5 Apr 24, 2025
3809f23
remove tests related to ``_reverse_hwp_direction()`` in ``test_wiregr…
sadachi5 Apr 24, 2025
e7d635b
add `get_direction()` in hwp.py and its test function
sadachi5 Apr 25, 2025
64b4904
add `get_direction()` in hwp.py and its test function
sadachi5 Apr 25, 2025
1cf3292
wiregrid.py: use hwp.get_direction() and change hwp direction label f…
sadachi5 Apr 25, 2025
b266e63
update test_wiregrid.py
sadachi5 Apr 25, 2025
5d7c2ad
update
sadachi5 Apr 25, 2025
b320d6c
update test_wiregrid.py
sadachi5 Apr 28, 2025
d3c55bd
update hwp.py, wiregrid.py
sadachi5 Apr 28, 2025
183e5d8
update test_hwp/wiregrid.py
sadachi5 Apr 28, 2025
036d41c
fix bug in wiregrid.py
sadachi5 Apr 28, 2025
9ebcc0b
update test_wiregrid.py
sadachi5 Apr 28, 2025
ef39b39
update test_wiregrid.py
sadachi5 Apr 28, 2025
8cdbbd2
update test_wiregrid.py
sadachi5 Apr 28, 2025
4d4cdc8
update wiregrid.py
sadachi5 Apr 28, 2025
9db2397
update test_wiregrid.py
sadachi5 Apr 28, 2025
4820d4a
update test_wiregrid.py
sadachi5 Apr 28, 2025
2e7e481
update test_wiregrid.py
sadachi5 Apr 28, 2025
6208663
Update hwp.py
sadachi5 Apr 30, 2025
a76a4fa
Update wiregrid.py
sadachi5 Apr 30, 2025
8a6c3d0
Update test_wiregrid.py
sadachi5 Apr 30, 2025
95496f8
Update test_hwp.py
sadachi5 Apr 30, 2025
70c9e00
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 30, 2025
466b368
update test_hwp.py
sadachi5 Apr 30, 2025
809fc17
update hwp.py, wiregrid.py, and their test scripts
sadachi5 Apr 30, 2025
36e4085
Add test for failed direction determination
BrianJKoopman May 13, 2025
3fbf4aa
Clean up docstrings and comments
BrianJKoopman May 13, 2025
2b842f1
Add argument name when calling rotate function
BrianJKoopman May 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/sorunlib/hwp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,33 @@
from sorunlib._internal import check_response


def _get_direction():
"""Get the rotational direction ('cw' or 'ccw') of the HWP. The direction
is determined in part by the configuration of the HWP supervisor agent. For
details see the `HWP Supervisor agent docs <docs_>`_.

* 'cw' is clockwise as seen from the sky to window.
* 'ccw' is counter-clockwise as seen from the sky to window.

Returns:
str: The direction of the HWP, either 'cw' or 'ccw'.

Raises:
RuntimeError: If the direction is not either 'cw' or 'ccw'.

.. _docs: https://socs.readthedocs.io/en/main/agents/hwp_supervisor_agent.html

"""
hwp = run.CLIENTS['hwp']
resp = hwp.monitor.status()
direction = resp.session['data']['hwp_state']['direction']

if direction not in ['cw', 'ccw']:
raise RuntimeError("The HWP direction is unknown. Aborting...")

return direction


# Public API
def set_freq(freq):
"""Set the rotational frequency of the HWP.
Expand Down
159 changes: 159 additions & 0 deletions src/sorunlib/wiregrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,24 @@ def _check_temperature_sensors():
_verify_temp_response(resp, 'AIN2C', 0)


def _check_wiregrid_position():
"""Check the wiregrid position.

Returns:
str: The wiregrid position, either 'inside' or 'outside'.

Raises:
RuntimeError: When the wiregrid position is unknown.

"""
actuator = run.CLIENTS['wiregrid']['actuator']
resp = actuator.acq.status()
position = resp.session['data']['fields']['position']
if position not in ['inside', 'outside']:
raise RuntimeError("The wiregrid position is unknown. Aborting...")
return position


# Public API
def insert():
"""Insert the wiregrid."""
Expand Down Expand Up @@ -305,3 +323,144 @@ def calibrate(continuous=False, elevation_check=True, boresight_check=True,
finally:
# Stop SMuRF streams
run.smurf.stream('off')


def time_constant(num_repeats=1):
"""
Run a wiregrid time constant measurement.

Args:
num_repeats (int): Number of repeats. Default is 1.
If this is odd, the HWP direction will be changed to the opposite
of the initial direction. If this is even, the HWP direction will be
the same as the initial direction.

"""
# Check the number of repeats
if num_repeats < 1 or not isinstance(num_repeats, int):
error = "The ``num_repeats`` should be int and larger than 0."
raise RuntimeError(error)

_check_agents_online()
_check_motor_on()
_check_telescope_position(elevation_check=True, boresight_check=False)
_check_wiregrid_position()
if _check_wiregrid_position() == 'inside':
error = "The wiregrid is already inserted before the wiregrid time " + \
"constant measurement. Please inspect wiregrid and HWP " + \
"before continuing observations."
raise RuntimeError(error)

if _check_zenith():
el_tag = ', wg_el90'
else:
el_tag = ''

# Check the current HWP direction
try:
current_hwp_direction = run.hwp._get_direction() # 'cw' or 'ccw'
except RuntimeError as e:
error = "Wiregrid time constant measurment has failed " + \
"due to a failure in getting the HWP direction.\n" + str(e)
raise RuntimeError(error)

# Rotate to get encoder reference before insertion
rotate(continuous=True, duration=10)

# Bias step (the wire grid is off the window)
bs_tag = 'wiregrid, wg_time_constant, wg_ejected, ' + \
f'hwp_{current_hwp_direction}' + el_tag
run.smurf.bias_step(tag=bs_tag, concurrent=True)
time.sleep(5)

# Insert the wiregrid while streaming
try:
stream_tag = 'wiregrid, wg_time_constant, wg_inserting, ' + \
f'hwp_{current_hwp_direction}' + el_tag
run.smurf.stream('on', tag=stream_tag, subtype='cal')
insert()
time.sleep(5)
finally:
run.smurf.stream('off')

for i in range(num_repeats):
if current_hwp_direction == 'ccw':
target_hwp_direction = 'cw'
elif current_hwp_direction == 'cw':
target_hwp_direction = 'ccw'

# Bias step (the wire grid is on the window)
# Before stopping the HWP
bs_tag = 'wiregrid, wg_time_constant, wg_inserted, ' + \
f'hwp_{current_hwp_direction}' + el_tag
run.smurf.bias_step(tag=bs_tag, concurrent=True)

# Run stepwise rotation before stopping the HWP
try:
stream_tag = 'wiregrid, wg_time_constant, ' + \
f'wg_stepwise, hwp_{current_hwp_direction}' + \
el_tag
run.smurf.stream('on', tag=stream_tag, subtype='cal')
# Run stepwise rotation
rotate(continuous=False)
finally:
run.smurf.stream('off')

# Stop the HWP while streaming
try:
stream_tag = 'wiregrid, wg_time_constant, ' + \
f'hwp_change_{current_hwp_direction}_to_stop' + el_tag
run.smurf.stream('on', tag=stream_tag, subtype='cal')
run.hwp.stop(active=True)
finally:
run.smurf.stream('off')

# Reverse the HWP while streaming
try:
stream_tag = 'wiregrid, wg_time_constant, ' + \
f'hwp_change_stop_to_{target_hwp_direction}' + el_tag
run.smurf.stream('on', tag=stream_tag, subtype='cal')
# Note: This is hardcoding the correspondance between direction and
# the sign of the frequency, which is subject to change depending
# on the hardware/agent configuration. This should be removed in
# the future, if possible.
if target_hwp_direction == 'ccw':
run.hwp.set_freq(freq=2.0)
elif target_hwp_direction == 'cw':
run.hwp.set_freq(freq=-2.0)
current_hwp_direction = target_hwp_direction
finally:
run.smurf.stream('off')

# Run stepwise rotation after changing the HWP rotation
try:
stream_tag = 'wiregrid, wg_time_constant, ' + \
f'wg_stepwise, hwp_{current_hwp_direction}' + \
el_tag
run.smurf.stream('on', tag=stream_tag, subtype='cal')
# Run stepwise rotation
rotate(continuous=False)
finally:
run.smurf.stream('off')

# Bias step (the wire grid is on the window)
# After changing the HWP rotation
bs_tag = 'wiregrid, wg_time_constant, wg_inserted, ' + \
f'hwp_{current_hwp_direction}' + el_tag
run.smurf.bias_step(tag=bs_tag, concurrent=True)
time.sleep(5)

# Eject the wiregrid while streaming
try:
stream_tag = 'wiregrid, wg_time_constant, wg_ejecting, ' + \
f'hwp_{current_hwp_direction}' + el_tag
run.smurf.stream('on', tag=stream_tag, subtype='cal')
eject()
time.sleep(5)
finally:
run.smurf.stream('off')

# Bias step (the wire grid is off the window)
bs_tag = 'wiregrid, wg_time_constant, wg_ejected, ' + \
f'hwp_{current_hwp_direction}' + el_tag
run.smurf.bias_step(tag=bs_tag, concurrent=True)
48 changes: 46 additions & 2 deletions tests/test_hwp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,59 @@
os.environ["OCS_CONFIG_DIR"] = "./test_util/"

import pytest
from unittest.mock import MagicMock
import time

import ocs
from ocs.ocs_client import OCSReply
from sorunlib import hwp

from util import create_patch_clients

from util import create_patch_clients, create_session

patch_clients_satp = create_patch_clients('satp')


def create_hwp_client(direction):
"""Create a HWP client with mock acq Process session.data.

Args:
direction (str): direction of the HWP. 'ccw' (counter-clockwise) or 'cw' (clockwise).

"""
client = MagicMock()
session = create_session('acq')
session.data = {
'hwp_state': {
'direction': direction,
},
'timestamp': time.time(),
}
reply = OCSReply(ocs.OK, 'msg', session.encoded())
client.monitor.status = MagicMock(return_value=reply)

return client


@pytest.mark.parametrize('direction', ['ccw', 'cw'])
def test__get_direction(patch_clients_satp, direction):
hwp.run.CLIENTS['hwp'] = create_hwp_client(direction)
ret = hwp._get_direction()
if direction == 'ccw':
assert ret == 'ccw'
elif direction == 'cw':
assert ret == 'cw'
hwp.run.CLIENTS['hwp'].monitor.status.assert_called_once()


@pytest.mark.parametrize('direction', [None, ''])
def test__get_direction_invalid(patch_clients_satp, direction):
hwp.run.CLIENTS['hwp'] = create_hwp_client(direction)
with pytest.raises(RuntimeError) as e:
hwp._get_direction()
assert str(e.value) == "The HWP direction is unknown. Aborting..."
hwp.run.CLIENTS['hwp'].monitor.status.assert_called_once()


@pytest.mark.parametrize("active", [True, False])
def test_stop(patch_clients_satp, active):
hwp.stop(active=active)
Expand Down
Loading