Create random circles according to an arithmetic calculation exercise

Hello,

I am trying to produce an experiment in which the subject will be presented with an arithmetic calculation (for example: 5 + 1) for a few milliseconds, followed by a large circle (white polygon) in which the subject will perform procedures (reactions).

At this point, if the subject presses the L key on the keyboard, a black circle will be formed inside the white circle, and if he presses the A key, a circle will be reduced.

When the subject thinks he answered correctly (accordingly: added 6 circles) he will press Enter on the keyboard and the answer, and the response time will be recorded.

The complexity of the matter is that the circle itself must sometimes be random and not overlaped one circle over another.

Unfortunately I did not learn coding, and did not see an answer related to the topic in the forum. I would love to get help coding the complex step:

1. A polygon is created by pressing a keyboard (and the size of this polygon is random and does not overlaped another polygon)
2. The answer is recorded (the number of polygons, their size, the response time of the whole trial and whether it is correct)

Untitled (2)
Untitled (1)
Untitled

Many thanks to readers and helpers :slightly_smiling_face: :pray:.

Hi There!

This is a fun one and does require some coding alright! Here is a demo, but let me talk it through so you know how to change it, build on it and learn some coding!
makeCircles.psyexp (20.7 KB)

First we need a few functions (these are in the “initialize” routine).

  1. A function to check if 2 circles overlap (locally, we can use overlaps but since you are using circles it is easy to calculate manually, and this one works online too).
def customOverlaps(a, b):
    ''' a custom function to detect overlap between circular objects
    Locally we can use psychopys inbuild overlaps method, this does not
    yet exist in psychoJS so we need a custom function for online use.
    
    input:
        a: a circular object with attributed pos and size
        b: a circular object with attributes pos and size'''
    pt1 = a.pos
    pt2 = b.pos
    
    sep = ((pt1[0]-pt2[0])**2+(pt1[1]-pt2[1])**2)**0.5
    
    # if the seperation is less than the sum of the radi
    if sep < a.size[0]/2 + b.size[0]/2:
        return True
    else:
        return False
  1. A function to check if a smaller circle is inside a larger circle

def insideCircle(circle1, circle2):
    '''
    circle1: larger circle
    circle2: smaller circle
    
    return: boolean true or false if smaller circle inside larger
    '''
    x1 = circle1.pos[0]
    y1 = circle1.pos[1]
    r1 = circle1.size[0]/2
    x2 = circle2.pos[0]
    y2 = circle2.pos[1]
    r2 = circle2.size[0]/2
    
    distSq = (((x1 - x2)* (x1 - x2))+ ((y1 - y2)* (y1 - y2)))**(.5)
    isInside = False
    if (distSq + r2 == r1):
        print("The smaller circle lies completely"
            " inside the bigger circle with "
            "touching each other "
            "at a poof circumference. ")
    elif (distSq + r2 < r1):
        print("The smaller circle lies completely"
            " inside the bigger circle without"
            " touching each other "
            "at a poof circumference. ")
        isInside = True
    else:
        print("The smaller does not lies inside"
            " the bigger circle completely.")
    return isInside

OK then in your main trial routine you need to make a set of circles in code, we actually now have a tutorial on how this works here - in case you want to learn more coding. The difference with your code is we start with a blank white circle, wait for a key response then add more stimuli to be drawn, in the end routine tab:


# if the right arrow was pressed, add a circle to the circle list
if key_resp.keys == 'right':
    circleSet = False
    while not circleSet:
    # make a circle in a random location (can use same method to make random size)
        thisCircle = visual.Polygon(
            win=win, name='black_circle',
            edges=100, size=(0.2, 0.2),
            ori=0.0, pos=(random()-0.5, random()-0.5),# using random to pick random position (-0.5 to center around 0 in height units)dividing by 2 so it will always be in perimiter of large circle
            lineWidth=1.0,     colorSpace='rgb',  lineColor='white', fillColor='black',
            opacity=None, depth=0.0, interpolate=True)
        overlap = False # do the circles overlap each other
        for circle in circleList:
            if customOverlaps(circle, thisCircle):
                print('circle overlaps with existing circle, creating new one')
                overlap = True
        isInside = insideCircle(whiteCircle, thisCircle) # is the circle inside he white circle
        if not overlap and isInside:
            circleList.append(thisCircle)
            circleSet = True
elif key_resp.keys == 'left':
    continueRoutine = False
    addCircleLoop.finished = True

OK, so I hope this gives you the framework to move forward!

Becca
please note that I made this with local use in mind as you didn’t mention this would be online. If you want to take this online at the moment you will need to do some work to aid the pythong to javascript translation - I highly recommend looking at the crib sheet) - hope this helps

2 Likes

Wow @Becca you helped me a lot! Thank you.

Of course I need some time now to understand the whole process, but it’s really a significant step forward, I’ll use it and update.

Thanks again!