def test_flatten_channel_string(self, x_series_device, seed): # Reset the pseudorandom number generator with seed. random.seed(seed) channels = ['Dev1/ai0', 'Dev1/ai1', 'Dev1/ai3', 'Dev2/ai0'] flattened_channels = 'Dev1/ai0:1,Dev1/ai3,Dev2/ai0' assert flatten_channel_string(channels) == flattened_channels assert flatten_channel_string([]) == ''
def test_one_sample_multi_line(self, x_series_device, seed): # Reset the pseudorandom number generator with seed. random.seed(seed) number_of_lines = random.randint(2, len(x_series_device.do_lines)) do_lines = random.sample(x_series_device.do_lines, number_of_lines) with nidaqmx.Task() as task: task.do_channels.add_do_chan( flatten_channel_string([d.name for d in do_lines]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES) writer = DigitalSingleChannelWriter(task.out_stream) reader = DigitalSingleChannelReader(task.in_stream) # Generate random values to test. values_to_test = numpy.array( [bool(random.getrandbits(1)) for _ in range(number_of_lines)]) writer.write_one_sample_multi_line(values_to_test) time.sleep(0.001) values_read = numpy.zeros(number_of_lines, dtype=bool) reader.read_one_sample_multi_line(values_read) numpy.testing.assert_array_equal(values_read, values_to_test)
def test_insufficient_write_data(self, x_series_device, seed): # Reset the pseudorandom number generator with seed. random.seed(seed) # Randomly select physical channels to test. number_of_channels = random.randint( 2, len(x_series_device.ao_physical_chans)) channels_to_test = random.sample(x_series_device.ao_physical_chans, number_of_channels) with nidaqmx.Task() as task: task.ao_channels.add_ao_voltage_chan(flatten_channel_string( [c.name for c in channels_to_test]), max_val=10, min_val=-10) with pytest.raises(DaqError) as e: task.write(random.uniform(-10, 10)) assert e.value.error_code == -200524 number_of_samples = random.randint(1, number_of_channels - 1) values_to_test = [ random.uniform(-10, 10) for _ in range(number_of_samples) ] with pytest.raises(DaqError) as e: task.write(values_to_test, auto_start=True) assert e.value.error_code == -200524
def all(self): """ nidaqmx.system.physical_channel.PhysicalChannel: Specifies a physical channel object that represents the entire list of physical channels on this channel collection. """ return PhysicalChannel(flatten_channel_string(self.channel_names))
def test_bool_n_chan_1_samp(self, x_series_device, seed): # Reset the pseudorandom number generator with seed. random.seed(seed) number_of_channels = random.randint(2, len(x_series_device.do_lines)) do_lines = random.sample(x_series_device.do_lines, number_of_channels) with nidaqmx.Task() as task: task.do_channels.add_do_chan( flatten_channel_string([d.name for d in do_lines]), line_grouping=LineGrouping.CHAN_PER_LINE) # Generate random values to test. values_to_test = [ bool(random.getrandbits(1)) for _ in range(number_of_channels) ] task.write(values_to_test) time.sleep(0.001) values_read = task.read() assert values_read == values_to_test # Verify setting number_of_samples_per_channel (even to 1) # returns a list of lists. value_read = task.read(number_of_samples_per_channel=1) assert isinstance(value_read, list) assert isinstance(value_read[0], list)
def test_uint_multi_port(self, x_series_device, seed): if len([d.do_port_width <= 16 for d in x_series_device.do_ports]) < 2: pytest.skip( 'task.read() accepts max of 32 bits for digital uint reads.') # Reset the pseudorandom number generator with seed. random.seed(seed) do_ports = random.sample( [d for d in x_series_device.do_ports if d.do_port_width <= 16], 2) total_port_width = sum([d.do_port_width for d in do_ports]) with nidaqmx.Task() as task: task.do_channels.add_do_chan( flatten_channel_string([d.name for d in do_ports]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES) # Generate random values to test. values_to_test = [ int(random.getrandbits(total_port_width)) for _ in range(10) ] values_read = [] for value_to_test in values_to_test: task.write(value_to_test) time.sleep(0.001) values_read.append(task.read()) assert values_read == values_to_test
def rec_only(device, t_array, inputs): dt = t_array[1] - t_array[0] sampling_rate = 1. / dt # if outputs.shape[0]>0: input_channels = get_analog_input_channels(device)[:inputs.shape[0]] with nidaqmx.Task() as read_task, nidaqmx.Task() as sample_clk_task: # Use a counter output pulse train task as the sample clock source # for both the AI and AO tasks. sample_clk_task.co_channels.add_co_pulse_chan_freq('{0}/ctr0'.format( device.name), freq=sampling_rate) sample_clk_task.timing.cfg_implicit_timing(samps_per_chan=len(t_array)) samp_clk_terminal = '/{0}/Ctr0InternalOutput'.format(device.name) read_task.ai_channels.add_ai_voltage_chan( flatten_channel_string(input_channels), max_val=10, min_val=-10) read_task.timing.cfg_samp_clk_timing(sampling_rate, source=samp_clk_terminal, active_edge=Edge.FALLING, samps_per_chan=len(t_array)) reader = AnalogMultiChannelReader(read_task.in_stream) # Start the read task before starting the sample clock source task. read_task.start() sample_clk_task.start() reader.read_many_sample(inputs, number_of_samples_per_channel=len(t_array), timeout=t_array[-1] + 2 * dt)
def test_extraneous_numpy_write_data(self, x_series_device, seed): # Reset the pseudorandom number generator with seed. random.seed(seed) # Randomly select physical channels to test. number_of_channels = random.randint( 1, len(x_series_device.ao_physical_chans)) channels_to_test = random.sample(x_series_device.ao_physical_chans, number_of_channels) with nidaqmx.Task() as task: task.ao_channels.add_ao_voltage_chan(flatten_channel_string( [c.name for c in channels_to_test]), max_val=10, min_val=-10) # Generate random values to test. number_of_data_rows = random.randint(number_of_channels + 1, number_of_channels + 10) values_to_test = [[random.uniform(-10, 10) for _ in range(10)] for _ in range(number_of_data_rows)] numpy_data = numpy.float64(values_to_test) with pytest.raises(DaqError) as e: task.write(numpy_data, auto_start=True) assert e.value.error_code == -200524
def test_numpy_write_incorrectly_shaped_data(self, x_series_device, seed): # Reset the pseudorandom number generator with seed. random.seed(seed) # Randomly select physical channels to test. number_of_channels = random.randint( 2, len(x_series_device.ao_physical_chans)) channels_to_test = random.sample(x_series_device.ao_physical_chans, number_of_channels) number_of_samples = random.randint(50, 100) with nidaqmx.Task() as task: task.ao_channels.add_ao_voltage_chan(flatten_channel_string( [c.name for c in channels_to_test]), max_val=10, min_val=-10) task.timing.cfg_samp_clk_timing(1000, samps_per_chan=number_of_samples) # Generate write data but swap the rows and columns so the numpy # array is shaped incorrectly, but the amount of samples is still # the same. values_to_test = numpy.float64( [[random.uniform(-10, 10) for _ in range(number_of_channels)] for _ in range(number_of_samples)]) with pytest.raises(DaqError) as e: task.write(values_to_test, auto_start=True) assert e.value.error_code == -200524
def channels(self): """ :class:`nidaqmx._task_modules.channels.channel.Channel`: Specifies a channel object that represents the entire list of virtual channels in this task. """ return Channel._factory( self._handle, flatten_channel_string(self.channel_names))
def test_n_chan_1_samp(self, x_series_device, seed): # Reset the pseudorandom number generator with seed. random.seed(seed) # Select a random loopback channel pair on the device. loopback_channel_pairs = self._get_analog_loopback_channels( x_series_device) number_of_channels = random.randint(2, len(loopback_channel_pairs)) channels_to_test = random.sample(loopback_channel_pairs, number_of_channels) with nidaqmx.Task() as write_task, nidaqmx.Task() as read_task: write_task.ao_channels.add_ao_voltage_chan(flatten_channel_string( [c.output_channel for c in channels_to_test]), max_val=10, min_val=-10) read_task.ai_channels.add_ai_voltage_chan(flatten_channel_string( [c.input_channel for c in channels_to_test]), max_val=10, min_val=-10) # Generate random values to test. values_to_test = [ random.uniform(-10, 10) for _ in range(number_of_channels) ] write_task.write(values_to_test) time.sleep(0.001) values_read = read_task.read() numpy.testing.assert_allclose(values_read, values_to_test, rtol=0.05, atol=0.005) # Verify setting number_of_samples_per_channel (even to 1) # returns a list of lists. value_read = read_task.read(number_of_samples_per_channel=1) assert isinstance(value_read, list) assert isinstance(value_read[0], list)
def cfg_watchdog_ao_expir_states(self, expiration_states): """ Configures the expiration states for an analog watchdog timer task. Args: expiration_states (List[nidaqmx.system.watchdog.AOExpirationState]): Contains the states to which to set analog physical channels when the watchdog timer expires. Each element of the list contains an analog physical channel name, the corresponding expiration state, and the output type for that analog physical channel. The units of "expiration state" must be specified in volts for an analog output voltage expiration state, or amps for an analog output current expiration state. physical_channel (str): Specifies the analog output channel to modify. You cannot modify dedicated analog input lines. expiration_state (float): Specifies the value to set the channel to upon expiration. output_type (nidaqmx.constants.WatchdogAOExpirState): Specifies the output type of the physical channel. Returns: List[nidaqmx.system._watchdog_modules.expiration_state.ExpirationState]: Indicates the list of objects representing the configured expiration states. """ channel_names = flatten_channel_string( [e.physical_channel for e in expiration_states]) expir_state = numpy.float64( [e.expiration_state for e in expiration_states]) output_type = numpy.int32( [e.output_type.value for e in expiration_states]) cfunc = lib_importer.windll.DAQmxCfgWatchdogAOExpirStates if cfunc.argtypes is None: with cfunc.arglock: if cfunc.argtypes is None: cfunc.argtypes = [ lib_importer.task_handle, ctypes_byte_str, wrapped_ndpointer(dtype=numpy.float64, flags=('C', 'W')), wrapped_ndpointer(dtype=numpy.int32, flags=('C', 'W')), ctypes.c_uint ] error_code = cfunc(self._handle, channel_names, expir_state, output_type, len(expiration_states)) check_for_error(error_code) return [ ExpirationState(self._handle, e.physical_channel) for e in expiration_states ]
def test_concatenate_operations(self, x_series_device, seed): # Reset the pseudorandom number generator with seed. random.seed(seed) ai_phys_chans = random.sample(x_series_device.ai_physical_chans, 2) with nidaqmx.Task() as task: ai_channel_1 = task.ai_channels.add_ai_voltage_chan( ai_phys_chans[0].name, max_val=5, min_val=-5) ai_channel_2 = task.ai_channels.add_ai_voltage_chan( ai_phys_chans[1].name, max_val=5, min_val=-5) # Concatenate two channels. ai_channel = ai_channel_1 + ai_channel_2 # Test that concatenated channel name has flattened value of the # individual channel names. assert ai_channel.name == flatten_channel_string( [ai_phys_chans[0].name, ai_phys_chans[1].name]) # Test that setting property on concatenated channel changes the # property values of the individual channels. ai_channel.ai_max = 10 assert ai_channel_1.ai_max == 10 assert ai_channel_2.ai_max == 10 # Concatenate two channels. ai_channel_1 += ai_channel_2 # Test that concatenated channel name has flattened value of the # individual channel names. assert ai_channel_1.name == flatten_channel_string( [ai_phys_chans[0].name, ai_phys_chans[1].name]) # Test that setting property on concatenated channel changes the # property values of the individual channels. ai_channel_1.ai_max = 0.1 ai_channel_1.ai_min = -0.1 assert ai_channel_2.ai_max == 0.1 assert ai_channel_2.ai_min == -0.1
def get_analog_power_up_states_with_output_type(self, physical_channels): """ Gets the power up states for analog physical channels. Args: physical_channels (List[str]): Indicates the physical channels that were modified. Returns: power_up_states (List[nidaqmx.types.AOPowerUpState]): Contains the physical channels and power up states set. Each element of the list contains a physical channel and the power up state set for that physical channel. - physical_channel (str): Specifies the physical channel that was modified. - power_up_state (float): Specifies the power up state set for the physical channel specified with the **physical_channel** input. - channel_type (:class:`nidaqmx.constants.AOPowerUpOutputBehavior`): Specifies the output type for the physical channel specified with the **physical_channel** input. """ size = len(physical_channels) states = numpy.zeros(size, dtype=numpy.float64) channel_types = numpy.zeros(size, dtype=numpy.int32) cfunc = lib_importer.cdll.DAQmxGetAnalogPowerUpStatesWithOutputType if cfunc.argtypes is None: with cfunc.arglock: if cfunc.argtypes is None: cfunc.argtypes = [ ctypes_byte_str, wrapped_ndpointer(dtype=numpy.float64, flags=('C','W')), wrapped_ndpointer(dtype=numpy.int32, flags=('C','W'))] error_code = cfunc( flatten_channel_string(physical_channels), states, channel_types, size) check_for_error(error_code) power_up_states = [] for p, s, c in zip(physical_channels, states, channel_types): power_up_states.append( AOPowerUpState( physical_channel=p, power_up_state=float(s), channel_type=AOPowerUpOutputBehavior(c.value))) return power_up_states
def __add__(self, other): if not isinstance(other, self.__class__): raise NotImplementedError( 'Cannot concatenate objects of type {0} and {1}'.format( self.__class__, other.__class__)) if self._handle != other._handle: raise NotImplementedError( 'Cannot concatenate Channel objects from different tasks.') name = flatten_channel_string([self.name, other.name]) return Channel._factory(self._handle, name)
def test_one_sample(self, x_series_device, seed): # Reset the pseudorandom number generator with seed. random.seed(seed) # Select a random loopback channel pair on the device. loopback_channel_pairs = self._get_analog_loopback_channels( x_series_device) number_of_channels = random.randint(2, len(loopback_channel_pairs)) channels_to_test = random.sample( loopback_channel_pairs, number_of_channels) with nidaqmx.Task() as write_task, nidaqmx.Task() as read_task: write_task.ao_channels.add_ao_voltage_chan( flatten_channel_string( [c.output_channel for c in channels_to_test]), max_val=10, min_val=-10) read_task.ai_channels.add_ai_voltage_chan( flatten_channel_string( [c.input_channel for c in channels_to_test]), max_val=10, min_val=-10) writer = AnalogMultiChannelWriter(write_task.out_stream) reader = AnalogMultiChannelReader(read_task.in_stream) values_to_test = numpy.array( [random.uniform(-10, 10) for _ in range(number_of_channels)], dtype=numpy.float64) writer.write_one_sample(values_to_test) time.sleep(0.001) values_read = numpy.zeros(number_of_channels, dtype=numpy.float64) reader.read_one_sample(values_read) numpy.testing.assert_allclose( values_read, values_to_test, rtol=0.05, atol=0.005)
def remove_cdaq_sync_connection(self, ports_to_disconnect): """ Removes a cDAQ Sync connection between devices. The connection is not verified. Args: ports_to_disconnect (nidaqmx.types.CDAQSyncConnection): Specifies the cDAQ Sync ports to disconnect. """ port_list = flatten_channel_string( [ports_to_disconnect.output_port, ports_to_disconnect.input_port]) cfunc = lib_importer.windll.DAQmxRemoveCDAQSyncConnection cfunc.argtypes = [ctypes_byte_str] error_code = cfunc(port_list) check_for_error(error_code)
def cfg_watchdog_do_expir_states(self, expiration_states): """ Configures the expiration states for a digital watchdog timer task. Args: expiration_states (List[nidaqmx.system.watchdog.DOExpirationState]): Contains the states to which to set digital physical channels when the watchdog timer expires. Each element of the list contains a digital physical channel name and the corresponding state for that digital physical channel. physical_channel (str): Specifies the digital output channel to modify. You cannot modify dedicated digital input lines. expiration_state (nidaqmx.constants.Level): Specifies the value to set the channel to upon expiration. Returns: List[nidaqmx.system._watchdog_modules.expiration_state.ExpirationState]: Indicates the list of objects representing the configured expiration states. """ channel_names = flatten_channel_string( [e.physical_channel for e in expiration_states]) expir_state = numpy.int32( [e.expiration_state.value for e in expiration_states]) cfunc = lib_importer.windll.DAQmxCfgWatchdogDOExpirStates if cfunc.argtypes is None: with cfunc.arglock: if cfunc.argtypes is None: cfunc.argtypes = [ lib_importer.task_handle, ctypes_byte_str, wrapped_ndpointer(dtype=numpy.int32, flags=('C', 'W')), ctypes.c_uint ] error_code = cfunc(self._handle, channel_names, expir_state, len(expiration_states)) check_for_error(error_code) return [ ExpirationState(self._handle, e.physical_channel) for e in expiration_states ]
def add_cdaq_sync_connection(self, ports_to_connect): """ Adds a cDAQ Sync connection between devices. The connection is not verified. Args: ports_to_connect (nidaqmx.types.CDAQSyncConnection): Specifies the cDAQ Sync ports to connect. """ port_list = flatten_channel_string( [ports_to_connect.output_port, ports_to_connect.input_port]) cfunc = lib_importer.windll.DAQmxAddCDAQSyncConnection if cfunc.argtypes is None: with cfunc.arglock: if cfunc.argtypes is None: cfunc.argtypes = [ctypes_byte_str] error_code = cfunc(port_list) check_for_error(error_code)
def set_analog_power_up_states_with_output_type( self, power_up_states): """ Updates power up states for analog physical channels. Args: power_up_states (List[nidaqmx.types.AOPowerUpState]): Contains the physical channels and power up states to set. Each element of the list contains a physical channel and the power up state to set for that physical channel. - physical_channel (str): Specifies the physical channel to modify. - power_up_state (float): Specifies the power up state to set for the physical channel specified with the **physical_channel** input. - channel_type (:class:`nidaqmx.constants.AOPowerUpOutputBehavior`): Specifies the output type for the physical channel specified with the **physical_channel** input. """ physical_channel = flatten_channel_string( [p.physical_channel for p in power_up_states]) state = numpy.float64( [p.power_up_state for p in power_up_states]) channel_type = numpy.int32( [p.channel_type.value for p in power_up_states]) cfunc = lib_importer.cdll.DAQmxSetAnalogPowerUpStatesWithOutputType if cfunc.argtypes is None: with cfunc.arglock: if cfunc.argtypes is None: cfunc.argtypes = [ ctypes_byte_str, wrapped_ndpointer(dtype=numpy.float64, flags=('C','W')), wrapped_ndpointer(dtype=numpy.int32, flags=('C','W'))] error_code = cfunc( physical_channel, state, channel_type, len(power_up_states)) check_for_error(error_code)
def add_global_channels(self, global_channels): """ Adds global virtual channels from MAX to the given task. Args: global_channels (List[nidaqmx.system.storage.persisted_channel.PersistedChannel]): Specifies the channels to add to the task. These channels must be valid channels available from MAX. If you pass an invalid channel, NI-DAQmx returns an error. This value is ignored if it is empty. """ cfunc = lib_importer.windll.DAQmxAddGlobalChansToTask cfunc.argtypes = [ lib_importer.task_handle, ctypes_byte_str] channels = flatten_channel_string([g._name for g in global_channels]) error_code = cfunc( self._handle, channels) check_for_error(error_code)
def __getitem__(self, index): """ Indexes a subset of virtual channels on this channel collection. Args: index: The value of the index. The following index types are supported: - str: Name of the virtual channel. You also can specify a string that contains a list or range of names to this input. If you have a list of names, use the DAQmx Flatten Channel String function to convert the list to a string. - int: Index/position of the virtual channel in the collection. - slice: Range of the indexes/positions of virtual channels in the collection. Returns: nidaqmx._task_modules.channels.channel.Channel: Indicates a channel object representing the subset of virtual channels indexed. """ if isinstance(index, six.integer_types): channel_names = self.channel_names[index] elif isinstance(index, slice): channel_names = flatten_channel_string(self.channel_names[index]) elif isinstance(index, six.string_types): channel_names = index else: raise DaqError( 'Invalid index type "{0}" used to access channels.'.format( type(index)), DAQmxErrors.UNKNOWN) if channel_names: return Channel._factory(self._handle, channel_names) else: raise DaqError( 'You cannot specify an empty index when indexing channels.\n' 'Index used: {0}'.format(index), DAQmxErrors.UNKNOWN)
def stim_and_rec(device, t_array, analog_inputs, analog_outputs, N_digital_inputs=0): dt = t_array[1] - t_array[0] sampling_rate = 1. / dt # if analog_outputs.shape[0]>0: output_analog_channels = get_analog_output_channels( device)[:analog_outputs.shape[0]] input_analog_channels = get_analog_input_channels( device)[:analog_inputs.shape[0]] if N_digital_inputs > 0: input_digital_channels = get_digital_input_channels( device)[:N_digital_inputs] with nidaqmx.Task() as write_analog_task, nidaqmx.Task() as read_analog_task,\ nidaqmx.Task() as read_digital_task, nidaqmx.Task() as sample_clk_task: # Use a counter output pulse train task as the sample clock source # for both the AI and AO tasks. sample_clk_task.co_channels.add_co_pulse_chan_freq('{0}/ctr0'.format( device.name), freq=sampling_rate) sample_clk_task.timing.cfg_implicit_timing(samps_per_chan=len(t_array)) samp_clk_terminal = '/{0}/Ctr0InternalOutput'.format(device.name) ### ---- OUTPUTS ---- ## write_analog_task.ao_channels.add_ao_voltage_chan( flatten_channel_string(output_analog_channels), max_val=10, min_val=-10) write_analog_task.timing.cfg_samp_clk_timing( sampling_rate, source=samp_clk_terminal, active_edge=Edge.RISING, samps_per_chan=len(t_array)) ### ---- INPUTS ---- ## read_analog_task.ai_channels.add_ai_voltage_chan( flatten_channel_string(input_analog_channels), max_val=10, min_val=-10) if N_digital_inputs > 0: read_digital_task.di_channels.add_di_chan( flatten_channel_string(input_digital_channels)) read_analog_task.timing.cfg_samp_clk_timing( sampling_rate, source=samp_clk_terminal, active_edge=Edge.FALLING, samps_per_chan=len(t_array)) if N_digital_inputs > 0: read_digital_task.timing.cfg_samp_clk_timing( sampling_rate, source=samp_clk_terminal, active_edge=Edge.FALLING, samps_per_chan=len(t_array)) analog_writer = AnalogMultiChannelWriter(write_analog_task.out_stream) analog_reader = AnalogMultiChannelReader(read_analog_task.in_stream) if N_digital_inputs > 0: digital_reader = DigitalMultiChannelReader( read_digital_task.in_stream) analog_writer.write_many_sample(analog_outputs) # Start the read and write tasks before starting the sample clock # source task. read_analog_task.start() if N_digital_inputs > 0: read_digital_task.start() write_analog_task.start() sample_clk_task.start() analog_reader.read_many_sample( analog_inputs, number_of_samples_per_channel=len(t_array), timeout=t_array[-1] + 2 * dt) if N_digital_inputs > 0: digital_inputs = np.zeros((1, len(t_array)), dtype=np.uint32) digital_reader.read_many_sample_port_uint32( digital_inputs, number_of_samples_per_channel=len(t_array), timeout=t_array[-1] + 2 * dt) else: digital_inputs = None return analog_inputs, digital_inputs
def test_n_chan_n_samp(self, x_series_device, seed): # Reset the pseudorandom number generator with seed. random.seed(seed) number_of_samples = random.randint(20, 100) sample_rate = random.uniform(1000, 5000) # Select a random loopback channel pair on the device. loopback_channel_pairs = self._get_analog_loopback_channels( x_series_device) number_of_channels = random.randint(2, len(loopback_channel_pairs)) channels_to_test = random.sample(loopback_channel_pairs, number_of_channels) with nidaqmx.Task() as write_task, nidaqmx.Task() as read_task, \ nidaqmx.Task() as sample_clk_task: # Use a counter output pulse train task as the sample clock source # for both the AI and AO tasks. sample_clk_task.co_channels.add_co_pulse_chan_freq( '{0}/ctr0'.format(x_series_device.name), freq=sample_rate) sample_clk_task.timing.cfg_implicit_timing( samps_per_chan=number_of_samples) sample_clk_task.control(TaskMode.TASK_COMMIT) samp_clk_terminal = '/{0}/Ctr0InternalOutput'.format( x_series_device.name) write_task.ao_channels.add_ao_voltage_chan(flatten_channel_string( [c.output_channel for c in channels_to_test]), max_val=10, min_val=-10) write_task.timing.cfg_samp_clk_timing( sample_rate, source=samp_clk_terminal, active_edge=Edge.RISING, samps_per_chan=number_of_samples) read_task.ai_channels.add_ai_voltage_chan(flatten_channel_string( [c.input_channel for c in channels_to_test]), max_val=10, min_val=-10) read_task.timing.cfg_samp_clk_timing( sample_rate, source=samp_clk_terminal, active_edge=Edge.FALLING, samps_per_chan=number_of_samples) # Generate random values to test. values_to_test = [[ random.uniform(-10, 10) for _ in range(number_of_samples) ] for _ in range(number_of_channels)] write_task.write(values_to_test) # Start the read and write tasks before starting the sample clock # source task. read_task.start() write_task.start() sample_clk_task.start() values_read = read_task.read( number_of_samples_per_channel=number_of_samples, timeout=2) numpy.testing.assert_allclose(values_read, values_to_test, rtol=0.05, atol=0.005)
def _configure_run(self): # check adc_config is filled if not self._adc_config: print('ERROR: First set configuration with "set_adc_config"!') return False # FIXME -> Only for one device adc_keys = list(self._adc_config.keys()) if len(adc_keys) != 1: print('ERROR: Unable to take data with multiple devices (FIXME)') return False config_dict = self._adc_config[adc_keys[0]] # check required parameter for param in self._required_adc_config: if param not in config_dict: print( 'ERROR from polaris::write_config: Missing ADC configuration "' + param + '"!') return False # set channels channel_list = config_dict['channel_list'] if isinstance(channel_list, str): channel_list = arg_utils.hyphen_range(config_dict['channel_list']) channel_names = list() for chan in channel_list: channel_names.append(config_dict['device_name'] + '/ai' + str(chan)) channel_names_flatten = flatten_channel_string(channel_names) # set channels/voltage ai_voltage_channels = self.ai_channels.add_ai_voltage_chan( str(channel_names_flatten), max_val=float(config_dict['voltage_max']), min_val=float(config_dict['voltage_min'])) # fill useful container self._nb_samples = int(config_dict['nb_samples']) self._nb_channels = len(channel_list) # transfer mode (not sure it is doing anything...) #ai_voltage_channels.ai_data_xfer_mech = nidaqmx.constants.DataTransferActiveTransferMode.INTERRUP #ai_voltage_channels.ai_data_xfer_mech = nidaqmx.constants.DataTransferActiveTransferMode.DMA # sampling rate / trigger mode (continuous vs finite) buffer_length = self._nb_samples if config_dict['trigger_type'] == 1: buffer_length = int(config_dict['sample_rate']) if 'buffer_length' in config_dict: buffer_length = config_dict['buffer_length'] mode = int() if config_dict['trigger_type'] == 1: mode = nidaqmx.constants.AcquisitionType.CONTINUOUS else: mode = nidaqmx.constants.AcquisitionType.FINITE self.timing.cfg_samp_clk_timing(int(config_dict['sample_rate']), sample_mode=mode, samps_per_chan=buffer_length) # low pass filter (PCI-6120 only) if niadc.NIDevice.get_product_type() == 'PCI-6120': ai_voltage_channels.ai_lowpass_enable = True # default if 'filter_enable' in config_dict and not config_dict[ 'filter_enable']: ai_voltage_channels.ai_lowpass_enable = False # external trigger if config_dict['trigger_type'] == 2: self.triggers.start_trigger.cfg_dig_edge_start_trig( trigger_source='/' + config_dict['device_name'] + '/pfi0') # data mode if config_dict['trigger_type'] == 1: self._is_continuous = True else: self._is_continuous = False # register callback function self.register_every_n_samples_acquired_into_buffer_event( self._nb_samples, self._read_callback) adc_conversion_factor = list() for chan in ai_voltage_channels: adc_conversion_factor.append(chan.ai_dev_scaling_coeff) config_dict['adc_conversion_factor'] = np.array(adc_conversion_factor) self._is_run_configured = True
seno = wm.Wave('sine', 100) ''' class nidaqmx.stream_writers.AnalogMultiChannelWriter write_many_sample(data, timeout=10.0) data (numpy.ndarray) – Contains a 2D NumPy array of floating-point samples to write to the task. Each row corresponds to a channel in the task. Each column corresponds to a sample to write to each channel. The order of the channels in the array corresponds to the order in which you add the channels to the task. ''' functionstowrite = seno.evaluate_sr(samplerate, duration=duration).T with nid.Task() as write_task: write_task.ao_channels.add_ao_voltage_chan( flatten_channel_string(channels_to_test), max_val=10, min_val=-10) writer = AnalogMultiChannelWriter(write_task.out_stream) values_to_test = functionstowrite writer.write_many_sample(values_to_test) # Start the read and write tasks before starting the sample clock # source task. write_task.start() # Save measurement #%% PWM with nid.Task() as task: # task.co_channels.add_co_pulse_chan_time('Dev20/ctr0') #pin 38 # sample = CtrTime(high_time=.001, low_time=.001) # sample = CtrTime()
if max(samples) > (pidvalue+0.1): delta = max(samples) - pidvalue output_array -= pidconstant * delta elif max(samples) < (pidvalue-0.1): delta = pidvalue - max(samples) output_array += pidconstant * delta return 0 # Now I start the actual PID loop with nid.Task() as write_task, nid.Task() as read_task: # First I configure the reading read_task.ai_channels.add_ai_voltage_chan( flatten_channel_string(channels_to_read), max_val=10, min_val=-10) reader = sr.AnalogMultiChannelReader(read_task.in_stream) # Now I configure the writing write_task.ao_channels.add_ao_voltage_chan( flatten_channel_string(channels_to_write), max_val=10, min_val=-10) writer = sw.AnalogMultiChannelWriter(write_task.out_stream) # source task. # Start the read and write tasks before starting the sample clock # source task. read_task.start() read_task.register_every_n_samples_acquired_into_buffer_event(
print(channels_to_test) with nidaqmx.Task() as write_task, nidaqmx.Task() as read_task, nidaqmx.Task( ) as sample_clk_task: # Use a counter output pulse train task as the sample clock source # for both the AI and AO tasks. sample_clk_task.co_channels.add_co_pulse_chan_freq('{0}/ctr0'.format( x_series_device.name), freq=sample_rate) sample_clk_task.timing.cfg_implicit_timing( samps_per_chan=number_of_samples) samp_clk_terminal = '/{0}/Ctr0InternalOutput'.format(x_series_device.name) write_task.ao_channels.add_ao_voltage_chan(flatten_channel_string( [c.output_channel for c in channels_to_test]), max_val=10, min_val=-10) write_task.timing.cfg_samp_clk_timing(sample_rate, source=samp_clk_terminal, active_edge=Edge.RISING, samps_per_chan=number_of_samples) read_task.ai_channels.add_ai_voltage_chan(flatten_channel_string( [c.input_channel for c in channels_to_test]), max_val=10, min_val=-10) read_task.timing.cfg_samp_clk_timing(sample_rate, source=samp_clk_terminal, active_edge=Edge.FALLING, samps_per_chan=number_of_samples)
def _write_config_file(self): """ Write config file - Assume configuration have been set already """ # check mandatory config if not self._polaris_config: print('ERROR: Polaris configuration not available! Unable to start run') return False if not self._adc_config: print('ERROR: ADC configuration not available! Unable to start run') return False if not self._run_config: print('ERROR: Run configuration not available! Unable to start run') return False # initialize list cfg_list = list() # date now = datetime.now() dt_string = now.strftime('%d/%m/%Y %H:%M:%S') cfg_list.append('# Configuration file production date: ' + dt_string + '\n\n') # polaris module cfg_list.append('\nmodule {\n') for module_key in self._polaris_config: cfg_list.append('\t' + module_key + ' {\n') config_dict = self._polaris_config[module_key] for key in config_dict: cfg_list.append('\t\t' + key + ' : ' + str(config_dict[key]) + ',\n') cfg_list.append('\t}\n') cfg_list.append('}\n\n') # run config for key in self._run_config: cfg_list.append(key + ' : ' + str(self._run_config[key]) + ',\n') # adc config for adc_name in self._adc_config: cfg_list.append('\n' + adc_name + ' {\n') config_dict = self._adc_config[adc_name] # check parameter for param in self._required_adc_config: if param not in config_dict: print('ERROR from polaris::write_config: Missing ADC configuration "' + param + '"!') return False # sample rate, nb samples cfg_list.append('\tsample_rate : ' + str(config_dict['sample_rate']) + ',\n') cfg_list.append('\tnb_samples : ' + str(config_dict['nb_samples']) + ',\n') # channel list channel_list = config_dict['channel_list'] if isinstance(channel_list,str): channel_list = arg_utils.hyphen_range(config_dict['channel_list']) channel_names = list() for chan in channel_list: channel_names.append(config_dict['device_name'] + '/ai' + str(chan)) channel_names_flatten = flatten_channel_string(channel_names) cfg_list.append('\tchannel : ' + channel_names_flatten + ',\n') # voltage range nb_channels = len(channel_list) voltage_min_list =list() if (isinstance(config_dict['voltage_min'], list) and len(config_dict['voltage_min'])==nb_channels): voltage_min_list = config_dict['voltage_min'] else: for ii in range(nb_channels): voltage_min_list.append(config_dict['voltage_min']) Vmin = ' '.join(map(str,voltage_min_list)) cfg_list.append('\tVmin : ' + Vmin + ',\n') voltage_max_list =list() if (isinstance(config_dict['voltage_max'], list) and len(config_dict['voltage_max'])==nb_channels): voltage_max_list = config_dict['voltage_max'] else: for ii in range(nb_channels): voltage_max_list.append(config_dict['voltage_max']) Vmax = ' '.join(map(str,voltage_max_list)) cfg_list.append('\tVmax : ' + Vmax + ',\n') # connection for config in config_dict: if 'connection' in config and 'connection_table'!= config: val = ' '.join(map(str,config_dict[config])) cfg_list.append('\t' + config + ' : ' + val + ',\n') data_mode = 'cont' if int(config_dict['trigger_type'])==2: data_mode = 'trig-ext' cfg_list.append('\tdata_mode : ' + data_mode + ',\n') if data_mode == 'trig-ext': trigger_channel = '/Dev1/pfi0' if 'trigger_channel' in config_dict: trigger_channel = config_dict['trigger_channel'] cfg_list.append('\ttrig_channel : ' + trigger_channel + ',\n') # close section cfg_list.append('}\n') # detector config if self._det_config: for adc_key in self._det_config: device_key = adc_key if adc_key[0:3] == 'adc': device_key = 'detconfig' + str(adc_key[3:]) cfg_list.append('\n'+device_key + ' {\n') config_dict = self._det_config[adc_key] for key,val_list in config_dict.items(): if not isinstance(val_list, list): val_list = [val_list] val_str = ' '.join(map(str,val_list)) cfg_list.append('\t' + key + ' : ' + val_str + ',\n') cfg_list.append('}\n') # write file print('INFO: Writing new polaris configuration file "' + self._config_file_name + '"!') cfg_str = ''.join(cfg_list) cfg_file= open(self._config_file_name,'w+') cfg_file.write(cfg_str) cfg_file.close() return True
def launch(self): if self.outputs is not None: self.write_task = nidaqmx.Task() if self.Nchannel_analog_in > 0: self.read_analog_task = nidaqmx.Task() if self.Nchannel_digital_in > 0: self.read_digital_task = nidaqmx.Task() self.sample_clk_task = nidaqmx.Task() # Use a counter output pulse train task as the sample clock source # for both the AI and AO tasks. self.sample_clk_task.co_channels.add_co_pulse_chan_freq( '{0}/ctr0'.format(self.device.name), freq=self.sampling_rate) self.sample_clk_task.timing.cfg_implicit_timing( samps_per_chan=int(self.max_time / self.dt)) self.samp_clk_terminal = '/{0}/Ctr0InternalOutput'.format( self.device.name) ### ---- OUTPUTS ---- ## if self.outputs is not None: self.write_task.ao_channels.add_ao_voltage_chan( flatten_channel_string(self.output_channels), max_val=10, min_val=-10) self.write_task.timing.cfg_samp_clk_timing( self.sampling_rate, source=self.samp_clk_terminal, active_edge=Edge.FALLING, samps_per_chan=int(self.max_time / self.dt)) ### ---- INPUTS ---- ## if self.Nchannel_analog_in > 0: self.read_analog_task.ai_channels.add_ai_voltage_chan( flatten_channel_string(self.analog_input_channels), max_val=10, min_val=-10) if self.Nchannel_digital_in > 0: self.read_digital_task.di_channels.add_di_chan( flatten_channel_string(self.digital_input_channels)) if self.Nchannel_analog_in > 0: self.read_analog_task.timing.cfg_samp_clk_timing( self.sampling_rate, source=self.samp_clk_terminal, active_edge=Edge.FALLING, samps_per_chan=int(self.max_time / self.dt)) if self.Nchannel_digital_in > 0: self.read_digital_task.timing.cfg_samp_clk_timing( self.sampling_rate, source=self.samp_clk_terminal, active_edge=Edge.FALLING, samps_per_chan=int(self.max_time / self.dt)) if self.Nchannel_analog_in > 0: self.analog_reader = AnalogMultiChannelReader( self.read_analog_task.in_stream) self.read_analog_task.register_every_n_samples_acquired_into_buffer_event( self.buffer_size, self.reading_task_callback) if self.Nchannel_digital_in > 0: self.digital_reader = DigitalMultiChannelReader( self.read_digital_task.in_stream) self.read_digital_task.register_every_n_samples_acquired_into_buffer_event( self.buffer_size, self.reading_task_callback) if self.outputs is not None: self.writer = AnalogMultiChannelWriter(self.write_task.out_stream) self.writer.write_many_sample(self.outputs) # Start the read task before starting the sample clock source task. if self.Nchannel_analog_in > 0: self.read_analog_task.start() if self.Nchannel_digital_in > 0: self.read_digital_task.start() if self.outputs is not None: self.write_task.start() self.sample_clk_task.start() if self.filename is not None: np.save(self.filename.replace('.npy', '.start.npy'), np.ones(1) * time.time()) # saving the time stamp of the start ! self.running, self.data_saved = True, False