Source code for panoptes.pocs.filterwheel.sbig
"""SBIG filter wheel integration via the SBIG camera SDK.
Provides a FilterWheel implementation that controls SBIG wheels attached to an
SBIG camera (via I2C) using the existing SBIG camera driver.
"""
import math
from astropy import units as u
from panoptes.pocs.camera.sbig import Camera as SBIGCamera
from panoptes.pocs.filterwheel import AbstractFilterWheel
[docs]
class FilterWheel(AbstractFilterWheel):
"""
Class for SBIG filter wheels connected to the I2C port of an SBIG camera.
Args:
name (str, optional): name of the filter wheel
model (str, optional): model of the filter wheel
camera (pocs.camera.sbig.Camera): camera that this filter wheel is associated with.
filter_names (list of str): names of the filters installed at each filter wheel position
timeout (u.Quantity, optional): maximum time to wait for a move to complete. Should be
a Quantity with time units. If a numeric type without units is given seconds will be
assumed. Default is 10 seconds.
serial_number (str): serial number of the filter wheel
"""
def __init__(
self,
name="SBIG Filter Wheel",
model="sbig",
camera=None,
filter_names=None,
timeout=10 * u.second,
serial_number=None,
*args,
**kwargs,
):
if camera is None:
msg = "Camera must be provided for SBIG filter wheels"
self.logger.error(msg)
raise ValueError(msg)
if not isinstance(camera, SBIGCamera):
msg = f"Camera must be an instance of pocs.camera.sbig.Camera, got {camera}"
self.logger.error(msg)
raise ValueError(msg)
super().__init__(
name=name,
model=model,
camera=camera,
filter_names=filter_names,
timeout=timeout,
serial_number=serial_number,
*args,
**kwargs,
)
##################################################################################################
# Properties
##################################################################################################
@property
def firmware_version(self):
"""Firmware version of the filter wheel"""
return self._firmware_version
@AbstractFilterWheel.position.getter
def position(self):
"""Current integer position of the filter wheel"""
status = self._driver.cfw_query(self._handle)
if math.isnan(status["position"]):
self.logger.warning("Filter wheel position unknown, returning NaN")
return status["position"]
@property
def is_moving(self):
"""Is the filterwheel currently moving"""
status = self._driver.cfw_query(self._handle)
if status["status"] == "UNKNOWN":
self.logger.warning(f"{self} returned 'UNKNOWN' status")
return bool(status["status"] == "BUSY")
@property
def is_unidirectional(self):
"""Whether the wheel enforces one-way rotation.
Returns:
bool: Always True for SBIG filter wheels.
"""
# All SBIG filterwheels unidirectional?
return True
##################################################################################################
# Methods
##################################################################################################
[docs]
def connect(self):
"""
Connect to filter wheel. Not called by __init__ because we need the camera to be connected
first. The SBIG camera connect() method will call this once it's OK to do so.
"""
assert self.camera.is_connected, self.logger.error(f"Can't connect {self}, camera not connected")
self._driver = self.camera._driver
self._handle = self.camera._handle
info = self._driver.cfw_get_info(self._handle)
self._model = info["model"]
self._firmware_version = info["firmware_version"]
self._n_positions = info["n_positions"]
if len(self.filter_names) != self.n_positions:
msg = (
f"Number of names in filter_names ({len(self.filter_names)}) doesn't"
+ f" match number of positions in filter wheel ({self.n_positions})"
)
self.logger.error(msg)
raise ValueError(msg)
self.logger.info(f"Filter wheel {self} initialised")
self._connected = True
[docs]
def recalibrate(self):
"""
Reinitialises/recalibrates the filter wheel. It should not be necessary to call this as
SBIG filter wheels initialise and calibrate themselves on power up.
"""
self._driver.cfw_init(handle=self._handle, timeout=self._timeout)
self.logger.info(f"{self} recalibrated")
##################################################################################################
# Private methods
##################################################################################################
def _move_to(self, position):
self._driver.cfw_goto(
handle=self._handle,
position=position,
cfw_event=self._move_event,
timeout=self._timeout,
)
def _add_fits_keywords(self, header):
header = super()._add_fits_keywords(header)
header.set("FW-FW", self.firmware_version, "Filter wheel firmware version")
return header