Ejemplo n.º 1
0
def findPR650(ports=None):
    """DEPRECATED (as of v.1.60.01). Use :func:`psychopy.hardware.findPhotometer()` instead, which
    finds a wider range of devices
    """
    log.error("DEPRECATED (as of v.1.60.01). Use psychopy.hardware.findPhotometer() instead, which "\
    +"finds a wider range of devices")

    if ports==None:
        if sys.platform=='darwin':
            ports=[]
            #try some known entries in /dev/tty. used by keyspan
            ports.extend(glob.glob('/dev/tty.USA*'))#keyspan twin adapter is usually USA28X13P1.1
            ports.extend(glob.glob('/dev/tty.Key*'))#some are Keyspan.1 or Keyserial.1
            ports.extend(glob.glob('/dev/tty.modem*'))#some are Keyspan.1 or Keyserial.1
            if len(ports)==0: log.error("couldn't find likely serial port in /dev/tty.* Check for \
                serial port name manually, check drivers installed etc...")
        elif sys.platform=='win32':
            ports = range(11)
    elif type(ports) in [int,float]:
        ports=[ports] #so that we can iterate
    pr650=None
    log.info('scanning serial ports...\n\t')
    log.console.flush()
    for thisPort in ports:
        log.info(str(thisPort)); log.console.flush()
        pr650 = Photometer(port=thisPort, meterType="PR650", verbose=False)
        if pr650.OK:
            log.info(' ...OK\n'); log.console.flush()
            break
        else:
            pr650=None
            log.info('...Nope!\n\t'); log.console.flush()
    return pr650
Ejemplo n.º 2
0
def findPR650(ports=None):
    """DEPRECATED (as of v.1.60.01). Use :func:`psychopy.hardware.findPhotometer()` instead, which
    finds a wider range of devices   
    """
    log.error("DEPRECATED (as of v.1.60.01). Use psychopy.hardware.findPhotometer() instead, which "\
    +"finds a wider range of devices")
    print 'here'
    if ports==None:
        if sys.platform=='darwin':
            ports=[]
            #try some known entries in /dev/tty. used by keyspan
            ports.extend(glob.glob('/dev/tty.USA*'))#keyspan twin adapter is usually USA28X13P1.1
            ports.extend(glob.glob('/dev/tty.Key*'))#some are Keyspan.1 or Keyserial.1
            ports.extend(glob.glob('/dev/tty.modem*'))#some are Keyspan.1 or Keyserial.1
            if len(ports)==0: log.error("couldn't find likely serial port in /dev/tty.* Check for \
                serial port name manually, check drivers installed etc...")
        elif sys.platform=='win32':
            ports = range(11)
    elif type(ports) in [int,float]:
        ports=[ports] #so that we can iterate
    pr650=None
    log.info('scanning serial ports...\n\t')
    log.console.flush()
    for thisPort in ports:
        log.info(str(thisPort)); log.console.flush()
        pr650 = Photometer(port=thisPort, meterType="PR650", verbose=False)
        if pr650.OK:
            log.info(' ...OK\n'); log.console.flush()
            break
        else:
            pr650=None
            log.info('...Nope!\n\t'); log.console.flush()
    return pr650
Ejemplo n.º 3
0
def rush(value=True):    
    """Raise the priority of the current thread/process 
    Win32 and OS X only so far - on linux use os.nice(niceIncrement)
    
    Set with rush(True) or rush(False)
    
    Beware and don't take priority until after debugging your code
    and ensuring you have a way out (e.g. an escape sequence of
    keys within the display loop). Otherwise you could end up locked
    out and having to reboot!
    """
    if importCtypesFailed: return False
    
    if value:
        bus = getBusFreq()
        extendedPolicy=_timeConstraintThreadPolicy()
        extendedPolicy.period=bus/160 #number of cycles in hz (make higher than frame rate)
        extendedPolicy.computation=bus/320#half of that period
        extendedPolicy.constrain= bus/640#max period that they should be carried out in
        extendedPolicy.preemptible=1
        extendedPolicy=getThreadPolicy(getDefault=True, flavour=THREAD_TIME_CONSTRAINT_POLICY)
        err=cocoa.thread_policy_set(cocoa.mach_thread_self(), THREAD_TIME_CONSTRAINT_POLICY, 
            ctypes.byref(extendedPolicy), #send the address of the struct
            THREAD_TIME_CONSTRAINT_POLICY_COUNT)
        if err!=KERN_SUCCESS:
            log.error('Failed to set darwin thread policy, with thread_policy_set')
        else:
            log.info('Successfully set darwin thread to realtime')
    else:
        #revert to default policy
        extendedPolicy=getThreadPolicy(getDefault=True, flavour=THREAD_STANDARD_POLICY)
        err=cocoa.thread_policy_set(cocoa.mach_thread_self(), THREAD_STANDARD_POLICY, 
            ctypes.byref(extendedPolicy), #send the address of the struct
            THREAD_STANDARD_POLICY_COUNT)
    return True
Ejemplo n.º 4
0
def makeGrating(
        res,
        ori=0.0,  #in degrees
        cycles=1.0,
        phase=0.0,  #in degrees
        gratType="sin",
        contr=1.0):
    """Make an array containing a luminance grating of the specified params

    :Parameters:
        res: integer
            the size of the resulting matrix on both dimensions (e.g 256)
        ori: float or int (default=0.0)
            the orientation of the grating in degrees
        cycles:float or int (default=1.0)
            the number of grating cycles within the array
        phase: float or int (default=0.0)
            the phase of the grating in degrees (NB this differs to most
            PsychoPy phase arguments which use units of fraction of a cycle)
        gratType: 'sin', 'sqr', 'ramp' or 'sinXsin' (default="sin")
            the type of grating to be 'drawn'
        contr: float (default=1.0)
            contrast of the grating

    :Returns:
        a square numpy array of size resXres

    """
    tiny = 0.0000000000001  #to prevent the sinusoid ever being exactly at zero (for sqr wave)
    ori *= (-numpy.pi / 180)
    phase *= (numpy.pi / 180)
    xrange, yrange = numpy.mgrid[0.0:cycles * 2.0 * numpy.pi:cycles * 2.0 *
                                 numpy.pi / res, 0.0:cycles * 2.0 *
                                 numpy.pi:cycles * 2.0 * numpy.pi / res]

    if gratType is "none":
        res = 2
        intensity = numpy.ones((res, res), Float)
    elif gratType is "sin":
        intensity = contr * (numpy.sin(xrange * numpy.sin(ori) +
                                       yrange * numpy.cos(ori) + phase))
    elif gratType is "ramp":
        intensity = contr * (xrange * numpy.cos(ori) +
                             yrange * numpy.sin(ori)) / (2 * numpy.pi)
    elif gratType is "sqr":  #square wave (symmetric duty cycle)
        intensity = numpy.where(
            numpy.sin(xrange * numpy.sin(ori) + yrange * numpy.cos(ori) +
                      phase + tiny) >= 0, 1, -1)
    elif gratType is "sinXsin":
        intensity = numpy.sin(xrange) * numpy.sin(yrange)
    else:  #might be a filename of an image
        try:
            im = Image.open(gratType)
        except:
            log.error("couldn't find tex...", gratType)
            return
    return intensity
