Howdy, Stranger!

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

Supported by

[solved] Selecting trials within a trial

edited March 2016 in OpenSesame

Hi everyone,

I received great support from this forum the last time and I had a few additional questions about OpenSesame functions.

In my experiment, I'm trying to create one long experimental trial that goes on for 8 minutes. More specifically, I'm trying to create a moving fixation dot that moves from back and forth continuously for 8 mins. Each individual pass from left to right should last for 1 second (therefore, 480 passes in all in one trial)

I managed to program the sinusoidal fixation dot in such a way that it travels for 8 minutes (exp.time() - start_time) > 480000). My questions are:
1. How do I ensure that each pass lasts for 1 second exactly?
2. If I want to present a line stimulus on any one randomly chosen pass (while the fixation dot is still moving back and forth), what would be the best way to do that in my inline script? I did ask for some help and this is what I have so far:

from openexp.keyboard import keyboard
from math import sin
import numpy as np

# Create keyboard reference
kb = keyboard(exp)

cnvs = self.offline_canvas()

# Left and right x coordinate of screen
screen_min_x = 0
screen_max_x = cnvs.xcenter()*2

# Wave properties in pixels
amplitude = 400

wavelength = 50.0 

# x to start with
x = cnvs.xcenter()

# horizontal translation in pixels per frame
dx = 3  

while True:
    # Check for keypress and stop if detected
    key, time = kb.get_key(timeout=0)
    if (exp.time() - start_time)  > 480000:
        break
    y = cnvs.ycenter() 
    x = sin((exp.time() - start_time) * dx / 1000.0 ) * amplitude + cnvs.xcenter()
    print x
    cnvs.clear()
    # Draw fixation dot at current position
    cnvs.fixdot(x=x,y=y)
    # Show the canvas
    cnvs.show()

start_time = exp.time()
first_stim_present_times = np.random.randint(2, 5, size = 500).cumsum()
first_stim_present_times = first_stim_present_times[first_stim_present_times < frame_times.max()]

So, I think the last part of the above code picks out random passes (stored in first_stim_present_times ) How do I then draw my stimulus on these chosen passes?

Looking forward to your reply!

Thanks in advance!
Anupama

