1

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?

Tasos Papastylianou
  • 21,371
  • 2
  • 28
  • 57
theEarlyRiser
  • 134
  • 12
  • just at a glance, is it possible that PsychImagine returns a handle to a figure object? What exactly do you expect window and windowRect to be? – Tasos Papastylianou Jul 20 '20 at 14:11
  • Just a hunch, mex files probably rely on autodetection of number of output arguments, which may fail when called through oct2py. Try running this via an eval statement, where you specify your two output arguments with appropriate octave syntax, i.e. `octave.eval("[window, windowrect] = PsychImaging('OpenWindow', screenNumber, gray);")`. These will then be accessible in your octave workspace if you need them further (but it doesn't sound like you do). (PS: are you sure gray is correct and shouldn't be a string or something?). – Tasos Papastylianou Jul 20 '20 at 16:21
  • So @TasosPapastylianou, in Octave these variables receive two different values being one double 1x1 and another double 1x4 respectively: ```window = 10``` and ```windowRect = [0,0,1366,768]``` that are also, parameters that are put in Screen method (to display image, to change, and so on...) but in Python, I was waiting that it should return float values – theEarlyRiser Jul 20 '20 at 19:51
  • @TasosPapastylianou it finally worked!!! Now I am reading the documentation in order how to recover values from the Octave variables to use in the same Python code – theEarlyRiser Jul 20 '20 at 20:33
  • That is also easy. See here: https://stackoverflow.com/a/38543580/4183191 – Tasos Papastylianou Jul 21 '20 at 04:57
  • When you say it worked, you mean the "eval" approach? If so, I'd like to answer this properly below so you can accept it. It's an interesting issue, I'm sure more people will run into it in the future too. – Tasos Papastylianou Jul 21 '20 at 04:59
  • btw, there's also oct2py.octave.push, and oct2py.octave.pull, for putting/retrieving values from the octave workspace – Tasos Papastylianou Jul 21 '20 at 05:06

1 Answers1

2

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.

Tasos Papastylianou
  • 21,371
  • 2
  • 28
  • 57