Ejemplo n.º 5
0
 def writeStartCode(self,buff):
     buff.writeIndented("#store info about the experiment session\n")
     buff.writeIndented("expName='%s'#from the Builder filename that created this script\n" %(self.exp.name))
     expInfo = self.params['Experiment info'].val.strip()
     if not len(expInfo): expInfo = '{}'
     try: eval('dict('+expInfo+')')
     except SyntaxError, err:
         log.error('Builder Expt: syntax error in "Experiment info" settings (expected a dict)')
         raise SyntaxError, 'Builder: error in "Experiment info" settings (expected a dict)'
Ejemplo n.º 6
0
 def checkOK(self,msg):
     """Check that the message from the photometer is OK. 
     If there's an error print it.
     
     Then return True (OK) or False.
     """        
     #also check that the reply is what was expected
     if msg[0:2] != 'OK':
         if msg=='': log.error('No reply from LS100'); sys.stdout.flush()
         else: log.error('Error message from LS100:' + self.codes[msg]); sys.stdout.flush()
         return False
     else: 
         return True
Ejemplo n.º 7
0
def makeGrating(res,
            ori=0.0,    #in degrees
            cycles=1.0,
            phase=0.0,    #in degrees
            gratType="sin",
            contr=1.0):
    """Make an array containing a luminance grating of the specified params

    :Parameters:
        res: integer
            the size of the resulting matrix on both dimensions (e.g 256)
        ori: float or int (default=0.0)
            the orientation of the grating in degrees
        cycles:float or int (default=1.0)
            the number of grating cycles within the array
        phase: float or int (default=0.0)
            the phase of the grating in degrees (NB this differs to most
            PsychoPy phase arguments which use units of fraction of a cycle)
        gratType: 'sin', 'sqr', 'ramp' or 'sinXsin' (default="sin")
            the type of grating to be 'drawn'
        contr: float (default=1.0)
            contrast of the grating

    :Returns:
        a square numpy array of size resXres

    """
    tiny=0.0000000000001#to prevent the sinusoid ever being exactly at zero (for sqr wave)
    ori *= (-numpy.pi/180)
    phase *= (numpy.pi/180)
    xrange, yrange = numpy.mgrid[0.0 : cycles*2.0*numpy.pi : cycles*2.0*numpy.pi/res,
                                    0.0 : cycles*2.0*numpy.pi : cycles*2.0*numpy.pi/res]

    if gratType is "none":
            res=2
            intensity = numpy.ones((res,res),Float)
    elif gratType is "sin":
            intensity= contr*(numpy.sin( xrange*numpy.sin(ori)+yrange*numpy.cos(ori) + phase))
    elif gratType is "ramp":
            intensity= contr*( xrange*numpy.cos(ori)+yrange*numpy.sin(ori) )/(2*numpy.pi)
    elif gratType is "sqr":#square wave (symmetric duty cycle)
            intensity = numpy.where(numpy.sin( xrange*numpy.sin(ori)+yrange*numpy.cos(ori) + phase + tiny)>=0, 1, -1)
    elif gratType is "sinXsin":
            intensity = numpy.sin(xrange)*numpy.sin(yrange)
    else:#might be a filename of an image
            try:
                    im = Image.open(gratType)
            except:
                    log.error( "couldn't find tex...",gratType)
                    return
    return intensity
Ejemplo n.º 8
0
def makeMPEG(filename,
             images,
             codec='mpeg1video',
             codecParams=None,
             verbose=False):
    if not havePyMedia:
        log.error('pymedia (www.pymedia.org) needed to make mpeg movies')
        return 0

    fw = open(filename, 'wb')
    t = time.time()

    #set bitrate
    if codec == 'mpeg1video':
        bitrate = 2700000
    else:
        bitrate = 9800000

    #set other params (or receive params dictionary)
    if codecParams == None:
        codecParams= { \
            'type': 0,
            'gop_size': 12,
            'frame_rate_base': 125,
            'max_b_frames': 0,
            'width': images[0].size[0],
            'height': images[0].size[1],
            'frame_rate': 3125,
            'deinterlace': 0,
            'bitrate': bitrate,
            'id': vcodec.getCodecID( codec )
            }
        log.info('Setting codec to ' + str(codecParams))
    encoder = vcodec.Encoder(codecParams)

    for im in images:
        # Create VFrame
        imStr = im.tostring()
        bmpFrame = vcodec.VFrame(vcodec.formats.PIX_FMT_RGB24, im.size,
                                 (imStr, None, None))
        yuvFrame = bmpFrame.convert(vcodec.formats.PIX_FMT_YUV420P, im.size)
        d = encoder.encode(yuvFrame)
        try:
            fw.write(d.data)  #this is what works!
        except:
            fw.write(d)  #this is what pymedia demo recommends
    else:
        log.info('%d frames written in %.2f secs' %
                 (len(images), time.time() - t))
        i = 0
    fw.close()
Ejemplo n.º 9
0
def init():
    """initialise the bits++ box
    Note that, by default, bits++ will perform gamma correction
    that you don't want (unless you have the CRS calibration device)
    (Recommended that you use the BitsBox class rather than
    calling this directly)
    """
    if haveBitsDLL:
        try:
            retVal = _bits.bitsInit() #returns null if fails?
        except:
            log.error('bits.init() barfed!')
            return 0
    return 1
Ejemplo n.º 10
0
def init():
    """initialise the bits++ box
    Note that, by default, bits++ will perform gamma correction
    that you don't want (unless you have the CRS calibration device)
    (Recommended that you use the BitsBox class rather than
    calling this directly)
    """
    if haveBitsDLL:
        try:
            retVal = _bits.bitsInit()  #returns null if fails?
        except:
            log.error('bits.init() barfed!')
            return 0
    return 1
