Commit 1b79ab46538942d56deeb33d3f9c5c71bb3a20e9
1 parent
c1f67e41
Exists in
master
Add a new component for cameras
Showing
4 changed files
with
318 additions
and
1 deletions
Show diff stats
src/guitastro/__init__.py
... | ... | @@ -140,6 +140,11 @@ guitastro.component_mount_pointing |
140 | 140 | .. automodule:: guitastro.component_mount_pointing |
141 | 141 | :members: |
142 | 142 | |
143 | +guitastro.component_sensor_detector | |
144 | +------------------------------------ | |
145 | +.. automodule:: guitastro.component_sensor_detector | |
146 | + :members: | |
147 | + | |
143 | 148 | guitastro.device |
144 | 149 | ------------------- |
145 | 150 | .. automodule:: guitastro.device | ... | ... |
... | ... | @@ -0,0 +1,273 @@ |
1 | +try: | |
2 | + from .siteobs import Siteobs | |
3 | +except: | |
4 | + from siteobs import Siteobs | |
5 | + | |
6 | +try: | |
7 | + from .ima import Ima | |
8 | +except: | |
9 | + from ima import Ima | |
10 | + | |
11 | +try: | |
12 | + from .etc import ExposureTimeCalculator | |
13 | +except: | |
14 | + from etc import ExposureTimeCalculator | |
15 | + | |
16 | +try: | |
17 | + from .component import Component, ComponentException | |
18 | +except: | |
19 | + from component import Component, ComponentException | |
20 | + | |
21 | +try: | |
22 | + from .guitastrotools import GuitastroException, GuitastroTools | |
23 | +except: | |
24 | + from guitastrotools import GuitastroException, GuitastroTools | |
25 | + | |
26 | +# ##################################################################### | |
27 | +# ##################################################################### | |
28 | +# ##################################################################### | |
29 | +# Class Component Sensor Detector | |
30 | +# ##################################################################### | |
31 | +# ##################################################################### | |
32 | +# ##################################################################### | |
33 | + | |
34 | +class ComponentSensorDetectorException(GuitastroException): | |
35 | + | |
36 | + ERR_DETECTOR_IS_EXPOSING = 1 | |
37 | + ERR_DETECTOR_IS_READING = 2 | |
38 | + | |
39 | + errors = [""]*3 | |
40 | + errors[ERR_DETECTOR_IS_EXPOSING] = "The detector is in exposure. Cannot start other exposures" | |
41 | + errors[ERR_DETECTOR_IS_READING] = "The detector is reading. Cannot start other exposures" | |
42 | + | |
43 | + | |
44 | +class ComponentSensorDetector(ComponentSensorDetectorException, Component, GuitastroTools): | |
45 | + """Component for Sensor detector | |
46 | + | |
47 | + Implement only simulation operations. | |
48 | + | |
49 | + Usage : ComponentSensorDetector() | |
50 | + """ | |
51 | + | |
52 | + # --- same as sensoraxis.py | |
53 | + SENSOR_STATE_UNKNOWN = -1 | |
54 | + SENSOR_STATE_STOPED = 0 | |
55 | + SENSOR_STATE_IDLE = 1 | |
56 | + SENSOR_STATE_EXPOSING = 2 | |
57 | + SENSOR_STATE_READING = 3 | |
58 | + | |
59 | + # ===================================================================== | |
60 | + # methods | |
61 | + # ===================================================================== | |
62 | + | |
63 | + # ------------ init | |
64 | + | |
65 | + def _my_init_params(self, param_optionals: dict, sensor_types: dict): | |
66 | + # --- This method could be overriden | |
67 | + return param_optionals, sensor_types | |
68 | + | |
69 | + def init(self, *args, **kwargs): | |
70 | + """ | |
71 | + Conversion from Uniform Python object into protocol language | |
72 | + Usage : ComponentSensorDetector("HADEC", name="Test") | |
73 | + """ | |
74 | + # === Parameters of the command line | |
75 | + # --- Dico of optional parameters for all axis_types | |
76 | + param_optionals = {} | |
77 | + param_optionals["MODEL"] = (str, "") | |
78 | + param_optionals["MANUFACTURER"] = (str, "") | |
79 | + param_optionals["SERIAL_NUMBER"] = (str, "") | |
80 | + param_optionals["REAL"] = (bool, False) | |
81 | + param_optionals["DESCRIPTION"] = (str, "No description.") | |
82 | + param_optionals["SITE"] = (Siteobs,"GPS 0 E 45 100") | |
83 | + param_optionals["LOGO_FILE"] = (str,"") | |
84 | + param_optionals["ETC"] = (ExposureTimeCalculator, None) | |
85 | + # --- Dico of axis_types and their parameters | |
86 | + sensor_types = {} | |
87 | + sensor_types["CCD"]= {"MANDATORY" : {"NAME":[str,"Unknown"]}, "OPTIONAL" : {"LABEL":[str,"CCD Sensor"]} } | |
88 | + sensor_types["CMOS"]= {"MANDATORY" : {"NAME":[str,"Unknown"]}, "OPTIONAL" : {"LABEL":[str,"CMOS Sensor"]} } | |
89 | + # --- Add params and types when inherited | |
90 | + param_optionals, sensor_types = self._my_init_params(param_optionals, sensor_types) | |
91 | + # --- Decode args and kwargs parameters | |
92 | + self._sensor_params = self.decode_args_kwargs(0, sensor_types, param_optionals, *args, **kwargs) | |
93 | + self._sensor_type = self._sensor_params["SELECTED_ARG"] | |
94 | + # === Observatory location for ephemeris | |
95 | + if str(type(self._sensor_params["SITE"])) == "<class 'siteobs.Siteobs'>": | |
96 | + self.siteobs = self._sensor_params["SITE"] | |
97 | + else: | |
98 | + self.siteobs = Siteobs(self._sensor_params["SITE"]) | |
99 | + # === Image in memory | |
100 | + self.ima = Ima() | |
101 | + self.ima.longitude(self.siteobs.longitude) | |
102 | + if str(type(self._sensor_params["ETC"])) == "<class 'etc.ExposureTimeCalculator'>": | |
103 | + self.ima.etc = self._sensor_params["ETC"] | |
104 | + # === Name | |
105 | + self.name = self._sensor_params["NAME"] | |
106 | + # === Initial state real or simulation | |
107 | + real = self._sensor_params["REAL"] | |
108 | + # === Call init1 (inherited from Component. Will be overriden by a concrete method) | |
109 | + self._my_init1(*args, **kwargs) | |
110 | + # === Initialisation of axis list according the sensor_type | |
111 | + # === Default axes setup | |
112 | + # === Call init2 (inherited from Component. Will be overriden by a concrete method) | |
113 | + self._my_init2(*args, **kwargs) | |
114 | + # === Default database | |
115 | + param = {} | |
116 | + param['exptime'] = 0.1 | |
117 | + param['binning'] = [1, 1] | |
118 | + self._queue.put(param) | |
119 | + | |
120 | + # ------------ prop | |
121 | + | |
122 | + def prop(self): | |
123 | + """Component property minimal concrete method | |
124 | + | |
125 | + Extended properties will be added in the method _my_prop. | |
126 | + """ | |
127 | + prop = {} | |
128 | + prop['category'] = 'SensorDetector' | |
129 | + prop['actions'] = ['GET', 'SET', 'DO'] | |
130 | + prop['DO'] = {} | |
131 | + prop['DO']['NATIVE'] = "The message is sent to the device with no transformation" | |
132 | + prop['DO']['ACQ'] = {} | |
133 | + prop['DO']['ACQ']['START'] = "Start a new image acquisition" | |
134 | + prop['DO']['ACQ']['STOP'] = "Stop the current sensor image with a readout" | |
135 | + prop['DO']['ACQ']['CANCEL'] = "Cancel the current sensor image without readout" | |
136 | + prop = self._my_prop(prop) | |
137 | + return prop | |
138 | + | |
139 | + # ------------ do | |
140 | + | |
141 | + def _do_stop(self, *args, **kwargs): | |
142 | + operation = args[0].upper() | |
143 | + # --- make the simulation | |
144 | + self.log = f"stop simulation of {operation}" | |
145 | + self.database.query("motion_simu", self.SENSOR_STATE_STOPED) | |
146 | + # --- call the real | |
147 | + if self.real: | |
148 | + self._my_do_stop(*args, **kwargs) | |
149 | + | |
150 | + def _do(self, *args, **kwargs): | |
151 | + """Do an action of the component. | |
152 | + Args: | |
153 | + | |
154 | + *args: List of operations extracted from split of the command: | |
155 | + | |
156 | + * args[0]: main operation | |
157 | + * args[1]: sub operation | |
158 | + | |
159 | + Returns: | |
160 | + | |
161 | + Result depending the operation. | |
162 | + """ | |
163 | + result = None | |
164 | + self._verify_nargs(1, *args) | |
165 | + operation = args[0].upper() | |
166 | + operations = list(self.prop()['DO'].keys()) | |
167 | + if operation not in operations: | |
168 | + msg = f"{operation} not found amongst {operations}" | |
169 | + raise ComponentException(ComponentException.ERR_OPERATION_NOT_FOUND, msg) | |
170 | + # --- | |
171 | + kwargs['operation'] = operation | |
172 | + if operation == "START": | |
173 | + # For real and simu | |
174 | + result = self._do_start(*args, **kwargs) | |
175 | + elif operation == "STOP": | |
176 | + # For real and simu | |
177 | + result = self._do_stop(*args, **kwargs) | |
178 | + # --- only call the real method | |
179 | + self.log = f"start operation {operation}" | |
180 | + if self.real: | |
181 | + result = self._my_do(*args, **kwargs) | |
182 | + return self._fresult(result) | |
183 | + | |
184 | + def _my_do(self, *args, **kwargs): | |
185 | + value = None | |
186 | + return value | |
187 | + | |
188 | + # ------------ set | |
189 | + | |
190 | + def _my_set(self, *args, **kwargs): | |
191 | + return args, kwargs | |
192 | + | |
193 | + # ------------ get | |
194 | + | |
195 | + def _my_get_final(self, *args, **kwargs): | |
196 | + # This method should be overriden | |
197 | + pass | |
198 | + | |
199 | + def _my_get(self, *args, **kwargs): | |
200 | + self._my_get_final(*args, **kwargs) | |
201 | + return None | |
202 | + | |
203 | + # ===================================================================== | |
204 | + # ===================================================================== | |
205 | + # Ima methods | |
206 | + # ===================================================================== | |
207 | + # ===================================================================== | |
208 | + | |
209 | + # ------------ conversion int -> string for human output | |
210 | + | |
211 | + def status2string(self, status:int, verb:bool= False): | |
212 | + if status == self.SENSOR_STATE_STOPED: | |
213 | + msg = "stoped" if verb else "stop" | |
214 | + elif status == self.SENSOR_STATE_IDLE: | |
215 | + msg = "idle" if verb else "idle" | |
216 | + elif status == self.SENSOR_STATE_EXPOSING: | |
217 | + msg = "exposing" if verb else "expose" | |
218 | + elif status == self.SENSOR_STATE_READING: | |
219 | + msg = "reading" if verb else "read" | |
220 | + else: | |
221 | + msg = "unknown" if verb else "unk" | |
222 | + return msg | |
223 | + | |
224 | + | |
225 | + | |
226 | +# ##################################################################### | |
227 | +# ##################################################################### | |
228 | +# ##################################################################### | |
229 | +# Main | |
230 | +# ##################################################################### | |
231 | +# ##################################################################### | |
232 | +# ##################################################################### | |
233 | + | |
234 | +if __name__ == "__main__": | |
235 | + | |
236 | + default = 0 | |
237 | + example = input(f"Select the example (0 to 0) ({default}) ") | |
238 | + try: | |
239 | + example = int(example) | |
240 | + except: | |
241 | + example = default | |
242 | + | |
243 | + print("Example = {}".format(example)) | |
244 | + | |
245 | + import time | |
246 | + if example == 0: | |
247 | + """ | |
248 | + Simple camera simulator | |
249 | + """ | |
250 | + # --- siteobs | |
251 | + siteobs = Siteobs("GPS 0 E 49 200") | |
252 | + # --- horizon | |
253 | + siteobs.horizon_altaz = [(0,40), (180,0), (360,40)] | |
254 | + # --- Image simulator | |
255 | + etc = ExposureTimeCalculator() | |
256 | + etc.camera("Audine Kaf401ME") | |
257 | + etc.optics("Takahashi_180ED") | |
258 | + # --- Component init | |
259 | + comp = ComponentSensorDetector("CCD", name="test", site=siteobs, etc=etc) | |
260 | + comp.verbose = 1 | |
261 | + comp.command("SET", "exptime", 1.0) | |
262 | + comp.command("SET", "binning", [1, 1]) | |
263 | + # --- Start the ACQ | |
264 | + comp.command("DO", "ACQ", "START") | |
265 | + k = 0 | |
266 | + while k<3: | |
267 | + # --- Get the current coordinates | |
268 | + status = comp.command("GET", "status") | |
269 | + print(f"{k:2d} status = {status} {comp.status2string(status)}") | |
270 | + time.sleep(2) | |
271 | + k += 1 | |
272 | + | |
273 | + | ... | ... |
src/guitastro/filenames.py
... | ... | @@ -3315,3 +3315,42 @@ if __name__ == "__main__": |
3315 | 3315 | in_fullname = "/home/myuser/messier63.fits.gz" |
3316 | 3316 | out_fullname = fn.join(in_fullname) |
3317 | 3317 | print(out_fullname) |
3318 | + | |
3319 | + if example == 16: | |
3320 | + """ | |
3321 | + Create many contexts | |
3322 | + """ | |
3323 | + contexts = [] | |
3324 | + contexts.append({'context':"sequences", 'description':"Sequence files (.p, .f)", 'rootdir':"/tmp/pyros/sequences", 'pathnaming':"PyROS.seq.1"}) | |
3325 | + contexts.append({'context':"img/darks/L0", 'description':"Dark images L0 (individuals)", 'rootdir':"/tmp/pyros/img/darks/l0", 'pathnaming':"PyROS.img.1", 'extension':".fit"}) | |
3326 | + contexts.append({'context':"img/darks/L1", 'description':"Dark images L1 (stacks)", 'rootdir':"/tmp/pyros/img/darks/l1", 'pathnaming':"PyROS.img.1", 'extension':".fit"}) | |
3327 | + | |
3328 | + fn = FileNames() | |
3329 | + | |
3330 | + for context in fn.fcontexts: | |
3331 | + fn.fcontext = context # select the context | |
3332 | + if fn.fcontext == "default": | |
3333 | + continue | |
3334 | + del fn.fcontext | |
3335 | + | |
3336 | + for context in contexts: | |
3337 | + | |
3338 | + fn.fcontext_create(context['context'], context['description']) | |
3339 | + fn.fcontext = context['context'] # select the context | |
3340 | + if context.get('rootdir') != None: | |
3341 | + fn.rootdir = context.get('rootdir') | |
3342 | + if context.get('naming') != None: | |
3343 | + fn.naming = context.get('naming') | |
3344 | + if context.get('pathing') != None: | |
3345 | + fn.pathing = context.get('pathing') | |
3346 | + if context.get('pathnaming') != None: | |
3347 | + fn.pathnaming = context.get('pathnaming') | |
3348 | + if context.get('extension') != None: | |
3349 | + fn.extension = context.get('extension') | |
3350 | + | |
3351 | + for context in fn.fcontexts: | |
3352 | + fn.fcontext = context # select the context | |
3353 | + if fn.fcontext == "default": | |
3354 | + continue | |
3355 | + print(f"{fn.fcontext} : {fn.fcontext_value('description')}") | |
3356 | + | ... | ... |
src/guitastro/guitastrotools.py
... | ... | @@ -650,6 +650,6 @@ if __name__ == "__main__": |
650 | 650 | Create initial source code of a component file. |
651 | 651 | """ |
652 | 652 | gta1 = GuitastroDev() |
653 | - res = gta1.create_component("DetectorFocuser", "MountyPointing") | |
653 | + res = gta1.create_component("MountPointing", "SensorDetector") | |
654 | 654 | print(f"res={res}") |
655 | 655 | ... | ... |