1 from __future__
import division
2 import operator
, re
, types
10 return isinstance(t
, types
.TupleType
) or isinstance(t
, types
.ListType
)
13 if isinstance(f
, FormulaStat
):
20 f
.value
= reduce(operator
.add
, v
)
27 if isinstance(f
, FormulaStat
):
41 return operator
.truediv(lv
, rv
)
43 def wrapop(op
, lv
, rv
):
44 if isinstance(lv
, str):
47 if isinstance(rv
, str):
53 for lx
,rx
in zip(lrun
.keys(),rrun
.keys()):
60 for ly
,ry
in zip(lrun
[lx
].keys(),rrun
[rx
].keys()):
70 def binaryop(op
, lf
, rf
):
73 if isinstance(lf
, FormulaStat
) and isinstance(rf
, FormulaStat
):
80 if same(lv
[r
], rv
[r
]):
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):
136 def __init__(self
, data
):
137 self
.__dict
__.update(data
.__dict
__)
138 if not self
.__dict
__.has_key('value'):
139 self
.__dict
__['value'] = None
140 if not self
.__dict
__.has_key('bins'):
141 self
.__dict
__['bins'] = None
142 if not self
.__dict
__.has_key('ticks'):
143 self
.__dict
__['ticks'] = None
144 if 'vc' not in self
.__dict
__:
147 def __getattribute__(self
, attr
):
149 if self
.__dict
__['ticks'] != globalTicks
:
150 self
.__dict
__['value'] = None
151 self
.__dict
__['ticks'] = globalTicks
152 return self
.__dict
__['ticks']
154 if self
.__dict
__['ticks'] != globalTicks
:
155 if self
.__dict
__['ticks'] != None and \
156 len(self
.__dict
__['ticks']) == 1:
157 self
.vc
[self
.__dict
__['ticks'][0]] = self
.__dict
__['value']
158 self
.__dict
__['ticks'] = globalTicks
159 if len(globalTicks
) == 1 and self
.vc
.has_key(globalTicks
[0]):
160 self
.__dict
__['value'] = self
.vc
[globalTicks
[0]]
162 self
.__dict
__['value'] = None
163 if self
.__dict
__['value'] == None:
164 self
.__dict
__['value'] = self
.getValue()
165 return self
.__dict
__['value']
167 return super(Statistic
, self
).__getattribute
__(attr
)
169 def __setattr__(self
, attr
, value
):
170 if attr
== 'bins' or attr
== 'ticks':
172 if value
is not None:
173 value
= source
.getBin(value
)
174 #elif attr == 'ticks' and type(value) is str:
175 # value = [ int(x) for x in value.split() ]
177 self
.__dict
__[attr
] = value
178 self
.__dict
__['value'] = None
181 super(Statistic
, self
).__setattr
__(attr
, value
)
184 raise AttributeError, 'getValue() must be defined'
189 def __ne__(self
, other
):
190 return not (self
== other
)
193 return '%f' % (float(self
))
195 class FormulaStat(object):
196 def __add__(self
, other
):
198 f
.value
= binaryop(operator
.add
, self
, other
)
200 def __sub__(self
, other
):
202 f
.value
= binaryop(operator
.sub
, self
, other
)
204 def __mul__(self
, other
):
206 f
.value
= binaryop(operator
.mul
, self
, other
)
208 def __truediv__(self
, other
):
210 f
.value
= binaryop(zerodiv
, self
, other
)
212 def __mod__(self
, other
):
214 f
.value
= binaryop(operator
.mod
, self
, other
)
216 def __radd__(self
, other
):
218 f
.value
= binaryop(operator
.add
, other
, self
)
220 def __rsub__(self
, other
):
222 f
.value
= binaryop(operator
.sub
, other
, self
)
224 def __rmul__(self
, other
):
226 f
.value
= binaryop(operator
.mul
, other
, self
)
228 def __rtruediv__(self
, other
):
230 f
.value
= binaryop(zerodiv
, other
, self
)
232 def __rmod__(self
, other
):
234 f
.value
= binaryop(operator
.mod
, other
, self
)
238 f
.value
= unaryop(operator
.neg
, self
)
240 def __getitem__(self
, idx
):
243 for key
in self
.value
.keys():
246 f
.value
[key
][0][0] = self
.value
[key
][idx
][0]
250 if isinstance(self
.value
, FormulaStat
):
251 return float(self
.value
)
252 if not self
.value
.has_key(display_run
):
254 if len(self
.value
[display_run
]) == 1:
255 return self
.value
[display_run
][0][0]
257 #print self.value[display_run]
258 return self
.value
[display_run
][4][0]
263 d
= display
.VectorDisplay()
268 val
= self
.value
[display_run
]
269 d
.value
= [ val
[x
][0] for x
in val
.keys() ]
273 class Scalar(Statistic
,FormulaStat
):
275 return source
.data(self
, self
.bins
, self
.ticks
)
282 p
.value
= float(self
)
284 p
.precision
= self
.precision
285 if display
.all
or (self
.flags
& flags
.printable
):
288 def comparable(self
, other
):
289 return self
.name
== other
.name
291 def __eq__(self
, other
):
292 return self
.value
== other
.value
294 def __isub__(self
, other
):
295 self
.value
-= other
.value
298 def __iadd__(self
, other
):
299 self
.value
+= other
.value
302 def __itruediv__(self
, other
):
308 class Vector(Statistic
,FormulaStat
):
310 return source
.data(self
, self
.bins
);
314 if not display
.all
and not (self
.flags
& flags
.printable
):
317 d
= display
.VectorDisplay()
318 d
.__dict
__.update(self
.__dict
__)
321 def comparable(self
, other
):
322 return self
.name
== other
.name
and \
323 len(self
.value
) == len(other
.value
)
325 def __eq__(self
, other
):
326 if issequence(self
.value
) != issequence(other
.value
):
329 if issequence(self
.value
):
330 if len(self
.value
) != len(other
.value
):
333 for v1
,v2
in zip(self
.value
, other
.value
):
338 return self
.value
== other
.value
340 def __isub__(self
, other
):
341 self
.value
= binaryop(operator
.sub
, self
.value
, other
.value
)
344 def __iadd__(self
, other
):
345 self
.value
= binaryop(operator
.add
, self
.value
, other
.value
)
348 def __itruediv__(self
, other
):
351 if issequence(self
.value
):
352 for i
in xrange(len(self
.value
)):
353 self
.value
[i
] /= other
358 class Formula(Vector
):
360 formula
= re
.sub(':', '__', self
.formula
)
361 x
= eval(formula
, source
.stattop
)
364 def comparable(self
, other
):
365 return self
.name
== other
.name
and \
366 compare(self
.dist
, other
.dist
)
368 def __eq__(self
, other
):
369 return self
.value
== other
.value
371 def __isub__(self
, other
):
374 def __iadd__(self
, other
):
377 def __itruediv__(self
, other
):
382 class SimpleDist(object):
383 def __init__(self
, sums
, squares
, samples
):
385 self
.squares
= squares
386 self
.samples
= samples
391 def display(self
, name
, desc
, flags
, precision
):
395 p
.precision
= precision
398 p
.name
= name
+ ".mean"
399 p
.value
= self
.sums
/ self
.samples
402 p
.name
= name
+ ".stdev"
404 var
= (self
.samples
* self
.squares
- self
.sums
** 2) \
405 / (self
.samples
* (self
.samples
- 1))
407 p
.value
= math
.sqrt(var
)
414 p
.name
= name
+ ".samples"
415 p
.value
= self
.samples
418 def comparable(self
, other
):
421 def __eq__(self
, other
):
422 return self
.sums
== other
.sums
and self
.squares
== other
.squares
and \
423 self
.samples
== other
.samples
425 def __isub__(self
, other
):
426 self
.sums
-= other
.sums
427 self
.squares
-= other
.squares
428 self
.samples
-= other
.samples
431 def __iadd__(self
, other
):
432 self
.sums
+= other
.sums
433 self
.squares
+= other
.squares
434 self
.samples
+= other
.samples
437 def __itruediv__(self
, other
):
441 self
.squares
/= other
442 self
.samples
/= other
445 class FullDist(SimpleDist
):
446 def __init__(self
, sums
, squares
, samples
, minval
, maxval
,
447 under
, vec
, over
, min, max, bsize
, size
):
449 self
.squares
= squares
450 self
.samples
= samples
464 def display(self
, name
, desc
, flags
, precision
):
468 p
.precision
= precision
470 p
.name
= name
+ '.min_val'
471 p
.value
= self
.minval
474 p
.name
= name
+ '.max_val'
475 p
.value
= self
.maxval
478 p
.name
= name
+ '.underflow'
483 for val
in self
.vec
[:-1]:
484 p
.name
= name
+ '[%d:%d]' % (i
, i
+ self
.bsize
- 1)
489 p
.name
= name
+ '[%d:%d]' % (i
, self
.max)
490 p
.value
= self
.vec
[-1]
494 p
.name
= name
+ '.overflow'
498 SimpleDist
.display(self
, name
, desc
, flags
, precision
)
500 def comparable(self
, other
):
501 return self
.min == other
.min and self
.max == other
.max and \
502 self
.bsize
== other
.bsize
and self
.size
== other
.size
504 def __eq__(self
, other
):
505 return self
.sums
== other
.sums
and self
.squares
== other
.squares
and \
506 self
.samples
== other
.samples
508 def __isub__(self
, other
):
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
)
517 self
.vec
= map(lambda x
,y
: x
- y
, self
.vec
, other
.vec
)
521 def __iadd__(self
, other
):
522 if not self
.samples
and other
.samples
:
526 self
.sums
+= other
.sums
527 self
.squares
+= other
.squares
528 self
.samples
+= other
.samples
531 self
.minval
= min(self
.minval
, other
.minval
)
532 self
.maxval
= max(self
.maxval
, other
.maxval
)
533 self
.under
+= other
.under
534 self
.vec
= map(lambda x
,y
: x
+ y
, self
.vec
, other
.vec
)
535 self
.over
+= other
.over
538 def __itruediv__(self
, other
):
542 self
.squares
/= other
543 self
.samples
/= other
547 for i
in xrange(len(self
.vec
)):
552 class Dist(Statistic
):
558 if not display
.all
and not (self
.flags
& flags
.printable
):
561 self
.dist
.display(self
.name
, self
.desc
, self
.flags
, self
.precision
)
563 def comparable(self
, other
):
564 return self
.name
== other
.name
and \
565 self
.dist
.compareable(other
.dist
)
567 def __eq__(self
, other
):
568 return self
.dist
== other
.dist
570 def __isub__(self
, other
):
571 self
.dist
-= other
.dist
574 def __iadd__(self
, other
):
575 self
.dist
+= other
.dist
578 def __itruediv__(self
, other
):
584 class VectorDist(Statistic
):
590 if not display
.all
and not (self
.flags
& flags
.printable
):
593 if isinstance(self
.dist
, SimpleDist
):
596 for dist
,sn
,sd
,i
in map(None, self
.dist
, self
.subnames
, self
.subdescs
,
597 range(len(self
.dist
))):
599 name
= '%s.%s' % (self
.name
, sn
)
601 name
= '%s[%d]' % (self
.name
, i
)
608 dist
.display(name
, desc
, self
.flags
, self
.precision
)
610 if (self
.flags
& flags
.total
) or 1:
611 if isinstance(self
.dist
[0], SimpleDist
):
612 disttotal
= SimpleDist( \
613 reduce(sums
, [d
.sums
for d
in self
.dist
]),
614 reduce(sums
, [d
.squares
for d
in self
.dist
]),
615 reduce(sums
, [d
.samples
for d
in self
.dist
]))
617 disttotal
= FullDist( \
618 reduce(sums
, [d
.sums
for d
in self
.dist
]),
619 reduce(sums
, [d
.squares
for d
in self
.dist
]),
620 reduce(sums
, [d
.samples
for d
in self
.dist
]),
621 min([d
.minval
for d
in self
.dist
]),
622 max([d
.maxval
for d
in self
.dist
]),
623 reduce(sums
, [d
.under
for d
in self
.dist
]),
624 reduce(sums
, [d
.vec
for d
in self
.dist
]),
625 reduce(sums
, [d
.over
for d
in self
.dist
]),
631 name
= '%s.total' % (self
.name
)
633 disttotal
.display(name
, desc
, self
.flags
, self
.precision
)
635 def comparable(self
, other
):
636 return self
.name
== other
.name
and \
637 alltrue(map(lambda x
, y
: x
.comparable(y
),
641 def __eq__(self
, other
):
642 return alltrue(map(lambda x
, y
: x
== y
, self
.dist
, other
.dist
))
644 def __isub__(self
, other
):
645 if issequence(self
.dist
) and issequence(other
.dist
):
646 for sd
,od
in zip(self
.dist
, other
.dist
):
649 self
.dist
-= other
.dist
652 def __iadd__(self
, other
):
653 if issequence(self
.dist
) and issequence(other
.dist
):
654 for sd
,od
in zip(self
.dist
, other
.dist
):
657 self
.dist
+= other
.dist
660 def __itruediv__(self
, other
):
663 if issequence(self
.dist
):
664 for dist
in self
.dist
:
670 class Vector2d(Statistic
):
676 if not display
.all
and not (self
.flags
& flags
.printable
):
679 d
= display
.VectorDisplay()
680 d
.__dict
__.update(self
.__dict
__)
682 if self
.__dict
__.has_key('ysubnames'):
683 ysubnames
= list(self
.ysubnames
)
684 slack
= self
.x
- len(ysubnames
)
686 ysubnames
.extend(['']*slack
)
688 ysubnames
= range(self
.x
)
690 for x
,sname
in enumerate(ysubnames
):
692 d
.value
= self
.value
[o
:o
+self
.y
]
693 d
.name
= '%s[%s]' % (self
.name
, sname
)
696 if self
.flags
& flags
.total
:
698 for y
in range(self
.y
):
700 for x
in range(self
.x
):
701 xtot
+= self
.value
[y
+ x
* self
.x
]
704 d
.name
= self
.name
+ '.total'
707 def comparable(self
, other
):
708 return self
.name
== other
.name
and self
.x
== other
.x
and \
711 def __eq__(self
, other
):
714 def __isub__(self
, other
):
717 def __iadd__(self
, other
):
720 def __itruediv__(self
, other
):
727 if data
.type == 'SCALAR':
729 elif data
.type == 'VECTOR':
731 elif data
.type == 'DIST':
733 elif data
.type == 'VECTORDIST':
734 stat
= VectorDist(data
)
735 elif data
.type == 'VECTOR2D':
736 stat
= Vector2d(data
)
737 elif data
.type == 'FORMULA':