def partfunctions(self, min, max, extendmin, extendmax): try: logmm = math.log(max - min) / math.log(10) except ArithmeticError: raise RuntimeError( "partitioning failed due to empty or invalid axis range") if logmm < 0: # correction for rounding towards zero of the int routine base = tick.rational((10, 1), power=int(logmm - 1)) else: base = tick.rational((10, 1), power=int(logmm)) ticks = list(map(tick.rational, self.variants[0])) useticks = [t * base for t in ticks] return [ lambda d=_partdata(min=min, max=max, extendmin=extendmin, extendmax=extendmax, sign=1, tickindex=-1, base=tick.rational(base)): self.partfunction(d), lambda d=_partdata(min=min, max=max, extendmin=extendmin, extendmax=extendmax, sign=-1, tickindex=0, base=tick.rational(base)): self.partfunction(d) ]
def __init__(self, plus="", minus="-", mantissaexp=r"{{%s}\cdot10^{%s}}", skipexp0=r"{%s}", skipexp1=None, nomantissaexp=r"{10^{%s}}", minusnomantissaexp=r"{-10^{%s}}", mantissamin=tick.rational((1, 1)), mantissamax=tick.rational((10L, 1)),
def __init__(self, plus="", minus="-", mantissaexp=r"{{%s}\cdot10^{%s}}", skipexp0=r"{%s}", skipexp1=None, nomantissaexp=r"{10^{%s}}", minusnomantissaexp=r"{-10^{%s}}", mantissamin=tick.rational((1, 1)), mantissamax=tick.rational((10, 1)), skipmantissa1=0, skipallmantissa1=1, mantissatexter=decimal()): r"""initializes the instance - plus or minus (string) is inserted for non-negative or negative exponents - mantissaexp (string) is taken as a format string generating the exponent; it has to contain exactly two string insert operators "%s" -- the first for the mantissa and the second for the exponent; examples are r"{{%s}\cdot10^{%s}}" and r"{{%s}{\rm e}{%s}}" - skipexp0 (string) is taken as a format string used for exponent 0; exactly one string insert operators "%s" for the mantissa; None turns off the special handling of exponent 0; an example is r"{%s}" - skipexp1 (string) is taken as a format string used for exponent 1; exactly one string insert operators "%s" for the mantissa; None turns off the special handling of exponent 1; an example is r"{{%s}\cdot10}" - nomantissaexp (string) is taken as a format string generating the exponent when the mantissa is one and should be skipped; it has to contain exactly one string insert operators "%s" for the exponent; an examples is r"{10^{%s}}" - minusnomantissaexp (string) is taken as a format string generating the exponent when the mantissa is minus one and should be skipped; it has to contain exactly one string insert operators "%s" for the exponent; None turns off the special handling of mantissa -1; an examples is r"{-10^{%s}}" - mantissamin and mantissamax are the minimum and maximum of the mantissa; they are rational instances greater than zero and mantissamin < mantissamax; the sign of the tick is ignored here - skipmantissa1 (boolean) turns on skipping of any mantissa equals one (and minus when minusnomantissaexp is set) - skipallmantissa1 (boolean) as above, but all mantissas must be 1 (or -1) - mantissatexter is the texter for the mantissa - the skipping of a mantissa is stronger than the skipping of an exponent""" self.plus = plus self.minus = minus self.mantissaexp = mantissaexp self.skipexp0 = skipexp0 self.skipexp1 = skipexp1 self.nomantissaexp = nomantissaexp self.minusnomantissaexp = minusnomantissaexp self.mantissamin = mantissamin self.mantissamax = mantissamax self.mantissamindivmax = self.mantissamin / self.mantissamax self.mantissamaxdivmin = self.mantissamax / self.mantissamin self.skipmantissa1 = skipmantissa1 self.skipallmantissa1 = skipallmantissa1 self.mantissatexter = mantissatexter
def __init__(self, tickdists=None, labeldists=None, extendtick=0, extendlabel=None, epsilon=1e-10): if tickdists is None and labeldists is not None: self.ticklist = [tick.rational(labeldists[0])] else: self.ticklist = map(tick.rational, tickdists) if labeldists is None and tickdists is not None: self.labellist = [tick.rational(tickdists[0])] else: self.labellist = map(tick.rational, labeldists) self.extendtick = extendtick self.extendlabel = extendlabel self.epsilon = epsilon
def partfunctions(self, min, max, extendmin, extendmax): try: logmm = math.log(max - min) / math.log(10) except ArithmeticError: raise RuntimeError("partitioning failed due to empty or invalid axis range") if logmm < 0: # correction for rounding towards zero of the int routine base = tick.rational((10, 1), power=int(logmm-1)) else: base = tick.rational((10, 1), power=int(logmm)) ticks = map(tick.rational, self.variants[0]) useticks = [t * base for t in ticks] return [lambda d=_partdata(min=min, max=max, extendmin=extendmin, extendmax=extendmax, sign=1, tickindex=-1, base=tick.rational(base)): self.partfunction(d), lambda d=_partdata(min=min, max=max, extendmin=extendmin, extendmax=extendmax, sign=-1, tickindex=0, base=tick.rational(base)): self.partfunction(d)]
def __init__(self, smallestdecimal=tick.rational((1, 1000)), biggestdecimal=tick.rational((9999, 1)), equaldecision=1, decimal=decimal(), exponential=exponential()): """initializes the instance - smallestdecimal and biggestdecimal are the smallest and biggest decimal values, where the decimal texter should be used; they are rational instances; the sign of the tick is ignored here; a tick at zero is considered for the decimal texter as well - equaldecision (boolean) uses decimal texter or exponential texter globaly (set) or for each tick separately (unset) - decimal and exponential are texters to be used""" self.smallestdecimal = smallestdecimal self.biggestdecimal = biggestdecimal self.equaldecision = equaldecision self.decimal = decimal self.exponential = exponential
def layout(data): self.adjustaxis(data, data.ticks, graphtexrunner, errorname) self.texter.labels(data.ticks) if self.divisor: for t in data.ticks: t *= tick.rational(self.divisor) canvas = painter.axiscanvas(self.painter, graphtexrunner) if self.painter is not None: self.painter.paint(canvas, data, self, positioner) return canvas
def autopartfunction(self, data): data.exponent *= self.autoexponent logarithmicparter = logarithmic(tickpreexps=[ preexp([tick.rational((1, 1))], data.exponent), logarithmic.pre1exp ], extendtick=self.extendtick, extendlabel=self.extendlabel, epsilon=self.epsilon) return logarithmicparter.partfunctions(min=data.min, max=data.max, extendmin=data.extendmin, extendmax=data.extendmax)[0]()
def testLogParter(self): self.PartEqual(log(tickpreexps=[log.pre1exp], labelpreexps=[]).partfunctions(1, 10, 1, 1)[0](), [tick((1, 1), 0, None), tick((10, 1), 0, None)]) self.PartEqual(log(tickpreexps=[log.pre1exp], labelpreexps=[]).partfunctions(1, 100, 1, 1)[0](), [tick((1, 1), 0, None), tick((10, 1), 0, None), tick((100, 1), 0, None)]) self.PartEqual(log(tickpreexps=[preexp([rational((1, 1))], 100)], labelpreexps=[]).partfunctions(1, 100, 1, 1)[0](), [tick((1, 1), 0, None), tick((100, 1), 0, None)]) self.PartEqual(log(tickpreexps=[log.pre1to9exp], labelpreexps=[]).partfunctions(1, 10, 1, 1)[0](), [tick((1, 1), 0, None), tick((2, 1), 0, None), tick((3, 1), 0, None), tick((4, 1), 0, None), tick((5, 1), 0, None), tick((6, 1), 0, None), tick((7, 1), 0, None), tick((8, 1), 0, None), tick((9, 1), 0, None), tick((10, 1), 0, None)]) self.PartEqual(log(tickpreexps=[log.pre1exp, log.pre1to9exp], labelpreexps=[]).partfunctions(1, 10, 1, 1)[0](), [tick((1, 1), 0, None), tick((2, 1), 1, None), tick((3, 1), 1, None), tick((4, 1), 1, None), tick((5, 1), 1, None), tick((6, 1), 1, None), tick((7, 1), 1, None), tick((8, 1), 1, None), tick((9, 1), 1, None), tick((10, 1), 0, None)]) self.PartEqual(log(tickpreexps=[log.pre1exp, log.pre1to9exp]).partfunctions(1, 10, 1, 1)[0](), [tick((1, 1), 0, 0), tick((2, 1), 1, None), tick((3, 1), 1, None), tick((4, 1), 1, None), tick((5, 1), 1, None), tick((6, 1), 1, None), tick((7, 1), 1, None), tick((8, 1), 1, None), tick((9, 1), 1, None), tick((10, 1), 0, 0)])
class autolinear(_parter): """partitioner to create an arbitrary number of linear partitions""" defaultvariants = [[tick.rational((1, 1)), tick.rational((1, 2))], [tick.rational((2, 1)), tick.rational((1, 1))], [tick.rational((5, 2)), tick.rational((5, 4))], [tick.rational((5, 1)), tick.rational((5, 2))]] def __init__(self, variants=defaultvariants, extendtick=0, epsilon=1e-10): self.variants = variants self.extendtick = extendtick self.epsilon = epsilon def partfunctions(self, min, max, extendmin, extendmax): try: logmm = math.log(max - min) / math.log(10) except ArithmeticError: raise RuntimeError("partitioning failed due to empty or invalid axis range") if logmm < 0: # correction for rounding towards zero of the int routine base = tick.rational((10, 1), power=int(logmm-1)) else: base = tick.rational((10, 1), power=int(logmm)) ticks = map(tick.rational, self.variants[0]) useticks = [t * base for t in ticks] return [lambda d=_partdata(min=min, max=max, extendmin=extendmin, extendmax=extendmax, sign=1, tickindex=-1, base=tick.rational(base)): self.partfunction(d), lambda d=_partdata(min=min, max=max, extendmin=extendmin, extendmax=extendmax, sign=-1, tickindex=0, base=tick.rational(base)): self.partfunction(d)] def partfunction(self, data): if data.sign == 1: if data.tickindex < len(self.variants) - 1: data.tickindex += 1 else: data.tickindex = 0 data.base.num *= 10 else: if data.tickindex: data.tickindex -= 1 else: data.tickindex = len(self.variants) - 1 data.base.denom *= 10 tickdists = [tick.rational(t) * data.base for t in self.variants[data.tickindex]] linearparter = linear(tickdists=tickdists, extendtick=self.extendtick, epsilon=self.epsilon) return linearparter.partfunctions(min=data.min, max=data.max, extendmin=data.extendmin, extendmax=data.extendmax)[0]()
def getticks(self, min, max, preexp, ticklevel=None, labellevel=None): ticks = [] minimin = 0 maximax = 0 for f in preexp.pres: thisticks = [] imin = int(math.ceil(math.log(min / float(f)) / math.log(preexp.exp) - 0.5 * self.epsilon)) imax = int(math.floor(math.log(max / float(f)) / math.log(preexp.exp) + 0.5 * self.epsilon)) for i in range(imin, imax + 1): pos = f * tick.rational((preexp.exp, 1), power=i) thisticks.append(tick.tick((pos.num, pos.denom), ticklevel = ticklevel, labellevel = labellevel)) ticks = tick.mergeticklists(ticks, thisticks) return ticks
def partfunction(self, data): if data.sign == 1: if data.tickindex < len(self.variants) - 1: data.tickindex += 1 else: data.tickindex = 0 data.base.num *= 10 else: if data.tickindex: data.tickindex -= 1 else: data.tickindex = len(self.variants) - 1 data.base.denom *= 10 tickdists = [tick.rational(t) * data.base for t in self.variants[data.tickindex]] linearparter = linear(tickdists=tickdists, extendtick=self.extendtick, epsilon=self.epsilon) return linearparter.partfunctions(min=data.min, max=data.max, extendmin=data.extendmin, extendmax=data.extendmax)[0]()
def testRationalInitSeq(self): self.RationalEqual(1, 1, rational((2, 2))) self.RationalEqual(1, 1, rational([2, 2]))
def autopartfunction(self, data): data.exponent *= self.autoexponent logarithmicparter= logarithmic(tickpreexps=[preexp([tick.rational((1, 1))], data.exponent), logarithmic.pre1exp], extendtick=self.extendtick, extendlabel=self.extendlabel, epsilon=self.epsilon) return logarithmicparter.partfunctions(min=data.min, max=data.max, extendmin=data.extendmin, extendmax=data.extendmax)[0]()
def _create(self, data, positioner, graphtexrunner, parter, rater, errorname): errorname = " for axis %s" % errorname if data.min is None or data.max is None: raise RuntimeError("incomplete axis range%s" % errorname) if data.max == data.min: if self.fallbackrange is not None: try: data.min, data.max = data.min - 0.5*self.fallbackrange, data.min + 0.5*self.fallbackrange except TypeError: data.min, data.max = self.fallbackrange[0], self.fallbackrange[1] else: raise RuntimeError("zero axis range%s" % errorname) if self.divisor is not None: rational_divisor = tick.rational(self.divisor) convert_tick = lambda x: float(x)*self.divisor else: convert_tick = lambda x: x def layout(data): if data.ticks: self.adjustaxis(data, [convert_tick(data.ticks[0]), convert_tick(data.ticks[-1])], graphtexrunner, errorname) self.texter.labels(data.ticks) if self.divisor: for t in data.ticks: t *= rational_divisor canvas = painter.axiscanvas(self.painter, graphtexrunner) if self.painter is not None: self.painter.paint(canvas, data, self, positioner) return canvas if parter is None: data.ticks = self.manualticks return layout(data) # a variant is a data copy with local modifications to test several partitions @functools.total_ordering class variant: def __init__(self, data, **kwargs): self.data = data for key, value in list(kwargs.items()): setattr(self, key, value) def __getattr__(self, key): return getattr(data, key) def __lt__(self, other): # we can also sort variants by their rate return self.rate < other.rate def __eq__(self, other): # we can also sort variants by their rate return self.rate == other.rate # build a list of variants bestrate = None if self.divisor is not None: if data.min is not None: data_min_divided = data.min/self.divisor else: data_min_divided = None if data.max is not None: data_max_divided = data.max/self.divisor else: data_max_divided = None partfunctions = parter.partfunctions(data_min_divided, data_max_divided, self.min is None, self.max is None) else: partfunctions = parter.partfunctions(data.min, data.max, self.min is None, self.max is None) variants = [] for partfunction in partfunctions: worse = 0 while worse < self.maxworse: worse += 1 ticks = partfunction() if ticks is None: break ticks = tick.mergeticklists(self.manualticks, ticks, mergeequal=0) if ticks: rate = rater.rateticks(self, ticks, self.density) if rate is not None: if self.reverse: rate += rater.raterange(self.convert(data, convert_tick(ticks[0])) - self.convert(data, convert_tick(ticks[-1])), 1) else: rate += rater.raterange(self.convert(data, convert_tick(ticks[-1])) - self.convert(data, convert_tick(ticks[0])), 1) if bestrate is None or rate < bestrate: bestrate = rate worse = 0 variants.append(variant(data, rate=rate, ticks=ticks)) if not variants: raise RuntimeError("no axis partitioning found%s" % errorname) if len(variants) == 1 or self.painter is None: # When the painter is None, we could sort the variants here by their rating. # However, we didn't did this so far and there is no real reason to change that. data.ticks = variants[0].ticks return layout(data) # build the layout for best variants for variant in variants: variant.storedcanvas = None variants.sort() while not variants[0].storedcanvas: variants[0].storedcanvas = layout(variants[0]) ratelayout = rater.ratelayout(variants[0].storedcanvas, self.density) if ratelayout is None: del variants[0] if not variants: raise NoValidPartitionError("no valid axis partitioning found%s" % errorname) else: variants[0].rate += ratelayout variants.sort() self.adjustaxis(data, variants[0].ticks, graphtexrunner, errorname) data.ticks = variants[0].ticks return variants[0].storedcanvas
def testRationalInitString(self): self.RationalEqual(1, 1, rational("1")) self.RationalEqual(11, 10, rational("1.1")) self.RationalEqual(12345, 1000, rational("12.345")) self.RationalEqual(1, 1, rational("1.")) self.RationalEqual(1, 10, rational(".1")) self.RationalEqual(1, 1, rational("1e+0")) self.RationalEqual(11, 10, rational("1.1e-0")) self.RationalEqual(10, 1, rational("1.e+1")) self.RationalEqual(1, 100, rational(".1e-1")) self.RationalEqual(-1, 1, rational("-1")) self.RationalEqual(-11, 10, rational("-1.1")) self.RationalEqual(-1, 1, rational("-1.")) self.RationalEqual(-1, 10, rational("-.1")) self.RationalEqual(-1, 1, rational("-1e0")) self.RationalEqual(-11, 10, rational("-1.1e-0")) self.RationalEqual(-10, 1, rational("-1.e+1")) self.RationalEqual(-1, 100, rational("-.1e-1")) self.RationalEqual(-100000000000000000000, 1, rational("-1e+20")) self.RationalEqual(-1, 100000000000000000000, rational("-1e-20")) self.RationalEqual(1234, 1, rational(" 1234")) self.assertRaises(ValueError, rational, "12 34") self.assertRaises(ValueError, rational, "1 2.34") self.assertRaises(ValueError, rational, "12 .34") self.assertRaises(ValueError, rational, "12. 34") self.assertRaises(ValueError, rational, "12.3 4") self.RationalEqual(1234, 100, rational("12.34 ")) self.RationalEqual(1234, 1, rational(" +1234")) self.RationalEqual(-1234, 1, rational(" -1234")) self.assertRaises(ValueError, rational, " + 1234") self.assertRaises(ValueError, rational, " - 1234") self.assertRaises(ValueError, rational, "12.34 e0") self.assertRaises(ValueError, rational, "12.34e 0") self.RationalEqual(1234, 10000, rational("12.34e-2")) self.RationalEqual(1234, 1000, rational("12.34E-1")) self.RationalEqual(1234, 100, rational("12.34e0 ")) self.RationalEqual(1234, 10, rational("12.34E+1")) self.RationalEqual(1234, 1, rational("12.34e+2")) self.assertRaises(ValueError, rational, "12.34e -0") self.assertRaises(ValueError, rational, "12.34e+ 0") self.assertRaises(ValueError, rational, "12.34e- 0") self.assertRaises(ValueError, rational, "12.34e +0") self.assertRaises(ValueError, rational, "12.34.56") self.assertRaises(ValueError, rational, "12e34.56")
def testRationalInitNumber(self): self.RationalEqual(1, 1, rational(1)) self.RationalEqual(11, 10, rational(1.1)) self.RationalEqual(1, 1, rational(1.0)) self.RationalEqual(1, 10, rational(0.1)) self.RationalEqual(1, 1, rational(1e0)) self.RationalEqual(11, 10, rational(1.1e-0)) self.RationalEqual(10, 1, rational(1.0e1)) self.RationalEqual(1, 100, rational(0.1e-1)) self.RationalEqual(-1, 1, rational(-1)) self.RationalEqual(-11, 10, rational(-1.1)) self.RationalEqual(-1, 1, rational(-1.0)) self.RationalEqual(-1, 10, rational(-0.1)) self.RationalEqual(-1, 1, rational(-1e0)) self.RationalEqual(-11, 10, rational(-1.1e-0)) self.RationalEqual(-10, 1, rational(-1.0e1)) self.RationalEqual(-1, 100, rational(-0.1e-1))
def testRationalInitStrings(self): self.RationalEqual(1, 2, rational("1/2")) self.RationalEqual(1, 2, rational("1.1/2.2")) self.RationalEqual(1, 2, rational("1./2.")) self.RationalEqual(1, 2, rational(".1/.2")) self.RationalEqual(1, 2, rational("1e+0/2e+0")) self.RationalEqual(1, 2, rational("1.1e-0/2.2e-0")) self.RationalEqual(1, 2, rational("1.e+1/2.e+1")) self.RationalEqual(1, 2, rational(".1e-1/.2e-1")) self.RationalEqual(1, 2, rational("-1/-2")) self.RationalEqual(1, 2, rational("-1.1/-2.2")) self.RationalEqual(1, 2, rational("-1./-2.")) self.RationalEqual(1, 2, rational("-.1/-.2")) self.RationalEqual(1, 2, rational("-1e0/-2e0")) self.RationalEqual(1, 2, rational("-1.1e-0/-2.2e-0")) self.RationalEqual(1, 2, rational("-1.e+1/-2.e+1")) self.RationalEqual(1, 2, rational("-.1e-1/-.2e-1"))
class logarithmic(linear): """partitioner to create a single logarithmic partition""" # define some useful constants pre1exp = preexp([tick.rational((1, 1))], 10) pre125exp = preexp([tick.rational((1, 1)), tick.rational((2, 1)), tick.rational((5, 1))], 10) pre1to9exp = preexp([tick.rational((x, 1)) for x in range(1, 10)], 10) # ^- we always include 1 in order to get extendto(tick|label)level to work as expected def __init__(self, tickpreexps=None, labelpreexps=None, extendtick=0, extendlabel=None, epsilon=1e-10): if tickpreexps is None and labelpreexps is not None: self.ticklist = [labelpreexps[0]] else: self.ticklist = tickpreexps if labelpreexps is None and tickpreexps is not None: self.labellist = [tickpreexps[0]] else: self.labellist = labelpreexps self.extendtick = extendtick self.extendlabel = extendlabel self.epsilon = epsilon def extendminmax(self, min, max, preexp, extendmin, extendmax): minpower = None maxpower = None for i in xrange(len(preexp.pres)): imin = int(math.floor(math.log(min / float(preexp.pres[i])) / math.log(preexp.exp) + self.epsilon)) + 1 imax = int(math.ceil(math.log(max / float(preexp.pres[i])) / math.log(preexp.exp) - self.epsilon)) - 1 if minpower is None or imin < minpower: minpower, minindex = imin, i if maxpower is None or imax >= maxpower: maxpower, maxindex = imax, i if minindex: minrational = preexp.pres[minindex - 1] else: minrational = preexp.pres[-1] minpower -= 1 if maxindex != len(preexp.pres) - 1: maxrational = preexp.pres[maxindex + 1] else: maxrational = preexp.pres[0] maxpower += 1 if extendmin: min = float(minrational) * float(preexp.exp) ** minpower if extendmax: max = float(maxrational) * float(preexp.exp) ** maxpower return min, max def getticks(self, min, max, preexp, ticklevel=None, labellevel=None): ticks = [] minimin = 0 maximax = 0 for f in preexp.pres: thisticks = [] imin = int(math.ceil(math.log(min / float(f)) / math.log(preexp.exp) - 0.5 * self.epsilon)) imax = int(math.floor(math.log(max / float(f)) / math.log(preexp.exp) + 0.5 * self.epsilon)) for i in range(imin, imax + 1): pos = f * tick.rational((preexp.exp, 1), power=i) thisticks.append(tick.tick((pos.num, pos.denom), ticklevel = ticklevel, labellevel = labellevel)) ticks = tick.mergeticklists(ticks, thisticks) return ticks
def _create(self, data, positioner, graphtextengine, parter, rater, errorname): errorname = " for axis %s" % errorname if data.min is None or data.max is None: raise RuntimeError("incomplete axis range%s" % errorname) if data.max == data.min: if self.fallbackrange is not None: try: data.min, data.max = data.min - 0.5 * self.fallbackrange, data.min + 0.5 * self.fallbackrange except TypeError: data.min, data.max = self.fallbackrange[ 0], self.fallbackrange[1] else: raise RuntimeError("zero axis range%s" % errorname) if self.divisor is not None: rational_divisor = tick.rational(self.divisor) convert_tick = lambda x: float(x) * self.divisor else: convert_tick = lambda x: x def layout(data): if data.ticks: self.adjustaxis(data, [ convert_tick(data.ticks[0]), convert_tick(data.ticks[-1]) ], graphtextengine, errorname) self.texter.labels(data.ticks) if self.divisor: for t in data.ticks: t *= rational_divisor canvas = painter.axiscanvas(self.painter, graphtextengine) if self.painter is not None: self.painter.paint(canvas, data, self, positioner) return canvas if parter is None: data.ticks = self.manualticks return layout(data) # a variant is a data copy with local modifications to test several partitions @functools.total_ordering class variant: def __init__(self, data, **kwargs): self.data = data for key, value in list(kwargs.items()): setattr(self, key, value) def __getattr__(self, key): return getattr(data, key) def __lt__(self, other): # we can also sort variants by their rate return self.rate < other.rate def __eq__(self, other): # we can also sort variants by their rate return self.rate == other.rate # build a list of variants bestrate = None if self.divisor is not None: if data.min is not None: data_min_divided = data.min / self.divisor else: data_min_divided = None if data.max is not None: data_max_divided = data.max / self.divisor else: data_max_divided = None partfunctions = parter.partfunctions(data_min_divided, data_max_divided, self.min is None, self.max is None) else: partfunctions = parter.partfunctions(data.min, data.max, self.min is None, self.max is None) variants = [] for partfunction in partfunctions: worse = 0 while worse < self.maxworse: worse += 1 ticks = partfunction() if ticks is None: break ticks = tick.mergeticklists(self.manualticks, ticks, mergeequal=0) if ticks: rate = rater.rateticks(self, ticks, self.density) if rate is not None: if self.reverse: rate += rater.raterange( self.convert(data, convert_tick(ticks[0])) - self.convert(data, convert_tick(ticks[-1])), 1) else: rate += rater.raterange( self.convert(data, convert_tick(ticks[-1])) - self.convert(data, convert_tick(ticks[0])), 1) if bestrate is None or rate < bestrate: bestrate = rate worse = 0 variants.append(variant(data, rate=rate, ticks=ticks)) if not variants: raise RuntimeError("no axis partitioning found%s" % errorname) if len(variants) == 1 or self.painter is None: # When the painter is None, we could sort the variants here by their rating. # However, we didn't did this so far and there is no real reason to change that. data.ticks = variants[0].ticks return layout(data) # build the layout for best variants for variant in variants: variant.storedcanvas = None variants.sort() while not variants[0].storedcanvas: variants[0].storedcanvas = layout(variants[0]) ratelayout = rater.ratelayout(variants[0].storedcanvas, self.density) if ratelayout is None: del variants[0] if not variants: raise NoValidPartitionError( "no valid axis partitioning found%s" % errorname) else: variants[0].rate += ratelayout variants.sort() self.adjustaxis(data, variants[0].ticks, graphtextengine, errorname) data.ticks = variants[0].ticks return variants[0].storedcanvas
def testRationalInitNumber(self): self.RationalEqual(1, 1, rational(1)) self.RationalEqual(11, 10, rational(1.1)) self.RationalEqual(1, 1, rational(1.)) self.RationalEqual(1, 10, rational(.1)) self.RationalEqual(1, 1, rational(1e+0)) self.RationalEqual(11, 10, rational(1.1e-0)) self.RationalEqual(10, 1, rational(1.e+1)) self.RationalEqual(1, 100, rational(.1e-1)) self.RationalEqual(-1, 1, rational(-1)) self.RationalEqual(-11, 10, rational(-1.1)) self.RationalEqual(-1, 1, rational(-1.)) self.RationalEqual(-1, 10, rational(-.1)) self.RationalEqual(-1, 1, rational(-1e0)) self.RationalEqual(-11, 10, rational(-1.1e-0)) self.RationalEqual(-10, 1, rational(-1.e+1)) self.RationalEqual(-1, 100, rational(-.1e-1))