Skip to content

Commit 20f8285

Browse files
Baharisstefsmeets
andauthored
Generalize get_binning and fix low-hanging mypy issues (#110)
* All configs have `default_binning` so define `get_binning` in `CameraBase` * Fix 15 low-hanging mypy warning, mostly `(int, int)` -> `Tuple[int, int]` * Avoid an expensive microscope call if possible Co-authored-by: Stef Smeets <stefsmeets@users.noreply.github.com> * Remove `CameraGatan2.get_binning` override of `CameraBase` --------- Co-authored-by: Stef Smeets <stefsmeets@users.noreply.github.com>
1 parent 0a3febd commit 20f8285

11 files changed

Lines changed: 54 additions & 30 deletions

File tree

src/instamatic/camera/camera_base.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from __future__ import annotations
22

33
from abc import ABC, abstractmethod
4-
from typing import List, Tuple
4+
from typing import List, Optional, Tuple
55

6-
from numpy import ndarray
6+
import numpy as np
77

88
from instamatic import config
99

@@ -37,33 +37,45 @@ def release_connection(self):
3737
pass
3838

3939
@abstractmethod
40-
def get_image(self, exposure: float = None, binsize: int = None, **kwargs) -> ndarray:
40+
def get_image(
41+
self,
42+
exposure: Optional[float] = None,
43+
binsize: Optional[int] = None,
44+
**kwargs,
45+
) -> np.ndarray:
4146
pass
4247

4348
def get_movie(
44-
self, n_frames: int, exposure: float = None, binsize: int = None, **kwargs
45-
) -> List[ndarray]:
49+
self,
50+
n_frames: int,
51+
exposure: Optional[float] = None,
52+
binsize: Optional[int] = None,
53+
**kwargs,
54+
) -> List[np.ndarray]:
4655
"""Basic implementation, subclasses should override with appropriate
4756
optimization."""
4857
return [
4958
self.get_image(exposure=exposure, binsize=binsize, **kwargs)
5059
for _ in range(n_frames)
5160
]
5261

53-
def __enter__(self):
62+
def __enter__(self) -> CameraBase:
5463
self.establish_connection()
5564
return self
5665

57-
def __exit__(self, kind, value, traceback):
66+
def __exit__(self, kind, value, traceback) -> None:
5867
self.release_connection()
5968

69+
def get_binning(self) -> int:
70+
return self.default_binsize
71+
6072
def get_camera_dimensions(self) -> Tuple[int, int]:
6173
return self.dimensions
6274

6375
def get_name(self) -> str:
6476
return self.name
6577

66-
def load_defaults(self):
78+
def load_defaults(self) -> None:
6779
if self.name != config.settings.camera:
6880
config.load_camera_config(camera_name=self.name)
6981
for key, val in config.camera.mapping.items():

src/instamatic/camera/camera_client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import subprocess as sp
66
import time
77
from functools import wraps
8+
from typing import Dict
89

910
import numpy as np
1011

@@ -79,7 +80,7 @@ def __init__(
7980
)
8081
print('Use shared memory:', self.use_shared_memory)
8182

82-
self.buffers = {}
83+
self.buffers: Dict[str, np.ndarray] = {}
8384
self.shms = {}
8485

8586
self._init_dict()

src/instamatic/camera/camera_emmenu.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import logging
55
import time
66
from pathlib import Path
7+
from typing import Tuple
78

89
import comtypes.client
910
import numpy as np
@@ -347,19 +348,19 @@ def get_image_data_by_index(self, img_index: int, drc_index: int = None) -> 'np.
347348

348349
return np.array(arr)
349350

350-
def get_camera_dimensions(self) -> (int, int):
351+
def get_camera_dimensions(self) -> Tuple[int, int]:
351352
"""Get the maximum dimensions reported by the camera."""
352353
# cfg = self.get_current_config()
353354
# return cfg.DimensionX, cfg.DimensionY
354355
return self._cam.RealSizeX, self._cam.RealSizeY
355356
# return self._cam.MaximumSizeX, self._cam.MaximumSizeY
356357

357-
def get_image_dimensions(self) -> (int, int):
358+
def get_image_dimensions(self) -> Tuple[int, int]:
358359
"""Get the dimensions of the image."""
359360
binning = self.get_binning()
360361
return int(self._cam.RealSizeX / binning), int(self._cam.RealSizeY / binning)
361362

362-
def get_physical_pixelsize(self) -> (int, int):
363+
def get_physical_pixelsize(self) -> Tuple[int, int]:
363364
"""Returns the physical pixel size of the camera nanometers."""
364365
return self._cam.PixelSizeX, self._cam.PixelSizeY
365366

src/instamatic/camera/camera_gatan.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
create_unicode_buffer,
1919
)
2020
from pathlib import Path
21+
from typing import Tuple
2122

2223
import numpy as np
2324

@@ -214,7 +215,7 @@ def is_camera_info_available(self) -> bool:
214215
"""Return the status of the camera."""
215216
return self._isCameraInfoAvailable()
216217

217-
def get_camera_dimensions(self) -> (int, int):
218+
def get_camera_dimensions(self) -> Tuple[int, int]:
218219
"""Return the dimensions reported by the camera."""
219220
pnWidth = c_int(0)
220221
pnHeight = c_int(0)

