Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stream_readers array shape validation is incompatible with READ_ALL_AVAILABLE #421

Open
bkeryan opened this issue Jun 22, 2023 · 2 comments

Comments

@bkeryan
Copy link
Collaborator

bkeryan commented Jun 22, 2023

If you use stream_readers to read into a preallocated NumPy array with number_of_samples_per_channel=READ_ALL_AVAILABLE, the stream reader validates the NumPy array shape against the available samples per channel, which is not a predictable number.

Steps to reproduce

Install an X Series or M Series as Dev1 and run this code:

import pprint
import time

import nidaqmx
import numpy
from nidaqmx.constants import AcquisitionType
from nidaqmx.stream_readers import AnalogMultiChannelReader

pp = pprint.PrettyPrinter(indent=4)

with nidaqmx.Task() as task:
    task.ai_channels.add_ai_voltage_chan("Dev1/ai0:1")
    task.timing.cfg_samp_clk_timing(1000.0, sample_mode=AcquisitionType.CONTINUOUS)
    task.start()
    time.sleep(100e-3)

    reader = AnalogMultiChannelReader(task.in_stream)
    data = numpy.zeros((2, 1000), dtype=numpy.double)
    reader.read_many_sample(data, timeout=0.0)

    pp.pprint(data)

Expected output

Prints array data

Actual output

The required number of samples varies from run to run but is around 100 to 110.

Traceback (most recent call last):
  File "D:\dev\nidaqmx-python\examples\ai_raw.py", line 19, in <module>
    reader.read_many_sample(data, timeout=0.0)
  File "D:\dev\nidaqmx-python\generated\nidaqmx\stream_readers.py", line 322, in read_many_sample
    self._verify_array(data, number_of_samples_per_channel, True, True)
  File "D:\dev\nidaqmx-python\generated\nidaqmx\stream_readers.py", line 83, in _verify_array
    raise DaqError(
nidaqmx.errors.DaqError: Read cannot be performed because the NumPy array passed into this function is not shaped correctly. You must pass in a NumPy array of the correct shape based on the number of channels in task and the number of samples per channel requested.

Shape of NumPy Array provided: (2, 1000)
Shape of NumPy Array required: (2, 105)

Task Name: _unnamedTask<0>
@zhindes
Copy link
Collaborator

zhindes commented Jun 23, 2023

Hmm, good catch. We could allow for a NumPy array that is bigger than necessary since read_many_sample returns how much data is valid.

@bkeryan
Copy link
Collaborator Author

bkeryan commented Jun 23, 2023

With GROUP_BY_CHANNEL, a larger array will not have the right binary layout.

  • With 3 channels and 3 samples, the array has this layout: [1,1,1,2,2,2,3,3,3]
  • With 3 channels and 5 samples, the array has this layout: [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3]
  • Writing 3 samples to a (3, 5) array requires leaving gaps between channels: [1,1,1,0,0,2,2,2,0,0,3,3,3,0,0]

I think this would work better if nidaqmx-python supported F_CONTIGUOUS and GROUP_BY_SCAN_NUMBER as described in #90

Then you would have:

  • With 3 channels and 3 samples, the array has this layout: [1,2,3,1,2,3,1,2,3]
  • With 3 channels and 5 samples, the array has this layout: [1,2,3,1,2,3,1,2,3,1,2,3,1,2,3]
  • Writing 3 samples to a (3, 5) array still uses a contiguous array: [1,2,3,1,2,3,1,2,3,0,0,0,0,0,0]

This would also behave better for partial data after read raises a timeout error. You wouldn't have to resize the array to put each channel in the right place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants