Skip to content

Commit

Permalink
Merge branch 'main' into hwp-acu-checks
Browse files Browse the repository at this point in the history
  • Loading branch information
ykyohei authored Jul 30, 2024
2 parents 8b777ec + 4902d3b commit e90c56e
Show file tree
Hide file tree
Showing 17 changed files with 743 additions and 87 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ repos:
- id: isort
name: isort (python)
- repo: https://github.com/hhatto/autopep8
rev: v2.2.0
rev: v2.3.1
hooks:
- id: autopep8
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
rev: 7.1.0
hooks:
- id: flake8
70 changes: 70 additions & 0 deletions docs/agents/wiregrid_tiltsensor.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
.. highlight:: rst

.. _wiregrid_tiltsensor:

==========================
Wiregrid Tilt Sensor Agent
==========================

The Wiregrid Tilt Sensor Agent records the wire-grid tilt sensor outputs
related to the tilt angle of the wire-grid plane along the gravitaional direction.
There is two types of tilt sensors, DWL and sherborne.
The tilt sensor data is sent via serial-to-ethernet converter.
The converter is linked to the tilt sensor
via RS-422(DWL) or RS-485(sherborne), D-sub 9-pin cable.
The agent communicates with the converter via Ethernet.

.. argparse::
:filename: ../socs/agents/wiregrid_tiltsensor/agent.py
:func: make_parser
:prog: python3 agent.py

Configuration File Examples
---------------------------

Below are configuration examples for the ocs config file and for running the
Agent in a docker container.

OCS Site Config
````````````````

An example site-config-file block::

{'agent-class': 'WiregridTiltSensorAgent',
'instance-id': 'wg-tilt-sensor',
'arguments': ['--ip-address', '192.168.11.27',
'--port', '32',
'--sensor-type', 'DWL']},

- ``ip-address`` is an IP address of the serial-to-ethernet converter.
- ``port`` is an asigned port for the tilt sensor.
(The converter has four D-sub ports, 23, 26, 29, 32, to control
multiple devices connected via serial communication.
Communicating device is determined by the ethernet port number of the converter.)
- ``sensor_type`` represents the type of tilt sensor to communicate with.
We have the two types of tilt sensor, DWL and sherborne.
Available values of this argument are only 'DWL' or 'sherborne',
and depend on SATp.

Docker Compose
``````````````

An example docker-compose configuration::

ocs-wg-tilt-sensor-agent:
image: simonsobs/socs:latest
hostname: ocs-docker
network_mode: "host"
command:
- INSTANCE_ID=wg-tilt-sensor
volumes:
- ${OCS_CONFIG_DIR}:/config:ro

- Since the agent within the container needs to communicate with hardware on the
host network you must use ``network_mode: "host"`` in your compose file.

Agent API
---------

.. autoclass:: socs.agents.wiregrid_tiltsensor.agent.WiregridTiltSensorAgent
:members:
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ API Reference Full API documentation for core parts of the SOCS library.
agents/wiregrid_actuator
agents/wiregrid_encoder
agents/wiregrid_kikusui
agents/wiregrid_tiltsensor

.. toctree::
:caption: Simulator Reference
Expand Down
3 changes: 2 additions & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
sphinx>=5.0.0
sphinx_rtd_theme>=2.0.0
sphinx-argparse>=0.4.0
# unpin when https://github.com/sphinx-doc/sphinx-argparse/issues/56 is fixed
sphinx-argparse==0.4.0
Empty file added socs/agents/hi6200/__init__.py
Empty file.
33 changes: 26 additions & 7 deletions socs/agents/hwp_supervisor/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,12 @@ class HWPClients:
class IBootState:
instance_id: str
outlets: List[int]
agent_type: Literal['iboot, synaccess']
outlet_state: Dict[int, Optional[int]] = None
op_data: Optional[Dict] = None

def __post_init__(self):
self.outlet_state = {o: None for o in self.outlets}
self.outlet_labels = {o: f'outletStatus_{o}' for o in self.outlets}

def update(self):
op = get_op_data(self.instance_id, 'acq', test_mode=False)
Expand All @@ -132,10 +132,23 @@ def update(self):
self.outlet_state = {o: None for o in self.outlets}
return

