Example #1
0
 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
Example #2
0
 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")
Example #4
0
    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'] + ' &nbsp;(%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 &lt; 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 &gt; 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 &gt; 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 &gt; 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 = '&nbsp;&nbsp;--'
        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, '&nbsp;&nbsp;--', _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
Example #5
0
    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'] + ' &nbsp;(%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 &lt; 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 &gt; 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 = '&nbsp;&nbsp;--'
        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, '&nbsp;&nbsp;--', 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
Example #6
0
 def test_info(self):
     info.RunTimeInfo(win=self.win, userProcsDetailed=True, verbose=True)
Example #7
0
                          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
Example #8
0
    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()
Example #9
0
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],
Example #10
0
    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()
Example #11
0
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()