python - Intelligently calculating chart tick positions -
whatever i'm using matplotlib, open-flash-charts or other charts frameworks end needing find way set x/y scales limits , intervals since builtins not enough smart (or not @ all...)
just try in pylab (ipyhton -pylab) understand mean:
in [1]: a, b, x = np.zeros(10), np.ones(10), np.arange(10) in [2]: plot(x, a); plot(x, b)
you'll see , empty frame grid hiding 2 horizontal lines under it's top , bottom borders.
i wonder if there algorithm around (that can port python) set smartly top , bottom y limits , steps , calculate every how many values show x thick.
for example, let's have 475 measures (datetime, temperature)
(x, y)
with
2011-01-15 10:45:00 < datetime < 2011-01-17 02:20:00
(one every 5 minutes) and
26.5 < temperature < 28.3
my suggestion particular case set:
26.4 <= y_scale <= 28.4
thick every.2
and tick on x_scale
every 12 items (once per hour).
but if have 20 measures on 20 days -21.5 < temperature < 38.7
, , on? there standardized method around?
the following i've used years simple , works enough. forgive me being c translating python shouldn't difficult.
the following function needed , graphic gems volume 1.
double nicenumber (const double value, const int round) { int exponent; double fraction; double nicefraction; exponent = (int) floor(log10(value)); fraction = value/pow(10, (double)exponent); if (round) { if (fraction < 1.5) nicefraction = 1.0; else if (fraction < 3.0) nicefraction = 2.0; else if (fraction < 7.0) nicefraction = 5.0; else nicefraction = 10.0; } else { if (fraction <= 1.0) nicefraction = 1.0; else if (fraction <= 2.0) nicefraction = 2.0; else if (fraction <= 5.0) nicefraction = 5.0; else nicefraction = 10.0; } return nicefraction*pow(10, (double)exponent); }
use in following example choose "nice" start/end of axis based on number of major ticks wish displayed. if don't care ticks can set constant value (ex: 10).
//input parameters double axisstart = 26.5; double axisend = 28.3; double numticks = 10; double axiswidth; double newaxisstart; double newaxisend; double nicerange; double nicetick; /* check special cases */ axiswidth = axisend - axisstart; if (axiswidth == 0.0) return (0.0); /* compute new nice range , ticks */ nicerange = nicenumber(axisend - axisstart, 0); nicetick = nicenumber(nicerange/(numticks - 1), 1); /* compute new nice start , end values */ newaxisstart = floor(axisstart/nicetick)*nicetick; newaxisend = ceil(axisend/nicetick)*nicetick; axisstart = newaxisstart; //26.4 axisend = newaxisend; //28.4
Comments
Post a Comment