colour experiment (modulations in DKL space)

667 views
Skip to first unread message

Joanne Powell

unread,
Nov 28, 2011, 5:49:14 AM11/28/11
to psychopy-users
Dear all,

I am new to Psychopy having never used the programme before.
I would like to use Psychopy to run a colour experiment.

Does anyone have a colour experiment (modulations in DKL space) using
Psychopy that I can use. It would better if I could see an already
constructed colour experiment (modulations in DKL space) and make
modifications to understand better how psychopy works.

Any help would be very much appreciated.

Many thanks in advance,
Joanne

Alex Holcombe

unread,
Nov 28, 2011, 4:04:15 PM11/28/11
to psychopy-users
Joanne, here is a movie I made using Psychopy to travel through DKL
space: http://www.youtube.com/watch?v=xwoVrGoBaWg
I can post the code somewhere, once I find it. Is there a preferred
place to post example psychopy code? If not I'll probably post it to
my lab wiki, and let you know. http://openwetware.org/wiki/Holcombe:LumColorPsychopy

Alex

Alex Holcombe

unread,
Nov 28, 2011, 6:49:26 PM11/28/11
to psychopy-users
I tried to upload the file that made that DKL movie to OpenWetWare but
got an error, uploading there seems to be broken. I'm pasting the code
below and emailing the associated file to Joanne. It will only work if
you define the full matrix of color conversions for your chosen
monitor (mine is '2mitsu' as you can see in the code, which won't work
for you). You have to hit spacebar to step through the movie.
In principle I thought tha 'testMonitor' monitor would work, as it's
the sample monitor definition provided by Psychopy but in my
installation at least a, b, and k of the linearisation table are NaN.
I think this is an oversight that should probably be fixed in a later
version of Psychopy.

-Alex


#!/usr/bin/env python
#by Alex Holcombe, 2011
#when run, must hit space to advance frames
#you must have a monitor with its full matrix defined in Tools-
>MonitorCenter
from psychopy import visual, event, core, log, monitors, misc
import copy
import numpy as np
import numpy
import math as m
from scipy import linalg
gotTexttable = True
try:
from texttable import *
except:
gotTexttable = False
#demo color spaces

#note that for this demo to present colors properly in calibrated
#DKL space (where isoluminant stimuli have elevation=0) you need
#to calibrate your monitor with a suitable spectrophotometer. If you
#have a PR60 then you can do this automatically using MonitorCenter.py
#in the monitors package
exportImages=False
monitorname='2mitsu'
autopilot = False
#mon='temp' #has gammas to 1,1,1

#because my monitor tops out, I will have to use my own luminance
conversion function to go from desired rgb luminance to rgb255 (with
gamma=1)
#then convert any dklCart I want to rgb

#so, pull latest calibration from monitor center, then manually set
gammas to 1
#monitorname = 'test' # used to be 'mitsubishi' but that was with
gamma=1. In case I've calibrated it and set a gamma, shouldn't use
it. #in psychopy Monitors Center
#mon = monitors.Monitor(monitorname)#fetch the most recent calib for
this monitor
#lums = mon.getLumsPre() #all the lums that were recorded
#fit function. First, exclude numbers where saturate. Then fit
function. Then
#saturationLevel = 249
#lumsExcludeSaturatn = lums[:,0:saturationLevel]
#levels=monitors.DACrange(256)
#for gun in [0,1,2,3]:
# gamCalc = monitors.GammaCalculator(levels, lums[gun,:],
eq=linMethod)
# currentCal[gun,0]=lums[gun,0]#min
# currentCal[gun,1]=lums[gun,-1]#max
# currentCal[gun,2]=gamCalc.gammaVal#gamma


#find some luminances for red and for yellow that work