Ejemplo n.º 11
0
 def writeStartCode(self, buff):
     buff.writeIndented("#store info about the experiment session\n")
     buff.writeIndented(
         "expName='%s'#from the Builder filename that created this script\n"
         % (self.exp.name))
     expInfo = self.params['Experiment info'].val.strip()
     if not len(expInfo): expInfo = '{}'
     try:
         eval('dict(' + expInfo + ')')
     except SyntaxError, err:
         log.error(
             'Builder Expt: syntax error in "Experiment info" settings (expected a dict)'
         )
         raise SyntaxError, 'Builder: error in "Experiment info" settings (expected a dict)'
Ejemplo n.º 12
0
def makeEdgeMatrix(width, center, size=512):
    """Create a matrix of given size that switches from 0 to 1 using a linear ramp.
    
    :params:
            width: (float) the width of the linear ramp (blur) as fraction of the total matrix
            center: (float) the location of the center of the ramp as a fraction of the total matrix
            size: (int=256) width and height of the matrix
            """
    center=int(center*(size-1))
    width = int(width*size/2)*2
    mat = np.ones([size,size], 'f')
    mat[:,0:(center-width/2)]=0
    if (center-width/2)<0 or (center+width/2)>size:
        log.error('ramp extends beyond texture')
    mat[:,(center-width/2):(center+width/2)] = np.linspace(0,1.0,width)
    return mat*2.0-1
Ejemplo n.º 13
0
 def run(self):
     self.running = True
     self.clock.reset()
     last_onset = 0.000
     # wait until next event requested, and simulate a key press
     for onset, key in self.responses:
         core.wait(float(onset) - last_onset)
         if type(key) == int:
             #log.warning('ResponseEmulator: int converted to str')
             key = str(key)[0]  # avoid cryptic error if int
         if type(key) == str:
             event._keyBuffer.append(key)
         else:
             log.error('ResponseEmulator: only keyboard events are supported')
         last_onset = onset
         if self.stopflag: break
     self.running = False
Ejemplo n.º 14
0
def makeMPEG(filename, images, codec='mpeg1video', codecParams = None, verbose=False):
    if not havePyMedia:
        log.error('pymedia (www.pymedia.org) needed to make mpeg movies')
        return 0
    
    fw= open( filename, 'wb' )
    t= time.time()	
    
    #set bitrate
    if codec== 'mpeg1video':
        bitrate= 2700000
    else:
        bitrate= 9800000
        
    #set other params (or receive params dictionary)
    if codecParams == None:
        codecParams= { \
            'type': 0,
            'gop_size': 12,
            'frame_rate_base': 125,
            'max_b_frames': 0,
            'width': images[0].size[0],
            'height': images[0].size[1],
            'frame_rate': 3125,
            'deinterlace': 0,
            'bitrate': bitrate,
            'id': vcodec.getCodecID( codec )
            }
        log.info('Setting codec to ' + str(codecParams))
    encoder= vcodec.Encoder( codecParams )    
    
    for im in images:	    
        # Create VFrame
        imStr = im.tostring()
        bmpFrame= vcodec.VFrame( vcodec.formats.PIX_FMT_RGB24, im.size, (imStr,None,None))
        yuvFrame= bmpFrame.convert( vcodec.formats.PIX_FMT_YUV420P, im.size )
        d = encoder.encode( yuvFrame )
        try:
            fw.write( d.data )#this is what works!
        except:
            fw.write( d )#this is what pymedia demo recommends
    else:
        log.info('%d frames written in %.2f secs' % ( len(images), time.time()- t))
        i= 0
    fw.close()
Ejemplo n.º 15
0
 def run(self):
     self.running = True
     self.clock.reset()
     last_onset = 0.000
     # wait until next event requested, and simulate a key press
     for onset, key in self.responses:
         core.wait(float(onset) - last_onset)
         if type(key) == int:
             # log.warning('ResponseEmulator: int converted to str')
             key = str(key)[0]  # avoid cryptic error if int
         if type(key) == str:
             event._keyBuffer.append(key)
         else:
             log.error("ResponseEmulator: only keyboard events are supported")
         last_onset = onset
         if self.stopflag:
             break
     self.running = False
Ejemplo n.º 16
0
def rush(value=True):
    """Raise the priority of the current thread/process 
    Win32 and OS X only so far - on linux use os.nice(niceIncrement)
    
    Set with rush(True) or rush(False)
    
    Beware and don't take priority until after debugging your code
    and ensuring you have a way out (e.g. an escape sequence of
    keys within the display loop). Otherwise you could end up locked
    out and having to reboot!
    """
    if importCtypesFailed: return False

    if value:
        bus = getBusFreq()
        extendedPolicy = _timeConstraintThreadPolicy()
        extendedPolicy.period = bus / 160  #number of cycles in hz (make higher than frame rate)
        extendedPolicy.computation = bus / 320  #half of that period
        extendedPolicy.constrain = bus / 640  #max period that they should be carried out in
        extendedPolicy.preemptible = 1
        extendedPolicy = getThreadPolicy(getDefault=True,
                                         flavour=THREAD_TIME_CONSTRAINT_POLICY)
        err = cocoa.thread_policy_set(
            cocoa.mach_thread_self(),
            THREAD_TIME_CONSTRAINT_POLICY,
            ctypes.byref(extendedPolicy),  #send the address of the struct
            THREAD_TIME_CONSTRAINT_POLICY_COUNT)
        if err != KERN_SUCCESS:
            log.error(
                'Failed to set darwin thread policy, with thread_policy_set')
        else:
            log.info('Successfully set darwin thread to realtime')
    else:
        #revert to default policy
        extendedPolicy = getThreadPolicy(getDefault=True,
                                         flavour=THREAD_STANDARD_POLICY)
        err = cocoa.thread_policy_set(
            cocoa.mach_thread_self(),
            THREAD_STANDARD_POLICY,
            ctypes.byref(extendedPolicy),  #send the address of the struct
            THREAD_STANDARD_POLICY_COUNT)
    return True
Ejemplo n.º 17
0
So setting to DEBUG level will include all possible messages, setting to ERROR will include only the absolutely essential messages.

