diff --git a/src/guitastro/__init__.py b/src/guitastro/__init__.py index 585812f..33778d7 100644 --- a/src/guitastro/__init__.py +++ b/src/guitastro/__init__.py @@ -140,6 +140,11 @@ guitastro.component_mount_pointing .. automodule:: guitastro.component_mount_pointing :members: +guitastro.component_sensor_detector +------------------------------------ +.. automodule:: guitastro.component_sensor_detector + :members: + guitastro.device ------------------- .. automodule:: guitastro.device diff --git a/src/guitastro/component_sensor_detector.py b/src/guitastro/component_sensor_detector.py new file mode 100644 index 0000000..80eca7d --- /dev/null +++ b/src/guitastro/component_sensor_detector.py @@ -0,0 +1,273 @@ +try: + from .siteobs import Siteobs +except: + from siteobs import Siteobs + +try: + from .ima import Ima +except: + from ima import Ima + +try: + from .etc import ExposureTimeCalculator +except: + from etc import ExposureTimeCalculator + +try: + from .component import Component, ComponentException +except: + from component import Component, ComponentException + +try: + from .guitastrotools import GuitastroException, GuitastroTools +except: + from guitastrotools import GuitastroException, GuitastroTools + +# ##################################################################### +# ##################################################################### +# ##################################################################### +# Class Component Sensor Detector +# ##################################################################### +# ##################################################################### +# ##################################################################### + +class ComponentSensorDetectorException(GuitastroException): + + ERR_DETECTOR_IS_EXPOSING = 1 + ERR_DETECTOR_IS_READING = 2 + + errors = [""]*3 + errors[ERR_DETECTOR_IS_EXPOSING] = "The detector is in exposure. Cannot start other exposures" + errors[ERR_DETECTOR_IS_READING] = "The detector is reading. Cannot start other exposures" + + +class ComponentSensorDetector(ComponentSensorDetectorException, Component, GuitastroTools): + """Component for Sensor detector + + Implement only simulation operations. + + Usage : ComponentSensorDetector() + """ + + # --- same as sensoraxis.py + SENSOR_STATE_UNKNOWN = -1 + SENSOR_STATE_STOPED = 0 + SENSOR_STATE_IDLE = 1 + SENSOR_STATE_EXPOSING = 2 + SENSOR_STATE_READING = 3 + + # ===================================================================== + # methods + # ===================================================================== + + # ------------ init + + def _my_init_params(self, param_optionals: dict, sensor_types: dict): + # --- This method could be overriden + return param_optionals, sensor_types + + def init(self, *args, **kwargs): + """ + Conversion from Uniform Python object into protocol language + Usage : ComponentSensorDetector("HADEC", name="Test") + """ + # === Parameters of the command line + # --- Dico of optional parameters for all axis_types + param_optionals = {} + param_optionals["MODEL"] = (str, "") + param_optionals["MANUFACTURER"] = (str, "") + param_optionals["SERIAL_NUMBER"] = (str, "") + param_optionals["REAL"] = (bool, False) + param_optionals["DESCRIPTION"] = (str, "No description.") + param_optionals["SITE"] = (Siteobs,"GPS 0 E 45 100") + param_optionals["LOGO_FILE"] = (str,"") + param_optionals["ETC"] = (ExposureTimeCalculator, None) + # --- Dico of axis_types and their parameters + sensor_types = {} + sensor_types["CCD"]= {"MANDATORY" : {"NAME":[str,"Unknown"]}, "OPTIONAL" : {"LABEL":[str,"CCD Sensor"]} } + sensor_types["CMOS"]= {"MANDATORY" : {"NAME":[str,"Unknown"]}, "OPTIONAL" : {"LABEL":[str,"CMOS Sensor"]} } + # --- Add params and types when inherited + param_optionals, sensor_types = self._my_init_params(param_optionals, sensor_types) + # --- Decode args and kwargs parameters + self._sensor_params = self.decode_args_kwargs(0, sensor_types, param_optionals, *args, **kwargs) + self._sensor_type = self._sensor_params["SELECTED_ARG"] + # === Observatory location for ephemeris + if str(type(self._sensor_params["SITE"])) == "": + self.siteobs = self._sensor_params["SITE"] + else: + self.siteobs = Siteobs(self._sensor_params["SITE"]) + # === Image in memory + self.ima = Ima() + self.ima.longitude(self.siteobs.longitude) + if str(type(self._sensor_params["ETC"])) == "": + self.ima.etc = self._sensor_params["ETC"] + # === Name + self.name = self._sensor_params["NAME"] + # === Initial state real or simulation + real = self._sensor_params["REAL"] + # === Call init1 (inherited from Component. Will be overriden by a concrete method) + self._my_init1(*args, **kwargs) + # === Initialisation of axis list according the sensor_type + # === Default axes setup + # === Call init2 (inherited from Component. Will be overriden by a concrete method) + self._my_init2(*args, **kwargs) + # === Default database + param = {} + param['exptime'] = 0.1 + param['binning'] = [1, 1] + self._queue.put(param) + + # ------------ prop + + def prop(self): + """Component property minimal concrete method + + Extended properties will be added in the method _my_prop. + """ + prop = {} + prop['category'] = 'SensorDetector' + prop['actions'] = ['GET', 'SET', 'DO'] + prop['DO'] = {} + prop['DO']['NATIVE'] = "The message is sent to the device with no transformation" + prop['DO']['ACQ'] = {} + prop['DO']['ACQ']['START'] = "Start a new image acquisition" + prop['DO']['ACQ']['STOP'] = "Stop the current sensor image with a readout" + prop['DO']['ACQ']['CANCEL'] = "Cancel the current sensor image without readout" + prop = self._my_prop(prop) + return prop + + # ------------ do + + def _do_stop(self, *args, **kwargs): + operation = args[0].upper() + # --- make the simulation + self.log = f"stop simulation of {operation}" + self.database.query("motion_simu", self.SENSOR_STATE_STOPED) + # --- call the real + if self.real: + self._my_do_stop(*args, **kwargs) + + def _do(self, *args, **kwargs): + """Do an action of the component. + Args: + + *args: List of operations extracted from split of the command: + + * args[0]: main operation + * args[1]: sub operation + + Returns: + + Result depending the operation. + """ + result = None + self._verify_nargs(1, *args) + operation = args[0].upper() + operations = list(self.prop()['DO'].keys()) + if operation not in operations: + msg = f"{operation} not found amongst {operations}" + raise ComponentException(ComponentException.ERR_OPERATION_NOT_FOUND, msg) + # --- + kwargs['operation'] = operation + if operation == "START": + # For real and simu + result = self._do_start(*args, **kwargs) + elif operation == "STOP": + # For real and simu + result = self._do_stop(*args, **kwargs) + # --- only call the real method + self.log = f"start operation {operation}" + if self.real: + result = self._my_do(*args, **kwargs) + return self._fresult(result) + + def _my_do(self, *args, **kwargs): + value = None + return value + + # ------------ set + + def _my_set(self, *args, **kwargs): + return args, kwargs + + # ------------ get + + def _my_get_final(self, *args, **kwargs): + # This method should be overriden + pass + + def _my_get(self, *args, **kwargs): + self._my_get_final(*args, **kwargs) + return None + + # ===================================================================== + # ===================================================================== + # Ima methods + # ===================================================================== + # ===================================================================== + + # ------------ conversion int -> string for human output + + def status2string(self, status:int, verb:bool= False): + if status == self.SENSOR_STATE_STOPED: + msg = "stoped" if verb else "stop" + elif status == self.SENSOR_STATE_IDLE: + msg = "idle" if verb else "idle" + elif status == self.SENSOR_STATE_EXPOSING: + msg = "exposing" if verb else "expose" + elif status == self.SENSOR_STATE_READING: + msg = "reading" if verb else "read" + else: + msg = "unknown" if verb else "unk" + return msg + + + +# ##################################################################### +# ##################################################################### +# ##################################################################### +# Main +# ##################################################################### +# ##################################################################### +# ##################################################################### + +if __name__ == "__main__": + + default = 0 + example = input(f"Select the example (0 to 0) ({default}) ") + try: + example = int(example) + except: + example = default + + print("Example = {}".format(example)) + + import time + if example == 0: + """ + Simple camera simulator + """ + # --- siteobs + siteobs = Siteobs("GPS 0 E 49 200") + # --- horizon + siteobs.horizon_altaz = [(0,40), (180,0), (360,40)] + # --- Image simulator + etc = ExposureTimeCalculator() + etc.camera("Audine Kaf401ME") + etc.optics("Takahashi_180ED") + # --- Component init + comp = ComponentSensorDetector("CCD", name="test", site=siteobs, etc=etc) + comp.verbose = 1 + comp.command("SET", "exptime", 1.0) + comp.command("SET", "binning", [1, 1]) + # --- Start the ACQ + comp.command("DO", "ACQ", "START") + k = 0 + while k<3: + # --- Get the current coordinates + status = comp.command("GET", "status") + print(f"{k:2d} status = {status} {comp.status2string(status)}") + time.sleep(2) + k += 1 + + diff --git a/src/guitastro/filenames.py b/src/guitastro/filenames.py index 6b79e56..80c6c39 100644 --- a/src/guitastro/filenames.py +++ b/src/guitastro/filenames.py @@ -3315,3 +3315,42 @@ if __name__ == "__main__": in_fullname = "/home/myuser/messier63.fits.gz" out_fullname = fn.join(in_fullname) print(out_fullname) + + if example == 16: + """ + Create many contexts + """ + contexts = [] + contexts.append({'context':"sequences", 'description':"Sequence files (.p, .f)", 'rootdir':"/tmp/pyros/sequences", 'pathnaming':"PyROS.seq.1"}) + contexts.append({'context':"img/darks/L0", 'description':"Dark images L0 (individuals)", 'rootdir':"/tmp/pyros/img/darks/l0", 'pathnaming':"PyROS.img.1", 'extension':".fit"}) + contexts.append({'context':"img/darks/L1", 'description':"Dark images L1 (stacks)", 'rootdir':"/tmp/pyros/img/darks/l1", 'pathnaming':"PyROS.img.1", 'extension':".fit"}) + + fn = FileNames() + + for context in fn.fcontexts: + fn.fcontext = context # select the context + if fn.fcontext == "default": + continue + del fn.fcontext + + for context in contexts: + + fn.fcontext_create(context['context'], context['description']) + fn.fcontext = context['context'] # select the context + if context.get('rootdir') != None: + fn.rootdir = context.get('rootdir') + if context.get('naming') != None: + fn.naming = context.get('naming') + if context.get('pathing') != None: + fn.pathing = context.get('pathing') + if context.get('pathnaming') != None: + fn.pathnaming = context.get('pathnaming') + if context.get('extension') != None: + fn.extension = context.get('extension') + + for context in fn.fcontexts: + fn.fcontext = context # select the context + if fn.fcontext == "default": + continue + print(f"{fn.fcontext} : {fn.fcontext_value('description')}") + diff --git a/src/guitastro/guitastrotools.py b/src/guitastro/guitastrotools.py index 99c23c0..614e63b 100644 --- a/src/guitastro/guitastrotools.py +++ b/src/guitastro/guitastrotools.py @@ -650,6 +650,6 @@ if __name__ == "__main__": Create initial source code of a component file. """ gta1 = GuitastroDev() - res = gta1.create_component("DetectorFocuser", "MountyPointing") + res = gta1.create_component("MountPointing", "SensorDetector") print(f"res={res}") -- libgit2 0.21.2