3131from PyDAQmx .DAQmxCallBack import *
3232
3333import numpy as np
34+ from numpy .lib .recfunctions import structured_to_unstructured
3435import labscript_utils .h5_lock
3536import h5py
3637from zprocess import Event
@@ -196,32 +197,32 @@ def program_buffered_DO(self, DO_table):
196197 line_final_value = bool ((1 << line ) & port_final_value )
197198 final_values ['%s/line%d' % (port_str , line )] = int (line_final_value )
198199
200+ # Convert DO table to a regular array and ensure it is C continguous:
201+ DO_table = np .ascontiguousarray (
202+ structured_to_unstructured (DO_table , dtype = np .uint32 )
203+ )
204+
199205 # Check if DOs are all zero for the whole shot. If they are this triggers a
200206 # bug in NI-DAQmx that throws a cryptic error for buffered output. In this
201207 # case, run it as a non-buffered task.
202- self .DO_all_zero = all (
203- DO_table [port ].sum () == 0 for port in DO_table .dtype .names
204- )
208+ self .DO_all_zero = not np .any (DO_table )
205209 if self .DO_all_zero :
206210 DO_table = DO_table [0 :1 ]
207211
208212 if self .static_DO or self .DO_all_zero :
209213 # Static DO. Start the task and write data, no timing configuration.
210214 self .DO_task .StartTask ()
211- # Write data for each port:
212- for port_str in ports :
213- # See the comment in self.program_manual as to why we are using uint32
214- # instead of the native size of the port
215- data = DO_table [port_str ].astype (np .uint32 , order = 'C' )
216- self .DO_task .WriteDigitalU32 (
217- 1 , # npts
218- False , # autostart
219- 10.0 , # timeout
220- DAQmx_Val_GroupByChannel ,
221- data ,
222- written ,
223- None ,
224- )
215+ # Write data. See the comment in self.program_manual as to why we are using
216+ # uint32 instead of the native size of each port
217+ self .DO_task .WriteDigitalU32 (
218+ 1 , # npts
219+ False , # autostart
220+ 10.0 , # timeout
221+ DAQmx_Val_GroupByScanNumber ,
222+ DO_table ,
223+ written ,
224+ None ,
225+ )
225226 else :
226227 # We use all but the last sample (which is identical to the second last
227228 # sample) in order to ensure there is one more clock tick than there are
@@ -237,23 +238,18 @@ def program_buffered_DO(self, DO_table):
237238 DAQmx_Val_FiniteSamps ,
238239 npts ,
239240 )
240- self .DO_task .CfgOutputBuffer (npts )
241-
242- # Write data for each port:
243- for port_str in ports :
244- # Use all but the last sample as mentioned above. See the comment in
245- # self.program_manual as to why we are using uint32 instead of the native
246- # size of the port.
247- data = DO_table [port_str ][:- 1 ].astype (np .uint32 , order = 'C' )
248- self .DO_task .WriteDigitalU32 (
249- npts ,
250- False , # autostart
251- 10.0 , # timeout
252- DAQmx_Val_GroupByChannel ,
253- data ,
254- written ,
255- None ,
256- )
241+
242+ # Write data. See the comment in self.program_manual as to why we are using
243+ # uint32 instead of the native size of each port.
244+ self .DO_task .WriteDigitalU32 (
245+ npts ,
246+ False , # autostart
247+ 10.0 , # timeout
248+ DAQmx_Val_GroupByScanNumber ,
249+ DO_table [:- 1 ], # All but the last sample as mentioned above
250+ written ,
251+ None ,
252+ )
257253
258254 # Go!
259255 self .DO_task .StartTask ()
@@ -273,15 +269,15 @@ def program_buffered_AO(self, AO_table):
273269 # Collect the final values of the analog outs:
274270 final_values = dict (zip (AO_table .dtype .names , AO_table [- 1 ]))
275271
276- # Obtain a view that is a regular array:
277- AO_table = AO_table . view (( AO_table . dtype [ 0 ], len ( AO_table . dtype . names )))
278- # And convert to 64 bit floats:
279- AO_table = AO_table . astype ( np . float64 )
272+ # Convert AO table to a regular array and ensure it is C continguous :
273+ AO_table = np . ascontiguousarray (
274+ structured_to_unstructured ( AO_table , dtype = np . float64 )
275+ )
280276
281277 # Check if AOs are all zero for the whole shot. If they are this triggers a
282278 # bug in NI-DAQmx that throws a cryptic error for buffered output. In this
283279 # case, run it as a non-buffered task.
284- self .AO_all_zero = all ( AO_table . flatten () == 0 )
280+ self .AO_all_zero = not np . any ( AO_table )
285281 if self .AO_all_zero :
286282 AO_table = AO_table [0 :1 ]
287283
0 commit comments