1 from __future__
import division
2 import operator
, re
, types
8 return isinstance(t
, types
.TupleType
) or isinstance(t
, types
.ListType
)
11 if isinstance(f
, FormulaStat
):
18 f
.value
= reduce(operator
.add
, v
)
25 if isinstance(f
, FormulaStat
):
39 return operator
.truediv(lv
, rv
)
41 def wrapop(op
, lv
, rv
):
42 if isinstance(lv
, str):
45 if isinstance(rv
, str):
51 for lrun
,rrun
in zip(lv
.keys(),rv
.keys()):
58 for lx
,rx
in zip(lv
[lrun
].keys(),rv
[rrun
].keys()):
65 for ly
,ry
in zip(lv
[lrun
][lx
].keys(),rv
[rrun
][rx
].keys()):
69 print lv
[lrun
][lx
].keys()
70 print rv
[rrun
][rx
].keys()
75 def binaryop(op
, lf
, rf
):
78 if isinstance(lf
, FormulaStat
) and isinstance(rf
, FormulaStat
):
83 raise AttributeError, "run,x,y not identical"
87 for x
in lv
[run
].keys():
89 for y
in lv
[run
][x
].keys():
90 result
[run
][x
][y
] = wrapop(op
, lv
[run
][x
][y
],
92 elif isinstance(lf
, FormulaStat
):
96 for x
in lv
[run
].keys():
98 for y
in lv
[run
][x
].keys():
99 result
[run
][x
][y
] = wrapop(op
, lv
[run
][x
][y
], rf
)
100 elif isinstance(rf
, FormulaStat
):
102 for run
in rv
.keys():
104 for x
in rv
[run
].keys():
106 for y
in rv
[run
][x
].keys():
107 result
[run
][x
][y
] = wrapop(op
, lf
, rv
[run
][x
][y
])
113 return map(lambda x
, y
: x
+ y
, x
, y
)
118 return reduce(lambda x
, y
: x
and y
, list)
121 return not reduce(lambda x
, y
: x
or y
, list)
124 return map(None, range(len(list)), list)
134 class Statistic(object):
135 def __init__(self
, data
):
136 self
.__dict
__.update(data
.__dict
__)
137 if not self
.__dict
__.has_key('value'):
138 self
.__dict
__['value'] = None
139 if not self
.__dict
__.has_key('bins'):
140 self
.__dict
__['bins'] = None
141 if not self
.__dict
__.has_key('ticks'):
142 self
.__dict
__['ticks'] = None
144 def __getattribute__(self
, attr
):
146 if self
.__dict
__['value'] == None:
147 self
.__dict
__['value'] = self
.getValue()
148 return self
.__dict
__['value']
150 return super(Statistic
, self
).__getattribute
__(attr
)
152 def __setattr__(self
, attr
, value
):
153 if attr
== 'bins' or attr
== 'ticks':
156 if value
is not None:
157 value
= db
.getBin(value
)
158 elif attr
== 'samples' and type(value
) is str:
159 value
= [ int(x
) for x
in value
.split() ]
161 self
.__dict
__[attr
] = value
162 self
.__dict
__['value'] = None
164 super(Statistic
, self
).__setattr
__(attr
, value
)
167 raise AttributeError, 'getValue() must be defined'
172 def __ne__(self
, other
):
173 return not (self
== other
)
176 return '%f' % (float(self
))
178 class FormulaStat(object):
179 def __add__(self
, other
):
181 f
.value
= binaryop(operator
.add
, self
, other
)
183 def __sub__(self
, other
):
185 f
.value
= binaryop(operator
.sub
, self
, other
)
187 def __mul__(self
, other
):
189 f
.value
= binaryop(operator
.mul
, self
, other
)
191 def __truediv__(self
, other
):
193 f
.value
= binaryop(zerodiv
, self
, other
)
195 def __mod__(self
, other
):
197 f
.value
= binaryop(operator
.mod
, self
, other
)
199 def __radd__(self
, other
):
201 f
.value
= binaryop(operator
.add
, other
, self
)
203 def __rsub__(self
, other
):
205 f
.value
= binaryop(operator
.sub
, other
, self
)
207 def __rmul__(self
, other
):
209 f
.value
= binaryop(operator
.mul
, other
, self
)
211 def __rtruediv__(self
, other
):
213 f
.value
= binaryop(zerodiv
, other
, self
)
215 def __rmod__(self
, other
):
217 f
.value
= binaryop(operator
.mod
, other
, self
)
221 f
.value
= unaryop(operator
.neg
, self
)
223 def __getitem__(self
, idx
):
226 for key
in self
.value
.keys():
229 f
.value
[key
][0][0] = self
.value
[key
][idx
][0]
233 if isinstance(self
.value
, FormulaStat
):
234 return float(self
.value
)
235 if not self
.value
.has_key(display_run
):
237 if len(self
.value
[display_run
]) == 1:
238 return self
.value
[display_run
][0][0]
240 #print self.value[display_run]
241 return self
.value
[display_run
][4][0]
246 d
= display
.VectorDisplay()
251 val
= self
.value
[display_run
]
252 d
.value
= [ val
[x
][0] for x
in val
.keys() ]
256 class Scalar(Statistic
,FormulaStat
):
258 return source
.data(self
, self
.bins
)
265 p
.value
= float(self
)
267 p
.precision
= self
.precision
268 if display
.all
or (self
.flags
& flags
.printable
):
271 def comparable(self
, other
):
272 return self
.name
== other
.name
274 def __eq__(self
, other
):
275 return self
.value
== other
.value
277 def __isub__(self
, other
):
278 self
.value
-= other
.value
281 def __iadd__(self
, other
):
282 self
.value
+= other
.value
285 def __itruediv__(self
, other
):
291 class Vector(Statistic
,FormulaStat
):
293 return source
.data(self
, self
.bins
);
297 if not display
.all
and not (self
.flags
& flags
.printable
):
300 d
= display
.VectorDisplay()
301 d
.__dict
__.update(self
.__dict
__)
304 def comparable(self
, other
):
305 return self
.name
== other
.name
and \
306 len(self
.value
) == len(other
.value
)
308 def __eq__(self
, other
):
309 if issequence(self
.value
) != issequence(other
.value
):
312 if issequence(self
.value
):
313 if len(self
.value
) != len(other
.value
):
316 for v1
,v2
in zip(self
.value
, other
.value
):
321 return self
.value
== other
.value
323 def __isub__(self
, other
):
324 self
.value
= binaryop(operator
.sub
, self
.value
, other
.value
)
327 def __iadd__(self
, other
):
328 self
.value
= binaryop(operator
.add
, self
.value
, other
.value
)
331 def __itruediv__(self
, other
):
334 if issequence(self
.value
):
335 for i
in xrange(len(self
.value
)):
336 self
.value
[i
] /= other
341 class Formula(Vector
):
343 formula
= re
.sub(':', '__', self
.formula
)
344 x
= eval(formula
, source
.stattop
)
347 def comparable(self
, other
):
348 return self
.name
== other
.name
and \
349 compare(self
.dist
, other
.dist
)
351 def __eq__(self
, other
):
352 return self
.value
== other
.value
354 def __isub__(self
, other
):
357 def __iadd__(self
, other
):
360 def __itruediv__(self
, other
):
365 class SimpleDist(object):
366 def __init__(self
, sums
, squares
, samples
):
368 self
.squares
= squares
369 self
.samples
= samples
374 def display(self
, name
, desc
, flags
, precision
):
378 p
.precision
= precision
381 p
.name
= name
+ ".mean"
382 p
.value
= self
.sums
/ self
.samples
385 p
.name
= name
+ ".stdev"
387 var
= (self
.samples
* self
.squares
- self
.sums
** 2) \
388 / (self
.samples
* (self
.samples
- 1))
390 p
.value
= math
.sqrt(var
)
397 p
.name
= name
+ ".samples"
398 p
.value
= self
.samples
401 def comparable(self
, other
):
404 def __eq__(self
, other
):
405 return self
.sums
== other
.sums
and self
.squares
== other
.squares
and \
406 self
.samples
== other
.samples
408 def __isub__(self
, other
):
409 self
.sums
-= other
.sums
410 self
.squares
-= other
.squares
411 self
.samples
-= other
.samples
414 def __iadd__(self
, other
):
415 self
.sums
+= other
.sums
416 self
.squares
+= other
.squares
417 self
.samples
+= other
.samples
420 def __itruediv__(self
, other
):
424 self
.squares
/= other
425 self
.samples
/= other
428 class FullDist(SimpleDist
):
429 def __init__(self
, sums
, squares
, samples
, minval
, maxval
,
430 under
, vec
, over
, min, max, bsize
, size
):
432 self
.squares
= squares
433 self
.samples
= samples
447 def display(self
, name
, desc
, flags
, precision
):
451 p
.precision
= precision
453 p
.name
= name
+ '.min_val'
454 p
.value
= self
.minval
457 p
.name
= name
+ '.max_val'
458 p
.value
= self
.maxval
461 p
.name
= name
+ '.underflow'
466 for val
in self
.vec
[:-1]:
467 p
.name
= name
+ '[%d:%d]' % (i
, i
+ self
.bsize
- 1)
472 p
.name
= name
+ '[%d:%d]' % (i
, self
.max)
473 p
.value
= self
.vec
[-1]
477 p
.name
= name
+ '.overflow'
481 SimpleDist
.display(self
, name
, desc
, flags
, precision
)
483 def comparable(self
, other
):
484 return self
.min == other
.min and self
.max == other
.max and \
485 self
.bsize
== other
.bsize
and self
.size
== other
.size
487 def __eq__(self
, other
):
488 return self
.sums
== other
.sums
and self
.squares
== other
.squares
and \
489 self
.samples
== other
.samples
491 def __isub__(self
, other
):
492 self
.sums
-= other
.sums
493 self
.squares
-= other
.squares
494 self
.samples
-= other
.samples
497 self
.minval
= min(self
.minval
, other
.minval
)
498 self
.maxval
= max(self
.maxval
, other
.maxval
)
500 self
.vec
= map(lambda x
,y
: x
- y
, self
.vec
, other
.vec
)
504 def __iadd__(self
, other
):
505 if not self
.samples
and other
.samples
:
509 self
.sums
+= other
.sums
510 self
.squares
+= other
.squares
511 self
.samples
+= other
.samples
514 self
.minval
= min(self
.minval
, other
.minval
)
515 self
.maxval
= max(self
.maxval
, other
.maxval
)
516 self
.under
+= other
.under
517 self
.vec
= map(lambda x
,y
: x
+ y
, self
.vec
, other
.vec
)
518 self
.over
+= other
.over
521 def __itruediv__(self
, other
):
525 self
.squares
/= other
526 self
.samples
/= other
530 for i
in xrange(len(self
.vec
)):
535 class Dist(Statistic
):
541 if not display
.all
and not (self
.flags
& flags
.printable
):
544 self
.dist
.display(self
.name
, self
.desc
, self
.flags
, self
.precision
)
546 def comparable(self
, other
):
547 return self
.name
== other
.name
and \
548 self
.dist
.compareable(other
.dist
)
550 def __eq__(self
, other
):
551 return self
.dist
== other
.dist
553 def __isub__(self
, other
):
554 self
.dist
-= other
.dist
557 def __iadd__(self
, other
):
558 self
.dist
+= other
.dist
561 def __itruediv__(self
, other
):
567 class VectorDist(Statistic
):
573 if not display
.all
and not (self
.flags
& flags
.printable
):
576 if isinstance(self
.dist
, SimpleDist
):
579 for dist
,sn
,sd
,i
in map(None, self
.dist
, self
.subnames
, self
.subdescs
,
580 range(len(self
.dist
))):
582 name
= '%s.%s' % (self
.name
, sn
)
584 name
= '%s[%d]' % (self
.name
, i
)
591 dist
.display(name
, desc
, self
.flags
, self
.precision
)
593 if (self
.flags
& flags
.total
) or 1:
594 if isinstance(self
.dist
[0], SimpleDist
):
595 disttotal
= SimpleDist( \
596 reduce(sums
, [d
.sums
for d
in self
.dist
]),
597 reduce(sums
, [d
.squares
for d
in self
.dist
]),
598 reduce(sums
, [d
.samples
for d
in self
.dist
]))
600 disttotal
= FullDist( \
601 reduce(sums
, [d
.sums
for d
in self
.dist
]),
602 reduce(sums
, [d
.squares
for d
in self
.dist
]),
603 reduce(sums
, [d
.samples
for d
in self
.dist
]),
604 min([d
.minval
for d
in self
.dist
]),
605 max([d
.maxval
for d
in self
.dist
]),
606 reduce(sums
, [d
.under
for d
in self
.dist
]),
607 reduce(sums
, [d
.vec
for d
in self
.dist
]),
608 reduce(sums
, [d
.over
for d
in self
.dist
]),
614 name
= '%s.total' % (self
.name
)
616 disttotal
.display(name
, desc
, self
.flags
, self
.precision
)
618 def comparable(self
, other
):
619 return self
.name
== other
.name
and \
620 alltrue(map(lambda x
, y
: x
.comparable(y
),
624 def __eq__(self
, other
):
625 return alltrue(map(lambda x
, y
: x
== y
, self
.dist
, other
.dist
))
627 def __isub__(self
, other
):
628 if issequence(self
.dist
) and issequence(other
.dist
):
629 for sd
,od
in zip(self
.dist
, other
.dist
):
632 self
.dist
-= other
.dist
635 def __iadd__(self
, other
):
636 if issequence(self
.dist
) and issequence(other
.dist
):
637 for sd
,od
in zip(self
.dist
, other
.dist
):
640 self
.dist
+= other
.dist
643 def __itruediv__(self
, other
):
646 if issequence(self
.dist
):
647 for dist
in self
.dist
:
653 class Vector2d(Statistic
):
659 if not display
.all
and not (self
.flags
& flags
.printable
):
662 d
= display
.VectorDisplay()
663 d
.__dict
__.update(self
.__dict
__)
665 if self
.__dict
__.has_key('ysubnames'):
666 ysubnames
= list(self
.ysubnames
)
667 slack
= self
.x
- len(ysubnames
)
669 ysubnames
.extend(['']*slack
)
671 ysubnames
= range(self
.x
)
673 for x
,sname
in enumerate(ysubnames
):
675 d
.value
= self
.value
[o
:o
+self
.y
]
676 d
.name
= '%s[%s]' % (self
.name
, sname
)
679 if self
.flags
& flags
.total
:
681 for y
in range(self
.y
):
683 for x
in range(self
.x
):
684 xtot
+= self
.value
[y
+ x
* self
.x
]
687 d
.name
= self
.name
+ '.total'
690 def comparable(self
, other
):
691 return self
.name
== other
.name
and self
.x
== other
.x
and \
694 def __eq__(self
, other
):
697 def __isub__(self
, other
):
700 def __iadd__(self
, other
):
703 def __itruediv__(self
, other
):
710 if data
.type == 'SCALAR':
712 elif data
.type == 'VECTOR':
714 elif data
.type == 'DIST':
716 elif data
.type == 'VECTORDIST':
717 stat
= VectorDist(data
)
718 elif data
.type == 'VECTOR2D':
719 stat
= Vector2d(data
)
720 elif data
.type == 'FORMULA':