Skip to content

Commit eb8bf7b

Browse files
Merge pull request #1000 from TheDeanLab/logging-updates
Attempt to come up with a more scalable approach to logging.
2 parents eb22cf5 + e0e0416 commit eb8bf7b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+434
-385
lines changed

src/navigate/controller/controller.py

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import os
4141
import time
4242
import platform
43+
import reprlib
4344

4445
# Third Party Imports
4546

@@ -82,7 +83,7 @@
8283
verify_configuration,
8384
get_navigate_path,
8485
)
85-
from navigate.tools.file_functions import create_save_path, save_yaml_file
86+
from navigate.tools.file_functions import create_save_path, save_yaml_file, get_ram_info
8687
from navigate.tools.common_dict_tools import update_stage_dict
8788
from navigate.tools.multipos_table_tools import update_table
8889
from navigate.tools.common_functions import combine_funcs
@@ -96,7 +97,6 @@
9697

9798
class Controller:
9899
"""Navigate Controller"""
99-
100100
def __init__(
101101
self,
102102
root,
@@ -139,7 +139,6 @@ def __init__(
139139
Command line input arguments for non-default
140140
file paths or using synthetic hardware modes.
141141
"""
142-
143142
#: Tk top-level widget: Tk.tk GUI instance.
144143
self.root = root
145144

@@ -148,24 +147,31 @@ def __init__(
148147

149148
#: string: Path to the configuration yaml file.
150149
self.configuration_path = configuration_path
150+
logger.info(f"Configuration Path: {self.configuration_path}")
151151

152152
#: string: Path to the experiment yaml file.
153153
self.experiment_path = experiment_path
154+
logger.info(f"Experiment Path: {self.experiment_path}")
154155

155156
#: string: Path to the waveform constants yaml file.
156157
self.waveform_constants_path = waveform_constants_path
158+
logger.info(f"Waveform Constants Path: {self.waveform_constants_path}")
157159

158160
#: string: Path to the REST API yaml file.
159161
self.rest_api_path = rest_api_path
162+
logger.info(f"REST API Path: {self.rest_api_path}")
160163

161164
#: string: Path to the waveform templates yaml file.
162165
self.waveform_templates_path = waveform_templates_path
166+
logger.info(f"Waveform Templates Path: {self.waveform_templates_path}")
163167

164168
#: string: Path to the GUI configuration yaml file.
165169
self.gui_configuration_path = gui_configuration_path
170+
logger.info(f"GUI Configuration Path: {self.gui_configuration_path}")
166171

167172
#: iterable: Non-default command line input arguments for
168173
self.args = args
174+
logger.info(f"Variable Input Arguments: {self.args}")
169175

170176
#: Object: Thread pool for the controller.
171177
self.threads_pool = SynchronizedThreadPool()
@@ -191,6 +197,10 @@ def __init__(
191197
verify_experiment_config(self.manager, self.configuration)
192198
verify_waveform_constants(self.manager, self.configuration)
193199

200+
total_ram, available_ram = get_ram_info()
201+
logger.info(f"Total RAM: {total_ram / 1024**3:.2f} GB. "
202+
f"Available RAM: {available_ram / 1024**3:.2f} GB.")
203+
194204
#: ObjectInSubprocess: Model object in MVC architecture.
195205
self.model = ObjectInSubprocess(
196206
Model, args, self.configuration, event_queue=self.event_queue
@@ -269,9 +279,6 @@ def __init__(
269279
t = threading.Thread(target=self.update_event)
270280
t.start()
271281

272-
# self.microscope = self.configuration['configuration']
273-
# ['microscopes'].keys()[0] # Default to the first microscope
274-
275282
#: MenuController: Menu Sub-Controller.
276283
self.menu_controller = MenuController(view=self.view, parent_controller=self)
277284
self.menu_controller.initialize_menus()
@@ -321,17 +328,6 @@ def __init__(
321328
if platform.system() == "Windows":
322329
self.view.root.bind("<Configure>", self.resize)
323330

324-
logger.info(self.__repr__())
325-
326-
def __repr__(self):
327-
return (
328-
f'Controller("{self.root}", "{self.splash_screen}", '
329-
f'"{self.configuration_path}", "{self.experiment_path}", '
330-
f'"{self.waveform_constants_path}", "{self.rest_api_path}", '
331-
f'"{self.waveform_templates_path}", "{self.gui_configuration_path}", '
332-
f'"{self.args}")'
333-
)
334-
335331
def update_buffer(self):
336332
"""Update the buffer size according to the camera
337333
dimensions listed in the experimental parameters.

src/navigate/controller/sub_controllers/acquire_bar.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
p = __name__.split(".")[1]
4545
logger = logging.getLogger(p)
4646

47-
4847
class AcquireBarController(GUIController):
4948
"""Acquire Bar Controller."""
5049

src/navigate/controller/sub_controllers/camera_view.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from typing import Dict
3939
import tempfile
4040
import os
41+
import time
4142

4243
# Third Party Imports
4344
import cv2
@@ -58,7 +59,6 @@
5859
p = __name__.split(".")[1]
5960
logger = logging.getLogger(p)
6061

61-
6262
class ABaseViewController(metaclass=abc.ABCMeta):
6363
"""Abstract Base View Controller Class."""
6464

@@ -429,6 +429,16 @@ def try_to_display_image(self, image):
429429
display_thread = threading.Thread(target=self.display_image, args=(image,))
430430
display_thread.start()
431431

432+
def display_image(self, image):
433+
"""Display an image.
434+
435+
Parameters
436+
----------
437+
image : numpy.ndarray
438+
Image data.
439+
"""
440+
pass
441+
432442
def apply_lut(self, image):
433443
"""Applies a LUT to an image.
434444
@@ -978,7 +988,7 @@ def update_min_max_counts(self, display=False):
978988
self.max_counts = float(self.image_palette["Max"].get())
979989
if display and self.image is not None:
980990
self.process_image()
981-
logger.debug(
991+
logger.info(
982992
f"Min and Max counts scaled to, {self.min_counts}, {self.max_counts}"
983993
)
984994

@@ -1321,6 +1331,7 @@ def display_image(self, image):
13211331
image : numpy.ndarray
13221332
Image data.
13231333
"""
1334+
start_time = time.time()
13241335
self.image = self.flip_image(image)
13251336
self.max_intensity_history.append(np.max(image))
13261337
if self._snr_selected:
@@ -1331,6 +1342,7 @@ def display_image(self, image):
13311342
self.update_max_counts()
13321343
with self.is_displaying_image as is_displaying_image:
13331344
is_displaying_image.value = False
1345+
logger.info(f"Displaying image took {time.time() - start_time:.4f} seconds")
13341346

13351347
def set_mask_color_table(self, colors):
13361348
"""Set up segmentation mask color table
@@ -1677,22 +1689,12 @@ def __init__(self, channels: int, size_y: int, size_x: int):
16771689
dir=default_directory,
16781690
)
16791691

1680-
logger.info(self.__repr__())
1681-
16821692
def __del__(self):
16831693
"""Delete the temporary files."""
16841694
if self.temp_files is not None:
16851695
for temp_file in self.temp_files.values():
16861696
temp_file.close()
16871697

1688-
def __repr__(self):
1689-
"""Return the string representation of the SpooledImageLoader."""
1690-
return (
1691-
f"SpooledImageLoader(channels={len(self.temp_files)}, "
1692-
f"size_y={self.size_y}, "
1693-
f"size_x={self.size_x})"
1694-
)
1695-
16961698
@staticmethod
16971699
def get_default_max_size() -> int:
16981700
"""Get the default max_size based on the total RAM.

src/navigate/controller/sub_controllers/plugins.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
from navigate.tools.decorators import AcquisitionMode
4747
from navigate.controller.sub_controllers.gui import GUIController
4848
from navigate.view.popups.plugins_popup import PluginsPopup
49-
5049
from navigate.plugins.plugin_manager import PluginFileManager, PluginPackageManager
5150

5251

src/navigate/controller/sub_controllers/stages.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,13 @@
3939

4040
# Local Imports
4141
from navigate.controller.sub_controllers.gui import GUIController
42+
from navigate.model.devices import log_initialization
4243

4344
# Logger Setup
4445
p = __name__.split(".")[1]
4546
logger = logging.getLogger(p)
4647

47-
48+
@log_initialization
4849
class StageController(GUIController):
4950
"""StageController
5051
@@ -261,27 +262,22 @@ def disable_synthetic_stages(self, config):
261262
if axis == "x":
262263
self.view.xy_frame.up_x_btn.config(state=state)
263264
self.view.xy_frame.down_x_btn.config(state=state)
264-
logger.info(f"X axis buttons set to {state}")
265265

266266
elif axis == "y":
267267
self.view.xy_frame.up_y_btn.config(state=state)
268268
self.view.xy_frame.down_y_btn.config(state=state)
269-
logger.info(f"Y axis buttons set to {state}")
270269

271270
elif axis == "z":
272271
self.view.z_frame.down_btn.config(state=state)
273272
self.view.z_frame.up_btn.config(state=state)
274-
logger.info(f"Z axis buttons set to {state}")
275273

276274
elif axis == "theta":
277275
self.view.theta_frame.down_btn.config(state=state)
278276
self.view.theta_frame.up_btn.config(state=state)
279-
logger.info(f"Theta axis buttons set to {state}")
280277

281278
elif axis == "f":
282279
self.view.f_frame.down_btn.config(state=state)
283280
self.view.f_frame.up_btn.config(state=state)
284-
logger.info(f"Focus axis buttons set to {state}")
285281
else:
286282
pass
287283

src/navigate/log_files/filters.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,10 @@ def filter(self, record):
9797
if record.getMessage().startswith("Spec"):
9898
return False
9999
return True
100+
101+
class DebugFilter(logging.Filter):
102+
"""
103+
A custom logging filter to include only DEBUG level messages.
104+
"""
105+
def filter(self, record):
106+
return record.levelno == logging.DEBUG

src/navigate/log_files/log_functions.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,6 @@ def find_filename(k, v):
6262
-------
6363
bool
6464
True if k == 'filename', False otherwise
65-
66-
Examples
67-
--------
68-
>>> find_filename('filename', 'test')
6965
"""
7066
if k == "filename":
7167
return True

src/navigate/log_files/logging.yml

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ filters:
99
(): ext://navigate.log_files.filters.PerformanceFilter
1010
not_performance:
1111
(): ext://navigate.log_files.filters.NonPerfFilter
12+
only_debug:
13+
(): ext://navigate.log_files.filters.DebugFilter
1214
handlers:
1315
console:
1416
class: logging.StreamHandler
@@ -28,27 +30,30 @@ handlers:
2830
level: DEBUG
2931
formatter: base
3032
filename: view_controller_debug.log
31-
filters: [not_performance]
32-
mode: a
33-
performance:
34-
class: logging.handlers.RotatingFileHandler
35-
level: DEBUG
36-
formatter: base
37-
filename: performance.log
38-
filters: [performance_specs]
33+
filters: [not_performance, only_debug]
3934
mode: a
35+
# performance:
36+
# class: logging.handlers.RotatingFileHandler
37+
# level: DEBUG
38+
# formatter: base
39+
# filename: view_controller_performance.log
40+
# filters: [performance_specs]
41+
# mode: a
4042
loggers:
4143
view:
4244
level: DEBUG
43-
handlers: [console, vc_info, vc_debug, performance]
45+
# handlers: [console, vc_info, vc_debug, performance]
46+
handlers: [console, vc_info, vc_debug]
4447
propagate: no
4548
controller:
4649
level: DEBUG
47-
handlers: [console, vc_info, vc_debug, performance]
50+
# handlers: [console, vc_info, vc_debug, performance]
51+
handlers: [console, vc_info, vc_debug]
4852
propagate: no
4953
config:
5054
level: DEBUG
51-
handlers: [console, vc_info, vc_debug, performance]
55+
# handlers: [console, vc_info, vc_debug, performance]
56+
handlers: [console, vc_info, vc_debug]
5257
propagate: no
5358

5459

src/navigate/log_files/model_logging.yml

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ filters:
99
(): ext://navigate.log_files.filters.PerformanceFilter
1010
not_performance:
1111
(): ext://navigate.log_files.filters.NonPerfFilter
12+
only_debug:
13+
(): ext://navigate.log_files.filters.DebugFilter
1214
handlers:
1315
console:
1416
class: logging.StreamHandler
@@ -28,7 +30,7 @@ handlers:
2830
level: DEBUG
2931
formatter: base
3032
filename: model_debug.log
31-
filters: [not_performance]
33+
filters: [not_performance, only_debug]
3234
mode: a
3335
model_error:
3436
class: logging.handlers.RotatingFileHandler
@@ -37,15 +39,16 @@ handlers:
3739
filename: model_error.log
3840
filters: [not_performance]
3941
mode: a
40-
model_performance:
41-
class: logging.handlers.RotatingFileHandler
42-
level: DEBUG
43-
formatter: base
44-
filename: model_performance.log
45-
filters: [performance_specs]
46-
mode: a
42+
# model_performance:
43+
# class: logging.handlers.RotatingFileHandler
44+
# level: DEBUG
45+
# formatter: base
46+
# filename: model_performance.log
47+
# filters: [performance_specs]
48+
# mode: a
4749
loggers:
4850
model:
4951
level: DEBUG
50-
handlers: [console, model_info, model_debug, model_performance]
52+
handlers: [console, model_info, model_debug]
53+
# handlers: [console, model_info, model_debug, model_performance]
5154
propagate: no

src/navigate/model/device_startup_functions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def auto_redial(func, args, n_tries=10, exception=Exception, **kwargs):
9292
val = None
9393
time.sleep(0.5) # TODO: 0.5 reached by trial and error. Better value?
9494
else:
95-
logger.error(f"Device startup error: {e}")
95+
logger.error(f"Device startup failed: {e}")
9696
raise exception
9797
else:
9898
break

0 commit comments

Comments
 (0)