waitBlank = False
mon = monitors.Monitor(monitorname)#relying on monitorwidth cm (39
for Mitsubishi to do deg calculations)
dkl2rgbMatrix = mon.getDKL_RGB()
gammaGrid = mon.getGammaGrid()
minLums = gammaGrid[1:4,0]
maxLums = gammaGrid[1:4,1] #skip 0 which is for all 3 guns combined
print 'dkl2rgbMatrix for this screen =',dkl2rgbMatrix
print 'minLums=',np.around(minLums,2)
print 'maxLums=',np.around(maxLums,2)
print 'gamma grid for this screen, not including minLum and maxLum=
\n',np.around(gammaGrid[:,2::],decimals=2)
DACceil=248#looks like ceiling happens around DAC=248

#convert from luminance to DACvalue? I don't think that's provided as
a inbuilt psychopy function
def RGB255ToLum(gun,rgb,gammaGrid):
#a+(b+kx)^g #this is a complete equation, so don't have to do any
scaling except bring 0->255 into 0->1
g = gammaGrid[gun+1,2] #e.g. 2.19
a = gammaGrid[gun+1,3] #e.g. 1.47
b = gammaGrid[gun+1,4] #e.g. 0.39
k = gammaGrid[gun+1,5] #e.g. 3.80
x = rgb/255.0 #need to discretize
lum = a + (b+k*x)**g
return (lum)

def lumToRGB255notlinearized(gun,lum,gammaGrid):
#lum specified in candelas per meter squared
#requires that lum be greater than minlum, otherwise nan
#lum=a+(b+kx)^g #(b+kx)^g = lum-a #b+kx = (lum-a)^(1/g) #kx =
(lum-a)^(1/g) - b #x = (lum-a)^(1/g) - b / k
g = gammaGrid[gun+1,2]; a = gammaGrid[gun+1,3]; b = gammaGrid[gun
+1,4]; k = gammaGrid[gun+1,5]
if lum < a:
print 'WARNING lumToRGB255: desired lum should be greater than
minimum lum for this gun, ',a
x = (lum-a)**(1./g)/k - b/k
return (x*255)

lumCeil = np.array([0.,0.,0.])
for guni in range(3): #calculate luminance where guns saturate, based
on hand-entered DACceil observed during calibration
lumCeil[guni] = RGB255ToLum(guni,DACceil,gammaGrid)
print 'lumCeil = ',lumCeil

#for a phosphor, calculate its RGB value to get this particular
luminance
#def lumToOneGunRGB(lum,gun): #lum from -1 (minimum of screen) to +1
(maximum of screen)
#print 'lumToRGB255 blue gun: l, rgb',
#for l in np.arange(-1,1.0,.05):
# proportn = l+1./2. #from -1->1 to 0->1
# minLum = minLums[2]; maxLum = maxLums[2] #gammaGrid[2+1,3];
maxLum = gammaGrid[2+1,4];
# lumWanted = (maxLum-minLum)*l + minLum
# print l,' lumWanted=',lumWanted,' rgb',
lumToRGB255notlinearized(2,lumWanted,gammaGrid)

#KLcartLumToRGB255(guni,lum,gammaGrid)
#go from DKLcart lum to phosphor rgb
def DKLcartLumToPhosphorRGB(gun,lum,gammaGrid):
#for a partcular DKLcartLum (-1->1), give corresponding rgb value
for a single phosphor to get that luminance
purePhosphor =[-1,-1,-1]; purePhosphor[gun] = 1
dklCartPhosphor = linalg.solve( dkl2rgbMatrix, purePhosphor )
maxLumThisGunDKL = dklCartPhosphor[0]
minLumThisGunDKL = linalg.solve( dkl2rgbMatrix, [-1,-1,-1] ) [0]
print 'minLumThisGunDKL,
maxLumThisGunDKL=',minLumThisGunDKL,maxLumThisGunDKL
proportnLum = (lum-minLumThisGunDKL) / (maxLumThisGunDKL-
minLumThisGunDKL)
minLum = minLums[gun]; maxLum = maxLums[gun]
#but are these luminances that gamma compensates linearly related
to L+M used in DKLcart ?
#that's determined by the first column of the dkl2rgb matrix,
which in my case is 1,1,1 so assume it's that
lumCandelas = (maxLum-minLum)*proportnLum + minLum
#rgb (linearized) for this gun is simply proportion of luminance
range
rgb = [-1,-1,-1]
rgb[gun] = proportnLum * 2. -1
dklCart = linalg.solve( dkl2rgbMatrix, rgb )
print 'these nums should be equal:', lum, round(dklCart[0],3),
'and yield rgb=',np.around(np.array(rgb),3)
return (rgb)

