Skip to content

Commit b6ddfa0

Browse files
committed
Squashed commit of the following:
Ran black over all source files updated documentation Added hw interupts to raspberry Pi input lines
1 parent fecaf7d commit b6ddfa0

File tree

12 files changed

+192
-95
lines changed

12 files changed

+192
-95
lines changed

NEWS.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,18 @@ Version 0.7.0 (upcoming)
3333

3434
* New devices supported:
3535

36+
* Added a DigitalIO device type
37+
* Implemented a simulated DigitalIO device (:class:`microscope.simulations.SimulatedDigitalIO`)
38+
* Implemented a concrete DigitalIO device on a Raspberry Pi (:class:`microscope.digitalio.raspberrypi.RPiDIO`)
39+
3640
* Hamamatsu cameras (:class:`microscope.cameras.hamamatsu.HamamatsuCamera`)
3741

3842
* Ludl MC 2000 (:class:`microscope.controllers.ludl.LudlMC2000`)
3943

4044
* RaspberryPi camera (:class:`microscope.cameras.picamera.PiCamera`)
4145

4246
* Toptica iChrome MLE (:class:`microscope.controllers.toptica.iChromeMLE`)
43-
47+
4448
* Device specific changes:
4549

4650
* `PVCamera`:

doc/architecture/abc.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,18 @@ Microscope has the following ABCs that map to a specific device type:
2828
* :class:`microscope.abc.FilterWheel`
2929
* :class:`microscope.abc.LightSource`
3030
* :class:`microscope.abc.Stage`
31+
* :class:`microscope.abc.DigitalIO`
3132

3233
In addition, they all subclass from :class:`microscope.abc.Device`
3334
which defines a base interface to all devices such as the
3435
:meth:`shutdown <microscope.abc.Device.shutdown>` method.
3536

37+
There is an additional special device class
38+
:class:`microsope.abc.DataDevice` which defines a class that has the
39+
ability to asynchronously send data back to the calling
40+
connection. This is used for situations like cameras and asynchronous
41+
communication such as digital input signals.
42+
3643
The actual concrete classes, those which provide actual control over
3744
the devices, are listed on the section :ref:`supported-devices`.
3845

doc/architecture/supported-devices.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ Stages
6767
- Ludl (:class:`microscope.controllers.ludl.LudlMC2000`)
6868
- Zaber (:class:`microscope.controllers.zaber.ZaberDaisyChain`)
6969

70+
DigitalIO
71+
=========
72+
73+
- Raspberry Pi (:class:`microsocpe.digitalio.raspberrypi`)
74+
7075
Other
7176
=====
7277

microscope/abc.py

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,7 @@ def get_setting(self, name: str):
453453

