Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
3fc8d8b
changed directory name from ~/git/socs/socs/agents/starcam to ~/git/s…
tanaybhandarkar Nov 13, 2024
82252e7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 13, 2024
f7a0565
changes:
tanaybhandarkar Nov 20, 2024
04999b4
Merge branch 'starcamera' of https://github.com/simonsobs/socs into s…
tanaybhandarkar Nov 20, 2024
735850d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 20, 2024
0733d7a
changes
tanaybhandarkar Nov 20, 2024
3ea0cce
Merge branch 'starcamera' of https://github.com/simonsobs/socs into s…
tanaybhandarkar Nov 20, 2024
6465c4f
changes:
tanaybhandarkar Nov 20, 2024
10db58a
changes:
tanaybhandarkar Nov 20, 2024
824305f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 20, 2024
d2ca913
changes:
Nov 20, 2024
336557b
Fix docstrings and a few typos
Jan 15, 2025
a5a2f24
Change buffer size in get_astrom_data
Jan 27, 2025
03e2d58
Remove unnecessary lines
Jan 27, 2025
fe0c275
Change attribute names
Jan 27, 2025
401c61f
Correct Task docstrings and fix acq() timeout+typo
Feb 12, 2025
34bfdfc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 12, 2025
e198836
Remove Returns: sections from agent operation dosctrings
Feb 12, 2025
21cc75d
Merge branch 'starcamera' of https://github.com/simonsobs/socs into s…
Feb 12, 2025
6d33d24
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 12, 2025
f2a9456
Touch up Docstrings
Feb 14, 2025
90bbfa9
Merge branch 'starcamera' of https://github.com/simonsobs/socs into s…
Feb 14, 2025
267a02c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 14, 2025
e789b4a
Fix typo
BrianJKoopman May 6, 2025
26988c5
Add agent to plugin list
BrianJKoopman May 6, 2025
7b5bc3a
Create docs page for starcam agent
BrianJKoopman May 6, 2025
f4fca40
Clean up documentation
BrianJKoopman May 6, 2025
f566702
Merge branch 'main' into starcamera
BrianJKoopman May 6, 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
75 changes: 75 additions & 0 deletions docs/agents/starcam_lat.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
.. highlight:: rst

.. _template:

=====================
Star Camera LAT Agent
=====================

# A brief description of the Agent.

.. argparse::
:module: socs.agents.starcam_lat.agent
:func: add_agent_args
:prog: python3 agent.py

Dependencies
------------

# Any external dependencies for agent. Omit if there are none, or they are
# included in the main requirements.txt file.

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': 'StarcamAgent',
'instance-id': 'starcam-lat',
'arguments': ['--ip-address', '192.168.1.20',
'--port', 8000]},

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

An example docker compose configuration::

ocs-starcam-lat:
image: simonsobs/socs:latest
hostname: ocs-docker
network_mode: "host"
volumes:
- ${OCS_CONFIG_DIR}:/config
environment:
- INSTANCE_ID=starcam-lat
- LOGLEVEL=info

Description
-----------

# Detailed description of the Agent. Include any details the users or developers
# might find valuable.

Subsection
``````````

# Use subsections where appropriate.

Agent API
---------

.. autoclass:: socs.agents.starcam_lat.agent.StarcamAgent
:members:

Supporting APIs
---------------

.. autoclass:: socs.agents.starcam_lat.agent.StarcamHelper
:members:
:noindex:
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ API Reference Full API documentation for core parts of the SOCS library.
agents/scpi_psu
agents/smurf_crate_monitor
agents/smurf_timing_card
agents/starcam_lat
agents/stimulator_encoder
agents/stimulator_thermometer
agents/suprsync
Expand Down
287 changes: 287 additions & 0 deletions socs/agents/starcam_lat/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
import argparse
import socket
import struct
import time
from os import environ

import txaio
from ocs import ocs_agent, site_config
from ocs.ocs_twisted import TimeoutLock


