Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Supported by

[solved] intentional binding paradigm / creating animations

edited November 2011 in OpenSesame

Hi. I have to create a paradigm in which there is a clock with a single hand that complete a revolution each 2560 ms. The hand rotation should be fluid and continuous and should start at a random position each time. The partecipant presses a key during the hand rotation and the software should detect and record the actual value in milliseconds of the point of the clock in which there's been the key press.

Do you think this paradigm can be implemented in open sesame without problems?

Comments

  • edited 3:11AM

    Hi Embodiment,

    Welcome to the forum!

    Yes, that's certainly possible to implement. It will require a moderately complex inline script (where the clock is drawn), but nothing too overwhelming. All the required functionality is available in the openexp.canvas and openexp.keyboard modules:

    Hope this gets you started and don't hesitate to post any questions you might have!

    Kindest regards,
    Sebastiaan

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

  • edited 3:11AM

    Thank you very Sebastian. So I may try to design such experiment with open sesame. Another question, important for my experiment, is about the millisecond precision of open sesame. If I use a USB keyboard, what would be the milliseconds delay?

  • edited 3:11AM

    Hi Embodiment,

    I cannot really say, because that depends on the keyboard. OpenSesame reads the keyboard in pretty much the same way as all other software, so in that respect it wouldn't matter which software you use.

    Here's a nice paper on the subject. Damian argues that the delays caused by keyboards is generally not a relevant source of noise:

    Damian, M. F. (2010). Does variability in human performance outweigh imprecision in response devices such as computer keyboards? Behavior Research Methods, 42, 205-211. doi:10.3758/BRM.42.1.205

    As an aside: The accuracy of the display presentation timestamp varies per back-end, as described at the end of the tutorial. For optimal results, you may want to consider using the opengl or psycho backend, although, like with a keyboard, it is doubtful whether it will make much of a difference in practice.

    Kindest regards,
    Sebastiaan

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

  • edited 3:11AM

    Ok Sebastian. You're been very clear and exhaustive. I've never used Open Sesame before, so I will ask for help if I were to have any problem.
    Thanks again.

    Andrea

  • edited 3:11AM

    Excuse me Sebastian. I'm trying to understand how can I create the moving clock hand. You wrote that the canvas module can be useful, but I see it allow only the drawing of shapes, not also the movement. What are the Python commands to use for producing a movement of an object (in this case a line)?

  • edited December 2013

    Hi Andrea,

    You can create animations by showing static canvasses in succession. Since this is probably quite a common thing to do, I'll give a few examples. In order to fully understand these examples, you will need a basic understanding of Python. If you are not familiar with Python, you may want to walk through A Byte of Python.

    Let's start simple, by drawing a static canvas with a simple clock:

    from math import radians, atan2, sin, cos # We need some trigonometry
    from openexp.canvas import canvas
    
    # The time is actually the clockwise rotation in
    # degrees from the 3 o'clock position.
    time = 30
    arm_len = 60 
    
    # The center coordinates
    xc = my_canvas.xcenter()
    yc = my_canvas.ycenter()
    
    # The end points of the arm, relative to the center
    dx = arm_len * cos(radians(time))
    dy = arm_len * sin(radians(time))
    
    # Draw!
    my_canvas = canvas(self.experiment) # Create a canvas
    my_canvas.fixdot() # A central fixation dot
    my_canvas.line(xc, yc, xc+dx, yc+dy) # Clock arm
    my_canvas.show() # And show
    

    Now, let's extend this to an animation of a rotating clock arm:

    from math import radians, atan2, sin, cos # We need some trigonometry
    from openexp.canvas import canvas
    
    arm_len = 60 # length of the arm
    n_rev = 2 # nr. of revolutions
    step_size = 2 # displacement per frame
    delay = 20 # Delay in milliseconds
    
    my_canvas = canvas(self.experiment) # Create a canvas
    xc = my_canvas.xcenter()
    yc = my_canvas.ycenter()
    
    for time in range(0, n_rev*360, step_size):
    
        # The end points of the arm, relative to the center
        dx = arm_len * cos(radians(time))
        dy = arm_len * sin(radians(time))
    
        # Draw!
        my_canvas.clear()
        my_canvas.fixdot() # A central fixation dot
        my_canvas.line(xc, yc, xc+dx, yc+dy) # Clock arm
        my_canvas.show() # And show
    
        # And wait for a bit
        self.sleep(delay)
    

    This works, but there's a drawback: The canvasses are created on the fly. If you have a slow computer or complex canvasses, this may cause timing problems. So we extend this example to prepare all canvasses, before showing them:

    from math import radians, sin, cos
    from openexp.canvas import canvas
    
    arm_len = 60 # length of the arm
    n_rev = 2 # nr. of revolutions
    step_size = 2 # displacement per frame
    delay = 20 # Delay in milliseconds
    
    # Create a list of canvasses, but don't show them yet
    my_canvas_list = []
    for time in range(0, 360):
        # Create a canvas
        my_canvas = canvas(self.experiment)
        xc = my_canvas.xcenter()
        yc = my_canvas.ycenter()    
        dx = arm_len * cos(radians(time))
        dy = arm_len * sin(radians(time))
        my_canvas.clear()
        my_canvas.fixdot()
        my_canvas.line(xc, yc, xc+dx, yc+dy)    
        # Add the canvas to the list
        my_canvas_list.append(my_canvas)
    
    # Walk through all the canvasses and show them
    for i in range(n_rev):
        for my_canvas in my_canvas_list:    
            my_canvas.show()
            self.sleep(delay)
    

    Pretty easy, right? Now all we have to do is poll the keyboard intermittently, to record when a key has been pressed:

    from math import radians, sin, cos
    from openexp.canvas import canvas
    from openexp.keyboard import keyboard
    
    arm_len = 60 # length of the arm
    n_rev = 2 # nr. of revolutions
    step_size = 2 # displacement per frame
    delay = 20 # Delay in milliseconds
    
    # Prepare a keyboard. Set a timeout, so the keyboard
    # doesn't block the animation.
    my_keyboard = keyboard(self.experiment, timeout=delay)
    
    # Create a list of canvasses, but don't show them yet
    my_canvas_list = []
    for time in range(0, 360):
        # Create a canvas
        my_canvas = canvas(self.experiment)
        xc = my_canvas.xcenter()
        yc = my_canvas.ycenter()    
        dx = arm_len * cos(radians(time))
        dy = arm_len * sin(radians(time))
        my_canvas.clear()
        my_canvas.fixdot()
        my_canvas.line(xc, yc, xc+dx, yc+dy)    
        # Add the canvas to the list
        my_canvas_list.append(my_canvas)
    
    # Walk through all the canvasses until a key has been pressed
    resp = None
    start_time = self.time()
    while resp == None:
        for my_canvas in my_canvas_list:    
            my_canvas.show()
            resp, end_time = my_keyboard.get_key()
            if resp != None:
                break
    
    # Save the responses
    self.experiment.set("response", my_keyboard.to_chr(resp))
    self.experiment.set("response_time", end_time - start_time)
    

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

  • edited 3:11AM

    Perfect! I would like to thank you for your patience and clarity in explanation. Now I can start to programming the clock, after reading some Python documents.

    Cheers,

    Andrea

  • edited 3:11AM

    I've tested this codes. There is a problem that I don't be sure if derives from my machine or something else.

    I've to set the revolution time to 2560 ms. To do this, one have to set the correct value of "delay". In my case, 2560/360 = 7.1: I've inserted 7, since the program accepts only integers. So:

    delay = 7

    Whit this value, the total time should be 2520, but it's not the case. The revolution is long more than 3 seconds. I've thought that one possible reason of that maybe concerns a poor precision of my computer with low milliseconds. So I've tried to increment the delay by reducing the number of canvas produced, from 360 to 180. To do this, I've added a step in the loop:

    for time in range(0, 360, 2):

    but nothing. The hand is still too slow.

    Do you have any idea about that?

  • edited 3:11AM

    Hi Andrea,

    One thing that is important to take into account is the restrictions imposed by the refresh rate of the monitor. Let's say the monitor is running at 100Hz, this means that a canvas can be shown at most every 10ms. If you try to show it more often (i.e, using a delay of 5ms), it will "round up" the delay and the animation will be slower than you intended. Another factor is that the real delay is always the delay you specify + some additional computational time (but very little if you prepare the canvases in advance).

    So you may want to match the delay to the refresh rate of your monitor and then deduct something like 2ms (so there's some additional room for processing, and any left-over delay will be rounded up anyway). So, for example, if the monitor is 60Hz -> 16.67ms per refresh -> 14ms delay.

    Does this make sense? Good luck!

    Regards,
    Sebastiaan

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

  • edited 3:11AM

    Ok, I'll try.

    Thanks,

    Andrea

  • edited 3:11AM

    Hi Sebastian. I'm continuing to test the code you provided me. To creating the compete clock, I thought that I can put the canvas rotation above a jpeg image of the clock face. So the canvasses appear above a background image. I've read the Python documentation but I didn't find the method to do this.

    Another method to design the clock face, I think, is certainly to create a circle, the numbers and the minute markers by Python, but also in this case I don't know how one can make these images static despite of the other canvasses movement. In my trials, if I draw a line it appears either before the hand rotation or intermittently inside the flow of the other canvasses.

    Do you have suggestions?

    Thanks, best regards,

    Andrea

  • edited 3:11AM
    To creating the compete clock, I thought that I can put the canvas rotation above a jpeg image of the clock face. So the canvasses appear above a background image. I've read the Python documentation but I didn't find the method to do this.

    Yes, that's possible. The easiest way to do this is to put your image in the file pool and use the following code to draw it:

    path = self.experiment.get_file("my_picture.png")
    my_canvas.image(path)

    For more option, see http://osdoc.cogsci.nl/python-inline-code/canvas-functions#canvas.image

    Hope this helps!

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

  • edited 3:11AM

    Yes, I've already tried with canvas.image command, but the problem is that I can't show at the same time both the background image (clock face) and the various canvasses of the hand. When I insert the command you wrote, the clock image appears always in a separate frame, before the beginning of the hand rotation.

  • edited 3:11AM

    Ah ok, yes, that's probably because you clear the canvas after every frame (otherwise you'd get lots of arms in your clock). So you need to redraw the image after every clear(), and before show(), and you should be good!

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

  • edited 3:11AM

    In fact, now it works! Thank you so much.
    Sadly, the paradigm I've to create is not so easy to implement, because there are various aspects to keep under control, as the duration of rotation, the hand movements smoothness, the timings etc. I hope OpenSesame can allows me to obtain a good result.

  • edited October 2011

    A curiosity: can OpenSesame read flash swf formats?

  • edited 3:11AM

    I'm not too familiar with flash, but swf format is the actual Flash program, right? No, OpenSesame cannot read that. The media player plug-in may be able to play Flash video content (.flv), but you'd have to try. In any case, you could convert a .flv video to .avi or another common format and play it that way for sure.

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

  • edited 3:11AM

    I had already tried to play an avi movie in Open Sesame. I noticed that the player reproduce the movie too fast.

    About swf clips, I think that Open Sesame can be able to reproduce such file format if one import a Python module that allow that. Are you agree? I ask this because I'm testing your code for generating clock hand rotation, but unfortunately there isn't a way to make rotation always of the same duration. Every time the revolution time changes. Since I've developed a flash file with the clock rotation, I would to insert it in Open Sesame. Now I check if Python can help me...

  • edited 3:11AM

    You might be able to play .swf files, if there is a Python module for that (you'd have to Google), but that might not be the best way to go. If the timing of the rotation is not constant, you could use the actual timestamp, rather than the number of steps, to determine the arm position. This way the number of frames might vary, but the overall timing will stay the same. Does this make sense? This would be only a minor modification of the script posted above:

    from math import radians, atan2, sin, cos # We need some trigonometry
    from openexp.canvas import canvas
    
    arm_len = 60 # length of the arm
    n_rev = 2 # nr. of revolutions
    speed = .1 # Speed of the arm
    duration = 2000 # Duration in milliseconds
    
    my_canvas = canvas(self.experiment) # Create a canvas
    xc = my_canvas.xcenter()
    yc = my_canvas.ycenter()
    
    start_t = self.time()
    t = 0
    while t < duration:
        t = self.time() - start_t   
        # The end points of the arm, relative to the center
        dx = arm_len * cos(radians(t*speed))
        dy = arm_len * sin(radians(t*speed))    
        # Draw!
        my_canvas.clear()
        my_canvas.fixdot() # A central fixation dot
        my_canvas.line(xc, yc, xc+dx, yc+dy) # Clock arm
        my_canvas.show() # And show 
    

    As an aside, the task you're developing obviously requires some knowledge of Python. Perhaps you could take a look at A Byte of Python. It's a simple, but complete tutorial, and it might clear many things up for you.

    (Btw, if you experience problems with the media_player plug-in, please open another topic and I'll refer to Daniel, who maintains that part of OpenSesame.)

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

  • edited 3:11AM

    In fact, now it works like a charm! I've noticed that, for a greater timing precision, it is better to manually draw the clock face, rather than add a specific jpeg image in the canvas, like I was doing.

    Thanks Sebastian, you have been very helpful!

  • edited 3:11AM

    Alright, great! I'll mark it as solved. But please don't hesitate to re-open or start another discussion if you run into more issues.

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

Sign In or Register to comment.