BioImager  4.9.0
A .NET microscopy imaging application based on Bio library. Supports various microscopes by using imported libraries & GUI automation. Supports XInput game controllers to move stage, take images, run ImageJ macros on images or Bio C# scripts.
Loading...
Searching...
No Matches
obis.py
1#!/usr/bin/env python3
2
3
21
22import logging
23
24import serial
25
26import microscope
27import microscope.abc
28
29
30_logger = logging.getLogger(__name__)
31
32
34 def __init__(self, com, baud=115200, timeout=0.5, **kwargs) -> None:
35 super().__init__(**kwargs)
36 self.connectionconnection = serial.Serial(
37 port=com,
38 baudrate=baud,
39 timeout=timeout,
40 stopbits=serial.STOPBITS_ONE,
41 bytesize=serial.EIGHTBITS,
42 parity=serial.PARITY_NONE,
43 )
44 # Start a logger.
45 self._write_write(b"SYSTem:INFormation:MODel?")
46 response = self._readline_readline()
47 _logger.info("OBIS laser model: [%s]", response.decode())
48 self._write_write(b"SYSTem:INFormation:SNUMber?")
49 response = self._readline_readline()
50 _logger.info("OBIS laser serial number: [%s]", response.decode())
51 self._write_write(b"SYSTem:CDRH?")
52 response = self._readline_readline()
53 _logger.info("CDRH safety: [%s]", response.decode())
54 self._write_write(b"SOURce:TEMPerature:APRobe?")
55 response = self._readline_readline()
56 _logger.info("TEC temperature control: [%s]", response.decode())
57 self._write_write(b"*TST?")
58 response = self._readline_readline()
59 _logger.info("Self test procedure: [%s]", response.decode())
60
61 # We need to ensure that autostart is disabled so that we can
62 # switch emission on/off remotely.
63 self._write_write(b"SYSTem:AUTostart?")
64 response = self._readline_readline()
65 _logger.info("Response to Autostart: [%s]", response.decode())
66
67 self._write_write(b"SOURce:POWer:LIMit:HIGH?")
68 response = self._readline_readline()
69 _logger.info("Max intensity in watts: [%s]", response.decode())
70 self._max_power_mw = float(response) * 1000.0
71
73
74 def _write(self, command):
75 """Send a command."""
76 response = self.connectionconnection.write(command + b"\r\n")
77 return response
78
79 def _readline(self):
80 """Read a line from connection without leading and trailing whitespace.
81 We override from SerialDeviceMixin
82 """
83 response = self.connectionconnection.readline().strip()
84 if self.connectionconnection.readline().strip() != b"OK":
86 "Did not get a proper answer from the laser serial comm."
87 )
88 return response
89
90 def _flush_handshake(self):
91 self.connectionconnection.readline()
92
93 @microscope.abc.SerialDeviceMixin.lock_comms
94 def get_status(self):
95 result = []
96 for cmd, stat in [
97 (b"SOURce:AM:STATe?", "Emission on?"),
98 (b"SOURce:POWer:LEVel:IMMediate:AMPLitude?", "Target power:"),
99 (b"SOURce:POWer:LEVel?", "Measured power:"),
100 (b"SYSTem:STATus?", "Status code?"),
101 (b"SYSTem:FAULt?", "Fault code?"),
102 (b"SYSTem:HOURs?", "Head operating hours:"),
103 ]:
104 self._write_write(cmd)
105 result.append(stat + " " + self._readline_readline().decode())
106 return result
107
108 @microscope.abc.SerialDeviceMixin.lock_comms
109 def _do_enable(self):
110 """Turn the laser ON. Return True if we succeeded, False otherwise."""
111 _logger.info("Turning laser ON.")
112 # Exiting Sleep Mode.
113 self._write_write(b"SOURce:TEMPerature:APRobe ON")
114 self._flush_handshake()
115 # Turn on emission.
116 self._write_write(b"SOURce:AM:STATe ON")
117 self._flush_handshake()
118 self._write_write(b"SOURce:AM:STATe?")
119 response = self._readline_readline()
120 _logger.info("SOURce:AM:STATe? [%s]", response.decode())
121
122 if not self.get_is_onget_is_on():
123 # Something went wrong.
124 _logger.error("Failed to turn ON. Current status:\r\n")
125 _logger.error(self.get_statusget_status())
126 return False
127 return True
128
129 def _do_shutdown(self) -> None:
130 self.disable()
131 # We set the power to a safe level
132 self._set_power_mw(2)
133 # We want it back into direct control mode.
134 self._write_write(b"SOURce:AM:INTernal CWP")
135 self._flush_handshake()
136
137 # Going into Sleep mode
138 self._write_write(b"SOURce:TEMPerature:APRobe OFF")
139 self._flush_handshake()
140
141 def initialize(self):
142 # self.flush_buffer()
143 # We ensure that handshaking is off.
144 self._write_write(b"SYSTem:COMMunicate:HANDshaking ON")
145 self._flush_handshake()
146 # We don't want 'direct control' mode.
147 # TODO: Change to MIXED when analogue output is available
148 self._write_write(b"SOURce:AM:EXTernal DIGital")
149 self._flush_handshake()
150
151 @microscope.abc.SerialDeviceMixin.lock_comms
152 def _do_disable(self):
153 """Turn the laser OFF. Return True if we succeeded, False otherwise."""
154 _logger.info("Turning laser OFF.")
155 # Turning LASER OFF
156 self._write_write(b"SOURce:AM:STATe OFF")
157 self._flush_handshake()
158
159 if self.get_is_onget_is_on():
160 _logger.error("Failed to turn OFF. Current status:\r\n")
161 _logger.error(self.get_statusget_status())
162 return False
163 return True
164
165 @microscope.abc.SerialDeviceMixin.lock_comms
166 def get_is_on(self):
167 """Return True if the laser is currently able to produce light."""
168 self._write_write(b"SOURce:AM:STATe?")
169 response = self._readline_readline()
170 _logger.info("Are we on? [%s]", response.decode())
171 return response == b"ON"
172
173 @microscope.abc.SerialDeviceMixin.lock_comms
174 def _get_power_mw(self):
175 if not self.get_is_onget_is_on():
176 return 0.0
177 self._write_write(b"SOURce:POWer:LEVel?")
178 response = self._readline_readline()
179 return float(response.decode()) * 1000.0
180
181 @microscope.abc.SerialDeviceMixin.lock_comms
182 def _set_power_mw(self, mw):
183 power_w = mw / 1000.0
184 _logger.info("Setting laser power to %.7sW", power_w)
185 self._write_write(b"SOURce:POWer:LEVel:IMMediate:AMPLitude %.5f" % power_w)
186 self._flush_handshake()
187
188 def _do_set_power(self, power: float) -> None:
189 self._set_power_mw(power * self._max_power_mw)
190
191 def _do_get_power(self) -> float:
192 return self._get_power_mw() / self._max_power_mw
193
194 @property
195 def trigger_type(self) -> microscope.TriggerType:
196 return microscope.TriggerType.HIGH
197
198 @property
199 def trigger_mode(self) -> microscope.TriggerMode:
200 return microscope.TriggerMode.BULB
201
203 self, ttype: microscope.TriggerType, tmode: microscope.TriggerMode
204 ) -> None:
205 if ttype is not microscope.TriggerType.HIGH:
207 "the only trigger type supported is 'high'"
208 )
209 if tmode is not microscope.TriggerMode.BULB:
211 "the only trigger mode supported is 'bulb'"
212 )
213
214 def _do_trigger(self) -> None:
216 "trigger does not make sense in trigger mode bulb, only enable"
217 )
None initialize(self)
Definition abc.py:339
None disable(self)
Definition abc.py:307
typing.List[str] get_status(self)
Definition abc.py:1206
int _write(self, bytes command)
Definition abc.py:1020
None set_trigger(self, microscope.TriggerType ttype, microscope.TriggerMode tmode)
Definition obis.py:204
None _do_set_power(self, float power)
Definition obis.py:188