def __init__(self, fullscreen=True, window=None, info_logger=None, trigger=None): """ :param fullscreen: a boolean indicating either full screen or not :param window: an optional psychopy.visual.Window a new full screen window will be created if this parameter is not provided :param info_logger: (string / Unicode) a specific logger name to log information. Will log to the root logger if None :param trigger: an ASCII character trigger when this is an fMRI task """ self.window = window if window is not None else visual.Window( fullscr=fullscreen) self.expInfo = info.RunTimeInfo(win=window, refreshTest=None, verbose=False) self.trigger = trigger # logging self.logger = logging.getLogger(info_logger) self.logger.info(self.expInfo) # Positions self.CENTRAL_POS = (0.0, 0.0) self.LEFT_CENTRAL_POS = (-0.5, 0.0) self.RIGHT_CENTRAL_POS = (0.5, 0.0) self.LIKERT_SCALE_INSTR_POS = (0, 0.8) self.LIKERT_SCALE_OPTION_INTERVAL = 0.2 self.LIKERT_SCALE_OPTION_POS_Y = -0.2 self.LIKERT_SCALE_LABEL_POS_Y = -0.35 self.FEEDBACK_POS_Y_DIFF = -0.4 # Selection self.SELECTED_STIM_OPACITY_CHANGE = 0.5
def __init__(self, fullscreen=True, window=None, logger=None, serial=None): """ :param fullscreen: a boolean indicating either full screen or not :param window: an optional psychopy.visual.Window a new full screen window will be created if this parameter is not provided :param logger: (string / Unicode) a specific logger name to log information. Will log to the root logger if None :param serial: (an SerialUtil object) if specified, responses will be obtained from the serial port instead of the keyboard, and stimuli will be presented for durations in terms of number of scanner triggers instead of seconds """ self.window = window if window is not None else visual.Window( fullscr=fullscreen) self.serial = serial # logging self.logger = logging.getLogger(logger) self.logger.info( info.RunTimeInfo(win=window, refreshTest=None, verbose=False)) # Positions self.CENTRAL_POS = (0.0, 0.0) self.LEFT_CENTRAL_POS = (-0.5, 0.0) self.RIGHT_CENTRAL_POS = (0.5, 0.0) self.LIKERT_SCALE_INSTR_POS = (0, 0.8) self.LIKERT_SCALE_OPTION_INTERVAL = 0.2 self.LIKERT_SCALE_OPTION_POS_Y = -0.2 self.LIKERT_SCALE_LABEL_POS_Y = -0.35 self.FEEDBACK_POS_Y_DIFF = -0.4 # Selection self.SELECTED_STIM_OPACITY_CHANGE = 0.5
def getRunTimeInfo(self): cwd = os.getcwd( ) #to handle bug in PsychoPy V1.71 where the cwd gets set to the psychopy lib folder. rtInfo = info.RunTimeInfo() os.chdir(cwd) self.psychopyVersion = rtInfo['psychopyVersion'] self.pythonVersion = rtInfo['pythonVersion'] self.machineName = rtInfo['systemHostName'] self.systemPlatform = rtInfo['systemPlatform'] self.windowRefreshStdev = rtInfo['windowRefreshTimeSD_ms'] self.windowRefreshMedian = rtInfo['windowRefreshTimeMedian_ms'] self.windowRefreshMean = rtInfo['windowRefreshTimeAvg_ms'] self.envDate = strftime("%m/%d/%Y") self.envTime = strftime("%H:%M")
def runDiagnostics(self, win, verbose=False): """Return list of (key, val, msg, warn) tuple, set self.warnings All tuple elements will be of <type str>. msg can depend on val; warn==True indicates a concern. Plain text is returned, expected to be used in html <table>. Hyperlinks can be embedded as <a href="..."> """ report = [] # add item tuples in display order # get lots of info and do quick-to-render visual (want no frames drop): # for me, grating draw times are: mean 0.53 ms, SD 0.77 ms items = info.RunTimeInfo(win=win, refreshTest='grating', verbose=True, userProcsDetailed=True) totalRAM, freeRAM = items['systemMemTotalRAM'], items['systemMemFreeRAM'] warn = False if freeRAM == 'unknown': if totalRAM != 'unknown': totalRAM = "%.1fG" % (totalRAM / 1024.) msg = _translate('could not assess available physical RAM; total %s') % totalRAM report.append(('available memory', 'unknown', msg, warn)) else: msg = _translate('physical RAM available for configuration test (of %.1fG total)') % (totalRAM / 1024.) if freeRAM < 300: # in M msg = _translate('Warning: low available physical RAM for configuration test (of %.1fG total)') % (totalRAM / 1024.) warn = True report.append(('available memory', unicode(freeRAM)+'M', msg, warn)) # ----- PSYCHOPY: ----- warn = False report.append(('PsychoPy', '', '', False)) # not localized report.append(('psychopy', __version__, _translate('avoid upgrading during an experiment'), False)) report.append(('locale', items['systemLocale'], _translate('can be set in <a href="http://www.psychopy.org/general/prefs.html#application-settings-app">Preferences -> App</a>'), False)) msg = '' if items['pythonVersion'] < '2.5' or items['pythonVersion'] >= '3': msg = _translate('Warning: python 2.6 or 2.7 required; 2.5 is not supported but might work') warn = True if 'EPD' in items['pythonFullVersion']: msg += ' Enthought Python Distribution' elif 'PsychoPy2.app' in items['pythonExecutable']: msg += ' (PsychoPy StandAlone)' bits, linkage = platform.architecture() #if not bits.startswith('32'): # msg = 'Warning: 32-bit python required; ' + msg report.append(('python version', items['pythonVersion'] + ' (%s)' % bits, msg, warn)) warn = False if verbose: msg = '' if items['pythonWxVersion'] < '2.8.10': msg = _translate('Warning: wx 2.8.10 or higher required') warn = True report.append(('wx', items['pythonWxVersion'], '', warn)) report.append(('pyglet', items['pythonPygletVersion'][:32], '', False)) report.append(('rush', str(items['psychopyHaveExtRush']), _translate('for high-priority threads'), False)) # ----- VISUAL: ----- report.append(('Visual', '', '', False)) warn = False # openGL settings: msg = '' if items['openGLVersion'] < '2.': msg = _translate('Warning: <a href="http://www.psychopy.org/general/timing/reducingFrameDrops.html?highlight=OpenGL+2.0">OpenGL 2.0 or higher is ideal</a>.') warn = True report.append(('openGL version', items['openGLVersion'], msg, warn)) report.append(('openGL vendor', items['openGLVendor'], '', False)) report.append(('screen size', ' x '.join(map(str, items['windowSize_pix'])), '', False)) #report.append(('wait blanking', str(items['windowWaitBlanking']), '', False)) warn = False msg = '' if not items['windowHaveShaders']: msg = _translate('Warning: <a href="http://www.psychopy.org/general/timing/reducingFrameDrops.html?highlight=shader">Rendering of complex stimuli will be slow</a>.') warn = True report.append(('have shaders', str(items['windowHaveShaders']), msg, warn)) warn = False msg = _translate('during the drifting <a href="http://www.psychopy.org/api/visual/gratingstim.html">GratingStim</a>') if items['windowRefreshTimeMedian_ms'] < 3.3333333: msg = _translate("""Warning: too fast? visual sync'ing with the monitor seems unlikely at 300+ Hz""") warn = True report.append(('visual sync (refresh)', "%.2f ms/frame" % items['windowRefreshTimeMedian_ms'], msg, warn)) msg = _translate('SD < 0.5 ms is ideal (want low variability)') warn = False if items['windowRefreshTimeSD_ms'] > .5: msg = _translate('Warning: the refresh rate has high frame-to-frame variability (SD > 0.5 ms)') warn = True report.append(('refresh stability (SD)', "%.2f ms" % items['windowRefreshTimeSD_ms'], msg, warn)) # draw 100 dots as a minimally demanding visual test: # first get baseline frame-rate (safe as possible, no drawing): avg, sd, median = visual.getMsPerFrame(win) dots100 = visual.DotStim(win, nDots=100, speed=0.005, dotLife=12, dir=90, coherence=0.2, dotSize=8, fieldShape='circle', autoLog=False) win.recordFrameIntervals = True win.frameIntervals = [] win.flip() for i in xrange(180): dots100.draw() win.flip() msg = _translate('during <a href="http://www.psychopy.org/api/visual/dotstim.html">DotStim</a> with 100 random dots') warn = False intervalsMS = np.array(win.frameIntervals) * 1000 nTotal = len(intervalsMS) nDropped = sum(intervalsMS > (1.5 * median)) if nDropped: msg = _translate('Warning: could not keep up during <a href="http://www.psychopy.org/api/visual/dotstim.html">DotStim</a> with 100 random dots.') warn = True report.append(('no dropped frames', '%i / %i' % (nDropped, nTotal), msg, warn)) win.recordFrameIntervals = False msg = _translate('for movies') warn = False try: from pyglet.media import avbin except: # not sure what error to catch, WindowsError not found report.append(('pyglet avbin', 'import error', _translate('Warning: could not import avbin; playing movies will not work'), True)) else: ver = avbin.get_version() if sys.platform.startswith('linux'): if not (7 <= ver < 8): msg = _translate('Warning: version 7 recommended on linux (for movies)') warn = True elif not (5 <= ver < 6): msg = _translate('Warning: version 5 recommended (for movies); Visit <a href="http://code.google.com/p/avbin">download page</a> [google.com]') warn = True report.append(('pyglet avbin', unicode(ver), msg, warn)) if verbose: report.append(('openGL max vertices', str(items['openGLmaxVerticesInVertexArray']), '', False)) keyList = ['GL_ARB_multitexture', 'GL_EXT_framebuffer_object', 'GL_ARB_fragment_program', 'GL_ARB_shader_objects', 'GL_ARB_vertex_shader', 'GL_ARB_texture_non_power_of_two', 'GL_ARB_texture_float', 'GL_STEREO'] for key in keyList: val = items['openGLext.'+key] # boolean if not val: val = '<strong>' + str(val) + '</strong>' report.append((key, str(val), '', False)) # ----- AUDIO: ----- report.append(('Audio', '', '', False)) msg = '' warn = False if not 'systemPyoVersion' in items: msg = _translate('Warning: pyo is needed for sound and microphone.') warn = True items['systemPyoVersion'] = _translate('(missing)') #elif items['systemPyoVersion'] < '0.6.2': # msg = 'pyo 0.6.2 compiled with --no-messages will suppress start-up messages' report.append(('pyo', items['systemPyoVersion'], msg, warn)) # sound latencies from portaudio; requires pyo svn r1024 try: sndInputDevices = items['systemPyo.InputDevices'] warn = False if len(sndInputDevices.keys()): key = sndInputDevices.keys()[0] mic = sndInputDevices[key] if mic['name'].endswith('icroph'): mic['name'] += 'one' # portaudio (?) seems to clip to 16 chars msg = '"%s"' % mic['name'] if mic['latency'] > 0.01: msg = _translate('Warning: "%s" latency > 10ms') % mic['name'] warn = True report.append(('microphone latency', "%.4f s" % mic['latency'], msg, warn)) else: report.append(('microphone', _translate('(not detected)'),'', False)) sndOutputDevices = items['systemPyo.OutputDevices'] if len(sndOutputDevices.keys()): warn = False key = sndOutputDevices.keys()[0] spkr = sndOutputDevices[key] msg = '"%s"' % spkr['name'] if spkr['latency'] > 0.01: msg = _translate('Warning: "%s" latency > 10ms') % spkr['name'] warn = True report.append(('speakers latency', "%.4f s" % spkr['latency'], msg, warn)) else: report.append(('speakers', _translate('(not detected)'),'', False)) except KeyError: pass s2t = '<a href="http://www.psychopy.org/api/microphone.html?highlight=Speech2Text">speech-to-text</a>' msg = _translate('audio codec for %s and sound file compression') % s2t warn = False if not 'systemFlacVersion' in items: msg = _translate('Warning: flac is needed for using %s and sound compression.') % s2t +\ ' <a href="http://flac.sourceforge.net/download.html">' +\ _translate('Download</a> [sourceforge.net].') warn = True items['systemFlacVersion'] = _translate('(missing)') if verbose: report.append(('flac', items['systemFlacVersion'].lstrip('flac '), msg, warn)) # TO-DO: add microphone + playback as sound test # ----- NUMERIC: ----- report.append(('Numeric', '', '', False)) report.append(('numpy', items['pythonNumpyVersion'], _translate('vector-based (fast) calculations'), False)) report.append(('scipy', items['pythonScipyVersion'], _translate('scientific / numerical'), False)) report.append(('matplotlib', items['pythonMatplotlibVersion'], _translate('plotting; fast contains(), overlaps()'), False)) # ----- SYSTEM: ----- report.append(('System', '', '', False)) report.append(('platform', items['systemPlatform'], '', False)) msg = _translate('for online help, usage statistics, software updates, and google-speech') warn = False if items['systemHaveInternetAccess'] is not True: items['systemHaveInternetAccess'] = 'False' msg = _translate('Warning: could not connect (no proxy attempted)') warn = True # TO-DO: dlg to query whether to try to auto-detect (can take a while), or allow manual entry of proxy str, save into prefs val = str(items['systemHaveInternetAccess']) report.append(('internet access', val, msg, warn)) report.append(('auto proxy', str(self.prefs.connections['autoProxy']), _translate('try to auto-detect a proxy if needed; see <a href="http://www.psychopy.org/general/prefs.html#connection-settings-connections">Preferences -> Connections</a>'), False)) if not self.prefs.connections['proxy'].strip(): prx = ' --' else: prx = unicode(self.prefs.connections['proxy']) report.append(('proxy setting', prx, _translate('current manual proxy setting from <a href="http://www.psychopy.org/general/prefs.html#connection-settings-connections">Preferences -> Connections</a>'), False)) msg = '' warn = False # assure that we have a list if items['systemUserProcFlagged'] is None: items['systemUserProcFlagged'] = [] items['systemUserProcFlagged'].sort() self.badBgProc = [p for p,pid in items['systemUserProcFlagged']] if len(self.badBgProc): val = ("%s ..." % self.badBgProc[0]) msg = _translate('Warning: Some <a href="http://www.psychopy.org/general/timing/reducingFrameDrops.html?highlight=background+processes">background processes</a> can adversely affect timing') warn = True else: val = _translate('No bad background processes active.') report.append(('background processes', val, msg, warn)) if verbose and 'systemSec.OpenSSLVersion' in items: report.append(('OpenSSL', items['systemSec.OpenSSLVersion'].lstrip('OpenSSL '), 'for <a href="http://www.psychopy.org/api/encryption.html">encryption</a>', False)) report.append(('CPU speed test', "%.3f s" % items['systemTimeNumpySD1000000_sec'], _translate('numpy.std() of 1,000,000 data points'), False)) # TO-DO: more speed benchmarks # - load large image file from disk # - transfer image to GPU # ----- IMPORTS (relevant for developers & non-StandAlone): ----- if verbose: # always False for a real first-run report.append((_translate('Python packages'), '', '', False)) packages = ['PIL', 'openpyxl', 'lxml', 'setuptools', 'pytest', 'sphinx', 'psignifit', 'pyserial', 'pp', 'pynetstation', 'ioLabs', 'labjack' ] if sys.platform == 'win32': packages.append('pywin32') packages.append('winioport') for pkg in packages: try: if pkg == 'PIL': exec('import PIL.Image') ver = PIL.Image.VERSION #elif pkg == 'lxml': # elif pkg == 'pp': exec('import pp; ver = pp.version') elif pkg == 'pynetstation': exec('from psychopy.hardware import egi') ver = 'import ok' elif pkg == 'pyserial': exec('import serial') ver = serial.VERSION elif pkg == 'pywin32': exec('import win32api') ver = 'import ok' else: exec('import ' + pkg) try: ver = eval(pkg+'.__version__') except: ver = 'import ok' report.append((pkg, ver, '', False)) except (ImportError, AttributeError): report.append((pkg, ' --', _translate('could not import package %s') % pkg, False)) # rewrite to avoid assumption of locale en_US: self.warnings = list(set([key for key, val, msg, warn in report if warn])) return report
def runDiagnostics(self, win, verbose=False): """Return list of (key, val, msg, warn) tuple, set self.warnings All tuple elements will be of <type str>. msg can depend on val; warn==True indicates a concern. Plain text is returned, expected to be used in html <table>. Hyperlinks can be embedded as <a href="..."> """ report = [] # add item tuples in display order # get lots of info and do quick-to-render visual (want 0 frames drop): # for me, grating draw times are: mean 0.53 ms, SD 0.77 ms items = info.RunTimeInfo(win=win, refreshTest='grating', verbose=True, userProcsDetailed=True) totalRAM = items['systemMemTotalRAM'] freeRAM = items['systemMemFreeRAM'] warn = False if freeRAM == 'unknown': if totalRAM != 'unknown': totalRAM = "%.1fG" % (totalRAM / 1024.0) txt = _translate( 'could not assess available physical RAM; total %s') msg = txt % totalRAM report.append(('available memory', 'unknown', msg, warn)) else: txt = _translate('physical RAM available for configuration test ' '(of %.1fG total)') msg = txt % (totalRAM / 1024.) if freeRAM < 300: # in M txt = _translate('Warning: low available physical RAM for ' 'configuration test (of %.1fG total)') msg = txt % (totalRAM / 1024.) warn = True report.append(('available memory', str(freeRAM) + 'M', msg, warn)) # ----- PSYCHOPY: ----- warn = False report.append(('PsychoPy', '', '', False)) # not localized report.append( ('psychopy', __version__, _translate('avoid upgrading during an experiment'), False)) msg = _translate( 'can be set in <a href="http://www.psychopy.org/general/' 'prefs.html#application-settings-app">Preferences -> App</a>') report.append(('locale', items['systemLocale'], msg, False)) msg = '' v = parse_version thisV = v(items['pythonVersion']) if (thisV < v('2.7') or (v('3.0') <= thisV < v('3.6'))): msg = _translate("Warning: python 2.7 or 3.6 are recommended; " "2.6 and 3.5 might work. Others probably won't.") warn = True if 'EPD' in items['pythonFullVersion']: msg += ' Enthought Python Distribution' elif 'PsychoPy3.app' in items['pythonExecutable']: msg += ' (PsychoPy StandAlone)' bits, linkage = platform.architecture() # if not bits.startswith('32'): # msg = 'Warning: 32-bit python required; ' + msg report.append( ('python version', items['pythonVersion'] + ' (%s)' % bits, msg, warn)) warn = False if verbose: msg = '' if items['pythonWxVersion'] < '2.8.10': msg = _translate('Warning: wx 2.8.10 or higher required') warn = True report.append(('wx', items['pythonWxVersion'], '', warn)) report.append( ('pyglet', items['pythonPygletVersion'][:32], '', False)) report.append(('rush', str(items['psychopyHaveExtRush']), _translate('for high-priority threads'), False)) # ----- VISUAL: ----- report.append(('Visual', '', '', False)) warn = False # openGL settings: msg = '' if items['openGLVersion'] < '2.': msg = _translate( 'Warning: <a href="http://www.psychopy.org/general/timing' '/reducingFrameDrops.html?highlight=OpenGL+2.0">OpenGL ' '2.0 or higher is ideal</a>.') warn = True report.append(('openGL version', items['openGLVersion'], msg, warn)) report.append(('openGL vendor', items['openGLVendor'], '', False)) report.append( ('screen size', ' x '.join(map(str, items['windowSize_pix'])), '', False)) # report.append(('wait blanking', str(items['windowWaitBlanking']), '', # False)) warn = False msg = '' if not items['windowHaveShaders']: msg = _translate( 'Warning: <a href="http://www.psychopy.org/general/timing' '/reducingFrameDrops.html?highlight=shader">Rendering of' ' complex stimuli will be slow</a>.') warn = True report.append( ('have shaders', str(items['windowHaveShaders']), msg, warn)) warn = False msg = _translate( 'during the drifting <a href="http://www.psychopy.org/api/' 'visual/gratingstim.html">GratingStim</a>') if items['windowRefreshTimeMedian_ms'] < 3.3333333: msg = _translate( "Warning: too fast? visual sync'ing with the monitor" " seems unlikely at 300+ Hz") warn = True report.append( ('visual sync (refresh)', "%.2f ms/frame" % items['windowRefreshTimeMedian_ms'], msg, warn)) msg = _translate('SD < 0.5 ms is ideal (want low variability)') warn = False if items['windowRefreshTimeSD_ms'] > .5: msg = _translate( 'Warning: the refresh rate has high frame-to-frame ' 'variability (SD > 0.5 ms)') warn = True report.append(('refresh stability (SD)', "%.2f ms" % items['windowRefreshTimeSD_ms'], msg, warn)) # draw 100 dots as a minimally demanding visual test: # first get baseline frame-rate (safe as possible, no drawing): avg, sd, median = visual.getMsPerFrame(win) dots100 = visual.DotStim(win, nDots=100, speed=0.005, dotLife=12, dir=90, coherence=0.2, dotSize=8, fieldShape='circle', autoLog=False) win.recordFrameIntervals = True win.frameIntervals = [] win.flip() for i in range(180): dots100.draw() win.flip() msg = _translate('during <a href="http://www.psychopy.org/api/visual/' 'dotstim.html">DotStim</a> with 100 random dots') warn = False intervalsMS = np.array(win.frameIntervals) * 1000 nTotal = len(intervalsMS) nDropped = sum(intervalsMS > (1.5 * median)) if nDropped: msg = _translate( 'Warning: could not keep up during <a href="http://' 'www.psychopy.org/api/visual/dotstim.html">DotStim</a>' ' with 100 random dots.') warn = True report.append( ('no dropped frames', '%i / %i' % (nDropped, nTotal), msg, warn)) win.recordFrameIntervals = False if verbose: report.append( ('openGL max vertices', str(items['openGLmaxVerticesInVertexArray']), '', False)) keyList = ('GL_ARB_multitexture', 'GL_EXT_framebuffer_object', 'GL_ARB_fragment_program', 'GL_ARB_shader_objects', 'GL_ARB_vertex_shader', 'GL_ARB_texture_float', 'GL_ARB_texture_non_power_of_two', 'GL_STEREO') for key in keyList: val = items['openGLext.' + key] # boolean if not val: val = '<strong>' + str(val) + '</strong>' report.append((key, str(val), '', False)) # ----- AUDIO: ----- report.append(('Audio', '', '', False)) msg = '' warn = False if not 'systemPyoVersion' in items: msg = _translate( 'Warning: pyo is needed for sound and microphone.') warn = True items['systemPyoVersion'] = _translate('(missing)') # elif items['systemPyoVersion'] < '0.6.2': # msg = 'pyo 0.6.2 compiled with --no-messages will # suppress start-up messages' report.append(('pyo', items['systemPyoVersion'], msg, warn)) # TO-DO: add microphone + playback as sound test # ----- NUMERIC: ----- report.append(('Numeric', '', '', False)) report.append(('numpy', items['pythonNumpyVersion'], _translate('vector-based (fast) calculations'), False)) report.append(('scipy', items['pythonScipyVersion'], _translate('scientific / numerical'), False)) report.append( ('matplotlib', items['pythonMatplotlibVersion'], _translate('plotting; fast contains(), overlaps()'), False)) # ----- SYSTEM: ----- report.append(('System', '', '', False)) report.append(('platform', items['systemPlatform'], '', False)) msg = _translate('for online help, usage statistics, software ' 'updates, and google-speech') warn = False if items['systemHaveInternetAccess'] is not True: items['systemHaveInternetAccess'] = 'False' msg = _translate('Warning: could not connect (no proxy attempted)') warn = True # TO-DO: dlg to query whether to try to auto-detect (can take a # while), or allow manual entry of proxy str, save into prefs val = str(items['systemHaveInternetAccess']) report.append(('internet access', val, msg, warn)) report.append(('auto proxy', str(self.prefs.connections['autoProxy']), _translate('try to auto-detect a proxy if needed; see' ' <a href="http://www.psychopy.org/general' '/prefs.html#connection-settings-connection' 's">Preferences -> Connections</a>'), False)) if not self.prefs.connections['proxy'].strip(): prx = ' --' else: prx = str(self.prefs.connections['proxy']) report.append(('proxy setting', prx, _translate('current manual proxy setting from <a ' 'href="http://www.psychopy.org/general/' 'prefs.html#connection-settings-connections' '">Preferences -> Connections</a>'), False)) txt = 'CPU speed test' report.append( (txt, "%.3f s" % items['systemTimeNumpySD1000000_sec'], _translate('numpy.std() of 1,000,000 data points'), False)) # TO-DO: more speed benchmarks # - load large image file from disk # - transfer image to GPU # ----- IMPORTS (relevant for developers & non-StandAlone): ----- if verbose: # always False for a real first-run report.append((_translate('Python packages'), '', '', False)) packages = [ 'PIL', 'openpyxl', 'lxml', 'setuptools', 'pytest', 'sphinx', 'psignifit', 'pyserial', 'pp', 'pynetstation', 'labjack' ] if sys.platform == 'win32': packages.append('pywin32') packages.append('winioport') if constants.PY3: pkgError = ModuleNotFoundError else: pkgError = ImportError for pkg in packages: try: if pkg == 'PIL': import PIL ver = PIL.__version__ # elif pkg == 'lxml': # elif pkg == 'pynetstation': from psychopy.hardware import egi ver = 'import ok' elif pkg == 'pyserial': import serial ver = serial.VERSION elif pkg == 'pywin32': import win32api ver = 'import ok' else: exec('import ' + pkg) try: ver = eval(pkg + '.__version__') except Exception: ver = 'imported but no version info' report.append((pkg, ver, '', False)) except (pkgError, AttributeError): msg = _translate('could not import package %s') report.append((pkg, ' --', msg % pkg, False)) # rewrite to avoid assumption of locale en_US: self.warnings = list( set([key for key, val, msg, warn in report if warn])) return report
def test_info(self): info.RunTimeInfo(win=self.win, userProcsDetailed=True, verbose=True)
counterbalance=nCondCombos) # get partner cue combo partnerConds = [partnerColors, partnerShapes] partnerCombos = list(itertools.product(*partnerConds)) random.seed(1928) random.shuffle(partnerCombos) partnerCounterbalance = expInfo['subject'] % len(partnerCombos) win = visual.Window(size=(1200, 700), fullscr=fullscreen, units='pix', monitor=monitor, colorSpace='rgb', color=(-1, -1, -1)) runTimeTest = info.RunTimeInfo(win=win, refreshTest=True) currRefreshRate = runTimeTest['windowRefreshTimeAvg_ms'] / 1000 print currRefreshRate saveDir = os.path.join(os.getcwd(), 'data', 'subject_' + str(expInfo['subject'])) if not os.path.exists(saveDir): os.makedirs(saveDir) # generate names for data and session log files saveFilename = os.path.join(saveDir, "%04d_%s_%s.csv") % (int( expInfo['subject']), expInfo['startTime'], expInfo['expName']) logFilename = os.path.join(saveDir, "%04d_%s_%s.log") % (int( expInfo['subject']), expInfo['startTime'], expInfo['expName']) logfile = logging.LogFile( logFilename, filemode='w', level=logging.EXP
def __init__(self, win, clock, sj="TEST", autoCalibration=True, saccadeSensitivity=HIGH, calibrationType='HV9', calibrationTargetColor=WHITE, calibrationBgColor=BLACK, CalibrationSounds=False): ''' win: psychopy visual window used for the experiment clock: psychopy time clock recording time for whole experiment sj: Subject identifier string (affects EDF filename) autoCalibration: True: enable auto-pacing during calibration saccadeSensitivity: HIGH: Pursuit and neurological work LOW: Cognitive research calibrationType: H3: Horizontal 3-point HV3: 3-point calibration, poor linearization HV5: 5-point calibration, poor at corners HV9: 9-point calibration, best overall calibrationTargetColor and calibrationBgColor: RGB tuple, i.e., (255,0,0) for Red One of: BLACK, WHITE, GRAY calibrationSounds: True: enable feedback sounds when calibrating ''' self.edfFileName = str(sj) + ".EDF" print(self.edfFileName) inf = info.RunTimeInfo("J", "1", win, refreshTest=None, userProcsDetailed=False) self.screenSize = inf['windowSize_pix'] self.units = inf['windowUnits'] self.monitorName = inf['windowMonitor.name'] monitor = monitors.Monitor(self.monitorName) print("Connecting to eyetracker.") self.tracker = pylink.EyeLink() self.timeCorrection = clock.getTime() - self.tracker.trackerTime() print("Loading custom graphics") genv = EyeLinkCoreGraphicsPsychopy(self.tracker, win, self.screenSize) self.tracker.openDataFile(self.edfFileName) pylink.flushGetkeyQueue() self.tracker.setOfflineMode() self.tracker.sendCommand("screen_pixel_coords = 0 0 %d %d" % (tuple(self.screenSize))) self.tracker.setCalibrationType(calibrationType) self.tracker.sendMessage("DISPLAY_COORDS 0 0 %d %d" % (tuple(self.screenSize))) eyelink_ver = self.tracker.getTrackerVersion() if eyelink_ver == 3: tvstr = self.tracker.getTrackerVersionString() vindex = tvstr.find("EYELINK CL") tracker_software_ver = int( float(tvstr[(vindex + len("EYELINK CL")):].strip())) else: tracker_software_ver = 0 if eyelink_ver >= 2: self.tracker.sendCommand("select_parser_configuration %d" % saccadeSensitivity) else: if saccadeSensitivity == HIGH: svt, sat = 22, 5000 else: svt, sat = 30, 9500 self.tracker.sendCommand("saccade_velocity_threshold = %d" % svt) self.tracker.sendCommand("saccade_acceleration_threshold = %d" % sat) if eyelink_ver == 2: #turn off scenelink camera stuff self.tracker.sendCommand("scene_camera_gazemap = NO") # set EDF file contents self.tracker.sendCommand( "file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON" ) if tracker_software_ver >= 4: self.tracker.sendCommand( "file_sample_data = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET" ) else: self.tracker.sendCommand( "file_sample_data = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS") # set link data (used for gaze cursor) self.tracker.sendCommand( "link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON") if tracker_software_ver >= 4: self.tracker.sendCommand( "link_sample_data = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET" ) else: self.tracker.sendCommand( "link_sample_data = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS") #Set the calibration settings: pylink.setCalibrationColors(calibrationTargetColor, calibrationBgColor) if CalibrationSounds: pylink.setCalibrationSounds("", "", "") pylink.setDriftCorrectSounds("", "off", "off") else: pylink.setCalibrationSounds("off", "off", "off") pylink.setDriftCorrectSounds("off", "off", "off") if autoCalibration: self.tracker.enableAutoCalibration else: self.tracker.disableAutoCalibration win.flip() print("Opening graphics") pylink.openGraphicsEx(genv) print("Begining tracker setup") self.tracker.doTrackerSetup() win.flip()
coin = visual.ImageStim(window, image='./images/coin.png', units='pix', size=[screen_size[0] / 20], pos=[120, 200]) treasure_chest = visual.ImageStim(window, image='./images/treasure_chest.png', units='pix', size=[screen_size[0] / 18], pos=[800, screen_size[1] / 2.5]) beep = sound.Sound('./sounds/buzz.wav') break_block = sound.Sound('./sounds/break_block.wav') runtimeInfo = info.RunTimeInfo(author='kb', win=window, userProcsDetailed=False, verbose=True) rewardMsg = visual.TextStim(win=window, units='pix', antialias='False', pos=[-20, 200], colorSpace='rgb', color=[1, 1, 1], height=screen_size[0] / 30) totalMsg = visual.TextStim( win=window, units='pix', antialias='False', pos=[treasure_chest.pos[0] - 150, treasure_chest.pos[1]], colorSpace='rgb', color=[.3, .3, .3],
def __init__(self, exp_name=None, pwd=None, use_srbox=False, autorun=False): self.autorun = autorun if pwd is None: self.pwd = os.path.dirname(os.path.abspath(__file__)).decode(sys.getfilesystemencoding()) else: self.pwd = pwd os.chdir(self.pwd) self.exp_name = u'untitled' if exp_name is None else exp_name data_dir = u'{}{}{}{}'.format( self.pwd, os.sep, u'participant_data', os.sep ) data_file_base = u'{}_'.format(self.exp_name) existing = [] for dirname, dirnames, filenames in os.walk(data_dir): for filename in filenames: if data_file_base in filename and filename.endswith('.csv'): filename = filename.split('_') participant = int(filename[1]) existing.append(participant) existing_low = sorted([x for x in existing if x < 500]) if not existing: participant_suggestion = 101 else: participant_suggestion = existing_low[-1] + 1 exp_suggestions = { u'participant': u''+str(participant_suggestion), u'version': u'{}'.format(__version__) } continue_dlg = True dlg_title = self.exp_name last_attempt = int(exp_suggestions['participant']) while continue_dlg: dlg = gui.DlgFromDict( dictionary=exp_suggestions, title=dlg_title, fixed=[u'version'] ) if dlg.OK == False: core.quit() else: part = int(exp_suggestions['participant']) if part in existing and part != last_attempt: last_attempt = part while part in existing: part += 1 exp_suggestions['participant'] = part dlg_title = u'Participant {:0>3} Already Exists! ({})'.format(last_attempt, self.exp_name) else: continue_dlg = False self.exp_info = exp_suggestions # self.get_session_info() self.window = visual.Window( size=(1920, 1080), fullscr=True, screen=0, allowGUI=True, allowStencil=False, monitor=u'testMonitor', color=[1,1,1], colorSpace='rgb', blendMode='avg', useFBO=True, winType='pyglet') runtime = info.RunTimeInfo(version=self.exp_info['version'], win=self.window) self.exp_info['exp_name'] = self.exp_name self.exp_info['date'] = datetime.today().strftime('%Y-%m-%d') self.exp_info['session_start'] = datetime.today().strftime('%H:%M:%S') self.exp_info['psychopy_version'] = runtime['psychopyVersion'] self.exp_info['hostname'] = runtime['systemHostName'] self.exp_info['platform'] = runtime['systemPlatform'] self.exp_info['proc_count'] = runtime['systemUserProcCount'] self.exp_info['window_type'] = runtime['windowWinType'] self.exp_info['window_size'] = runtime['windowSize_pix'] self.exp_info['all_runtime'] = dict(runtime) self.participant_id = int(self.exp_info['participant']) if 'darwin' in self.exp_info['platform'] or 'linux' in self.exp_info['platform']: self.use_srbox = False print('Not using SRBOX') else: self.use_srbox = use_srbox if self.use_srbox: self.srbox = SRBox('COM4', 19200, 0) self.srbox.set_lights([1,1,1,1,1], update=True) core.wait(0.5) self.srbox.set_lights([0,0,0,0,0], update=True) data_file_stem = u'{}_{}_{}'.format( self.exp_name, self.exp_info['participant'], datetime.today().strftime('%Y-%m-%d') ) # data file name stem if autorun: data_file_stem = u'AUTORUN-DEBUG-DATA-' + data_file_stem elif int(self.exp_info['participant']) > 500: data_file_stem = u'TESTFILE-' + data_file_stem self.data_file_stem = u'{}{}{}{}{}'.format( self.pwd, os.sep, u'participant_data', os.sep, data_file_stem ) # print(self.data_file_stem) self.experiment = data.ExperimentHandler( name = self.exp_name, version = self.exp_info['version'], extraInfo = self.exp_info, originPath = None, savePickle = True, saveWideText = True, dataFileName = self.data_file_stem ) self.log_file = logging.LogFile('{}.log'.format(self.data_file_stem), level=logging.DEBUG, encoding='utf-8') logging.console.setLevel(logging.CRITICAL) self.end_exp_now = False self.frame_rate = self.window.getActualFrameRate() if self.frame_rate != None: self.frame_dur = 1.0 / round(self.frame_rate) else: self.frame_dur = 1.0 / 60.0 # could not measure, so guess self.global_clock = core.Clock() # self.instr_clock = core.Clock() self.sentence_clock = core.Clock() self.pair_clock = core.Clock() self.routine_timer = core.CountdownTimer() logging.flush() instructions = Instructions(self, self.exp_info) instructions.begin_instructions() self.prepare_visuals() self.load_latin_square() self.load_trials() self.load_practice_trials() practice_block = PracticeBlock(self, self.experiment, self.exp_info, self.practice_trials, autorun=self.autorun) sentence_block = SentenceBlock(self, self.experiment, self.exp_info, self.trials, autorun=self.autorun) logging.flush()
def get_system_info(w): SYS_DICT = info.RunTimeInfo(win=w, refreshTest=True) return (SYS_DICT['pythonVersion'], SYS_DICT['psychopyVersion'], SYS_DICT['systemHostName'], SYS_DICT['windowRefreshTimeAvg_ms'], SYS_DICT['windowRefreshTimeSD_ms'], SYS_DICT['windowSize_pix'], SYS_DICT['windowIsFullScr'])
def run(self, runsubject=False, monitor=None, distance=None, store_runtime_info=False, display_report=True): try: # TODO: do this only if this a model run print('Removing old model data files.') logging.info('Removing old model data files from data directory.') filelist = glob.glob( os.path.join(self.cwd, 'data', 'model-' + self.params['expName'] + '.csv')) for f in filelist: print('Removing: ' + str(f)) os.remove(f) runtime_info = None runsubject = self.params['runsubject'] if runsubject or self.params['genstim']: self.win = visual.Window( size=self.monitor.getSizePix(), fullscr=False, screen=0, winType='pyglet', allowGUI=True, allowStencil=False, #monitor=self.monitor, color='black', colorSpace='rgb', # TODO: add color parameter for newlibrary: mainwindow monitor=self.monitor, color=self.params['window_color'], colorSpace='rgb', blendMode='avg', useFBO=True, autoLog=False) if store_runtime_info: from psychopy import info # this library is slow to load, so we load here only since it is now needed runtime_info = info.RunTimeInfo(author=None, version=None, win=self.win, refreshTest='grating', userProcsDetailed=False, verbose=True) else: self.model = Model(name=self.params['expName'], cwd=self.params['cwd'], saveimages=self.params['saveimages'], params=self.params, **self.params['model']) self.params['model'][ 'decision_sigma'] = self.model.decision_sigma self.params['model']['decision_K'] = self.model.decision_K #logging.exp('Params:\n'+str(params)) if not self.params['genstim']: # An ExperimentHandler isn't essential but helps with data saving self.thisExp = data.ExperimentHandler( name=self.params['name'], version='', extraInfo=self.expInfo, runtimeInfo=runtime_info, savePickle=False, saveWideText=True, dataFileName=self.filename, autoLog=True) for routine in self.routines: routine.create(self.win, exp_handler=self.thisExp) for routine in self.routines: routine.run(runmodel=self.model, genstim=self.params['genstim'], params=self.params, loopstate=Params()) if self.thisExp: self.thisExp.close() logging.exp('Experiment Finished.') logging.exp('Params used in experiment:\n' + str(self.params)) logging.exp('Done.--------------------------------') if display_report: self.displayreport() #core.quit() except Exception as e: logging.error(traceback.format_exc()) self.end() core.quit()