def __init__( self, focuser: Union[str, IFocuser], camera: Union[str, IImageGrabber], series: FocusSeries, offset: bool = False, filters: Optional[Union[str, IFilters]] = None, filter_name: Optional[str] = None, binning: Optional[int] = None, **kwargs: Any, ): """Initialize a new auto focus system. Args: focuser: Name of IFocuser. camera: Name of ICamera. filters: Name of IFilters, if any. filter_name: Name of filter to set. offset: If True, offsets are used instead of absolute focus values. """ Module.__init__(self, **kwargs) # store focuser and camera self._focuser = focuser self._camera = camera self._filters = filters self._offset = offset self._abort = threading.Event() # create focus series self._series: FocusSeries = get_object(series, FocusSeries) # init camera settings mixin CameraSettingsMixin.__init__(self, filters=filters, filter_name=filter_name, binning=binning, **kwargs) # register exceptions if isinstance(camera, str): exc.register_exception( exc.RemoteError, 3, timespan=600, module=camera, callback=self._default_remote_error_callback) if isinstance(focuser, str): exc.register_exception( exc.RemoteError, 3, timespan=600, module=focuser, callback=self._default_remote_error_callback)
def __init__( self, fits_headers: Optional[Dict[str, Any]] = None, centre: Optional[Tuple[float, float]] = None, rotation: float = 0.0, flip: bool = False, filenames: str = "/cache/pyobs-{DAY-OBS|date:}-{FRAMENUM|string:04d}-{IMAGETYP|type}00.fits.gz", fits_namespaces: Optional[List[str]] = None, **kwargs: Any, ): """Creates a new BaseCamera. Args: fits_headers: Additional FITS headers. centre: (x, y) tuple of camera centre. rotation: Rotation east of north. flip: Whether or not to flip the image along its first axis. filenames: Template for file naming. fits_namespaces: List of namespaces for FITS headers that this camera should request """ Module.__init__(self, **kwargs) ImageFitsHeaderMixin.__init__( self, fits_namespaces=fits_namespaces, fits_headers=fits_headers, centre=centre, rotation=rotation, filenames=filenames, ) # check if self.comm is None: log.warning( "No comm module given, will not be able to signal new images!") # store self._flip = flip self._exposure_time: float = 0.0 self._image_type = ImageType.OBJECT # init camera self._exposure: Optional[ExposureInfo] = None self._camera_status = ExposureStatus.IDLE # multi-threading self.expose_abort = asyncio.Event() # register exception exc.register_exception(exc.GrabImageError, 3, timespan=600, callback=self._default_remote_error_callback)
def test_remote() -> None: # get triggered after 3 MotionErrors exc.register_exception(exc.MotionError, 3, throw=True) # raise two, shouldn't do anything exc.MotionError() exc.MotionError() # one InvocationError should trigger MotionError with pytest.raises(exc.SevereError) as exc_info: raise exc.InvocationError(module="test", exception=exc.MotionError()) assert isinstance(exc_info.value, exc.SevereError) assert isinstance(exc_info.value.exception, exc.InvocationError) assert isinstance(exc_info.value.exception.exception, exc.MotionError)
def test_remote_module() -> None: # get triggered after 3 MotionErrors exc.register_exception(exc.MotionError, 1, module="test", throw=True) # raise, shouldn't do anything exc.MotionError() exc.MotionError() # same with other remote errors with other module exc.InvocationError(module="wrong", exception=exc.MotionError()) exc.InvocationError(module="wrong", exception=exc.MotionError()) # but with correct module, it should with pytest.raises(exc.SevereError) as exc_info: raise exc.InvocationError(module="test", exception=exc.MotionError()) assert isinstance(exc_info.value, exc.SevereError) assert isinstance(exc_info.value.exception, exc.InvocationError) assert isinstance(exc_info.value.exception.exception, exc.MotionError)
def __init__( self, fits_headers: Optional[Dict[str, Any]] = None, min_altitude: float = 10, wait_for_dome: Optional[str] = None, **kwargs: Any, ): """Initialize a new base telescope. Args: fits_headers: Additional FITS headers to send. min_altitude: Minimal altitude for telescope. wait_for_dome: Name of dome module to wait for. """ Module.__init__(self, **kwargs) # store self._fits_headers = fits_headers if fits_headers is not None else {} self._min_altitude = min_altitude # some multi-threading stuff self._lock_moving = asyncio.Lock() self._abort_move = asyncio.Event() # celestial status self._celestial_headers: Dict[str, Any] = {} # add thread func self.add_background_task(self._celestial, True) # init mixins WeatherAwareMixin.__init__(self, **kwargs) MotionStatusMixin.__init__(self, **kwargs) WaitForMotionMixin.__init__( self, wait_for_modules=None if wait_for_dome is None else [wait_for_dome], wait_for_timeout=60000, wait_for_states=[MotionStatus.POSITIONED, MotionStatus.TRACKING], ) # register exception exc.register_exception(exc.MotionError, 3, timespan=600, callback=self._default_remote_error_callback)
def test_raise() -> None: event = asyncio.Event() async def cb(exception: PyObsError) -> None: assert isinstance(exception, exc.MotionError) event.set() # get triggered after 2 MotionErrors exc.register_exception(exc.MotionError, 2, callback=cb, throw=True) # 1st is fine exc.MotionError() # 2nd raises SevereError with pytest.raises(exc.SevereError) as exc_info: raise exc.MotionError() # nested exception is MotionError assert isinstance(exc_info.value, exc.SevereError) assert isinstance(exc_info.value.exception, exc.MotionError)
def test_callback() -> None: event = asyncio.Event() async def cb(exception: PyObsError) -> None: assert isinstance(exception, exc.MotionError) event.set() # get triggered after 3 MotionErrors exc.register_exception(exc.MotionError, 3, callback=cb) # 1st is fine exc.MotionError() assert event.is_set() is False # 2nd is fine exc.MotionError() assert event.is_set() is False # 3rd triggers callback exc.MotionError() assert event.is_set() is True
async def test_timespan() -> None: event = asyncio.Event() async def cb(exception: PyObsError) -> None: assert isinstance(exception, exc.MotionError) event.set() # get triggered after 3 MotionErrors exc.register_exception(exc.MotionError, 3, callback=cb, timespan=0.1, throw=True) # raise two and wait a little exc.MotionError() exc.MotionError() await asyncio.sleep(0.11) exc.MotionError() # raise two more exc.MotionError() exc.MotionError() with pytest.raises(exc.SevereError): raise exc.MotionError() assert event.is_set()
def __init__(self, **kwargs: Any): """Initialize a new base dome.""" BaseRoof.__init__(self, **kwargs) # register exception exc.register_exception(exc.MotionError, 3, timespan=600, callback=self._default_remote_error_callback)
def __init__( self, telescope: Union[str, ITelescope], camera: Union[str, ICamera], flat_fielder: Optional[Union[Dict[str, Any], FlatFielder]], filters: Optional[Union[str, IFilters]] = None, log_file: Optional[str] = None, **kwargs: Any, ): """Initialize a new flat fielder. Args: telescope: Name of ITelescope. camera: Name of ICamera. flat_fielder: Flat field object to use. filters: Name of IFilters, if any. log_file: Name of file to store flat field log in. """ Module.__init__(self, **kwargs) # store telescope, camera, and filters self._telescope = telescope self._camera = camera self._filter_wheel = filters self._abort = asyncio.Event() self._running = False # flat fielder self._flat_fielder = self.get_object(flat_fielder, FlatFielder, callback=self.callback) # init log file self._publisher = None if log_file is None else CsvPublisher(log_file) # init binning and filter self._binning = (1, 1) self._filter: Optional[str] = None # need to add IFilters interface? if self._filter_wheel is not None: # check filters if not self._flat_fielder.has_filters: raise ValueError( "Filter wheel module given in config, but no filters in functions." ) # add it # self.__class__ = type('FlatFieldFilter', (FlatField, IFilters), {}) # register exceptions if isinstance(camera, str): exc.register_exception( exc.RemoteError, 3, timespan=600, module=camera, callback=self._default_remote_error_callback) if isinstance(telescope, str): exc.register_exception( exc.RemoteError, 3, timespan=600, module=telescope, callback=self._default_remote_error_callback) if isinstance(filters, str): exc.register_exception( exc.RemoteError, 3, timespan=600, module=filters, callback=self._default_remote_error_callback)
def test_register() -> None: async def cb(exception: PyObsError) -> None: pass exc.register_exception(exc.MotionError, 5, callback=cb) assert len(exc._handlers) == 1