class CVEggStimText: # Some are overwritten by the init func. Here for reference text = "NULL" font_sz = 50 anchor = "center" t = 1 tscale = "seconds" # initme's arguments are : (text,font-sz,time,t-unit,screen) def initMe(self, arg_text, arg_font_sz, arg_t, arg_tscale, arg_screen, arg_r=1.0, arg_g=1.0, arg_b=1.0): # member vars init self.text = arg_text self.font_sz = arg_font_sz self.t = arg_t self.tscale = arg_tscale self.color = (arg_r, arg_g, arg_b) # dyn vars text_vegg = Text( text=self.text, color=self.color, position=(arg_screen.size[0] / 2, arg_screen.size[1] / 2), font_size=self.font_sz, anchor=self.anchor, ) viewport_vegg = Viewport(screen=arg_screen, size=arg_screen.size, stimuli=[text_vegg]) # Set up the pres var self.pres_vegg = Presentation(go_duration=(arg_t, arg_tscale), viewports=[viewport_vegg]) def show(self): # print self.text_vegg self.pres_vegg.go()
def showImage(screen, img, duration=1): def quitKey(event): if event.key == pygame.locals.K_SPACE: quit() def click(event): quit() def quit(dummy_arg=None): image.parameters.go_duration = (0,'frames') img = Image.open(img) #create textures tex = Texture(img) x = screen.size[0] / 2 y = screen.size[1] / 2 stimulus = TextureStimulus(texture = tex, position = (x, y), anchor = 'center') #create viewports viewport = Viewport(screen=screen, stimuli=[stimulus]) if duration: image = Presentation(go_duration=(duration, 'seconds'), viewports=[viewport]) else: image = Presentation(go_duration=('forever', ''), viewports=[viewport]) image.parameters.handle_event_callbacks=[(pygame.locals.QUIT, quit),(pygame.locals.KEYDOWN, quitKey), (pygame.locals.MOUSEBUTTONDOWN, click)] image.go()
def showInstructions(screen, text, textSize=60, textcolor=(255, 255, 255)): #create our instruction screen #load up the instruction text insStim, insView = printText(screen, text, textSize, textcolor) instructions = Presentation(go_duration=('forever', ), viewports=[insView]) #add a quit function and a handler to go with it def quitKey(event): if event.key == pygame.locals.K_SPACE: quit() def click(event): quit() def quit(dummy_arg=None): instructions.parameters.go_duration = (0, 'frames') instructions.parameters.handle_event_callbacks = [ (pygame.locals.QUIT, quit), (pygame.locals.KEYDOWN, quitKey), (pygame.locals.MOUSEBUTTONDOWN, click) ] #show instructions instructions.go()
def showStimulus(screen, text, colour): word, viewport = printWord(screen, text, 200, colour) p = Presentation(go_duration=(0.5, 'seconds'), viewports=[viewport]) p.go() start = time.clock() exit = 0 while not exit: data = raw_lpt_module.inp(0x379) & 0x20 if not data: RT = time.clock() p.parameters.go_duration = (0.032, 'seconds') #dataList.append ([text, colour, start, RT]) exit = 1 else: pass
def showStimulus(screen, text, colour): word, viewport = printWord(screen, text, 200, colour) p = Presentation(go_duration=(0.5,'seconds'),viewports=[viewport]) p.go() start = time.clock() exit = 0 while not exit: data = raw_lpt_module.inp(0x379) & 0x20 if not data: RT = time.clock() p.parameters.go_duration = (0.032, 'seconds') #dataList.append ([text, colour, start, RT]) exit = 1 else: pass
def __init__(self): global w, h self._running = True # Initialize screen # TODO # Set fullscreen self.screen = get_default_screen() # Get dimension of the screen w = self.screen.size[0] h = self.screen.size[1] # Initialize Targets self.TopTarget = Target2D() self.BotTarget = Target2D() self.LeftTarget = Target2D() self.RightTarget = Target2D() # Message self.mess = Text(text='Please wait for next trial...', color=(1.0, 0.5, 0.5), position=(w/2, h*0.8), font_size=50, anchor='center', on=True) # Arrows self.arrow = TextureStimulus() # Viewports to stick graphical objects to screen self.viewport1 = Viewport(screen=self.screen, stimuli=[self.TopTarget, self.BotTarget, self.LeftTarget, self.RightTarget]) # For Targets self.viewport2 = Viewport(screen=self.screen, stimuli=[self.arrow]) # For cue (and other things) self.viewport3 = Viewport(screen=self.screen, stimuli=[self.mess]) # For cue (and other things) # Presentations (for controlling timing) self.initialize = Presentation(go_duration=(duration_init, 'seconds'), viewports=[self.viewport3]) self.targetShow = Presentation(go_duration=(duration_target, 'seconds'), viewports=[self.viewport1]) self.cueShow = Presentation(go_duration=(duration_cue, 'seconds'), viewports=[self.viewport2]) # For result self.TargetLog = np.zeros((numTrial, 2)) # First column: target code,
def showStimulus(screen, text, colour, useLPT=True): word, viewport = printWord(screen, text, 200, colour) p = Presentation(go_duration=(stroopDuration,'seconds'),viewports=[viewport]) if useLPT: p.go() start = time.clock() exit = 0 while not exit: data = raw_lpt_module.inp(0x379) & 0x20 #print data if not data: #print "hello" RT = time.clock() p.parameters.go_duration = (blank, 'seconds') subject.inputData(trial, "text", text) subject.inputData(trial, "colour", colour) subject.inputData(trial, "RT", RT) exit = 1 else: pass
def showImage(screen, img, duration=1): def quitKey(event): if event.key == pygame.locals.K_SPACE: quit() def click(event): quit() def quit(dummy_arg=None): image.parameters.go_duration = (0, 'frames') img = Image.open(img) #create textures tex = Texture(img) x = screen.size[0] / 2 y = screen.size[1] / 2 stimulus = TextureStimulus(texture=tex, position=(x, y), anchor='center') #create viewports viewport = Viewport(screen=screen, stimuli=[stimulus]) if duration: image = Presentation(go_duration=(duration, 'seconds'), viewports=[viewport]) else: image = Presentation(go_duration=('forever', ''), viewports=[viewport]) image.parameters.handle_event_callbacks = [ (pygame.locals.QUIT, quit), (pygame.locals.KEYDOWN, quitKey), (pygame.locals.MOUSEBUTTONDOWN, click) ] image.go()
def showInstructions(screen, text, textSize=60, textcolor=(255, 255, 255)): #create our instruction screen #load up the instruction text insStim, insView = printText(screen, text, textSize, textcolor) instructions = Presentation(go_duration=('forever',), viewports=[insView]) #add a quit function and a handler to go with it def quitKey(event): if event.key == pygame.locals.K_SPACE: quit() def click(event): quit() def quit(dummy_arg=None): instructions.parameters.go_duration = (0,'frames') instructions.parameters.handle_event_callbacks=[(pygame.locals.QUIT, quit),(pygame.locals.KEYDOWN, quitKey), (pygame.locals.MOUSEBUTTONDOWN, click)] #show instructions instructions.go()
def set_stimuli(self, stimuli, trigger=None, kb_controller=False): """Now that we have our stimuli, we initialize everything we can""" viewport = Viewport(screen=self.screen, size=self.screen.size, stimuli=stimuli) # We disable "check_events" so that we don't lose "instantaneous" key # presses and can check these in our Response classes self.presentation = Presentation(viewports=[viewport], check_events=False) if trigger: trigger_controller = KeyboardTriggerInController(trigger) self.presentation.add_controller(self.presentation, "trigger_go_if_armed", trigger_controller) self.presentation.set(trigger_go_if_armed=0) if kb_controller: self.keyboard_controller = KeyboardResponseController() self.presentation.add_controller(None, None, self.keyboard_controller)
def initMe(self, arg_text, arg_font_sz, arg_t, arg_tscale, arg_screen, arg_r=1.0, arg_g=1.0, arg_b=1.0): # member vars init self.text = arg_text self.font_sz = arg_font_sz self.t = arg_t self.tscale = arg_tscale self.color = (arg_r, arg_g, arg_b) # dyn vars text_vegg = Text( text=self.text, color=self.color, position=(arg_screen.size[0] / 2, arg_screen.size[1] / 2), font_size=self.font_sz, anchor=self.anchor, ) viewport_vegg = Viewport(screen=arg_screen, size=arg_screen.size, stimuli=[text_vegg]) # Set up the pres var self.pres_vegg = Presentation(go_duration=(arg_t, arg_tscale), viewports=[viewport_vegg])
def set_stims(self, stim_list, stim_dict, stim_seq_file): self.stim_list = stim_list self.stim_dict = stim_dict self.stim_seq = yaml.load(stim_seq_file) viewport = Viewport(screen=self.screen, size=self.screen.size, stimuli=self.stim_list) # Need to at least wait for the first trigger if this is going to work. go_duration = (self.TR * len(self.stim_seq), 'seconds') self.presentation = Presentation(go_duration=go_duration, trigger_go_if_armed=0, viewports=[viewport]) self.presentation.add_controller(None, None, FunctionController(during_go_func=self.update) ) self.presentation.add_controller(None, None, self.keyboard_controller) # Adding this so that we can start the stimuli ahead of time self.presentation.add_controller(self.presentation,'trigger_go_if_armed', self.firstTTL_trigger)
gamma_scale += 0.05 do_gamma() elif event.key in [pygame.locals.K_KP_MINUS, pygame.locals.K_MINUS]: gamma_scale -= 0.05 do_gamma() def do_gamma(): global gamma_scale, text2 r = (np.arange(256) * 256 * gamma_scale).astype('i') g = r b = r worked = pygame.display.set_gamma_ramp(r, g, b) if worked: text2.parameters.text = "set_gamma_ramp(r,g,b): success" else: text2.parameters.text = "set_gamma_ramp(r,g,b): failure" do_gamma() # set gamma once initially handle_event_callbacks = [(pygame.locals.QUIT, quit), (pygame.locals.KEYDOWN, keydown)] # Create an instance of the Presentation class p = Presentation(viewports=[viewport], handle_event_callbacks=handle_event_callbacks) # Go! p.run_forever()
taskend = Text(text=' ', color=(1.0, 1.0, 1.0), position=(d_screen_half_x, d_screen_half_y + 160), font_size=60, anchor='center') viewportIntro = Viewport(screen=screen) viewport = Viewport(screen=screen, stimuli=[ title, title2, left_choice, right_choice, left_choice2, right_choice2, newset, taskend, fixation ]) p = Presentation( go_duration=(2000, 'seconds'), # run for longer than needed trigger_go_if_armed=0, #wait for trigger viewports=[viewport, viewportIntro]) def getState(t): global qIndex, screenText, screenText2, ip, question, gn_keystroke, subQ, amountRow, delay, krow, blocknum, amount, amountD, amountI, currentdelay, trialnum global isi, isi_index, now, firsttime, response, stim_onset, newseton, goodRow, taskendon, fixon, customdelays, amtText, amtText0I, amtText0D if (t > isi + isi_array[isi_index]): newseton = 0 fixon = 0 taskendon = 0 if firsttime: now = int(round(random())) stim_onset = t firsttime = 0
import VisionEgg VisionEgg.start_default_logging(); VisionEgg.watch_exceptions() from VisionEgg.Core import * from VisionEgg.FlowControl import Presentation from VisionEgg.Gratings import * from VisionEgg.PyroHelpers import * pyro_server = PyroServer() # get visionegg stimulus ready to go screen = get_default_screen() stimulus = SinGrating2D(temporal_freq_hz=0.0) viewport = Viewport(screen=screen,stimuli=[stimulus]) p = Presentation(go_duration=(5.0,'seconds'),viewports=[viewport]) # make a controller, serve it via pyro, and glue it to the Presentation tf_controller = PyroConstantController(during_go_value=0.0) pyro_server.connect(tf_controller,'tf_controller') p.add_controller(stimulus,'temporal_freq_hz', tf_controller) quit_controller = PyroConstantController(during_go_value=0) pyro_server.connect(quit_controller,'quit_controller') p.add_controller(p,'quit', quit_controller) # get listener controller and register it p.add_controller(None,None, pyro_server.create_listener_controller()) # initialize graphics to between presentations state p.run_forever()
import VisionEgg VisionEgg.start_default_logging(); VisionEgg.watch_exceptions() from VisionEgg.Core import * from VisionEgg.FlowControl import Presentation from VisionEgg.Gratings import * import VisionEgg.Daq from VisionEgg.DaqLPT import * # Normal stuff (from grating demo): screen = get_default_screen() stimulus = SinGrating2D(position = ( screen.size[0]/2.0, screen.size[1]/2.0 ), anchor = 'center', size = ( 300.0 , 300.0 ), spatial_freq = 10.0 / screen.size[0], # units of cycles/pixel temporal_freq_hz = 5.0, orientation = 45.0 ) viewport = Viewport( screen=screen, stimuli=[stimulus] ) p = Presentation(go_duration=(5.0,'seconds'),viewports=[viewport]) # Create a trigger output controller trigger_out_controller = LPTTriggerOutController() # Add the trigger output controller to the presentation's list of controllers p.add_controller(None,None,trigger_out_controller) # Go! p.go()
class VisualSpellerVE(MainloopFeedback): ''' Visual Speller with six circles like the classical HexOSpell. ''' # Triggers: look in Marker END_LEVEL1, END_LEVEL2 = 244, 245 # end of hex levels COPYSPELLING_FINISHED = 246 STIMULUS = [[11, 12, 13, 14, 15, 16], [21, 22, 23, 24, 25, 26]] RESPONSE = [[51, 52, 53, 54, 55, 56], [61, 62, 63, 64, 65, 66]] TARGET_ADD = 20 ERROR_ADD = 100 COUNTDOWN_STIMULI = 239 ERROR_POTENTIAL = 96 # send if error potential is classified def init(self): ''' initialize parameters ''' self.log_filename = 'VisualSpellerVE.log' self.geometry = [0, 0, 1280, 800] ## size self.letterbox_size = (60, 60) self.osc_size = 40 self.font_size_phrase = 60 # the spelled phrase at the top self.font_size_current_letter = 80 # the spelled phrase at the top self.font_size_countdown = 150 # number during countdown self.desired_phrase = "" ## colors: self.bg_color = (0., 0., 0.) self.phrase_color = (0.2, 0.0, 1.0) self.current_letter_color = (1.0, 0.0, 0.0) self.countdown_color = (0.2, 0.0, 1.0) self.osc_color = (1, 1, 1) self.letter_set = [['A','B','C','D','E'], \ ['F','G','H','I','J'], \ ['K','L','M','N','O'], \ ['P','Q','R','S','T'], \ ['U','V','W','X','Y'], \ ['Z','_','.',',','<']] self.fullscreen = False self.use_oscillator = True self.offline = True self.copy_spelling = True # in copy-spelling mode, selection of the target symbol is forced self.debug = False self.nCountdown = 5 self.nr_sequences = 6 self.randomize_sequence = True # set to False to present a fixed stimulus sequence self.min_dist = 2 # Min number of intermediate flashes bef. a flash is repeated twice self.stimulus_duration = 0.083 # 5 frames @60 Hz = 83ms flash self.interstimulus_duration = 0.1 self.animation_time = 1 self.wait_before_classify = 1. self.feedback_duration = 1. self.feedback_ErrP_duration = 1.0 self.wait_after_start = 0. # Countdown options self.do_animation = True self.synchronized_countdown = True if (self.synchronized_countdown): self.do_animation = False self.countdown_level1 = True self.countdown_level2 = True self.countdown_shapes = { 'circle': FilledCircle, 'hexagon': FilledHexagon } self.countdown_shape_select = 'hexagon' self.countdown_shape_color = (0.7, 0.7, 0.7) self.countdown_shape_on = True self.countdown_blinking_nr = 5 #number of pre-sequence stimuli(1 sec is approx. 5 frames at 60 Hz) self.wait_after_early_stopping = 3 #sec self.abort_trial = False self.output_per_stimulus = True self.use_ErrP_detection = False self.serialtrigger = False # FIXME: this should be fixed properly try: self.serialport = serialport.SerialPort(13) except: self.serialport = None self.send_parallel_bak = self.send_parallel if self.debug: msg = "!!! YOU\'RE IN DEBUG MODE! CLASSIFICATION WILL BE RANDOM OR KEYBOARD CONTROLLED !!!" self.logger.warning(msg) def pre_mainloop(self): ## logging assert (len(self.log_filename) != 0 ) # 'log_filename' must not be empty string! logger.setLevel(logging.ERROR) handler = logging.FileHandler(self.log_filename, 'w') handler.setLevel(logging.INFO) formatter = logging.Formatter("%(asctime)s: %(message)s") handler.setFormatter(formatter) self.logger.setLevel(logging.INFO) self.logger.addHandler(handler) self._nr_elements = 6 self._idx_backdoor = 5 self._init_classifier_output() self._classified_element = -1 self._classified_letter = -1 for s in self.desired_phrase: assert s in [l for ls in self.letter_set for l in ls] # invalid letters in desired phrase! self._spelled_phrase = "" self._spelled_letters = "" self._desired_letters = self.desired_phrase self._copyspelling_finished = False # if self.offline: # self.__idle() # In offline mode: set the first to-be-spelled letter self._spellerHeight = self.geometry[3] - self.letterbox_size[1] self._centerPos = (self.geometry[2] / 2., self._spellerHeight / 2.) self._nr_letters = 0 for i in xrange(len(self.letter_set)): self._nr_letters += len(self.letter_set[i]) self._current_level = 1 # Index of current level self._current_sequence = 0 # Index of current sequence self._current_stimulus = 0 # Index of current stimlus self._current_countdown = self.nCountdown self.random = random.Random(clock()) self._debug_classified = None ## init states: self._state_countdown = True if not self.countdown_level1: self._state_countdown = False self._state_trial = True else: #self._state_countdown = not self.offline self._state_trial = False self._state_classify = False self._state_feedback = False self._state_abort = False ## init containers for VE elements: self._ve_elements = [] ## oscillator state: if not self.use_oscillator: self.osc_color = self.bg_color self.osc_size = 0 ## call subclass-specific pre_mainloop: self.prepare_mainloop() ## build screen elements: self.__init_screen() if self.offline: self.__idle() if self.abort_trial: ''' Start listener for abort_trial event eg. ''' ## delay after play (might be useful for filters...) pygame.time.wait(int(self.wait_after_start * 1000)) self.logger.info("waiting %d seconds after play." % self.wait_after_start) ## send start trigger: self.send_parallel(marker.RUN_START) self.logger.info("[TRIGGER] %d" % marker.RUN_START) ## error potential classifier: self._ErrP_classifier = None def on_interaction_event(self, data): self.logger.debug('interaction event') serial = data.get('serialtrigger', None) if serial is None: return if serial: self.logger.debug('using serial port') self.send_parallel = self.serialport.send else: self.logger.debug('using parallel port') self.send_parallel = self.send_parallel_bak def post_mainloop(self): """ Sends end marker to parallel port. """ if self.abort_trial: ''' Stop listener for abort_trial event ''' pass pygame.time.wait(500) self.send_parallel(marker.RUN_END) self.logger.info("[TRIGGER] %d" % marker.RUN_END) pygame.time.wait(500) self._presentation.set(quit=True) self._screen.close() def __init_screen(self): ## create screen: if not self.fullscreen: os.environ['SDL_VIDEO_WINDOW_POS'] = '%d, %d' % (self.geometry[0], self.geometry[1]) self._screen = Screen(size=(self.geometry[2], self.geometry[3]), fullscreen=self.fullscreen, bgcolor=self.bg_color, sync_swap=True) ## create letter box on top: self._ve_letterbox = Target2D(position=(self._centerPos[0], self.geometry[3] * (1 - 0.01) - self.letterbox_size[1] / 2.), size=(self.letterbox_size[0], self.letterbox_size[1]), color=self.phrase_color) self._ve_innerbox = Target2D(position=(self._centerPos[0], self.geometry[3] * (1 - 0.01) - self.letterbox_size[1] / 2.), size=(self.letterbox_size[0] - 6, self.letterbox_size[1] - 6), color=self.bg_color) self._current_letter_position = (self._centerPos[0], self.geometry[3] * (1 - 0.015) - self.letterbox_size[1] / 2.) self._ve_current_letter = Text( position=self._current_letter_position, text=(len(self._desired_letters[:1]) == 0 and " " or self._desired_letters[:1]), font_size=self.font_size_current_letter, color=self.current_letter_color, anchor='center') self._ve_desired_letters = Text( position=(self._centerPos[0] + 5 + self.letterbox_size[0] / 2., self._current_letter_position[1]), text=(len(self._desired_letters[1:]) == 0 and " " or self._desired_letters[1:]), font_size=self.font_size_phrase, color=self.phrase_color, anchor='left') self._ve_spelled_phrase = Text( position=(self._centerPos[0] - 5 - self.letterbox_size[0] / 2., self._current_letter_position[1]), text=(len(self._spelled_phrase) == 0 and " " or self._spelled_phrase), font_size=self.font_size_phrase, color=self.phrase_color, anchor='right') # if we're in free spelling mode, we hide all text fields but # the _ve_spelled_phrase. we also need a multiline # _ve_spelled_phrase instead of the single lined one if self.offline == self.copy_spelling == False: self._spelled_phrase = " " self._ve_spelled_phrase = WrappedText( position=(0, self._current_letter_position[1]), text=(len(self._spelled_phrase) == 0 and " " or self._spelled_phrase), font_size=self.font_size_phrase, color=self.phrase_color, size=(float(self.geometry[2]), float(self.geometry[3]))) for i in self._ve_letterbox, self._ve_innerbox, self._ve_current_letter, self._ve_desired_letters: i.set(on=False) ## add word box to elementlist: self._ve_elements.extend([ self._ve_letterbox, self._ve_innerbox, self._ve_current_letter, self._ve_desired_letters, self._ve_spelled_phrase ]) ## create countdown: self._ve_countdown = Text(position=self._centerPos, text=" ", font_size=self.font_size_countdown, color=self.countdown_color, anchor='center', on=False) ## create countdown shapes self._ve_countdown_shape = self.countdown_shapes[ self.countdown_shape_select](radius=90, position=self._centerPos, color=self.countdown_shape_color, on=False) ## create oscillator circle: self._ve_oscillator = FilledCircle(position=(self.osc_size / 2 + 10, self.osc_size / 2 + 10), radius=self.osc_size / 2, color=self.osc_color, on=False) ## create shapes and letters: self.init_screen_elements() ## add remaining elements to element list: self._ve_elements.extend([ self._ve_countdown_shape, self._ve_countdown, self._ve_oscillator ]) ## add elements to viewport: self._viewport = Viewport(screen=self._screen, stimuli=self._ve_elements) self._presentation = Presentation(viewports=[self._viewport], handle_event_callbacks=[ (pygame.KEYDOWN, self.keyboard_input), (pygame.QUIT, self.__stop) ]) def play_tick(self): """ called every loop, if in play mode. """ self.pre_play_tick() if self._state_countdown: self.pre__countdown() self.__countdown() self.post__countdown() elif self._state_trial: self.pre__trial() self.__trial() self.post__trial() elif self._state_classify: self.pre__classify() self.__classify() self.post__classify() elif self._state_feedback: self.pre__feedback() self.__feedback() self.post__feedback() elif self._state_abort: self.__abort() self.post__abort() else: self.pre__idle() self.__idle() self.post__idle() self.post_play_tick() def __stop(self, *args): self.on_stop() def __idle(self): if self.offline and len(self._desired_letters) > 0: # add new letter: for e in xrange(len(self.letter_set)): for l in xrange(len(self.letter_set[e])): if self._desired_letters[0] == self.letter_set[e][l]: self._classified_element = e self._classified_letter = l if self.countdown_level1: self._state_countdown = True else: self._state_trial = True else: ## otherwise just wait until a new letter is sent: self._presentation.set(go_duration=(0.1, 'seconds')) self._presentation.go() def __countdown(self): def blink(): i = 0 while (i < self.countdown_blinking_nr): self._ve_countdown_shape.set(on=True) self._ve_countdown.set(text="%d" % self._current_countdown, on=True) self.send_parallel(self.COUNTDOWN_STIMULI) self.logger.info("[TRIGGER] %d" % self.COUNTDOWN_STIMULI) self._presentation.set(go_duration=(self.stimulus_duration, 'seconds')) self._presentation.go() self._ve_countdown_shape.set(on=False) self._ve_countdown.set(on=False) self._presentation.set( go_duration=(self.interstimulus_duration, 'seconds')) self._presentation.go() i = i + 1 if self._current_countdown == self.nCountdown: self.send_parallel(marker.COUNTDOWN_START) self.logger.info("[TRIGGER] %d" % marker.COUNTDOWN_START) self.set_countdown_screen() self._ve_countdown.set(on=True) self._ve_countdown_shape.set(on=self.countdown_shape_on) self._presentation.set(go_duration=(1, 'seconds')) self._ve_countdown.set(text="%d" % self._current_countdown) self._presentation.go() self._current_countdown = (self._current_countdown - 1) % self.nCountdown if self.synchronized_countdown and self._current_countdown == 1: self.set_synchronized_countdown_screen() blink() self._current_countdown = self.nCountdown self.set_standard_screen() self._state_countdown = False self._state_trial = True self._ve_countdown.set(on=False) self._ve_countdown_shape.set(on=False) self._ve_countdown.set(color=self.countdown_color) if self._current_countdown == 0: # Executed only if self.synchronized_countdown = False self._current_countdown = self.nCountdown self.set_standard_screen() pygame.time.wait(10) self._state_countdown = False self._state_trial = True self._ve_countdown_shape.set(on=False) self._ve_countdown.set(on=False) self._ve_countdown.set(color=self.countdown_color) def __trial(self): if self._current_sequence == 0 and self._current_stimulus == 0: #level 1 animation when there is no countdown if self._current_level == 1 and not self.countdown_level1: if self.do_animation: self.set_countdown_screen() self.set_standard_screen() # generate random sequences: if self.randomize_sequence: self.flash_sequence = [] for _ in range(self.nr_sequences): random_flash_sequence(self, set=range(self._nr_elements), min_dist=self.min_dist, seq_len=self._nr_elements) # or else use fixed sequence: else: self.flash_sequence = range(self._nr_elements) if self.randomize_sequence: currentStimulus = self.flash_sequence[self._current_sequence * self._nr_elements + self._current_stimulus] else: currentStimulus = self.flash_sequence[self._current_stimulus] # set stimulus: self.stimulus(currentStimulus, True) #self._ve_oscillator.set(on=True) if self.abort_trial and self.abort_trial_check(): # restart trial on abort_trial event: self._state_trial = False self._state_abort = True return # check if current stimulus is target and then send trigger: target_add = 0 if len(self._desired_letters) > 0: if self._current_level == 1: if self._desired_letters[:1] in self.letter_set[ currentStimulus]: # current stimulus is target group: target_add = self.TARGET_ADD else: if currentStimulus == self._idx_backdoor: # current stimulus is backdoor: if not self._desired_letters[:1] in self.letter_set[ self._classified_element]: # we are in the wrong group. backdoor is target: target_add = self.TARGET_ADD else: # current stimulus is no backdoor: if self._desired_letters[:1] == self.letter_set[ self._classified_element][currentStimulus]: # current stimulus is target symbol: target_add = self.TARGET_ADD self.send_parallel(self.STIMULUS[self._current_level - 1][currentStimulus] + target_add) self.logger.info( "[TRIGGER] %d" % (self.STIMULUS[self._current_level - 1][currentStimulus] + target_add)) # present stimulus: self._presentation.set(go_duration=(self.stimulus_duration, 'seconds')) self._presentation.go() # reset to normal: self._ve_oscillator.set(on=False) self.stimulus(currentStimulus, False) # present interstimulus: self._presentation.set(go_duration=(self.interstimulus_duration, 'seconds')) self._presentation.go() if self.debug: self.on_control_event( {'cl_output': (self.random.random(), currentStimulus + 1)}) ## TODO: check here for classification !!!! if self.output_per_stimulus: # increase self._current_stimulus = (self._current_stimulus + 1) % self._nr_elements if self._current_stimulus == 0: self._current_sequence = (self._current_sequence + 1) % self.nr_sequences # check for end of trial: if self._current_sequence == 0 and self._current_stimulus == 0: # send trigger: if self._current_level == 1: self.send_parallel(self.END_LEVEL1) self.logger.info("[TRIGGER] %d" % self.END_LEVEL1) else: self.send_parallel(self.END_LEVEL2) self.logger.info("[TRIGGER] %d" % self.END_LEVEL2) # decide how to continue: self._state_trial = False self._state_classify = True else: # increase self._current_stimulus = (self._current_stimulus + 1) % self._nr_elements if self._current_stimulus == 0: self._current_sequence = (self._current_sequence + 1) % self.nr_sequences if self.check_classification(self._current_sequence + 1): self._state_trial = False self._state_classify = True pygame.time.wait(self.wait_after_early_stopping * 1000) if self._current_sequence == 0 and self._current_stimulus == 0: # send trigger: if self._current_level == 1: self.send_parallel(self.END_LEVEL1) self.logger.info("[TRIGGER] %d" % self.END_LEVEL1) else: self.send_parallel(self.END_LEVEL2) self.logger.info("[TRIGGER] %d" % self.END_LEVEL2) # decide how to continue: self._state_trial = False self._state_classify = True def check_classification(self, nr): #print self._classifier_output means = [None] * self._nr_elements minimum = maxint classified = None for ii in range(self._nr_elements): means[ii] = sum(self._classifier_output[ii]) / nr if means[ii] < minimum: minimum = means[ii] classified = ii + 1 print "\n**** Class: %d (mean=%f)\n" % (classified, means[classified - 1]) return classified def __classify(self): ## wait until all classifier outputs are received: self._presentation.set(go_duration=(self.wait_before_classify, 'seconds')) self._presentation.go() if self.offline: if self._current_level == 1: classified = self._classified_element else: classified = self._classified_letter elif not self._debug_classified == None: classified = self._debug_classified self._debug_classified = None else: if self.output_per_stimulus: nClassified = sum([ len(self._classifier_output[i]) for i in xrange(self._nr_elements) ]) if nClassified < self._nr_elements * self.nr_sequences: pygame.time.wait(20) print 'not enough classifier-outputs received! (something may be wrong)' return ## classify and set output: means = [None] * self._nr_elements minimum = maxint classified = None for ii in range(self._nr_elements): means[ii] = sum( self._classifier_output[ii]) / self.nr_sequences if means[ii] < minimum: minimum = means[ii] classified = ii print "\n**** Class: %d (mean=%f)\n" % (classified + 1, means[classified]) else: means = [None] * self._nr_elements minimum = maxint classified = None for ii in range(self._nr_elements): means[ii] = sum( self._classifier_output[ii]) / self.nr_sequences if means[ii] < minimum: minimum = means[ii] classified = ii print "\n**** Class: %d (mean=%f)\n" % (classified + 1, means[classified]) ## Reset classifier output to empty lists self._init_classifier_output() error_add = 0 ## evaluate classification: if self._current_level == 1: self._classified_element = classified if len(self._desired_letters ) > 0 and not self._desired_letters[:1] in self.letter_set[ classified]: # wrong group selected: error_add = self.ERROR_ADD else: self._classified_letter = classified if self._classified_letter == self._idx_backdoor: ## backdoor classified: if len(self._desired_letters ) > 0 and self._desired_letters[:1] in self.letter_set[ self._classified_element]: # backdoor selection wrong: error_add = self.ERROR_ADD else: ## no backdoor classified: spelled_letter = self.letter_set[self._classified_element][ self._classified_letter] if len(self._desired_letters ) > 0 and spelled_letter != self._desired_letters[:1]: # wrong letter spelled: error_add = self.ERROR_ADD ## send response trigger: self.send_parallel(self.RESPONSE[self._current_level - 1][classified] + error_add) self.logger.info( "[TRIGGER] %d" % (self.RESPONSE[self._current_level - 1][classified] + error_add)) self._state_classify = False self._state_feedback = True def __feedback(self): self._state_feedback = False ## call subclass method: self.feedback() ## check ErrP classification: if self.use_ErrP_detection: t = 0 while self._ErrP_classifier is None and t < 1000: t += 50 pygame.time.wait(50) if self._ErrP_classifier is None: print "no ErrP classifier received! " if self._ErrP_classifier: self.send_parallel(self.ERROR_POTENTIAL) self.logger.info("[TRIGGER] %d" % (self.ERROR_POTENTIAL)) ## call subclass method: if not self.countdown_level2: self.switch_level() ## update phrases: if ((self._current_level == 2) and # only update, if we are at the end of level 2, (self._classified_letter != self._idx_backdoor or self.copy_spelling) and # if copyspelling off, we have no backdoor selected (self._ErrP_classifier is None or not self._ErrP_classifier) ): # no ErrP was detected (or ErrP detection is off) spelled_letter = "" if self.copy_spelling: ## in copy spelling we force the desired letter to be spelled if len(self._desired_letters) > 0: spelled_letter = self._desired_letters[:1] else: print "??? moved beyond desired phrase in copy spelling ???" else: spelled_letter = self.letter_set[self._classified_element][ self._classified_letter] ## update desired phrase: if len(self._desired_letters) > 0: if spelled_letter == self._desired_letters[:1]: # correct letter spelled: self._desired_letters = self._desired_letters[ 1:] # remove first letter else: # wrong letter spelled: if spelled_letter == "<": self._desired_letters = self._spelled_phrase[ -1:] + self._desired_letters else: self._desired_letters = "<" + self._desired_letters if len(self._desired_letters) == 0: self._copyspelling_finished = True ## update spelled phrase: self._spelled_letters += spelled_letter if spelled_letter == "<": self._spelled_phrase = self._spelled_phrase[:-1] else: self._spelled_phrase += spelled_letter ## update screen phrases: self.logger.info('Current Phrase:') self.logger.info(self._spelled_phrase) self._ve_spelled_phrase.set( text=(len(self._spelled_phrase) == 0 and " " or self._spelled_phrase)) self._ve_current_letter.set( text=(len(self._desired_letters[:1]) == 0 and " " or self._desired_letters[:1])) self._ve_desired_letters.set( text=(len(self._desired_letters[1:]) == 0 and " " or self._desired_letters[1:])) if self.use_ErrP_detection and self._ErrP_classifier: self._state_trial = True else: if self._current_level == 1: # continue with level2 trial: if self.countdown_level2: self._state_countdown = True else: self._state_trial = True elif not self.offline: # start countdown if self.countdown_level1: self._state_countdown = True else: self._state_trial = True # set new level: self._current_level = 3 - self._current_level ## reset ErrP_classifier: self._ErrP_classifier = None # check copyspelling: if self._copyspelling_finished: self._copyspelling_finished = False self.on_control_event({'print': 0}) # print desired phrase self.on_control_event({'print': 1}) # print spelled phrase self.on_control_event({'print': 2}) # print all spelled letters self.send_parallel(self.COPYSPELLING_FINISHED) self.logger.info("[TRIGGER] %d" % (self.COPYSPELLING_FINISHED)) pygame.time.wait(50) def __abort(self): # play warning sound def sine_array_onecycle(hz, peak, sample_rate): length = sample_rate / float(hz) omega = NP.pi * 2 / length xvalues = NP.arange(int(length)) * omega return (peak * NP.sin(xvalues)) def sine_array(hz, peak, samples_rate): return NP.resize(sine_array_onecycle(hz, peak, sample_rate), (sample_rate, )) sample_rate = 44100 pygame.mixer.init(sample_rate, -16, 2) # 44.1kHz, 16-bit signed, stereo f = sine_array(8000, 1, sample_rate) f = NP.array(zip(f, f)) sound = pygame.sndarray.make_sound(f) channel = sound.play(-1) channel.set_volume(0.2, 0.2) pygame.time.delay(1000) sound.stop() if self._current_level == 1 and self.countdown_level1: self._state_countdown = True elif self._current_level == 2 and self.countdown_level2: self._state_countdown = True else: self._state_trial = True self._init_classifier_output() def _init_classifier_output(self): ## Empty lists self._classifier_output = [list() for _ in xrange(self._nr_elements)] def abort_trial_check(self): ''' Check if event is an abort trial event ''' return False def keyboard_input(self, event): if event.key == pygame.K_ESCAPE: self.on_stop() elif event.key == pygame.K_KP_ENTER: self.on_control_event({'print': 0}) # print desired phrase self.on_control_event({'print': 1}) # print spelled phrase self.on_control_event({'print': 2}) # print all spelled letters elif event.key == pygame.K_DELETE: # The DELETE key empties the spelled text shown this works # only in free spelling mode (i.e. offline and copy_spelling # are set to False) if self.offline == self.copy_spelling == False: self.logger.info('Clearing Text.') self._spelled_phrase = " " elif self.debug: if ((event.key >= pygame.K_a and event.key <= pygame.K_z) or (event.key == pygame.K_LESS) or (event.key == pygame.K_PERIOD) or (event.key == pygame.K_COMMA)): self.on_control_event({'new_letter': chr(event.key).upper()}) elif event.key == pygame.K_MINUS: self.on_control_event({'new_letter': chr(pygame.K_UNDERSCORE)}) elif event.key == pygame.K_BACKSPACE: self.on_control_event({'new_letter': chr(pygame.K_LESS)}) elif event.key == pygame.K_SPACE: self.on_control_event({'new_letter': chr(pygame.K_UNDERSCORE)}) elif event.key == pygame.K_UP and self.use_ErrP_detection: self.on_control_event({'cl_output': (1, 7)}) elif event.key == pygame.K_DOWN and self.use_ErrP_detection: self.on_control_event({'cl_output': (0, 7)}) if not self.offline: if (event.key >= pygame.K_0 and event.key <= pygame.K_5): self._debug_classified = int(chr(event.key)) elif (event.key >= pygame.K_KP0 and event.key <= pygame.K_KP5): self._debug_classified = int(chr(event.key - 208)) def on_control_event(self, data): self.logger.info("[CONTROL_EVENT] %s" % str(data)) if data.has_key(u'cl_output'): # classification output was sent: score_data = data[u'cl_output'] cl_out = score_data[0] iSubstim = int(score_data[1]) # evt auch "Subtrial" if iSubstim in range(1, 7): self._classifier_output[iSubstim - 1].append(cl_out) elif self.use_ErrP_detection: self._ErrP_classifier = cl_out elif data.has_key('new_letter'): # get new letter to spell: self._desired_letters += data['new_letter'] self._ve_current_letter.set( text=(len(self._desired_letters[:1]) == 0 and " " or self._desired_letters[:1])) self._ve_desired_letters.set( text=(len(self._desired_letters[1:]) == 0 and " " or self._desired_letters[1:])) elif data.has_key(u'print'): if data[u'print'] == 0: self.logger.info("[DESIRED_PHRASE] %s" % self.desired_phrase) elif data[u'print'] == 1: self.logger.info("[SPELLED_PHRASE] %s" % self._spelled_phrase) elif data[u'print'] == 2: self.logger.info("[SPELLED_LETTERS] %s" % self._spelled_letters) ''' ========================== == METHODS TO OVERLOAD: == ========================== ''' def init_screen_elements(self): ''' overwrite this function in subclass. ''' pass def prepare_mainloop(self): ''' overwrite this function in subclass. ''' pass def set_countdown_screen(self): ''' set screen how it should look during countdown. overwrite this function in subclass. ''' pass def set_standard_screen(self): ''' set screen elements to standard state. overwrite this function in subclass. ''' pass def set_synchronized_countdown_screen(self): ''' set screen elements to for the synchronized countdown. overwrite this function in subclass. ''' pass def stimulus(self, i_element, on=True): ''' turn on/off the stimulus elements and turn off/on the normal elements. overwrite this function in subclass. ''' pass def feedback(self): ''' set screen how it should look during feedback presentation. overwrite this function in subclass. ''' pass def switch_level(self): ''' overwrite this function in subclass. ''' pass def pre_play_tick(self): pass def post_play_tick(self): pass def pre__countdown(self): pass def post__countdown(self): pass def pre__trial(self): pass def post__trial(self): pass def pre__classify(self): pass def post__classify(self): pass def pre__feedback(self): pass def post__feedback(self): pass def pre__idle(self): pass def post__idle(self): pass def post__abort(self): pass
pygame.font.init() pygame.mixer.init() sound = pygame.mixer.Sound("beep.wav") sound.play() for s in stimList: trial += 1 print s RT = 0 acc = 0 w, v = printWord(screen, str(s), 48, [255, 255, 255]) p = Presentation(go_duration=[0.675, 'seconds'], viewports=[v]) p.parameters.handle_event_callbacks = [(pygame.locals.KEYDOWN, key_handler) ] p.go() sub.inputData(trial, "RT", RT) sub.inputData(trial, "acc", acc) sub.inputData(trial, "s", s) sub.inputData(trial, "target", target) sub.printData() sound.play() sub.printData()
sub.inputData(trial, "largecolor", cDict[color]) sub.inputData(trial, "yellowButton", yellowB) sub.inputData(trial, "blueButton", blueB) print color if block == "overlapping": phase = "" fname = "%s_%s_%s_%s_%s_OL.bmp" % (ratio, n1, color, size, exemplar) t = Texture(Image.open(os.path.join(stimLib, fname))) s = TextureStimulus(texture=t, position=(x, y), anchor='center') texture_object = s.parameters.texture.get_texture_object() v = Viewport(screen=screen, stimuli=[s]) p = Presentation(go_duration=('forever', ), viewports=[v]) p.add_controller( None, None, FunctionController(during_go_func=put_image_overlapping, temporal_variables=TIME_SEC_ABSOLUTE)) p.parameters.handle_event_callbacks = [(pygame.locals.KEYDOWN, keyFunc)] p.go() else: if side == "large": fname1 = "%s_%s_%s_%s_%s_S2.bmp" % (ratio, n1, color, size, exemplar) fname2 = "%s_%s_%s_%s_%s_S1.bmp" % (ratio, n1, color, size, exemplar) else:
# Generate some images image_list = [] for i in range(num_images): image = Image.new("RGB",image_size,(0,0,255)) # Blue background draw = ImageDraw.Draw(image) line_x = image_size[0]/float(num_images) * i draw.line((line_x, 0, line_x, image_size[1]), fill=(255,255,255)) image_list.append(image) texture_list = map(Texture,image_list) # create instances of Texture from images screen = get_default_screen() stimulus = TextureStimulus(texture=texture_list[0], position = (screen.size[0]/2.0,screen.size[1]/2.0), anchor='center', size=image_size) viewport = Viewport(screen=screen, stimuli=[stimulus]) p = Presentation(go_duration=(num_images*duration_per_image,'seconds'),viewports=[viewport]) def put_image(t): i = int(t/duration_per_image) # choose image stimulus.parameters.texture = texture_list[i] p.add_controller(None,None,FunctionController(during_go_func=put_image)) p.go()
target_bottom = 0.2 * screen.size[1] - shift_unit stim_range_half = (target_top - target_bottom) / 2.0 score_factor = 90.0 / (30.0 * 0.5) # assume 30 maximum TRs at maximum -.5 # "score" to go from 90 to 0 deg # Create a Viewport instance viewport = Viewport(screen=screen, \ stimuli=[arrowStimulus,textAA,centerStim,taskStimulus,\ tach1,tach2,tach3,tach4,tach5,tach6,tach7,tach8,\ tach9,tach10,tach11,tach12,tach13,tach14,tach15,\ tach12,tach16,tach17,tach18,tach19,tachLabelR,\ tachLabelL]) # the Vision Egg's runtime control abilities. p = Presentation( go_duration=(Num_Secs,'seconds'), \ trigger_go_if_armed=0, \ viewports=[viewport]) # calculate a few variables we need next_stim_time = 0 direction = 1.0 last_direction = 1.0 arrow_scale = 0 arrowColor = 0 score = 90.0 first_loop = 1 start_time = 0 StimCount = -1 stimVis = 0 fbVis = 0 stimText = "+"
draw = ImageDraw.Draw(image) line_x = image_size[0] / float(num_images) * i draw.line((line_x, 0, line_x, image_size[1]), fill=(255, 255, 255)) image_list.append(image) texture_list = map(Texture, image_list) # create instances of Texture from images screen = get_default_screen() stimulus = TextureStimulus(texture=texture_list[0], position=(screen.size[0] / 2.0, screen.size[1] / 2.0), anchor='center', size=image_size) viewport = Viewport(screen=screen, stimuli=[stimulus]) p = Presentation(go_duration=(num_images * duration_per_image, 'seconds'), viewports=[viewport]) def put_image(t): i = int(t / duration_per_image) # choose image stimulus.parameters.texture = texture_list[i] p.add_controller(None, None, FunctionController(during_go_func=put_image)) p.go()
position=(screen.size[0] / 2, screen.size[1] / 2), ) cur_time = Text( text="", font_size=15, color=(.75, .75, .75), anchor='lowerleft', position=(0, 0), ) viewport_instructions = Viewport(screen=screen, stimuli=[instructions, cur_time]) attend_face = Viewport(screen=screen, stimuli=[instructions_attendFACE]) attend_scene = Viewport(screen=screen, stimuli=[instructions_attendSCENE]) p1 = Presentation(go_duration=('forever', ), viewports=[viewport_instructions]) p1.add_controller(None, None, FunctionController(during_go_func=displayTime)) p1.parameters.handle_event_callbacks = [(pygame.locals.KEYDOWN, waitForTrigger) ] # setup main experimental loop loadStims = 0 wrote_response = 0 stimulus = TextureStimulus( anchor='center', size=stimuli_size, position=(screen.size[0] / 2.0, screen.size[1] / 2.0), texture_min_filter=gl.GL_LINEAR, shrink_texture_ok=1, # PW 2012/11/26
drum = SpinningDrum(texture=texture, shrink_texture_ok=1) # Create a perspective projection for the spinning drum perspective = SimplePerspectiveProjection(fov_x=90.0) # Create a viewport with this projection drum_viewport = Viewport(screen=screen, projection=perspective, stimuli=[drum]) ################################################## # Create an instance of the Presentation class # ################################################## # Add target_viewport last so its stimulus is drawn last. This way the # target is always drawn after (on top of) the drum and is therefore # visible. p = Presentation(go_duration=(10.0, 'seconds'), viewports=[drum_viewport, target_viewport]) ######################## # Define controllers # ######################## # calculate a few variables we need mid_x = screen.size[0] / 2.0 mid_y = screen.size[1] / 2.0 max_vel = min(screen.size[0], screen.size[1]) * 0.4 # define target position as a function of time def get_target_position(t): global mid_x, mid_y, max_vel return (
random.shuffle(ns_list2) if ns_list1[-1] != ns_list2[0]: ns_list = ns_list1 + ns_list2 badshuffle = False print len(ns_list) print ns_list lastSoln = 0 mems = 0 calcs = 0 print "PRESS SPACE TO START" pause = Presentation(go_duration=('forever', ), viewports=[fixCross]) pause.parameters.handle_event_callbacks = [(pygame.locals.KEYDOWN, pause_handler)] pause.go() for ns in ns_list: #reset state vars misfire = 0 verify = 0 problem = None soln = None orig_strat = ns[1] problem = Problem(ns[0]) ns = problem.row['ns']
def doSim(self, trial, road, duration, tau, doEyetrack): # Measure sample rate in order to calculate delay buffer sample_rate = self.screen.measure_refresh_rate(2.0) print "Sample rate: " + str(sample_rate) #sample_rate = 60 self.doEyetrack = doEyetrack self.pos_ring = RingBuffer(self.center, int(math.floor(tau * sample_rate)) + 1) print("Ring Buffer:: size: " + str(self.pos_ring.size)) if doEyetrack: import pylink from EyeLinkCoreGraphicsVE import EyeLinkCoreGraphicsVE self.tracker = pylink.EyeLink() if self.tracker == None: print "Error: Eyelink is not connected" sys.exit() genv = EyeLinkCoreGraphicsVE(self.screen, self.tracker) pylink.openGraphicsEx(genv) #Opens the EDF file. edfFileName = "TRIAL" + str(trial) + ".EDF" self.tracker.openDataFile(edfFileName) pylink.flushGetkeyQueue() self.tracker.sendCommand("screen_pixel_coords = 0 0 %d %d" % (VisionEgg.config.VISIONEGG_SCREEN_W, VisionEgg.config.VISIONEGG_SCREEN_H)) tracker_software_ver = 0 eyelink_ver = self.tracker.getTrackerVersion() if eyelink_ver == 3: tvstr = self.tracker.getTrackerVersionString() vindex = tvstr.find("EYELINK CL") tracker_software_ver = int( float(tvstr[(vindex + len("EYELINK CL")):].strip())) if eyelink_ver >= 2: self.tracker.sendCommand("select_parser_configuration 0") if eyelink_ver == 2: #turn off scenelink camera stuff self.tracker.sendCommand("scene_camera_gazemap = NO") else: self.tracker.sendCommand("saccade_velocity_threshold = 35") self.tracker.sendCommand( "saccade_acceleration_threshold = 9500") # set EDF file contents self.tracker.sendCommand( "file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON" ) if tracker_software_ver >= 4: self.tracker.sendCommand( "file_sample_data = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET" ) else: self.tracker.sendCommand( "file_sample_data = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS") # set link data (used for gaze cursor) self.tracker.sendCommand( "link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON") if tracker_software_ver >= 4: self.tracker.sendCommand( "link_sample_data = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET" ) else: self.tracker.sendCommand( "link_sample_data = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS") if not self.doneSetup: self.tracker.doTrackerSetup() self.doneSetup = True else: while 1: try: error = self.tracker.doDriftCorrect( self.screen.size[0] / 2, self.screen.size[1] / 2, 1, 1) if error != 27: # ?? from example break else: self.tracker.doTrackerSetup() except: break self.screen.parameters.bgcolor = 106.0 / 255.0, 147.0 / 255.0, 0.0 # Load road data from file and create an image roadArray = numpy.loadtxt('road' + str(road) + '.txt') # Convert to a Path roadPath = ImagePath.Path( map(lambda xy: (xy[0], xy[1]), roadArray.tolist())) # Use Path to create a plot of the road im = Image.new("RGB", (2000, 100), (50, 50, 50)) draw = ImageDraw.Draw(im) # draw each side of the road separately draw.line(roadPath[:4000], fill=(200, 200, 200)) draw.line(roadPath[4000:], fill=(200, 200, 200)) del draw # Lay out a road texture in the x-z plane roadTexture = Texture(im) del im eye_height = 2.5 vertices = [(-10, -eye_height, 0), (-10, -eye_height, -1000), (10, -eye_height, 0), (10, -eye_height, -1000)] rect = TextureStimulus3D(texture=roadTexture, lowerleft=vertices[0], lowerright=vertices[1], upperleft=vertices[2], upperright=vertices[3]) # We will use these later for our camera transforms self.camera_matrix = ModelView() self.frame_timer = FrameTimer() self.outf = open( 'steersim-' + str(trial) + '-' + str(road) + '-out.txt', 'wb') # Vewport for the road viewport3D = Viewport( screen=self.screen, projection=SimplePerspectiveProjection(fov_x=75.2), camera_matrix=self.camera_matrix, stimuli=[rect]) # Construct a sky sky_l = 0 sky_r = self.screen.size[0] sky_t = self.screen.size[1] sky_b = self.screen.size[1] / 2 sky_vertices = [(sky_l, sky_t, 0), (sky_r, sky_t, 0), (sky_r, sky_b, 0), (sky_l, sky_b, 0)] sky = Rectangle3D(color=(144.0 / 255.0, 190.0 / 255.0, 1.0), vertex1=sky_vertices[0], vertex2=sky_vertices[1], vertex3=sky_vertices[2], vertex4=sky_vertices[3]) wheelTexture = Texture('wheel.png') self.wheel = TextureStimulus(texture=wheelTexture, internal_format=gl.GL_RGBA, position=(self.center, -75), anchor='center') # display the sky in its own viewport viewport2D = Viewport(screen=self.screen) viewport2D.parameters.stimuli = [sky, self.wheel] self.init_state() askText = Text(text='Press a key to start', anchor='center', position=(self.center, self.screen.size[1] / 2)) splash = Viewport(screen=self.screen) splash.parameters.stimuli = [askText] self.askForNext = Presentation(go_duration=(0.5, 'seconds'), viewports=[splash]) self.askForNext.add_controller( None, None, FunctionController(during_go_func=self.wait_for_key)) self.askForNext.parameters.enter_go_loop = True self.askForNext.run_forever() self.simPres = Presentation(go_duration=(duration, 'seconds'), viewports=[viewport3D, viewport2D], handle_event_callbacks=[ (pygame.KEYDOWN, self.check_keypress) ]) self.simPres.add_controller( None, None, FunctionController(during_go_func=self.update)) if doEyetrack: startTime = pylink.currentTime() self.tracker.sendMessage("SYNCTIME %d" % (pylink.currentTime() - startTime)) error = self.tracker.startRecording(1, 1, 1, 1) self.tracker.sendMessage("PRES %d START" % (trial)) self.simPres.go() if doEyetrack: self.tracker.sendMessage("PRES %d END" % (trial)) self.tracker.stopRecording() # File transfer and cleanup! self.tracker.setOfflineMode() pylink.msecDelay(500) #Close the file and transfer it to Display PC self.tracker.closeDataFile() self.tracker.receiveDataFile(edfFileName, edfFileName) self.outf.close() if self.quit: raise SystemExit
anchor='center', size=(300.0, 300.0), signal_fraction=cohLevel, signal_direction_deg=dirx, velocity_pixels_per_sec=100.0, dot_lifespan_sec=0.08, dot_size=3.0, num_dots=200) # Create a Viewport instance viewport = Viewport( screen=screen, stimuli=[str_instruct_1, fixation, dotStim, str_instruct_2, sampleFix]) p = Presentation( go_duration=(exp_length, 'seconds'), trigger_go_if_armed=0, #wait for trigger viewports=[viewport]) #initialize log file logname = time.strftime('_%m-%d-%Y_%Hh-%Mm.csv') logname = 'log_' + ss_num + logname logfile = open(logname, 'w') logfile.write("# LOGFILE: {0}\n".format(logname)) logfile.write("# Coherence,Direction,Response\n") ################################# # Main procedure # ################################# def getState(t):
screen = get_default_screen() screen.parameters.bgcolor = (0, 0, 0) pygame.font.init() ###UNCHANGING STIMULI #strat selection fixText, fixCross = printText(screen, '', 60, (255, 255, 255)) #generate texts strat2 = "\n\nDescribe your strategy" stratText, stratPort = printText(screen, strat2, 60, (255, 255, 255)) pauseText, pausePort = printText(screen, "paused", 60, (255, 255, 255)) p4 = Presentation(go_duration=(problemTime, 'seconds')) p = Presentation(go_duration=('forever', )) #strat selection startText, startCross = printWord(screen, 'Press the SPACEBAR to start', 60, (255, 255, 255)) pause = Presentation(go_duration=('forever', ), viewports=[startCross]) pause.parameters.handle_event_callbacks=[(pygame.locals.KEYDOWN, pause_handler)] pause.go() p3 = Presentation(go_duration=(0.5, 'seconds'), viewports=[fixCross]) p2 = Presentation(go_duration=(diffTime, 'seconds'), viewports=[stratPort]) p2.parameters.handle_event_callbacks=[(pygame.locals.KEYDOWN, diff_handler)]
screen = get_default_screen() # Set the background color to white (RGBA). screen.parameters.bgcolor = (1.0,1.0,1.0,1.0) # Create an instance of the Target2D class with appropriate parameters. target = Target2D(size = (25.0,10.0), color = (0.0,0.0,0.0,1.0), # Set the target color (RGBA) black orientation = -45.0) # Create a Viewport instance viewport = Viewport(screen=screen, stimuli=[target]) # Create an instance of the Presentation class. This contains the # the Vision Egg's runtime control abilities. p = Presentation(go_duration=(10.0,'seconds'),viewports=[viewport]) ####################### # Define controller # ####################### # calculate a few variables we need mid_x = screen.size[0]/2.0 mid_y = screen.size[1]/2.0 max_vel = min(screen.size[0],screen.size[1]) * 0.4 # define position as a function of time def get_target_position(t): global mid_x, mid_y, max_vel return ( max_vel*sin(0.1*2.0*pi*t) + mid_x , # x max_vel*sin(0.1*2.0*pi*t) + mid_y ) # y
dot_lifespan_sec = 5.0, dot_size = 3.0, num_dots = 100 ) ############################################################### # Create viewport - intermediary between stimuli and screen # ############################################################### viewport = Viewport(screen=screen, stimuli=[stimulus]) ######################################## # Create presentation object and go! # ######################################## p = Presentation(go_duration=(5.0,'seconds'), viewports=[viewport]) ############################################## # Connect the controller with the stimulus # ############################################## keyboard_response = KeyboardResponseController() # Add the keyboard controller to the presentation's list of controllers p.add_controller(None, None, keyboard_response) ######## # Go # ######## for i in range(3):
velocity_pixels_per_sec=10.0, dot_lifespan_sec=5.0, dot_size=3.0, num_dots=100) ############################################################### # Create viewport - intermediary between stimuli and screen # ############################################################### viewport = Viewport(screen=screen, stimuli=[stimulus]) ######################################## # Create presentation object and go! # ######################################## p = Presentation(go_duration=(5.0, 'seconds'), viewports=[viewport]) ############################################## # Connect the controller with the stimulus # ############################################## keyboard_response = KeyboardResponseController() # Add the keyboard controller to the presentation's list of controllers p.add_controller(None, None, keyboard_response) ######## # Go # ######## for i in range(3):
class SimpleVisionEgg: keyboard_controller = None trigger_controller = None screen = None presentation = None keys = None presses = None releases = None def __init__(self): """We break up initialization a bit as we need to go back and forth with some information. In this case, we need screen size before specifying the stimuli""" # pasted in from where it used to be at the beginning of the script # used to be outside of any methods... VisionEgg.start_default_logging() VisionEgg.watch_exceptions() # get screen size for setting fullscreen resolution # comment this block out if you don't want to use full-screen. screen = pygame.display.set_mode((0,0)) WIDTH, HEIGHT = screen.get_size() pygame.quit() VisionEgg.config.VISIONEGG_SCREEN_W = WIDTH VisionEgg.config.VISIONEGG_SCREEN_H = HEIGHT self.screen = get_default_screen() self.keys = [] self.presses = [] self.releases = [] def set_stimuli(self, stimuli, trigger=None, kb_controller=False): """Now that we have our stimuli, we initialize everything we can""" viewport = Viewport(screen=self.screen, size=self.screen.size, stimuli=stimuli) # We disable "check_events" so that we don't lose "instantaneous" key # presses and can check these in our Response classes self.presentation = Presentation(viewports=[viewport], check_events=False) if trigger: trigger_controller = KeyboardTriggerInController(trigger) self.presentation.add_controller(self.presentation, 'trigger_go_if_armed', trigger_controller) self.presentation.set(trigger_go_if_armed=0) if kb_controller: self.keyboard_controller = KeyboardResponseController() self.presentation.add_controller(None, None, self.keyboard_controller) def set_functions(self, update=None, pause_update=None): """Interface for cognac.StimulusController or similar""" self.presentation.add_controller(None, None, FunctionController(during_go_func=update, between_go_func=pause_update, return_type=NoneType) ) def go(self, go_duration=('forever',)): self.presentation.parameters.go_duration = go_duration self.presentation.go() def pause(self): self.presentation.parameters.go_duration = (0, 'frames') def get_new_response(self, t, min_interval=2.0 / 60, releases=False): """(key, press) = get_new_response(self, t, min_interval=2.0 / 60) DEPRECATED! Use this function to get responses from the keyboard controller in real time. Returns (None, None) if no new response is available. Maintains three instance variables - keys, presses and releases, which you can also access directly (but they won't be updated during loops where you don't call this function) This function makes a number of assumptions and is a little brittle right now. By not hard-coding the min_interval and maybe using key presses and release events directly, we'd have a much better function. But I don't really care right now. DJC """ raise DeprecationWarning("please use pygame directly, as in" + "StimController.Response") # Note - this is deprecated anyway, but it'd probably make more sense to # use the keyboard_controller.get_responses() to simply get the keys # that are down _right_now_ press_time = self.keyboard_controller.get_time_last_response_since_go() key = self.keyboard_controller.get_last_response_since_go() # Our first response! if len(self.keys) == 0: if key: self.keys.append(key) self.presses.append(press_time) self.releases.append(None) if releases: return (key, None) else: return (key, press_time) else: return (None, None) # We haven't seen a key press for min_interval if t >= press_time + min_interval and not self.releases[-1]: # This is only approximate! self.releases[-1] = t if releases: return (self.keys[-1], t) else: return (None, None) # We've seen a release, or we see a new key if (self.releases[-1] and press_time > self.releases[-1]) or \ key != self.keys[-1]: if not self.releases[-1]: self.releases[-1] = press_time self.keys.append(key) self.presses.append(press_time) self.releases.append(None) if releases: return (key, None) else: return (key, press_time) return (None, None) def get_responses(self, timeToSubtract=0, min_interval=2.0/60): """ Use this function to post-process the results of a KeyboardController VisionEgg's keyboard libraries records a keypress and timestamp every time something is down. So if a key is held down for 100 ms, there will be an entry in the keylist for every sample during that 100ms. This is a bit much; I'd rather just save onsets and offsets for every key. This function evaluates that. """ ''' If we're using the FORP, this isn't necessary, as events have no duration; they are represented as instantaneous keypresses. -- John ''' response = self.keyboard_controller.get_responses_since_go() responseTime = self.keyboard_controller.get_time_responses_since_go() # If I've only got one item in my response list, then it's silly to worry about onset/offset. Just keep it. if len(response) < 2: return (response,responseTime) # Save the first response, as by definition that's the first onset: goodResp = [response[0]] goodRespTime = [responseTime[0]-timeToSubtract] # Now step through every other item in the response list to check for unique-ness. for i in range(1,len(responseTime)): if (not(response[i] == response[i-1]) or \ (responseTime[i] - responseTime[i-1] > \ min_interval)): # ie, if something changed, or we have a long gap: offsetResp = [] # we might want to save an offset for item in response[i-1]: # loop through last item's data if (responseTime[i] - responseTime[i-1] < \ min_interval) and \ not(item in response[i]): # Bit clunky. Basically, holding down a key while pressing another creates # a unique response. So if you only let up one of those keys, code the # offset just for that key. offsetResp.append(item+'_Off') else: # it's been long enough that everything that was on should be called off. offsetResp.append(item+'_Off') if len(offsetResp) > 0: # If there's offset stuff to worry about, save it. goodResp.append(offsetResp) goodRespTime.append(responseTime[i-1]-timeToSubtract) # Save the new (onset) response. goodResp.append(response[i]) goodRespTime.append(responseTime[i]-timeToSubtract) # The final event should be an offset for whatever was down. offsetResp = [] for item in response[-1]: offsetResp.append(item+'_Off') goodResp.append(offsetResp) #goodResp.append(response[-1]+'_Off') goodRespTime.append(responseTime[-1]-timeToSubtract) return (goodResp, goodRespTime)
trial = 1 experiment = "numbers" enoughPractice = False while not enoughPractice: pracList = stroop.makePracticeList() for item in pracList: showStimulus(screen, item[0], item[1]) trial += 1 #experimenter prompt pracText, pracView = printWord(screen, 'Press SPACE TO CONTINUE, R TO REDO', 60, (255, 255, 255)) pause = Presentation(go_duration=('forever', ), viewports=[pracView]) pause.parameters.handle_event_callbacks=[(pygame.locals.KEYDOWN, practice_handler)] pause.go() """ TRADITIONAL STROOP 1. run trad stroop, 32 trials, 8 colour words """ trials = 32 colourWords = ["red", "blue", "green", "white", "yellow", "pink", "orange", "grey"] colours = [[255, 0, 0], [0, 0, 255], [0, 255, 0], [255, 255, 255], [255, 255, 0], [255, 0, 255], [255, 153, 51], [100, 100, 100]] Stroop = stroop.Stroop(colourWords, True, colours)
import VisionEgg VisionEgg.start_default_logging(); VisionEgg.watch_exceptions() from VisionEgg.Core import * from VisionEgg.FlowControl import Presentation from VisionEgg.Gratings import * from VisionEgg.PyroHelpers import * pyro_server = PyroServer() # get visionegg stimulus ready to go screen = get_default_screen() stimulus = SinGrating2D() viewport = Viewport(screen=screen,stimuli=[stimulus]) p = Presentation(viewports=[viewport]) # make a controller, serve it via pyro, and glue it to the Presentation tf_controller = PyroConstantController(during_go_value=0.0) pyro_server.connect(tf_controller,'tf_controller') p.add_controller(stimulus,'temporal_freq_hz', tf_controller) sf_controller = PyroConstantController(during_go_value=0.0) pyro_server.connect(sf_controller,'sf_controller') p.add_controller(stimulus,'spatial_freq', sf_controller) contrast_controller = PyroConstantController(during_go_value=0.0) pyro_server.connect(contrast_controller,'contrast_controller') p.add_controller(stimulus,'contrast', contrast_controller) orient_controller = PyroConstantController(during_go_value=0.0)
class TRStimController: """This is a relatively simple controller that simply updates what's on the screen every TR (which is the next occurrence of keyboard input of '5' after the TR length is exceeded. Currently it sets one stimulus on, and all others off, though we may want to change that to turn a list of stimuli on eventually""" # 3T laptop forp sends TTL pulses as "5"; buttons as "1","2","3","4" # John used to do things this way: # trigger_in_controller = KeyboardTriggerInController(pygame.locals.K_5) # Expected length of 1 TR TR = 2.0 # Time interval after which we assume we missed the trigger eps = 0.1 t = 0 trial_times = None missed_trigs = None stim_list = [] stim_dict = {} stim_seq = [] keyboard_controller = None presentation = None screen = None def __init__(self, TR=None, eps=None): # Get the initial setup if TR: self.TR = TR if eps: self.eps = eps self.trial_times = [] self.missed_trigs = [] self.state = self.state_generator() self.screen = get_default_screen() # background black (RGBA) self.screen.parameters.bgcolor = (0.0,0.0,0.0,0.0) self.keyboard_controller = KeyboardResponseController() self.firstTTL_trigger = KeyboardTriggerInController(K_5) def set_stims(self, stim_list, stim_dict, stim_seq_file): self.stim_list = stim_list self.stim_dict = stim_dict self.stim_seq = yaml.load(stim_seq_file) viewport = Viewport(screen=self.screen, size=self.screen.size, stimuli=self.stim_list) # Need to at least wait for the first trigger if this is going to work. go_duration = (self.TR * len(self.stim_seq), 'seconds') self.presentation = Presentation(go_duration=go_duration, trigger_go_if_armed=0, viewports=[viewport]) self.presentation.add_controller(None, None, FunctionController(during_go_func=self.update) ) self.presentation.add_controller(None, None, self.keyboard_controller) # Adding this so that we can start the stimuli ahead of time self.presentation.add_controller(self.presentation,'trigger_go_if_armed', self.firstTTL_trigger) def run(self): self.presentation.go() self.screen.close() def update(self, t): self.t = t try: self.state.next() except StopIteration: # shouldn't really happen, what with epsilon and all... self.blank_all_stims() def blank_all_stims(self): for stim in self.stim_list: stim.parameters.on=False def state_generator(self): for stim_info in self.stim_seq: self.trial_times.append(self.t) self.blank_all_stims() try: for stim_name, params in stim_info.items(): stim = self.stim_dict[stim_name] stim.parameters.on = True try: for name, value in params.items(): setattr(stim.parameters, name, value) except AttributeError: # params was None or something else we don't deal with pass except AttributeError: # We assume a no-colon single token / key self.stim_dict[stim_info].parameters.on = True # Don't even bother 'til we're close to the expected TR time while self.t - self.trial_times[-1] < self.TR - 2*self.eps: yield while self.t - self.trial_times[-1] < self.TR + self.eps: # Handle the rare case when a key might register between # function calls - THIS WOULD NEVER HAPPEN WITH VisionEgg as # written! while True: keys = self.keyboard_controller.get_responses_since_go() times = \ self.keyboard_controller.get_time_responses_since_go() if len(keys) == len(times): break i = None try: # Find the last value of '5' without inline reversal of keys/times # VisionEgg returns "responses" as a list of lists of chars, not just a list of chars... i = len(keys)-1-list(reversed(keys)).index(['5']) except ValueError: pass # If anybody presses the escape key, quit entirely. try: needToQuit = keys.index(['escape']) #self.presentation = None #exit() except ValueError: pass if i and times[i] > self.trial_times[-1]: break else: yield if self.t - self.trial_times[-1] >= self.TR + self.eps: # We missed a TR (we think) self.missed_trigs.append(self.t) self.t = self.trial_times[-1] + self.TR def get_responses(self, timeToSubtract=0, min_interval=2.0/60): """ This function isn't especially elegant, but it's functional. VisionEgg's keyboard libraries records a keypress and timestamp every time something is down. So if a key is held down for 100 ms, there will be an entry in the keylist for every sample during that 100ms. This is a bit much; I'd rather just save onsets and offsets for every key. This function evaluates that. """ ''' If we're using the FORP, this isn't necessary, as events have no duration; they are represented as instantaneous keypresses. -- John ''' response = self.keyboard_controller.get_responses_since_go() responseTime = self.keyboard_controller.get_time_responses_since_go() # If I've only got one item in my response list, then it's silly to worry about onset/offset. Just keep it. if len(response) < 2: return (response,responseTime) # Save the first response, as by definition that's the first onset: goodResp = [response[0]] goodRespTime = [responseTime[0]-timeToSubtract] # Now step through every other item in the response list to check for unique-ness. for i in range(1,len(responseTime)): if (not(response[i] == response[i-1]) or \ (responseTime[i] - responseTime[i-1] > \ min_interval)): # ie, if something changed, or we have a long gap: offsetResp = [] # we might want to save an offset for item in response[i-1]: # loop through last item's data if (responseTime[i] - responseTime[i-1] < \ min_interval) and \ not(item in response[i]): # Bit clunky. Basically, holding down a key while pressing another creates # a unique response. So if you only let up one of those keys, code the # offset just for that key. offsetResp.append(item+'_Off') else: # it's been long enough that everything that was on should be called off. offsetResp.append(item+'_Off') if len(offsetResp) > 0: # If there's offset stuff to worry about, save it. goodResp.append(offsetResp) goodRespTime.append(responseTime[i-1]-timeToSubtract) # Save the new (onset) response. goodResp.append(response[i]) goodRespTime.append(responseTime[i]-timeToSubtract) # The final event should be an offset for whatever was down. offsetResp = [] for item in response[-1]: offsetResp.append(item+'_Off') goodResp.append(offsetResp) #goodResp.append(response[-1]+'_Off') goodRespTime.append(responseTime[-1]-timeToSubtract) return (goodResp, goodRespTime)
dotStim = DotArea2D( position = ( screen_half_x, screen_half_y ), anchor = 'center', size = ( 300.0 , 300.0 ), signal_fraction = cohLevel, signal_direction_deg = dirx, velocity_pixels_per_sec = 100.0, dot_lifespan_sec = 0.08, dot_size = 3.0, num_dots = 200) # Create a Viewport instance viewport = Viewport(screen=screen, stimuli=[str_instruct_1, fixation, dotStim, str_instruct_2, sampleFix]) p = Presentation( go_duration = (exp_length,'seconds'), trigger_go_if_armed = 0, #wait for trigger viewports = [viewport]) #initialize log file logname=time.strftime('_%m-%d-%Y_%Hh-%Mm.csv') logname='log_'+ss_num+logname logfile = open(logname, 'w') logfile.write("# LOGFILE: {0}\n".format(logname)) logfile.write("# Coherence,Direction,Response\n") ################################# # Main procedure # ################################# def getState(t): global fixOn, dotsOn, changeCoh, changeDir, keyPressed, fixOn_start, dotsOn_start, rt, main_curr, block_total, block_curr, practicenum, blocktype, sampleFixOn
# Set the background color to white (RGBA). screen.parameters.bgcolor = (1.0,1.0,1.0,1.0) # Create an instance of the Target2D class with appropriate parameters. target = Target2D(size = (25.0,10.0), anchor = 'center', color = (0.0,0.0,0.0,1.0), # Set the target color (RGBA) black orientation = -45.0) # Create a Viewport instance viewport = Viewport(screen=screen, stimuli=[target]) # Create an instance of the Presentation class. This contains the # the Vision Egg's runtime control abilities. p = Presentation(go_duration=(10.0,'seconds'),viewports=[viewport]) ####################### # Define controller # ####################### # calculate a few variables we need mid_x = screen.size[0]/2.0 mid_y = screen.size[1]/2.0 max_vel = min(screen.size[0],screen.size[1]) * 0.4 # define position as a function of time def get_target_position(t): global mid_x, mid_y, max_vel return ( max_vel*sin(0.1*2.0*pi*t) + mid_x , # x max_vel*sin(0.1*2.0*pi*t) + mid_y ) # y
# first block images ##################### ## RUNTIME CONTROL ## ##################### count = 0 while (count<1): # Create a Viewport instance (initialized just to display instructions) viewport = Viewport(screen=screen, stimuli=[introTexts[count]]) # Create an instance of the Presentation class. (Runtime control) p = Presentation(go_duration=('forever',), viewports=[viewport]) # Register Event Handlers p.parameters.handle_event_callbacks = \ [(pygame.locals.QUIT, quit), (pygame.locals.KEYDOWN, keydown), (pygame.locals.KEYUP, keyup)] count = count + 1 # # Script to show only example from targets. # def showTargets(viewport):
class VisualSpellerVE(MainloopFeedback): """ Visual Speller with six circles like the classical HexOSpell. """ # Triggers: look in Marker END_LEVEL1, END_LEVEL2 = 244, 245 # end of hex levels COPYSPELLING_FINISHED = 246 STIMULUS = [[11, 12, 13, 14, 15, 16], [21, 22, 23, 24, 25, 26]] RESPONSE = [[51, 52, 53, 54, 55, 56], [61, 62, 63, 64, 65, 66]] TARGET_ADD = 20 ERROR_ADD = 100 COUNTDOWN_STIMULI = 239 ERROR_POTENTIAL = 96 # send if error potential is classified def init(self): """ initialize parameters """ self.log_filename = "VisualSpellerVE.log" self.geometry = [0, 0, 1280, 800] ## size self.letterbox_size = (60, 60) self.osc_size = 40 self.font_size_phrase = 60 # the spelled phrase at the top self.font_size_current_letter = 80 # the spelled phrase at the top self.font_size_countdown = 150 # number during countdown self.desired_phrase = "" ## colors: self.bg_color = (0.0, 0.0, 0.0) self.phrase_color = (0.2, 0.0, 1.0) self.current_letter_color = (1.0, 0.0, 0.0) self.countdown_color = (0.2, 0.0, 1.0) self.osc_color = (1, 1, 1) self.letter_set = [ ["A", "B", "C", "D", "E"], ["F", "G", "H", "I", "J"], ["K", "L", "M", "N", "O"], ["P", "Q", "R", "S", "T"], ["U", "V", "W", "X", "Y"], ["Z", "_", ".", ",", "<"], ] self.fullscreen = False self.use_oscillator = True self.offline = True self.copy_spelling = True # in copy-spelling mode, selection of the target symbol is forced self.debug = False self.nCountdown = 5 self.nr_sequences = 6 self.randomize_sequence = True # set to False to present a fixed stimulus sequence self.min_dist = 2 # Min number of intermediate flashes bef. a flash is repeated twice self.stimulus_duration = 0.083 # 5 frames @60 Hz = 83ms flash self.interstimulus_duration = 0.1 self.animation_time = 1 self.wait_before_classify = 1.0 self.feedback_duration = 1.0 self.feedback_ErrP_duration = 1.0 self.wait_after_start = 0.0 # Countdown options self.do_animation = True self.synchronized_countdown = True if self.synchronized_countdown: self.do_animation = False self.countdown_level1 = True self.countdown_level2 = True self.countdown_shapes = {"circle": FilledCircle, "hexagon": FilledHexagon} self.countdown_shape_select = "hexagon" self.countdown_shape_color = (0.7, 0.7, 0.7) self.countdown_shape_on = True self.countdown_blinking_nr = 5 # number of pre-sequence stimuli(1 sec is approx. 5 frames at 60 Hz) self.wait_after_early_stopping = 3 # sec self.abort_trial = False self.output_per_stimulus = True self.use_ErrP_detection = False self.serialtrigger = False self.serialport = serialport.SerialPort(13) self.send_parallel_bak = self.send_parallel if self.debug: msg = "!!! YOU'RE IN DEBUG MODE! CLASSIFICATION WILL BE RANDOM OR KEYBOARD CONTROLLED !!!" self.logger.warning(msg) def pre_mainloop(self): ## logging assert len(self.log_filename) != 0 # 'log_filename' must not be empty string! logger.setLevel(logging.ERROR) handler = logging.FileHandler(self.log_filename, "w") handler.setLevel(logging.INFO) formatter = logging.Formatter("%(asctime)s: %(message)s") handler.setFormatter(formatter) self.logger.setLevel(logging.INFO) self.logger.addHandler(handler) self._nr_elements = 6 self._idx_backdoor = 5 self._init_classifier_output() self._classified_element = -1 self._classified_letter = -1 for s in self.desired_phrase: assert s in [l for ls in self.letter_set for l in ls] # invalid letters in desired phrase! self._spelled_phrase = "" self._spelled_letters = "" self._desired_letters = self.desired_phrase self._copyspelling_finished = False # if self.offline: # self.__idle() # In offline mode: set the first to-be-spelled letter self._spellerHeight = self.geometry[3] - self.letterbox_size[1] self._centerPos = (self.geometry[2] / 2.0, self._spellerHeight / 2.0) self._nr_letters = 0 for i in xrange(len(self.letter_set)): self._nr_letters += len(self.letter_set[i]) self._current_level = 1 # Index of current level self._current_sequence = 0 # Index of current sequence self._current_stimulus = 0 # Index of current stimlus self._current_countdown = self.nCountdown self.random = random.Random(clock()) self._debug_classified = None ## init states: self._state_countdown = True if not self.countdown_level1: self._state_countdown = False self._state_trial = True else: # self._state_countdown = not self.offline self._state_trial = False self._state_classify = False self._state_feedback = False self._state_abort = False ## init containers for VE elements: self._ve_elements = [] ## oscillator state: if not self.use_oscillator: self.osc_color = self.bg_color self.osc_size = 0 ## call subclass-specific pre_mainloop: self.prepare_mainloop() ## build screen elements: self.__init_screen() if self.offline: self.__idle() if self.abort_trial: """ Start listener for abort_trial event eg. """ ## delay after play (might be useful for filters...) pygame.time.wait(int(self.wait_after_start * 1000)) self.logger.info("waiting %d seconds after play." % self.wait_after_start) ## send start trigger: self.send_parallel(marker.RUN_START) self.logger.info("[TRIGGER] %d" % marker.RUN_START) ## error potential classifier: self._ErrP_classifier = None def on_interaction_event(self, data): self.logger.debug("interaction event") serial = data.get("serialtrigger", None) if serial is None: return if serial: self.logger.debug("using serial port") self.send_parallel = self.serialport.send else: self.logger.debug("using parallel port") self.send_parallel = self.send_parallel_bak def post_mainloop(self): """ Sends end marker to parallel port. """ if self.abort_trial: """ Stop listener for abort_trial event """ pass pygame.time.wait(500) self.send_parallel(marker.RUN_END) self.logger.info("[TRIGGER] %d" % marker.RUN_END) pygame.time.wait(500) self._presentation.set(quit=True) self._screen.close() def __init_screen(self): ## create screen: if not self.fullscreen: os.environ["SDL_VIDEO_WINDOW_POS"] = "%d, %d" % (self.geometry[0], self.geometry[1]) self._screen = Screen( size=(self.geometry[2], self.geometry[3]), fullscreen=self.fullscreen, bgcolor=self.bg_color, sync_swap=True ) ## create letter box on top: self._ve_letterbox = Target2D( position=(self._centerPos[0], self.geometry[3] * (1 - 0.01) - self.letterbox_size[1] / 2.0), size=(self.letterbox_size[0], self.letterbox_size[1]), color=self.phrase_color, ) self._ve_innerbox = Target2D( position=(self._centerPos[0], self.geometry[3] * (1 - 0.01) - self.letterbox_size[1] / 2.0), size=(self.letterbox_size[0] - 6, self.letterbox_size[1] - 6), color=self.bg_color, ) self._current_letter_position = ( self._centerPos[0], self.geometry[3] * (1 - 0.015) - self.letterbox_size[1] / 2.0, ) self._ve_current_letter = Text( position=self._current_letter_position, text=(len(self._desired_letters[:1]) == 0 and " " or self._desired_letters[:1]), font_size=self.font_size_current_letter, color=self.current_letter_color, anchor="center", ) self._ve_desired_letters = Text( position=(self._centerPos[0] + 5 + self.letterbox_size[0] / 2.0, self._current_letter_position[1]), text=(len(self._desired_letters[1:]) == 0 and " " or self._desired_letters[1:]), font_size=self.font_size_phrase, color=self.phrase_color, anchor="left", ) self._ve_spelled_phrase = Text( position=(self._centerPos[0] - 5 - self.letterbox_size[0] / 2.0, self._current_letter_position[1]), text=(len(self._spelled_phrase) == 0 and " " or self._spelled_phrase), font_size=self.font_size_phrase, color=self.phrase_color, anchor="right", ) # if we're in free spelling mode, we hide all text fields but # the _ve_spelled_phrase. we also need a multiline # _ve_spelled_phrase instead of the single lined one if self.offline == self.copy_spelling == False: self._spelled_phrase = " " self._ve_spelled_phrase = WrappedText( position=(0, self._current_letter_position[1]), text=(len(self._spelled_phrase) == 0 and " " or self._spelled_phrase), font_size=self.font_size_phrase, color=self.phrase_color, size=(float(self.geometry[2]), float(self.geometry[3])), ) for i in self._ve_letterbox, self._ve_innerbox, self._ve_current_letter, self._ve_desired_letters: i.set(on=False) ## add word box to elementlist: self._ve_elements.extend( [ self._ve_letterbox, self._ve_innerbox, self._ve_current_letter, self._ve_desired_letters, self._ve_spelled_phrase, ] ) ## create countdown: self._ve_countdown = Text( position=self._centerPos, text=" ", font_size=self.font_size_countdown, color=self.countdown_color, anchor="center", on=False, ) ## create countdown shapes self._ve_countdown_shape = self.countdown_shapes[self.countdown_shape_select]( radius=90, position=self._centerPos, color=self.countdown_shape_color, on=False ) ## create oscillator circle: self._ve_oscillator = FilledCircle( position=(self.osc_size / 2 + 10, self.osc_size / 2 + 10), radius=self.osc_size / 2, color=self.osc_color, on=False, ) ## create shapes and letters: self.init_screen_elements() ## add remaining elements to element list: self._ve_elements.extend([self._ve_countdown_shape, self._ve_countdown, self._ve_oscillator]) ## add elements to viewport: self._viewport = Viewport(screen=self._screen, stimuli=self._ve_elements) self._presentation = Presentation( viewports=[self._viewport], handle_event_callbacks=[(pygame.KEYDOWN, self.keyboard_input), (pygame.QUIT, self.__stop)], ) def play_tick(self): """ called every loop, if in play mode. """ self.pre_play_tick() if self._state_countdown: self.pre__countdown() self.__countdown() self.post__countdown() elif self._state_trial: self.pre__trial() self.__trial() self.post__trial() elif self._state_classify: self.pre__classify() self.__classify() self.post__classify() elif self._state_feedback: self.pre__feedback() self.__feedback() self.post__feedback() elif self._state_abort: self.__abort() self.post__abort() else: self.pre__idle() self.__idle() self.post__idle() self.post_play_tick() def __stop(self, *args): self.on_stop() def __idle(self): if self.offline and len(self._desired_letters) > 0: # add new letter: for e in xrange(len(self.letter_set)): for l in xrange(len(self.letter_set[e])): if self._desired_letters[0] == self.letter_set[e][l]: self._classified_element = e self._classified_letter = l if self.countdown_level1: self._state_countdown = True else: self._state_trial = True else: ## otherwise just wait until a new letter is sent: self._presentation.set(go_duration=(0.1, "seconds")) self._presentation.go() def __countdown(self): def blink(): i = 0 while i < self.countdown_blinking_nr: self._ve_countdown_shape.set(on=True) self._ve_countdown.set(text="%d" % self._current_countdown, on=True) self.send_parallel(self.COUNTDOWN_STIMULI) self.logger.info("[TRIGGER] %d" % self.COUNTDOWN_STIMULI) self._presentation.set(go_duration=(self.stimulus_duration, "seconds")) self._presentation.go() self._ve_countdown_shape.set(on=False) self._ve_countdown.set(on=False) self._presentation.set(go_duration=(self.interstimulus_duration, "seconds")) self._presentation.go() i = i + 1 if self._current_countdown == self.nCountdown: self.send_parallel(marker.COUNTDOWN_START) self.logger.info("[TRIGGER] %d" % marker.COUNTDOWN_START) self.set_countdown_screen() self._ve_countdown.set(on=True) self._ve_countdown_shape.set(on=self.countdown_shape_on) self._presentation.set(go_duration=(1, "seconds")) self._ve_countdown.set(text="%d" % self._current_countdown) self._presentation.go() self._current_countdown = (self._current_countdown - 1) % self.nCountdown if self.synchronized_countdown and self._current_countdown == 1: self.set_synchronized_countdown_screen() blink() self._current_countdown = self.nCountdown self.set_standard_screen() self._state_countdown = False self._state_trial = True self._ve_countdown.set(on=False) self._ve_countdown_shape.set(on=False) self._ve_countdown.set(color=self.countdown_color) if self._current_countdown == 0: # Executed only if self.synchronized_countdown = False self._current_countdown = self.nCountdown self.set_standard_screen() pygame.time.wait(10) self._state_countdown = False self._state_trial = True self._ve_countdown_shape.set(on=False) self._ve_countdown.set(on=False) self._ve_countdown.set(color=self.countdown_color) def __trial(self): if self._current_sequence == 0 and self._current_stimulus == 0: # level 1 animation when there is no countdown if self._current_level == 1 and not self.countdown_level1: if self.do_animation: self.set_countdown_screen() self.set_standard_screen() # generate random sequences: if self.randomize_sequence: self.flash_sequence = [] for _ in range(self.nr_sequences): random_flash_sequence( self, set=range(self._nr_elements), min_dist=self.min_dist, seq_len=self._nr_elements ) # or else use fixed sequence: else: self.flash_sequence = range(self._nr_elements) if self.randomize_sequence: currentStimulus = self.flash_sequence[self._current_sequence * self._nr_elements + self._current_stimulus] else: currentStimulus = self.flash_sequence[self._current_stimulus] # set stimulus: self.stimulus(currentStimulus, True) # self._ve_oscillator.set(on=True) if self.abort_trial and self.abort_trial_check(): # restart trial on abort_trial event: self._state_trial = False self._state_abort = True return # check if current stimulus is target and then send trigger: target_add = 0 if len(self._desired_letters) > 0: if self._current_level == 1: if self._desired_letters[:1] in self.letter_set[currentStimulus]: # current stimulus is target group: target_add = self.TARGET_ADD else: if currentStimulus == self._idx_backdoor: # current stimulus is backdoor: if not self._desired_letters[:1] in self.letter_set[self._classified_element]: # we are in the wrong group. backdoor is target: target_add = self.TARGET_ADD else: # current stimulus is no backdoor: if self._desired_letters[:1] == self.letter_set[self._classified_element][currentStimulus]: # current stimulus is target symbol: target_add = self.TARGET_ADD self.send_parallel(self.STIMULUS[self._current_level - 1][currentStimulus] + target_add) self.logger.info("[TRIGGER] %d" % (self.STIMULUS[self._current_level - 1][currentStimulus] + target_add)) # present stimulus: self._presentation.set(go_duration=(self.stimulus_duration, "seconds")) self._presentation.go() # reset to normal: self._ve_oscillator.set(on=False) self.stimulus(currentStimulus, False) # present interstimulus: self._presentation.set(go_duration=(self.interstimulus_duration, "seconds")) self._presentation.go() if self.debug: self.on_control_event({"cl_output": (self.random.random(), currentStimulus + 1)}) ## TODO: check here for classification !!!! if self.output_per_stimulus: # increase self._current_stimulus = (self._current_stimulus + 1) % self._nr_elements if self._current_stimulus == 0: self._current_sequence = (self._current_sequence + 1) % self.nr_sequences # check for end of trial: if self._current_sequence == 0 and self._current_stimulus == 0: # send trigger: if self._current_level == 1: self.send_parallel(self.END_LEVEL1) self.logger.info("[TRIGGER] %d" % self.END_LEVEL1) else: self.send_parallel(self.END_LEVEL2) self.logger.info("[TRIGGER] %d" % self.END_LEVEL2) # decide how to continue: self._state_trial = False self._state_classify = True else: # increase self._current_stimulus = (self._current_stimulus + 1) % self._nr_elements if self._current_stimulus == 0: self._current_sequence = (self._current_sequence + 1) % self.nr_sequences if self.check_classification(self._current_sequence + 1): self._state_trial = False self._state_classify = True pygame.time.wait(self.wait_after_early_stopping * 1000) if self._current_sequence == 0 and self._current_stimulus == 0: # send trigger: if self._current_level == 1: self.send_parallel(self.END_LEVEL1) self.logger.info("[TRIGGER] %d" % self.END_LEVEL1) else: self.send_parallel(self.END_LEVEL2) self.logger.info("[TRIGGER] %d" % self.END_LEVEL2) # decide how to continue: self._state_trial = False self._state_classify = True def check_classification(self, nr): # print self._classifier_output means = [None] * self._nr_elements minimum = maxint classified = None for ii in range(self._nr_elements): means[ii] = sum(self._classifier_output[ii]) / nr if means[ii] < minimum: minimum = means[ii] classified = ii + 1 print "\n**** Class: %d (mean=%f)\n" % (classified, means[classified - 1]) return classified def __classify(self): ## wait until all classifier outputs are received: self._presentation.set(go_duration=(self.wait_before_classify, "seconds")) self._presentation.go() if self.offline: if self._current_level == 1: classified = self._classified_element else: classified = self._classified_letter elif not self._debug_classified == None: classified = self._debug_classified self._debug_classified = None else: if self.output_per_stimulus: nClassified = sum([len(self._classifier_output[i]) for i in xrange(self._nr_elements)]) if nClassified < self._nr_elements * self.nr_sequences: pygame.time.wait(20) print "not enough classifier-outputs received! (something may be wrong)" return ## classify and set output: means = [None] * self._nr_elements minimum = maxint classified = None for ii in range(self._nr_elements): means[ii] = sum(self._classifier_output[ii]) / self.nr_sequences if means[ii] < minimum: minimum = means[ii] classified = ii print "\n**** Class: %d (mean=%f)\n" % (classified + 1, means[classified]) else: means = [None] * self._nr_elements minimum = maxint classified = None for ii in range(self._nr_elements): means[ii] = sum(self._classifier_output[ii]) / self.nr_sequences if means[ii] < minimum: minimum = means[ii] classified = ii print "\n**** Class: %d (mean=%f)\n" % (classified + 1, means[classified]) ## Reset classifier output to empty lists self._init_classifier_output() error_add = 0 ## evaluate classification: if self._current_level == 1: self._classified_element = classified if len(self._desired_letters) > 0 and not self._desired_letters[:1] in self.letter_set[classified]: # wrong group selected: error_add = self.ERROR_ADD else: self._classified_letter = classified if self._classified_letter == self._idx_backdoor: ## backdoor classified: if ( len(self._desired_letters) > 0 and self._desired_letters[:1] in self.letter_set[self._classified_element] ): # backdoor selection wrong: error_add = self.ERROR_ADD else: ## no backdoor classified: spelled_letter = self.letter_set[self._classified_element][self._classified_letter] if len(self._desired_letters) > 0 and spelled_letter != self._desired_letters[:1]: # wrong letter spelled: error_add = self.ERROR_ADD ## send response trigger: self.send_parallel(self.RESPONSE[self._current_level - 1][classified] + error_add) self.logger.info("[TRIGGER] %d" % (self.RESPONSE[self._current_level - 1][classified] + error_add)) self._state_classify = False self._state_feedback = True def __feedback(self): self._state_feedback = False ## call subclass method: self.feedback() ## check ErrP classification: if self.use_ErrP_detection: t = 0 while self._ErrP_classifier is None and t < 1000: t += 50 pygame.time.wait(50) if self._ErrP_classifier is None: print "no ErrP classifier received! " if self._ErrP_classifier: self.send_parallel(self.ERROR_POTENTIAL) self.logger.info("[TRIGGER] %d" % (self.ERROR_POTENTIAL)) ## call subclass method: if not self.countdown_level2: self.switch_level() ## update phrases: if ( (self._current_level == 2) and ( # only update, if we are at the end of level 2, self._classified_letter != self._idx_backdoor or self.copy_spelling ) and ( # if copyspelling off, we have no backdoor selected self._ErrP_classifier is None or not self._ErrP_classifier ) ): # no ErrP was detected (or ErrP detection is off) spelled_letter = "" if self.copy_spelling: ## in copy spelling we force the desired letter to be spelled if len(self._desired_letters) > 0: spelled_letter = self._desired_letters[:1] else: print "??? moved beyond desired phrase in copy spelling ???" else: spelled_letter = self.letter_set[self._classified_element][self._classified_letter] ## update desired phrase: if len(self._desired_letters) > 0: if spelled_letter == self._desired_letters[:1]: # correct letter spelled: self._desired_letters = self._desired_letters[1:] # remove first letter else: # wrong letter spelled: if spelled_letter == "<": self._desired_letters = self._spelled_phrase[-1:] + self._desired_letters else: self._desired_letters = "<" + self._desired_letters if len(self._desired_letters) == 0: self._copyspelling_finished = True ## update spelled phrase: self._spelled_letters += spelled_letter if spelled_letter == "<": self._spelled_phrase = self._spelled_phrase[:-1] else: self._spelled_phrase += spelled_letter ## update screen phrases: self.logger.info("Current Phrase:") self.logger.info(self._spelled_phrase) self._ve_spelled_phrase.set(text=(len(self._spelled_phrase) == 0 and " " or self._spelled_phrase)) self._ve_current_letter.set(text=(len(self._desired_letters[:1]) == 0 and " " or self._desired_letters[:1])) self._ve_desired_letters.set( text=(len(self._desired_letters[1:]) == 0 and " " or self._desired_letters[1:]) ) if self.use_ErrP_detection and self._ErrP_classifier: self._state_trial = True else: if self._current_level == 1: # continue with level2 trial: if self.countdown_level2: self._state_countdown = True else: self._state_trial = True elif not self.offline: # start countdown if self.countdown_level1: self._state_countdown = True else: self._state_trial = True # set new level: self._current_level = 3 - self._current_level ## reset ErrP_classifier: self._ErrP_classifier = None # check copyspelling: if self._copyspelling_finished: self._copyspelling_finished = False self.on_control_event({"print": 0}) # print desired phrase self.on_control_event({"print": 1}) # print spelled phrase self.on_control_event({"print": 2}) # print all spelled letters self.send_parallel(self.COPYSPELLING_FINISHED) self.logger.info("[TRIGGER] %d" % (self.COPYSPELLING_FINISHED)) pygame.time.wait(50) def __abort(self): # play warning sound def sine_array_onecycle(hz, peak, sample_rate): length = sample_rate / float(hz) omega = NP.pi * 2 / length xvalues = NP.arange(int(length)) * omega return peak * NP.sin(xvalues) def sine_array(hz, peak, samples_rate): return NP.resize(sine_array_onecycle(hz, peak, sample_rate), (sample_rate,)) sample_rate = 44100 pygame.mixer.init(sample_rate, -16, 2) # 44.1kHz, 16-bit signed, stereo f = sine_array(8000, 1, sample_rate) f = NP.array(zip(f, f)) sound = pygame.sndarray.make_sound(f) channel = sound.play(-1) channel.set_volume(0.2, 0.2) pygame.time.delay(1000) sound.stop() if self._current_level == 1 and self.countdown_level1: self._state_countdown = True elif self._current_level == 2 and self.countdown_level2: self._state_countdown = True else: self._state_trial = True self._init_classifier_output() def _init_classifier_output(self): ## Empty lists self._classifier_output = [list() for _ in xrange(self._nr_elements)] def abort_trial_check(self): """ Check if event is an abort trial event """ return False def keyboard_input(self, event): if event.key == pygame.K_ESCAPE: self.on_stop() elif event.key == pygame.K_KP_ENTER: self.on_control_event({"print": 0}) # print desired phrase self.on_control_event({"print": 1}) # print spelled phrase self.on_control_event({"print": 2}) # print all spelled letters elif event.key == pygame.K_DELETE: # The DELETE key empties the spelled text shown this works # only in free spelling mode (i.e. offline and copy_spelling # are set to False) if self.offline == self.copy_spelling == False: self.logger.info("Clearing Text.") self._spelled_phrase = " " elif self.debug: if ( (event.key >= pygame.K_a and event.key <= pygame.K_z) or (event.key == pygame.K_LESS) or (event.key == pygame.K_PERIOD) or (event.key == pygame.K_COMMA) ): self.on_control_event({"new_letter": chr(event.key).upper()}) elif event.key == pygame.K_MINUS: self.on_control_event({"new_letter": chr(pygame.K_UNDERSCORE)}) elif event.key == pygame.K_BACKSPACE: self.on_control_event({"new_letter": chr(pygame.K_LESS)}) elif event.key == pygame.K_SPACE: self.on_control_event({"new_letter": chr(pygame.K_UNDERSCORE)}) elif event.key == pygame.K_UP and self.use_ErrP_detection: self.on_control_event({"cl_output": (1, 7)}) elif event.key == pygame.K_DOWN and self.use_ErrP_detection: self.on_control_event({"cl_output": (0, 7)}) if not self.offline: if event.key >= pygame.K_0 and event.key <= pygame.K_5: self._debug_classified = int(chr(event.key)) elif event.key >= pygame.K_KP0 and event.key <= pygame.K_KP5: self._debug_classified = int(chr(event.key - 208)) def on_control_event(self, data): self.logger.info("[CONTROL_EVENT] %s" % str(data)) if data.has_key(u"cl_output"): # classification output was sent: score_data = data[u"cl_output"] cl_out = score_data[0] iSubstim = int(score_data[1]) # evt auch "Subtrial" if iSubstim in range(1, 7): self._classifier_output[iSubstim - 1].append(cl_out) elif self.use_ErrP_detection: self._ErrP_classifier = cl_out elif data.has_key("new_letter"): # get new letter to spell: self._desired_letters += data["new_letter"] self._ve_current_letter.set(text=(len(self._desired_letters[:1]) == 0 and " " or self._desired_letters[:1])) self._ve_desired_letters.set( text=(len(self._desired_letters[1:]) == 0 and " " or self._desired_letters[1:]) ) elif data.has_key(u"print"): if data[u"print"] == 0: self.logger.info("[DESIRED_PHRASE] %s" % self.desired_phrase) elif data[u"print"] == 1: self.logger.info("[SPELLED_PHRASE] %s" % self._spelled_phrase) elif data[u"print"] == 2: self.logger.info("[SPELLED_LETTERS] %s" % self._spelled_letters) """ ========================== == METHODS TO OVERLOAD: == ========================== """ def init_screen_elements(self): """ overwrite this function in subclass. """ pass def prepare_mainloop(self): """ overwrite this function in subclass. """ pass def set_countdown_screen(self): """ set screen how it should look during countdown. overwrite this function in subclass. """ pass def set_standard_screen(self): """ set screen elements to standard state. overwrite this function in subclass. """ pass def set_synchronized_countdown_screen(self): """ set screen elements to for the synchronized countdown. overwrite this function in subclass. """ pass def stimulus(self, i_element, on=True): """ turn on/off the stimulus elements and turn off/on the normal elements. overwrite this function in subclass. """ pass def feedback(self): """ set screen how it should look during feedback presentation. overwrite this function in subclass. """ pass def switch_level(self): """ overwrite this function in subclass. """ pass def pre_play_tick(self): pass def post_play_tick(self): pass def pre__countdown(self): pass def post__countdown(self): pass def pre__trial(self): pass def post__trial(self): pass def pre__classify(self): pass def post__classify(self): pass def pre__feedback(self): pass def post__feedback(self): pass def pre__idle(self): pass def post__idle(self): pass def post__abort(self): pass
def aplicacion(): global p,inten,coord pos=[0.4,0.5,0.6,0.7,0.8] pos2=[1.3,1.4,1.5,1.6,1.7,1.8] rellenar() shuffle(coord) i = len(coord)-1 target.parameters.position = coord[i][:2] (xpos,ypos)=target.parameters.position x=xpos-screen.size[0]/2 y=ypos-screen.size[1]/2 anrad=math.atan2(y, x) angrad=math.degrees(anrad) if angrad>=0: if angrad<=90: orientacion=-45 xx=2.0 yy=2.0 else: orientacion=-135 xx=-2.0 yy=2.0 else: aux=angrad*(-1) if aux<=90: orientacion=45 xx=2.0 yy=-2.0 else: orientacion=135 xx=-2.0 yy=-2.0 fixpoint.parameters.position=((screen.size[0]/2.0)+xx, (screen.size[1]/2.0)+yy) fixpoint.parameters.orientation=orientacion viewport = Viewport(screen=screen, stimuli=[fixpoint,fixcirc]) p = Presentation(go_duration=(1.0,'seconds'),viewports=[viewport]) p.parameters.handle_event_callbacks = [(pygame.locals.KEYDOWN, keydown), (pygame.locals.KEYUP, keyup), (pygame.locals.QUIT, quit_app)] p.add_controller(None, None, FunctionController(during_go_func=settings)) #winsound.PlaySound('instruccion',winsound.SND_FILENAME) p.go() while len(coord)!= 0: if end: break i = len(coord)-1 target.parameters.position = coord[i][:2] dur=pos[random.randrange(0,4,1)] (xpos,ypos)=target.parameters.position x=xpos-screen.size[0]/2 y=ypos-screen.size[1]/2 anrad=math.atan2(y, x) angrad=math.degrees(anrad) #fixpoint.parameters.orientation=(-angrad) if angrad>=0: if angrad<=90: orientacion=-45 xx=2.0 yy=2.0 else: orientacion=-135 xx=-2.0 yy=2.0 else: aux=angrad*(-1) if aux<=90: orientacion=45 xx=2.0 yy=-2.0 else: orientacion=135 xx=-2.0 yy=-2.0 fixpoint.parameters.position=((screen.size[0]/2.0)+xx, (screen.size[1]/2.0)+yy) fixpoint.parameters.orientation=orientacion viewport = Viewport(screen=screen, stimuli=[fixpoint,fixcirc]) p = Presentation(go_duration=(dur,'seconds'),viewports=[viewport]) p.parameters.handle_event_callbacks = [ (pygame.locals.QUIT, quit_app)] p.add_controller(None, None, FunctionController(during_go_func=settings)) p.go() inten = coord[i][-1] target.parameters.color = (1.0,1.0,1.0,inten) #Se muestra el estimulo Duracion 0.3 segundos viewport = Viewport(screen=screen, stimuli=[target,fixpoint,fixcirc]) p = Presentation(go_duration=(0.3,'seconds'),viewports=[viewport]) p.parameters.handle_event_callbacks = [ (pygame.locals.QUIT, quit_app)] p.add_controller(None, None, FunctionController(during_go_func=settings)) p.go() target.parameters.color = (0.0,0.0,0.0,1.0) #Desaparece el estimulo tiempo para registrar viewport = Viewport(screen=screen, stimuli=[target,fixpoint,fixcirc]) dur2=pos[random.randrange(0,4,1)] p = Presentation(go_duration=(dur2,'seconds'),viewports=[viewport]) p.parameters.handle_event_callbacks = [(pygame.locals.KEYDOWN, keydown), (pygame.locals.KEYUP, keyup), (pygame.locals.QUIT, quit_app)] p.add_controller(None, None, FunctionController(during_go_func=settings)) p.go() coord.pop()
##################### ## RUNTIME CONTROL ## ##################### count = 0 while (count<len(introTexts)): # DJ CHANGE 4/23/12 # Create a Viewport instance (initialized just to display instructions) viewport = Viewport(screen=screen, stimuli=[introTexts[count], introTexts_bottomline[count]]) # Create an instance of the Presentation class. (Runtime control) # note that timeBetweenBlocks/2 is used here to match the time of each between-block frame. p = Presentation(go_duration=(timeBetweenBlocks/2,'seconds'), viewports=[viewport]) # Register Event Handlers so we can speed things up or quit early if we need to p.parameters.handle_event_callbacks = \ [(pygame.locals.QUIT, quit), (pygame.locals.KEYDOWN, keydown), (pygame.locals.KEYUP, keyup)] p.between_presentations() p.go() count = count+1 ##################################################################### ## Here the intro text is complete, entering the image block loop ## #####################################################################
) instructions_attendSCENE = Text( text="Attend to SCENES", font_size=32, color=(1, 1, 1), anchor="center", position=(screen.size[0] / 2, screen.size[1] / 2), ) cur_time = Text(text="", font_size=15, color=(0.75, 0.75, 0.75), anchor="lowerleft", position=(0, 0)) viewport_instructions = Viewport(screen=screen, stimuli=[instructions, cur_time]) attend_face = Viewport(screen=screen, stimuli=[instructions_attendFACE]) attend_scene = Viewport(screen=screen, stimuli=[instructions_attendSCENE]) p1 = Presentation(go_duration=("forever",), viewports=[viewport_instructions]) p1.add_controller(None, None, FunctionController(during_go_func=displayTime)) p1.parameters.handle_event_callbacks = [(pygame.locals.KEYDOWN, waitForTrigger)] # setup main experimental loop loadStims = 0 wrote_response = 0 stimulus = TextureStimulus( anchor="center", size=stimuli_size, position=(screen.size[0] / 2.0, screen.size[1] / 2.0), texture_min_filter=gl.GL_LINEAR, shrink_texture_ok=1, # PW 2012/11/26 mipmaps_enabled=False,
# Set the background color to white (RGBA). screen.parameters.bgcolor = (1.0, 1.0, 1.0, 1.0) # Create an instance of the Target2D class with appropriate parameters. target = Target2D( size=(25.0, 10.0), color=(0.0, 0.0, 0.0, 1.0), # Set the target color (RGBA) black orientation=-45.0) # Create a Viewport instance viewport = Viewport(screen=screen, stimuli=[target]) # Create an instance of the Presentation class. This contains the # the Vision Egg's runtime control abilities. p = Presentation(go_duration=(10.0, 'seconds'), viewports=[viewport]) ####################### # Define controller # ####################### # calculate a few variables we need mid_x = screen.size[0] / 2.0 mid_y = screen.size[1] / 2.0 max_vel = min(screen.size[0], screen.size[1]) * 0.4 # define position as a function of time def get_target_position(t): global mid_x, mid_y, max_vel return (
VisionEgg.start_default_logging() VisionEgg.watch_exceptions() from VisionEgg.Core import * from VisionEgg.FlowControl import Presentation from VisionEgg.Textures import * import pygame.image import OpenGL.GL as gl filename = os.path.join(VisionEgg.config.VISIONEGG_SYSTEM_DIR, "data", "visionegg.bmp") pygame_surface = pygame.image.load(filename) texture = Texture(pygame_surface) screen = get_default_screen() # Create the instance of TextureStimulus stimulus = TextureStimulus(texture=texture, position=(screen.size[0] / 2.0, screen.size[1] / 2.0), anchor='center', size=texture.size, mipmaps_enabled=0, texture_min_filter=gl.GL_LINEAR, shrink_texture_ok=1) viewport = Viewport(screen=screen, stimuli=[stimulus]) p = Presentation(go_duration=(5.0, 'seconds'), viewports=[viewport]) p.go()
from VisionEgg.Core import * from VisionEgg.FlowControl import Presentation, FunctionController from VisionEgg.Textures import * import math, os max_speed = 100.0 # degrees per second def angle_as_function_of_time(t): return max_speed*math.cos(t) def contrast_as_function_of_time(t): return abs(math.cos(2*math.pi*t*0.2)) filename = os.path.join(config.VISIONEGG_SYSTEM_DIR,"data","panorama.jpg") texture = Texture(filename) screen = get_default_screen() projection = SimplePerspectiveProjection(fov_x=90.0) stimulus = SpinningDrum(texture=texture,shrink_texture_ok=1) viewport = Viewport(screen=screen, size=screen.size, projection=projection, stimuli=[stimulus]) p = Presentation(go_duration=(10.0,'seconds'),viewports=[viewport]) p.add_controller(stimulus,'angular_position', FunctionController(during_go_func=angle_as_function_of_time)) p.add_controller(stimulus,'contrast', FunctionController(during_go_func=contrast_as_function_of_time)) p.go()
def keyup(event): global up, down, left, right if event.key == pygame.locals.K_UP: up = 0 elif event.key == pygame.locals.K_DOWN: down = 0 elif event.key == pygame.locals.K_RIGHT: right = 0 elif event.key == pygame.locals.K_LEFT: left = 0 # Create an instance of the Presentation class. This contains the # the Vision Egg's runtime control abilities. p = Presentation(go_duration=('forever', ), viewports=[viewport]) def quit(event): p.parameters.go_duration = (0, 'frames') p.parameters.handle_event_callbacks = [(pygame.locals.QUIT, quit), (pygame.locals.KEYDOWN, keydown), (pygame.locals.KEYUP, keyup)] ############################################################# # Connect the controllers with the variables they control # ############################################################# p.add_controller(None, None,
"Error: Use MPEG file as command line argument - Press Esc to quit", position=(screen.size[0] / 2, screen.size[1]), anchor='top', font_size=24, color=(1.0, 0.0, 0.0)) text2 = Text( text="(If you have a free MPEG to contribute, it could go here.)", position=(screen.size[0] / 2, screen.size[1] / 2), anchor='center', font_size=20, color=(1.0, 1.0, 1.0)) viewport = Viewport(screen=screen, stimuli=[text, text2]) p = Presentation( go_duration=('forever', ), viewports=[viewport], handle_event_callbacks=[(pygame.locals.QUIT, quit), (pygame.locals.KEYDOWN, keydown)], ) p.go() sys.exit(1) movie = pygame.movie.Movie(filename) width, height = movie.get_size() scale_x = screen.size[0] / float(width) scale_y = screen.size[1] / float(height) scale = min(scale_x, scale_y) # maintain aspect ratio # create pygame surface (buffer to draw uncompressed movie data into) pygame_surface = pygame.surface.Surface((width, height))
from VisionEgg.Gratings import * import VisionEgg.Daq from VisionEgg.DaqLPT import * # Normal stuff (from grating demo): screen = get_default_screen() stimulus = SinGrating2D(on = 1, # turn grating is off when not in go loop position = ( screen.size[0]/2.0, screen.size[1]/2.0 ), anchor = 'center', size = ( 300.0 , 300.0 ), spatial_freq = 10.0 / screen.size[0], temporal_freq_hz = 5.0, orientation = 45.0 ) viewport = Viewport( screen=screen, stimuli=[stimulus] ) p = Presentation(go_duration=(5.0,'seconds'), trigger_go_if_armed=0, # wait for trigger viewports=[viewport]) # Stimulus on controller stimulus_on_controller = ConstantController(during_go_value=0,between_go_value=1) # Create a trigger input controller trigger_in_controller = LPTTriggerInController() # Add the trigger output controller to the presentation's list of controllers p.add_controller(stimulus,'on',stimulus_on_controller) p.add_controller(p,'trigger_go_if_armed',trigger_in_controller) # Go! p.go()
pygame.locals.K_EQUALS]: gamma_scale += 0.05 do_gamma() elif event.key in [pygame.locals.K_KP_MINUS, pygame.locals.K_MINUS]: gamma_scale -= 0.05 do_gamma() def do_gamma(): global gamma_scale, text2 r = (np.arange(256)*256*gamma_scale).astype('i') g = r b = r worked = pygame.display.set_gamma_ramp(r,g,b) if worked: text2.parameters.text = "set_gamma_ramp(r,g,b): success" else: text2.parameters.text = "set_gamma_ramp(r,g,b): failure" do_gamma() # set gamma once initially handle_event_callbacks = [(pygame.locals.QUIT, quit), (pygame.locals.KEYDOWN, keydown)] # Create an instance of the Presentation class p = Presentation(viewports=[viewport], handle_event_callbacks=handle_event_callbacks) # Go! p.run_forever()
# default strategy strategy = None trial = 1 # STIMULI # Fixation Cross fixText, fixCross = printWord(screen, "*", 120, (255, 255, 255)) errorText, errorPort = printWord(screen, "X", 120, (1.0, 0.1, 0.1)) print "PRESS SPACE TO START" pause = Presentation(go_duration=("forever",), viewports=[fixCross]) pause.parameters.handle_event_callbacks = [(pygame.locals.KEYDOWN, pause_handler)] pause.go() problemQ = [] while len(mag_problems): if problemQ: stim = problemQ[2] n1 = problemQ[0] n2 = problemQ[1] else: p = mag_problems.pop(0) n1 = p[0] n2 = p[1]
def __init_screen(self): ## create screen: if not self.fullscreen: os.environ['SDL_VIDEO_WINDOW_POS'] = '%d, %d' % (self.geometry[0], self.geometry[1]) self._screen = Screen(size=(self.geometry[2], self.geometry[3]), fullscreen=self.fullscreen, bgcolor=self.bg_color, sync_swap=True) ## create letter box on top: self._ve_letterbox = Target2D(position=(self._centerPos[0], self.geometry[3] * (1 - 0.01) - self.letterbox_size[1] / 2.), size=(self.letterbox_size[0], self.letterbox_size[1]), color=self.phrase_color) self._ve_innerbox = Target2D(position=(self._centerPos[0], self.geometry[3] * (1 - 0.01) - self.letterbox_size[1] / 2.), size=(self.letterbox_size[0] - 6, self.letterbox_size[1] - 6), color=self.bg_color) self._current_letter_position = (self._centerPos[0], self.geometry[3] * (1 - 0.015) - self.letterbox_size[1] / 2.) self._ve_current_letter = Text( position=self._current_letter_position, text=(len(self._desired_letters[:1]) == 0 and " " or self._desired_letters[:1]), font_size=self.font_size_current_letter, color=self.current_letter_color, anchor='center') self._ve_desired_letters = Text( position=(self._centerPos[0] + 5 + self.letterbox_size[0] / 2., self._current_letter_position[1]), text=(len(self._desired_letters[1:]) == 0 and " " or self._desired_letters[1:]), font_size=self.font_size_phrase, color=self.phrase_color, anchor='left') self._ve_spelled_phrase = Text( position=(self._centerPos[0] - 5 - self.letterbox_size[0] / 2., self._current_letter_position[1]), text=(len(self._spelled_phrase) == 0 and " " or self._spelled_phrase), font_size=self.font_size_phrase, color=self.phrase_color, anchor='right') # if we're in free spelling mode, we hide all text fields but # the _ve_spelled_phrase. we also need a multiline # _ve_spelled_phrase instead of the single lined one if self.offline == self.copy_spelling == False: self._spelled_phrase = " " self._ve_spelled_phrase = WrappedText( position=(0, self._current_letter_position[1]), text=(len(self._spelled_phrase) == 0 and " " or self._spelled_phrase), font_size=self.font_size_phrase, color=self.phrase_color, size=(float(self.geometry[2]), float(self.geometry[3]))) for i in self._ve_letterbox, self._ve_innerbox, self._ve_current_letter, self._ve_desired_letters: i.set(on=False) ## add word box to elementlist: self._ve_elements.extend([ self._ve_letterbox, self._ve_innerbox, self._ve_current_letter, self._ve_desired_letters, self._ve_spelled_phrase ]) ## create countdown: self._ve_countdown = Text(position=self._centerPos, text=" ", font_size=self.font_size_countdown, color=self.countdown_color, anchor='center', on=False) ## create countdown shapes self._ve_countdown_shape = self.countdown_shapes[ self.countdown_shape_select](radius=90, position=self._centerPos, color=self.countdown_shape_color, on=False) ## create oscillator circle: self._ve_oscillator = FilledCircle(position=(self.osc_size / 2 + 10, self.osc_size / 2 + 10), radius=self.osc_size / 2, color=self.osc_color, on=False) ## create shapes and letters: self.init_screen_elements() ## add remaining elements to element list: self._ve_elements.extend([ self._ve_countdown_shape, self._ve_countdown, self._ve_oscillator ]) ## add elements to viewport: self._viewport = Viewport(screen=self._screen, stimuli=self._ve_elements) self._presentation = Presentation(viewports=[self._viewport], handle_event_callbacks=[ (pygame.KEYDOWN, self.keyboard_input), (pygame.QUIT, self.__stop) ])
def __init_screen(self): ## create screen: if not self.fullscreen: os.environ["SDL_VIDEO_WINDOW_POS"] = "%d, %d" % (self.geometry[0], self.geometry[1]) self._screen = Screen( size=(self.geometry[2], self.geometry[3]), fullscreen=self.fullscreen, bgcolor=self.bg_color, sync_swap=True ) ## create letter box on top: self._ve_letterbox = Target2D( position=(self._centerPos[0], self.geometry[3] * (1 - 0.01) - self.letterbox_size[1] / 2.0), size=(self.letterbox_size[0], self.letterbox_size[1]), color=self.phrase_color, ) self._ve_innerbox = Target2D( position=(self._centerPos[0], self.geometry[3] * (1 - 0.01) - self.letterbox_size[1] / 2.0), size=(self.letterbox_size[0] - 6, self.letterbox_size[1] - 6), color=self.bg_color, ) self._current_letter_position = ( self._centerPos[0], self.geometry[3] * (1 - 0.015) - self.letterbox_size[1] / 2.0, ) self._ve_current_letter = Text( position=self._current_letter_position, text=(len(self._desired_letters[:1]) == 0 and " " or self._desired_letters[:1]), font_size=self.font_size_current_letter, color=self.current_letter_color, anchor="center", ) self._ve_desired_letters = Text( position=(self._centerPos[0] + 5 + self.letterbox_size[0] / 2.0, self._current_letter_position[1]), text=(len(self._desired_letters[1:]) == 0 and " " or self._desired_letters[1:]), font_size=self.font_size_phrase, color=self.phrase_color, anchor="left", ) self._ve_spelled_phrase = Text( position=(self._centerPos[0] - 5 - self.letterbox_size[0] / 2.0, self._current_letter_position[1]), text=(len(self._spelled_phrase) == 0 and " " or self._spelled_phrase), font_size=self.font_size_phrase, color=self.phrase_color, anchor="right", ) # if we're in free spelling mode, we hide all text fields but # the _ve_spelled_phrase. we also need a multiline # _ve_spelled_phrase instead of the single lined one if self.offline == self.copy_spelling == False: self._spelled_phrase = " " self._ve_spelled_phrase = WrappedText( position=(0, self._current_letter_position[1]), text=(len(self._spelled_phrase) == 0 and " " or self._spelled_phrase), font_size=self.font_size_phrase, color=self.phrase_color, size=(float(self.geometry[2]), float(self.geometry[3])), ) for i in self._ve_letterbox, self._ve_innerbox, self._ve_current_letter, self._ve_desired_letters: i.set(on=False) ## add word box to elementlist: self._ve_elements.extend( [ self._ve_letterbox, self._ve_innerbox, self._ve_current_letter, self._ve_desired_letters, self._ve_spelled_phrase, ] ) ## create countdown: self._ve_countdown = Text( position=self._centerPos, text=" ", font_size=self.font_size_countdown, color=self.countdown_color, anchor="center", on=False, ) ## create countdown shapes self._ve_countdown_shape = self.countdown_shapes[self.countdown_shape_select]( radius=90, position=self._centerPos, color=self.countdown_shape_color, on=False ) ## create oscillator circle: self._ve_oscillator = FilledCircle( position=(self.osc_size / 2 + 10, self.osc_size / 2 + 10), radius=self.osc_size / 2, color=self.osc_color, on=False, ) ## create shapes and letters: self.init_screen_elements() ## add remaining elements to element list: self._ve_elements.extend([self._ve_countdown_shape, self._ve_countdown, self._ve_oscillator]) ## add elements to viewport: self._viewport = Viewport(screen=self._screen, stimuli=self._ve_elements) self._presentation = Presentation( viewports=[self._viewport], handle_event_callbacks=[(pygame.KEYDOWN, self.keyboard_input), (pygame.QUIT, self.__stop)], )
initial_controller=ConstantController(during_go_value=(10,'seconds')) ) go_controller = tcp_listener.create_tcp_controller( tcp_name="go", initial_controller=ConstantController(during_go_value=0) ) # Create the instance SinGrating with appropriate parameters stimulus = SinGrating2D(anchor='center') # Create a viewport (with default pixel coordinate system) # with stimulus viewport = Viewport( screen=screen, stimuli=[stimulus] ) # Create an instance of the Presentation class p = Presentation(viewports=[viewport],check_events=1) # Register the controller functions, connecting them with the parameters they control p.add_controller(None,None, tcp_listener) # Actually listens to the TCP socket p.add_controller(stimulus,'on', on_controller) p.add_controller(stimulus,'contrast', contrast_controller) p.add_controller(stimulus,'position', center_controller) p.add_controller(stimulus,'size', size_controller) p.add_controller(stimulus,'spatial_freq', spatial_freq_controller) p.add_controller(stimulus,'temporal_freq_hz', temporal_freq_controller) p.add_controller(stimulus,'phase_at_t0', phase_controller) p.add_controller(stimulus,'orientation', orientation_controller) p.add_controller(stimulus,'num_samples', num_samples_controller) p.add_controller(stimulus,'bit_depth', bit_depth_controller) p.add_controller(p,'go_duration', go_duration_controller) p.add_controller(p,'enter_go_loop', go_controller)
#default strategy strategy = None trial = 1 #STIMULI #Fixation Cross fixText, fixCross = printWord(screen, '*', 120, (255, 255, 255)) errorText, errorPort = printWord(screen, 'X', 120, (1., .1, .1)) print "PRESS SPACE TO START" pause = Presentation(go_duration=('forever', ), viewports=[fixCross]) pause.parameters.handle_event_callbacks = [(pygame.locals.KEYDOWN, pause_handler)] pause.go() problemQ = [] while len(mag_problems): if problemQ: stim = problemQ[2] n1 = problemQ[0] n2 = problemQ[1] else: p = mag_problems.pop(0) n1 = p[0]
def __init_presentation(self): """ Provide a standard presentation object. """ self.presentation = Presentation( handle_event_callbacks=self._event_handlers)
##################################### # Initialize OpenGL window/screen # ##################################### screen = get_default_screen() ###################################### # Create sinusoidal grating object # ###################################### stimulus = SinGrating2D(position = ( screen.size[0]/2.0, screen.size[1]/2.0 ), anchor = 'center', size = ( 300.0 , 300.0 ), spatial_freq = 10.0 / screen.size[0], # units of cycles/pixel temporal_freq_hz = 1.0, orientation = 45.0 ) ############################################################### # Create viewport - intermediary between stimuli and screen # ############################################################### viewport = Viewport( screen=screen, stimuli=[stimulus] ) ######################################## # Create presentation object and go! # ######################################## p = Presentation(go_duration=(5.0,'seconds'),viewports=[viewport]) p.go()
class VisionEggView(object): """ This class handles VisionEgg internals and the creation of common/standard stimuli like centered words, a fixation cross or a countdown. Inherit this and pass the type to VisionEggFeedback for customization. """ def __init__(self): self.__init_attributes() def __init_attributes(self): """ Setup internal attributes. """ self._logger = logging.getLogger('VisionEggView') self._logger.addHandler(logging.FileHandler('log')) self._screen_acquired = False self._viewports = [] def set_trigger_function(self, trigger): self._trigger = trigger def set_event_handlers(self, event_handlers): """ Set pygame/VisionEgg event handler function. """ self._event_handlers = event_handlers def set_iterator_semaphore(self, flag): """ Specify the object to be used as semaphore for iterators. See L{Switcherator} for more. """ self._iter = lambda it: Switcherator(flag, it) def update_parameters(self, **kwargs): """ Apply new parameters set from pyff. """ for k, v in kwargs.iteritems(): setattr(self, '_' + k, v) if self._screen_acquired: self.reinit() def acquire(self): """ Allow L{update_parameters} initialize VisionEgg. """ self._screen_acquired = True def reinit(self): """ Initialize VisionEgg objects. """ self.__init_screen() self.__init_presentation() self.__init_viewports() self.init() self.__init_text() def init(self): """ Overload this for additional custom VisionEgg initialization. """ pass def __init_screen(self): """ Create the VisionEgg Screen object using the pyff configuration parameters 'fullscreen' and 'geometry' and the font and background colors according to parameters 'font_color_name' and 'bg_color'. """ params = {'fullscreen': self._fullscreen, 'sync_swap': True} if not self._fullscreen: os.environ['SDL_VIDEO_WINDOW_POS'] = '%d, %d' % (self._geometry[0], self._geometry[1]) params['size'] = self._geometry[2:] self.screen = Screen(**params) self._set_bg_color() self._set_font_color() def __init_presentation(self): """ Provide a standard presentation object. """ self.presentation = Presentation( handle_event_callbacks=self._event_handlers) def __init_viewports(self): """ Provide a standard viewport. """ self._standard_viewport = Viewport(screen=self.screen) self.add_viewport(self._standard_viewport) def __init_text(self): """ Provide a text in the screen center for standard stimuli and fixation cross etc. """ sz = self.screen.size self._center_text = self.add_color_word(position=(sz[0] / 2., sz[1] / 2.), font_size=self._font_size) def add_viewport(self, viewport): """ Add an additional custom viewport object to the list of viewports. """ self._viewports.append(viewport) self.presentation.set(viewports=self._viewports) def clear_stimuli(self): """ Remove all existing stimuli in the standard viewport. """ self.set_stimuli() def add_stimuli(self, *stimuli): """ Add additional custom stimulus objects to the list of stimuli. TextList instances need their own Viewport, as they consist of multiple stimulus objects that are deleted everytime they change, and so the Viewport needs to have a reference to the containing TextList, otherwise they get lost. """ text_lists = filter(lambda s: isinstance(s, TextList), stimuli) if text_lists: for text in text_lists: self.add_viewport(Viewport(screen=self.screen, stimuli=text)) stimuli = filter(lambda s: not isinstance(s, TextList), stimuli) stimuli = self._standard_viewport.parameters.stimuli + list(stimuli) if stimuli: self.set_stimuli(*stimuli) def set_stimuli(self, *stimuli): """ Set the list of stimulus objects. """ self._standard_viewport.set(stimuli=list(stimuli)) def add_text_stimulus(self, text, font_size=None, **kw): if not kw.has_key('anchor'): kw['anchor'] = 'center' font_size = font_size or self._font_size txt = VisionEgg.Text.Text(text=text, font_size=font_size, **kw) self.add_stimuli(txt) return txt def add_color_word(self, text='', font_size=None, **kw): font_size = font_size or self._font_size txt = ColorWord(text=text, symbol_size=font_size, **kw) self.add_stimuli(txt) return txt def add_image_stimulus(self, **kw): if not kw.has_key('anchor'): kw['anchor'] = 'center' img = TextureStimulus(**kw) self.add_stimuli(img) return img def _create_color(self, name): try: if isinstance(name, tuple): return Color(*name).normalize() else: return Color(str(name)).normalize() except ValueError: self._logger.warn('No such pygame.Color: %s' % str(name)) def _set_font_color(self): """ Set the standard font color by pygame name. """ self._font_color = (self._create_color(self._font_color_name) or Color(1, 1, 1, 255).normalize()) def _set_bg_color(self): """ Set the standard background color by pygame name. """ c = (self._create_color(self._bg_color) or Color(0, 0, 0, 255).normalize()) self.screen.set(bgcolor=c) def present_frames(self, num_frames): """ Launch the presentation main loop for a given number of frames. """ self.presentation.set(go_duration=(num_frames, 'frames')) self.presentation.go() def present(self, sec): self.presentation.set(go_duration=(sec, 'seconds')) self.presentation.go() def update(self): """ Repaint the canvas for one frame to update changed stimuli. """ self.present_frames(1) def center_word(self, text, color=None): """ Set the standard word in the screen center. """ self._center_text.set(text=text) self._center_text.set(colors=color or (self._font_color for l in self._center_text)) def clear_center_word(self): """ Remove the center word from the screen. """ self.center_word('') self.update() def present_center_word(self, text, seconds, color=None): self.center_word(text, color) self.present(seconds) self.clear_center_word() def ask(self, question=True): """ Loop indefinitely until answered() is called. If question is True, a question mark is shown in the center. """ if question: self.center_word('?') self.presentation.run_forever() self.presentation.set(quit=False) self.clear_center_word() def answered(self): """ Abort the current presentation (usually the question mark) after subject input. For thread safety, the screen shouldn't be changed here. """ self.presentation.set(quit=True) def show_fixation_cross(self): """ Display the pyff parameter 'fixation_cross_symbol' for the period of time given by pyff parameter 'fixation_cross_time'. """ self.center_word(self._fixation_cross_symbol) self._trigger(marker.FIXATION_START, wait=True) self.present(self._fixation_cross_time) self._trigger(marker.FIXATION_END, wait=True) def countdown(self): """ Display a countdown according to pyff parameters 'countdown_start' and 'countdown_symbol_duration'. """ self._trigger(marker.COUNTDOWN_START, wait=True) for i in self._iter(reversed(xrange(self._countdown_start + 1))): self.center_word(str(i)) self.present(self._countdown_symbol_duration) self._trigger(marker.COUNTDOWN_END, wait=True) self.clear_center_word() def close(self): """ Shut down the screen. """ self._screen_acquired = False self.screen.close() def quit(self): """ Stop the presentation. """ self.presentation.set(quit=True) self.presentation.set(go_duration=(1, 'frames'))