self.outlet_state = {
outlet: op['data'][label]['status']
for outlet, label in self.outlet_labels.items()
}
if self.agent_type == 'iboot':
self.outlet_labels = {o: f'outletStatus_{o}' for o in self.outlets}
self.outlet_state = {
outlet: op['data'][label]['status']
for outlet, label in self.outlet_labels.items()
}
elif self.agent_type == 'synaccess':
self.outlet_labels = {o: str(o - 1) for o in self.outlets}
self.outlet_state = {
outlet: op['data']['fields'][label]['status']
for outlet, label in self.outlet_labels.items()
}
else:
raise ValueError(
f"Invalid agent_type: {self.agent_type}. "
"Must be in ['iboot', 'synaccess']"
)


@dataclass
Expand Down Expand Up @@ -238,13 +251,15 @@ def from_args(cls, args: argparse.Namespace):
)

if args.gripper_iboot_id is not None:
self.gripper_iboot = IBootState(args.gripper_iboot_id, args.gripper_iboot_outlets)
self.gripper_iboot = IBootState(args.gripper_iboot_id, args.gripper_iboot_outlets,
args.gripper_power_agent_type)
log.info("Gripper Ibootbar id set: {id}", id=args.gripper_iboot_id)
else:
log.warn("Gripper Ibootbar id not set")

if args.driver_iboot_id is not None:
self.driver_iboot = IBootState(args.driver_iboot_id, args.driver_iboot_outlets)
self.driver_iboot = IBootState(args.driver_iboot_id, args.driver_iboot_outlets,
args.driver_power_agent_type)
log.info("Driver Ibootbar id set: {id}", id=args.driver_iboot_id)
else:
log.warn("Driver Ibootbar id not set")
Expand Down Expand Up @@ -284,6 +299,7 @@ def update_enc_state(self, op):
"""
self._update_from_keymap(op, {
'enc_freq': 'approx_hwp_freq',
'encoder_last_updated': 'encoder_last_updated',
'last_quad': 'last_quad',
'last_quad_time': 'last_quad_time',
})
Expand Down Expand Up @@ -1555,6 +1571,9 @@ def make_parser(parser=None):
pgroup.add_argument(
'--gripper-iboot-outlets', nargs='+', type=int,
help="Outlets for gripper iboot power")
pgroup.add_argument(
'--gripper-power-agent-type', choices=['iboot', 'synaccess'], default=None,
help="Type of agent used for controlling the gripper power")

pgroup.add_argument(
'--acu-instance-id',
Expand Down
1 change: 1 addition & 0 deletions socs/agents/ocs_plugin_so.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,6 @@
('WiregridActuatorAgent', 'wiregrid_actuator/agent.py'),
('WiregridEncoderAgent', 'wiregrid_encoder/agent.py'),
('WiregridKikusuiAgent', 'wiregrid_kikusui/agent.py'),
('WiregridTiltSensorAgent', 'wiregrid_tiltsensor/agent.py'),
]:
ocs.site_config.register_agent_class(n, os.path.join(root, f))
107 changes: 69 additions & 38 deletions socs/agents/pysmurf_controller/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from sodetlib.operations import bias_dets

from socs.agents.pysmurf_controller.smurf_subprocess_util import (
RunCfg, RunResult, run_smurf_func)
QuantileData, RunCfg, RunResult, run_smurf_func)


class PysmurfScriptProtocol(protocol.ProcessProtocol):
Expand Down Expand Up @@ -129,7 +129,10 @@ def __init__(self, agent, args):
'observatory.{}.feeds.pysmurf_session_data'.format(args.monitor_id),
)

self.agent.register_feed('bias_step_quantiles', record=True)
self.agent.register_feed('bias_step_results', record=True)
self.agent.register_feed('noise_results', record=True)
self.agent.register_feed('iv_results', record=True)
self.agent.register_feed('bias_wave_results', record=True)

def _on_session_data(self, _data):
data, feed = _data
Expand Down Expand Up @@ -655,6 +658,18 @@ def take_noise(self, session, params):

result = run_smurf_func(cfg)
set_session_data(session, result)
if result.success:
block_data = {}
for qd in result.return_val['quantiles'].values():
if isinstance(qd, dict):
qd = QuantileData(**qd)
block_data.update(qd.to_block_data())
d = {
'timestamp': time.time(),
'block_name': 'noise_results',
'data': block_data
}
self.agent.publish_to_feed('noise_results', d)
return result.success, "Finished taking noise"

@ocs_agent.param('kwargs', default=None)
Expand Down Expand Up @@ -747,11 +762,11 @@ def take_iv(self, session, params):
>> response.session['data']
{
'bands': Bands number of each resonator
'channels': Channel number of each resonator
'bgmap': BGMap assignment for each resonator
'R_n': Normal resistance for each resonator
'filepath': Filepath of saved IVAnalysis object
'quantiles': {
'Rn': Rn quantiles
'p_sat': electrical power at 90% Rn quantiles
}
}
"""
if params['kwargs'] is None:
Expand All @@ -770,6 +785,18 @@ def take_iv(self, session, params):
)
result = run_smurf_func(cfg)
set_session_data(session, result)
if result.success:
block_data = {}
for qd in result.return_val['quantiles'].values():
if isinstance(qd, dict):
qd = QuantileData(**qd)
block_data.update(qd.to_block_data())
d = {
'timestamp': time.time(),
'block_name': 'iv_results',
'data': block_data
}
self.agent.publish_to_feed('iv_results', d)
return result.success, "Finished taking IV"