print 'DKLcartLum of -.5 for red, rgb=',DKLcartLumToPhosphorRGB(0,-.
5,gammaGrid)
print 'DKLcartLum of -.5 for green, rgb=',DKLcartLumToPhosphorRGB(1,-.
5,gammaGrid)
print 'DKLcartLum of -.5 for blue, rgb=',DKLcartLumToPhosphorRGB(2,-.
5,gammaGrid)
print 'DKLcartLum of -1 for red,
rgb=',DKLcartLumToPhosphorRGB(0,-1,gammaGrid)
print 'DKLcartLum of -1 for green,
rgb=',DKLcartLumToPhosphorRGB(1,-1,gammaGrid)
def cart2sph( ar ):
#ar is numpy array
r = m.sqrt(ar[0]**2 + ar[1]**2 + ar[2]**2) # r
elev = m.atan2(ar[0],m.sqrt(ar[1]**2+ar[2]**2)) # theta
# elev = m.atan2(ar[2],m.sqrt(XsqPlusYsq)) # theta
az = m.atan2(ar[2],ar[1]) # phi
# az = m.atan2(ar[1],ar[0]) # phi

elev = elev/m.pi*180 #convert from radians to degrees
az = az/m.pi*180 #convert from radians to degrees
sph = np.array( [elev,az,r] )
return sph

def dklSphericalToCart(dkl_Nx3):
#dklCartesian(Nx3) = dklSphericalToCart(dkl_Nx3(el,az,radius))
dkl_3xN = np.transpose(dkl_Nx3)#its easier to use in the other
orientation!
if np.size(dkl_3xN)==3:
RG, BY, LUM = misc.sph2cart(dkl_3xN[0],dkl_3xN[1],dkl_3xN[2])
else:
RG, BY, LUM =
misc.sph2cart(dkl_3xN[0,:],dkl_3xN[1,:],dkl_3xN[2,:])
dkl_cartesian = np.asarray([LUM, RG, BY])
return dkl_cartesian
#
#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)
# print 'Entered dkl2rgb with dkl_Nx3 = ',dkl_Nx3
# dkl_3xN = numpy.transpose(dkl_Nx3)#its easier to use in the other
orientation!
# if numpy.size(dkl_3xN)==3:
# RG, BY, LUM = misc.sph2cart(dkl_3xN[0],dkl_3xN[1],dkl_3xN[2])
# else:
# RG, BY, LUM =
misc.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)
# print 'dkl2rgb converted dkl to rgb with
dkl_cartesian=',dkl_cartesian , ' whereas my cartesian conversion
yields ', dklSphericalToCart(dkl_Nx3),
# print ' and rgb result is = ',rgb
#
# return numpy.transpose(rgb)#return in the shape we received it