class StarcamHelper:
"""Functions to control and retrieve data from the starcam.

Parameters
----------
ip_addres: str
IP address of the starcam computer.
port: int
Port of the starcam computer.
timeout: float
Socket connection timeout in seconds. Defaults to 10 seconds.

"""

def __init__(self, ip_address, port, timeout=10):
self.ip = ip_address
self.port = port
self.server_addr = (self.ip, self.port)
self.comm = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.comm.connect(self.server_addr)
self.comm.settimeout(timeout)

def pack_and_send_cmds(self):
"""Packs commands and parameters to be sent to the starcam and sends.

Returns:
list: Values sent to the starcam.

"""
logodds = 1e8
latitude = -22.9586
longitude = -67.7875
height = 5200.0
exposure = 700
timelimit = 1
set_focus_to_amount = 0
auto_focus_bool = 1
start_focus = 0
end_focus = 0
step_size = 5
photos_per_focus = 3
infinity_focus_bool = 0
set_aperture_steps = 0
max_aperture_bool = 0
make_HP_bool = 0
use_HP_bool = 0
spike_limit_value = 3
dynamic_hot_pixels_bool = 1
r_smooth_value = 2
high_pass_filter_bool = 0
r_high_pass_filter_value = 10
centroid_search_border_value = 1
filter_return_image_bool = 0
n_sigma_value = 2
star_spacing_value = 15
values = [logodds,
latitude,
longitude,
height,
exposure,
timelimit,
set_focus_to_amount,
auto_focus_bool,
start_focus,
end_focus,
step_size,
photos_per_focus,
infinity_focus_bool,
set_aperture_steps,
max_aperture_bool,
make_HP_bool,
use_HP_bool,
spike_limit_value,
dynamic_hot_pixels_bool,
r_smooth_value,
high_pass_filter_bool,
r_high_pass_filter_value,
centroid_search_border_value,
filter_return_image_bool,
n_sigma_value,
star_spacing_value]
# Pack values into the command for the camera
self.cmds_for_camera = struct.pack('ddddddfiiiiiiiiiifffffffff',
*values)
# send commands to the camera
self.comm.sendto(self.cmds_for_camera, (self.ip, self.port))
print("Commands sent to camera.")
# Return the list of values
return values

def get_astrom_data(self):
"""Receives and unpacks data from the starcam.

Returns:
dict: Dictionary of unpacked data.
"""
(scdata_raw, _) = self.comm.recvfrom(256)
data = struct.unpack_from("dddddddddddddiiiiiiiiddiiiiiiiiiiiiiifiii",
scdata_raw)
keys = ['c_time',
'gmt',
'blob_num',
'obs_ra',
'astrom_ra',
'obs_dec',
'fr',
'ps',
'alt',
'az',
'ir',
'astrom_solve_time',
'camera_time']
# Create a dictionary of the unpacked data
astrom_data = [data[i] for i in range(len(keys))]
astrom_data_dict = {keys[i]: astrom_data[i] for i in range(len(keys))}
return astrom_data_dict

def close(self):
"""Closes the socket connection."""
self.comm.close()


class StarcamAgent:
"""Communicate with the starcam.

Parameters
----------
agent: OCSAgent
OCSAgent object for this agent.
ip_address: str
IP address of starcam computer.
port: int
Port of the starcam computer.

Attributes
----------
agent: OCSAgent
OCSAgent object for this agent.
take_data: bool
Tracks whether or not the agent is trying to retrieve data from the
starcam computer. Setting to False stops this process.
log: txaio.tx.Logger
txaio logger object, created by OCSAgent.
"""

def __init__(self, agent, ip_address, port):
self.agent = agent
self.log = agent.log
self.take_data = False
self.lock = TimeoutLock()
agg_params = {'frame_length': 60}
self.agent.register_feed("starcamera", record=True,
agg_params=agg_params, buffer_time=1)
try:
self.starcam = StarcamHelper(ip_address, port)
except socket.timeout:
self.log.error("Starcam connection has timed out.")
return False, "Timeout"

