[docs]classBaseCameraActor(BaseActor):"""Base class for a camera CLU-like actor class. Expands a `CLU <https://clu.readthedocs.io/en/latest/>`__ actor to receive commands, interact with the camera system, and reply to the commander. This base class needs to be subclassed along with the desired implementation of CLU `~clu.actor.BaseActor`. For example :: from clu.actor import AMQPActor class MyCameraActor(BaseCameraActor, AMQPActor): pass Parameters ---------- camera_system The camera system, already instantiated. default_cameras A list of camera names or UIDs that define what cameras to use by default in most command. command_parser The list of commands to use. It must be a command group deriving from `~clu.parsers.click.CluGroup` containing all the commands to use. If ``commands=None``, uses the internal command set. schema The path to the JSONSchema file with the actor datamodel. If ``"internal"``, uses the default ``basecam`` model; `None` disables model validation. args,kwars Arguments and keyword arguments to be passed to the actor class. """def__init__(self,camera_system:CameraSystem,*args,default_cameras:Union[List[str],str,None]=None,command_parser:clu.parsers.click.CluGroup|None=None,schema:Optional[str]="internal",**kwargs,):self._check_is_subclass()assertcamera_systemisnotNoneself.camera_system=camera_systemassertself.camera_system.camera_class# Add actor to camera class context and all connected cameras.self.camera_system.camera_class.fits_model.context.update({"__actor__":self})forcamerainself.camera_system.cameras:camera.fits_model.context.update({"__actor__":self})#: An `.EventListener` that can be used to wait or respond to events.self.listener=EventListener()self.camera_system.notifier.register_listener(self.listener)self.log:SDSSLoggerself.parser=command_parserorcommands.camera_parserifschema=="internal":schema=os.path.join(os.path.dirname(__file__),"schema.json")super().__init__(*args,schema=schema,**kwargs)# Add commands that depend on what mixins the base camera has# been subclassed with.ifself.parser==commands.camera_parser:self._add_optional_commands()# Output camera_system log messages as keywords.actor_handler=ActorHandler(self,code_mapping={logging.INFO:"d"},filter_warnings=[CameraWarning,UserWarning],)actor_handler.setLevel(logging.INFO)self.camera_system.logger.addHandler(actor_handler)self.default_cameras=Noneself.set_default_cameras(default_cameras)def_check_is_subclass(self):"""Checks if the object is a subclass of a CLU actor."""error="BaseCameraActor must be sub-classed along with a CLU actor class."bases=self.__class__.__bases__assertissubclass(self.__class__,BaseCameraActor),error# Check that at least one of the bases is a sublass of BaseActorforbaseinbases:ifbase==BaseCameraActor:continueifissubclass(base,BaseActor):returnraiseRuntimeError(error)def_add_optional_commands(self):"""Adds commands and groups based on the mixins present."""camera_class=self.camera_system.camera_classassertcamera_classisnotNoneformixinincamera_class.__bases__:mixin_name=mixin.__name__ifmixin_nameincommands._MIXIN_TO_COMMANDS:forcommandincommands._MIXIN_TO_COMMANDS[mixin_name]:self.parser.add_command(command)
[docs]defset_default_cameras(self,cameras:Union[str,List[str],None]=None):"""Sets the camera(s) that will be used by default. These cameras will be used by default when a command is issued without listing the cameras to command. Parameters ---------- cameras : str or list A list of camera names or a string with comma-separated camera names. If `None`, no cameras will be considered default and commands will fail if they do not specify a camera. """ifcamerasisNone:self.default_cameras=Nonereturnifisinstance(cameras,str):self.default_cameras=cameras.split(",")elifisinstance(cameras,(list,tuple)):self.default_cameras=list(cameras)else:raiseValueError(f"invalid data type for cameras={cameras!r}")connected_cameras=[camera.nameforcamerainself.camera_system.cameras]forcamerainself.default_cameras:ifcameranotinconnected_cameras:self.log.warning(f"camera {camera!r} made default but is not connected.")
[docs]classCameraActor(BaseCameraActor,JSONActor):"""A camera actor that replies with JSONs using `~clu.actor.JSONActor`."""pass