"""
globalClock = core.Clock()#if this isn't provided the log times will reflect secs since python started
log.setDefaultClock(globalClock)#use this for 

log.console.setLevel(log.DEBUG)#set the console to receive nearly all messges
logDat = log.LogFile('logLastRun.log', 
    filemode='w',#if you set this to 'a' it will append instead of overwriting
    level=log.WARNING)#errors, data and warnings will be sent to this logfile

#the following will go to any files with the appropriate minimum level set
log.info('Something fairly unimportant')
log.data('Something about our data. Data is likely very important!')
log.warning('Handy while building your experiment - highlights possible flaws in code/design')
log.error("You might have done something that PsychoPy can't handle! But hopefully this gives you some idea what.")

#some things should be logged timestamped on the next video frame
#For instance the time of a stimulus appearing is related to the flip:
win = visual.Window([400,400])
for n in range(5):
    win.logOnFlip('frame %i occured' %n, level=log.EXP)
    if n in [2,4]:
        win.logOnFlip('an even frame occured', level=log.EXP)
    win.flip()
    
#LogFiles can also simply receive direct input from the write() method
#messages using write() will be sent immediately, and are often not
#in correct chronological order with logged messages
logDat.write("Testing\n\n")
log.flush()
Ejemplo n.º 18
0
 def __init__(self, port, meterType="PR650", verbose=True):
     log.error(self.__doc__)
     sys.exit()
Ejemplo n.º 19
0
of PsychoPy as of version 1.62.01).

installation:

    Download the package from the link above and copy egi.py into your
    site-packages directory.
    
usage::

    from psychopy.hardware import egi
    
For an example see the demos menu of the PsychoPy Coder
For further documentation see the pynetstation website

"""
# Part of the PsychoPy library
# Copyright (C) 2010 Jonathan Peirce
# Distributed under the terms of the GNU General Public License (GPL).

from psychopy import log
try:
    from egi import *
except:
    msg="""Failed to import egi (pynetstation). If you're using your own copy of 
python (not the Standalone distribution of PsychoPy) then try installing pynetstation.
See:
    http://code.google.com/p/pynetstation/wiki/Installation
    
"""
    log.error(msg)
Ejemplo n.º 20
0
    def lineariseLums(self, desiredLums, newInterpolators=False, overrideGamma=None):
        """lums should be uncalibrated luminance values (e.g. a linear ramp)
        ranging 0:1"""
        linMethod = self.getLineariseMethod()
        desiredLums = numpy.asarray(desiredLums)
        output = desiredLums*0.0 #needs same size as input

        #gamma interpolation
        if linMethod==3:
            lumsPre = copy(self.getLumsPre())
            if self._gammaInterpolator!=None and not newInterpolators:
                pass #we already have an interpolator
            elif lumsPre != None:
                log.info('Creating linear interpolation for gamma')
                #we can make an interpolator
                self._gammaInterpolator, self._gammaInterpolator2 =[],[]
                #each of these interpolators is a function!
                levelsPre = self.getLevelsPre()/255.0
                for gun in range(4):
                    lumsPre[gun,:] = (lumsPre[gun,:]-lumsPre[gun,0])/(lumsPre[gun,-1]-lumsPre[gun,0])#scale to 0:1
                    self._gammaInterpolator.append(interp1d(lumsPre[gun,:], levelsPre,kind='linear'))
                    #interpFunc = Interpolation.InterpolatingFunction((lumsPre[gun,:],), levelsPre)
                    #polyFunc = interpFunc.fitPolynomial(3)
                    #print polyFunc.coeff
                    #print polyFunc.derivative(0)
                    #print polyFunc.derivative(0.5)
                    #print polyFunc.derivative(1.0)
                    #self._gammaInterpolator2.append( [polyFunc.coeff])
            else:
                #no way to do this! Calibrate the monitor
                log.error("Can't do a gamma interpolation on your monitor without calibrating!")
                return desiredLums

            #then do the actual interpolations
            if len(desiredLums.shape)>1:
                for gun in range(3):
                    output[:,gun] = self._gammaInterpolator[gun+1](desiredLums[:,gun])#gun+1 because we don't want luminance interpolator

            else:#just luminance
                output = self._gammaInterpolator[0](desiredLums)

        #use a fitted gamma equation (1 or 2)
        elif linMethod in [1,2]:

            #get the min,max lums
            gammaGrid = self.getGammaGrid()
            if gammaGrid!=None:
                #if we have info about min and max luminance then use it
                minLum = gammaGrid[1,0]
                maxLum = gammaGrid[1:4,1]
                if overrideGamma is not None: gamma=overrideGamma
                else: gamma = gammaGrid[1:4,2]
                maxLumWhite = gammaGrid[0,1]
                gammaWhite = gammaGrid[0,2]
                log.debug('using gamma grid'+str(gammaGrid))
            else:
                #just do the calculation using gamma
                minLum=0
                maxLumR, maxLumG, maxLumB, maxLumWhite= 1,1,1, 1
                gamma = self.gamma
                gammaWhite = num.average(self.gamma)

            #get the inverse gamma
            if len(desiredLums.shape)>1:
                for gun in range(3):
                    output[:,gun] = gammaInvFun(desiredLums[:,gun],
                        minLum, maxLum[gun], gamma[gun],eq=linMethod)
                #print gamma
            else:
                output = gammaInvFun(desiredLums,
                    minLum, maxLumWhite, gammaWhite,eq=linMethod)

        else:
            log.error("Don't know how to linearise with method %i" %linMethod)
            output = desiredLums

        #if DEBUG: print 'LUT:', output[0:10,1], '...'
        return output
Ejemplo n.º 21
0
def getLumSeries(lumLevels=8,
    winSize=(800,600),
    monitor=None,
    gamma=1.0,
    allGuns = True,
    useBits=False,
    autoMode='auto',
    stimSize = 0.3,
    photometer=None):
    """
    Automatically measures a series of gun values and measures
    the luminance with a photometer.

    :Parameters:

        photometer : a photometer object
            e.g. a :class:`~psychopy.hardware.pr.PR65` or
            :class:`~psychopy.hardware.minolta.LS100` from hardware.findPhotometer()

        lumLevels : (default=8)
            array of values to test or single value for n evenly spaced test values

        gamma : (default=1.0) the gamma value at which to test

        autoMode : 'auto' or 'semi'(='auto')

            If 'auto' the program will present the screen
            and automatically take a measurement before moving on.

            If set to 'semi' the program will wait for a keypress before
            moving on but will not attempt to make a measurement (use this
            to make a measurement with your own device).

            Any other value will simply move on without pausing on each screen (use this to see
            that the display is performing as expected).

    """
    import psychopy.event, psychopy.visual
    from psychopy import core

    if photometer==None:
        havePhotom = False
    elif not hasattr(photometer, 'getLum'):
        log.error("photometer argument to monitors.getLumSeries should be a type of photometer "+\
            "object, not a %s" %type(photometer))
        return None
    else: havePhotom = True

    if useBits:
        #all gamma transforms will occur in calling the Bits++ LUT
        #which improves the precision (14bit not 8bit gamma)
        bitsMode='fast'
    else: bitsMode=None

    if gamma==1:
        initRGB= 0.5**(1/2.0)*2-1
    else: initRGB=0.8
    #setup screen and "stimuli"
    myWin = psychopy.visual.Window(fullscr = 0, size=winSize,
        gamma=gamma,units='norm',monitor=monitor,allowGUI=True,winType='pyglet',
        bitsMode=bitsMode)
    instructions="Point the photometer at the central bar. Hit a key when ready (or wait 30s)"
    message = psychopy.visual.TextStim(myWin, text = instructions,height=0.1,
        pos=(0,-0.85), rgb=[1,-1,-1])
    noise = numpy.random.rand(512,512).round()*2-1
    backPatch = psychopy.visual.PatchStim(myWin, tex=noise, size=2, units='norm',
        sf=[winSize[0]/512.0, winSize[1]/512.0])
    testPatch = psychopy.visual.PatchStim(myWin,
        tex='sqr',
        size=stimSize,
        rgb=initRGB,
        units='norm')

    #stay like this until key press (or 30secs has passed)
    waitClock=core.Clock()
    tRemain=30
    while tRemain>0:
        tRemain = 30-waitClock.getTime()
        instructions="Point the photometer at the central white bar. Hit a key when ready (or wait %iss)" %tRemain
        backPatch.draw()
        testPatch.draw()
        message.setText(instructions)
        message.draw()
        myWin.flip()
        if len(psychopy.event.getKeys()):
            break#we got a keypress so move on


    message.setText('Q to quit at any time')
    #
    if photometer.type=='LS100':#LS100 likes to take at least one bright measurement
        junk=photometer.getLum()

    #what are the test values of luminance
    if (type(lumLevels) is int) or (type(lumLevels) is float):
        toTest= DACrange(lumLevels)
    else: toTest= numpy.asarray(lumLevels)

    if allGuns: guns=[0,1,2,3]#gun=0 is the white luminance measure
    else: allGuns=[0]
    lumsList = numpy.zeros((len(guns),len(toTest)), 'd') #this will hoold the measured luminance values
    #for each gun, for each value run test
    for gun in guns:
        for valN, DACval in enumerate(toTest):
            lum = DACval/127.5-1 #get into range -1:1
            #only do luminanc=-1 once
            if lum==-1 and gun>0: continue
            #set hte patch color
            if gun>0:
                rgb=[-1,-1,-1];
                rgb[gun-1]=lum
            else:
                rgb = [lum,lum,lum]

            backPatch.draw()
            testPatch.setColor(rgb)
            testPatch.draw()
            message.draw()
            myWin.flip()

            time.sleep(0.2)#allowing the screen to settle (no good reason!)
            #check for quit request
            for thisKey in psychopy.event.getKeys():
                if thisKey in ['q', 'Q', 'escape']:
                    myWin.close()
                    return numpy.array([])
            #take measurement
            if havePhotom and autoMode=='auto':
                actualLum = photometer.getLum()
                print "At DAC value %i\t: %.2fcd/m^2" % (DACval, actualLum)
                if lum==-1 or not allGuns:
                    #if the screen is black set all guns to this lum value!
                    lumsList[:,valN] = actualLum
                else:
                    #otherwise just this gun
                    lumsList[gun,valN] =  actualLum
            elif autoMode=='semi':
                print "At DAC value %i" % DACval
                psychopy.event.waitKeys()

    myWin.close() #we're done with the visual stimuli
    if havePhotom: return lumsList
    else: return numpy.array([])
Ejemplo n.º 22
0
def getLumSeries(lumLevels=8,
    winSize=(800,600),
    monitor=None,
    gamma=1.0,
    allGuns = True,
    useBits=False,
    autoMode='auto',
    stimSize = 0.3,
    photometer=None):
    """
    Automatically measures a series of gun values and measures
    the luminance with a photometer.

    :Parameters:
    
        photometer : a photometer object 
            e.g. a :class:`~psychopy.hardware.pr.PR65` or
            :class:`~psychopy.hardware.minolta.LS100` from hardware.findPhotometer()
        
        lumLevels : (default=8) 
            array of values to test or single value for n evenly spaced test values
        
        gamma : (default=1.0) the gamma value at which to test
        
        autoMode : 'auto' or 'semi'(='auto')
            
            If 'auto' the program will present the screen
            and automatically take a measurement before moving on.
            
            If set to 'semi' the program will wait for a keypress before
            moving on but will not attempt to make a measurement (use this
            to make a measurement with your own device). 
            
            Any other value will simply move on without pausing on each screen (use this to see
            that the display is performing as expected).
    
    """
    import psychopy.event, psychopy.visual
    from psychopy import core

    if photometer==None:
        havePhotom = False
    elif not hasattr(photometer, 'getLum'):
        log.error("photometer argument to monitors.getLumSeries should be a type of photometer "+\
            "object, not a %s" %type(photometer))
        return None
    else: havePhotom = True

    if useBits:
        #all gamma transforms will occur in calling the Bits++ LUT
        #which improves the precision (14bit not 8bit gamma)
        bitsMode='fast'
    else: bitsMode=None

    if gamma==1:
        initRGB= 0.5**(1/2.0)*2-1
    else: initRGB=0.8
    #setup screen and "stimuli"
    myWin = psychopy.visual.Window(fullscr = 0, size=winSize,
        gamma=gamma,units='norm',monitor=monitor,allowGUI=True,winType='pyglet',
        bitsMode=bitsMode)
    instructions="Point the photometer at the central bar. Hit a key when ready (or wait 30s)"
    message = psychopy.visual.TextStim(myWin, text = instructions,height=0.1,
        pos=(0,-0.95), rgb=[1,-1,-1])    
    noise = numpy.random.rand(512,512).round()*2-1
    backPatch = psychopy.visual.PatchStim(myWin, tex=noise, size=2, units='norm',
        sf=[winSize[0]/512.0, winSize[1]/512.0])
    testPatch = psychopy.visual.PatchStim(myWin,
        tex='sqr',
        size=stimSize,
        rgb=initRGB,
        units='norm')
   
    #stay like this until key press (or 30secs has passed)
    waitClock=core.Clock()
    tRemain=30
    while tRemain>0:
        tRemain = 30-waitClock.getTime()
        instructions="Point the photometer at the central white bar. Hit a key when ready (or wait %iss)" %tRemain
        backPatch.draw()
        testPatch.draw()
        message.setText(instructions)
        message.draw()  
        myWin.flip()
        if len(psychopy.event.getKeys()):
            break#we got a keypress so move on
    
    #
    if photometer.type=='LS100':#LS100 likes to take at least one bright measurement
        junk=photometer.getLum()
    
    #what are the test values of luminance
    if (type(lumLevels) is int) or (type(lumLevels) is float):
        toTest= DACrange(lumLevels)
    else: toTest= numpy.asarray(lumLevels)
    
    if allGuns: guns=[0,1,2,3]#gun=0 is the white luminance measure
    else: allGuns=[0]
    lumsList = numpy.zeros((len(guns),len(toTest)), 'd') #this will hoold the measured luminance values
    #for each gun, for each value run test
    for gun in guns:
        for valN, DACval in enumerate(toTest):
            lum = DACval/127.5-1 #get into range -1:1
            #only do luminanc=-1 once
            if lum==-1 and gun>0: continue
            #set hte patch color
            if gun>0:
                rgb=[-1,-1,-1];
                rgb[gun-1]=lum
            else:
                rgb = [lum,lum,lum]
            
            backPatch.draw()
            testPatch.setColor(rgb)
            testPatch.draw()
            myWin.flip()
            
            time.sleep(0.2)#allowing the screen to settle (no good reason!)
            #check for quit request
            for thisKey in psychopy.event.getKeys():
                if thisKey in ['q', 'Q']:
                    myWin.close()
                    return numpy.array([])
            #take measurement
            if havePhotom and autoMode=='auto':
                actualLum = photometer.getLum()
                print "At DAC value %i\t: %.2fcd/m^2" % (DACval, actualLum)
                if lum==-1 or not allGuns:
                    #if the screen is black set all guns to this lum value!
                    lumsList[:,valN] = actualLum
                else:
                    #otherwise just this gun
                    lumsList[gun,valN] =  actualLum
            elif autoMode=='semi':
                print "At DAC value %i" % DACval
                psychopy.event.waitKeys()

    myWin.close() #we're done with the visual stimuli
    if havePhotom: return lumsList
    else: return numpy.array([])