454454
def get_all_settings(self):
455455
"""Return ordered settings as a list of dicts."""
456+
456457
# Fetching some settings may fail depending on device state.
457458
# Report these values as 'None' and continue fetching other settings.
458459
def catch(f):
@@ -870,7 +871,8 @@ def get_transform(self) -> typing.Tuple[bool, bool, bool]:
870871
def _update_transform(self):
871872
"""Update transform (after setting the client or readout transform)."""
872873
lr, ud, rot = (
873-
self._readout_transform[i] ^ self._client_transform[i] for i in range(3)
874+
self._readout_transform[i] ^ self._client_transform[i]
875+
for i in range(3)
874876
)
875877
if self._readout_transform[2] and self._client_transform[2]:
876878
lr = not lr
@@ -1556,15 +1558,16 @@ def move_to(self, position: typing.Mapping[str, float]) -> None:
15561558
"""
15571559
raise NotImplementedError()
15581560

1559-
class DigitalIO(Device, metaclass=abc.ABCMeta):
1561+
1562+
class DigitalIO(DataDevice, metaclass=abc.ABCMeta):
15601563
"""ABC for digital IO devices.
15611564
15621565
Digital IO devices (DIO) have a num,ber of digital lines that can
15631566
be for output, or optionally input and can switch between a on and
15641567
off state.
15651568
15661569
Args:
1567-
numLines: total number of digital lines numberes 0 to n-1.
1570+
numLines: total number of digital lines numberes 0 to n-1.
15681571
15691572
"""
15701573

@@ -1576,25 +1579,25 @@ def __init__(self, numLines: int, **kwargs) -> None:
15761579
)
15771580
self._numLines = numLines
15781581

1579-
#array to map wether lines are input or output
1580-
# true is output, start with all lines defined for output.
1581-
self._IOMap = [True]*self._numLines
1582-
1582+
# array to map wether lines are input or output
1583+
# true is output, start with all lines defined for output.
1584+
self._IOMap = [True] * self._numLines
1585+
15831586
def get_num_lines(self):
15841587
"""Returns the number of Io lines present in this instance"""
15851588
return self._numLines
15861589

1587-
@abc.abstractmethod
1590+
@abc.abstractmethod
15881591
def set_IO_state(self, line: int, state: bool):
15891592
"""Sets the state of a single Digital line to either Output or Input
15901593
15911594
Args:
15921595
line: The line to have its mode set.
1593-
1596+
15941597
state: True for Output or False for Input."""
15951598
raise NotImplementedError()
15961599

1597-
@abc.abstractmethod
1600+
@abc.abstractmethod
15981601
def get_IO_state(self, line):
15991602
"""Returns the state of a single Digital line, either Output or Input
16001603
@@ -1610,48 +1613,47 @@ def set_all_IO_state(self, stateArray):
16101613
stateArray: Boolean array for the lines, True in output False
16111614
is Input"""
16121615
for i, state in enumerate(stateArray):
1613-
#set each line as defined in stateArray
1614-
self.set_IO_state(i,state)
1615-
1616+
# set each line as defined in stateArray
1617+
self.set_IO_state(i, state)
16161618

16171619
def get_all_IO_state(self):
16181620
"""Returns the state of a all Digital line, either Output or Input
16191621
1620-
Returns a boolean array one entry for each line,
1622+
Returns a boolean array one entry for each line,
16211623
True for Output and False for Input"""
16221624

1623-
stateArray=[None]*self._numLines
1625+
stateArray = [None] * self._numLines
16241626
for i in range(self._numLines):
1625-
stateArray[i]=self.get_IO_state(i)
1627+
stateArray[i] = self.get_IO_state(i)
16261628
return stateArray
16271629

1628-
@abc.abstractmethod
1629-
def write_line(self,line,ouput):
1630+
@abc.abstractmethod
1631+
def write_line(self, line, ouput):
16301632
"""Sets the level of a single output line
16311633
16321634
Args:
16331635
line: the line to be set
16341636
output: the level True for high and Flase for low."""
1635-
1637+
16361638
raise NotImplementedError()
16371639

1638-
def write_all_lines(self,ouput_array):
1640+
def write_all_lines(self, ouput_array):
16391641
"""Sets the output level of every output line.
16401642
16411643
Args:
1642-
output_array: Boolean array of output states True for high,
1643-
False for low, array entries for lines set
1644+
output_array: Boolean array of output states True for high,
1645+
False for low, array entries for lines set
16441646
as inputs are ignored."""
1645-
1646-
if len(output_array) != self._numLines :
1647-
raise("Output array must be numLines in length")
1647+
1648+
if len(ouput_array) != self._numLines:
1649+
raise ("Output array must be numLines in length")
16481650
for i in range(self._numLines):
1649-
#set line i to the IOMap entry, true for output false for input.
1650-
if(not self._IOMap[i]):
1651-
self.write_line(i,output_array[i])
1651+
# set line i to the IOMap entry, true for output false for input.
1652+
if not self._IOMap[i]:
1653+
self.write_line(i, ouput_array[i])
16521654

1653-
@abc.abstractmethod
1654-
def read_line(self,line):
1655+
@abc.abstractmethod
1656+
def read_line(self, line):
16551657
"""Read a single input line.
16561658
Args:
16571659
line: the line to read
@@ -1661,8 +1663,8 @@ def read_line(self,line):
16611663
def read_all_lines(self):
16621664
"""Read all the input lines.
16631665
Return: Boolean Array with outline enteries set to None."""
1664-
1665-
readarray=[None]*self._numLines
1666+
1667+
readarray = [None] * self._numLines
16661668
for i in range(self._numLines):
1667-
readarray[i]=self.read_line(i)
1668-
return(readarray)
1669+
readarray[i] = self.read_line(i)
1670+
return readarray

