1 coding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
2 ecoding = coding + '-.'
3 codeset = {
4 'simple': {
5 'coding': coding,
6 'max_value': 61,
7 'char': ',',
8 'dchar': '',
9 'none': '_',
10 'value': lambda x: coding[x]
11 },
12 'text': {
13 'coding': '',
14 'max_value': 100,
15 'none': '-1',
16 'char': '|',
17 'dchar': ',',
18 'value': lambda x: '%.1f'%float(x)
19 },
20 'extended': {
21 'coding': ecoding,
22 'max_value': 4095,
23 'none': '__',
24 'dchar': '',
25 'char': ',',
26 'value': lambda x: '%s%s'% \
27 (ecoding[int(float(x)/64)], ecoding[int(x%64)])
28 }
29 }
30
32 """Data encoder that handles simple,text, and extended encodings
33
34 Based on javascript encoding algorithm and pygooglecharts"""
35 - def __init__(self, encoding=None, scale=None, series=''):
44
46 return value
47 if self.encoding != 'text' and self.scale and \
48 isinstance(value, int) or isinstance(value, float):
49 if type(self.scale) == type(()):
50 lower,upper = self.scale
51 else:
52 lower,upper = 0,float(self.scale)
53 value = int(round(float(value - lower) * self.codeset['max_value'] / upper))
54 return min(value, self.codeset['max_value'])
55
56 - def encode(self, *args, **kwargs):
57 """Encode wrapper for a dataset with maximum value
58
59 Datasets can be one or two dimensional
60 Strings are ignored as ordinal encoding"""
61 if isinstance(args[0], str):
62 return self.encode([args[0]],**kwargs)
63 elif isinstance(args[0], int) or isinstance(args[0], float):
64 return self.encode([[args[0]]],**kwargs)
65 if len(args)>1:
66 dataset = args
67 else:
68 dataset = args[0]
69 typemap = list(map(type,dataset))
70 code = self.encoding[0]
71 if type('') in typemap:
72 data = ','.join(map(str,dataset))
73 elif type([]) in typemap or type(()) in typemap:
74 data = self.codeset['char'].join([self.encodedata(data) for data in dataset])
75 elif len(dataset) == 1 and hasattr(dataset[0], '__iter__'):
76 data = self.encodedata(dataset[0])
77 else:
78 data = self.encodedata(dataset)
79 if not '.' in data and code == 't':
80 code = 'e'
81 return '%s%s:%s'%(code,self.series,data)
82
84 sub_data = []
85 enc_size = len(self.codeset['coding'])
86 for value in data:
87 if value in (None,'None'):
88 sub_data.append(self.codeset['none'])
89 elif isinstance(value, str):
90 sub_data.append(value)
91 elif value >= -1:
92 try:
93 sub_data.append(self.codeset['value'](self.scalevalue(value)))
94 except:
95 raise ValueError('cannot encode value: %s'%value)
96 return self.codeset['dchar'].join(sub_data)
97
99 e = astr[0]
100 dec_data = []
101 for data in astr[2:].split(self.codeset['char']):
102 sub_data = []
103 if e == 't':
104 sub_data.extend([float(value) for value in data.split(',')])
105 elif e == 'e':
106 flag = 0
107 index = self.codeset['coding'].index
108 for i in range(len(data)):
109 if not flag:
110 this,next = index(data[i]),index(data[i+1])
111 flag = 1
112 sub_data.append((64 * this) + next)
113 else: flag = 0
114 elif e == 's':
115 sub_data.extend([self.codeset['coding'].index(value) for value in data])
116 dec_data.append(sub_data)
117 return dec_data
118
119
120 if __name__=='__main__':
121 import unittest
124 self.tests = [
125 ('simple','s:Ab9',[0,27,61],61),
126 ('text','t:0.0,10.0,100.0,-1.0,-1.0',[0,10,100,-1,-1],(0,100)),
127 ('extended','e:AH-HAA..',[7,3975,0,4095],4095)
128 ]
129
136
137 unittest.main()
138