1
2
3
4
5
6
7
8
9
10
11
12
13 __doc__='''Sequence variables support
14
15
16 $Id: DT_InSV.py 1069 2008-11-13 21:55:43Z stefan $'''
17 __version__='$Revision: 1069 $'[11:-2]
18
19 from string import lower, rfind, split, join
20 from math import sqrt
21 TupleType=type(())
22 try:
23 import Missing
24 mv=Missing.Value
25 except: mv=None
26
27
29
31
32 self.items=items
33 self.query_string=query_string
34 self.start_name_re=start_name_re
35
36 self.data=data={
37 'previous-sequence': 0,
38 'next-sequence': 0,
39 'sequence-start': 1,
40 'sequence-end': 0,
41 }
42
43
45 - def number(self,index): return index+1
46 - def even(self,index): return index%2 == 0
47 - def odd(self,index): return index%2
50 - def key(self,index): return self.items[index][0]
51 - def item(self,index, tt=type(())):
52 i=self.items[index]
53 if type(i) is tt and len(i)==2: return i[1]
54 return i
55
56 - def roman(self,index): return lower(self.Roman(index))
57
59
60 num = int(num)+1
61
62
63 roman = ''
64
65 while num >= 1000:
66 num = num - 1000
67 roman = '%sM' % roman
68
69 while num >= 500:
70 num = num - 500
71 roman = '%sD' % roman
72
73 while num >= 100:
74 num = num - 100
75 roman = '%sC' % roman
76
77 while num >= 50:
78 num = num - 50
79 roman = '%sL' % roman
80
81 while num >= 10:
82 num = num - 10
83 roman = '%sX' % roman
84
85 while num >= 5:
86 num = num - 5
87 roman = '%sV' % roman
88
89 while num < 5 and num >= 1:
90 num = num - 1
91 roman = '%sI' % roman
92
93
94
95 roman = sub('DCCCC', 'CM', roman)
96 roman = sub('CCCC', 'CD', roman)
97 roman = sub('LXXXX', 'XC', roman)
98 roman = sub('XXXX', 'XL', roman)
99 roman = sub('VIIII', 'IX', roman)
100 roman = sub('IIII', 'IV', roman)
101
102 return roman
103
104
105 - def value(self,index,name):
112
113 - def first(self,name,key=''):
114 data=self.data
115 if data['sequence-start']: return 1
116 index=data['sequence-index']
117 return self.value(index,name) != self.value(index-1,name)
118
119 - def last(self,name,key=''):
120 data=self.data
121 if data['sequence-end']: return 1
122 index=data['sequence-index']
123 return self.value(index,name) != self.value(index+1,name)
124
126 l=self.data['sequence-length']=len(self.items)
127 return l
128
129 - def query(self, *ignored):
130
131 if self.start_name_re is None: raise KeyError, 'sequence-query'
132 query_string=self.query_string
133 while query_string and query_string[:1] in '?&':
134 query_string=query_string[1:]
135 while query_string[-1:] == '&':
136 query_string=query_string[:-1]
137 if query_string:
138 query_string='&%s&' % query_string
139 re=self.start_name_re
140 l=re.search_group(query_string, (0,))
141 if l:
142 v=l[1]
143 l=l[0]
144 query_string=(query_string[:l]+
145 query_string[l+len(v)-1:])
146 query_string='?'+query_string[1:]
147 else: query_string='?'
148 self.data['sequence-query']=query_string
149 return query_string
150
151
152 statistic_names=(
153 'total', 'count', 'min', 'max', 'median', 'mean',
154 'variance', 'variance-n','standard-deviation', 'standard-deviation-n',
155 )
156
158 items=self.items
159 data=self.data
160 mapping=data['mapping']
161 count=sum=sumsq=0
162 min=max=None
163 scount=smin=smax=None
164 values=[]
165 svalues=[]
166 for item in items:
167 try:
168 if mapping: item=item[name]
169 else: item=getattr(item,name)
170 try:
171 if item is mv:
172 item = None
173 if type(item)==type(1):
174 s=item*long(item)
175 else:
176 s=item*item
177 sum=sum+item
178 sumsq=sumsq+s
179 values.append(item)
180 if min is None:
181 min=max=item
182 else:
183 if item < min: min=item
184 if item > max: max=item
185 except:
186 if item is not None and item is not mv:
187 if smin is None: smin=smax=item
188 else:
189 if item < smin: smin=item
190 if item > smax: smax=item
191 svalues.append(item)
192 except: pass
193
194
195 for stat in self.statistic_names: data['%s-%s' % (stat,name)]=''
196
197 count=len(values)
198 try:
199 n=float(count)
200 mean=sum/n
201 sumsq=sumsq/n - mean*mean
202 data['mean-%s' % name]=mean
203 data['total-%s' % name]=sum
204 data['variance-n-%s' % name]=sumsq
205 data['standard-deviation-n-%s' % name]=sqrt(sumsq)
206 if count > 1:
207 sumsq=sumsq*n/(n-1)
208 data['variance-%s' % name]=sumsq
209 data['standard-deviation-%s' % name]=sqrt(sumsq)
210 else:
211 data['variance-%s' % name]=''
212 data['standard-deviation-%s' % name]=''
213 except:
214 if min is None: min,max,values=smin,smax,svalues
215 else:
216 if smin < min: min=smin
217 if smax > max: max=smax
218 values=values+svalues
219 count=len(values)
220
221 data['count-%s' % name]=count
222
223 if min is not None:
224 data['min-%s' % name]=min
225 data['max-%s' % name]=max
226 values.sort()
227 if count==1:
228 data['median-%s' % name]=min
229 else:
230 n=count+1
231 if n/2*2==n: data['median-%s' % name]=values[n/2-1]
232 else:
233 n=n/2
234 try: data['median-%s' % name]=(values[n]+values[n-1])/2
235 except:
236 try: data['median-%s' % name]=(
237 "between %s and %s" % (values[n],values[n-1]))
238 except: pass
239
240 return data[key]
241
243 if suffix != 'batches': raise KeyError, key
244 data=self.data
245 sequence=self.items
246 try:
247 if not data['next-sequence']: return ()
248 sz=data['sequence-step-size']
249 start=data['sequence-step-start']
250 end=data['sequence-step-end']
251 l=len(sequence)
252 orphan=data['sequence-step-orphan']
253 overlap=data['sequence-step-overlap']
254 except: AttributeError, 'next-batches'
255 r=[]
256 while end < l:
257 start,end,spam=opt(end+1-overlap,0,sz,orphan,sequence)
258 v=sequence_variables(self.items,
259 self.query_string,self.start_name_re)
260 d=v.data
261 d['batch-start-index']=start-1
262 d['batch-end-index']=end-1
263 d['batch-size']=end+1-start
264 d['mapping']=data['mapping']
265 r.append(v)
266 data['next-batches']=r
267 return r
268
270 if suffix != 'batches': raise KeyError, key
271 data=self.data
272 sequence=self.items
273 try:
274 if not data['previous-sequence']: return ()
275 sz=data['sequence-step-size']
276 start=data['sequence-step-start']
277 end=data['sequence-step-end']
278 l=len(sequence)
279 orphan=data['sequence-step-orphan']
280 overlap=data['sequence-step-overlap']
281 except: AttributeError, 'previous-batches'
282 r=[]
283 while start > 1:
284 start,end,spam=opt(0,start-1+overlap,sz,orphan,sequence)
285 v=sequence_variables(self.items,
286 self.query_string,self.start_name_re)
287 d=v.data
288 d['batch-start-index']=start-1
289 d['batch-end-index']=end-1
290 d['batch-size']=end+1-start
291 d['mapping']=data['mapping']
292 r.append(v)
293 r.reverse()
294 data['previous-batches']=r
295 return r
296
297
298 special_prefixes={
299 'first': first,
300 'last': last,
301 'previous': previous_batches,
302 'next': next_batches,
303
304 'sequence-index': lambda self, suffix, key: self['sequence-'+suffix],
305 'sequence-index-is': lambda self, suffix, key: self['sequence-'+suffix],
306 }
307 for n in statistic_names: special_prefixes[n]=statistics
308
313 data=self.data
314 if data.has_key(key): return data[key]
315
316 l=rfind(key,'-')
317 if l < 0: raise KeyError, key
318
319 suffix=key[l+1:]
320 prefix=key[:l]
321
322 if hasattr(self, suffix):
323 try: v=data[prefix+'-index']
324 except: pass
325 else: return getattr(self,suffix)(v)
326
327 if special_prefix(prefix):
328 return special_prefixes[prefix](self, suffix, key)
329
330 if prefix[-4:]=='-var':
331 prefix=prefix[:-4]
332 try: return self.value(data[prefix+'-index'],suffix)
333 except: pass
334
335 if key=='sequence-query': return self.query()
336
337 raise KeyError, key
338
339
340
341
342 -def sub(s1, s2, src):
343 return join(split(src, s1), s2)
344
345 -def opt(start,end,size,orphan,sequence):
346 if size < 1:
347 if start > 0 and end > 0 and end >= start:
348 size=end+1-start
349 else: size=7
350
351 if start > 0:
352
353 try: sequence[start-1]
354 except: start=len(sequence)
355
356
357 if end > 0:
358 if end < start: end=start
359 else:
360 end=start+size-1
361 try: sequence[end+orphan-1]
362 except: end=len(sequence)
363
364 elif end > 0:
365 try: sequence[end-1]
366 except: end=len(sequence)
367
368 start=end+1-size
369 if start - 1 < orphan: start=1
370 else:
371 start=1
372 end=start+size-1
373 try: sequence[end+orphan-1]
374 except: end=len(sequence)
375
376 return start,end,size
377