Controlling the position of a class object stimuli

Hi all,

My issue is, I don’t know how to (flexibly) control the position of my stimuli after the point at which it has been created. I’m making my stimuli by stacking 5 circles (rings), and so I’m using a class to do this. When an instance of the class has been made, the position is then fixed; is there a way to change the overall position of this stimuli (now of type ‘instance’)?

from psychopy import visual,event,core

win = visual.Window(size=[800, 800], monitor="testMonitor", units="deg", fullscr=False, color=[1, 1, 1])

class MakeStimuli:
    def __init__(self, win, stim_fill, backg_fill, pos=(0,0)):
        self.ring1 = visual.Circle(win, units="deg", radius= 1, fillColor=stim_fill,  pos=pos, lineColor=None)
        self.ring2 = visual.Circle(win, units="deg", radius=.8, fillColor=backg_fill, pos=pos, lineColor=None)
        self.ring3 = visual.Circle(win, units="deg", radius=.6, fillColor=stim_fill,  pos=pos, lineColor=None)
        self.ring4 = visual.Circle(win, units="deg", radius=.4, fillColor=backg_fill, pos=pos, lineColor=None)
        self.ring5 = visual.Circle(win, units="deg", radius=.2, fillColor=stim_fill,  pos=pos, lineColor=None)

    def draw(self):
        self.ring1.draw()
        self.ring2.draw()
        self.ring3.draw()
        self.ring4.draw()
        self.ring5.draw()

red_low = MakeStimuli(win, 'red', 'white', pos=(2,2))

red_low.draw()

win.flip()
event.waitKeys()
win.close()

The above code creates an instance of the class ‘MakeStimuli’ and displays it. As you can see, I am overriding the default stimuli position of (0,0) to set the position to (2,2). However, thereafter I am unable to change this position, presumably because despite that the instance is made up of several psychopy objects, the instance itself is not a psychopy object.

I want to treat the instance as a psychopy object, free to move it around as and when I please. Any ideas?

Cheers,
Jon

Hi @Jon1, you could make a new method for your class that calls the setPos method of your stim: Alternatively, see elementArrayStim for drawing multiple objects efficiently

e.g., for your current class…

from psychopy import visual,event,core

win = visual.Window(size=[800, 800], monitor="testMonitor", units="deg", fullscr=False, color=[1, 1, 1])

class MakeStimuli:
    def __init__(self, win, stim_fill, backg_fill, pos=(0,0)):
        self.ring1 = visual.Circle(win, units="deg", radius= 1, fillColor=stim_fill,  pos=pos, lineColor=None)
        self.ring2 = visual.Circle(win, units="deg", radius=.8, fillColor=backg_fill, pos=pos, lineColor=None)
        self.ring3 = visual.Circle(win, units="deg", radius=.6, fillColor=stim_fill,  pos=pos, lineColor=None)
        self.ring4 = visual.Circle(win, units="deg", radius=.4, fillColor=backg_fill, pos=pos, lineColor=None)
        self.ring5 = visual.Circle(win, units="deg", radius=.2, fillColor=stim_fill,  pos=pos, lineColor=None)

    def draw(self):
        self.ring1.draw()
        self.ring2.draw()
        self.ring3.draw()
        self.ring4.draw()
        self.ring5.draw()
    
    def setPos(self, pos):
        self.ring1.setPos(pos)
        #...etc

red_low = MakeStimuli(win, 'red', 'white', pos=(2,2))

for i in range(100):
    red_low.setPos((i/100, 2))  # remember to pass the method a tuple
    red_low.draw()
    win.flip()

win.close()
2 Likes

Very helpful, that worked nicely! Thanks @dvbridges.

Jon