src/instamatic/camera/camera_gatan2.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import sys
66
import time
77
from pathlib import Path
8+
from typing import Tuple
89

910
import numpy as np
1011

@@ -44,21 +45,16 @@ def get_dm_version(self) -> str:
4445
"""Get the version number of DM."""
4546
return self.g.GetDMVersion()
4647

47-
def get_image_dimensions(self) -> (int, int):
48+
def get_image_dimensions(self) -> Tuple[int, int]:
4849
"""Get the dimensions of the image."""
4950
binning = self.get_binning()
5051
dim_x, dim_y = self.get_camera_dimensions()
5152
return int(dim_x / binning), int(dim_y / binning)
5253

53-
def get_physical_pixelsize(self) -> (int, int):
54+
def get_physical_pixelsize(self) -> Tuple[int, int]:
5455
"""Returns the physical pixel size of the camera nanometers."""
5556
raise NotImplementedError
5657

57-
def get_binning(self) -> int:
58-
"""Returns the binning corresponding to the currently selected camera
59-
config."""
60-
raise NotImplementedError
61-
6258
def get_camera_name(self) -> str:
6359
"""Get the name reported by the camera."""
6460
return self.name

src/instamatic/camera/camera_merlin.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import logging
3030
import socket
3131
import time
32-
from typing import Any, List
32+
from typing import Any, List, Tuple
3333

3434
import numpy as np
3535

@@ -337,7 +337,7 @@ def get_movie(self, n_frames: int, exposure: float = None, **kwargs) -> List[np.
337337

338338
return data
339339

340-
def get_image_dimensions(self) -> (int, int):
340+
def get_image_dimensions(self) -> Tuple[int, int]:
341341
"""Get the binned dimensions reported by the camera."""
342342
binning = self.get_binning()
343343
dim_x, dim_y = self.get_camera_dimensions()

src/instamatic/camera/camera_serval.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import atexit
44
import logging
55
from pathlib import Path
6+
from typing import Tuple
67

78
import numpy as np
89
from serval_toolkit.camera import Camera as ServalCamera
@@ -92,7 +93,7 @@ def get_movie(self, n_frames, exposure=None, binsize=None, **kwargs):
9293

9394
return arr
9495

95-
def get_image_dimensions(self) -> (int, int):
96+
def get_image_dimensions(self) -> Tuple[int, int]:
9697
"""Get the binned dimensions reported by the camera."""
9798
binning = self.get_binning()
9899
dim_x, dim_y = self.get_camera_dimensions()

src/instamatic/camera/camera_simu.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import atexit
44
import logging
55
import time
6+
from typing import List, Optional, Tuple
67

78
import numpy as np
89

@@ -66,7 +67,14 @@ def get_image(self, exposure=None, binsize=None, **kwargs) -> np.ndarray:
6667

6768
return arr
6869

69-
def get_movie(self, n_frames, *, exposure: float = None, binsize: int = None, **kwargs):
70+
def get_movie(
71+
self,
72+
n_frames: int,
73+
*,
74+
exposure: Optional[float] = None,
75+
binsize: Optional[int] = None,
76+
**kwargs,
77+
) -> List[np.ndarray]:
7078
"""Movie acquisition routine. If the exposure and binsize are not
7179
given, the default values are read from the config file.
7280
@@ -93,7 +101,7 @@ def is_camera_info_available(self) -> bool:
93101
"""Check if the camera is available."""
94102
return True
95103

96-
def get_image_dimensions(self) -> (int, int):
104+
def get_image_dimensions(self) -> Tuple[int, int]:
97105
"""Get the binned dimensions reported by the camera."""
98106
binning = self.get_binning()
99107
dim_x, dim_y = self.get_camera_dimensions()
@@ -170,9 +178,6 @@ def get_exposure(self) -> int:
170178
def get_timestamps(self, start_index, end_index):
171179
return list(range(20))
172180

173-
def get_binning(self):
174-
return self.default_binsize
175-
176181
def write_tiffs(
177182
self, start_index: int, stop_index: int, path: str, clear_buffer=True
178183
) -> None:

src/instamatic/microscope/components/stage.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,10 @@ def set_xy_with_backlash_correction(
283283
delay between movements in seconds to allow the stage to settle
284284
"""
285285
wait = True
286+
if (x is None) or (y is None):
287+
current_x, current_y = self.xy
288+
x = current_x if x is None else x
289+
y = current_y if y is None else y
286290
self.set(x=x - step, y=y - step)
287291
if settle_delay:
288292
time.sleep(settle_delay)

src/instamatic/microscope/microscope.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
from typing import Optional
4+
35
from instamatic import config
46
from instamatic.microscope.base import MicroscopeBase
57

@@ -32,7 +34,7 @@ def get_microscope_class(interface: str) -> 'type[MicroscopeBase]':
3234
return cls
3335

3436

35-
def get_microscope(name: str = None, use_server: bool = False) -> MicroscopeBase:
37+
def get_microscope(name: Optional[str] = None, use_server: bool = False) -> MicroscopeBase:
3638
"""Generic class to load microscope interface class.
3739
3840
name: str

0 commit comments

Comments
 (0)