|
From: Helge A. <av...@ii...> - 2004-10-01 16:52:23
|
John Hunter <jdh...@ac...> writes:
|
| Do you have any thoughts on how we might do labels with your code?
2 ways:
1) automatically: define a coarser(user defined coarseness) mesh on
the function to be labelled, and add the labels in the vertices of
this mesh. the angle of each label can easily be found from the
closest contour line segment. this method avoids clusters of labels
effectively, but will not be good in areas with high variability.
2) manually: let the user point and click on contours, I implemented
this for use with gist that you could take a look at (clabel below).
matlab also does this, and I think this is the best way for real
publication quality. I have never seen automatic routines that do
labelling well. TECPLOT is close but not quite there.
I also attached a routine to do this for 2D stretched coordinates (see
the contour plots with labels on
http://www.ii.uib.no/~avle/python.html
for examples) which is called vclabel
|
| If we decide to go with your routines, at least for the time being
| until we can "do it right", would you be willing to contribute your
| code to matplotlib under the matplotlib license (PSF inspired, free
| for commercial and noncommercial reuse)?
sure, no problem.
Helge
def clabel(z,clevels,opa=1,col='black',meth='std',digits=1):
"""
clabel(z,clevels,opa=1,col='black')
At the point where the mouse is clicked, print the contour level
from clevels that are closest to the interpolated value in this
point. Meant to be useful for labeling contour lines manually...
optional arguments:
opa=0 : Transparent text.
opa=1 : Erase background under label
col='white' : text color.
meth= 'std' bilinear interpo on a std grid, might give error near coast
'grid' values not given cellcentered but on corners of cells.
'bigrid' values taken from a bilinearly interpol fine mesh from
futil.contour
'cell' takes value from cell directly
Helge Avlesen <av...@ii...>
"""
print """
Insert contour levels by left clicking, middle button display
values, right button finishes.
"""
button=0
while button<>3:
mus=gist.mouse()
button=mus[9]
if meth=='bigrid':
i=int(2*mus[0])+1 ; j=int(2*mus[1])+1
x=2*mus[0]-i+1 ; y=2*mus[1]-j+1
elif meth=='std':
i=int( mus[0] ); j=int( mus[1] )
x=mus[0]-i ; y=mus[1]-j
elif meth=='grid':
xm=mus[0]+0.5 ; ym=mus[1]+0.5
i=int( xm ); j=int( ym )
x=xm-i ; y=ym-j
elif meth=='cell':
print mus[0], mus[1]
i=int(round(mus[0])) ; j=int(round(mus[1]))
if meth=='cell':
val=z[i,j]
print val,i,j
else:
# bilinear interpolation to find value
a00=z[i,j]
a10=z[i+1,j]-a00
a01=z[i,j+1]-a00
a11=z[i+1,j+1]-(a00+a10+a01)
val=a00 + a10*x + a01*y + a11*x*y
print val,i,j,x,y
if button==1:
# compare this value to the selected levels
diff= abs( clevels-val )
# use the closest
label=fpformat.fix( clevels[ Numeric.argmin(diff) ], digits )
gist.plt(label, mus[0], mus[1], opaque=opa, tosys=1, \
height=8, justify="CH", color=col )
def vclabel(z,sx,sy,clevels,opa=1,col='black',digits=1):
"""
manual(z,clevels,opa=1,col='black')
At the point where the mouse is clicked, print the contour level
from clevels that are closest to the interpolated value in this
point. Meant to be useful for labeling contour lines manually...
sx[i,j],sy[i,j] is the x,z coordinate of point z[i,j]. if [:,1]
denotes the top layer, [:,kb-1] the bottom (common in
oceanography) j_is_down will be true. (z is always positive in
the upward direction, but the indice j may go downwards)
optional arguments:
opa=0 : Transparent text.
opa=1 : Use background color for text.
col='white' : text color.
digits: number of decimals in label
Helge Avlesen <av...@ii...>
"""
print """
Insert contour levels by left clicking, middle button display
depth, right button finishes.
"""
kb=z.shape[1]
im=z.shape[0]
j_is_down=0
if sy[0,0]>sy[0,1]:
j_is_down=1
button=0
while button<>3:
mus=gist.mouse()
button=mus[9]
# bisection search for the indices
i=hbisect( sx[:,0], mus[0] )
if i<0 or i>im-1:
print 'outside:',i
continue
x=(mus[0]-sx[i,0])/(sx[i+1,0]-sx[i,0])
if j_is_down:
finn=hbisect( (1.-x)*sy[i,::-1] + x*sy[i+1,::-1] , mus[1] )
j=kb-2-finn
if finn<0 or finn>kb-1:
print 'outside',i,finn
continue
xa=Numeric.array((sx[i,j+1]+x*(sx[i+1,j+1]-sx[i,j+1]),\
sy[i,j+1]+x*(sy[i+1,j+1]-sy[i,j+1])))
if mus[1]-xa[1]<0:
print 'below'
continue
xb=Numeric.array((sx[i,j]+x*(sx[i+1,j]-sx[i,j]),\
sy[i,j]+x*(sy[i+1,j]-sy[i,j])))
y=(((mus[0]-xa[0])**2 + (mus[1]-xa[1])**2 )\
/((xb[0]-xa[0])**2 + (xb[1]-xa[1])**2 ))**0.5
# bilinear interpolation to find value
a1=z[i,j+1]
a2=z[i+1,j+1]-a1
a3=z[i,j]-a1
a4=z[i+1,j]-(a1+a2+a3)
val=a1 + a2*x + a3*y + a4*x*y
else:
print 'increasing j upwards not yet implemented'
continue
print 'x,y=',x,y,' i,j=',i,j, 'val=',val
if button==1:
# compare this value to the selected levels
diff= abs( clevels-val )
# use the closest
label=fpformat.fix( clevels[ Numeric.argmin(diff) ], 1)
if opa==1:
label=' '+label+' '
gist.plt(label, mus[0], mus[1], opaque=opa, tosys=1, \
height=8, justify="CH", color=col )
|