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,6 +197,11 @@ 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.
@@ -208,20 +214,17 @@ def program_buffered_DO(self, DO_table):
208214 if self .static_DO or self .DO_all_zero :
209215 # Static DO. Start the task and write data, no timing configuration.
210216 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- )
217+ # Write data. See the comment in self.program_manual as to why we are using
218+ # uint32 instead of the native size of each port
219+ self .DO_task .WriteDigitalU32 (
220+ 1 , # npts
221+ False , # autostart
222+ 10.0 , # timeout
223+ DAQmx_Val_GroupByScanNumber ,
224+ DO_table ,
225+ written ,
226+ None ,
227+ )
225228 else :
226229 # We use all but the last sample (which is identical to the second last
227230 # sample) in order to ensure there is one more clock tick than there are
@@ -237,23 +240,18 @@ def program_buffered_DO(self, DO_table):
237240 DAQmx_Val_FiniteSamps ,
238241 npts ,
239242 )
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- )
243+
244+ # Write data. See the comment in self.program_manual as to why we are using
245+ # uint32 instead of the native size of each port.
246+ self .DO_task .WriteDigitalU32 (
247+ npts ,
248+ False , # autostart
249+ 10.0 , # timeout
250+ DAQmx_Val_GroupByScanNumber ,
251+ DO_table [:- 1 ], # All but the last sample as mentioned above
252+ written ,
253+ None ,
254+ )
257255
258256 # Go!
259257 self .DO_task .StartTask ()
@@ -273,10 +271,10 @@ def program_buffered_AO(self, AO_table):
273271 # Collect the final values of the analog outs:
274272 final_values = dict (zip (AO_table .dtype .names , AO_table [- 1 ]))
275273
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 )
274+ # Convert AO table to a regular array and ensure it is C continguous :
275+ AO_table = np . ascontiguousarray (
276+ structured_to_unstructured ( AO_table , dtype = np . float64 )
277+ )
280278
281279 # Check if AOs are all zero for the whole shot. If they are this triggers a
282280 # bug in NI-DAQmx that throws a cryptic error for buffered output. In this
0 commit comments