#dkl spherical. Elevation (90 is pure luminance), Azimuth (0 is L-M,
90 is S-(L+M), Contrast/Radius -1 to 1
dklRedSpherical = [0.,0.,1.]; dklSconeYellowSpherical = [0.,90.,1.];
dklSconeBlueSpherical = [0.,-90.,1.]
#dkl cartesian LUM, RG, BY
dklRedCartCalculated = dklSphericalToCart(dklRedSpherical);
dklSconeBlueCartCalculated = dklSphericalToCart(dklSconeBlueSpherical)
dklRedCartesian = [0.,1.,0.]
print 'dklRedCartCalculated = ',dklRedCartCalculated, ' whereas I
thought it would be ',dklRedCartesian
print 'dklSconeBlueCartCalculated = ', dklSconeBlueCartCalculated
rgbRed = misc.dkl2rgb( dklRedSpherical, dkl2rgbMatrix ); rgbSconeBlue
= misc.dkl2rgb( dklSconeBlueSpherical , dkl2rgbMatrix)
print 'rgbRed from dkl is ', np.around(rgbRed,2) #0,0,0 for some
reason
print 'rgbSconeBlue from dkl is ', np.around(rgbSconeBlue,2)
#Because I'm interested in getting maximally differential colors,
maybe I should use pure guns, but use psychopy code to tell me what
the color coordinates are
#and the luminance? No because with yellow manipulation want to
maintain constant chromaticity.
#So maybe I should determine chromaticity of canonical yellow. Then
adjust luminance of that.
#try to convert rgb back to dkl
#linalg.solve(A, B) # Computes the "exact" solution, x, of the
well-determined, i.e., full rank, linear matrix equation Ax = B
#for conversion of RGB to DKL, A is the DKL->RGB conversion matrix and
B is the RGB coordinates
dklRedBackwardsCheck = linalg.solve(dkl2rgbMatrix, rgbRed)
print 'dklRedBackwardsCheck = ', np.around( dklRedBackwardsCheck, 2)
#it works
dklSconeBlueBackwardsCheck = linalg.solve(dkl2rgbMatrix, rgbSconeBlue)
print 'dklSconeBlueBackwardsCheck = ',
np.around( dklSconeBlueBackwardsCheck, 2), \
'versus dklSconeBlueCartCalculated = ',
np.around( dklSconeBlueCartCalculated, 2 )
dklRedGunOnly = linalg.solve(dkl2rgbMatrix, [1,-1,-1])
print 'dklRedGunOnly = ', np.around(dklRedGunOnly, 2)

unitsSupplement = ['', '90=lum,0=L-M,90=S,contrast/radius', '', '',
'', '','']
columns= ['name', 'DKL sph', 'DKL cart', 'RGB', 'DKL cart', 'DKL sph',
'RGB']
units=['', 'elev,az,r', 'LUM,GR,BY', 'R,G,B', 'LUM,GR,BY',
'elev,az,r' , 'R,G,B' ]

def calcEveryThingFromDKL(dkl_3xN, dkl2rgbMatrix):
dklSph = dkl_3xN
dklCart = dklSphericalToCart( dklSph )
rgb = misc.dkl2rgb ( dklSph, dkl2rgbMatrix )
#should rgb be 1x3 ( row) or 3x1 (column) ?
dklCartFromRGB = linalg.solve( dkl2rgbMatrix, rgb )
dklSphFromRGB = cart2sph( dklCartFromRGB )
return 'NA', dklSph, dklCart, rgb, dklCartFromRGB, dklSphFromRGB,
'NA'

def arrayOfTripletsToListOfStrs( arrayTriplets, decimals=2 ):
listStrs = list()
for t in arrayTriplets:
tripletNoBrackets = ''
for i in t: #for each number in the tripletNoBrackets
if type(i) != type(str()): #if it's not a string, turn it
into array and round it
i = np.around( np.array(i), decimals)
tripletNoBrackets += str(i) + ' '
listStrs.append( tripletNoBrackets )
return listStrs

everythingDklRed = list( calcEveryThingFromDKL( dklRedSpherical,
dkl2rgbMatrix ) ); everythingDklRed[0]='red Lcone'
everythingDklSconeYellow =
list( calcEveryThingFromDKL( dklSconeYellowSpherical,
dkl2rgbMatrix ) ); everythingDklSconeYellow[0]='yellow Scone'
everythingDklSconeBlue =
list( calcEveryThingFromDKL( dklSconeBlueSpherical, dkl2rgbMatrix ) );
everythingDklSconeBlue[0]='blue Scone'

everythingDklRedToPrint =
arrayOfTripletsToListOfStrs( everythingDklRed )
everythingDklSconeBlueToPrint =
arrayOfTripletsToListOfStrs( everythingDklSconeBlue )
everythingDklSconeYellowToPrint =
arrayOfTripletsToListOfStrs( everythingDklSconeYellow )

def calcEveryThingFromRGB(rgb_3xN, dkl2rgbMatrix):
rgb = rgb_3xN
dklCart = linalg.solve( dkl2rgbMatrix, rgb )
dklSph = cart2sph( dklCart )
rgbFromDklSph = misc.dkl2rgb ( dklSph, dkl2rgbMatrix )
return 'NA', 'NA', 'NA', rgb, dklCart, dklSph, rgbFromDklSph


