~syleam/openobject-server/exit-properly

« back to all changes in this revision

Viewing changes to bin/reportlab/graphics/charts/utils.py

  • Committer: pinky
  • Date: 2006-12-07 13:41:40 UTC
  • Revision ID: pinky-3f10ee12cea3c4c75cef44ab04ad33ef47432907
New trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#Copyright ReportLab Europe Ltd. 2000-2004
 
2
#see license.txt for license details
 
3
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/graphics/charts/utils.py
 
4
"Utilities used here and there."
 
5
__version__=''' $Id$ '''
 
6
 
 
7
from time import mktime, gmtime, strftime
 
8
import string
 
9
 
 
10
 
 
11
### Dinu's stuff used in some line plots (likely to vansih).
 
12
 
 
13
def mkTimeTuple(timeString):
 
14
    "Convert a 'dd/mm/yyyy' formatted string to a tuple for use in the time module."
 
15
 
 
16
    list = [0] * 9
 
17
    dd, mm, yyyy = map(int, string.split(timeString, '/'))
 
18
    list[:3] = [yyyy, mm, dd]
 
19
 
 
20
    return tuple(list)
 
21
 
 
22
 
 
23
def str2seconds(timeString):
 
24
    "Convert a number of seconds since the epoch into a date string."
 
25
 
 
26
    return mktime(mkTimeTuple(timeString))
 
27
 
 
28
 
 
29
def seconds2str(seconds):
 
30
    "Convert a date string into the number of seconds since the epoch."
 
31
 
 
32
    return strftime('%Y-%m-%d', gmtime(seconds))
 
33
 
 
34
 
 
35
### Aaron's rounding function for making nice values on axes.
 
36
 
 
37
from math import log10
 
38
 
 
39
def nextRoundNumber(x):
 
40
    """Return the first 'nice round number' greater than or equal to x
 
41
 
 
42
    Used in selecting apropriate tick mark intervals; we say we want
 
43
    an interval which places ticks at least 10 points apart, work out
 
44
    what that is in chart space, and ask for the nextRoundNumber().
 
45
    Tries the series 1,2,5,10,20,50,100.., going up or down as needed.
 
46
    """
 
47
 
 
48
    #guess to nearest order of magnitude
 
49
    if x in (0, 1):
 
50
        return x
 
51
 
 
52
    if x < 0:
 
53
        return -1.0 * nextRoundNumber(-x)
 
54
    else:
 
55
        lg = int(log10(x))
 
56
 
 
57
        if lg == 0:
 
58
            if x < 1:
 
59
                base = 0.1
 
60
            else:
 
61
                base = 1.0
 
62
        elif lg < 0:
 
63
            base = 10.0 ** (lg - 1)
 
64
        else:
 
65
            base = 10.0 ** lg    # e.g. base(153) = 100
 
66
        # base will always be lower than x
 
67
 
 
68
        if base >= x:
 
69
            return base * 1.0
 
70
        elif (base * 2) >= x:
 
71
            return base * 2.0
 
72
        elif (base * 5) >= x:
 
73
            return base * 5.0
 
74
        else:
 
75
            return base * 10.0
 
76
 
 
77
 
 
78
### Robin's stuff from rgb_ticks.
 
79
 
 
80
from math import log10, floor
 
81
 
 
82
_intervals=(.1, .2, .25, .5)
 
83
_j_max=len(_intervals)-1
 
84
 
 
85
 
 
86
def find_interval(lo,hi,I=5):
 
87
    'determine tick parameters for range [lo, hi] using I intervals'
 
88
 
 
89
    if lo >= hi:
 
90
        if lo==hi:
 
91
            if lo==0:
 
92
                lo = -.1
 
93
                hi =  .1
 
94
            else:
 
95
                lo = 0.9*lo
 
96
                hi = 1.1*hi
 
97
        else:
 
98
            raise ValueError, "lo>hi"
 
99
    x=(hi - lo)/float(I)
 
100
    b= (x>0 and (x<1 or x>10)) and 10**floor(log10(x)) or 1
 
101
    b = b
 
102
    while 1:
 
103
        a = x/b
 
104
        if a<=_intervals[-1]: break
 
105
        b = b*10
 
106
 
 
107
    j = 0
 
108
    while a>_intervals[j]: j = j + 1
 
109
 
 
110
    while 1:
 
111
        ss = _intervals[j]*b
 
112
        n = lo/ss
 
113
        l = int(n)-(n<0)
 
114
        n = ss*l
 
115
        x = ss*(l+I)
 
116
        a = I*ss
 
117
        if n>0:
 
118
            if a>=hi:
 
119
                n = 0.0
 
120
                x = a
 
121
        elif hi<0:
 
122
            a = -a
 
123
            if lo>a:
 
124
                n = a
 
125
                x = 0
 
126
        if hi<=x and n<=lo: break
 
127
        j = j + 1
 
128
        if j>_j_max:
 
129
            j = 0
 
130
            b = b*10
 
131
    return n, x, ss, lo - n + x - hi
 
132
 
 
133
 
 
134
def find_good_grid(lower,upper,n=(4,5,6,7,8,9), grid=None):
 
135
    if grid:
 
136
        t = divmod(lower,grid)[0] * grid
 
137
        hi, z = divmod(upper,grid)
 
138
        if z>1e-8: hi = hi+1
 
139
        hi = hi*grid
 
140
    else:
 
141
        try:
 
142
            n[0]
 
143
        except TypeError:
 
144
            n = xrange(max(1,n-2),max(n+3,2))
 
145
 
 
146
        w = 1e308
 
147
        for i in n:
 
148
            z=find_interval(lower,upper,i)
 
149
            if z[3]<w:
 
150
                t, hi, grid = z[:3]
 
151
                w=z[3]
 
152
    return t, hi, grid
 
153
 
 
154
 
 
155
def ticks(lower, upper, n=(4,5,6,7,8,9), split=1, percent=0, grid=None):
 
156
    '''
 
157
    return tick positions and labels for range lower<=x<=upper
 
158
    n=number of intervals to try (can be a list or sequence)
 
159
    split=1 return ticks then labels else (tick,label) pairs
 
160
    '''
 
161
    t, hi, grid = find_good_grid(lower, upper, n, grid)
 
162
    power = floor(log10(grid))
 
163
    if power==0: power = 1
 
164
    w = grid/10.**power
 
165
    w = int(w)!=w
 
166
 
 
167
    if power > 3 or power < -3:
 
168
        format = '%+'+`w+7`+'.0e'
 
169
    else:
 
170
        if power >= 0:
 
171
            digits = int(power)+w
 
172
            format = '%' + `digits`+'.0f'
 
173
        else:
 
174
            digits = w-int(power)
 
175
            format = '%'+`digits+2`+'.'+`digits`+'f'
 
176
 
 
177
    if percent: format=format+'%%'
 
178
    T = []
 
179
    n = int(float(hi-t)/grid+0.1)+1
 
180
    if split:
 
181
        labels = []
 
182
        for i in xrange(n):
 
183
            v = t+grid*i
 
184
            T.append(v)
 
185
            labels.append(format % v)
 
186
        return T, labels
 
187
    else:
 
188
        for i in xrange(n):
 
189
            v = t+grid*i
 
190
            T.append((v, format % v))
 
191
        return T
 
 
b'\\ No newline at end of file'