[reportlab-users] findMinMaxStep()
Felipe Almeida Lessa
felipe.lessa at gmail.com
Fri Jan 27 13:54:03 EST 2006
Hi!
Disappointed about ReportLab's way of finding how to scale the axis, I
wrote a nice function to find it out to me while keeping in mind the
appearance when ReportLab plots the graph. It can be use for any
ValueAxis on any chart, for example:
chart = LinePlot()
chart.data = data = [[(10, 14), (11, 23), (12, 38)], [(9, 8), (11, 9), (13, 7)]]
chart.height = height = 10*cm
chart.width = width = 10*cm
for (axis, values, size, pos) in ((chart.xValueAxis, height, 0),
(chart.yValueAxis, width, 1)):
axis.valueMin, axis.valueMax, axis.valueStep = \
findMinMaxStep(data, size, pos=pos)
I hope someone find it useful. Here's the code:
from types import ListType, TupleType
def findMinMaxStep(rawData, size=5*cm, minValue=None, maxValue=None,
stepValue=None, aprox=50, pos=None):
"""findMinMaxStep(data, [size, ...]) -> (min, max, step)
Find minimum, maximum and step values between steps of aprox.
"""
# Some vars used below
scale = 100.0/aprox
error = aprox/2.0
# Get only the parts of the data that we want
data = rawData
if type(rawData[0]) in (ListType, TupleType):
# Flatten (remove nested)
data = sum(rawData, [])
if pos is not None:
# Remove 2nd dimension
data = [a[pos] for a in data]
# Remove Nones
data = [i for i in data if i is not None]
# Get the min and max values of the data
minData = min(data)
maxData = max(data)
if minValue is None:
# Calculate the Min value while keeping in mind the aproximation
Min = round((minData - error) * scale, -2) / scale
Min = min((Min, minData)) # Prevent buggy calculations
else:
Min = minValue
if maxValue is None:
# Calculate the Max value while keeping in mind the aproximation
Max = round((maxData + error) * scale, -2) / scale
Max = max((Max, maxData)) # Prevent buggy calculations
else:
Max = maxValue
if stepValue is None:
# Calculate the Step value while keeping in mind the height and the
# Min and Max values (to be coherent with what is being displayed)
Step = round(((Max - Min) * scale * cm) / (size * 2.0), -2) / scale
else:
Step = stepValue
# Check if the step value is valid (rounding can do disgusting things)
if Step <= 0:
if aprox > 15:
if size > 6*cm:
newAprox = 5
elif size > 3.5*cm:
newAprox = 10
else:
newAprox = 15
return findMinMaxStep(data, size, minValue, maxValue, stepValue,
newAprox)
else:
Step = aprox
# Try to make it look good on ReportLab's algorhythm
if minValue is None and int((Min - (1e-8*Step)) / 100) * 100 + Step != Min:
Min -= Step
if Min < 0 and minData >= 0:
Min = 0
# (Max-Min)/Step should be an integer
if divmod(Max - Min, Step)[1] != 0:
newMax = Min + Step * int((Max - Min) / Step)
while newMax < Max:
newMax += Step
Max = newMax
# Return the values we magically found
return Min, Max, Step
--
"Quem excele em empregar a força militar subjulga os exércitos dos
outros povos sem travar batalha, toma cidades fortificadas dos outros
povos sem as atacar e destrói os estados dos outros povos sem lutas
prolongadas. Deve lutar sob o Céu com o propósito primordial da
'preservação'. Desse modo suas armas não se embotarão, e os ganhos
poderão ser preservados. Essa é a estratégia para planejar ofensivas."
-- Sun Tzu, em "A arte da guerra"
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://two.pairlist.net/pipermail/reportlab-users/attachments/20060127/81e3ad74/attachment.html
More information about the reportlab-users
mailing list