Comments

  • edited 5:48AM

    Hi Anupama,

    Regarding your first question, from a quick glance at your code it seems that you're already guaranteed that each pass lasts exactly a second, because the x-coordinate of the dot is based on a sinus function that uses the current time. It's pretty elegant I must say :) What more did you hope to achieve?

    Second question: before entering the while-loop, you could just pick a random number between 0 and 480, knowing that there are 480 passes in total. The chosen number will be the pass during which you display your line stimulus.
    In the while-loop, then, you'll need to keep count of the passes. So right before the while-loop you create a variable current_pass = 0, and at the end of every cycle (e.g. below cnvs.show()) you insert the line current_pass += 1.

    Now you have to add a line of code that draws a line onto your canvas, but this line should be preceded by an if-statement, e.g. if current_pass == chosen_pass:.

    I think that's all you need.

    Cheers,

    Josh

  • edited March 2016

    Hi Josh,

    Thank you so much for your reply, that was quite insightful!
    I had further queries regarding your advice that I hope you can help me with!
    1. I implemented your suggestion in my code and printed out current_pass values. I believe it increments with every increase of the sin function variable (instead of each pass) so I still don't get a count of passes. How can I change this?
    2. Secondly, if I do get my counter working, by choosing a random number between 0 and 480, I may not get a stimulus presentation till the very end of the trial whereas I want a number of stimulus presentations in each 8 min trial. Is there a way to accomplish that?
    3.Lastly, I also want my line stimulus to be presented in a way that it flashes exactly when the fixation dot passes through the center. With my current sin function, there's no way of knowing if the fixation dot would always cross the canvas x.center(). Can I change my sin function in any way to accomplish that?

    Thanks again for your help!
    Anupama


    chosen_pass = random.randint(0,480) current_pass = 0 while True: # Check for keypress and stop if detected key, time = kb.get_key(timeout=0) if (exp.time() - start_time) > 480000: break y = cnvs.ycenter() x = sin((exp.time() - start_time) * dx / 1000.0 ) * amplitude + cnvs.xcenter() cnvs.clear() # Draw fixation dot at current position cnvs.fixdot(x=x,y=y) # Show the canvas cnvs.show() current_pass += 1 print current_pass
  • edited 5:48AM

    Hi,

    1. Woops, you're totally right. Knowing that the dot will have made a cycle every second, your variable that keeps track of the cycles could be current_pass = int((exp.time()-start_time()) / 1000).

    2. It may be best to create a list variable that contains the digits 0 to 480, with the command list_variable = list(range(480)). If you want, say, 4 stimuli, you can pick 4 random elements from this list: first_pick = list_variable.pop(random.randint(0,480)). The second pick should pick from a range of 0 to 479, because the list will become shorter with every pick. By 'popping' from the list, you prevent elements from being picked twice.

    3. Do you mean you want the line to flash only if the dot is positioned exactly in the center? (It will always pass the center because it will move from left to right; you just don't know if it also appears exactly in the center). In any case, you could make sure that the line is only presented when the dot is at a certain x-value, and this x could be the screen center or a range around the screen center, depending on what you want. (e.g.
      if cnvs.xcenter()-20 < x < cnvs.center()+20: cnvs.line(*input arguments here*) will draw the line if x is in a 40-pixel range around the center).

    Cheers,

    Josh

  • edited March 2016

    Hi again Josh!

    So the newly defined current_pass does give me an increment according to the passes. (it continually returns the same number till it reaches the next pass for which it increases by 1) But when I run the following code, I get a new kind of error- "IndexError: pop index out of range"
    The code below is a bit longer than necessary (since I'm comparing each randomly picked trial to the current_pass) but I couldn't determine what exactly is going wrong.

    sx = cnvs.xcenter()
    sy = cnvs.ycenter()
    
    # horizontal translation in pixels per frame
    dx = 2
    
    start_time = exp.time()
    
    while True:
        # Check for keypress and stop if detected
        key, time = kb.get_key(timeout=0)
        if exp.time() - start_time > 480000:
            break   
        x = int(sin((exp.time() - start_time) * dx / 1000.0 ) * amplitude +  cnvs.xcenter())
        current_pass = int((exp.time() - start_time) / 1000.0)
        cnvs.clear()
        # Draw fixation dot at current position
        cnvs.fixdot(x=x,y=sy)
        list_variable = list(range(480))
        first_pick = list_variable.pop(random.randint(0,480))
        second_pick = list_variable.pop(random.randint(0,479))
        third_pick = list_variable.pop(random.randint(0,478))
        fourth_pick = list_variable.pop(random.randint(0,477))
        if (first_pick == current_pass) or (second_pick == current_pass) or (third_pick == current_pass) or (fourth_pick == current_pass) and (x > (sx-20) and x < (sx+20)):        
            cnvs.line(sx, sy-20, sx, sy-40, penwidth = penwidth, color = "red")  
            cnvs.show()
            self.sleep(100)
        cnvs.show()
    
    

    Do you have any insights?

    Thanks again!
    Anupama

  • edited 5:48AM

    Hi Anupama,

    Could you try changing the lines with the pop commands into list_variable.pop(random.choice(range(480))) ? I think that should work.

    Cheers,

    Josh

  • edited March 2016

    Hi Josh,

    Yes, when I implemented that, I didn't get the error anymore. But the line stimulus also started flashing multiple times randomly on the same trial.
    I also need to show a second stimulus one second after the first stimulus. I tried implementing the following code but it entered an infinite loop and finally was aborted. I'm sure there's a logical error but I'm not able to detect it. Can you help me with knowing what's going wrong here?

    from openexp.keyboard import keyboard
    from math import sin, cos
    import numpy as np
    import random
    
    # Create keyboard reference
    kb = keyboard(exp)
    cnvs = self.offline_canvas()
    
    # Left and right x coordinate of screen
    screen_min_x = 0
    screen_max_x = cnvs.xcenter()*2
    print cnvs.xcenter()
    
    # Wave properties in pixels
    amplitude = 400
    
    wavelength = 50.0 
    
    # x to start with
    sx = cnvs.xcenter()
    sy = cnvs.ycenter()
    
    # horizontal translation in pixels per frame
    dx = 2
    
    start_time = exp.time()
    
    while True:
        # Check for keypress and stop if detected
        key, time = kb.get_key(timeout=0)
        if exp.time() - start_time > 480000:
            break   
        x = int(sin((exp.time() - start_time) * dx / 1000.0 ) * amplitude + cnvs.xcenter())
        current_pass = int((exp.time() - start_time) / 1000.0)
        cnvs.clear()
        # Draw fixation dot at current position
        cnvs.fixdot(x=x,y=sy)
        list_variable = list(range(480))
        for m in range (0,300):
            first_stim_present_times = np.random.choice(range(480))
            m += 1
            print first_stim_present_times
            second_stim_present_times = first_stim_present_times + 1
    
        if (first_stim_present_times == current_pass) and (x > (sx-20) and x < (sx+20)):
            penwidth = 10
    
            cnvs.line(sx, sy-20, sx, sy-40, penwidth = penwidth, color = "red")  
            cnvs.show()
            self.sleep(100)
        cnvs.show()
    
    

    Thanks,
    Anupama

    #

  • edited March 2016

    Hi anapuma,

    To me it seems weird that you have

        current_pass = int((exp.time() - start_time) / 1000.0)
        cnvs.clear()
        # Draw fixation dot at current position
        cnvs.fixdot(x=x,y=sy)
        list_variable = list(range(480))
        first_pick = list_variable.pop(random.randint(0,480))
        second_pick = list_variable.pop(random.randint(0,479))
        third_pick = list_variable.pop(random.randint(0,478))
        fourth_pick = list_variable.pop(random.randint(0,477))
        if (first_pick == current_pass) or (second_pick == current_pass) or (third_pick == current_pass) or (fourth_pick == current_pass) and (x > (sx-20) and x < (sx+20)):        
            cnvs.line(sx, sy-20, sx, sy-40, penwidth = penwidth, color = "red")  
            cnvs.show()
            self.sleep(100)
    

    in your while==True loop. This means that these values for all your picks, change with every frame. I doubt that is what you want as this appears quite haphazard to me. Rather, you probably want to determine these picks before you start the loop, but do compare their values to current_pass inside the loop. and act accordingly.

    However, maybe I don't really have a clear view of your current problem or what you intend to do. The purpose of your experiment or what you are trying to get on screen is quite unclear to me.

    Buy Me A Coffee

  • edited March 2016

    Hi Daniel,

    I probably wasn't too clear about what I'm trying to achieve. I am trying to get my first stimulus (a line) to be presented above the sinusoidal fixation dot only when the dot crosses the center. This has to happen on random trials (within the 8 minute trial) but the stimulus should only be presented if the fixation dot travels through the center coordinates of the screen.
    For this reason, I was trying to set a counter of individual trials (each sweep from left to right or vice versa) to randomly select any one of these 480 trials and present a stimulus on that trial.
    I didn't try implementing the random picks before the start of the while loop, as you suggested but I think that is more feasible.
    If I managed to show my first line stimulus correctly, I also need to show a second line stimulus (positioned randomly) exactly one second after the first stimulus presentation (therefore on the next trial)
    Hope this was more clear! I'm still a bit stuck on presenting the stimulus over the center on random trials, but if you also have ideas on this, I'd really appreciate if you could help me out!

    Thanks,
    Anupama

  • edited March 2016

    Hi Anapuma,
    Your intentions are a bit clearer now; your terminology was a bit confusing. Technically speaking, a trial is just a single instance of your task during which you collect responses, that you (usually) take as one sample in your data set later. Thus a trial in a trial seemed a bit odd; maybe it's better to call it 480 oscillations in a trial?

    To determine if your dot is on (or better: close to) the center of the screen, you can compare its x and y coordinates with those of the screen's center. The math module has a very useful function for this that I always use for these kinds of things: math.hypot (or hypotenuse/Euclidian distance). This basically gives you the distance in pixels between two points.

    To demonstrate in a simplified version of your script:

    # the dot is regarded as 'being at the center' if it is within a 5 pixel radius.
    # the higher this radius, the longer the dot will be regarded as 'at the center'
    # and thus the longer your line stimulus will be displayed.
    min_distance_to_center = 5
    
    while True:
        #... ommited for brevity
        x = int(sin((exp.time() - start_time) * dx / 1000.0 ) * amplitude + cnvs.xcenter())
        #...
        # Draw fixation dot at current position
        cnvs.fixdot(x=x,y=sy)
    
        distance_to_center = math.hypot(x-sx,y-sy)
        if distance_to_center <= min_distance_to_center:
             # The dot is less than 5 pixels away from the center
             cnvs.line(x1_line, y1_line, x2_line, y2_line)
        #...
    

    Then to your second problem. You want to randomly select some trials on which you want to draw this line. We need to extend the example above by adding an extra criterium when to draw the line. You can use your current_pass variable for that. So if you know there will be 480 oscillations in one trial, you can select 5 of them and show the line during only those instances. The random module has a very useful function for this. If you want to select multiple random samples from a list (and prevent individual items being selected twice) you can use random.sample(). Try this out in python or in the opensesame debug window:

    import random
    # Do it multiple times just for illustration purposes
    for i in range(5):
        random.sample(range(0,480),5)
    

    So putting things together, you could do something like this:

    import random
    
    # ...
    
    line_oscillations = random.sample(range(0,480))
    
    while True:
        #... ommited for brevity
        x = int(sin((exp.time() - start_time) * dx / 1000.0 ) * amplitude + cnvs.xcenter())
        #...
        # Draw fixation dot at current position
        cnvs.fixdot(x=x,y=sy)
    
        distance_to_center = math.hypot(x-sx,y-sy)
        if distance_to_center <= min_distance_to_center and current_pass in line_oscillations:
             # The dot is less than 5 pixels away from the center
             cnvs.line(x1_line, y1_line, x2_line, y2_line)
        #...
    

    I hope this gets you going again for a while. Good luck!

    Buy Me A Coffee

  • edited 5:48AM

    Oh, this works much better! Thanks again Daniel, appreciate the help :D

Sign In or Register to comment.

agen judi bola , sportbook, casino, togel, number game, singapore, tangkas, basket, slot, poker, dominoqq, agen bola. Semua permainan bisa dimainkan hanya dengan 1 ID. minimal deposit 50.000 ,- bonus cashback hingga 10% , diskon togel hingga 66% bisa bermain di android dan IOS kapanpun dan dimana pun. poker , bandarq , aduq, domino qq , dominobet. Semua permainan bisa dimainkan hanya dengan 1 ID. minimal deposit 10.000 ,- bonus turnover 0.5% dan bonus referral 20%. Bonus - bonus yang dihadirkan bisa terbilang cukup tinggi dan memuaskan, anda hanya perlu memasang pada situs yang memberikan bursa pasaran terbaik yaitu http://45.77.173.118/ Bola168. Situs penyedia segala jenis permainan poker online kini semakin banyak ditemukan di Internet, salah satunya TahunQQ merupakan situs Agen Judi Domino66 Dan BandarQ Terpercaya yang mampu memberikan banyak provit bagi bettornya. Permainan Yang Di Sediakan Dewi365 Juga sangat banyak Dan menarik dan Peluang untuk memenangkan Taruhan Judi online ini juga sangat mudah . Mainkan Segera Taruhan Sportbook anda bersama Agen Judi Bola Bersama Dewi365 Kemenangan Anda Berapa pun akan Terbayarkan. Tersedia 9 macam permainan seru yang bisa kamu mainkan hanya di dalam 1 ID saja. Permainan seru yang tersedia seperti Poker, Domino QQ Dan juga BandarQ Online. Semuanya tersedia lengkap hanya di ABGQQ. Situs ABGQQ sangat mudah dimenangkan, kamu juga akan mendapatkan mega bonus dan setiap pemain berhak mendapatkan cashback mingguan. ABGQQ juga telah diakui sebagai Bandar Domino Online yang menjamin sistem FAIR PLAY disetiap permainan yang bisa dimainkan dengan deposit minimal hanya Rp.25.000. DEWI365 adalah Bandar Judi Bola Terpercaya & resmi dan terpercaya di indonesia. Situs judi bola ini menyediakan fasilitas bagi anda untuk dapat bermain memainkan permainan judi bola. Didalam situs ini memiliki berbagai permainan taruhan bola terlengkap seperti Sbobet, yang membuat DEWI365 menjadi situs judi bola terbaik dan terpercaya di Indonesia. Tentunya sebagai situs yang bertugas sebagai Bandar Poker Online pastinya akan berusaha untuk menjaga semua informasi dan keamanan yang terdapat di POKERQQ13. Kotakqq adalah situs Judi Poker Online Terpercayayang menyediakan 9 jenis permainan sakong online, dominoqq, domino99, bandarq, bandar ceme, aduq, poker online, bandar poker, balak66, perang baccarat, dan capsa susun. Dengan minimal deposit withdraw 15.000 Anda sudah bisa memainkan semua permaina pkv games di situs kami. Jackpot besar,Win rate tinggi, Fair play, PKV Games