Skip to content

Commit 6254f5c

Browse files
Commented ASIDaq
1 parent 7e0e7a1 commit 6254f5c

File tree

1 file changed

+56
-75
lines changed
  • src/navigate/model/devices/daq

1 file changed

+56
-75
lines changed

src/navigate/model/devices/daq/asi.py

Lines changed: 56 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,14 @@ def __init__(self, microscope_name, device_connection, configuration: Dict[str,
6868
6969
Parameters
7070
----------
71+
microscope_name : str
72+
Name of the microscope.
73+
device_connection : Any
74+
Connection to the Tiger Controller.
7175
configuration : Dict[str, Any]
72-
Configuration dictionary.
76+
Dictionary of configuration parameters.
77+
device_id : int
78+
Parameter necessary for start_device but not used here.
7379
"""
7480
super().__init__(configuration)
7581

@@ -96,8 +102,10 @@ def __init__(self, microscope_name, device_connection, configuration: Dict[str,
96102

97103
#: str: microscope name
98104
self.microscope_name = microscope_name
105+
99106
#: str: zoom
100107
self.zoom = self.configuration["experiment"]["MicroscopeState"]["zoom"]
108+
101109
# retrieves galvo ListProxy/DictProxy from config file
102110
galvos_raw = self.configuration["configuration"]['microscopes'][self.microscope_name]['galvo']
103111

@@ -109,7 +117,7 @@ def __init__(self, microscope_name, device_connection, configuration: Dict[str,
109117
else:
110118
raise TypeError("Unexpected type for galvos: {}".format(type(galvos_raw)))
111119

112-
# update analog outputs with galvo numbers and associated axes
120+
# update analog outputs with galvo IDs and associated axes
113121
i=0
114122
for g in self.galvos:
115123
self.analog_outputs[f"galvo {i}"] = g['hardware']['axis']
@@ -119,17 +127,18 @@ def __init__(self, microscope_name, device_connection, configuration: Dict[str,
119127
self.phases = [
120128
galvo["phase"] for galvo in self.galvos
121129
]
122-
print(self.phases)
130+
123131
# update analog outputs with rfvc and associated axis
124132
remote_focus_channel = self.configuration["configuration"]["microscopes"][self.microscope_name]["remote_focus"]["hardware"]["axis"]
125133
self.analog_outputs["remote_focus"] = remote_focus_channel
126-
# sets up initial PLC configuration with default delay (ms), sweep time (ms), and analog outputs dict
134+
135+
# sets up initial PLC configuration with default delay (ms), camera delay, rfvc delay, sweep time (ms), and analog outputs dict
127136
self.daq.setup_control_loop([200], 0, 0, 120, self.analog_outputs)
128137

129138

130139
@classmethod
131140
def connect(cls, port, baudrate=115200, timeout=0.25):
132-
"""Build ASILaser Serial Port connection
141+
"""Build ASIDaq Serial Port connection
133142
134143
Parameters
135144
----------
@@ -153,129 +162,101 @@ def connect(cls, port, baudrate=115200, timeout=0.25):
153162
raise Exception("ASI stage connection failed.")
154163
return tiger_controller
155164

156-
def create_camera_task(self, channel_key: str) -> None:
157-
"""
158-
Set up the camera trigger pulse using ASI Tiger Controller.
165+
def prepare_acquisition(self, channel_key: str) -> None:
166+
"""Prepare the acquisition.
167+
168+
Creates and configures the DAQ tasks.
169+
Writes the waveforms to each task.
159170
160171
Parameters
161172
----------
162173
channel_key : str
163174
Channel key for current channel.
164175
"""
165-
camera_waveform_repeat_num = self.waveform_repeat_num * self.waveform_expand_num
166-
167-
if self.analog_outputs:
168-
camera_high_time = 4 # ms
169-
elif camera_waveform_repeat_num == 1:
170-
camera_high_time = (self.sweep_times[channel_key] * 1000) - (self.camera_delay * 1000)
171-
else:
172-
camera_high_time = (self.sweep_times[channel_key] * 1000) - 4
173-
174-
camera_delay_ms = int(self.camera_delay * 1000)
175-
176-
ttl_channel = int(self.configuration["configuration"]["microscopes"][self.microscope_name]["daq"]["camera_trigger_out_line"])
177-
178-
try:
179-
response = TigerController.send_ttl_pulse(
180-
channel=ttl_channel,
181-
pulse_width_ms=int(camera_high_time),
182-
delay_ms=camera_delay_ms
183-
)
184-
logger.info(f"Sent TTL command to ASI: {response}")
185-
except Exception:
186-
logger.exception("Failed to send TTL command to ASI.")
187-
188-
def prepare_acquisition(self, channel_key: str) -> None:
189-
# self.create_analog_output_tasks(channel_key)
190-
# self.create_camera_task(channel_key)
191-
192-
# Gets appropriate sweep_time for the current channel
176+
# Get appropriate sweep_time for the current channel
193177
sweep_time = self.sweep_times[channel_key]
194178

195-
# loops through galvo phases to calculate time delays
196-
# delays[i] corresponds to the time between the triggering of the ith galvo and the master trigger
197-
# delay between consecutive triggers must be greater than 175 ms (limitation of TG-1000)
179+
# loop through galvo phases to calculate time delays
180+
# delays[i] corresponds to the time between the ith galvo trigger and the master trigger
198181
n = len(self.galvos)
199182
i = 0
200183
delays = []
201184
for phase in self.phases:
202185
frequency = self.waveform_constants["galvo_constants"][f"Galvo {i}"][self.microscope_name][self.zoom]["frequency"]
203186
period = self.exposure_times[channel_key]*1000/float(frequency)
204-
# rounds period for triangle waveform to even number, as the TG-1000 can only generate triangle waveforms with even-number-of-ms periods
187+
188+
# round period for triangle waveform to even number, as the TG-1000 can only generate triangle waveforms with even-number-of-ms periods
205189
if self.galvos[i]['waveform'] == 'sawtooth':
206190
rising_ramp = float(self.waveform_constants["galvo_constants"][f"Galvo {i}"][self.microscope_name][self.zoom].get("rising_ramp", 50))
207191
if (rising_ramp == 50):
208192
period = 2*round(period/2)
209-
# rounds period to closest number of ms, as TG-1000 can only generate waveforms with whole number of ms periods
193+
194+
# round period to closest number of ms, as TG-1000 can only generate waveforms with whole-number-of-ms periods
210195
period = int(round(period))
196+
197+
# save first period to sync control loop with first galvo
211198
if (i == 0):
212-
period1 = period # saves first period to sync loop with first galvo
199+
period0 = period
200+
201+
# calculate time delay corresponding to phase offset
213202
t = period*phase/(2*3.14159265)
214-
# n39 = ((n-i)*0 + t) // period + 1
215203
delays.append(period*(n-i) - t)
216204
i += 1
217-
# modify sweep time to sync with first galvo if there are asi galvos in config
205+
206+
# modify sweep time to sync with the first galvo if there are asi galvos in config
218207
if (len(delays) > 0):
219-
n7 = 1000*sweep_time // period1 + 1
220-
sweep_time = period1*n7
208+
n7 = 1000*sweep_time // period0 + 1
209+
sweep_time = period0*n7
221210

222211
self.camera_delay = (
223212
float(self.waveform_constants["other_constants"].get("camera_delay", 5))
224213
)
225214
rfvc_delay = (
226215
float(self.waveform_constants["other_constants"].get("remote_focus_delay", 5))
227216
)
228-
229-
self.daq.setup_control_loop(delays, self.camera_delay, rfvc_delay, sweep_time, self.analog_outputs) # delay (ms), sweep_time (ms)
217+
# sets up control loop with all parameters (all times in ms)
218+
self.daq.setup_control_loop(delays, self.camera_delay, rfvc_delay, sweep_time, self.analog_outputs)
230219

231220
self.current_channel_key = channel_key
232221
self.is_updating_analog_task = False
233222
# if self.wait_to_run_lock.locked():
234223
# self.wait_to_run_lock.release()
235224

236225
def run_acquisition(self) -> None:
226+
"""Run DAQ Acquisition.
237227
228+
Run the tasks for triggering, analog and counter outputs.
229+
The master trigger initiates all other waveforms via a shared trigger
230+
For this to work, all analog output and counter tasks have to be primed so that
231+
they are waiting for the trigger signal.
232+
"""
238233
# if self.is_updating_analog_task:
239234
# self.wait_to_run_lock.acquire()
240235
# self.wait_to_run_lock.release()
241236

242-
# try:
243-
#send logic card on to cell 1
244-
self.daq.logic_cell_on("1")
245-
# self.daq.trigger_acquisition()
246-
# except Exception:
247-
# logger.debug("DAQ cannot turn on")
248-
# pass
237+
# turn on PLC cell 1 (Master Trigger)
238+
try:
239+
self.daq.logic_cell_on("1")
240+
except Exception:
241+
logger.debug("DAQ cannot turn on")
242+
pass
249243

250244
def stop_acquisition(self) -> None:
251-
#send logic card off to cell 1
245+
"""Stop Acquisition.
246+
247+
Stop control loop.
248+
"""
249+
# turn on PLC cell 8 (kills control loop)
250+
# reset PLC cell 1 (Master Trigger)
252251
try:
253252
self.daq.logic_cell_on("8")
254-
self.daq.logic_cell_off("1")
255-
# self.daq.send_command("3 sam a = 0")
256-
# self.daq.read_response()
257-
# self.daq.send_command("3 sam c = 0")
258-
# self.daq.read_response()
253+
self.daq.logic_cell_off("1")
259254
except Exception:
260255
logger.debug("DAQ cannot turn off")
261256
pass
262257

263258
# if self.wait_to_run_lock.locked():
264259
# self.wait_to_run_lock.release()
265260

266-
# def create_analog_output_tasks(self, channel_key: str) -> None:
267-
# galvo_channel = self.configuration["configuration"]["microscopes"][self.microscope_name]["galvo"][0]["hardware"]["axis"]
268-
# if isinstance(galvo_channel, list):
269-
# for channel in galvo_channel:
270-
# self.analog_outputs.update({channel: "galvo"})
271-
# self.galvo.move(self.exposure_times,self.sweep_times,offset=None)
272-
# else:
273-
# self.analog_outputs.update({galvo_channel: "galvo"})
274-
# remote_focus_channel = self.configuration["configuration"]["microscopes"][self.microscope_name]["remote_focus"]["hardware"]["axis"]
275-
# self.analog_outputs.update({remote_focus_channel: "remote_focus"})
276-
# print(self.exposure_times)
277-
# print(self.sweep_times)
278-
# self.remote_focus.move(self.exposure_times, self.sweep_times)
279-
280261

281262

0 commit comments

Comments
 (0)