Ejemplo n.º 23
0
    def lineariseLums(self, desiredLums, newInterpolators=False, overrideGamma=None):
        """lums should be uncalibrated luminance values (e.g. a linear ramp)
        ranging 0:1"""
        linMethod = self.getLineariseMethod()
        desiredLums = numpy.asarray(desiredLums)
        output = desiredLums*0.0 #needs same size as input

        #gamma interpolation
        if linMethod==3:
            lumsPre = copy(self.getLumsPre())
            if self._gammaInterpolator!=None and not newInterpolators:
                pass #we already have an interpolator
            elif lumsPre != None:
                log.info('Creating linear interpolation for gamma')
                #we can make an interpolator
                self._gammaInterpolator, self._gammaInterpolator2 =[],[]
                #each of these interpolators is a function!
                levelsPre = self.getLevelsPre()/255.0
                for gun in range(4):
                    lumsPre[gun,:] = (lumsPre[gun,:]-lumsPre[gun,0])/(lumsPre[gun,-1]-lumsPre[gun,0])#scale to 0:1
                    self._gammaInterpolator.append(interp1d(lumsPre[gun,:], levelsPre,kind='linear'))
                    #interpFunc = Interpolation.InterpolatingFunction((lumsPre[gun,:],), levelsPre)
                    #polyFunc = interpFunc.fitPolynomial(3)
                    #print polyFunc.coeff
                    #print polyFunc.derivative(0)
                    #print polyFunc.derivative(0.5)
                    #print polyFunc.derivative(1.0)
                    #self._gammaInterpolator2.append( [polyFunc.coeff])
            else:
                #no way to do this! Calibrate the monitor
                log.error("Can't do a gamma interpolation on your monitor without calibrating!")
                return desiredLums

            #then do the actual interpolations
            if len(desiredLums.shape)>1:
                for gun in range(3):
                    output[:,gun] = self._gammaInterpolator[gun+1](desiredLums[:,gun])#gun+1 because we don't want luminance interpolator

            else:#just luminance
                output = self._gammaInterpolator[0](desiredLums)

        #use a fitted gamma equation (1 or 2)
        elif linMethod in [1,2,4]:

            #get the min,max lums
            gammaGrid = self.getGammaGrid()
            if gammaGrid!=None:
                #if we have info about min and max luminance then use it
                minLum = gammaGrid[1,0]
                maxLum = gammaGrid[1:4,1]
                b = gammaGrid[1:4,4]
                if overrideGamma is not None: gamma=overrideGamma
                else: gamma = gammaGrid[1:4,2]
                maxLumWhite = gammaGrid[0,1]
                gammaWhite = gammaGrid[0,2]
                log.debug('using gamma grid'+str(gammaGrid))
            else:
                #just do the calculation using gamma
                minLum=0
                maxLumR, maxLumG, maxLumB, maxLumWhite= 1,1,1, 1
                gamma = self.gamma
                gammaWhite = num.average(self.gamma)

            #get the inverse gamma
            if len(desiredLums.shape)>1:
                for gun in range(3):
                    output[:,gun] = gammaInvFun(desiredLums[:,gun],
                        minLum, maxLum[gun], gamma[gun],eq=linMethod, b=b[gun])
                #print gamma
            else:
                output = gammaInvFun(desiredLums,
                    minLum, maxLumWhite, gammaWhite,eq=linMethod)
            
        else:
            log.error("Don't know how to linearise with method %i" %linMethod)
            output = desiredLums

        #if DEBUG: print 'LUT:', output[0:10,1], '...'
        return output
Ejemplo n.º 24
0
 def __init__(self, port, meterType="PR650", verbose=True):
     log.error(self.__doc__)
     sys.exit()
Ejemplo n.º 25
0
This is currently a simple import of the `ioLab python library 
<http://github.com/ioLab/python-ioLabs>`_. 
That needs to be installed (but is included in the *Standalone* distributions
of PsychoPy as of version 1.62.01).

installation::

    easy_install iolabs

usage::

    from psychopy.hardware import ioLabs
    
for examples see the demos menu of the PsychoPy Coder or go to the URL above.