@ocs_agent.param('kwargs', default=None)
Expand Down Expand Up @@ -807,14 +834,11 @@ def take_bias_steps(self, session, params):
'filepath': Filepath of saved BiasStepAnalysis object
'biased_total': Total number of detectors biased into rfrac_range
'biased_per_bg': List containing number of biased detectors on each bias line
'Rtes_quantiles': {
'Rtes': List of 15%, 25%, 50%, 75%, 85% Rtes quantiles,
'quantiles': List of quantile labels
'count': Total count of the distribution
'quantiles': {
'Rtes': Rtes quantiles,
'Rfrac': Rfrac quantiles,
'Si': Si quantiles,
}
'responsivity_quantiles': Same as above for responsivity
'Rfrac_quantiles': Same as above for Rfrac
}
"""

Expand All @@ -838,15 +862,21 @@ def take_bias_steps(self, session, params):
result = run_smurf_func(cfg)
set_session_data(session, result)
if result.success: # Publish quantile results
for name, d in result.return_val['quantiles'].items():
block = dict(zip(d['labels'], d['values']))
block[f'{name}_count'] = d['count']
pub_data = {
'timestamp': time.time(),
'block_name': f'{name}_quantile',
'data': block
}
self.agent.publish_to_feed('bias_step_quantiles', pub_data)
block_data = {
f'biased_bg{bg}': v
for bg, v in enumerate(result.return_val['biased_per_bg'])
}
block_data['biased_total'] = result.return_val['biased_total']
for qd in result.return_val['quantiles'].values():
if isinstance(qd, dict):
qd = QuantileData(**qd)
block_data.update(qd.to_block_data())
data = {
'timestamp': time.time(),
'block_name': 'bias_steps_results',
'data': block_data
}
self.agent.publish_to_feed('bias_step_results', data)

return result.success, "Finished taking bias steps"

Expand Down Expand Up @@ -883,14 +913,11 @@ def take_bias_waves(self, session, params):
'filepath': Filepath of saved BiasWaveAnalysis object
'biased_total': Total number of detectors biased into rfrac_range
'biased_per_bg': List containing number of biased detectors on each bias line
'Rtes_quantiles': {
'Rtes': List of 15%, 25%, 50%, 75%, 85% Rtes quantiles,
'quantiles': List of quantile labels
'count': Total count of the distribution
'quantiles': {
'Rtes': Rtes quantiles,
'Rfrac': Rfrac quantiles,
'Si': Si quantiles,
}
'responsivity_quantiles': Same as above for responsivity
'Rfrac_quantiles': Same as above for Rfrac
}
"""

Expand All @@ -914,15 +941,19 @@ def take_bias_waves(self, session, params):
result = run_smurf_func(cfg)
set_session_data(session, result)
if result.success: # Publish quantile results
for name, d in result.return_val['quantiles'].items():
block = dict(zip(d['labels'], d['values']))
block[f'{name}_count'] = d['count']
pub_data = {
'timestamp': time.time(),
'block_name': f'{name}_quantile',
'data': block
}
self.agent.publish_to_feed('bias_wave_quantiles', pub_data)
block_data = {
f'biased_bg{bg}': v
for bg, v in enumerate(result.return_val['biased_per_bg'])
}
block_data['biased_total'] = result.return_val['biased_total']
for qd in result.return_val['quantiles'].values():
block_data.update(QuantileData(**qd).to_block_data())
data = {
'timestamp': time.time(),
'block_name': 'bias_wave_results',
'data': block_data
}
self.agent.publish_to_feed('bias_wave_results', data)

return result.success, "Finished taking bias steps"

Expand Down
Loading

0 comments on commit e90c56e

Please sign in to comment.