misc.py :  » Game-2D-3D » PsychoPy » PsychoPy-0.96.02 » psychopy » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Game 2D 3D » PsychoPy 
PsychoPy » PsychoPy 0.96.02 » psychopy » misc.py
"""Tools, nothing to do with psychophysics or experiments
- just handy things like conversion functions etc...
""" 

import numpy #this is imported by psychopy.core
from psychopy import log
import monitors

import Image, cPickle
#from random import shuffle #this is core python dist

def toFile(filename, data):
    """save data (of any sort) as a pickle file
    
    simple wrapper of the cPickle module in core python
    """
    f = open(filename, 'w')
    cPickle.dump(data,f)
    f.close()

def fromFile(filename):
    """load data (of any sort) from a pickle file
    
    simple wrapper of the cPickle module in core python
    """
    f = open(filename)
    contents = cPickle.load(f)
    f.close()
    return contents

def radians(degrees):
    return degrees*numpy.pi/180.0

def shuffleArray(inArray, shuffleAxis=-1, seed=None):
    """Takes a  (flat) num array, list or string and returns a shuffled
    version as a num array with the same shape. Optional argument ShuffleAxis
    determines the axis to shuffle along (default=-1 meaning shuffle across
    entire matrix?)
    
    THIS DOESN'T WORK WITH MATRICES YET - ONLY FLAT ARRAYS - APPEARS TO BE BUG
    IN EITHER NUMPY.ARGSORT() OR NUMPY.TAKE()
    """
    #arrAsList = shuffle(list(inArray))
    #return numpy.array(arrAsList)
    if seed is not None:
        numpy.random.seed(seed)
        
    inArray = numpy.array(inArray, 'O')#convert to array if necess
    rndArray = numpy.random.random(inArray.shape)#create a random array of the same shape
    newIndices =  numpy.argsort(rndArray, shuffleAxis)# and get the arguments that would sort it
    return numpy.take(inArray,newIndices)#return the array with the sorted random indices

def extendArr(inArray,newSize):
    """Takes a numpy array and returns it padded with zeros to the necessary size
    """ 
    newArr = numpy.zeros(newSize,inArray.dtype)
    #create a string to eval (see comment below)
    indString=''
    for thisDim in inArray.shape:
        indString += '0:'+str(thisDim)+','
    indString = indString[0:-1]#remove the final comma
    
    #e.g.
    #newArr[0:4,0:3]=inArray
    
    exec("newArr["+indString+"]=inArray")
    return newArr
    


def ratioRange(start, nSteps=None, stop=None, 
               stepRatio=None, stepdB=None, stepLogUnits=None):
    """Creates a  array where each step is a constant ratio
    rather than a constant addition.
    
    Specify *start* and any 2 of, *nSteps*, *stop*, *stepRatio*, *stepdB*, *stepLogUnits*
    
    examples (all return [1, 2, 4, 8]):
        rangeRatio(1,nSteps=4,stop=8) 
        rangeRatio(1,nSteps=4,stepRatio=2)
        rangeRatio(1,stop=8,stepRatio=2)
            
    """

    if start<=0:
        raise RuntimeError, "Can't calculate ratio ranges on negatives or zero"
    if (stepdB != None): stepRatio= 10.0**(stepdB/20.0) #dB = 20*log10(ratio)
    if (stepLogUnits != None): stepRatio= 10.0**stepLogUnits #logUnit = log10(ratio)
    
    if (stepRatio!=None) and (nSteps!=None):
        factors = stepRatio**numpy.arange(nSteps,dtype='d')
        output = start*factors
        
    elif (nSteps!=None) and (stop!=None):
        if stop<=0:
            raise RuntimeError, "Can't calculate ratio ranges on negatives or zero"
        lgStart = numpy.log10(start) 
        lgStop = numpy.log10(stop)
        lgStep = (lgStop-lgStart)/(nSteps-1)
        lgArray = numpy.arange(lgStart, lgStop+lgStep, lgStep)
        #if the above is a badly rounded float it may have one extra entry
        if len(lgArray)>nSteps: lgArray=lgArray[:-1]
        output = 10**lgArray
        
    elif (stepRatio!=None) and (stop!=None):
        thisVal=float(start)
        outList = []
        while thisVal<stop:
            outList.append(thisVal)
            thisVal *= stepRatio
        output=numpy.asarray(outList)
        
    return output
    

def makeImageAuto(inarray):
    """Combines float_uint8 and image2array operations
    ie. scales a numeric array from -1:1 to 0:255 and
    converts to PIL image format"""
    return image2array(float_uint8(inarray))

