Search code examples
pythonoctavepsychtoolboxoct2py

Oct2Py gives "TypeError: cannot unpack non-iterable float object" with Psychtoolbox function returning multiple arguments


I am running a very basic Psychtoolbox example from their site using Oct2py package and I am facing an issue that is happening when I am trying to return two float values for that it looks like:

from oct2py import octave
import sys

def ptb():
    # Clear the workspace and the screen
    octave.sca;
    octave.close;

    octave.PsychDebugWindowConfiguration; 

    # Here we call some default settings for setting up Psychtoolbox
    octave.PsychDefaultSetup(2);

    # Get the screen numbers. This gives us a number for each of the screens
    # attached to our computer.
    screens = octave.Screen('Screens');

    # To draw we select the maximum of these numbers. So in a situation where we
    # have two screens attached to our monitor we will draw to the external
    # screen.
    screenNumber = octave.max(screens);

    # Define black and white (white will be 1 and black 0). This is because
    # in general luminace values are defined between 0 and 1 with 255 steps in
    # between. All values in Psychtoolbox are defined between 0 and 1
    white = octave.WhiteIndex(screenNumber);
    black = octave.BlackIndex(screenNumber);

    # Do a simply calculation to calculate the luminance value for grey. This
    # will be half the luminace values for white
    grey = white / 2;

    # Open an on screen window using PsychImaging and color it grey.
    window, windowRect = octave.PsychImaging('OpenWindow', screenNumber, grey);

    # Now we have drawn to the screen we wait for a keyboard button press (any
    # key) to terminate the demo.
    octave.KbStrokeWait;

    # Clear the screen.
    octave.sca;
    
    sys.exit()
    
if __name__ == "__main__":
    ptb()

The error occurs at line 49:

TypeError                                 Traceback (most recent call last)
<ipython-input-1-6e0dcd049170> in <module>
     47 
     48 if __name__ == "__main__":
---> 49     ptb()

<ipython-input-1-6e0dcd049170> in ptb()
     37 
     38     #Open an on screen window using PsychImaging and color it grey.
---> 39     window, windowRect = octave.PsychImaging('OpenWindow', screenNumber, grey);
     40 
     41     #Now we have drawn to the screen we wait for a keyboard button press (any

TypeError: cannot unpack non-iterable float object

I was looking for a help to this error around the net, but I saw very few explanations and none helped me out. When I perform it in Octave it worked well but in Python I am facing this issue, I have tried to put brackets between window and windowRect and it didn't work also. How could I proceed on it?


Solution

  • Converting comments to an answer.

    The problem here is that when oct2py runs that line, it acts as if the function was called with a single argument. Oct2py cannot infer the number of arguments from the number of outputs of the python call. (apparently this used to be the case with older oct2py versions, but not anymore: see this answer).

    As the linked answer suggests, the way to do this is by passing an extra nout=2 parameter to the function. I.e. your call (assuming all other arguments are correct?) should be:

    window, windowRect = octave.PsychImaging('OpenWindow', screenNumber, grey, nout=2);
    

    Alternatively, you can run your function with "eval" in a more natural octave syntax, i.e.

    octave.eval("[window, windowRect] = PsychImaging('OpenWindow', screenNumber, grey);")
    

    I note that you don't really need to use the resulting output variables in this case, but if you did, you can retrieve them into your python session using oct2py's pull function.