[Matrix-SIG] algorithm for intelligent axis scaling?

Konrad Hinsen hinsen@cnrs-orleans.fr
Fri, 19 Mar 1999 16:47:24 +0100


> I'm afraid this might not be needed anymore, but I guess it's good to have
> as many different opinions on how to solve a particular problem as
> possible...:

Right, so I'll add mine as well (from my Tk plotting widget). You call it
with the lower and upper limits of what you want to see, and it returns
a list of tick marks (value/string pairs):

    import Numeric

    def ticks(lower, upper):
	ideal = (upper-lower)/7.
	log = Numeric.log10(ideal)
	power = Numeric.floor(log)
	fraction = log-power
	factor = 1.
	error = fraction
	for f, lf in multiples:
	    e = Numeric.fabs(fraction-lf)
	    if e < error:
		error = e
		factor = f
	grid = factor * 10.**power
        if power > 3 or power < -3:
            format = '%+7.0e'
        elif power >= 0:
            digits = max(1, int(power))
            format = '%' + `digits`+'.0f'
        else:
            digits = -int(power)
            format = '%'+`digits+2`+'.'+`digits`+'f'
	ticks = []
	t = -grid*Numeric.floor(-lower/grid)
	while t <= upper and len(ticks) < 200:
	    ticks.append(t, format % (t,))
	    t = t + grid
	return ticks

    multiples = [(2., Numeric.log10(2.)), (5., Numeric.log10(5.))]

To decide about the limits to feed to ticks(), I use the following
function. It is called with the smallest and largest value in the
dataset and returns updated values for the limits according to one
of two strategies (minimal plot box or "nicely rounded"):

    def axisInterval(spec, lower, upper):
	if spec == 'minimal':
	    if lower == upper:
		return lower-0.5, upper+0.5
	    else:
		return lower, upper
	if spec == 'automatic':
	    range = upper-lower
	    if range == 0.:
		return lower-0.5, upper+0.5
	    log = Numeric.log10(range)
	    power = Numeric.floor(log)
	    fraction = log-power
	    if fraction <= 0.05:
		power = power-1
	    grid = 10.**power
	    lower = lower - lower % grid
	    mod = upper % grid
	    if mod != 0:
		upper = upper - mod + grid
	    return lower, upper
	if type(spec) == type(()):
	    lower, upper = spec
	    if lower <= upper:
		return lower, upper
	    else:
		return upper, lower
	raise ValueError, str(spec) + ': illegal axis specification'

-- 
-------------------------------------------------------------------------------
Konrad Hinsen                            | E-Mail: hinsen@cnrs-orleans.fr
Centre de Biophysique Moleculaire (CNRS) | Tel.: +33-2.38.25.55.69
Rue Charles Sadron                       | Fax:  +33-2.38.63.15.17
45071 Orleans Cedex 2                    | Deutsch/Esperanto/English/
France                                   | Nederlands/Francais
-------------------------------------------------------------------------------