"""
# Part of the PsychoPy library
# Copyright (C) 2011 Jonathan Peirce
# Distributed under the terms of the GNU General Public License (GPL).

from psychopy import log
try:
    from ioLabs import *
except:
    msg="""Failed to import the ioLabs library. If you're using your own copy of 
python (not the Standalone distribution of PsychoPy) then try installing it with:
    > easy_install ioLabs
    
"""
    log.error(msg)
Ejemplo n.º 26
0
 def _error(self, msg):
     self.OK = False
     log.error(msg)
Ejemplo n.º 27
0
from psychopy import log

#create a log that gets replaced every run and stores all the details
detailedLog =  log.LogFile('complete.log', 
    'w', #'a' will append to previous file, 'w' will overwrite
    level=log.INFO)

#set the level of the console log
log.console.setLevel(log.WARNING)

#set the level of the log at site-packages/psychopy/psychopy.log
log.psychopyLog.setLevel(log.ERROR)

log.warning('a shot across the bows')
log.error('just a test error message')
log.info('this will only get sent to the detailed log file')
Ejemplo n.º 28
0
        log.warn('Requested stereo setting was not possible')


def setAudioAPI(api):
    """Change the API used for the presentation of sounds

        usage:
            setAudioAPI(api)

        where:
            api is one of 'pygame','pyglet', pyaudio'

    """
    global audioAPI, Sound
    exec('haveThis=have%s' % api.title())
    if haveThis:
        audioAPI = api
        exec('init%s()' % (API.title()))
        exec('thisSound= Sound%s' % (API.title()))
        Sound = thisSound
    return haveThis


#initialise it and keep track
for API in preferredAPI:
    if setAudioAPI(API):
        audioAPI = API
        break  #we found one so stop looking
if audioAPI is None:
    log.error('No audio API found. Try installing pygame 1.8+')
Ejemplo n.º 29
0
from psychopy import log

#create a log that gets replaced every run and stores all the details
detailedLog = log.LogFile(
    'complete.log',
    'w',  #'a' will append to previous file, 'w' will overwrite
    level=log.INFO)

#set the level of the console log
log.console.setLevel(log.WARNING)

#set the level of the log at site-packages/psychopy/psychopy.log
log.psychopyLog.setLevel(log.ERROR)

log.warning('a shot across the bows')
log.error('just a test error message')
log.info('this will only get sent to the detailed log file')
Ejemplo n.º 30
0
        log.warn('Requested stereo setting was not possible')
    

def setAudioAPI(api):
    """Change the API used for the presentation of sounds
            
        usage:
            setAudioAPI(api)
            
        where:
            api is one of 'pygame','pyglet', pyaudio'
            
    """
    global audioAPI, Sound
    exec('haveThis=have%s' %api.title())
    if haveThis:
        audioAPI=api
        exec('init%s()' %(API.title()))
        exec('thisSound= Sound%s' %(API.title()))
        Sound= thisSound
    return haveThis
    
#initialise it and keep track
for API in preferredAPI:
    if setAudioAPI(API):
        audioAPI=API
        break#we found one so stop looking
if audioAPI is None:
    log.error('No audio API found. Try installing pygame 1.8+')

Ejemplo n.º 31
0
def findPhotometer(ports=None, device=None):
    """Try to find a connected photometer/photospectrometer! 
    PsychoPy will sweep a series of serial ports trying to open them. If a port 
    successfully opens then it will try to issue a command to the device. If it 
    responds with one of the expected values then it is assumed to be the 
    appropriate device. 
    
    :parameters:
        
        ports : a list of ports to search
            Each port can be a string (e.g. 'COM1', ''/dev/tty.Keyspan1.1') or a 
            number (for win32 comports only). If none are provided then PsychoPy 
            will sweep COM0-10 on win32 and search known likely port names on OS X
            and linux.
            
        device : string giving expected device (e.g. 'PR650', 'PR655', 'LS110').
            If this is not given then an attempt will be made to find a device of 
            any type, but this often fails
            
    :returns:
    
        * An object representing the first photometer found
        * None if the ports didn't yield a valid response
        * -1 if there were not even any valid ports (suggesting a driver not being installed)
        
    e.g.::
    
        photom = findPhotometer(device='PR655') #sweeps ports 0 to 10 searching for a PR655
        print photom.getLum()
        if hasattr(photom, 'getSpectrum'):#can retrieve spectrum (e.g. a PR650)
            print photom.getSpectrum()
        
    """
    import minolta, pr
    if device.lower() in ['pr650']:
        photometers=[pr.PR650]
    elif device.lower() in ['pr655', 'pr670']:
        photometers=[pr.PR655]
    elif device.lower() in ['ls110', 'ls100']:
        photometers=[minolta.LS100]
    else:#try them all
        photometers=[pr.PR650, pr.PR655, minolta.LS100]#a list of photometer objects to test for
    
    #determine candidate ports
    if ports==None:
        if sys.platform=='darwin':
            ports=[]
            #try some known entries in /dev/tty. used by keyspan
            ports.extend(glob.glob('/dev/tty.USA*'))#keyspan twin adapter is usually USA28X13P1.1
            ports.extend(glob.glob('/dev/tty.Key*'))#some are Keyspan.1 or Keyserial.1
            ports.extend(glob.glob('/dev/tty.modem*'))#some are Keyspan.1 or Keyserial.1
            ports.extend(glob.glob('/dev/cu.usbmodem*'))#for PR650
            if len(ports)==0:
                log.error("PsychoPy couldn't find any likely serial port in /dev/tty.* or /dev/cs* Check for " \
                    +"serial port name manually, check drivers installed etc...")
                return None
        elif sys.platform.startswith('linux'):
            ports = glob.glob('/dev/ttyACM?')#USB CDC devices (virtual serial ports)
            ports.extend(glob.glob('/dev/ttyS?'))#genuine serial ports usually /dev/ttyS0 or /dev/ttyS1
        elif sys.platform=='win32':
            ports = range(11)
    elif type(ports) in [int,float]:
        ports=[ports] #so that we can iterate
        
    #go through each port in turn
    photom=None
    log.info('scanning serial ports...')
    log.flush()
    for thisPort in ports:
        log.info('...'+str(thisPort)); log.flush()
        for Photometer in photometers:
            photom = Photometer(port=thisPort)
            if photom.OK: 
                log.info(' ...found a %s\n' %(photom.type)); log.flush()
                #we're now sure that this is the correct device and that it's configured
                #now increase the number of attempts made to communicate for temperamental devices!
                if hasattr(photom,'setMaxAttempts'):photom.setMaxAttempts(10)
                return photom#we found one so stop looking
            else:
                if photom.com and photom.com.isOpen: 
                    log.info('closing port')
                    photom.com.close()

        #If we got here we didn't find one
        log.info('...nope!\n\t'); log.flush()
            
    return None
Ejemplo n.º 32
0
 def _error(self, msg):
     self.OK=False
     log.error(msg)
Ejemplo n.º 33
0
log.setDefaultClock(globalClock)  #use this for

log.console.setLevel(log.DEBUG)  #set the console to receive nearly all messges
logDat = log.LogFile(
    'logLastRun.log',
    filemode='w',  #if you set this to 'a' it will append instead of overwriting
    level=log.WARNING)  #errors, data and warnings will be sent to this logfile

#the following will go to any files with the appropriate minimum level set
log.info('Something fairly unimportant')
log.data('Something about our data. Data is likely very important!')
log.warning(
    'Handy while building your experiment - highlights possible flaws in code/design'
)
log.error(
    "You might have done something that PsychoPy can't handle! But hopefully this gives you some idea what."
)

#some things should be logged timestamped on the next video frame
#For instance the time of a stimulus appearing is related to the flip:
win = visual.Window([400, 400])
for n in range(5):
    win.logOnFlip('frame %i occured' % n, level=log.EXP)
    if n in [2, 4]:
        win.logOnFlip('an even frame occured', level=log.EXP)
    win.flip()

#LogFiles can also simply receive direct input from the write() method
#messages using write() will be sent immediately, and are often not
#in correct chronological order with logged messages
logDat.write("Test ended\n\n")
Ejemplo n.º 34
0
def findPhotometer(ports=None, device=None):
    """Try to find a connected photometer/photospectrometer! 
    PsychoPy will sweep a series of serial ports trying to open them. If a port 
    successfully opens then it will try to issue a command to the device. If it 
    responds with one of the expected values then it is assumed to be the 
    appropriate device. 
    
    :parameters:
        
        ports : a list of ports to search
            Each port can be a string (e.g. 'COM1', ''/dev/tty.Keyspan1.1') or a 
            number (for win32 comports only). If none are provided then PsychoPy 
            will sweep COM0-10 on win32 and search known likely port names on OS X
            and linux.
            
        device : string giving expected device (e.g. 'PR650', 'PR655', 'LS110').
            If this is not given then an attempt will be made to find a device of 
            any type, but this often fails
            
    :returns:
    
        * An object representing the first photometer found
        * None if the ports didn't yield a valid response
        * -1 if there were not even any valid ports (suggesting a driver not being installed)
        
    e.g.::
    
        photom = findPhotometer(device='PR655') #sweeps ports 0 to 10 searching for a PR655
        print photom.getLum()
        if hasattr(photom, 'getSpectrum'):#can retrieve spectrum (e.g. a PR650)
            print photom.getSpectrum()
        
    """
    import minolta, pr
    if device.lower() in ['pr650']:
        photometers = [pr.PR650]
    elif device.lower() in ['pr655', 'pr670']:
        photometers = [pr.PR655]
    elif device.lower() in ['ls110', 'ls100']:
        photometers = [minolta.LS100]
    else:  #try them all
        photometers = [pr.PR650, pr.PR655, minolta.LS100
                       ]  #a list of photometer objects to test for

    #determine candidate ports
    if ports == None:
        if sys.platform == 'darwin':
            ports = []
            #try some known entries in /dev/tty. used by keyspan
            ports.extend(glob.glob('/dev/tty.USA*')
                         )  #keyspan twin adapter is usually USA28X13P1.1
            ports.extend(
                glob.glob('/dev/tty.Key*'))  #some are Keyspan.1 or Keyserial.1
            ports.extend(glob.glob(
                '/dev/tty.modem*'))  #some are Keyspan.1 or Keyserial.1
            ports.extend(glob.glob('/dev/cu.usbmodem*'))  #for PR650
            if len(ports) == 0:
                log.error("PsychoPy couldn't find any likely serial port in /dev/tty.* or /dev/cs* Check for " \
                    +"serial port name manually, check drivers installed etc...")
                return None
        elif sys.platform.startswith('linux'):
            ports = glob.glob(
                '/dev/ttyACM?')  #USB CDC devices (virtual serial ports)
            ports.extend(
                glob.glob('/dev/ttyS?')
            )  #genuine serial ports usually /dev/ttyS0 or /dev/ttyS1
        elif sys.platform == 'win32':
            ports = range(11)
    elif type(ports) in [int, float]:
        ports = [ports]  #so that we can iterate

    #go through each port in turn
    photom = None
    log.info('scanning serial ports...')
    log.flush()
    for thisPort in ports:
        log.info('...' + str(thisPort))
        log.flush()
        for Photometer in photometers:
            photom = Photometer(port=thisPort)
            if photom.OK:
                log.info(' ...found a %s\n' % (photom.type))
                log.flush()
                #we're now sure that this is the correct device and that it's configured
                #now increase the number of attempts made to communicate for temperamental devices!
                if hasattr(photom, 'setMaxAttempts'): photom.setMaxAttempts(10)
                return photom  #we found one so stop looking
            else:
                if photom.com and photom.com.isOpen:
                    log.info('closing port')
                    photom.com.close()

        #If we got here we didn't find one
        log.info('...nope!\n\t')
        log.flush()

    return None
Ejemplo n.º 35
0
To run this demo the ioLab library needs to be installed (it is included with
the Standalone distributions of PsychoPy).

"""

__author__ = 'Jonathan Roberts'

from psychopy import log
#log.console.setLevel(log.CRITICAL)

from psychopy import core, visual, event
try:
   import ioLabs
except RuntimeError, errMsg:
    log.error('Is an ioLabs button-box connected and turned on? (import failed: "'+str(errMsg)+'")')
    core.quit()

import random

def setup_bbox():
    '''Initialize the button box object and disable all buttons and lights.'''

    global usbbox # button box object declared global so the other routines can use it
    usbbox=ioLabs.USBBox()
    usbbox.buttons.enabled = 0x00 #8 bit pattern 0=disabled 1=enabled
    usbbox.port2.state = 0xFF #port2 is the lights on the bbox - 8 bit pattern 0=on 1=off
    
def enableButtons(buttonList=(0,1,2,3,4,5,6,7)):
    '''enable the specified buttons
    the argument should beone of the following: