def drawLines(windowSize, gap, bs): linesPositions = np.empty([2, 2], object) linesPositions[0, 0] = (-windowSize[0] / float(2), windowSize[1] / float(2) - 2 * gap - cardSize[0] - linesThickness / float(2)) linesPositions[0, 1] = (windowSize[0] / float(2), windowSize[1] / float(2) - 2 * gap - cardSize[0] - linesThickness / float(2)) linesPositions[1, 0] = (-windowSize[0] / float(2), -windowSize[1] / float(2) + 2 * gap + cardSize[1] + linesThickness / float(2)) linesPositions[1, 1] = (windowSize[0] / float(2), -windowSize[1] / float(2) + 2 * gap + cardSize[1] + linesThickness / float(2)) lines = np.empty([2], object) lines[0] = stimuli.Line(linesPositions[0, 0], linesPositions[0, 1], linesThickness, colour=colorLine, anti_aliasing=None) lines[1] = stimuli.Line(linesPositions[1, 0], linesPositions[1, 1], linesThickness, colour=colorLine, anti_aliasing=None) for line in lines: line.plot(bs) bs.present()
def __init__(self, should_paint_grid): self.should_paint_grid = should_paint_grid self.line_horsizontal1 = stimuli.Line((-300, 80), (300, 80), 5) self.line_horsizontal2 = stimuli.Line((-300, -80), (300, -80), 5) self.line_vertical1 = stimuli.Line((-100, 200), (-100, -200), 5) self.line_vertical2 = stimuli.Line((100, 200), (100, -200), 5) self.cross = stimuli.FixCross((50, 50), (0, 0), 5) self.line_horsizontal1.preload() self.line_horsizontal2.preload() self.line_vertical1.preload() self.line_vertical2.preload()
def add_helplines(self, note): if len(note.help_lines) > 0: for hline in note.help_lines: help_line = stimuli.Line(hline['start_point'], hline['end_point'], hline['line_width'], colour=hline['colour']) help_line.present(clear=False, update=False)
def line(self, sx, sy, ex, ey, color=None): """See openexp._canvas.legacy""" if color != None: color = self.color(color) else: color = self.fgcolor stim = stimuli.Line(c2p((sx,sy)), c2p((ex,ey)), line_width= \ self.penwidth, colour=color, anti_aliasing=self.aa) self.add_stim(stim)
def line(self, sx, sy, ex, ey): stim = stimuli.Line(self.to_xy((sx, sy)), self.to_xy((ex, ey)), line_width=self.penwidth, colour=self.color.backend_color, anti_aliasing=self.aa) self.add_stim(stim)
def line(self, sx, sy, ex, ey, color=None, penwidth=None): if penwidth == None: penwidth = self.penwidth if color != None: color = self.color(color) else: color = self.fgcolor stim = stimuli.Line(c2p((sx,sy)), c2p((ex,ey)), line_width=penwidth, colour=color, anti_aliasing=self.aa) self.add_stim(stim)
def prepare_grid_stimulus(self): side = self.num_boxes**(0.5) block_size = self.canvas_size / side center = self.canvas_size / 2 grid = stimuli.BlankScreen() colour_grid = self.exp._colours( self.exp.config.get('APPEARANCE', 'colour_grid')) colour_fixation_cross = self.exp._colours( self.exp.config.get('APPEARANCE', 'colour_fixation_cross')) antialiasing = 10 if self.exp.config.getboolean( 'APPEARANCE', 'antialiasing') else None if colour_grid: for a, b in [(i % side, i // side) for i in range(self.num_boxes)]: stimuli.Line( (a * block_size - center, b * block_size - center), ((a + 1) * block_size - center, b * block_size - center), line_width=self.line_width, colour=colour_grid, anti_aliasing=antialiasing).plot(grid) stimuli.Line( (a * block_size - center, b * block_size - center), (a * block_size - center, (b + 1) * block_size - center), line_width=self.line_width, colour=(colour_grid), anti_aliasing=antialiasing).plot(grid) stimuli.Line( (0 - center, side * block_size - center), (side * block_size - center, side * block_size - center), line_width=self.line_width, colour=colour_grid, anti_aliasing=antialiasing).plot(grid) stimuli.Line( (side * block_size - center, 0 - center), (side * block_size - center, side * block_size - center), line_width=self.line_width, colour=colour_grid, anti_aliasing=antialiasing).plot(grid) if colour_fixation_cross: stimuli.FixCross(colour=colour_fixation_cross).plot(grid) grid.preload() return (grid)
def plotLine(bs, gap, color=bgColor): linePositions = np.empty([2], object) linePositions[0] = (-cardSize[0] / float(2), windowSize[1] / float(2) - 2 * gap - cardSize[0] - linesThickness / float(2)) linePositions[1] = (cardSize[0] / float(2), windowSize[1] / float(2) - 2 * gap - cardSize[0] - linesThickness / float(2)) line = stimuli.Line(linePositions[0], linePositions[1], linesThickness, colour=color) line.plot(bs) return bs
def __init__(self, screen_size, pos_y, clef_name="g", design="bw", text=None): self.background_colour = constants.C_WHITE self.foreground_colour = constants.C_BLACK self.clef_name = clef_name # Position of field self.pos_x = 0 self.pos_y = pos_y[self.clef_name] self.field_position = [self.pos_x, self.pos_y] # Size of field is 1 / factor of whole screen factor = 3.5 field_x = screen_size[0] / 2 field_y = screen_size[1] / factor self.field_size = [field_x, field_y] self.Field = stimuli.Canvas(size=self.field_size, position=self.field_position, colour=self.background_colour) # Text field for debugging if text is not None: self.text = text text = stimuli.TextBox(self.text, [100,100]) text.plot(self.Field) # Add lines self.distance = screen_size[0] / 60 line_radius = screen_size[0]/10 for i in range(-2, 3, 1): item = { 'start_point': [-line_radius, self.pos_x - (i * self.distance)], 'end_point': [line_radius, self.pos_x - (i * self.distance)], 'line_width': 2, 'colour': self.foreground_colour } line = stimuli.Line(item['start_point'], item['end_point'], item['line_width'], colour=item['colour']) line.plot(self.Field) # Add clef clef_pos_x = line_radius * 1.2 clef = stimuli.Picture('Stimuli/clef_' + design + '_' + clef_name + '.jpg', position=[-clef_pos_x, 0]) clef.scale(3.9 * screen_size[0] / 100000) clef.plot(self.Field)
def main_loop(exp, recorder, remote_control=False): """udp command: "start", "pause", "stop" "thresholds = [x,...]" : start level detection for Fz parameter and set threshold "thresholds stop" : stop level detection """ indicator_grid = 70 # distance between indicator center plotter_width = 900 plotter_position = (0, -30) s = GUIStatus( screen_refresh_interval_indicator=config. screen_refresh_interval_indicator, screen_refresh_interval_plotter=config. gui_screen_refresh_interval_plotter, recorder=recorder, remote_control=remote_control, level_detection_parameter=ForceData.forces_names.index( config.level_detection_parameter), # only one dimension screen_size=exp.screen.size, data_min_max=config.data_min_max, plotter_pixel_min_max=config.plotter_pixel_min_max, indicator_pixel_min_max=config.indicator_pixel_min_max, plot_axis=config.plot_axis) # plotter plotter_thread = None exp.keyboard.clear() while not s.quit_recording: ######## process loop if s.pause_recording: sleep(0.01) ################################ process keyboard s.process_key(exp.keyboard.check(check_for_control_keys=False)) ############################## process udp udp = recorder.process_and_write_udp_events() while len(udp) > 0: s.process_udp_event(udp.pop(0)) ########################### process new samples for x in s.check_new_samples(): s.update_history(sensor=x) if s.thresholds is not None: # level change detection level_change, tmp = s.thresholds.get_level_change( s.history[x].moving_average[s.level_detection_parameter], channel=x) if level_change: if x == 1: recorder.udp.send_queue.put(RcCmd.CHANGED_LEVEL2 + dumps(tmp)) else: recorder.udp.send_queue.put(RcCmd.CHANGED_LEVEL + dumps(tmp)) # minmax detection tmp = s.thresholds.get_response_minmax( s.history[x].moving_average[s.level_detection_parameter], channel=x) if tmp is not None: if x == 1: recorder.udp.send_queue.put(RcCmd.RESPONSE_MINMAX2 + dumps(tmp)) else: recorder.udp.send_queue.put(RcCmd.RESPONSE_MINMAX + dumps(tmp)) ######################## show pause or recording screen if s.check_recording_status_change(): if s.pause_recording: s.background.stimulus("writing data...").present() recorder.pause_recording() s.background.stimulus("Paused ('b' for baseline)").present() if remote_control: recorder.udp.send_queue.put(RcCmd.FEEDBACK_PAUSED) else: recorder.start_recording() s.set_start_recording_time() s.background.stimulus().present() if remote_control: recorder.udp.send_queue.put(RcCmd.FEEDBACK_STARTED) ########################### ########################### plotting ########################### if s.check_refresh_required(): #do not give priority to visual output update_rects = [] if s.check_thresholds_changed(): draw_plotter_thread_thresholds(plotter_thread, s.thresholds, s.scaling_plotter) if s.plot_indicator: ############################################ plot_indicator if plotter_thread is not None: plotter_thread.stop() plotter_thread = None ## indicator force_data_array = map( lambda x: s.sensor_processes[x[0]].get_force(x[1]), s.plot_data_indicator) for cnt in range(6): x_pos = (-3 * indicator_grid) + ( cnt * indicator_grid) + 0.5 * indicator_grid if cnt == s.level_detection_parameter: thr = s.thresholds else: thr = None li = level_indicator(value=force_data_array[cnt], text=s.plot_data_indicator_names[cnt], scaling=s.scaling_indicator, width=50, position=(x_pos, 0), thresholds=thr) li.present(update=False, clear=False) update_rects.append(get_pygame_rect(li, exp.screen.size)) #line zero = s.scaling_indicator.data2pixel( s.scaling_indicator.trim(0)) rect = stimuli.Line(start_point=(-200, zero), end_point=(200, zero), line_width=1, colour=misc.constants.C_YELLOW) rect.present(update=False, clear=False) update_rects.append(get_pygame_rect(rect, exp.screen.size)) # axis labels pos = (-220, -145) stimuli.Canvas(position=pos, size=(30, 20), colour=misc.constants.C_BLACK).present( update=False, clear=False) txt = stimuli.TextLine(position=pos, text=str(s.scaling_indicator.min), text_size=15, text_colour=misc.constants.C_YELLOW) txt.present(update=False, clear=False) update_rects.append(get_pygame_rect(txt, exp.screen.size)) pos = (-220, 145) stimuli.Canvas(position=pos, size=(30, 20), colour=misc.constants.C_BLACK).present( update=False, clear=False) txt = stimuli.TextLine(position=pos, text=str(s.scaling_indicator.max), text_size=15, text_colour=misc.constants.C_YELLOW) txt.present(update=False, clear=False) update_rects.append(get_pygame_rect(txt, exp.screen.size)) # end indicator stimuli.Canvas(position=(-250, 200), size=(200, 50), colour=misc.constants.C_BLACK).present( update=False, clear=False) txt = stimuli.TextBox( text=str(s.sensor_info_str), #background_colour=(30,30,30), size=(200, 50), text_size=15, position=(-250, 200), text_colour=misc.constants.C_YELLOW, text_justification=0) txt.present(update=False, clear=False) update_rects.append(get_pygame_rect(txt, exp.screen.size)) else: ############################################ plotter if plotter_thread is None: plotter_thread = PlotterThread( n_data_rows=len(s.plot_data_plotter), data_row_colours=colours[:len(s.plot_data_plotter)], y_range=[ s.scaling_plotter.pixel_min, s.scaling_plotter.pixel_max ], width=plotter_width, position=plotter_position, background_colour=[10, 10, 10], axis_colour=misc.constants.C_YELLOW) plotter_thread.start() if s.plot_axis: plotter_thread.set_horizontal_lines( y_values=[s.scaling_plotter.data2pixel(0)]) if s.thresholds is not None: plotter_thread.set_horizontal_lines( y_values=s.scaling_plotter.data2pixel( np.array(s.thresholds.thresholds))) if s.clear_screen: plotter_thread.clear_area() s.clear_screen = False if s.plot_filtered: tmp = np.array(map( lambda x: s.history[x[0]].moving_average[x[1]], s.plot_data_plotter), dtype=float) else: tmp = np.array(map( lambda x: s.sensor_processes[x[0]].get_force(x[1]), s.plot_data_plotter), dtype=float) if s.thresholds is not None: point_marker = s.thresholds.is_detecting_anything() else: point_marker = False plotter_thread.add_values( values=s.scaling_plotter.data2pixel(tmp), set_marker=s.set_marker, set_point_marker=point_marker) s.set_marker = False update_rects.append( plotter_thread.get_plotter_rect(exp.screen.size)) # axis labels axis_labels = (int(s.scaling_plotter.min), int(s.scaling_plotter.max), 0) xpos = plotter_position[0] - (plotter_width / 2) - 20 for cnt, ypos in enumerate( (plotter_position[1] + s.scaling_plotter.pixel_min + 10, plotter_position[1] + s.scaling_plotter.pixel_max - 10, plotter_position[1] + s.scaling_plotter.data2pixel(0))): stimuli.Canvas(position=(xpos, ypos), size=(50, 30), colour=misc.constants.C_BLACK).present( update=False, clear=False) txt = stimuli.TextLine(position=(xpos, ypos), text=str(axis_labels[cnt]), text_size=15, text_colour=misc.constants.C_YELLOW) txt.present(update=False, clear=False) update_rects.append(get_pygame_rect(txt, exp.screen.size)) # counter pos = (-230, 250) stimuli.Canvas(position=pos, size=(400, 50), colour=misc.constants.C_BLACK).present(update=False, clear=False) txt = stimuli.TextBox( position=pos, size=(400, 50), #background_colour=(30,30,30), text_size=15, text="n samples (total): {0}\nn samples: {1} ({2} sec.)". format( str(map(SensorProcess.get_sample_cnt, s.sensor_processes))[1:-1], str(map(SensorProcess.get_buffer_size, s.sensor_processes))[1:-1], s.recording_duration_in_sec), text_colour=misc.constants.C_YELLOW, text_justification=0) txt.present(update=False, clear=False) update_rects.append(get_pygame_rect(txt, exp.screen.size)) # Infos pos = (200, 250) tmp = stimuli.Canvas(position=pos, size=(400, 50), colour=misc.constants.C_BLACK) tmp.present(update=False, clear=False) update_rects.append(get_pygame_rect(tmp, exp.screen.size)) if s.thresholds is not None: if s.n_sensors > 1: tmp = [ s.thresholds.get_level( s.level_detection_parameter_average(0)), s.thresholds.get_level( s.level_detection_parameter_average(1)) ] else: tmp = s.thresholds.get_level( s.level_detection_parameter_average(0)) txt = stimuli.TextBox(position=pos, size=(400, 50), text_size=15, text="T: {0} L: {1}".format( s.thresholds, tmp), text_colour=misc.constants.C_YELLOW, text_justification=0) txt.present(update=False, clear=False) pos = (400, 250) tmp = stimuli.Canvas(position=pos, size=(400, 50), colour=misc.constants.C_BLACK) tmp.present(update=False, clear=False) update_rects.append(get_pygame_rect(tmp, exp.screen.size)) if s.plot_filtered: txt = stimuli.TextBox(position=pos, size=(400, 50), text_size=15, text="Filtered data!", text_colour=misc.constants.C_YELLOW, text_justification=0) txt.present(update=False, clear=False) # last_udp input if s.last_udp_data is not None: pos = (420, 250) stimuli.Canvas(position=pos, size=(200, 30), colour=misc.constants.C_BLACK).present( update=False, clear=False) txt = stimuli.TextBox( position=pos, size=(200, 30), #background_colour=(30,30,30), text_size=15, text="UDP:" + str(s.last_udp_data), text_colour=misc.constants.C_YELLOW, text_justification=0) txt.present(update=False, clear=False) update_rects.append(get_pygame_rect(txt, exp.screen.size)) pygame.display.update(update_rects) # end plotting screen ##### end main loop s.background.stimulus("Quitting").present() if plotter_thread is not None: plotter_thread.stop() recorder.pause_recording(s.background)
def run_trial(self, block, trial): trial = block.trials[0] def display_labels(lbls): return ' - '.join(lbls[:6]) + (' - ...' if len(lbls) > 6 else '') target_order = display_labels(self.labels[block.get_factor('target_titles')]) self.exp._show_message('', 'instruction', format={'target_order': target_order}) idoffset = trial.stimuli[1].id - 1 def make_surface(trial): sf = stimuli.BlankScreen() boundary = self.exp.config.gettuple('APPEARANCE', 'colour_window_boundary') if boundary: stimuli.Rectangle(self.exp.screen.window_size, line_width=self.line_width, colour=boundary).plot(sf) [s.plot(sf) for s in trial.stimuli] return sf surface = make_surface(trial) surface.present() cumulated = 0 path = [] currentcircle = 0 score = 0 mouse = self.exp.mouse.position has_moved = False logs = {'lost_touch': [], 'touched_targets': []} def get_log(evt): return { '_block': block.id + 1, 'current_target': currentcircle, 'distance': cumulated, 'time': self.exp.clock.stopwatch_time, 'score': score, 'event': evt } in_circle = -1 mismatched_circles = [] misc.Clock.reset_stopwatch(self.exp.clock) while True: new_mouse = self.exp.mouse.wait_motion(duration=20)[0] if self.exp.clock.stopwatch_time / 1000 >= block.get_factor('timeout'): self.exp._log_trial(block, trial, get_log('timeout')) break if self.exp.mouse.pressed_buttons[0] != 1: lost = False if currentcircle > 0 or len(mismatched_circles) > 0: lost = True if self.on_pointer_release == 'reset': currentcircle = 0 mismatched_circles = [] score = 0 # TODO has_moved = False surface = make_surface(trial) surface.present() elif self.on_pointer_release == 'nothing': pass if lost: logs['lost_touch'].append(get_log('lost_touch')) self.exp._log_trial(block, trial, logs['lost_touch'][-1]) continue if mouse == new_mouse: continue if not has_moved: has_moved = True mouse = None continue if abs(new_mouse[0]) >= self.exp.screen.window_size[0]/2 or abs(new_mouse[1]) >= self.exp.screen.window_size[1]/2: continue if mouse is not None: stimuli.Line(mouse, new_mouse, self.line_width, self.colour_line).plot(surface) stimuli.Circle(radius=self.line_width/2, position=new_mouse, colour=self.colour_line, anti_aliasing=self.antialiasing ).plot(surface) cumulated += TrailMaking.point_distance(new_mouse, mouse) path.append([new_mouse[0], new_mouse[1], self.exp.clock.stopwatch_time]) def get_stimulus_position(sid): return [ x for x in trial.stimuli if x.id == sid][0].position for s in trial.stimuli: if 'Circle' in s.__class__.__name__: x, y = s.position if TrailMaking.point_distance((x, y), new_mouse) <= self.radius: if in_circle == -1: in_circle = s.id if (s.id - idoffset)/2+0 == currentcircle: # stimuli.Circle(radius=CIRCLE_SIZE, colour=COLOUR_CIRCLE_DONE, line_width=LINEWIDTH, position=(x, y)).plot(surface) # , anti_aliasing=ANTIALIASING currentcircle += 1 # score += SCORE_CORRECT_CIRCLE logs['touched_targets'].append(get_log('correct_touch')) self.exp._log_trial(block, trial, logs['touched_targets'][-1]) if len(mismatched_circles) > 0: for ss in mismatched_circles + [s.id]: trial.stimuli[ss - idoffset].plot(surface) trial.stimuli[ss - idoffset + 1].plot(surface) mismatched_circles = [] elif (s.id - idoffset)/2+0 < currentcircle - 1 or (s.id - idoffset)/2+0 > currentcircle: if self.on_mismatched_circle == 'repeat_last': if len(mismatched_circles) == 0 and currentcircle > 0: currentcircle -= 1 stimuli.Circle(radius=self.ring_radius, colour=self.colour_target_hint, line_width=self.line_width, position=get_stimulus_position( currentcircle*2 + idoffset)).plot(surface) if self.on_mismatched_circle in ['highlight_only', 'repeat_last']: mismatched_circles.append(s.id) stimuli.Circle(radius=self.ring_radius, colour=self.colour_target_error, line_width=self.line_width, position=(x, y), anti_aliasing=self.antialiasing).plot(surface) # score += SCORE_WRONG_CIRCLE logs['touched_targets'].append( get_log('wrong_touch:' + str(currentcircle))) self.exp._log_trial(block, trial, logs['touched_targets'][-1]) else: if in_circle == s.id and TrailMaking.point_distance((x, y), new_mouse) >= self.radius + 1: trial.stimuli[in_circle - idoffset + 1].plot(surface) in_circle = -1 surface.present() mouse = new_mouse if currentcircle >= len(trial.stimuli)/2: self.exp._log_trial(block, trial, get_log('finish')) break logs['time'] = self.exp.clock.stopwatch_time logs['distance'] = cumulated logs['score'] = score self.exp._show_message('', 'trial_done', format={ 'distance': logs['distance'], 'time': logs['time'], 'score': logs['score']}) self.exp._log_block(trial, block, logs, {'trail': trial.id}, TrailMaking.make_trail_summary(logs, block)) # TODO # self.log_trail(block, path) # self.log_targets(block, block.trials[0].stimuli) return()