BioImager  3.9.1
A .NET microscopy imaging library. Supports various microscopes by using imported libraries & GUI automation. Supported libraries include PriorĀ® & ZeissĀ® & all devices supported by Micromanager 2.0 and python-microscope.
Loading...
Searching...
No Matches
obis.py
1#!/usr/bin/env python3
2
3## Copyright (C) 2020 David Miguel Susano Pinto <carandraug@gmail.com>
4## Copyright (C) 2020 Julio Mateos Langerak <julio.mateos-langerak@igh.cnrs.fr>
5## Copyright (C) 2020 Mick Phillips <mick.phillips@gmail.com>
6##
7## This file is part of Microscope.
8##
9## Microscope is free software: you can redistribute it and/or modify
10## it under the terms of the GNU General Public License as published by
11## the Free Software Foundation, either version 3 of the License, or
12## (at your option) any later version.
13##
14## Microscope is distributed in the hope that it will be useful,
15## but WITHOUT ANY WARRANTY; without even the implied warranty of
16## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17## GNU General Public License for more details.
18##
19## You should have received a copy of the GNU General Public License
20## along with Microscope. If not, see <http://www.gnu.org/licenses/>.
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
bool get_is_on(self)
Definition: abc.py:1212
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
def _write(self, command)
Definition: obis.py:74
def _set_power_mw(self, mw)
Definition: obis.py:182