Package VisionEgg :: Package PyroApps :: Module MouseTargetServer |
[frames] | no frames]

# Source Code for Module VisionEgg.PyroApps.MouseTargetServer

      1  #!/usr/bin/env python
      2  #
      3  # The Vision Egg: MouseTargetServer
      4  #
      5  # Copyright (C) 2001-2003 Andrew Straw.
      6  # Author: Andrew Straw <astraw@users.sourceforge.net>
      7  # URL: <http://www.visionegg.org/>
      8  #
      9  # Distributed under the terms of the GNU Lesser General Public License
     10  # (LGPL). See LICENSE.TXT that came with this file.
     11  #
     12  # $Id$
     13
     14  """Handle mouse-controlled small targets (server-side)"""
     15
     16  import VisionEgg, string
     17  import VisionEgg.ParameterTypes as ve_types
     18
     19  __version__ = VisionEgg.release_name
     20  __cvs__ = string.split('$Revision$')[1]
     21  __date__ = string.join(string.split('$Date$')[1:3], ' ')
     22  __author__ = 'Andrew Straw <astraw@users.sourceforge.net>'
     23
     24  import sys, os, math
     25  import VisionEgg.Core
     26  import VisionEgg.FlowControl
     27  import VisionEgg.MoreStimuli
     28  import VisionEgg.PyroHelpers
     29  import Pyro.core
     30  import pygame, pygame.locals
     31
     32  from VisionEgg.PyroApps.MouseTargetGUI import MouseTargetMetaParameters
     33
     34  # Variables to store the mouse position
     35  mouse_position = (320.0, 240.0)
     36  last_mouse_position = (0.0,0.0)
     37
     38  # target size global variables
     39  target_w = 50.0
     40  target_h = 10.0
     41
     42  # key state global variables
     43  up = 0
     44  down = 0
     45  left = 0
     46  right = 0
     47
     48 -def keydown(event):
     49      global up, down, left, right
     50      if event.key == pygame.locals.K_UP:
     51          up = 1
     52      elif event.key == pygame.locals.K_DOWN:
     53          down = 1
     54      elif event.key == pygame.locals.K_RIGHT:
     55          right = 1
     56      elif event.key == pygame.locals.K_LEFT:
     57          left = 1
     58
     59 -def keyup(event):
     60      global up, down, left, right
     61      if event.key == pygame.locals.K_UP:
     62          up = 0
     63      elif event.key == pygame.locals.K_DOWN:
     64          down = 0
     65      elif event.key == pygame.locals.K_RIGHT:
     66          right = 0
     67      elif event.key == pygame.locals.K_LEFT:
     68          left = 0
     69
     70  handle_event_callbacks = [(pygame.locals.KEYDOWN, keydown),
     71                            (pygame.locals.KEYUP, keyup)]
     72
     73 -class MouseTargetExperimentMetaController( Pyro.core.ObjBase ):
     74 -    def __init__(self,screen,presentation,stimuli):
     75          global screen_global
     76          screen_global = screen
     77          # get stimulus
     78          assert( stimuli[0][0] == '2d_overlay')
     79          target = stimuli[0][1]
     80
     81          Pyro.core.ObjBase.__init__(self)
     82          self.meta_params = MouseTargetMetaParameters()
     83          if not isinstance(screen,VisionEgg.Core.Screen):
     84              raise ValueError("Expecting instance of VisionEgg.Core.Screen")
     85          if not isinstance(presentation,VisionEgg.FlowControl.Presentation):
     86              raise ValueError("Expecting instance of VisionEgg.FlowControl.Presentation")
     87          if not isinstance(target,VisionEgg.MoreStimuli.Target2D):
     88              raise ValueError("Expecting instance of VisionEgg.MoreStimuli.Target2D")
     89
     90          self.screen = screen
     91          self.p = presentation
     92          self.stim = target
     93
     94          self.p.add_controller(target,'position', TargetPositionController())
     95          self.p.add_controller(target,'size', VisionEgg.FlowControl.FunctionController(during_go_func=get_target_size,
     96                                                                  between_go_func=get_target_size) )
     97          self.p.add_controller(target,'orientation', TargetOrientationController() )
     98          self.mouse_position_controller = MousePositionController()
     99          self.p.add_controller(None,None,self.mouse_position_controller)
    100          self.orig_event_handlers = self.p.parameters.handle_event_callbacks
    101          self.p.parameters.handle_event_callbacks = handle_event_callbacks
    102
    103          self.update() # set stimulus parameters to initial defaults
    104
    105 -    def __del__(self):
    106          self.p.parameters.handle_event_callbacks = self.orig_event_handlers
    107          self.p.remove_controller(None,None,self.mouse_position_controller)
    108          self.p.remove_controller(self.stim,'position')
    109          self.p.remove_controller(self.stim,'size')
    110          self.p.remove_controller(self.stim,'orientation')
    111
    112 -    def get_parameters(self):
    113          return self.meta_params
    114
    115 -    def set_parameters(self, new_parameters):
    116          if isinstance(new_parameters, MouseTargetMetaParameters):
    117              self.meta_params = new_parameters
    118          else:
    119              raise ValueError("Argument to set_parameters must be instance of MouseTargetMetaParameters")
    120          self.update()
    121
    122 -    def update(self):
    123          stim_params = self.stim.parameters # shorthand
    124          meta_params = self.meta_params # shorthand
    125
    126          # colors
    127          stim_params.color = meta_params.color
    128          self.screen.parameters.bgcolor = meta_params.bgcolor
    129
    130 -    def go(self):
    131          pass
    132          #self.p.parameters.enter_go_loop = 1
    133
    134 -    def quit_server(self):
    135          self.p.parameters.quit = 1
    136
    137 -def get_meta_controller_class():
    138      return MouseTargetExperimentMetaController
    139
    140 -def make_stimuli():
    141      stimulus = VisionEgg.MoreStimuli.Target2D(anchor='center')
    142      return [('2d_overlay',stimulus)]
    143
    144 -def get_meta_controller_stimkey():
    145      return "mouse_target_server"
    146
    147  ########################
    148  #  Define controllers  #
    149  ########################
    150
    151 -class MousePositionController( VisionEgg.FlowControl.Controller ):
    152 -    def __init__(self):
    153          global mouse_position
    154          VisionEgg.FlowControl.Controller.__init__(self,
    155                              return_type=ve_types.get_type(None),
    156                              eval_frequency=VisionEgg.FlowControl.Controller.EVERY_FRAME)
    157          self.between_go_eval = self.during_go_eval
    158
    159 -    def during_go_eval(self,t=None):
    160          # Convert pygame mouse position to OpenGL position
    161          global mouse_position, last_mouse_position, screen_global
    162          just_current_pos = mouse_position
    163          (x,y) = pygame.mouse.get_pos()
    164          y = screen_global.size[1]-y
    165          mouse_position = (x,y)
    166          if just_current_pos != mouse_position:
    167              last_mouse_position = just_current_pos
    168          return None
    169
    170 -class TargetPositionController( VisionEgg.FlowControl.Controller ):
    171 -    def __init__(self):
    172          global mouse_position
    173          VisionEgg.FlowControl.Controller.__init__(self,
    174                              return_type=ve_types.Sequence2(ve_types.Real),
    175                              eval_frequency=VisionEgg.FlowControl.Controller.EVERY_FRAME)
    176          self.between_go_eval = self.during_go_eval
    177
    178 -    def during_go_eval(self,t=None):
    179          global mouse_position
    180          return mouse_position
    181
    182 -def cross_product(b,c):
    183      """Cross product between vectors, represented as tuples of length 3."""
    184      det_i = b[1]*c[2] - b[2]*c[1]
    185      det_j = b[0]*c[2] - b[2]*c[0]
    186      det_k = b[0]*c[1] - b[1]*c[0]
    187      return (det_i,-det_j,det_k)
    188
    189 -def mag(b):
    190      """Magnitude of a vector."""
    191      return b[0]**2.0 + b[1]**2.0 + b[2]**2.0
    192
    193 -class TargetOrientationController( VisionEgg.FlowControl.Controller ):
    194 -    def __init__(self):
    195          VisionEgg.FlowControl.Controller.__init__(self,
    196                              return_type=ve_types.Real,
    197                              eval_frequency=VisionEgg.FlowControl.Controller.EVERY_FRAME)
    198          self.c = (0.0,0.0,1.0)
    199          self.last_orientation = 0.0
    200          self.between_go_eval = self.during_go_eval
    201
    202 -    def during_go_eval(self):
    203          global mouse_position, last_mouse_position
    204
    205          b = (float(last_mouse_position[0]-mouse_position[0]),
    206               float(last_mouse_position[1]-mouse_position[1]),
    207               0.0)
    208
    209          if mag(b) > 1.0: # Must mouse 1 pixel before changing orientation (supposed to reject noise)
    210              # find cross product b x c. assume b and c are 3-vecs, b has
    211              # 3rd component 0.
    212              orientation_vector = cross_product(b,self.c)
    213              self.last_orientation = math.atan2(orientation_vector[1],orientation_vector[0])/math.pi*180.0
    214          return self.last_orientation
    215
    216 -def get_target_size(t=None):
    217      global target_w, target_h
    218      global up, down, left, right
    219
    220      amount = 0.02
    221
    222      if up:
    223          target_w = target_w+(amount*target_w)
    224      elif down:
    225          target_w = target_w-(amount*target_w)
    226      elif right:
    227          target_h = target_h+(amount*target_h)
    228      elif left:
    229          target_h = target_h-(amount*target_h)
    230      target_w = max(target_w,0.0)
    231      target_h = max(target_h,0.0)
    232
    233      return (target_w, target_h)
    234
    235  # Don't do anything unless this script is being run
    236  if __name__ == '__main__':
    237
    238      pyro_server = VisionEgg.PyroHelpers.PyroServer()
    239
    240      screen = VisionEgg.Core.Screen.create_default()
    241
    242      # get Vision Egg stimulus ready to go
    243      stimuli = make_stimuli()
    244      stimulus = stimuli[0][1]
    245      viewport = VisionEgg.Core.Viewport(screen=screen,stimuli=[stimulus])
    246      p = VisionEgg.FlowControl.Presentation(viewports=[viewport])
    247
    248      # now hand over control of grating and mask to FlatGratingExperimentMetaController
    249      meta_controller = MouseTargetExperimentMetaController(screen,p,stimuli)
    250      pyro_server.connect(meta_controller,get_meta_controller_stimkey())
    251
    252      # get listener controller and register it
    253      p.add_controller(None,None, pyro_server.create_listener_controller())
    254
    255      # enter endless loop
    256      p.run_forever()
    257