wavefrontshaping / ALP4lib

Python control module for Vialux DMDs based on ALP4.X API.
MIT License
58 stars 41 forks source link

DMD.SeqPut error #14

Closed zcshinee closed 3 years ago

zcshinee commented 3 years ago

I am using the example code you provided to test the DMD (Vialux V-9001 with ALP 4.3). However, I ran into an error with the DMD.SeqPut function shown below. I am using python version of 3.6.5. Could you kindly let me know how to troubleshoot this? Thank you.

Loading library: C:\Program Files\ALP-4.3/ALP-4.3 API/x64/alp4395.dll
DMD found, resolution = 2560 x 1600.
Traceback (most recent call last):
  File "c:/Users/cheng/ALP4lib/demo.py", line 21, in <module>
    DMD.SeqPut(imgData=imgSeq)
  File "c:\users\cheng\alp4lib\src\ALP4.py", line 651, in SeqPut
    'Cannot send image sequence to device.')
  File "c:\users\cheng\alp4lib\src\ALP4.py", line 431, in _checkError
    raise ALPError(returnValue)
ALP4.ALPError: Error accessing user data.
wavefrontshaping commented 3 years ago

Hi,

ALP4lib is a wrapping of the functions of the ALP API, it uses the C dll provided by the manufacturer. This error is an ALP one, meaning that is not directly related to the Python code (while it may originate from it), and is documented in the ALP API documentation. I do not have the ALP documentation right here, what does it say about this error?

Sebastien

zcshinee commented 3 years ago

Hi

The error is 1006 error in the ALP. It is also called 'ALP_ADDR_INVALID'.

ALP_ADDR_INVALID
Functions that access user data through a pointer parameter (e.g. long *UserVarPtr) return
ALP_ADDR_INVALID when memory access fails. The most probable cause is that this
pointer contains an invalid memory address

Should I change something to correct the address?

Thank you Cheng

zcshinee commented 3 years ago

An update on this thread.

Previous i use the Dell workstation (windows) to run the code and get the bug. However, if I use my windows laptop to run the code, it can succeed without bug.

best cheng

wavefrontshaping commented 3 years ago

I am glad it works for you in the end, but I am a bit puzzled by this error.

SeqAlloc() is supposed to allocate the memory and to return the id (memory address) of the sequence. By default, because in most applications you only have one sequence at a time, it is not required to store this id outside the DMD object at SeqPut will automatically use the id from the previous call of SeqAlloc (the id is stored internally in DMD._lastDDRseq). You can, however, specify the sequence id manually if need be.

If you have this problem again, I would be curious to know the result of this:

seq_id = DMD.SeqAlloc(...)
print(seq_id)
DMD.SeqPut(imgData = imgSeq, SequenceId=seq_id)
zcshinee commented 3 years ago

I do test the script you gave, the result is as follows:

Loading library: C:\Program Files\ALP-4.3/ALP-4.3 API/x64/alp4395.dll
self._ALPLib <CDLL 'C:\Program Files\ALP-4.3/ALP-4.3 API/x64/alp4395.dll', handle 7ff988840000 at 0x24d9ecab6d8>
DMD found, resolution = 2560 x 1600.
seq_id c_long(1)
Traceback (most recent call last):
  File "c:/Users/cheng/ALP4lib/demo.py", line 28, in <module>
    DMD.SeqPut(imgData=imgSeq, SequenceId=seq_id)
  File "c:\users\cheng\alp4lib\src\ALP4.py", line 657, in SeqPut
    'Cannot send image sequence to device.')
  File "c:\users\cheng\alp4lib\src\ALP4.py", line 432, in _checkError
    raise ALPError(returnValue)
ALP4.ALPError: Error accessing user data.

Seems the 'c_long(1)' memory does not work here.

wavefrontshaping commented 3 years ago

Indeed, it seems like it failed to allocate the memory in the first place. My best guess is that the .dll fails for your computer config for some reason (drivers issue?). I do not have access to the ALP code source. As it is most likely an ALP API error, if you want to find a solution, I am afraid I cannot help you much and you would have to ask Vialux. (And because they would most likely not trust that it is not a bug in the Python module, they would probably ask you to confirm the bug by writing a C example that reproduces the error).

guilhermebene commented 3 years ago

I have a similar issue when I allocate the memory and then send the images one by one to the DMD using the following code:

seqId = DMD.SeqAlloc(nbImg=acquisition_params.pattern_amount, 
                             bitDepth=bitplanes)

for index,pattern_name in enumerate(pattern_order):
    image = Image.open(metadata.pattern_source+str(pattern_name)+'.png')
    patterns = np.array(image,dtype=np.uint8).ravel()
    # Converting image to nparray and transforming it to a 1D vector (ravel)
    DMD.SeqPut(imgData=patterns, SequenceId=seqId) 

The error is the following:

Traceback (most recent call last):
  File "c:/Programs/Python/acquisition.py", line 937, in <module>
    spectrometer_params, DMD_params, wavelenghts = setup(
  File "c:\Programs\Python\acquisition.py", line 628, in setup
    _setup_patterns2(DMD, metadata, DMD_params, acquisition_params)
  File "c:\Programs\Python\acquisition.py", line 475, in _setup_patterns2
    DMD.SeqPut(imgData=patterns, SequenceId=seqId)
  File "C:\Users\user1\Anaconda3\envs\singlepixelenv\lib\site-packages\ALP4.py", line 599, in SeqPut
    self._checkError(
  File "C:\Users\user1\Anaconda3\envs\singlepixelenv\lib\site-packages\ALP4.py", line 391, in _checkError
    raise ALPError(returnValue)
ALP4.ALPError: Error accessing user data.

However, everything works fine when I do things in the following order: put all the images in a single array, allocate the memory in the DMD and then send the entire array. The following piece of code exemplifies this:

patterns = np.empty((dmd_pixels*acquisition_params.pattern_amount),dtype=np.uint8)

for index,pattern_name in enumerate(pattern_order):
    image = Image.open(metadata.pattern_source+str(pattern_name)+'.png')

    #Converting image to nparray and transforming it to a 1D vector (ravel)
    patterns[dmd_pixels*index:dmd_pixels*(index+1)] = np.array(image,dtype=np.uint8).ravel()

seqId = DMD.SeqAlloc(nbImg=len(pattern_order), bitDepth=bitplanes)
DMD.SeqPut(imgData = patterns)

Based on my understanding of the ALP API I should be able to send the images one by one.

wavefrontshaping commented 3 years ago

That error is more understandable, when you use SeqPut without setting the PicLoad argument, it assumes you upload the entire sequence, not one image at a time. So the .dll noticed that the data you send does not have the same size as the allocated sequence.

Your first example should look like something like:

seqId = DMD.SeqAlloc(nbImg=acquisition_params.pattern_amount, 
                             bitDepth=bitplanes)

for index,pattern_name in enumerate(pattern_order):
    image = Image.open(metadata.pattern_source+str(pattern_name)+'.png')
    patterns = np.array(image,dtype=np.uint8).ravel()
    # Converting image to nparray and transforming it to a 1D vector (ravel)
    DMD.SeqPut(imgData=patterns.copy(), SequenceId=seqId, PicOffset=index, PicLoad=1) 

Check the help of the SeqPut function.

guilhermebene commented 3 years ago

Thank you for your answer. It does work now.