microscope/cameras/_SDK3.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ class TimeoutError(CameraError):
123123
### Functions ###
124124
STRING = POINTER(AT_WC)
125125

126+
126127
# classes so that we do some magic and automatically add byrefs etc ... can classify outputs
127128
class _meta:
128129
pass

microscope/cameras/andorsdk3.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@
142142
"_vertically_centre_aoi": "VerticallyCentreAOI",
143143
}
144144

145+
145146
# Wrapper to ensure feature is readable.
146147
def readable_wrapper(func):
147148
def wrapper(self, *args, **kwargs):

microscope/cameras/atmcd.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@
9999
at_u64 = c_ulonglong
100100

101101
"""Version Information Definitions"""
102+
103+
102104
# Version information enumeration
103105
class AT_VersionInfoId(c_int):
104106
pass
@@ -114,6 +116,8 @@ class AT_VersionInfoId(c_int):
114116
AT_CONTROLLER_CARD_MODEL_LEN = 80
115117

116118
"""DDG Lite Definitions"""
119+
120+
117121
# Channel enumeration
118122
class AT_DDGLiteChannelId(c_int):
119123
pass
@@ -501,6 +505,7 @@ class WHITEBALANCEINFO(Structure):
501505
if attrib_name.startswith("DRV_"):
502506
status_codes.update({eval(attrib_name): attrib_name})
503507

508+
504509
# The lookup function.
505510
def lookup_status(code):
506511
key = code[0] if type(code) is list else code
@@ -513,6 +518,7 @@ def lookup_status(code):
513518
# The following DLL-wrapping classes are largely lifted from David Baddeley's
514519
# SDK3 wrapper, with some modifications and additions.
515520

521+
516522
# Classes used to handle outputs and parameters that need buffers.
517523
class _meta:
518524
pass

microscope/cameras/hamamatsu.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,6 @@ def _init_method_add_all_properties(self) -> None:
499499
def _init_method_get_prop_values(
500500
self, prop_attr: dcam.PROP_ATTR
501501
) -> typing.Dict[int, str]:
502-
503502
strbuf = ctypes.create_string_buffer(64)
504503
vtxt = _create_struct_with_cbSize(dcam.PROP_VALUETEXT)
505504
vtxt.iProp = prop_attr.iProp

microscope/cameras/pvcam.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,7 @@ class md_frame(ctypes.Structure):
685685
### Functions ###
686686
STRING = ctypes.c_char_p
687687

688+
688689
# classes so that we do some magic and automatically add byrefs etc ... can classify outputs
689690
# (Nicked from PYME's Ixon wrapper.)
690691
class _meta:
@@ -1691,6 +1692,7 @@ def initialize(self):
16911692
_logger.info("Initializing %s", self._pv_name)
16921693
self.handle = _cam_open(self._pv_name, OPEN_EXCLUSIVE)
16931694
PVCamera.open_cameras.append(self.handle)
1695+
16941696
# Set up event callbacks. Tried to use the resume callback to reinit camera
16951697
# after power loss, but any attempt to close/reopen the camera or deinit the
16961698
# DLL throws a Windows Error 0xE06D7363.
@@ -1717,7 +1719,7 @@ def _cb(event):
17171719
)
17181720
# Repopulate _params.
17191721
self._params = {}
1720-
for (param_id, name) in _param_to_name.items():
1722+
for param_id, name in _param_to_name.items():
17211723
try:
17221724
p = PVParam.factory(self, param_id)
17231725
except:

0 commit comments

Comments
 (0)