Skip to content

Commit a19a9eb

Browse files
committed
Added type hints
1 parent fb4273d commit a19a9eb

File tree

3 files changed

+61
-41
lines changed

3 files changed

+61
-41
lines changed

pyobs_fli/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
__title__ = 'FLI camera modules'
55

66
from .flicamera import FliCamera
7+
8+
9+
__all__ = ['FliCamera']

pyobs_fli/flicamera.py

+37-22
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
import threading
44
from datetime import datetime
55
import time
6-
from typing import Tuple
7-
from astropy.io import fits
6+
from typing import Tuple, Any, Optional, Dict
7+
import numpy as np
88

99
from pyobs.interfaces import ICamera, IWindow, IBinning, ICooling
1010
from pyobs.modules.camera.basecamera import BaseCamera
1111
from pyobs.images import Image
1212
from pyobs.utils.enums import ExposureStatus
13-
from pyobs_fli.flidriver import *
13+
from pyobs_fli.flidriver import FliDriver, FliTemperature
1414

1515

1616
log = logging.getLogger(__name__)
@@ -20,23 +20,23 @@ class FliCamera(BaseCamera, ICamera, IWindow, IBinning, ICooling):
2020
"""A pyobs module for FLI cameras."""
2121
__module__ = 'pyobs_fli'
2222

23-
def __init__(self, setpoint: float = -20, *args, **kwargs):
23+
def __init__(self, setpoint: float = -20., **kwargs: Any):
2424
"""Initializes a new FliCamera.
2525
2626
Args:
2727
setpoint: Cooling temperature setpoint.
2828
"""
29-
BaseCamera.__init__(self, *args, **kwargs)
29+
BaseCamera.__init__(self, **kwargs)
3030

3131
# variables
32-
self._driver = None
33-
self._temp_setpoint = setpoint
32+
self._driver: Optional[FliDriver] = None
33+
self._temp_setpoint: Optional[float] = setpoint
3434

3535
# window and binning
36-
self._window = None
37-
self._binning = None
36+
self._window = (0, 0, 0, 0)
37+
self._binning = (1, 1)
3838

39-
def open(self):
39+
def open(self) -> None:
4040
"""Open module."""
4141
BaseCamera.open(self)
4242

@@ -58,9 +58,10 @@ def open(self):
5858
self._window, self._binning = self._driver.get_window_binning()
5959

6060
# set cooling
61-
self.set_cooling(True, self._temp_setpoint)
61+
if self._temp_setpoint is not None:
62+
self.set_cooling(True, self._temp_setpoint)
6263

63-
def close(self):
64+
def close(self) -> None:
6465
"""Close the module."""
6566
BaseCamera.close(self)
6667

@@ -70,31 +71,33 @@ def close(self):
7071
self._driver.close()
7172
self._driver = None
7273

73-
def get_full_frame(self, *args, **kwargs) -> Tuple[int, int, int, int]:
74+
def get_full_frame(self, **kwargs: Any) -> Tuple[int, int, int, int]:
7475
"""Returns full size of CCD.
7576
7677
Returns:
7778
Tuple with left, top, width, and height set.
7879
"""
80+
if self._driver is None:
81+
raise ValueError('No camera driver.')
7982
return self._driver.get_full_frame()
8083

81-
def get_window(self, *args, **kwargs) -> Tuple[int, int, int, int]:
84+
def get_window(self, **kwargs: Any) -> Tuple[int, int, int, int]:
8285
"""Returns the camera window.
8386
8487
Returns:
8588
Tuple with left, top, width, and height set.
8689
"""
8790
return self._window
8891

89-
def get_binning(self, *args, **kwargs) -> Tuple[int, int]:
92+
def get_binning(self, **kwargs: Any) -> Tuple[int, int]:
9093
"""Returns the camera binning.
9194
9295
Returns:
9396
Tuple with x and y.
9497
"""
9598
return self._binning
9699

97-
def set_window(self, left: float, top: float, width: float, height: float, *args, **kwargs):
100+
def set_window(self, left: int, top: int, width: int, height: int, **kwargs: Any) -> None:
98101
"""Set the camera window.
99102
100103
Args:
@@ -109,7 +112,7 @@ def set_window(self, left: float, top: float, width: float, height: float, *args
109112
self._window = (left, top, width, height)
110113
log.info('Setting window to %dx%d at %d,%d...', width, height, left, top)
111114

112-
def set_binning(self, x: int, y: int, *args, **kwargs):
115+
def set_binning(self, x: int, y: int, **kwargs: Any) -> None:
113116
"""Set the camera binning.
114117
115118
Args:
@@ -137,6 +140,10 @@ def _expose(self, exposure_time: float, open_shutter: bool, abort_event: threadi
137140
ValueError: If exposure was not successful.
138141
"""
139142

143+
# check driver
144+
if self._driver is None:
145+
raise ValueError('No camera driver.')
146+
140147
# set binning
141148
log.info("Set binning to %dx%d.", self._binning[0], self._binning[1])
142149
self._driver.set_binning(*self._binning)
@@ -220,16 +227,18 @@ def _expose(self, exposure_time: float, open_shutter: bool, abort_event: threadi
220227
self._change_exposure_status(ExposureStatus.IDLE)
221228
return image
222229

223-
def _abort_exposure(self):
230+
def _abort_exposure(self) -> None:
224231
"""Abort the running exposure. Should be implemented by derived class.
225232
226233
Raises:
227234
ValueError: If an error occured.
228235
"""
236+
if self._driver is None:
237+
raise ValueError('No camera driver.')
229238
self._driver.cancel_exposure()
230239
self._camera_status = ExposureStatus.IDLE
231240

232-
def get_cooling_status(self, *args, **kwargs) -> Tuple[bool, float, float]:
241+
def get_cooling_status(self, **kwargs: Any) -> Tuple[bool, float, float]:
233242
"""Returns the current status for the cooling.
234243
235244
Returns:
@@ -238,21 +247,25 @@ def get_cooling_status(self, *args, **kwargs) -> Tuple[bool, float, float]:
238247
SetPoint (float): Setpoint for the cooling in celsius.
239248
Power (float): Current cooling power in percent or None.
240249
"""
250+
if self._driver is None:
251+
raise ValueError('No camera driver.')
241252
enabled = self._temp_setpoint is not None
242-
return enabled, self._temp_setpoint, self._driver.get_cooler_power()
253+
return enabled, self._temp_setpoint if self._temp_setpoint is not None else 99., self._driver.get_cooler_power()
243254

244-
def get_temperatures(self, *args, **kwargs) -> dict:
255+
def get_temperatures(self, **kwargs: Any) -> Dict[str, float]:
245256
"""Returns all temperatures measured by this module.
246257
247258
Returns:
248259
Dict containing temperatures.
249260
"""
261+
if self._driver is None:
262+
raise ValueError('No camera driver.')
250263
return {
251264
'CCD': self._driver.get_temp(FliTemperature.CCD),
252265
'Base': self._driver.get_temp(FliTemperature.BASE)
253266
}
254267

255-
def set_cooling(self, enabled: bool, setpoint: float, *args, **kwargs):
268+
def set_cooling(self, enabled: bool, setpoint: float, **kwargs: Any) -> None:
256269
"""Enables/disables cooling and sets setpoint.
257270
258271
Args:
@@ -262,6 +275,8 @@ def set_cooling(self, enabled: bool, setpoint: float, *args, **kwargs):
262275
Raises:
263276
ValueError: If cooling could not be set.
264277
"""
278+
if self._driver is None:
279+
raise ValueError('No camera driver.')
265280

266281
# log
267282
if enabled:

pyobs_fli/flidriver.pyx

+21-19
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
from collections import namedtuple
44
from enum import Enum
5+
from typing import Tuple, List
6+
57
import numpy as np
68
cimport numpy as np
79
np.import_array()
@@ -24,7 +26,7 @@ cdef class FliDriver:
2426
"""Wrapper for the FLI driver."""
2527

2628
@staticmethod
27-
def list_devices():
29+
def list_devices() -> List[DeviceInfo]:
2830
"""List all FLI USB cameras connected to this computer.
2931

3032
Returns:
@@ -71,7 +73,7 @@ cdef class FliDriver:
7173
"""
7274
self._device_info = device_info
7375

74-
def open(self):
76+
def open(self) -> None:
7577
"""Open driver.
7678

7779
Raises:
@@ -81,7 +83,7 @@ cdef class FliDriver:
8183
if res != 0:
8284
raise ValueError('Could not open device.')
8385

84-
def close(self):
86+
def close(self) -> None:
8587
"""Close driver.
8688

8789
Raises:
@@ -92,11 +94,11 @@ cdef class FliDriver:
9294
raise ValueError('Could not open device.')
9395

9496
@property
95-
def name(self):
97+
def name(self) -> str:
9698
"""Returns the name of the connected device."""
9799
return self._device_info.name.decode('utf-8')
98100

99-
def get_window_binning(self):
101+
def get_window_binning(self) -> Tuple[Tuple[int, int, int, int], Tuple[int, int]]:
100102
"""Get tuple of window and binning dicts.
101103

102104
Returns:
@@ -117,7 +119,7 @@ cdef class FliDriver:
117119
# return window and binning
118120
return (hoffset, voffset, width, height), (hbin, vbin)
119121

120-
def get_visible_frame(self):
122+
def get_visible_frame(self) -> Tuple[int, int, int, int]:
121123
"""Returns the visible frame of the connected camera.
122124

123125
Returns:
@@ -138,7 +140,7 @@ cdef class FliDriver:
138140
# return it
139141
return ul_x, ul_y, lr_x - ul_x, lr_y - ul_y
140142

141-
def get_full_frame(self):
143+
def get_full_frame(self) -> Tuple[int, int, int, int]:
142144
"""Returns the full frame of the connected camera.
143145

144146
Returns:
@@ -159,7 +161,7 @@ cdef class FliDriver:
159161
# return it
160162
return ul_x, ul_y, lr_x - ul_x, lr_y - ul_y
161163

162-
def set_binning(self, x: int, y: int):
164+
def set_binning(self, x: int, y: int) -> None:
163165
"""Set the binning.
164166

165167
Args:
@@ -180,7 +182,7 @@ cdef class FliDriver:
180182
if res != 0:
181183
raise ValueError('Could not set y binning.')
182184

183-
def set_window(self, left: int, top: int, width: int, height: int):
185+
def set_window(self, left: int, top: int, width: int, height: int) -> None:
184186
"""Sets the window.
185187

186188
Args:
@@ -198,7 +200,7 @@ cdef class FliDriver:
198200
if res != 0:
199201
raise ValueError('Could not set window.')
200202

201-
def init_exposure(self, open_shutter: bool):
203+
def init_exposure(self, open_shutter: bool) -> None:
202204
"""Initializes an exposure.
203205

204206
Args:
@@ -218,7 +220,7 @@ cdef class FliDriver:
218220
if res != 0:
219221
raise ValueError('Could not set frame type.')
220222

221-
def set_exposure_time(self, exptime: int):
223+
def set_exposure_time(self, exptime: int) -> None:
222224
"""Sets the exposure time.
223225

224226
Args:
@@ -233,7 +235,7 @@ cdef class FliDriver:
233235
if res != 0:
234236
raise ValueError('Could not set exposure time.')
235237

236-
def start_exposure(self):
238+
def start_exposure(self) -> None:
237239
"""Start a new exposure.
238240

239241
Raises:
@@ -245,7 +247,7 @@ cdef class FliDriver:
245247
if res != 0:
246248
raise ValueError('Could not start exposure.')
247249

248-
def is_exposing(self):
250+
def is_exposing(self) -> bool:
249251
"""Checks, whether the camera is currently exposing
250252

251253
Returns:
@@ -270,7 +272,7 @@ cdef class FliDriver:
270272
return (status == FLI_CAMERA_STATUS_UNKNOWN and timeleft == 0) or \
271273
(status != FLI_CAMERA_STATUS_UNKNOWN and status & FLI_CAMERA_DATA_READY)
272274

273-
def get_temp(self, channel: FliTemperature):
275+
def get_temp(self, channel: FliTemperature) -> float:
274276
"""Returns the temperature of the given sensor.
275277

276278
Args:
@@ -294,7 +296,7 @@ cdef class FliDriver:
294296
# return it
295297
return temp
296298

297-
def get_cooler_power(self):
299+
def get_cooler_power(self) -> float:
298300
"""Get power of cooling in percent.
299301

300302
Returns:
@@ -315,7 +317,7 @@ cdef class FliDriver:
315317
# return it
316318
return power
317319

318-
def grab_row(self, width: int):
320+
def grab_row(self, width: int) -> np.ndarray:
319321
"""Reads out a row from the camera.
320322

321323
Args:
@@ -332,7 +334,7 @@ cdef class FliDriver:
332334
cdef np.ndarray[unsigned short, ndim=1] row = np.zeros((width), dtype=np.ushort)
333335

334336
# get pointer to data
335-
cdef unsigned short* row_data = <unsigned short*> row.data
337+
cdef void* row_data = <void*> row.data
336338

337339
# call library
338340
res = FLIGrabRow(self._device, row_data, width)
@@ -342,7 +344,7 @@ cdef class FliDriver:
342344
# return row
343345
return row
344346

345-
def cancel_exposure(self):
347+
def cancel_exposure(self) -> None:
346348
"""Cancel an exposure.
347349

348350
Raises:
@@ -353,7 +355,7 @@ cdef class FliDriver:
353355
if res != 0:
354356
raise ValueError('Could not cancel exposure.')
355357

356-
def set_temperature(self, setpoint: float):
358+
def set_temperature(self, setpoint: float) -> None:
357359
"""Set cooling emperature setpoint.
358360

359361
Args:

0 commit comments

Comments
 (0)