1
1
# Copyright (c) 2021-2024 The University of Texas Southwestern Medical Center.
2
2
# All rights reserved.
3
-
4
3
# Redistribution and use in source and binary forms, with or without
5
4
# modification, are permitted for academic and research use only (subject to the
6
5
# limitations in the disclaimer below) provided that the following conditions are met:
36
35
import traceback
37
36
import time
38
37
from typing import Union , Dict , Any
38
+ import gc
39
39
40
40
# Third Party Imports
41
41
import nidaqmx
42
42
import nidaqmx .constants
43
43
import nidaqmx .task
44
+ from nidaqmx .system import System
44
45
import numpy as np
45
46
46
47
# Local Imports
@@ -104,13 +105,23 @@ def __init__(self, configuration: Dict[str, Any]) -> None:
104
105
#: bool: Flag for waiting to run.
105
106
self .wait_to_run_lock = Lock ()
106
107
108
+ #: int: trigger count
109
+ self .trigger_count = 0
110
+
111
+ #: int: trigger reset count
112
+ self .trigger_reset_count = None
113
+
107
114
def __str__ (self ) -> str :
108
115
"""String representation of the class."""
109
116
return "NIDAQ"
110
117
111
118
def __del__ (self ) -> None :
112
119
"""Destructor."""
113
- for task in [self .camera_trigger_task , self .master_trigger_task , self .laser_switching_task ]:
120
+ for task in [
121
+ self .camera_trigger_task ,
122
+ self .master_trigger_task ,
123
+ self .laser_switching_task ,
124
+ ]:
114
125
if task :
115
126
try :
116
127
task .stop ()
@@ -125,8 +136,9 @@ def __del__(self) -> None:
125
136
task .stop ()
126
137
task .close ()
127
138
except Exception :
128
- logger .exception (f"Error stopping task: { traceback .format_exc ()} " )
129
-
139
+ logger .exception (
140
+ f"Error stopping task: { traceback .format_exc ()} "
141
+ )
130
142
131
143
def set_external_trigger (self , external_trigger = None ) -> None :
132
144
"""Set trigger mode.
@@ -438,7 +450,7 @@ def prepare_acquisition(self, channel_key: str) -> None:
438
450
# Specify ports, timing, and triggering
439
451
self .set_external_trigger (self .external_trigger )
440
452
441
- def run_acquisition (self , wait_until_done : bool = True ) -> None :
453
+ def run_acquisition (self , wait_until_done : bool = True ) -> None :
442
454
"""Run DAQ Acquisition.
443
455
444
456
Run the tasks for triggering, analog and counter outputs.
@@ -464,6 +476,8 @@ def run_acquisition(self, wait_until_done : bool = True) -> None:
464
476
if wait_until_done :
465
477
self .wait_acquisition_done ()
466
478
479
+ self .trigger_count += 1
480
+
467
481
def wait_acquisition_done (self ) -> None :
468
482
"""Wait acquisition tasks done"""
469
483
@@ -485,6 +499,13 @@ def wait_acquisition_done(self) -> None:
485
499
except nidaqmx .DaqError :
486
500
pass
487
501
502
+ if (
503
+ self .trigger_reset_count is not None
504
+ and self .trigger_count >= self .trigger_reset_count
505
+ ):
506
+ self .stop_acquisition ()
507
+ self .prepare_acquisition (self .current_channel_key )
508
+
488
509
def stop_acquisition (self ) -> None :
489
510
"""Stop Acquisition.
490
511
@@ -509,6 +530,12 @@ def stop_acquisition(self) -> None:
509
530
self .wait_to_run_lock .release ()
510
531
511
532
self .analog_output_tasks = {}
533
+ if (
534
+ self .trigger_reset_count is not None
535
+ and self .trigger_count >= self .trigger_reset_count
536
+ ):
537
+ self .reset ()
538
+ self .trigger_count = 0
512
539
513
540
def enable_microscope (self , microscope_name : str ) -> None :
514
541
"""Enable microscope.
@@ -522,6 +549,9 @@ def enable_microscope(self, microscope_name: str) -> None:
522
549
self .microscope_name = microscope_name
523
550
self .analog_outputs = {}
524
551
self .analog_output_tasks = {}
552
+ self .trigger_reset_count = self .configuration ["configuration" ][
553
+ "microscopes"
554
+ ][microscope_name ]["daq" ].get ("trigger_reset_count" , None )
525
555
526
556
self .camera_delay = (
527
557
float (self .waveform_constants ["other_constants" ].get ("camera_delay" , 5 ))
@@ -607,3 +637,29 @@ def update_analog_task(self, board_name: str) -> Union[bool, None]:
607
637
608
638
self .is_updating_analog_task = False
609
639
self .wait_to_run_lock .release ()
640
+
641
+ def reset (self , device_name : str = None ) -> None :
642
+ """Reset the DAQ device.
643
+
644
+ Parameters
645
+ ----------
646
+ device_name : str
647
+ Name of the device to reset. If None, reset all devices.
648
+ """
649
+ for k in list (self .analog_output_tasks .keys ()):
650
+ del self .analog_output_tasks [k ]
651
+
652
+ if hasattr (self , "camera_trigger_task" ):
653
+ del self .camera_trigger_task
654
+ if hasattr (self , "master_trigger_task" ):
655
+ del self .master_trigger_task
656
+ gc .collect ()
657
+
658
+ system = System .local ()
659
+ for device in system .devices :
660
+ if device_name is None or device .name == device_name :
661
+ try :
662
+ device .reset_device ()
663
+ logger .info (f"Reset device: { device .name } " )
664
+ except Exception :
665
+ logger .debug (f"Could not reset device: { traceback .format_exc ()} " )
0 commit comments