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