def setRadius(self, radius, log=True): """Changes the radius of the Polygon. If radius is a 2-tuple or list, the values will be interpreted as semi-major and semi-minor radii of an ellipse.""" self.radius = numpy.asarray(radius) self._calcVertices() self.setVertices(self.vertices, log=False) logAttrib(self, log, 'radius', radius)
def _set(self, attrib, val, op='', log=True): """Use this to set attributes of your stimulus after initialising it. :Parameters: attrib : a string naming any of the attributes of the stimulus (set during init) val : the value to be used in the operation on the attrib op : a string representing the operation to be performed (optional) most maths operators apply ('+','-','*'...) examples:: myStim.set('rgb',0) #will simply set all guns to zero (black) myStim.set('rgb',0.5,'+') #will increment all 3 guns by 0.5 myStim.set('rgb',(1.0,0.5,0.5),'*') # will keep the red gun the same and halve the others """ #format the input value as float vectors if type(val) in [tuple,list]: val=numpy.array(val,float) #change the attribute as requested setWithOperation(self, attrib, val, op) #update the actual coherence for the requested coherence and nDots if attrib in ['nDots','coherence']: self.coherence=round(self.coherence*self.nDots)/self.nDots logAttrib(self, log, attrib)
def setPhases(self,value,operation='', log=True): """Set the phase for each element. Should either be: - a single value - an Nx1 array/list - an Nx2 array/list (for separate X and Y phase) """ #make into an array if type(value) in [int, float, list, tuple]: value = numpy.array(value, dtype=float) #check shape if value.shape in [(),(1,),(2,)]: value = numpy.resize(value, [self.nElements,2]) elif value.shape in [(self.nElements,), (self.nElements,1)]: value.shape=(self.nElements,1)#set to be 2D value = value.repeat(2,1) #repeat once on dim 1 elif value.shape == (self.nElements,2): pass#all is good else: raise ValueError("New value for setPhases should be either Nx1, Nx2 or a single value") #set value and log setWithOperation(self, 'phases', value, operation) logAttrib(self, log, 'phases', type(value)) self._needTexCoordUpdate=True
def setSfs(self, value,operation='', log=True): """Set the spatial frequency for each element. Should either be: - a single value - an Nx1 array/list - an Nx2 array/list (spatial frequency of the element in X and Y). If the units for the stimulus are 'pix' or 'norm' then the units of sf are cycles per stimulus width. For units of 'deg' or 'cm' the units are c/cm or c/deg respectively. """ #make into an array if type(value) in [int, float, list, tuple]: value = numpy.array(value, dtype=float) #check shape if value.shape in [(),(1,),(2,)]: value = numpy.resize(value, [self.nElements,2]) elif value.shape in [(self.nElements,), (self.nElements,1)]: value.shape=(self.nElements,1)#set to be 2D value = value.repeat(2,1) #repeat once on dim 1 elif value.shape == (self.nElements,2): pass#all is good else: raise ValueError("New value for setSfs should be either Nx1, Nx2 or a single value") # Set value and log setWithOperation(self, 'sfs', value, operation) logAttrib(self, log, 'sfs', type(value))
def loadMovie(self, filename, log=None): """Load a movie from file :Parameters: filename: string The name of the file, including path if necessary Brings up a warning if avbin is not found on the computer. After the file is loaded MovieStim.duration is updated with the movie duration (in seconds). """ try: self._movie = pyglet.media.load(filename, streaming=True) except Exception as e: # pyglet.media.riff is N/A if avbin is available, and then # actual exception would get masked with a new one for unknown # (sub)module riff, thus catching any exception and tuning msg # up if it has to do anything with avbin estr = str(e) msg = '' if "avbin" in estr.lower(): msg = ("\nIt seems that avbin was not installed correctly." "\nPlease fetch/install it from " "http://code.google.com/p/avbin/.") emsg = "Caught exception '%s' while loading file '%s'.%s" raise IOError(emsg % (estr, filename, msg)) self._player.queue(self._movie) self.duration = self._movie.duration while self._player.source != self._movie: next(self._player) self.status = NOT_STARTED self._player.pause() # start 'playing' on the next draw command self.filename = filename logAttrib(self, log, 'movie', filename)
def setMask(self,value, log=True): """Change the mask (all elements have the same mask). Avoid doing this during time-critical points in your script. Uploading new textures to the graphics card can be time-consuming.""" self.mask = value self.createTexture(value, id=self._maskID, pixFormat=GL.GL_ALPHA, stim=self, res=self.texRes) logAttrib(self, log, 'mask')
def seek(self, timestamp, log=True): """Seek to a particular timestamp in the movie. """ if self.status in [PLAYING, PAUSED]: if timestamp > 0.0: if self.status == PLAYING: self.pause() player = self._audio_stream_player if player and player.is_seekable(): player.set_time(int(timestamp * 1000.0)) self._audio_stream_clock.reset(-timestamp) MSEC = cv2.CAP_PROP_POS_MSEC FRAMES = cv2.CAP_PROP_POS_FRAMES self._video_stream.set(MSEC, timestamp * 1000.0) self._video_track_clock.reset(-timestamp) self._next_frame_index = self._video_stream.get(FRAMES) self._next_frame_sec = self._video_stream.get(MSEC)/1000.0 else: self.stop() self.loadMovie(self.filename) if log: logAttrib(self, log, 'seek', timestamp) self.play()
def seek(self, timestamp, log=None): """Seek to a particular timestamp in the movie. NB this does not seem very robust as at version 1.62, may crash! """ self._player.seek(float(timestamp)) logAttrib(self, log, 'seek', timestamp)
def loadMovie(self, filename, log=True): """Load a movie from file :Parameters: filename: string The name of the file, including path if necessary After the file is loaded MovieStim.duration is updated with the movie duration (in seconds). """ self.reset() #set status and timestamps etc # Create Video Stream stuff if os.path.isfile(filename): self._mov = VideoFileClip(filename, audio= (1-self.noAudio)) if (not self.noAudio) and (self._mov.audio is not None): self._audioStream = sound.Sound(self._mov.audio.to_soundarray(), sampleRate = self._mov.audio.fps) else: #make sure we set to None (in case prev clip did have auido) self._audioStream = None else: raise IOError("Movie file '%s' was not found" %filename) #mov has attributes: # size, duration, fps #mov.audio has attributes #duration, fps (aka sampleRate), to_soundarray() self._frameInterval = 1.0/self._mov.fps self.duration = self._mov.duration self.filename = filename self._updateFrameTexture() logAttrib(self, log, 'movie', filename)
def setFlipHoriz(self, newVal=True, log=None): """If set to True then the movie will be flipped horizontally (left-to-right). Note that this is relative to the original, not relative to the current state. """ self.flipHoriz = newVal logAttrib(self, log, 'flipHoriz') self._needVertexUpdate = True
def setStart(self, start, log=True): """Changes the start point of the line. Argument should be - tuple, list or 2x1 array specifying the coordinates of the start point""" self.start = start self.setVertices([self.start, self.end], log=False) logAttrib(self, log, 'start')
def setFlipVert(self, newVal=True, log=None): """If set to True then the movie will be flipped vertically (top-to-bottom). Note that this is relative to the original, not relative to the current state. """ self.flipVert = newVal logAttrib(self, log, 'flipVert') self._needVertexUpdate = True
def setPos(self, pos, needReset=True, log=True): """Set the pos (centre) of the Aperture """ self.pos = numpy.array(pos) self._shape.pos = self.pos if needReset: self._reset() logAttrib(self, log, 'pos')
def setFlipHoriz(self, newVal=True, log=True): """If set to True then the movie will be flipped horizontally (left-to-right). Note that this is relative to the original, not relative to the current state. """ self.flipHoriz = newVal logAttrib(self, log, 'flipHoriz') self._needVertexUpdate = True
def setTex(self,value, log=True): """Change the texture (all elements have the same base texture). Avoid this during time-critical points in your script. Uploading new textures to the graphics card can be time-consuming. """ self.tex = value self.createTexture(value, id=self._texID, pixFormat=GL.GL_RGB, stim=self, res=self.texRes) logAttrib(self, log, 'tex')
def setSize(self, size, needReset=True, log=True): """Set the size (diameter) of the Aperture """ self.size = size self._shape.size = size if needReset: self._reset() logAttrib(self, log, 'size')
def setFlipVert(self, newVal=True, log=True): """If set to True then the movie will be flipped vertically (top-to-bottom). Note that this is relative to the original, not relative to the current state. """ self.flipVert = newVal logAttrib(self, log, 'flipVert') self._needVertexUpdate = True
def setOri(self, ori, needReset=True, log=True): """Set the orientation of the Aperture """ self.ori = ori self._shape.ori = ori if needReset: self._reset() logAttrib(self, log, 'ori')
def setRadius(self, radius, log=True): """Changes the radius of the Polygon. Parameter should be - float, int, tuple, list or 2x1 array""" self.radius = numpy.asarray(radius) self._calcVertices() self.setVertices(self.vertices, log=False) logAttrib(self, log, 'radius')
def loadMovie(self, filename, log=True): """Load a movie from file :Parameters: filename: string The name of the file, including path if necessary After the file is loaded MovieStim.duration is updated with the movie duration (in seconds). """ self._unload() self._reset() if self._no_audio is False: self._createAudioStream() # Create Video Stream stuff self._video_stream = cv2.VideoCapture() self._video_stream.open(filename) if not self._video_stream.isOpened(): raise RuntimeError("Error when reading image file") self._total_frame_count = self._video_stream.get( cv2.cv.CV_CAP_PROP_FRAME_COUNT) self._video_width = self._video_stream.get( cv2.cv.CV_CAP_PROP_FRAME_WIDTH) self._video_height = self._video_stream.get( cv2.cv.CV_CAP_PROP_FRAME_HEIGHT) self._format = self._video_stream.get(cv2.cv.CV_CAP_PROP_FORMAT) # TODO: Read depth from video source self._video_frame_depth = 3 if self._no_audio: self._video_frame_rate = self._requested_fps else: self._video_frame_rate = self._video_stream.get( cv2.cv.CV_CAP_PROP_FPS) self._inter_frame_interval = 1.0 / self._video_frame_rate # Create a numpy array that can hold one video frame, as returned by cv2. self._numpy_frame = numpy.zeros( (self._video_height, self._video_width, self._video_frame_depth), dtype=numpy.uint8) # Uses a preallocated numpy array as the pyglet ImageData data self._frame_data_interface = ArrayInterfaceImage(self._numpy_frame, allow_copy=False, rectangle=True, force_rectangle=True) #frame texture; transformed so it looks right in psychopy self._frame_texture = self._frame_data_interface.texture.get_transform( flip_x=not self.flipHoriz, flip_y=not self.flipVert) self.duration = self._total_frame_count * self._inter_frame_interval self.status = NOT_STARTED self.filename = filename logAttrib(self, log, 'movie', filename)
def setFlipVert(self,newVal=True, log=True): """If set to True then the image will be flipped vertically (top-to-bottom). Note that this is relative to the original image, not relative to the current state. """ if newVal!=self.flipVert: #we need to make the flip self.imArray = numpy.fliplr(self.imArray)#numpy and pyglet disagree about ori so ud<=>lr self.flipVert=newVal logAttrib(self, log, 'flipVert') self._needStrUpdate=True
def setFlipHoriz(self,newVal=True, log=True): """If set to True then the image will be flipped horiztonally (left-to-right). Note that this is relative to the original image, not relative to the current state. """ if newVal!=self.flipHoriz: #we need to make the flip self.imArray = numpy.flipud(self.imArray)#numpy and pyglet disagree about ori so ud<=>lr self.flipHoriz=newVal logAttrib(self, log, 'flipHoriz') self._needStrUpdate=True
def setLineColor(self, color, colorSpace=None, operation='', log=None): """Sets the color of the shape edge. See :meth:`psychopy.visual.GratingStim.color` for further details of how to use this function. """ setColor(self,color, colorSpace=colorSpace, operation=operation, rgbAttrib='lineRGB',#the name for this rgb value colorAttrib='lineColor',#the name for this color ) logAttrib(self, log, 'lineColor', value='%s (%s)' %(self.lineColor, self.lineColorSpace))
def setMask(self,value, log=True): """Change the image to be used as an alpha-mask for the image """ self.mask = value self.createTexture(value, id=self._maskID, pixFormat=GL.GL_ALPHA,dataType=GL.GL_UNSIGNED_BYTE, stim=self, res=self.texRes, maskParams=self.maskParams) logAttrib(self, log, 'mask')
def loadMovie(self, filename, log=True): """Load a movie from file :Parameters: filename: string The name of the file, including path if necessary After the file is loaded MovieStim.duration is updated with the movie duration (in seconds). """ filename = pathToString(filename) self._unload() self._reset() if self._no_audio is False: self._createAudioStream() # Create Video Stream stuff self._video_stream.open(filename) vfstime = core.getTime() opened = self._video_stream.isOpened() if not opened and core.getTime() - vfstime < 1: raise RuntimeError("Error when reading image file") if not opened: raise RuntimeError("Error when reading image file") self._total_frame_count = self._video_stream.get( cv2.CAP_PROP_FRAME_COUNT) self._video_width = int(self._video_stream.get( cv2.CAP_PROP_FRAME_WIDTH)) self._video_height = int(self._video_stream.get( cv2.CAP_PROP_FRAME_HEIGHT)) self._format = self._video_stream.get( cv2.CAP_PROP_FORMAT) # TODO: Read depth from video source self._video_frame_depth = 3 cv_fps = self._video_stream.get(cv2.CAP_PROP_FPS) self._video_frame_rate = cv_fps self._inter_frame_interval = 1.0/self._video_frame_rate # Create a numpy array that can hold one video frame, as returned by # cv2. self._numpy_frame = numpy.zeros((self._video_height, self._video_width, self._video_frame_depth), dtype=numpy.uint8) self.duration = self._total_frame_count * self._inter_frame_interval self.status = NOT_STARTED self.filename = filename logAttrib(self, log, 'movie', filename)
def setHeight(self,height, log=True): """Set the height of the letters (including the entire box that surrounds the letters in the font). The width of the letters is then defined by the font. """ self.heightPix = convertToPix(pos = numpy.array([0,0]), vertices=numpy.array([0,height]), units=self.units, win=self.win)[1] #need to update the font to reflect the change self.setFont(self.fontname, log=False) logAttrib(self, log, 'height', height)
def loadMovie(self, filename, log=True): """Load a movie from file :Parameters: filename: string The name of the file, including path if necessary After the file is loaded MovieStim.duration is updated with the movie duration (in seconds). """ self._unload() self._reset() if self._no_audio is False: self._createAudioStream() # Create Video Stream stuff self._video_stream = cv2.VideoCapture() self._video_stream.open(filename) if not self._video_stream.isOpened(): raise RuntimeError( "Error when reading image file") self._total_frame_count = self._video_stream.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT) self._video_width = self._video_stream.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH) self._video_height = self._video_stream.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT) self._format = self._video_stream.get(cv2.cv.CV_CAP_PROP_FORMAT) # TODO: Read depth from video source self._video_frame_depth = 3 if self._no_audio: self._video_frame_rate = self._requested_fps else: self._video_frame_rate = self._video_stream.get(cv2.cv.CV_CAP_PROP_FPS) self._inter_frame_interval = 1.0/self._video_frame_rate # Create a numpy array that can hold one video frame, as returned by cv2. self._numpy_frame = numpy.zeros((self._video_height, self._video_width, self._video_frame_depth), dtype=numpy.uint8) # Uses a preallocated numpy array as the pyglet ImageData data self._frame_data_interface = ArrayInterfaceImage(self._numpy_frame, allow_copy=False, rectangle=True, force_rectangle=True) #frame texture; transformed so it looks right in psychopy self._frame_texture = self._frame_data_interface.texture.get_transform(flip_x=not self.flipHoriz, flip_y=not self.flipVert) self.duration = self._total_frame_count * self._inter_frame_interval self.status = NOT_STARTED self.filename = filename logAttrib(self, log, 'movie', filename)
def setMask(self, value, log=True): """Change the mask (all elements have the same mask). Avoid doing this during time-critical points in your script. Uploading new textures to the graphics card can be time-consuming.""" self.mask = value self.createTexture(value, id=self._maskID, pixFormat=GL.GL_ALPHA, stim=self, res=self.texRes) logAttrib(self, log, 'mask')
def setText(self,text=None, log=True): """Set the text to be rendered using the current font """ if text!=None:#make sure we have unicode object to render self.text = unicode(text) if self.useShaders: self._setTextShaders(text) else: self._setTextNoShaders(text) self._needSetText=False logAttrib(self, log, 'text', text)
def loadMovie(self, filename, log=True): """Load a movie from file. After the file is loaded `MovieStim.duration` is updated with the movie duration (in seconds). Parameters ---------- filename : str The name of the file, including path if necessary. log : bool Log this event. """ filename = pathToString(filename) self.reset() # set status and timestamps etc self._mov = None # Create Video Stream stuff if os.path.isfile(filename): self._mov = VideoFileClip(filename, audio=(1 - self.noAudio)) if (not self.noAudio) and (self._mov.audio is not None): sound = self.sound try: self._audioStream = sound.Sound( self._mov.audio.to_soundarray(), sampleRate=self._mov.audio.fps) except: # JWE added this as a patch for a moviepy oddity where the # duration is inflated in the saved file causes the # audioclip to be the wrong length, so round down and it # should work jwe_tmp = self._mov.subclip(0, round(self._mov.duration)) self._audioStream = sound.Sound( jwe_tmp.audio.to_soundarray(), sampleRate=self._mov.audio.fps) del(jwe_tmp) else: # make sure we set to None (in case prev clip had audio) self._audioStream = None elif not filename.startswith(prefs.paths['resources']): # If not found, and we aren't already looking in the Resources folder, try again in the Resources folder self.loadMovie(Path(prefs.paths['resources']) / filename, log=False) else: # Raise error if *still* not found raise IOError("Movie file '%s' was not found" % filename) # mov has attributes: # size, duration, fps # mov.audio has attributes # duration, fps (aka sampleRate), to_soundarray() self._frameInterval = 1.0 / self._mov.fps # self.duration = self._mov.duration self.filename = filename self._updateFrameTexture() logAttrib(self, log, 'movie', filename)
def loadMovie(self, filename, audio_filename, log=True): """Load a movie from file :Parameters: filename: string The name of the file, including path if necessary After the file is loaded MovieStim.duration is updated with the movie duration (in seconds). """ self.reset() # set status and timestamps etc # Create Video Stream stuff if os.path.isfile(filename): self._mov = VideoFileClip(filename, audio=(1 - self.noAudio)) if (not self.noAudio) and (self._mov.audio is not None): sound = self.sound if audio_filename == None: try: jwe_tmp = self._mov.subclip(0, round(self._mov.duration)) self._audioStream = sound.Sound( self.jwe_tmp.audio.to_soundarray(), sampleRate=self._mov.audio.fps) except: # JWE added this as a patch for a moviepy oddity where the # duration is inflated in the saved file causes the # audioclip to be the wrong length, so round down and it # should work jwe_tmp = self._mov.subclip(0, round(self._mov.duration)) self._audioStream = sound.Sound( jwe_tmp.audio.to_soundarray(), sampleRate=self._mov.audio.fps) del (jwe_tmp) else: self._audioStream = sound.Sound( audio_filename, sampleRate=self._mov.audio.fps) #print(self._mov.audio.fps) else: # make sure we set to None (in case prev clip had audio) self._audioStream = None else: raise IOError("Movie file '%s' was not found" % filename) # mov has attributes: # size, duration, fps # mov.audio has attributes # duration, fps (aka sampleRate), to_soundarray() self._frameInterval = old_div(1.0, self._mov.fps) self.duration = self._mov.duration self.filename = filename self._updateFrameTexture() logAttrib(self, log, 'movie', filename)
def setTex(self, value, log=True): """Change the texture (all elements have the same base texture). Avoid this during time-critical points in your script. Uploading new textures to the graphics card can be time-consuming. """ self.tex = value self.createTexture(value, id=self._texID, pixFormat=GL.GL_RGB, stim=self, res=self.texRes) logAttrib(self, log, 'tex')
def setFillColor(self, color, colorSpace=None, operation='', log=None): """Sets the color of the shape fill. See :meth:`psychopy.visual.GratingStim.color` for further details of how to use this function. Note that shapes where some vertices point inwards will usually not 'fill' correctly. """ #run the original setColor, which creates color and setColor(self,color, colorSpace=colorSpace, operation=operation, rgbAttrib='fillRGB',#the name for this rgb value colorAttrib='fillColor',#the name for this color ) logAttrib(self, log, 'fillColor', value='%s (%s)' %(self.fillColor, self.fillColorSpace))
def setFieldPos(self,value,operation='', log=True): """Set the centre of the array (X,Y) """ #make into an array if type(value) in [int, float, list, tuple]: value = numpy.array(value, dtype=float) #check shape if value.shape != (2,): raise ValueError("New value for setFieldPos should be [x,y]") #set value and log setWithOperation(self, 'fieldPos', value, operation) logAttrib(self, log, 'fieldPos', type(value))
def seek(self, timestamp, log=True): """ Seek to a particular timestamp in the movie. """ if self.status in [PLAYING, PAUSED]: if self.status == PLAYING: self.pause() if self._audio_stream_player and self._audio_stream_player.is_seekable(): self._audio_stream_player.set_time(int(timestamp*1000.0)) self._video_stream.set(cv2.cv.CV_CAP_PROP_POS_MSEC, timestamp*1000.0) self.play() if log: logAttrib(self, log, 'seek', timestamp)
def seek(self, timestamp, log=True): """Seek to a particular timestamp in the movie. """ if self.status in [PLAYING, PAUSED]: player = self._player if player and player.is_seekable(): player.set_time(int(timestamp * 1000.0)) self._vlc_clock.reset(timestamp) if self.status == PAUSED: self._pause_time = timestamp if log: logAttrib(self, log, 'seek', timestamp)
def setFieldPos(self, value, operation='', log=True): """Set the centre of the array (X,Y) """ #make into an array if type(value) in [int, float, list, tuple]: value = numpy.array(value, dtype=float) #check shape if value.shape != (2, ): raise ValueError("New value for setFieldPos should be [x,y]") #set value and log setWithOperation(self, 'fieldPos', value, operation) logAttrib(self, log, 'fieldPos', type(value)) self._needVertexUpdate = True
def setFont(self, font, log=True): """Set the font to be used for text rendering. font should be a string specifying the name of the font (in system resources) """ self.fontname = None # until we find one if self.win.winType == "pyglet": self._font = pyglet.font.load(font, int(self.heightPix), dpi=72, italic=self.italic, bold=self.bold) self.fontname = font else: if font == None or len(font) == 0: self.fontname = pygame.font.get_default_font() elif font in pygame.font.get_fonts(): self.fontname = font elif type(font) == str: # try to find a xxx.ttf file for it fontFilenames = glob.glob(font + "*") # check for possible matching filenames if len(fontFilenames) > 0: for thisFont in fontFilenames: if thisFont[-4:] in [".TTF", ".ttf"]: self.fontname = thisFont # take the first match break # stop at the first one we find # trhen check if we were successful if self.fontname == None and font != "": # we didn't find a ttf filename logging.warning("Found %s but it doesn't end .ttf. Using default font." % fontFilenames[0]) self.fontname = pygame.font.get_default_font() if self.fontname is not None and os.path.isfile(self.fontname): self._font = pygame.font.Font(self.fontname, int(self.heightPix), italic=self.italic, bold=self.bold) else: try: self._font = pygame.font.SysFont( self.fontname, int(self.heightPix), italic=self.italic, bold=self.bold ) self.fontname = font logging.info("using sysFont " + str(font)) except: self.fontname = pygame.font.get_default_font() logging.error( "Couldn't find font %s on the system. Using %s instead!\n \ Font names should be written as concatenated names all in lower case.\n \ e.g. 'arial', 'monotypecorsiva', 'rockwellextra'..." % (font, self.fontname) ) self._font = pygame.font.SysFont( self.fontname, int(self.heightPix), italic=self.italic, bold=self.bold ) # re-render text after a font change self._needSetText = True logAttrib(self, log, "font", self.fontname)
def setXYs(self, value=None, operation='', log=True): """Set the xy values of the element centres (relative to the centre of the field). Values should be: - None - an array/list of Nx2 coordinates. If value is None then the xy positions will be generated automatically, based on the fieldSize and fieldPos. In this case opacity will also be overridden by this function (it is used to make elements outside the field invisible. """ if value == None: if self.fieldShape in ['sqr', 'square']: self.xys = numpy.random.rand( self.nElements, 2 ) * self.fieldSize - self.fieldSize / 2 #initialise a random array of X,Y #gone outside the square self.xys[:, 0] = ((self.xys[:, 0] + self.fieldSize[0] / 2) % self.fieldSize[0]) - self.fieldSize[0] / 2 self.xys[:, 1] = ((self.xys[:, 1] + self.fieldSize[1] / 2) % self.fieldSize[1]) - self.fieldSize[1] / 2 elif self.fieldShape is 'circle': #take twice as many elements as we need (and cull the ones outside the circle) xys = numpy.random.rand( self.nElements * 2, 2 ) * self.fieldSize - self.fieldSize / 2 #initialise a random array of X,Y #gone outside the square xys[:, 0] = ((xys[:, 0] + self.fieldSize[0] / 2) % self.fieldSize[0]) - self.fieldSize[0] / 2 xys[:, 1] = ((xys[:, 1] + self.fieldSize[1] / 2) % self.fieldSize[1]) - self.fieldSize[1] / 2 #use a circular envelope and flips dot to opposite edge if they fall #beyond radius. #NB always circular - uses fieldSize in X only normxy = xys / (self.fieldSize / 2.0) dotDist = numpy.sqrt((normxy[:, 0]**2.0 + normxy[:, 1]**2.0)) self.xys = xys[dotDist < 1.0, :][0:self.nElements] else: #make into an array if type(value) in [int, float, list, tuple]: value = numpy.array(value, dtype=float) #check shape if not (value.shape in [(), (2, ), (self.nElements, 2)]): raise ValueError( "New value for setXYs should be either None or Nx2") #set value setWithOperation(self, 'xys', value, operation) self._needVertexUpdate = True logAttrib(self, log, 'XYs', type(value))
def setAutoDraw(self, val, log=None): """Add or remove a stimulus from the list of stimuli that will be automatically drawn on each flip :parameters: - val: True/False True to add the stimulus to the draw list, False to remove it """ if val: self.play(log=False) # set to play in case stopped else: self.pause(log=False) #add to drawing list and update status self.__dict__['autoDraw'] = val logAttrib(self, log, 'autoDraw')
def seek(self, timestamp, log=True): """ Seek to a particular timestamp in the movie. Completely untested in all regards. Does not currently work. """ if self.status in [PLAYING, PAUSED]: if self.status == PLAYING: self.pause() if self._audio_stream_player and self._audio_stream_player.is_seekable(): aresult = self._audio_stream_player.set_time(int(timestamp*1000.0)) vresult = self._video_stream.set(cv2.cv.CV_CAP_PROP_POS_MSEC, timestamp*1000.0) self.play() if log: logAttrib(self, log, 'seek', timestamp)
def setFieldSize(self, value, operation='', log=True): """Set the size of the array on the screen (will override current XY positions of the elements) """ #make into an array if type(value) in [int, float, list, tuple]: value = numpy.array(value, dtype=float) #check shape if value.shape not in [(2, ), (1, )]: raise ValueError( "New value for setFieldSize should be [x,y] or a single value") #set value and log setWithOperation(self, 'fieldSize', value, operation) logAttrib(self, log, 'fieldSize') self.setXYs( log=False) #to reflect new settings, overriding individual xys
def loadMovie(self, filename, log=True): """Load a movie from file :Parameters: filename: string The name of the file, including path if necessary Due to VLC oddness, .duration is not correct until the movie starts playing. """ self._reset() self.filename = pathToString(filename) # Initialize VLC self._vlc_start() self.status = NOT_STARTED logAttrib(self, log, 'movie', filename)
def setVertices(self,value=None, operation='', log=True): """Set the xy values of the vertices (relative to the centre of the field). Values should be: - an array/list of Nx2 coordinates. """ #make into an array if type(value) in [int, float, list, tuple]: value = numpy.array(value, dtype=float) #check shape if not (value.shape==(2,) \ or (len(value.shape)==2 and value.shape[1]==2) ): raise ValueError("New value for setXYs should be 2x1 or Nx2") #set value and log setWithOperation(self, 'vertices', value, operation) logAttrib(self, log, 'vertices', value) self._needVertexUpdate=True
def seek(self, timestamp, log=True): """Seek to a particular timestamp in the movie. Parameters ---------- timestamp : float Time in seconds. log : bool Log the seek event. """ if self.isPlaying or self.isPaused: player = self._player if player and player.is_seekable(): # pause while seeking player.set_time(int(timestamp * 1000.0)) if log: logAttrib(self, log, 'seek', timestamp)
def setFont(self, font, log=True): """Set the font to be used for text rendering. font should be a string specifying the name of the font (in system resources) """ self.fontname=None#until we find one if self.win.winType=="pyglet": self._font = pyglet.font.load(font, int(self.heightPix), dpi=72, italic=self.italic, bold=self.bold) self.fontname=font else: if font==None or len(font)==0: self.fontname = pygame.font.get_default_font() elif font in pygame.font.get_fonts(): self.fontname = font elif type(font)==str: #try to find a xxx.ttf file for it fontFilenames = glob.glob(font+'*')#check for possible matching filenames if len(fontFilenames)>0: for thisFont in fontFilenames: if thisFont[-4:] in ['.TTF', '.ttf']: self.fontname = thisFont#take the first match break #stop at the first one we find #trhen check if we were successful if self.fontname == None and font!="": #we didn't find a ttf filename logging.warning("Found %s but it doesn't end .ttf. Using default font." %fontFilenames[0]) self.fontname = pygame.font.get_default_font() if self.fontname is not None and os.path.isfile(self.fontname): self._font = pygame.font.Font(self.fontname, int(self.heightPix), italic=self.italic, bold=self.bold) else: try: self._font = pygame.font.SysFont(self.fontname, int(self.heightPix), italic=self.italic, bold=self.bold) self.fontname = font logging.info('using sysFont ' + str(font)) except: self.fontname = pygame.font.get_default_font() logging.error("Couldn't find font %s on the system. Using %s instead!\n \ Font names should be written as concatenated names all in lower case.\n \ e.g. 'arial', 'monotypecorsiva', 'rockwellextra'..." %(font, self.fontname)) self._font = pygame.font.SysFont(self.fontname, int(self.heightPix), italic=self.italic, bold=self.bold) #re-render text after a font change self._needSetText=True logAttrib(self, log, 'font', self.fontname)
def _set(self, attrib, val, op='', log=True): """ Deprecated. Use methods specific to the parameter you want to set e.g. :: stim.pos = [3,2.5] stim.ori = 45 stim.phase += 0.5 NB this method does not flag the need for updates any more - that is done by specific methods as described above. """ if op==None: op='' #format the input value as float vectors if type(val) in (tuple, list): val=numpy.array(val, float) setWithOperation(self, attrib, val, op) logAttrib(self, log, attrib)
def setColors(self, color, colorSpace=None, operation="", log=None): """See ``color`` for more info on the color parameter and ``colorSpace`` for more info in the colorSpace parameter. """ setColor( self, color, colorSpace=colorSpace, operation=operation, rgbAttrib="rgbs", # or 'fillRGB' etc colorAttrib="colors", colorSpaceAttrib="colorSpace", ) logAttrib(self, log, "colors", value="%s (%s)" % (self.colors, self.colorSpace)) # check shape if self.rgbs.shape in ((), (1,), (3,)): self.rgbs = numpy.resize(self.rgbs, [self.nElements, 3]) elif self.rgbs.shape in ((self.nElements,), (self.nElements, 1)): self.rgbs.shape = (self.nElements, 1) # set to be 2D self.rgbs = self.rgbs.repeat(3, 1) # repeat once on dim 1 elif self.rgbs.shape == (self.nElements, 3): pass # all is good else: raise ValueError("New value for setRgbs should be either " "Nx1, Nx3 or a single value") self._needColorUpdate = True