purePhosphors = [ [1,-1,-1], [1,1,-1], [-1,-1,1] ]#add pure color guns
to see their color coordinates
purePhosphorsNames=['redGun','greenGun','blueGun']

if gotTexttable:
table = Texttable()
table.add_row(unitsSupplement)
table.add_row(columns)
table.add_row(units)
table.add_row( everythingDklRedToPrint )
table.add_row( everythingDklSconeBlueToPrint )
table.add_row( everythingDklSconeYellowToPrint )
for rgb,name in zip(purePhosphors,purePhosphorsNames):
#print rgb,name
cols = list( calcEveryThingFromRGB(rgb, dkl2rgbMatrix) )
cols[0] = name
colsToPrint = arrayOfTripletsToListOfStrs( cols )
table.add_row( colsToPrint )


#take pure red, but with luminance of -.5 and see how that does
redPatchBrightestDkl = copy.deepcopy( dklRedCartesian )
patchTopLum = -.6

dklCartRed = linalg.solve( dkl2rgbMatrix, [.9,-.2,-.2] )
dklCartYel = [-.4,0,0.2] # linalg.solve( dkl2rgbMatrix, [.3,.5,-.2] )
#[.07, .38, .87] # [-.55,.76,1.73]
dklCartBlue = linalg.solve( dkl2rgbMatrix,[-.8,-.8,1] )
#dklCartRed = redPatchBrightestDkl
#dklCartYel= dklSphericalToCart(dklSconeYellowSpherical)
#dklCartBlue= dklSphericalToCart(dklSconeBlueSpherical)

dklCartRed[0] = patchTopLum
dklCartYel[0] = patchTopLum
dklCartBlue[0] = patchTopLum

everything_dklCartRed=
list( calcEveryThingFromDKL( cart2sph(dklCartRed), dkl2rgbMatrix ) );
everything_dklCartRed[0]='redPatch'
if gotTexttable:
table.add_row( arrayOfTripletsToListOfStrs(everything_dklCartRed) )
everything_dklCartYel=
list( calcEveryThingFromDKL( cart2sph(dklCartYel), dkl2rgbMatrix ) );
everything_dklCartYel[0]='yelPatch'
if gotTexttable:
table.add_row( arrayOfTripletsToListOfStrs(everything_dklCartYel) )
everything_dklCartBlue=
list( calcEveryThingFromDKL( cart2sph(dklCartBlue), dkl2rgbMatrix ) );
everything_dklCartBlue[0]='bluPatch'
if gotTexttable:
table.add_row( arrayOfTripletsToListOfStrs(everything_dklCartBlue) )

if gotTexttable: print table.draw()

scrn=1 #1
fullscr=1 #1
allowGUI=True
winSize=(800,600) #(1024,768)
myWin =
visual.Window(monitor=mon,size=winSize,allowGUI=allowGUI,fullscr=fullscr,screen=scrn,colorSpace='name',color='black')

#draw luminance gradient using DKL of red next to luminance gradient
of a good yellow
allStim = list();

stepsInGradient = 12
topLumDkl = dklCartRed[0]
portionOfLumRangeToSpan = .6
lumStepDkl = (topLumDkl - -1)*portionOfLumRangeToSpan /
stepsInGradient #because spans -1 to 1

def makeLine(x,y,width,fillColorSpace,fillColor,orientation):
halfW =width/2.
rectangularVertices = [ [+halfW,-.9], [-halfW,-.9], [-halfW,+.9],
[+halfW,+.9] ]
line = visual.ShapeStim(myWin,
lineColorSpace='rgb',lineColor=[-1,-1,-1],
fillColorSpace=fillColorSpace, fillColor=fillColor,
units='norm',
lineWidth=1, #in pixels. must be greater than 0
vertices=rectangularVertices,#choose something from
the above or make your own
closeShape=True,#do you want the final vertex to
complete a loop with 1st?
interpolate=True,
ori=orientation,
pos= [x,y], #the anchor (rotaion and vertices are
position with respect to this)
autoLog=False)#this stim changes too much for
autologging to be useful
return (line)

def
makeSquare(width,lineColorSpace,lineColor,fillColorSpace,fillColor):
halfW =width/2.
sqrVertices = [ [halfW,-halfW], [-halfW,-halfW], [-halfW,halfW],
[halfW,halfW] ]
square = visual.ShapeStim(myWin,
lineColorSpace=lineColorSpace, lineColor=lineColor,
fillColorSpace=fillColorSpace, fillColor=fillColor,
units='norm',
lineWidth=1.0, #in pixels
vertices=sqrVertices,#choose something from the above
or make your own
closeShape=True,#do you want the final vertex to
complete a loop with 1st?
interpolate=True,
pos= [0.5,0.5], #the anchor (rotaion and vertices are
position with respect to this)
autoLog=False)#this stim changes too much for
autologging to be useful
return (square)
# import matplotlib
# matplotlib.use('WXAgg')
# from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
as FigureCanvas
# from matplotlib.figure import Figure
#plot DKLcart space
from psychopy import log
log.console.setLevel(log.CRITICAL) #don't print warnings because takes
time
stop=False
repetitions =1
if exportImages:
repetitions = 7 #to make 2 per second, have to show each frame
many times

for lum in np.arange(-.904,.9,.001): #np.arange(-.9,.9,.1):
for reps in range(repetitions):
colorStim=list()
lumText =
visual.TextStim(myWin,colorSpace='rgb',color=(1,1,1),ori=0,height=.
06,wrapWidth=999,alignHoriz='center', units='norm',autoLog=False)
lumText.setPos([0,.85]);
lumText.setText('L+M= '+str(round(lum,2))+ ' -1 is
minimum of screen, +1 is maximum')
colorStim.append(lumText)
stepsInGradient = 40
GRmin = -1.4 #-1.7;
GRmax = 2.0 #1.8
BYmin = -2.0 #-1.7;
BYmax = 1.4 #1.8
screenPortionToUse = .8
spacing = screenPortionToUse*2.0/stepsInGradient
xposMin = -screenPortionToUse*2.0/2 +.05
yposMin = -screenPortionToUse*2.0/2 +.05
GRstep = (GRmax-GRmin)*1.0/stepsInGradient
BYstep = (BYmax-BYmin)*1.0/stepsInGradient
labelSpacing = .1; labelFreq = round(labelSpacing/spacing)
grAxisText = visual.TextStim(myWin,colorSpace='rgb',color=(1,1,1),
height=.05, alignHoriz='center', units='norm',autoLog=False)
grAxisText.setPos([0,yposMin-spacing*2.6]); grAxisText.setText('GR
(L-M)')
colorStim.append(grAxisText)
byAxisText =
visual.TextStim(myWin,colorSpace='rgb',color=(1,1,1),ori=-90, height=.
05, alignHoriz='center', units='norm',autoLog=False)
byAxisText.setPos([xposMin-spacing*2.9,0]); byAxisText.setText('BY
(L+M)-S')
colorStim.append(byAxisText)

for GRi in range(stepsInGradient):
GR = GRmin + GRstep*GRi
xpos = xposMin + GRi*spacing
grStr=''
if GRi % labelFreq ==0: #draw GR text
grText =
visual.TextStim(myWin,colorSpace='rgb',color=(1,1,1), height=.05,
alignHoriz='center', units='norm',autoLog=False)
grText.setPos([xpos,yposMin-1.3*spacing]);
grStr = str(round(GR,2))
grText.setText(grStr);
colorStim.append( grText )
for BYi in range(stepsInGradient):
ypos = yposMin + BYi*spacing
BY = BYmin + BYstep*BYi
if GRi==0 and (BYi %labelFreq==0): #create y coordinate
text
byText =
visual.TextStim(myWin,colorSpace='rgb',color=(1,1,1), height=.05,
alignHoriz='center', units='norm',autoLog=False)
byText.setPos([xposMin-1.3*spacing,ypos]);
byStr = str(round(BY,2))
byText.setText(byStr);
colorStim.append( byText )
#create color patch
dklCart = [lum,GR,BY]
width = spacing*.8
height = spacing*.8

dklSph = cart2sph(dklCart)
rgb = misc.dkl2rgb ( dklSph, dkl2rgbMatrix ) #check my Dkl
to RGB conversion is working, visually
if np.any(np.array(rgb)**2.0>1.0): #if any desired RGB
values are outside gamut, drawsomething else instead
#print rgb
square = makeSquare(width*.9,'rgb',[-.9,-1,-.
9],'rgb',None)
square.setPos([xpos,ypos])
#colorStim.append( square ) #to save memory, of which I
run out, don't draw these
else:
square = makeSquare(width*.95,'rgb',
[1.,1.,1.],'dkl',dklSph)
#enclose it with a white circle so it shows up even if
wrong gamma
square.setPos([xpos,ypos])
colorStim.append( square )

#determine rgb values of phosphors for this luminance and the DKL
coordinates
phosphors=list();
for guni in range(0,3):
rgb= DKLcartLumToPhosphorRGB(guni,lum,gammaGrid)
rgb=np.array(rgb)
print 'rgb=',rgb
dklCart = linalg.solve( dkl2rgbMatrix, rgb )
print 'these nums should be equal:', lum, round(dklCart[0],3)
x = xposMin + (dklCart[1] - GRmin) / GRstep * spacing
y = yposMin + (dklCart[2] - BYmin) / BYstep * spacing
if not np.any(rgb**2>1): #not out of range
phosText =
visual.TextStim(myWin,colorSpace='rgb',color=rgb, height=.08,
alignHoriz='center',alignVert='center',units='norm',autoLog=False)
gunNames = ['R','G','B']
phosText.setText( gunNames[guni] )
phosText.setPos([x,y])
colorStim.append(phosText)
phosTextColor=[-1,-1,-1]; phosTextColor[guni]=1
phosTextNum =
visual.TextStim(myWin,colorSpace='rgb',color=phosTextColor,height=.05,
alignHoriz='center',alignVert='center',units='norm',autoLog=False)
phosTextNum.setText( str(round(dklCart[1],2))
+','+str(round(dklCart[2],2)) )
offsetAngles = [45,135,225]; offsetVec =
misc.pol2cart(offsetAngles[guni],.08)
phosTextNum.setPos([x+offsetVec[0],y+offsetVec[1]])
colorStim.append(phosTextNum)
#add lines for cartesian axes of graph
x = xposMin + (0 - GRmin) / GRstep * spacing
y = yposMin + (0 - BYmin) / BYstep * spacing
hline = makeLine(x,y,.005,'rgb',[0.1,0.1,0.1],0)
colorStim.append(hline)
vline = makeLine(x,y,.005,'rgb',[0.1,0.1,0.1],90)
colorStim.append(vline)
for thisStim in colorStim: #draw graph for this luminance
thisStim.draw()
myWin.flip()
if exportImages:
myWin.getMovieFrame(buffer='front') #for later saving
if not autopilot:
for key in event.getKeys(): #wait for key
if key in ['escape','q']: #check if pressed abort-type
key
stop=True
if not autopilot and not exportImages:
event.waitKeys() #wait until key hit
del colorStim #free memory

if exportImages:
myWin.saveMovieFrames('exported/frame.png')
#myWin.saveMovieFrames('exported/stimuli.mov', fps=1)

myWin.close(); core.quit()

#want to draw adjacent patches for minimally distinct border method

Jonathan Peirce

unread,
Nov 29, 2011, 3:49:50 AM11/29/11
to psychop...@googlegroups.com
Yes, the extended gamma equation that uses those values isn't working
properly yet. Stick to the original, shorter version of the gamma
correction equation for now.

Jon

On 28/11/2011 23:49, Alex Holcombe wrote:
> installation at least a, b, and k of the linearisation table are NaN.
> I think this is an oversight that should probably be fixed in a later
> version of Psychopy.

--
Jonathan Peirce
Nottingham Visual Neuroscience

http://www.peirce.org.uk


This message and any attachment are intended solely for the addressee and may contain confidential information. If you have received this message in error, please send it back to me, and immediately delete it. Please do not use, copy or disclose the information contained in this message or in any attachment. Any views or opinions expressed by the author of this email do not necessarily reflect the views of the University of Nottingham.

This message has been checked for viruses but the contents of an attachment
may still contain software viruses which could damage your computer system:
you are advised to perform your own checks. Email communications with the
University of Nottingham may be monitored as permitted by UK legislation.

joanne powell

unread,
Dec 4, 2011, 12:14:31 PM12/4/11
to psychop...@googlegroups.com
Thank you Jon and Alex for your response.
 
Kind regards
Joanne
 
> Date: Tue, 29 Nov 2011 08:49:50 +0000
> From: jonatha...@nottingham.ac.uk
> To: psychop...@googlegroups.com
> Subject: Re: [psychopy-users] Re: colour experiment (modulations in DKL space)
> --
> You received this message because you are subscribed to the Google Groups "psychopy-users" group.
> To post to this group, send email to psychop...@googlegroups.com.
> To unsubscribe from this group, send email to psychopy-user...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/psychopy-users?hl=en.
>

Chris Cox

unread,
Dec 4, 2011, 2:02:31 PM12/4/11
to psychop...@googlegroups.com
Hi everyone,

This must be mind numbingly simple, but I am having trouble getting my font to change.  Here is my code.  I certainly don't see a problem.

from psychopy import event,visual
from string import letters,digits

win = visual.Window(units='pix')
text = visual.TextStim(win=win,text=' '.join(letters+digits),height=30,wrapWidth=400)

for font in ['Times','Arial','Courier']:
    print font
    text.setFont(font)
    print text._font
    print text.fontname
    text.draw()
    win.flip()
    event.waitKeys()

I have couple print statements in there, in a failed attempt to gain insight into the problem.  Can someone catch my error?  I am running the script from ~/Documents/subfolder on a Mac running OS 10.6.  I am out of ideas.

Thank you very much,
Chris

Chris Cox

unread,
Dec 4, 2011, 2:23:53 PM12/4/11
to psychop...@googlegroups.com
By contrast, this does work...

from psychopy import event,visual
from string import letters,digits

win = visual.Window(units='pix')

for font in ['Sathu','Edwardian Script ITC','Capitals']:
    text = visual.TextStim(win=win,text=' '.join(letters+digits),height=30,wrapWidth=400,font=font)
    text.draw()
    win.flip()
    event.waitKeys()

So am I just missing something about .setFont()?  Is this a bug?

Chris

On Dec 4, 2011, at 1:02 PM, Chris Cox wrote:

Hi everyone,

This must be mind numbingly simple, but I am having trouble getting my font to change.  Here is my code.  I certainly don't see a problem.

from psychopy import event,visual
from string import letters,digits

win = visual.Window(units='pix')
text = visual.TextStim(win=win,text=' '.join(letters+digits),height=30,wrapWidth=400)

for font in ['Times New Roman','Arial','Courier']:

Jonathan Peirce

unread,
Dec 4, 2011, 2:55:03 PM12/4/11
to psychop...@googlegroups.com
It's a bug. Probably nobody ever tried to change the font of an existing stimulus (or at least nobody mentioned it).
The text has to be re-created after a font change and that wasn't being done. Easiest workaround is to call this after doing setFont():

    myStim.setText(myStim.text)

This is fixed in repository so will be fine in the next release. Thanks for letting us know.

Jon
-- 
Dr. Jonathan Peirce
Nottingham Visual Neuroscience

http://www.peirce.org.uk/

Chris Cox

unread,
Dec 4, 2011, 3:00:27 PM12/4/11
to psychop...@googlegroups.com
Thanks a lot! I can see how this is something that most people wouldn't want to do, so it is understandable that not many people would bring it up.  If my task were any more complicated, I probably wouldn't have tried this at all.
Reply all
Reply to author
Forward
0 new messages