def image2array(im):
    """Takes an image object (PIL) and returns an array
    
     fredrik lundh, october 1998
    
     fredrik@pythonware.com
     http://www.pythonware.com
    
    """
    if im.mode not in ("L", "F"):
            raise ValueError, "can only convert single-layer images"
    if im.mode == "L":
            a = numpy.fromstring(im.tostring(), numpy.uint8)
    else:
            a = numpy.fromstring(im.tostring(), numpy.float32)
    a.shape = im.size[1], im.size[0]
    return a

def array2image(a):
    """Takes an array and returns an image object (PIL)""" 
    # fredrik lundh, october 1998
    #
    # fredrik@pythonware.com
    # http://www.pythonware.com
    #
    if a.dtype.kind in ['u','I', 'B']:
            mode = "L"
    elif a.dtype.kind == numpy.float32:
            mode = "F"
    else:
            raise ValueError, "unsupported image mode"
    return Image.fromstring(mode, (a.shape[1], a.shape[0]), a.tostring())
########################################################################

    

def float_uint8(inarray):
    """Converts arrays, lists, tuples and floats ranging -1:1
    into an array of Uint8s ranging 0:255
    """
    retVal = numpy.around(255*(0.5+0.5*numpy.asarray(inarray)))
    return retVal.astype(numpy.uint8)
def uint8_float(inarray):
    """Converts arrays, lists, tuples and UINTs ranging 0:255
    into an array of floats ranging -1:1
    """
    return numpy.asarray(inarray,'f')/127.5 - 1
def float_uint16(inarray):
    """Converts arrays, lists, tuples and floats ranging -1:1
    into an array of Uint16s ranging 0:2^16
    """
    i16max = 2**16 - 1
    retVal = numpy.around(i16max*(1.0+numpy.asarray(inarray))/2.0)
    return retVal.astype(numpy.UnsignedInt16)

def sph2cart(*args):
    #convert from spherical coordinates (elevation, azimuth, radius)
    #to cartesian (x,y,z)
    
    #usage:
        #array3xN[x,y,z] = sph2cart(array3xN[el,az,rad])
        #OR 
        #x,y,z = sph2cart(elev, azim, radius)
        
    if len(args)==1:  #received an Nx3 array
        elev = args[0][0,:]
        azim = args[0][1,:]
        radius = args[0][2,:]
        returnAsArray = True
    elif len(args)==3:
        elev = args[0]
        azim = args[1]
        radius = args[2]
        returnAsArray = False
        
    z = radius * numpy.sin(radians(elev))
    x = radius * numpy.cos(radians(elev))*numpy.cos(radians(azim))
    y = radius * numpy.cos(radians(elev))*numpy.sin(radians(azim))
    if returnAsArray:
        return numpy.asarray([x, y, z])
    else:
        return x, y, z
    
#---unit conversions
def deg2pix(degrees, monitor):
    """Convert size in degrees to size in pixels for a given Monitor object"""   
    #get monitor params and raise error if necess
    scrWidthCm = monitor.getWidth()
    scrSizePix = monitor.getSizePix()
    if scrSizePix==None:
        raise "Monitor %s has no known size in pixels (SEE MONITOR CENTER)" %monitor.name
    if scrWidthCm==None:
        raise "Monitor %s has no known width in cm (SEE MONITOR CENTER)" %monitor.name
    
    cmSize = deg2cm(degrees, monitor)
    return cmSize*scrSizePix[0]/scrWidthCm

def deg2cm(degrees, monitor):
    """Convert size in degrees to size in pixels for a given Monitor object"""
    #check we have a monitor
    if not isinstance(monitor, monitors.Monitor):
        raise "deg2cm requires a monitors.Monitor object as the second argument but received %s" %str(type(monitor))
    
    #get monitor dimensions
    dist = monitor.getDistance()
    
    #check they all exist
    if dist==None:
        raise "Monitor %s has no known distance (SEE MONITOR CENTER)" %monitor.name
    
    return degrees*dist*0.017455

def cm2pix(cm, monitor):
    """Convert size in degrees to size in pixels for a given Monitor object"""
    #check we have a monitor
    if not isinstance(monitor, monitors.Monitor):
        raise "cm2pix requires a monitors.Monitor object as the second argument but received %s" %str(type(monitor))
    #get monitor params and raise error if necess
    scrWidthCm = monitor.getWidth()
    scrSizePix = monitor.getSizePix()
    if scrSizePix==None:
        raise "Monitor %s has no known size in pixels (SEE MONITOR CENTER)" %monitor.name
    if scrWidthCm==None:
        raise "Monitor %s has no known width in cm (SEE MONITOR CENTER)" %monitor.name
    
    return cm*scrSizePix[0]/scrWidthCm

