Deleted Added
sdiff udiff text old ( 1547:1f0c266940d4 ) new ( 1758:74acd5b23964 )
full compact
1from __future__ import division
2import operator, re, types
3
4source = None
5display_run = 0
6global globalTicks
7globalTicks = None
8
9def total(f):
10 if isinstance(f, FormulaStat):
11 v = f.value
12 else:
13 v = f
14
15 f = FormulaStat()
16 if isinstance(v, (list, tuple)):
17 f.value = reduce(operator.add, v)
18 else:
19 f.value = v
20
21 return f
22
23def unaryop(op, f):
24 if isinstance(f, FormulaStat):
25 v = f.value
26 else:
27 v = f
28
29 if isinstance(v, (list, tuple)):
30 return map(op, v)
31 else:
32 return op(v)
33
34def zerodiv(lv, rv):
35 if rv == 0.0:
36 return 0.0
37 else:
38 return operator.truediv(lv, rv)
39
40def wrapop(op, lv, rv):
41 if isinstance(lv, str):
42 return lv
43
44 if isinstance(rv, str):
45 return rv
46
47 return op(lv, rv)
48
49def same(lrun, rrun):
50 for lx,rx in zip(lrun.keys(),rrun.keys()):
51 if lx != rx:
52 print 'lx != rx'
53 print lx, rx
54 print lrun.keys()
55 print rrun.keys()
56 return False
57 for ly,ry in zip(lrun[lx].keys(),rrun[rx].keys()):
58 if ly != ry:
59 print 'ly != ry'
60 print ly, ry
61 print lrun[lx].keys()
62 print rrun[rx].keys()
63 return False
64 return True
65
66
67def binaryop(op, lf, rf):
68 result = {}
69
70 if isinstance(lf, FormulaStat) and isinstance(rf, FormulaStat):
71 lv = lf.value
72 rv = rf.value
73
74 theruns = []
75 for r in lv.keys():
76 if rv.has_key(r):
77 if same(lv[r], rv[r]):
78 theruns.append(r)
79 else:
80 raise AttributeError
81
82 for run in theruns:
83 result[run] = {}
84 for x in lv[run].keys():
85 result[run][x] = {}
86 for y in lv[run][x].keys():
87 result[run][x][y] = wrapop(op, lv[run][x][y],
88 rv[run][x][y])
89 elif isinstance(lf, FormulaStat):
90 lv = lf.value
91 for run in lv.keys():
92 result[run] = {}
93 for x in lv[run].keys():
94 result[run][x] = {}
95 for y in lv[run][x].keys():
96 result[run][x][y] = wrapop(op, lv[run][x][y], rf)
97 elif isinstance(rf, FormulaStat):
98 rv = rf.value
99 for run in rv.keys():
100 result[run] = {}
101 for x in rv[run].keys():
102 result[run][x] = {}
103 for y in rv[run][x].keys():
104 result[run][x][y] = wrapop(op, lf, rv[run][x][y])
105
106 return result
107
108def sums(x, y):
109 if isinstance(x, (list, tuple)):
110 return map(lambda x, y: x + y, x, y)
111 else:
112 return x + y
113
114def alltrue(seq):
115 return reduce(lambda x, y: x and y, seq)
116
117def allfalse(seq):
118 return not reduce(lambda x, y: x or y, seq)
119
120def enumerate(seq):
121 return map(None, range(len(seq)), seq)
122
123def cmp(a, b):
124 if a < b:
125 return -1
126 elif a == b:
127 return 0
128 else:
129 return 1
130
131class Statistic(object):
132
133 def __init__(self, data):
134 self.__dict__.update(data.__dict__)
135 if not self.__dict__.has_key('value'):
136 self.__dict__['value'] = None
137 if not self.__dict__.has_key('bins'):
138 self.__dict__['bins'] = None
139 if not self.__dict__.has_key('ticks'):
140 self.__dict__['ticks'] = None
141 if 'vc' not in self.__dict__:
142 self.vc = {}
143
144 def __getattribute__(self, attr):
145 if attr == 'ticks':
146 if self.__dict__['ticks'] != globalTicks:
147 self.__dict__['value'] = None
148 self.__dict__['ticks'] = globalTicks
149 return self.__dict__['ticks']
150 if attr == 'value':
151 if self.__dict__['ticks'] != globalTicks:
152 if self.__dict__['ticks'] != None and \
153 len(self.__dict__['ticks']) == 1:
154 self.vc[self.__dict__['ticks'][0]] = self.__dict__['value']
155 self.__dict__['ticks'] = globalTicks
156 if len(globalTicks) == 1 and self.vc.has_key(globalTicks[0]):
157 self.__dict__['value'] = self.vc[globalTicks[0]]
158 else:
159 self.__dict__['value'] = None
160 if self.__dict__['value'] == None:
161 self.__dict__['value'] = self.getValue()
162 return self.__dict__['value']
163 else:
164 return super(Statistic, self).__getattribute__(attr)
165
166 def __setattr__(self, attr, value):
167 if attr == 'bins' or attr == 'ticks':
168 if attr == 'bins':
169 if value is not None:
170 value = source.getBin(value)
171 #elif attr == 'ticks' and type(value) is str:
172 # value = [ int(x) for x in value.split() ]
173
174 self.__dict__[attr] = value
175 self.__dict__['value'] = None
176 self.vc = {}
177 else:
178 super(Statistic, self).__setattr__(attr, value)
179
180 def getValue(self):
181 raise AttributeError, 'getValue() must be defined'
182
183 def zero(self):
184 return False
185
186 def __ne__(self, other):
187 return not (self == other)
188
189 def __str__(self):
190 return '%f' % (float(self))
191
192class FormulaStat(object):
193 def __add__(self, other):
194 f = FormulaStat()
195 f.value = binaryop(operator.add, self, other)
196 return f
197 def __sub__(self, other):
198 f = FormulaStat()
199 f.value = binaryop(operator.sub, self, other)
200 return f
201 def __mul__(self, other):
202 f = FormulaStat()
203 f.value = binaryop(operator.mul, self, other)
204 return f
205 def __truediv__(self, other):
206 f = FormulaStat()
207 f.value = binaryop(zerodiv, self, other)
208 return f
209 def __mod__(self, other):
210 f = FormulaStat()
211 f.value = binaryop(operator.mod, self, other)
212 return f
213 def __radd__(self, other):
214 f = FormulaStat()
215 f.value = binaryop(operator.add, other, self)
216 return f
217 def __rsub__(self, other):
218 f = FormulaStat()
219 f.value = binaryop(operator.sub, other, self)
220 return f
221 def __rmul__(self, other):
222 f = FormulaStat()
223 f.value = binaryop(operator.mul, other, self)
224 return f
225 def __rtruediv__(self, other):
226 f = FormulaStat()
227 f.value = binaryop(zerodiv, other, self)
228 return f
229 def __rmod__(self, other):
230 f = FormulaStat()
231 f.value = binaryop(operator.mod, other, self)
232 return f
233 def __neg__(self):
234 f = FormulaStat()
235 f.value = unaryop(operator.neg, self)
236 return f
237 def __getitem__(self, idx):
238 f = FormulaStat()
239 f.value = {}
240 for key in self.value.keys():
241 f.value[key] = {}
242 f.value[key][0] = {}
243 f.value[key][0][0] = self.value[key][idx][0]
244 return f
245
246 def __float__(self):
247 if isinstance(self.value, FormulaStat):
248 return float(self.value)
249 if not self.value.has_key(display_run):
250 return (1e300*1e300)
251 if len(self.value[display_run]) == 1:
252 return self.value[display_run][0][0]
253 else:
254 #print self.value[display_run]
255 return self.value[display_run][4][0]
256 #raise ValueError
257
258 def display(self):
259 import display
260 d = display.VectorDisplay()
261 d.flags = 0
262 d.precision = 1
263 d.name = 'formula'
264 d.desc = 'formula'
265 val = self.value[display_run]
266 d.value = [ val[x][0] for x in val.keys() ]
267 d.display()
268
269
270class Scalar(Statistic,FormulaStat):
271 def getValue(self):
272 return source.data(self, self.bins, self.ticks)
273
274 def display(self):
275 import display
276 p = display.Print()
277 p.name = self.name
278 p.desc = self.desc
279 p.value = float(self)
280 p.flags = self.flags
281 p.precision = self.precision
282 if display.all or (self.flags & flags.printable):
283 p.display()
284
285 def comparable(self, other):
286 return self.name == other.name
287
288 def __eq__(self, other):
289 return self.value == other.value
290
291 def __isub__(self, other):
292 self.value -= other.value
293 return self
294
295 def __iadd__(self, other):
296 self.value += other.value
297 return self
298
299 def __itruediv__(self, other):
300 if not other:
301 return self
302 self.value /= other
303 return self
304
305class Vector(Statistic,FormulaStat):
306 def getValue(self):
307 return source.data(self, self.bins, self.ticks);
308
309 def display(self):
310 import display
311 if not display.all and not (self.flags & flags.printable):
312 return
313
314 d = display.VectorDisplay()
315 d.__dict__.update(self.__dict__)
316 d.display()
317
318 def comparable(self, other):
319 return self.name == other.name and \
320 len(self.value) == len(other.value)
321
322 def __eq__(self, other):
323 if isinstance(self.value, (list, tuple)) != \
324 isinstance(other.value, (list, tuple)):
325 return False
326
327 if isinstance(self.value, (list, tuple)):
328 if len(self.value) != len(other.value):
329 return False
330 else:
331 for v1,v2 in zip(self.value, other.value):
332 if v1 != v2:
333 return False
334 return True
335 else:
336 return self.value == other.value
337
338 def __isub__(self, other):
339 self.value = binaryop(operator.sub, self.value, other.value)
340 return self
341
342 def __iadd__(self, other):
343 self.value = binaryop(operator.add, self.value, other.value)
344 return self
345
346 def __itruediv__(self, other):
347 if not other:
348 return self
349 if isinstance(self.value, (list, tuple)):
350 for i in xrange(len(self.value)):
351 self.value[i] /= other
352 else:
353 self.value /= other
354 return self
355
356class Formula(Vector):
357 def getValue(self):
358 formula = re.sub(':', '__', self.formula)
359 x = eval(formula, source.stattop)
360 return x.value
361
362 def comparable(self, other):
363 return self.name == other.name and \
364 compare(self.dist, other.dist)
365
366 def __eq__(self, other):
367 return self.value == other.value
368
369 def __isub__(self, other):
370 return self
371
372 def __iadd__(self, other):
373 return self
374
375 def __itruediv__(self, other):
376 if not other:
377 return self
378 return self
379
380class SimpleDist(object):
381 def __init__(self, sums, squares, samples):
382 self.sums = sums
383 self.squares = squares
384 self.samples = samples
385
386 def getValue(self):
387 return 0.0
388
389 def display(self, name, desc, flags, precision):
390 import display
391 p = display.Print()
392 p.flags = flags
393 p.precision = precision
394
395 if self.samples > 0:
396 p.name = name + ".mean"
397 p.value = self.sums / self.samples
398 p.display()
399
400 p.name = name + ".stdev"
401 if self.samples > 1:
402 var = (self.samples * self.squares - self.sums ** 2) \
403 / (self.samples * (self.samples - 1))
404 if var >= 0:
405 p.value = math.sqrt(var)
406 else:
407 p.value = 'NaN'
408 else:
409 p.value = 0.0
410 p.display()
411
412 p.name = name + ".samples"
413 p.value = self.samples
414 p.display()
415
416 def comparable(self, other):
417 return True
418
419 def __eq__(self, other):
420 return self.sums == other.sums and self.squares == other.squares and \
421 self.samples == other.samples
422
423 def __isub__(self, other):
424 self.sums -= other.sums
425 self.squares -= other.squares
426 self.samples -= other.samples
427 return self
428
429 def __iadd__(self, other):
430 self.sums += other.sums
431 self.squares += other.squares
432 self.samples += other.samples
433 return self
434
435 def __itruediv__(self, other):
436 if not other:
437 return self
438 self.sums /= other
439 self.squares /= other
440 self.samples /= other
441 return self
442
443class FullDist(SimpleDist):
444 def __init__(self, sums, squares, samples, minval, maxval,
445 under, vec, over, min, max, bsize, size):
446 self.sums = sums
447 self.squares = squares
448 self.samples = samples
449 self.minval = minval
450 self.maxval = maxval
451 self.under = under
452 self.vec = vec
453 self.over = over
454 self.min = min
455 self.max = max
456 self.bsize = bsize
457 self.size = size
458
459 def getValue(self):
460 return 0.0
461
462 def display(self, name, desc, flags, precision):
463 import display
464 p = display.Print()
465 p.flags = flags
466 p.precision = precision
467
468 p.name = name + '.min_val'
469 p.value = self.minval
470 p.display()
471
472 p.name = name + '.max_val'
473 p.value = self.maxval
474 p.display()
475
476 p.name = name + '.underflow'
477 p.value = self.under
478 p.display()
479
480 i = self.min
481 for val in self.vec[:-1]:
482 p.name = name + '[%d:%d]' % (i, i + self.bsize - 1)
483 p.value = val
484 p.display()
485 i += self.bsize
486
487 p.name = name + '[%d:%d]' % (i, self.max)
488 p.value = self.vec[-1]
489 p.display()
490
491
492 p.name = name + '.overflow'
493 p.value = self.over
494 p.display()
495
496 SimpleDist.display(self, name, desc, flags, precision)
497
498 def comparable(self, other):
499 return self.min == other.min and self.max == other.max and \
500 self.bsize == other.bsize and self.size == other.size
501
502 def __eq__(self, other):
503 return self.sums == other.sums and self.squares == other.squares and \
504 self.samples == other.samples
505
506 def __isub__(self, other):
507 self.sums -= other.sums
508 self.squares -= other.squares
509 self.samples -= other.samples
510
511 if other.samples:
512 self.minval = min(self.minval, other.minval)
513 self.maxval = max(self.maxval, other.maxval)
514 self.under -= under
515 self.vec = map(lambda x,y: x - y, self.vec, other.vec)
516 self.over -= over
517 return self
518
519 def __iadd__(self, other):
520 if not self.samples and other.samples:
521 self = other
522 return self
523
524 self.sums += other.sums
525 self.squares += other.squares
526 self.samples += other.samples
527
528 if other.samples:
529 self.minval = min(self.minval, other.minval)
530 self.maxval = max(self.maxval, other.maxval)
531 self.under += other.under
532 self.vec = map(lambda x,y: x + y, self.vec, other.vec)
533 self.over += other.over
534 return self
535
536 def __itruediv__(self, other):
537 if not other:
538 return self
539 self.sums /= other
540 self.squares /= other
541 self.samples /= other
542
543 if self.samples:
544 self.under /= other
545 for i in xrange(len(self.vec)):
546 self.vec[i] /= other
547 self.over /= other
548 return self
549
550class Dist(Statistic):
551 def getValue(self):
552 return 0.0
553
554 def display(self):
555 import display
556 if not display.all and not (self.flags & flags.printable):
557 return
558
559 self.dist.display(self.name, self.desc, self.flags, self.precision)
560
561 def comparable(self, other):
562 return self.name == other.name and \
563 self.dist.compareable(other.dist)
564
565 def __eq__(self, other):
566 return self.dist == other.dist
567
568 def __isub__(self, other):
569 self.dist -= other.dist
570 return self
571
572 def __iadd__(self, other):
573 self.dist += other.dist
574 return self
575
576 def __itruediv__(self, other):
577 if not other:
578 return self
579 self.dist /= other
580 return self
581
582class VectorDist(Statistic):
583 def getValue(self):
584 return 0.0
585
586 def display(self):
587 import display
588 if not display.all and not (self.flags & flags.printable):
589 return
590
591 if isinstance(self.dist, SimpleDist):
592 return
593
594 for dist,sn,sd,i in map(None, self.dist, self.subnames, self.subdescs,
595 range(len(self.dist))):
596 if len(sn) > 0:
597 name = '%s.%s' % (self.name, sn)
598 else:
599 name = '%s[%d]' % (self.name, i)
600
601 if len(sd) > 0:
602 desc = sd
603 else:
604 desc = self.desc
605
606 dist.display(name, desc, self.flags, self.precision)
607
608 if (self.flags & flags.total) or 1:
609 if isinstance(self.dist[0], SimpleDist):
610 disttotal = SimpleDist( \
611 reduce(sums, [d.sums for d in self.dist]),
612 reduce(sums, [d.squares for d in self.dist]),
613 reduce(sums, [d.samples for d in self.dist]))
614 else:
615 disttotal = FullDist( \
616 reduce(sums, [d.sums for d in self.dist]),
617 reduce(sums, [d.squares for d in self.dist]),
618 reduce(sums, [d.samples for d in self.dist]),
619 min([d.minval for d in self.dist]),
620 max([d.maxval for d in self.dist]),
621 reduce(sums, [d.under for d in self.dist]),
622 reduce(sums, [d.vec for d in self.dist]),
623 reduce(sums, [d.over for d in self.dist]),
624 dist[0].min,
625 dist[0].max,
626 dist[0].bsize,
627 dist[0].size)
628
629 name = '%s.total' % (self.name)
630 desc = self.desc
631 disttotal.display(name, desc, self.flags, self.precision)
632
633 def comparable(self, other):
634 return self.name == other.name and \
635 alltrue(map(lambda x, y : x.comparable(y),
636 self.dist,
637 other.dist))
638
639 def __eq__(self, other):
640 return alltrue(map(lambda x, y : x == y, self.dist, other.dist))
641
642 def __isub__(self, other):
643 if isinstance(self.dist, (list, tuple)) and \
644 isinstance(other.dist, (list, tuple)):
645 for sd,od in zip(self.dist, other.dist):
646 sd -= od
647 else:
648 self.dist -= other.dist
649 return self
650
651 def __iadd__(self, other):
652 if isinstance(self.dist, (list, tuple)) and \
653 isinstance(other.dist, (list, tuple)):
654 for sd,od in zip(self.dist, other.dist):
655 sd += od
656 else:
657 self.dist += other.dist
658 return self
659
660 def __itruediv__(self, other):
661 if not other:
662 return self
663 if isinstance(self.dist, (list, tuple)):
664 for dist in self.dist:
665 dist /= other
666 else:
667 self.dist /= other
668 return self
669
670class Vector2d(Statistic):
671 def getValue(self):
672 return 0.0
673
674 def display(self):
675 import display
676 if not display.all and not (self.flags & flags.printable):
677 return
678
679 d = display.VectorDisplay()
680 d.__dict__.update(self.__dict__)
681
682 if self.__dict__.has_key('ysubnames'):
683 ysubnames = list(self.ysubnames)
684 slack = self.x - len(ysubnames)
685 if slack > 0:
686 ysubnames.extend(['']*slack)
687 else:
688 ysubnames = range(self.x)
689
690 for x,sname in enumerate(ysubnames):
691 o = x * self.y
692 d.value = self.value[o:o+self.y]
693 d.name = '%s[%s]' % (self.name, sname)
694 d.display()
695
696 if self.flags & flags.total:
697 d.value = []
698 for y in range(self.y):
699 xtot = 0.0
700 for x in range(self.x):
701 xtot += self.value[y + x * self.x]
702 d.value.append(xtot)
703
704 d.name = self.name + '.total'
705 d.display()
706
707 def comparable(self, other):
708 return self.name == other.name and self.x == other.x and \
709 self.y == other.y
710
711 def __eq__(self, other):
712 return True
713
714 def __isub__(self, other):
715 return self
716
717 def __iadd__(self, other):
718 return self
719
720 def __itruediv__(self, other):
721 if not other:
722 return self
723 return self
724
725def NewStat(data):
726 stat = None
727 if data.type == 'SCALAR':
728 stat = Scalar(data)
729 elif data.type == 'VECTOR':
730 stat = Vector(data)
731 elif data.type == 'DIST':
732 stat = Dist(data)
733 elif data.type == 'VECTORDIST':
734 stat = VectorDist(data)
735 elif data.type == 'VECTOR2D':
736 stat = Vector2d(data)
737 elif data.type == 'FORMULA':
738 stat = Formula(data)
739
740 return stat
741