Hi,
In learning to make a nice plot for a small window on a web page,
I had to go through a number of contortions to get the layout correct.
Graph layout should be based on em and ex spacing rather than
portion of the viewable area. The attached file computes the
portions as best it can based on the font size (I don't know if
em and ex are readily available). It still isn't right. In
particular, the legend box width can't be controlled properly,
or the distance between legend and one graph edge since there
is one number for each of axespad and pad regardless of aspect ratio.
I propose allowing all dimensions to carry units with them:
point, pixel, font, axis, figure or data
The x and y dims may have different units. Even for the same
units, the x and y will be different because of aspect ratio.
I would suggest allowing string values such as:
'10pt', '14px', '1ch', '0.01ax', '0.01fig', '35d'
or pairs:
(10,'pt'), (14,'px'), ...
The OOP trick of 10*pt, 14*px, etc. is cute, but the names need
to be much longer for this to work.
The transform= kw on some entries would no longer be necessary.
I won't have time to code this for a long time, but I wanted
to get it out there while it is fresh in my mind, and give
people a chance to comment on it.
A further note: small/medium/large aren't quite what I wanted
for relative font sizes. It would be nice to be able to specify
0.9x/1x/1.1x instead.
- Paul
import numpy
# Note: I'm using Figure and Canvas directly rather than pylab since
# pylab is not thread safe, but my app is.
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg as Canvas
# Use relative fonts rather than absolute fonts
# These are all the fields required to control the text size
from matplotlib import rcParams
rcParams['font.size']=10
rcParams['xtick.labelsize'] = 'small'
rcParams['ytick.labelsize'] = 'small'
rcParams['legend.fontsize'] = 'small'
rcParams['axes.labelsize'] = 'medium'
rcParams['axes.titlesize'] = 'medium'
rcParams['legend.numpoints'] = 1
def plotbins(x,yset,title=None,filename=None):
# Compute margin sizes in figure units from size relative to font
fontsize = rcParams['font.size']/72. # fontsize in inches
w,h= 5, 2.5 # figure dims in inches
dw,dh = [fontsize/s for s in (w,h)] # fontsize wrt figure
#l,r,t,b= 0.75/w, .25/w, .5/h, .5/h # margins in inches
l,r,t,b = 4*dw,1*dw,2*dh,2.5*dh # margins wrt to fontsize
aw,ah = w*(1-(l+r)),h*(1-(t+b)) # axes dims in inches
adw,adh = [fontsize/s for s in (aw,ah)] # fontsize wrt axes
# Create figure and axes
fig = Figure(figsize=(w,h),dpi=72)
ax = fig.gca()
ax.set_position([l, b, 1-(l+r), 1-(t+b)])
ax.set_title(title)
ax.set_xlabel('Bin Number')
ax.set_ylabel('Counts')
# Put some text on the graph
# Note: alpha blending on background doesn't seem to work
ax.text(1-0.5*adw, 0.5*adh, 'cumulative histogram',
transform=ax.transAxes, ha='right', va='bottom',
fontsize='small', backgroundcolor=(0.7,0.8,0,0.1))
ax.hold(True)
legend = []
for ylabel,y in yset.items():
ax.plot(x,y,'-+')
legend.append(ylabel)
if len(legend) > 0:
# Set legend properties based on font size
# This doesn't really work because the padding and axespadding
# is affected by aspect ratio. Padding in particular relative
# to the legend box makes the spacing before and after depend
# on the number of lines, but it is the best I can do within
# the context of the transform.
ax.legend(legend, loc='best',
pad=0.75/len(legend), # padding is wrt legend box
axespad=0.5*adh, # axespad is wrt axes
labelsep=0.2*adh, # labelsep is wrt axes
handletextsep=0.5*adw) # handle text is wrt axes
canvas = Canvas(fig)
canvas.print_figure(filename)
x = numpy.arange(10)
yset = dict((label,numpy.cumsum(numpy.random.randint(20,size=10)))
for label in ['apples','oranges','bananas','grapes'])
# Show plots with different font sizes
rcParams['font.size']=9
plotbins(x,yset,title='random fruits 9pt',filename='bins9.png')
rcParams['font.size']=14
plotbins(x,yset,title='random fruits 14pt',filename='bins14.png')
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel