|
3 | 3 | import threading |
4 | 4 | import warnings |
5 | 5 | from enum import Enum |
6 | | -from typing import List, Tuple, Union |
7 | 6 |
|
8 | 7 | import numpy |
| 8 | +from nitypes.waveform import AnalogWaveform |
9 | 9 | from nidaqmx import utils |
| 10 | +from nidaqmx._feature_toggles import WAVEFORM_SUPPORT, requires_feature |
10 | 11 | from nidaqmx.task.channels._channel import Channel |
11 | 12 | from nidaqmx.task._export_signals import ExportSignals |
12 | 13 | from nidaqmx.task._in_stream import InStream |
@@ -516,6 +517,7 @@ def read(self, number_of_samples_per_channel=NUM_SAMPLES_UNSET, |
516 | 517 |
|
517 | 518 | This read method is dynamic, and is capable of inferring an appropriate |
518 | 519 | return type based on these factors: |
| 520 | +
|
519 | 521 | - The channel type of the task. |
520 | 522 | - The number of channels to read. |
521 | 523 | - The number of samples per channel. |
@@ -768,6 +770,117 @@ def _read_power( |
768 | 770 | for v, i in zip(voltages, currents) |
769 | 771 | ][:samples_read] |
770 | 772 |
|
| 773 | + @requires_feature(WAVEFORM_SUPPORT) |
| 774 | + def read_waveform(self, number_of_samples_per_channel=READ_ALL_AVAILABLE, |
| 775 | + timeout=10.0): |
| 776 | + """ |
| 777 | + Reads samples from the task or virtual channels you specify, and returns them as waveforms. |
| 778 | +
|
| 779 | + This read method is dynamic, and is capable of inferring an appropriate |
| 780 | + return type based on these factors: |
| 781 | +
|
| 782 | + - The channel type of the task. |
| 783 | + - The number of channels to read. |
| 784 | + - The number of samples per channel. |
| 785 | +
|
| 786 | + The data type of the samples returned is independently determined by |
| 787 | + the channel type of the task. |
| 788 | +
|
| 789 | + If you do not set the number of samples per channel, this method |
| 790 | + reads all available data for each channel. |
| 791 | +
|
| 792 | + Args: |
| 793 | + number_of_samples_per_channel (Optional[int]): Specifies the |
| 794 | + number of samples to read. If this input is not set, |
| 795 | + it defaults to nidaqmx.constants.READ_ALL_AVAILABLE. |
| 796 | +
|
| 797 | + If this input is nidaqmx.constants.READ_ALL_AVAILABLE, |
| 798 | + NI-DAQmx determines how many samples |
| 799 | + to read based on if the task acquires samples |
| 800 | + continuously or acquires a finite number of samples. |
| 801 | +
|
| 802 | + If the task acquires samples continuously and you set |
| 803 | + this input to nidaqmx.constants.READ_ALL_AVAILABLE, this |
| 804 | + method reads all the samples currently available in the |
| 805 | + buffer. |
| 806 | +
|
| 807 | + If the task acquires a finite number of samples and you |
| 808 | + set this input to nidaqmx.constants.READ_ALL_AVAILABLE, |
| 809 | + the method waits for the task to acquire all requested |
| 810 | + samples, then reads those samples. If you set the |
| 811 | + "read_all_avail_samp" property to True, the method reads |
| 812 | + the samples currently available in the buffer and does |
| 813 | + not wait for the task to acquire all requested samples. |
| 814 | + timeout (Optional[float]): Specifies the amount of time in |
| 815 | + seconds to wait for samples to become available. If the |
| 816 | + time elapses, the method returns an error and any |
| 817 | + samples read before the timeout elapsed. The default |
| 818 | + timeout is 10 seconds. If you set timeout to |
| 819 | + nidaqmx.constants.WAIT_INFINITELY, the method waits |
| 820 | + indefinitely. If you set timeout to 0, the method tries |
| 821 | + once to read the requested samples and returns an error |
| 822 | + if it is unable to. |
| 823 | + Returns: |
| 824 | + dynamic: |
| 825 | +
|
| 826 | + The samples requested in the form of a waveform (for a single channel) |
| 827 | + or a list of waveforms (for multiple channels). |
| 828 | + See method docstring for more info. |
| 829 | +
|
| 830 | + NI-DAQmx scales the data to the units of the measurement, |
| 831 | + including any custom scaling you apply to the channels. Use a |
| 832 | + DAQmx Create Channel method to specify these units. |
| 833 | +
|
| 834 | + Example: |
| 835 | + >>> task = Task() |
| 836 | + >>> task.ai_channels.add_ai_voltage_chan('Dev1/ai0') |
| 837 | + >>> data = task.read_waveform() |
| 838 | + >>> type(data) |
| 839 | + <type 'AnalogWaveform'> |
| 840 | + """ |
| 841 | + channels_to_read = self.in_stream.channels_to_read |
| 842 | + number_of_channels = len(channels_to_read.channel_names) |
| 843 | + read_chan_type = channels_to_read.chan_type |
| 844 | + |
| 845 | + number_of_samples_per_channel = self._calculate_num_samps_per_chan( |
| 846 | + number_of_samples_per_channel) |
| 847 | + |
| 848 | + if read_chan_type == ChannelType.ANALOG_INPUT: |
| 849 | + if number_of_channels == 1: |
| 850 | + waveform = AnalogWaveform(number_of_samples_per_channel) |
| 851 | + self._interpreter.read_analog_waveform( |
| 852 | + self._handle, |
| 853 | + number_of_samples_per_channel, |
| 854 | + timeout, |
| 855 | + waveform, |
| 856 | + self._in_stream.waveform_attribute_mode, |
| 857 | + ) |
| 858 | + return waveform |
| 859 | + else: |
| 860 | + waveforms = [ |
| 861 | + AnalogWaveform(number_of_samples_per_channel) |
| 862 | + for _ in range(number_of_channels) |
| 863 | + ] |
| 864 | + self._interpreter.read_analog_waveforms( |
| 865 | + self._handle, |
| 866 | + number_of_samples_per_channel, |
| 867 | + timeout, |
| 868 | + waveforms, |
| 869 | + self._in_stream.waveform_attribute_mode, |
| 870 | + ) |
| 871 | + return waveforms |
| 872 | + |
| 873 | + elif (read_chan_type == ChannelType.DIGITAL_INPUT or |
| 874 | + read_chan_type == ChannelType.DIGITAL_OUTPUT): |
| 875 | + raise NotImplementedError("Digital input/output reading is not implemented yet.") |
| 876 | + |
| 877 | + else: |
| 878 | + raise DaqError( |
| 879 | + 'Read failed, because there are no channels in this task from ' |
| 880 | + 'which data can be read.', |
| 881 | + DAQmxErrors.READ_NO_INPUT_CHANS_IN_TASK, |
| 882 | + task_name=self.name) |
| 883 | + |
771 | 884 | def register_done_event(self, callback_method): |
772 | 885 | """ |
773 | 886 | Registers a callback function to receive an event when a task stops due |
|
0 commit comments