@ocs_agent.param('_')
def send_commands(self, session, params=None):
"""send_commands()

**Process** - Pack and send camera and astrometry-related commands to
the starcam.

"""
with self.lock.acquire_timeout(job='send_commands') as acquired:
if not acquired:
self.log.warn(f"Could not start task because "
f"{self.lock.job} is already running.")
return False, "Could not acquire lock."
self.log.info("Sending commands.")
self.starcam.pack_and_send_cmds()
return True, "Sent commands to the starcam."

@ocs_agent.param('_')
def acq(self, session, params=None):
"""acq()

**Process** - Acquire data from the starcam.

Notes
-----
An example of the updated session data::

>>> response.session['data']
{'timestamp': 1734668749.643134,
'block_name': 'astrometry',
'data':
{'c_time': 1734668749,
'gmt': Dec 20 04:25:49,
'blob_num': 6,
'obs_ra': 87.339171,
'astrom_ra': 87.391578,
'obs_dec': -22.956034,
'astrom_dec': -22.964401,
'fr': 36.591606,
'ps': 6.220203,
'alt': 89.758799574147034,
'az': 270.55842800340095,
'ir': 54.068988,
'astrom_solve_time': 507.617792,
'camera_time': 508.128256,
}
}

"""
with self.lock.acquire_timeout(timeout=10, job='acq') as acquired:
if not acquired:
self.log.warn("Could not start acq because {} is already "
"running".format(self.lock.job))
return False, "Could not acquire lock."
session.set_status('running')
self.log.info("Starting acquisition.")
self.take_data = True
while self.take_data:
data = {
'timestamp': time.time(),
'block_name': 'astrometry',
'data': {}
}
# get astrometry data
astrom_data_dict = self.starcam.get_astrom_data()
# update the data dictionary+session and publish
data['data'].update(astrom_data_dict)
session.data.update(data['data'])
self.agent.publish_to_feed('starcamera', data)

return True, 'Acquisition exited cleanly.'

def _stop_acq(self, session, params):
"""
Stops acq process.
"""
ok = False
if self.take_data:
session.set_status('stopping')
self.take_data = False
ok = True
return (ok, {True: 'Requested process to stop.',
False: 'Failed to request process stop.'}[ok])


def add_agent_args(parser=None):
if parser is None:
parser = argparse.ArgumentParser()
pgroup = parser.add_argument_group('Agent Options')
pgroup.add_argument("--ip-address", type=str,
help="IP address of starcam computer")
pgroup.add_argument("--port", default="8000", type=int,
help="Port of starcam computer")
return parser


def main(args=None):
# for logging
txaio.use_twisted()
txaio.make_logger()

# start logging
txaio.start_logging(level=environ.get("LOGLEVEL", "info"))

parser = add_agent_args()
args = site_config.parse_args(agent_class="StarcamAgent", parser=parser)
agent, runner = ocs_agent.init_site_agent(args)
starcam_agent = StarcamAgent(agent, ip_address=args.ip_address,
port=args.port)
agent.register_task('send_commands', starcam_agent.send_commands,
startup=True)
agent.register_process('acq', starcam_agent.acq, starcam_agent._stop_acq)
runner.run(agent, auto_reconnect=False)


if __name__ == '__main__':
main()
1 change: 1 addition & 0 deletions socs/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
'SmurfFileEmulator': {'module': 'socs.agents.smurf_file_emulator.agent', 'entry_point': 'main'},
'SmurfStreamSimulator': {'module': 'socs.agents.smurf_stream_simulator.agent', 'entry_point': 'main'},
'SmurfTimingCardAgent': {'module': 'socs.agents.smurf_timing_card.agent', 'entry_point': 'main'},
'StarcamAgent': {'module': 'socs.agents.starcam_lat.agent', 'entry_point': 'main'},
'StimEncAgent': {'module': 'socs.agents.stimulator_encoder.agent', 'entry_point': 'main'},
'StimThermometerAgent': {'module': 'socs.agents.stimulator_thermometer.agent', 'entry_point': 'main'},
'SupRsync': {'module': 'socs.agents.suprsync.agent', 'entry_point': 'main'},
Expand Down