Skip to content

Commit 8f2d2fd

Browse files
committed
Device: replace Device._logger with module loggers (issue #110)
Each device instance has its own logger. This was meant to help in filter the log records by device. This was achieved by having DeviceServer get the logger with that device name and have records from it written to a properly named file. However, this meant that log record from other loggers were discarded and has since been changed. This means that there's no longer need for each Device to have its own instance and can instead used module loggers as is recommended in the documentation and is standard in other packages. This commits removes the Device._logger attribute and replaces all its use with loggers from the individual modules.
1 parent 6e122b9 commit 8f2d2fd

File tree

9 files changed

+168
-119
lines changed

9 files changed

+168
-119
lines changed

microscope/cameras/andorsdk3.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
a camera and all its settings to be exposed over Pyro.
2323
"""
2424

25+
import logging
2526
import queue
2627
import time
2728

@@ -34,6 +35,9 @@
3435
from .SDK3Cam import *
3536

3637

38+
_logger = logging.getLogger(__name__)
39+
40+
3741
# SDK data pointer type
3842
DPTR_TYPE = SDK3.POINTER(SDK3.AT_U8)
3943

@@ -322,7 +326,7 @@ def set_num_buffers(self, num):
322326

323327
def _purge_buffers(self):
324328
"""Purge buffers on both camera and PC."""
325-
self._logger.debug("Purging buffers.")
329+
_logger.debug("Purging buffers.")
326330
self._buffers_valid = False
327331
if self._acquiring:
328332
raise Exception ('Can not modify buffers while camera acquiring.')
@@ -340,7 +344,7 @@ def _create_buffers(self, num=None):
340344
if num is None:
341345
num = self.num_buffers
342346
self._purge_buffers()
343-
self._logger.debug("Creating %d buffers." % num)
347+
_logger.debug("Creating %d buffers." % num)
344348
self._img_stride = self._aoi_stride.get_value()
345349
self._img_width = self._aoi_width.get_value()
346350
self._img_height = self._aoi_height.get_value()
@@ -372,7 +376,7 @@ def _fetch_data(self, timeout=5, debug=False):
372376
ptr, length = SDK3.WaitBuffer(self.handle, timeout)
373377
except SDK3.TimeoutError as e:
374378
if debug:
375-
self._logger.debug(e)
379+
_logger.debug(e)
376380
return None
377381
except Exception:
378382
raise
@@ -395,7 +399,7 @@ def _fetch_data(self, timeout=5, debug=False):
395399

396400
def abort(self):
397401
"""Abort acquisition."""
398-
self._logger.debug('Disabling acquisition.')
402+
_logger.debug('Disabling acquisition.')
399403
if self._acquiring:
400404
self._acquisition_stop()
401405

@@ -447,7 +451,7 @@ def initialize(self):
447451
self._trigger_mode.set_string('Software')
448452
self._cycle_mode.set_string('Continuous')
449453
else:
450-
self._logger.warn("No hardware found - using SIMCAM")
454+
_logger.warn("No hardware found - using SIMCAM")
451455

452456

453457
def callback(*args):
@@ -485,15 +489,15 @@ def _on_disable(self):
485489
self._buffers_valid = False
486490

487491
def _on_enable(self):
488-
self._logger.debug("Preparing for acquisition.")
492+
_logger.debug("Preparing for acquisition.")
489493
if self._acquiring:
490494
self._acquisition_stop()
491495
self._create_buffers()
492496
try:
493497
self._acquisition_start()
494498
except Exception as e:
495499
raise Exception(str(e))
496-
self._logger.debug("Acquisition enabled: %s." % self._acquiring)
500+
_logger.debug("Acquisition enabled: %s." % self._acquiring)
497501
return True
498502

499503
@keep_acquiring
@@ -503,7 +507,7 @@ def set_exposure_time(self, value):
503507
value))[1]
504508
self._exposure_time.set_value(bounded_value)
505509
self._frame_rate.set_value(self._frame_rate.max())
506-
self._logger.debug("Set exposure time to %f, resulting framerate %f."
510+
_logger.debug("Set exposure time to %f, resulting framerate %f."
507511
% (bounded_value, self._frame_rate.get_value()))
508512

509513
def get_exposure_time(self):

microscope/cameras/atmcd.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
3030
Tested against Ixon Ultra with atmcd64d.dll ver 2.97.30007.0 .
3131
"""
32+
33+
import logging
3234
import re, sys, functools, os, platform
3335
import ctypes
3436
from ctypes import Structure, POINTER
@@ -37,6 +39,10 @@
3739
from ctypes import c_void_p
3840
from numpy.ctypeslib import ndpointer
3941

42+
43+
_logger = logging.getLogger(__name__)
44+
45+
4046
# Andor docs use Windows datatypes in call signatures. These may not be available on
4147
# other platforms.
4248
try:
@@ -1191,7 +1197,7 @@ def _acquiring(self, value):
11911197

11921198
def abort(self):
11931199
"""Abort acquisition."""
1194-
self._logger.debug('Disabling acquisition.')
1200+
_logger.debug('Disabling acquisition.')
11951201
try:
11961202
with self:
11971203
AbortAcquisition()
@@ -1209,7 +1215,7 @@ def _set_cooler_state(self, state):
12091215

12101216
def initialize(self):
12111217
"""Initialize the library and hardware and create Setting objects."""
1212-
self._logger.info('Initializing ...')
1218+
_logger.info('Initializing ...')
12131219
num_cams = GetAvailableCameras()
12141220
if self._index >= num_cams:
12151221
msg = "Requested camera %d, but only found %d cameras" % (self._index, num_cams)
@@ -1244,7 +1250,7 @@ def initialize(self):
12441250
for s in range(GetNumberHSSpeeds(ch, amp.value)):
12451251
speed = GetHSSpeed(ch, amp.value, s)
12461252
self._readout_modes.append(ReadoutMode(ch, amp, s, speed))
1247-
self._logger.info("... initilized %s s/n %s" % (model, serial))
1253+
_logger.info("... initilized %s s/n %s" % (model, serial))
12481254
## Add settings. Some are write-only, so we set defaults here.
12491255
# Mode
12501256
name = 'readout mode'
@@ -1394,18 +1400,19 @@ def _on_shutdown(self):
13941400
with self:
13951401
CoolerOFF()
13961402

1397-
self._logger.info("Waiting for temperature to rise above -20C before shutdown ...")
1403+
_logger.info('Waiting for temperature to rise above -20C'
1404+
' before shutdown ...')
13981405

13991406
while True:
14001407
# Check temperature then release lock.
14011408
with self:
14021409
t = GetTemperature()[1]
1403-
self._logger.info("... T = %dC" % t)
1410+
_logger.info("... T = %dC" % t)
14041411
if t > -20:
14051412
break
14061413
time.sleep(10)
14071414

1408-
self._logger.info("Temperature is %dC: shutting down camera." % t)
1415+
_logger.info("Temperature is %dC: shutting down camera." % t)
14091416

14101417
with self:
14111418
ShutDown()
@@ -1478,7 +1485,7 @@ def get_cycle_time(self):
14781485
def _set_readout_mode(self, mode_index):
14791486
"""Configure channel, amplifier and VS-speed."""
14801487
mode = self._readout_modes[mode_index]
1481-
self._logger.info("Setting readout mode to %s" % mode)
1488+
_logger.info("Setting readout mode to %s" % mode)
14821489
with self:
14831490
SetADChannel(mode.channel)
14841491
SetOutputAmplifier(mode.amp)

microscope/cameras/pvcam.py

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@
128128
"""
129129

130130
import ctypes
131+
import logging
131132
import os
132133
import platform
133134
import time
@@ -139,6 +140,10 @@
139140
from microscope.devices import ROI, Binning
140141
from microscope.devices import keep_acquiring
141142

143+
144+
_logger = logging.getLogger(__name__)
145+
146+
142147
# Readout transform mapping - {CHIP_NAME: {port: transform}}
143148
READOUT_TRANSFORMS = {
144149
'Evolve-5': {0: (0,0,0),
@@ -1081,7 +1086,8 @@ def _query(self, what=ATTR_CURRENT, force_query=False):
10811086
result = ctypes.POINTER(self._ctype)(result).contents.value
10821087
# Test on err.args prevents indexing into empty tuple.
10831088
if err and err.args and err.args[0].startswith('pvcam error 49'):
1084-
self.cam._logger.warn("Parameter %s not available due to camera state." % self.name)
1089+
_logger.warn("Parameter %s not available due to camera state."
1090+
% self.name)
10851091
result = None
10861092
elif err:
10871093
raise e
@@ -1259,7 +1265,7 @@ def cb():
12591265
"""Soft trigger mode end-of-frame callback."""
12601266
timestamp = time.time()
12611267
frame = self._buffer.copy()
1262-
self._logger.debug("Fetched single frame.")
1268+
_logger.debug("Fetched single frame.")
12631269
_exp_finish_seq(self.handle, CCS_CLEAR)
12641270
self._put(frame, timestamp)
12651271
return
@@ -1280,7 +1286,7 @@ def cb():
12801286
timestamp = time.time()
12811287
frame_p = ctypes.cast(_exp_get_latest_frame(self.handle), ctypes.POINTER(uns16))
12821288
frame = np.ctypeslib.as_array(frame_p, (self.roi[2], self.roi[3])).copy()
1283-
self._logger.debug("Fetched frame from circular buffer.")
1289+
_logger.debug("Fetched frame from circular buffer.")
12841290
self._put(frame, timestamp)
12851291
return
12861292
# Need to keep a reference to the callback.
@@ -1333,7 +1339,7 @@ def _on_shutdown(self):
13331339
_cam_close(self.handle)
13341340
PVCamera.open_cameras.remove(self.handle)
13351341
if not PVCamera.open_cameras:
1336-
self._logger.info("No more open cameras - calling _pvcam_uninit.")
1342+
_logger.info("No more open cameras - calling _pvcam_uninit.")
13371343
_pvcam_uninit()
13381344

13391345

@@ -1400,18 +1406,18 @@ def initialize(self):
14001406
_pvcam_uninit()
14011407
raise Exception ('No cameras detected.')
14021408
# Connect to the camera.
1403-
self._logger.info("DLL version: %s" % _pvcam_get_ver().value)
1409+
_logger.info("DLL version: %s" % _pvcam_get_ver().value)
14041410
self._pv_name = _cam_get_name(self._index).value
1405-
self._logger.info('Initializing %s' % self._pv_name)
1411+
_logger.info('Initializing %s' % self._pv_name)
14061412
self.handle = _cam_open(self._pv_name, OPEN_EXCLUSIVE)
14071413
PVCamera.open_cameras.append(self.handle)
14081414
# Set up event callbacks. Tried to use the resume callback to reinit camera
14091415
# after power loss, but any attempt to close/reopen the camera or deinit the
14101416
# DLL throws a Windows Error 0xE06D7363.
14111417
def _cb(event):
1412-
self._logger.info("Received %s event." % event)
1418+
_logger.info("Received %s event." % event)
14131419
if event == 'removed':
1414-
self._logger.critical("Can not re-init hardware. Exiting.")
1420+
_logger.critical("Can not re-init hardware. Exiting.")
14151421
exit(-1)
14161422
return
14171423
self._cbs = {'check': CALLBACK(lambda: _cb('check')),
@@ -1426,7 +1432,7 @@ def _cb(event):
14261432
try:
14271433
p = PVParam.factory(self, param_id)
14281434
except:
1429-
self._logger.warn("Skipping unsupported parameter %s." % name)
1435+
_logger.warn("Skipping unsupported parameter %s." % name)
14301436
continue
14311437
if not p.dtype or not p.available:
14321438
continue
@@ -1441,7 +1447,8 @@ def _cb(event):
14411447
except Exception as err:
14421448
# Test on err.args prevents indexing into empty tuple.
14431449
if err.args and not err.args[0].startswith('pvcam error 49'):
1444-
self._logger.warn("Skipping parameter %s: not supported in python." % (p.name))
1450+
_logger.warn('Skipping parameter %s: not supported'
1451+
' in python.' % (p.name))
14451452
continue
14461453
self.add_setting(p.name,
14471454
p.dtype,
@@ -1554,14 +1561,16 @@ def soft_trigger(self):
15541561
Trigger an exposure in TRIG_SOFT mode.
15551562
Log some debugging stats in other trigger modes."""
15561563
if self._trigger == TRIG_SOFT:
1557-
self._logger.debug("Received soft trigger ...")
1564+
_logger.debug("Received soft trigger ...")
15581565
_exp_start_seq(self.handle, self._buffer.ctypes.data_as(ctypes.c_void_p))
15591566
else:
15601567
cstatus, cbytes, cframes = _exp_check_cont_status(self.handle)
15611568
status, bytes = _exp_check_status(self.handle)
15621569

1563-
self._logger.debug("Status checks\ncheck_cont: %s \t bytes: %d\tframes: %d\n" \
1564-
"check_status: %s \t bytes: %d\t" \
1565-
% (STATUS_STRINGS[cstatus.value], cbytes.value, cframes.value,
1566-
STATUS_STRINGS[status.value], bytes.value))
1570+
_logger.debug('Status checks\n'
1571+
'check_cont: %s \t bytes: %d\tframes: %d\n'
1572+
'check_status: %s \t bytes: %d\t'
1573+
% (STATUS_STRINGS[cstatus.value], cbytes.value,
1574+
cframes.value, STATUS_STRINGS[status.value],
1575+
bytes.value))
15671576
return

microscope/cameras/ximea.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
## You should have received a copy of the GNU General Public License
2020
## along with Microscope. If not, see <http://www.gnu.org/licenses/>.
2121

22+
import logging
23+
2224
import numpy as np
2325

2426
from microscope import devices
@@ -28,6 +30,9 @@
2830
from ximea import xiapi
2931

3032

33+
_logger = logging.getLogger(__name__)
34+
35+
3136
# Trigger mode to type.
3237
TRIGGER_MODES = {
3338
'internal': None,
@@ -59,13 +64,13 @@ def __init__(self, **kwargs):
5964
def _fetch_data(self):
6065
if self._acquiring and self._triggered:
6166
self.handle.get_image(self.img)
62-
self._logger.info('Sending image')
67+
_logger.info('Sending image')
6368
self._triggered = False
6469
data = np.array(list(self.img.get_image_data_raw()),dtype=np.uint16).reshape(self.img.width,self.img.height)
6570
return data
6671

6772
def abort(self):
68-
self._logger.info('Disabling acquisition.')
73+
_logger.info('Disabling acquisition.')
6974
if self._acquiring:
7075
self._acquiring = False
7176
self.handle.stop_acquisition()
@@ -82,7 +87,7 @@ def initialize(self):
8287
raise Exception("Problem opening camera.")
8388
if self.handle == None:
8489
raise Exception("No camera opened.")
85-
self._logger.info('Initializing.')
90+
_logger.info('Initializing.')
8691
self.img=xiapi.Image()
8792

8893
def make_safe(self):
@@ -93,13 +98,13 @@ def _on_disable(self):
9398
self.abort()
9499

95100
def _on_enable(self):
96-
self._logger.info("Preparing for acquisition.")
101+
_logger.info("Preparing for acquisition.")
97102
if self._acquiring:
98103
self.abort()
99104
self._acquiring = True
100105
#actually start camera
101106
self.handle.start_acquisition()
102-
self._logger.info("Acquisition enabled.")
107+
_logger.info("Acquisition enabled.")
103108
return True
104109

105110
def set_exposure_time(self, value):
@@ -134,8 +139,8 @@ def set_trigger_type(self, trigger):
134139
self.handle.set_gpi_mode(XI_GPI_TRIGGER)
135140

136141
def soft_trigger(self):
137-
self._logger.info('Trigger received; self._acquiring is %s.'
138-
% self._acquiring)
142+
_logger.info('Trigger received; self._acquiring is %s.'
143+
% self._acquiring)
139144
if self._acquiring:
140145
self._triggered = True
141146

0 commit comments

Comments
 (0)