def writeWindowCode(self, buff): """Setup the window code. """ buff.writeIndentedLines("\n# Setup the Window\n") # get parameters for the Window fullScr = self.params['Full-screen window'].val # if fullscreen then hide the mouse, unless its requested explicitly allowGUI = (not bool(fullScr)) or bool(self.params['Show mouse'].val) allowStencil = False # NB routines is a dict: for thisRoutine in list(self.exp.routines.values()): # a single routine is a list of components: for thisComp in thisRoutine: if thisComp.type == 'Aperture': allowStencil = True if thisComp.type == 'RatingScale': allowGUI = True # to have a mouse requestedScreenNumber = int(self.params['Screen'].val) nScreens = 10 # try: # nScreens = wx.Display.GetCount() # except Exception: # # will fail if application hasn't been created (e.g. in test # # environments) # nScreens = 10 if requestedScreenNumber > nScreens: logging.warn("Requested screen can't be found. Writing script " "using first available screen.") screenNumber = 0 else: # computer has 1 as first screen screenNumber = requestedScreenNumber - 1 size = self.params['Window size (pixels)'] code = ("win = visual.Window(\n size=%s, fullscr=%s, screen=%s," "\n allowGUI=%s, allowStencil=%s,\n") vals = (size, fullScr, screenNumber, allowGUI, allowStencil) buff.writeIndented(code % vals) code = (" monitor=%(Monitor)s, color=%(color)s, " "colorSpace=%(colorSpace)s,\n") if self.params['blendMode'].val: code += " blendMode=%(blendMode)s, useFBO=True,\n" if self.params['Units'].val != 'use prefs': code += " units=%(Units)s" code = code.rstrip(', \n') + ')\n' buff.writeIndentedLines(code % self.params) if 'microphone' in self.exp.psychopyLibs: # need a pyo Server buff.writeIndentedLines("\n# Enable sound input/output:\n" "microphone.switchOn()\n") code = ("# store frame rate of monitor if we can measure it\n" "expInfo['frameRate'] = win.getActualFrameRate()\n" "if expInfo['frameRate'] != None:\n" " frameDur = 1.0 / round(expInfo['frameRate'])\n" "else:\n" " frameDur = 1.0 / 60.0 # could not measure, so guess\n") buff.writeIndentedLines(code)
def setMouseType(self, name='arrow'): """Change the appearance of the cursor for this window. Cursor types provide contextual hints about how to interact with on-screen objects. The graphics used 'standard cursors' provided by the operating system. They may vary in appearance and hot spot location across platforms. The following names are valid on most platforms: 'arrow' : Default pointer 'ibeam' : Indicates text can be edited 'crosshair' : Crosshair with hot-spot at center 'hand' : A pointing hand 'hresize' : Double arrows pointing horizontally 'vresize' : Double arrows pointing vertically Note, on Windows the 'crosshair' option is XORed with the background color. It will not be visible when placed over 50% grey fields. :param name: str, type of standard cursor to use :return: """ try: glfw.set_cursor(self.winHandle, _CURSORS_[name]) except KeyError: logging.warn( "Invalid cursor type name '{}', using default.".format(type)) glfw.set_cursor(self.winHandle, _CURSORS_['arrow'])
def flac2wav(path, keep=True): """Uncompress: convert .flac file (on disk) to .wav format (new file). If `path` is a directory name, convert all .flac files in the directory. `keep` to retain the original .flac file(s), default `True`. """ flac_path = _getFlacPath() flac_files = [] if path.endswith('.flac'): flac_files = [path] elif type(path) == str and os.path.isdir(path): flac_files = glob.glob(os.path.join(path, '*.flac')) if len(flac_files) == 0: logging.warn('failed to find .flac file(s) from %s' % path) return None wav_files = [] for flacfile in flac_files: wavname = flacfile.strip('.flac') + '.wav' flac_cmd = [ flac_path, "-d", "--totally-silent", "-f", "-o", wavname, flacfile ] _junk, se = core.shellCall(flac_cmd, stderr=True) if se: logging.error(se) if not keep: os.unlink(flacfile) wav_files.append(wavname) if len(wav_files) == 1: return wav_files[0] else: return wav_files
def resample(self, newRate=16000, keep=True): """Re-sample the saved file to a new rate, return the full path. Can take several visual frames to resample a 2s recording. The default values for resample() are for google-speech, keeping the original (presumably recorded at 48kHz) to archive. A warning is generated if the new rate not an integer factor / multiple of the old rate. To control anti-aliasing, use pyo.downsamp() or upsamp() directly. """ if not self.savedFile or not os.path.isfile(self.savedFile): msg = '%s: Re-sample requested but no saved file' % self.loggingId logging.error(msg) raise ValueError(msg) if newRate <= 0 or type(newRate) != int: msg = '%s: Re-sample bad new rate = %s' % (self.loggingId, repr(newRate)) logging.error(msg) raise ValueError(msg) # set-up: if self.rate >= newRate: ratio = float(self.rate) / newRate info = '-ds%i' % ratio else: ratio = float(newRate) / self.rate info = '-us%i' % ratio if ratio != int(ratio): logging.warn('%s: old rate is not an integer factor of new rate' % self.loggingId) ratio = int(ratio) newFile = info.join(os.path.splitext(self.savedFile)) # use pyo's downsamp or upsamp based on relative rates: if not ratio: logging.warn('%s: Re-sample by %sx is undefined, skipping' % (self.loggingId, str(ratio))) elif self.rate >= newRate: t0 = time.time() downsamp(self.savedFile, newFile, ratio) # default 128-sample anti-aliasing logging.exp( '%s: Down-sampled %sx in %.3fs to %s' % (self.loggingId, str(ratio), time.time() - t0, newFile)) else: t0 = time.time() upsamp(self.savedFile, newFile, ratio) # default 128-sample anti-aliasing logging.exp( '%s: Up-sampled %sx in %.3fs to %s' % (self.loggingId, str(ratio), time.time() - t0, newFile)) # clean-up: if not keep: os.unlink(self.savedFile) self.savedFile = newFile self.rate = newRate return os.path.abspath(newFile)
def setMouseType(self, name='arrow'): """Change the appearance of the cursor for this window. Cursor types provide contextual hints about how to interact with on-screen objects. The graphics used 'standard cursors' provided by the operating system. They may vary in appearance and hot spot location across platforms. The following names are valid on most platforms: * ``arrow`` : Default pointer * ``ibeam`` : Indicates text can be edited * ``crosshair`` : Crosshair with hot-spot at center * ``hand`` : A pointing hand * ``hresize`` : Double arrows pointing horizontally * ``vresize`` : Double arrows pointing vertically Requires the GLFW backend, otherwise this function does nothing! Note, on Windows the ``crosshair`` option is negated with the background color. It will not be visible when placed over 50% grey fields. Parameters ---------- name : str Type of standard cursor to use. """ try: glfw.set_cursor(self.winHandle, _CURSORS_[name]) except KeyError: logging.warn( "Invalid cursor type name '{}', using default.".format(type)) glfw.set_cursor(self.winHandle, _CURSORS_['arrow'])
def setGammaRamp(pygletWindow, newRamp, nAttempts=3): """Sets the hardware look-up table, using platform-specific ctypes functions. For use with pyglet windows only (pygame has its ow routines for this). Ramp should be provided as 3x256 or 3x1024 array in range 0:1.0 On windows the first attempt to set the ramp doesn't always work. The parameter nAttemps allows the user to determine how many attempts should be made before failing """ if newRamp.shape[0]!=3 and newRamp.shape[1]==3: newRamp= numpy.ascontiguousarray(newRamp.transpose()) if sys.platform=='win32': newRamp= (255.0*newRamp).astype(numpy.uint16) newRamp.byteswap(True)#necessary, according to pyglet post from Martin Spacek for n in range(nAttempts): success = windll.gdi32.SetDeviceGammaRamp(pygletWindow._dc, newRamp.ctypes) if success: break assert success, 'SetDeviceGammaRamp failed' if sys.platform=='darwin': newRamp= (newRamp).astype(numpy.float32) LUTlength=newRamp.shape[1] error =carbon.CGSetDisplayTransferByTable(pygletWindow._screen.id, LUTlength, newRamp[0,:].ctypes, newRamp[1,:].ctypes, newRamp[2,:].ctypes) assert not error, 'CGSetDisplayTransferByTable failed' if sys.platform.startswith('linux') and not _TravisTesting: newRamp= (65535*newRamp).astype(numpy.uint16) success = xf86vm.XF86VidModeSetGammaRamp(pygletWindow._x_display, pygletWindow._x_screen_id, 256, newRamp[0,:].ctypes, newRamp[1,:].ctypes, newRamp[2,:].ctypes) assert success, 'XF86VidModeSetGammaRamp failed' elif _TravisTesting: logging.warn("It looks like we're running in the Travis-CI testing environment. Hardware gamma table cannot be set")
def getGammaRampSize(screenID, xDisplay=None, gammaErrorPolicy=None): """Returns the size of each channel of the gamma ramp.""" if not gammaErrorPolicy: gammaErrorPolicy = defaultGammaErrorPolicy if sys.platform == 'win32' or _vmTesting: # windows documentation (for SetDeviceGammaRamp) seems to indicate that # the LUT size is always 256 rampSize = 256 elif sys.platform == 'darwin': rampSize = carbon.CGDisplayGammaTableCapacity(screenID) elif sys.platform.startswith('linux'): rampSize = ctypes.c_int() success = xf86vm.XF86VidModeGetGammaRampSize(xDisplay, screenID, ctypes.byref(rampSize)) if not success: func = 'XF86VidModeGetGammaRampSize' if gammaErrorPolicy == 'raise': raise OSError(raise_msg.format(func=func)) elif gammaErrorPolicy == 'warn': logging.warning(warn_msg.format(func=func)) else: rampSize = rampSize.value else: rampSize = 256 if rampSize == 0: logging.warn( "The size of the gamma ramp was reported as 0. This can " + "mean that gamma settings have no effect. Proceeding with " + "a default gamma ramp size.") rampSize = 256 return rampSize
def setGammaRamp(pygletWindow, newRamp, nAttempts=3): """Sets the hardware look-up table, using platform-specific ctypes functions. For use with pyglet windows only (pygame has its ow routines for this). Ramp should be provided as 3x256 or 3x1024 array in range 0:1.0 On windows the first attempt to set the ramp doesn't always work. The parameter nAttemps allows the user to determine how many attempts should be made before failing """ if newRamp.shape[0]!=3 and newRamp.shape[1]==3: newRamp= numpy.ascontiguousarray(newRamp.transpose()) if sys.platform=='win32': newRamp= (255.0*newRamp).astype(numpy.uint16) newRamp.byteswap(True)#necessary, according to pyglet post from Martin Spacek for n in range(nAttempts): success = windll.gdi32.SetDeviceGammaRamp(0xFFFFFFFF & pygletWindow._dc, newRamp.ctypes) # FB 504 if success: break assert success, 'SetDeviceGammaRamp failed' if sys.platform=='darwin': newRamp= (newRamp).astype(numpy.float32) LUTlength=newRamp.shape[1] error =carbon.CGSetDisplayTransferByTable(pygletWindow._screen.id, LUTlength, newRamp[0,:].ctypes, newRamp[1,:].ctypes, newRamp[2,:].ctypes) assert not error, 'CGSetDisplayTransferByTable failed' if sys.platform.startswith('linux') and not _TravisTesting: newRamp= (65535*newRamp).astype(numpy.uint16) success = xf86vm.XF86VidModeSetGammaRamp(pygletWindow._x_display, pygletWindow._x_screen_id, 256, newRamp[0,:].ctypes, newRamp[1,:].ctypes, newRamp[2,:].ctypes) assert success, 'XF86VidModeSetGammaRamp failed' elif _TravisTesting: logging.warn("It looks like we're running in the Travis-CI testing environment. Hardware gamma table cannot be set")
def wav2flac(path, keep=True): """Lossless compression: convert .wav file (on disk) to .flac format. If `path` is a directory name, convert all .wav files in the directory. `keep` to retain the original .wav file(s), default `True`. """ flac_path = _getFlacPath() wav_files = [] if path.endswith(".wav"): wav_files = [path] elif type(path) == str and os.path.isdir(path): wav_files = glob.glob(os.path.join(path, "*.wav")) if len(wav_files) == 0: logging.warn("failed to find .wav file(s) from %s" % path) return None flac_files = [] for wavfile in wav_files: flacfile = wavfile.strip(".wav") + ".flac" flac_cmd = [flac_path, "-8", "-f", "--totally-silent", "-o", flacfile, wavfile] __, se = core.shellCall(flac_cmd, stderr=True) if se or not os.path.isfile(flacfile): # just try again # ~2% incidence when recording for 1s, 650+ trials # never got two in a row; core.wait() does not help logging.warn("Failed to convert to .flac; trying again") __, se = core.shellCall(flac_cmd, stderr=True) if se: logging.error(se) if not keep: os.unlink(wavfile) flac_files.append(flacfile) if len(wav_files) == 1: return flac_files[0] else: return flac_files
def load(self, filename=None): """If name is None then we'll try to save to """ def parseLUTLine(line): return line.replace('[','').replace(']','').split(',') if filename is None: from psychopy import prefs filename = os.path.join(prefs.paths['userPrefsDir'], 'crs_bits.cfg') if os.path.exists(filename): config = configparser.RawConfigParser() with open(filename) as f: config.readfp(f) self.os = config.get('system','os') self.gfxCard = config.get('system','gfxCard') self.identityLUT = np.ones([256,3]) self.identityLUT[:,0] = parseLUTLine(config.get('identityLUT','r')) self.identityLUT[:,1] = parseLUTLine(config.get('identityLUT','g')) self.identityLUT[:,2] = parseLUTLine(config.get('identityLUT','b')) return True else: logging.warn('no config file yet for %s' %self.bits) self.identityLUT = None self.gfxCard = None self.os = None return False
def __init__(self, project_file=None, root_path=None, osf=None, name='', autosave=True): self.autosave = autosave # try to save file automatically on __del__ self.project_file = project_file self.root_path = root_path # overwrite previous (indexed) location self.name = name # not needed but allows storing a short descr name # these will be update from project file loading if it exists self.index = [] self.username = None self.project_id = None self.connected = False # have we gone online yet? # load the project file (if exists) for info about previous sync if project_file: self.load(project_file) # check/set root_path if self.root_path is None: self.root_path = root_path # use what we just loaded elif root_path not in [None, self.root_path]: logging.warn("The requested root_path and the previous root_path " "differ. Using the requested path." "given: {}" "stored: {}".format(root_path, self.root_path)) if self.root_path is None: logging.warn("Project file failed to load a root_path " "for the local files and none was provided") self.osf = osf # the self.osf is as property set on-access
def load(self, filename=None): """If name is None then we'll try to save to """ def parseLUTLine(line): return line.replace("[", "").replace("]", "").split(",") if filename is None: from psychopy import prefs filename = os.path.join(prefs.paths["userPrefsDir"], "crs_bits.cfg") if os.path.exists(filename): config = configparser.RawConfigParser() with open(filename) as f: config.readfp(f) self.os = config.get("system", "os") self.gfxCard = config.get("system", "gfxCard") self.identityLUT = np.ones([256, 3]) _idLUT = "identityLUT" self.identityLUT[:, 0] = parseLUTLine(config.get(_idLUT, "r")) self.identityLUT[:, 1] = parseLUTLine(config.get(_idLUT, "g")) self.identityLUT[:, 2] = parseLUTLine(config.get(_idLUT, "b")) return True else: logging.warn("no config file yet for %s" % self.bits) self.identityLUT = None self.gfxCard = None self.os = None return False
def _bestDriver(devNames, devIDs): """Find ASIO or Windows sound drivers """ preferredDrivers = prefs.general['audioDriver'] outputID = None audioDriver = None osEncoding = sys.getfilesystemencoding() for prefDriver in preferredDrivers: logging.info('Looking for {}'.format(prefDriver)) if prefDriver.lower() == 'directsound': prefDriver = u'Primary Sound' # look for that driver in available devices for devN, devString in enumerate(devNames): logging.info('Examining for {}'.format(devString)) try: ds = devString.decode(osEncoding).encode('utf-8').lower() if prefDriver.encode('utf-8').lower() in ds: audioDriver = devString.decode(osEncoding).encode('utf-8') outputID = devIDs[devN] logging.info('Success: {}'.format(devString)) # we found a driver don't look for others return audioDriver, outputID except (UnicodeDecodeError, UnicodeEncodeError): logging.info('Failed: {}'.format(devString)) logging.warn('find best sound driver - could not ' 'interpret unicode in driver name') else: return None, None
def flac2wav(path, keep=True): """Uncompress: convert .flac file (on disk) to .wav format (new file). If `path` is a directory name, convert all .flac files in the directory. `keep` to retain the original .flac file(s), default `True`. """ flac_path = _getFlacPath() flac_files = [] if path.endswith('.flac'): flac_files = [path] elif type(path) == str and os.path.isdir(path): flac_files = glob.glob(os.path.join(path, '*.flac')) if len(flac_files) == 0: logging.warn('failed to find .flac file(s) from %s' % path) return None wav_files = [] for flacfile in flac_files: wavname = flacfile.strip('.flac') + '.wav' flac_cmd = [flac_path, "-d", "--totally-silent", "-f", "-o", wavname, flacfile] _junk, se = core.shellCall(flac_cmd, stderr=True) if se: logging.error(se) if not keep: os.unlink(flacfile) wav_files.append(wavname) if len(wav_files) == 1: return wav_files[0] else: return wav_files
def __init__(self, win, size, pos=(0,0), ori=0, nVert=120, shape='circle', units=None, name='', autoLog=True): #what local vars are defined (these are the init params) for use by __repr__ self._initParams = dir() self._initParams.remove('self') #set self params self.autoLog=False #set this False first and change after attribs are set self.win=win self.name = name self.ori = ori #unit conversions if units!=None and len(units): self.units = units else: self.units = win.units # ugly hack for setting vertices using combination of shape and nVerts if type(nVert) == int: self.nVert = nVert regularPolygon = True self.shape = shape unrecognized = False if shape is None: pass #just use the nVert we were given elif type(shape) in [str, unicode]: if shape.lower() == 'circle': pass #just use the nVert we were given elif shape.lower() == 'square': regularPolygon = False # if we use polygon then we have to hack the orientation vertices = [[0.5,-0.5],[-0.5,-0.5],[-0.5,0.5],[0.5,0.5]] elif shape.lower() == 'triangle': regularPolygon = False # if we use polygon then we have to hack the orientation vertices = [[0.5,-0.5],[0,0.5],[-0.5,-0.5]] else: unrecognized = True elif type(shape) in [tuple, list, numpy.ndarray]: regularPolygon = False vertices = shape else: unrecognized = True if unrecognized: logging.warn("Unrecognized shape for aperture. Expected 'circle', 'square', 'triangle', vertices or None but got %s" %(repr(shape))) if regularPolygon: self._shape = polygon.Polygon(win=self.win, edges=self.nVert, fillColor=1, lineColor=None, interpolate=False, pos=pos, size=size) else: self._shape = ShapeStim(win=self.win, vertices=vertices, fillColor=1, lineColor=None, interpolate=False, pos=pos, size=size) self._needVertexUpdate = True self._reset()#implicitly runs an self.enable() self.autoLog= autoLog if autoLog: logging.exp("Created %s = %s" %(self.name, str(self)))
def wav2flac(path, keep=True): """Lossless compression: convert .wav file (on disk) to .flac format. If `path` is a directory name, convert all .wav files in the directory. `keep` to retain the original .wav file(s), default `True`. """ flac_path = _getFlacPath() wav_files = [] if path.endswith('.wav'): wav_files = [path] elif type(path) == str and os.path.isdir(path): wav_files = glob.glob(os.path.join(path, '*.wav')) if len(wav_files) == 0: logging.warn('failed to find .wav file(s) from %s' % path) return None flac_files = [] for wavfile in wav_files: flacfile = wavfile.strip('.wav') + '.flac' flac_cmd = [flac_path, "-8", "-f", "--totally-silent", "-o", flacfile, wavfile] __, se = core.shellCall(flac_cmd, stderr=True) if se or not os.path.isfile(flacfile): # just try again # ~2% incidence when recording for 1s, 650+ trials # never got two in a row; core.wait() does not help logging.warn('Failed to convert to .flac; trying again') __, se = core.shellCall(flac_cmd, stderr=True) if se: logging.error(se) if not keep: os.unlink(wavfile) flac_files.append(flacfile) if len(wav_files) == 1: return flac_files[0] else: return flac_files
def load(self, filename=None): """If name is None then we'll try to save to """ def parseLUTLine(line): return line.replace('[', '').replace(']', '').split(',') if filename is None: from psychopy import prefs filename = os.path.join(prefs.paths['userPrefsDir'], 'crs_bits.cfg') if os.path.exists(filename): config = configparser.RawConfigParser() with open(filename) as f: config.readfp(f) self.os = config.get('system', 'os') self.gfxCard = config.get('system', 'gfxCard') self.identityLUT = np.ones([256, 3]) _idLUT = 'identityLUT' self.identityLUT[:, 0] = parseLUTLine(config.get(_idLUT, 'r')) self.identityLUT[:, 1] = parseLUTLine(config.get(_idLUT, 'g')) self.identityLUT[:, 2] = parseLUTLine(config.get(_idLUT, 'b')) return True else: logging.warn('no config file yet for %s' % self.bits) self.identityLUT = None self.gfxCard = None self.os = None return False
def writeWindowCode(self, buff): """ setup the window code """ buff.writeIndentedLines("\n# Setup the Window\n") #get parameters for the Window fullScr = self.params['Full-screen window'].val allowGUI = (not bool(fullScr)) or bool( self.params['Show mouse'].val ) #if fullscreen then hide the mouse, unless its requested explicitly allowStencil = False for thisRoutine in self.exp.routines.values(): #NB routines is a dict for thisComp in thisRoutine: #a single routine is a list of components if thisComp.type == 'Aperture': allowStencil = True if thisComp.type == 'RatingScale': allowGUI = True # to have a mouse; BUT might not want it shown in other routines requestedScreenNumber = int(self.params['Screen'].val) if requestedScreenNumber > wx.Display.GetCount(): logging.warn( "Requested screen can't be found. Writing script using first available screen." ) screenNumber = 0 else: screenNumber = requestedScreenNumber - 1 #computer has 1 as first screen if fullScr: size = wx.Display(screenNumber).GetGeometry()[2:4] else: size = self.params['Window size (pixels)'] buff.writeIndented( "win = visual.Window(size=%s, fullscr=%s, screen=%s, allowGUI=%s, allowStencil=%s,\n" % (size, fullScr, screenNumber, allowGUI, allowStencil)) buff.writeIndented( " monitor=%(Monitor)s, color=%(color)s, colorSpace=%(colorSpace)s,\n" % (self.params)) if self.params['blendMode'].val: buff.writeIndented(" blendMode=%(blendMode)s, useFBO=True,\n" % (self.params)) if self.params['Units'].val == 'use prefs': buff.write(" )\n") else: buff.write(" units=%s)\n" % self.params['Units']) if 'microphone' in self.exp.psychopyLibs: # need a pyo Server buff.writeIndentedLines("\n# Enable sound input/output:\n" + "microphone.switchOn()\n") buff.writeIndented( "# store frame rate of monitor if we can measure it successfully\n" ) buff.writeIndented("expInfo['frameRate']=win.getActualFrameRate()\n") buff.writeIndented("if expInfo['frameRate']!=None:\n") buff.writeIndented(" frameDur = 1.0/round(expInfo['frameRate'])\n") buff.writeIndented("else:\n") buff.writeIndented( " frameDur = 1.0/60.0 # couldn't get a reliable measure so guess\n" )
def getGammaRamp(screenID, xDisplay=None, gammaErrorPolicy='raise'): """Ramp will be returned as 3xN array in range 0:1 """ rampSize = getGammaRampSize(screenID, xDisplay=xDisplay) if sys.platform == 'win32': # init R, G, and B ramps origramps = numpy.empty((3, rampSize), dtype=numpy.uint16) success = windll.gdi32.GetDeviceGammaRamp(screenID, origramps.ctypes) # FB 504 if not success: func = 'GetDeviceGammaRamp' if gammaErrorPolicy == 'raise': raise OSError(raise_msg.format(func=func)) elif gammaErrorPolicy == 'warn': logging.warning(warn_msg.format(func=func)) else: origramps.byteswap(True) # back to 0:255 origramps = origramps / 255.0 # rescale to 0:1 if sys.platform == 'darwin': # init R, G, and B ramps origramps = numpy.empty((3, rampSize), dtype=numpy.float32) n = numpy.empty([1], dtype=numpy.int) error = carbon.CGGetDisplayTransferByTable(screenID, rampSize, origramps[0, :].ctypes, origramps[1, :].ctypes, origramps[2, :].ctypes, n.ctypes) if error: func = 'CGSetDisplayTransferByTable' if gammaErrorPolicy == 'raise': raise OSError(raise_msg.format(func=func)) elif gammaErrorPolicy == 'warn': logging.warning(warn_msg.format(func=func)) if sys.platform.startswith('linux') and not _TravisTesting: origramps = numpy.empty((3, rampSize), dtype=numpy.uint16) success = xf86vm.XF86VidModeGetGammaRamp(xDisplay, screenID, rampSize, origramps[0, :].ctypes, origramps[1, :].ctypes, origramps[2, :].ctypes) if not success: func = 'XF86VidModeGetGammaRamp' if gammaErrorPolicy == 'raise': raise OSError(raise_msg.format(func=func)) elif gammaErrorPolicy == 'warn': logging.warning(warn_msg.format(func=func)) else: origramps = origramps / 65535.0 # rescale to 0:1 elif _TravisTesting: logging.warn("It looks like we're running in the Travis-CI testing " "environment. Hardware gamma table cannot be retrieved") origramps = None return origramps
def resample(self, newRate=16000, keep=True, log=True): """Re-sample the saved file to a new rate, return the full path. Can take several visual frames to resample a 2s recording. The default values for resample() are for google-speech, keeping the original (presumably recorded at 48kHz) to archive. A warning is generated if the new rate not an integer factor / multiple of the old rate. To control anti-aliasing, use pyo.downsamp() or upsamp() directly. """ if not self.savedFile or not os.path.isfile(self.savedFile): msg = "%s: Re-sample requested but no saved file" % self.loggingId logging.error(msg) raise ValueError(msg) if newRate <= 0 or type(newRate) != int: msg = "%s: Re-sample bad new rate = %s" % (self.loggingId, repr(newRate)) logging.error(msg) raise ValueError(msg) # set-up: if self.rate >= newRate: ratio = float(self.rate) / newRate info = "-ds%i" % ratio else: ratio = float(newRate) / self.rate info = "-us%i" % ratio if ratio != int(ratio): logging.warn("%s: old rate is not an integer factor of new rate" % self.loggingId) ratio = int(ratio) newFile = info.join(os.path.splitext(self.savedFile)) # use pyo's downsamp or upsamp based on relative rates: if not ratio: logging.warn("%s: Re-sample by %sx is undefined, skipping" % (self.loggingId, str(ratio))) elif self.rate >= newRate: t0 = core.getTime() downsamp(self.savedFile, newFile, ratio) # default 128-sample anti-aliasing if log and self.autoLog: logging.exp( "%s: Down-sampled %sx in %.3fs to %s" % (self.loggingId, str(ratio), core.getTime() - t0, newFile) ) else: t0 = core.getTime() upsamp(self.savedFile, newFile, ratio) # default 128-sample anti-aliasing if log and self.autoLog: logging.exp( "%s: Up-sampled %sx in %.3fs to %s" % (self.loggingId, str(ratio), core.getTime() - t0, newFile) ) # clean-up: if not keep: os.unlink(self.savedFile) self.savedFile = newFile self.rate = newRate return os.path.abspath(newFile)
def run_event(self): if self.event == 'exit': logging.info("Exiting. . .") self.window.close() core.quit() if self.event in ['nothing', 'continue']: pass else: logging.warn("Event not recognized. Doing nothing.")
def _create_window(self): """ Creates a window based on the settings and calculates framerate. """ win = Window(monitor=self.monitor.name, **self.settings['window']) win.flip(clearBuffer=True) self.actual_framerate = win.getActualFrameRate() t_per_frame = 1. / self.actual_framerate logging.warn(f"Actual framerate: {self.actual_framerate:.5f} " f"(1 frame = {t_per_frame:.5f})") return win
def setUseShaders(self, val=True): """Set this stimulus to use shaders if possible. """ if val==True and self.win._haveShaders==False: logging.warn("Shaders were requested but aren;t available. Shaders need OpenGL 2.0+ drivers") if val!=self.useShaders: self.useShaders=val self._needSetText=True self._needUpdate = True
def run_event(self): if self.event == "exit": logging.info("Exiting. . .") self.window.close() core.quit() if self.event in ["nothing", "continue"]: pass else: logging.warn("Event not recognized. Doing nothing.")
def __init__(self, output_str, subject=None, output_dir=None, settings_file=None): super().__init__(output_str, subject=subject, output_dir=output_dir, settings_file=settings_file, run=run, eyetracker_on=False) logging.warn(self.settings['run']) self.buttons = self.settings['various'].get('buttons') self.image2 = ImageStim(self.win, self.settings['pile'].get('image2'), texRes=32, size=self.settings['pile'].get('dot_radius'))
def quickCheck(self): """Check whether the current graphics card and OS match those of the last saved LUT """ if self._getGfxCardString() != self.gfxCard: logging.warn("The graphics card or its driver has changed. We'll re-check the identity LUT for the card") return 0 if self._getOSstring() != self.os: logging.warn("The OS has been changed/updated. We'll re-check the identity LUT for the card") return 0 return 1 #all seems the same as before
def _warnTesting(self): msg = "We need to run some tests on your graphics card (hopefully just once).\n" + \ "The BitsSharp will go into status mode while this is done.\n" + \ "It can take a minute of two." logging.warn(msg) logging.flush() msgOnScreen = visual.TextStim(self.win, msg) msgOnScreen.draw() self.win.flip() core.wait(1.0) self.win.flip()
def _warnTesting(self): msg = "We need to run some tests on your graphics card (hopefully just once). " + \ "The BitsSharp will go into status mode while this is done. " + \ "It can take a minute or two." logging.warn(msg) logging.flush() msgOnScreen = visual.TextStim(self.win, msg) msgOnScreen.draw() self.win.flip() core.wait(1.0) self.win.flip()
def __init__(self, outpath, nameDict, first_columns): self.columns = nameDict.keys() self.outpath = outpath self.outdir = os.path.dirname(outpath) if len(self.columns) != len(set(self.columns)): logging.warn("There are duplicate file names in the logfile!") self.data = pd.DataFrame(columns=self.columns) self.defaultTrial = nameDict self.curRowIdx = 0 self.first_columns = first_columns
def _create_window(self): """ Creates a window based on the settings and calculates framerate. """ win = Window(monitor=self.monitor.name, **self.settings['window']) win.flip(clearBuffer=True) self.actual_framerate = win.getActualFrameRate() if self.actual_framerate is None: logging.warn("framerate not measured, substituting 60 by default") self.actual_framerate = 60.0 t_per_frame = 1. / self.actual_framerate logging.warn(f"Actual framerate: {self.actual_framerate:.5f} " f"(1 frame = {t_per_frame:.5f})") return win
def setUser(self, user): if user == self._user: return # nothing to do here. Move along please. self._user = user try: self.app.osf_session = pyosf.Session(user) except pyosf.AuthError: print("failed to authenticate - probably need 2FA") except requests.exceptions.ConnectionError: logging.warn("Connection error trying to connect to pyosf") ProjectsMenu.appData['user'] = user if self.searchDlg: self.searchDlg.updateUserProjs()
def get_output_dir_str(subject, session, task, run): output_dir = op.join(op.dirname(__file__), 'logs', f'sub-{subject}') logging.warn(f'Writing results to {output_dir}') if session: output_dir = op.join(output_dir, f'ses-{session}') output_str = f'sub-{subject}_ses-{session}_task-{task}' else: output_str = f'sub-{subject}_task-{task}' if run: output_str += f'_run-{run}' return output_dir, output_str
def oneAttempt(): self.com.flushInput() self.sendMessage('$GetVideoLine=[%i, %i]\r' %(lineN, nPixels)) #prepare to read t0 = time.time() raw="" vals=[] while len(vals)<(nPixels*3): raw += self.read(timeout=0.001) vals = raw.split(';')[1:-1] if (time.time()-t0)>timeout: logging.warn("getVideoLine() timed out: only found %i pixels in %.2f s" %(len(vals), timeout)) break return np.array(vals, dtype=int).reshape([-1,3])
def writeWindowCode(self,buff): """ setup the window code """ buff.writeIndentedLines("\n# Setup the Window\n") #get parameters for the Window fullScr = self.params['Full-screen window'].val allowGUI = (not bool(fullScr)) or bool(self.params['Show mouse'].val) #if fullscreen then hide the mouse, unless its requested explicitly allowStencil = False for thisRoutine in self.exp.routines.values(): #NB routines is a dict for thisComp in thisRoutine: #a single routine is a list of components if thisComp.type=='Aperture': allowStencil = True if thisComp.type=='RatingScale': allowGUI = True # to have a mouse; BUT might not want it shown in other routines requestedScreenNumber = int(self.params['Screen'].val) try: nScreens = wx.Display.GetCount() except: nScreens = 10 #will fail if application hasn't been created (e.g. in test environments) if requestedScreenNumber > nScreens: logging.warn("Requested screen can't be found. Writing script using first available screen.") screenNumber = 0 else: screenNumber = requestedScreenNumber-1 #computer has 1 as first screen if fullScr: size = wx.Display(screenNumber).GetGeometry()[2:4] else: size=self.params['Window size (pixels)'] buff.writeIndented("win = visual.Window(size=%s, fullscr=%s, screen=%s, allowGUI=%s, allowStencil=%s,\n" % (size, fullScr, screenNumber, allowGUI, allowStencil)) buff.writeIndented(" monitor=%(Monitor)s, color=%(color)s, colorSpace=%(colorSpace)s,\n" %(self.params)) if self.params['blendMode'].val: buff.writeIndented(" blendMode=%(blendMode)s, useFBO=True,\n" %(self.params)) if self.params['Units'].val=='use prefs': buff.write(" )\n") else: buff.write(" units=%s)\n" %self.params['Units']) if 'microphone' in self.exp.psychopyLibs: # need a pyo Server buff.writeIndentedLines("\n# Enable sound input/output:\n"+ "microphone.switchOn()\n") buff.writeIndented("# store frame rate of monitor if we can measure it successfully\n") buff.writeIndented("expInfo['frameRate'] = win.getActualFrameRate()\n") buff.writeIndented("if expInfo['frameRate'] != None:\n") buff.writeIndented(" frameDur = 1.0 / round(expInfo['frameRate'])\n") buff.writeIndented("else:\n") buff.writeIndented(" frameDur = 1.0 / 60.0 # couldn't get a reliable measure so guess\n")
def oneAttempt(): self.com.flushInput() self.sendMessage('$GetVideoLine=[%i, %i]\r' %(lineN, nPixels)) self.__dict__['mode'] = 'status' #the box implicitly ends up in status mode #prepare to read t0 = time.time() raw="" vals=[] while len(vals)<(nPixels*3): raw += self.read(timeout=0.001) vals = raw.split(';')[1:-1] if (time.time()-t0)>timeout: logging.warn("getVideoLine() timed out: only found %i pixels in %.2f s" %(len(vals), timeout)) return [] return np.array(vals, dtype=int).reshape([-1,3])
def complete(self): """Completes the period, using up whatever time is remaining with a call to wait() :return: 1 for success, 0 for fail (the period overran) """ self.status=FINISHED timeRemaining = self.countdown.getTime() if self.win: self.win.recordFrameIntervals = self._winWasRecordingIntervals if timeRemaining<0: logging.warn('We overshot the intended duration of %s by %.4fs. The intervening code took too long to execute.' %(self.name, abs(timeRemaining))) return 0 else: wait(timeRemaining) return 1
def saveAsJson(self, fileName=None, encoding='utf-8', fileCollisionMethod='rename'): """ Serialize the object to the JSON format. Parameters ---------- fileName: string, or None the name of the file to create or append. Can include a relative or absolute path. If `None`, will not write to a file, but return an in-memory JSON object. encoding : string, optional The encoding to use when writing the file. This parameter will be ignored if `append` is `False` and `fileName` ends with `.psydat` or `.npy` (i.e. if a binary file is to be written). fileCollisionMethod : string Collision method passed to :func:`~psychopy.tools.fileerrortools.handleFileCollision`. Can be either of `'rename'`, `'overwrite'`, or `'fail'`. Notes ----- Currently, a copy of the object is created, and the copy's .origin attribute is set to an empty string before serializing because loading the created JSON file would sometimes fail otherwise. """ fileName = pathToString(fileName) self_copy = copy.deepcopy(self) self_copy.origin = '' msg = ('Setting attribute .origin to empty string during JSON ' 'serialization.') logging.warn(msg) if (fileName is None) or (fileName == 'stdout'): return json_tricks.dumps(self_copy) else: with openOutputFile(fileName=fileName, fileCollisionMethod=fileCollisionMethod, encoding=encoding) as f: json_tricks.dump(self_copy, f) logging.info('Saved JSON data to %s' % f.name)
def saveAsJson(self, fileName=None, encoding='utf-8', fileCollisionMethod='rename'): """ Serialize the object to the JSON format. Parameters ---------- fileName: string, or None the name of the file to create or append. Can include a relative or absolute path. If `None`, will not write to a file, but return an in-memory JSON object. encoding : string, optional The encoding to use when writing the file. This parameter will be ignored if `append` is `False` and `fileName` ends with `.psydat` or `.npy` (i.e. if a binary file is to be written). fileCollisionMethod : string Collision method passed to :func:`~psychopy.tools.fileerrortools.handleFileCollision`. Can be either of `'rename'`, `'overwrite'`, or `'fail'`. Notes ----- Currently, a copy of the object is created, and the copy's .origin attribute is set to an empty string before serializing because loading the created JSON file would sometimes fail otherwise. """ self_copy = copy.deepcopy(self) self_copy.origin = '' msg = ('Setting attribute .origin to empty string during JSON ' 'serialization.') logging.warn(msg) if fileName is None: return json_tricks.np.dumps(self_copy) else: f = openOutputFile(fileName, fileCollisionMethod=fileCollisionMethod, encoding=encoding) json_tricks.np.dump(self_copy, f) if f != sys.stdout: f.close() logging.info('Saved JSON data to %s' % f.name)
def __init__(self, output_str, subject=None, output_dir=None, settings_file=None, run=None, eyetracker_on=False): print(settings_file) super().__init__(output_str, subject=subject, output_dir=output_dir, settings_file=settings_file, run=run, eyetracker_on=eyetracker_on) logging.warn(self.settings['run'])
def _load_settings(self): """ Loads settings and sets preferences. """ if self.settings_file is None: self.settings_file = op.join(op.dirname(__file__), 'default_settings.yml') logging.warn(f"Using default logfile ({self.settings_file}") with open(self.settings_file, 'r') as f_in: settings = yaml.load(f_in) exp_prefs = settings['preferences'] # set preferences globally for preftype, these_settings in exp_prefs.items(): for key, value in these_settings.items(): pref_subclass = getattr(psychopy_prefs, preftype) pref_subclass[key] = value setattr(psychopy_prefs, preftype, pref_subclass) return settings
def oneAttempt(): self.com.flushInput() self.sendMessage("$GetVideoLine=[%i, %i]\r" % (lineN, nPixels)) # the box implicitly ends up in status mode self.__dict__["mode"] = "status" # prepare to read t0 = time.time() raw = "" vals = [] while len(vals) < (nPixels * 3): raw += self.read(timeout=0.001) vals = raw.split(";")[1:-1] if time.time() - t0 > timeout: msg = "getVideoLine() timed out: only found %i pixels" " in %.2f s" logging.warn(msg % (len(vals), timeout)) return [] return np.array(vals, dtype=int).reshape([-1, 3])
def saveAsJson(self, fileName=None, encoding='utf-8', fileCollisionMethod='rename'): """ Serialize the object to the JSON format. Parameters ---------- fileName: string, or None the name of the file to create or append. Can include a relative or absolute path. If `None`, will not write to a file, but return an in-memory JSON object. encoding : string, optional The encoding to use when writing the file. fileCollisionMethod : string Collision method passed to :func:`~psychopy.tools.fileerrortools.handleFileCollision`. Can be either of `'rename'`, `'overwrite'`, or `'fail'`. Notes ----- Currently, a copy of the object is created, and the copy's .origin attribute is set to an empty string before serializing because loading the created JSON file would sometimes fail otherwise. """ fileName = pathToString(fileName) self_copy = copy.deepcopy(self) self_copy.origin = '' msg = ('Setting attribute .origin to empty string during JSON ' 'serialization.') logging.warn(msg) if (fileName is None) or (fileName == 'stdout'): return json_tricks.dumps(self_copy) else: with openOutputFile(fileName=fileName, fileCollisionMethod=fileCollisionMethod, encoding=encoding) as f: json_tricks.dump(self_copy, f) logging.info('Saved JSON data to %s' % f.name)
def complete(self): """Completes the period, using up whatever time is remaining with a call to wait() :return: 1 for success, 0 for fail (the period overran) """ self.status = FINISHED timeRemaining = self.countdown.getTime() if self.win: self.win.recordFrameIntervals = self._winWasRecordingIntervals if timeRemaining < 0: logging.warn( 'We overshot the intended duration of %s by %.4fs. The intervening code took too long to execute.' % (self.name, abs(timeRemaining))) return 0 else: wait(timeRemaining) return 1
def load_next_trial(self, phase_dur): self.draw() # draw this phase, then load self.session.win.flip() load_start = self.session.clock.getTime() try: self.session.create_trial(self.trial_nr+1) except Exception as err: # not quite happy about this try/except part ... logging.warn('Cannot create trial - probably at last one ' f'(trial {self.trial_nr})!') raise(err) load_dur = self.session.clock.getTime() - load_start if load_dur > phase_dur: # overshoot! not good! logging.warn(f'Time to load stimulus ({load_dur:.5f}) is longer than' f' phase-duration {phase_dur:.5f} (trial {self.trial_nr})!')
def getGammaRamp(screenID, xDisplay=None): """Ramp will be returned as 3xN array in range 0:1 """ rampSize = getGammaRampSize(screenID, xDisplay=xDisplay) if sys.platform == 'win32': # init R, G, and B ramps origramps = numpy.empty((3, rampSize), dtype=numpy.uint16) success = windll.gdi32.GetDeviceGammaRamp( screenID, origramps.ctypes) # FB 504 if not success: raise AssertionError('GetDeviceGammaRamp failed') origramps.byteswap(True) # back to 0:255 origramps = origramps/255.0 # rescale to 0:1 if sys.platform == 'darwin': # init R, G, and B ramps origramps = numpy.empty((3, rampSize), dtype=numpy.float32) n = numpy.empty([1], dtype=numpy.int) error = carbon.CGGetDisplayTransferByTable( screenID, rampSize, origramps[0, :].ctypes, origramps[1, :].ctypes, origramps[2, :].ctypes, n.ctypes) if error: raise AssertionError('CGSetDisplayTransferByTable failed') if sys.platform.startswith('linux') and not _TravisTesting: origramps = numpy.empty((3, rampSize), dtype=numpy.uint16) success = xf86vm.XF86VidModeGetGammaRamp( xDisplay, screenID, rampSize, origramps[0, :].ctypes, origramps[1, :].ctypes, origramps[2, :].ctypes) if not success: raise AssertionError('XF86VidModeGetGammaRamp failed') origramps = origramps/65535.0 # rescale to 0:1 elif _TravisTesting: logging.warn("It looks like we're running in the Travis-CI testing " "environment. Hardware gamma table cannot be retrieved") origramps = None return origramps
def _bestDriver(devNames, devIDs): """Find ASIO or Windows sound drivers """ preferredDrivers = prefs.general['audioDriver'] outputID=None audioDriver=None for prefDriver in preferredDrivers: if prefDriver.lower()=='directsound': prefDriver = 'Primary Sound' #look for that driver in available devices for devN, devString in enumerate(devNames): try: if prefDriver.encode('utf-8') in devString.encode('utf-8'): audioDriver=devString outputID=devIDs[devN] return audioDriver, outputID #we found an asio driver don'w look for others except UnicodeDecodeError, UnicodeEncodeError: logging.warn('find best sound driver - could not interpret unicode in driver name')
def _bestDriver(devNames, devIDs): """Find ASIO or Windows sound drivers """ preferredDrivers = prefs.general["audioDriver"] outputID = None audioDriver = None for prefDriver in preferredDrivers: if prefDriver.lower() == "directsound": prefDriver = "Primary Sound" # look for that driver in available devices for devN, devString in enumerate(devNames): try: if prefDriver.encode("utf-8") in devString.encode("utf-8"): audioDriver = devString outputID = devIDs[devN] return audioDriver, outputID # we found an asio driver don'w look for others except UnicodeDecodeError, UnicodeEncodeError: logging.warn("find best sound driver - could not interpret unicode in driver name")
def getGammaRampSize(screenID, xDisplay=None): """Returns the size of each channel of the gamma ramp.""" if sys.platform == 'win32': # windows documentation (for SetDeviceGammaRamp) seems to indicate that # the LUT size is always 256 rampSize = 256 elif sys.platform == 'darwin': rampSize = carbon.CGDisplayGammaTableCapacity(screenID) elif sys.platform.startswith('linux') and not _TravisTesting: rampSize = ctypes.c_int() success = xf86vm.XF86VidModeGetGammaRampSize( xDisplay, screenID, ctypes.byref(rampSize) ) assert success, 'XF86VidModeGetGammaRampSize failed' rampSize = rampSize.value else: assert _TravisTesting rampSize = 256 if rampSize == 0: logging.warn( "The size of the gamma ramp was reported as 0. This can " + "mean that gamma settings have no effect. Proceeding with " + "a default gamma ramp size." ) rampSize = 256 return rampSize
def load(self, proj_path=None): """Load the project from a json-format file """ if projPath is None: projPath = self.project_path if not os.path.isfile(proj_path): self.session = remote.Session() # todo: handle the case that the path doesn't (yet) exist with open(projPath, 'r') as f: d = json.load(f) if not self.root_path: self.root_path = d['root_path'] elif self.root_path != d['root_path']: logging.warn("The Project was given a directory that does not " "match the previous stored location. " "Using new location.") self.session = remote.Session(token=d['session']['token']) self.index = d['index']
def _bestDriver(devNames, devIDs): """Find ASIO or Windows sound drivers """ preferredDrivers = prefs.general['audioDriver'] outputID=None audioDriver=None for prefDriver in preferredDrivers: if prefDriver.lower()=='directsound': prefDriver = 'Primary Sound' #look for that driver in available devices for devN, devString in enumerate(devNames): try: if prefDriver.encode('utf-8') in devString.encode('utf-8'): audioDriver=devString outputID=devIDs[devN] return audioDriver, outputID #we found an asio driver don'w look for others except (UnicodeDecodeError, UnicodeEncodeError): logging.warn('find best sound driver - could not interpret unicode in driver name') else: return None, None
def initPygame(rate=22050, bits=16, stereo=True, buffer=1024): """If you need a specific format for sounds you need to run this init function. Run this *before creating your visual.Window*. The format cannot be changed once initialised or once a Window has been created. If a Sound object is created before this function is run it will be executed with default format (signed 16bit stereo at 22KHz). For more details see pygame help page for the mixer. """ global Sound, audioDriver Sound = SoundPygame audioDriver='n/a' if stereo==True: stereoChans=2 else: stereoChans=0 if bits==16: bits=-16 #for pygame bits are signed for 16bit, signified by the minus mixer.init(rate, bits, stereoChans, buffer) #defaults: 22050Hz, 16bit, stereo, sndarray.use_arraytype("numpy") setRate, setBits, setStereo = mixer.get_init() if setRate!=rate: logging.warn('Requested sound sample rate was not poossible') if setBits!=bits: logging.warn('Requested sound depth (bits) was not possible') if setStereo!=2 and stereo==True: logging.warn('Requested stereo setting was not possible')