#---color conversions---#000000#FFFFFF------------------------------------------ 
def dkl2rgb(dkl_Nx3, conversionMatrix=None):
    #Convert from DKL color space (cone-opponent space from Derrington,
    #Krauskopf & Lennie) to RGB. 

    #Requires a conversion matrix, which will be generated from generic
    #Sony Trinitron phosphors if not supplied (note that this will not be
    #an accurate representation of the color space unless you supply a 
    #conversion matrix
    #
    #usage:
        #rgb(Nx3) = dkl2rgb(dkl_Nx3(el,az,radius), conversionMatrix)
    
    dkl_3xN = numpy.transpose(dkl_Nx3)#its easier to use in the other orientation!
    if numpy.size(dkl_3xN)==3:
        RG, BY, LUM = sph2cart(dkl_3xN[0],dkl_3xN[1],dkl_3xN[2])
    else:
        RG, BY, LUM = sph2cart(dkl_3xN[0,:],dkl_3xN[1,:],dkl_3xN[2,:])
    dkl_cartesian = numpy.asarray([LUM, RG, BY])

    if conversionMatrix==None:
        conversionMatrix = numpy.asarray([ \
            #LUMIN  %L-M  %L+M-S  (note that dkl has to be in cartesian coords first!)
            [1.0000, 1.0000, -0.1462],  #R
            [1.0000, -0.3900, 0.2094],  #G
            [1.0000, 0.0180, -1.0000]])  #B
        log.warning('This monitor has not been color-calibrated. Using default DKL conversion matrix.')
        
    rgb = numpy.dot(conversionMatrix, dkl_cartesian)
    
    return numpy.transpose(rgb)#return in the shape we received it
    
def lms2rgb(lms_Nx3, conversionMatrix=None):
    #Convert from cone space (Long, Medium, Short) to RGB. 
    
    #Requires a conversion matrix, which will be generated from generic
    #Sony Trinitron phosphors if not supplied (note that you will not get
    #an accurate representation of the color space unless you supply a 
    #conversion matrix)
    #
    #usage:
        #rgb(Nx3) = lms2rgb(dkl_Nx3(el,az,radius), conversionMatrix)
    
    lms_3xN = numpy.transpose(lms_Nx3)#its easier to use in the other orientation!
        
    if conversionMatrix==None:
        cones_to_rgb = numpy.asarray([ \
            #L    M    S
            [ 4.97068857, -4.14354132, 0.17285275],#R
            [-0.90913894, 2.15671326, -0.24757432],#G
            [-0.03976551, -0.14253782, 1.18230333]#B
            ])
        log.warning('This monitor has not been color-calibrated. Using default LMS conversion matrix.')
    else: cones_to_rgb=conversionMatrix
    
    rgb_to_cones = numpy.linalg.pinv(cones_to_rgb)#get inverse
    rgb = numpy.dot(cones_to_rgb, lms_3xN)
    return numpy.transpose(rgb)#return in the shape we received it

def pol2cart(theta, radius, units='deg'):
    """Convert from polar to cartesian coordinates
    
    **usage**:
        x,y = pol2cart(theta, radius, units='deg')
    """
    if units=='deg':
        theta = theta*numpy.pi/180.0
    xx = radius*numpy.cos(theta)
    yy = radius*numpy.sin(theta)
    
    return xx,yy
#----------------------------------------------------------------------
def  cart2pol(x,y, units='deg'):
    """Convert from cartesian to polar coordinates
    
    **usage**:
        theta, radius = pol2cart(x, y, units='deg')
        
    units refers to the units (rad or deg) for theta that should be returned"""
    radius= numpy.hypot(x,y)
    theta= numpy.arctan2(y,x)
    if units=='deg':
        theta=theta*180/numpy.pi
    return theta, radius
    
def plotFrameIntervals(intervals):
    """Plot a histogram of the frame intervals.
    
    Arguments:
        - intervals: Either a filename to a log file, saved by Window.saveFrameIntervals
            or simply a list (or array of frame intervals)
    """
    from pylab import hist,show,plot
    
    if type(intervals)==str:
        f = open(intervals, 'r')
        exec("intervals = [%s]" %(f.readline()))
#    hist(intervals, int(len(intervals)/10))
    plot(intervals)
    show()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.