Package PyFoam :: Package Applications :: Module SamplePlot
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.Applications.SamplePlot

  1  #  ICE Revision: $Id$ 
  2  """ 
  3  Application class that implements pyFoamSamplePlot.py 
  4  """ 
  5   
  6  import sys,string 
  7  from os import path 
  8  from optparse import OptionGroup 
  9   
 10  from .PyFoamApplication import PyFoamApplication 
 11  from PyFoam.RunDictionary.SampleDirectory import SampleDirectory 
 12  from PyFoam.Basics.SpreadsheetData import WrongDataSize 
 13   
 14  from PyFoam.Error import error,warning 
 15   
 16  from .PlotHelpers import cleanFilename 
 17   
 18  from PyFoam.ThirdParty.six import print_ 
 19   
20 -class SamplePlot(PyFoamApplication):
21 - def __init__(self,args=None):
22 description="""\ 23 Reads data from the sample-dictionary and generates appropriate 24 gnuplot-commands. As an option the data can be written to a CSV-file. 25 """ 26 27 PyFoamApplication.__init__(self, 28 args=args, 29 description=description, 30 usage="%prog [options] <casedir>", 31 nr=1, 32 changeVersion=False, 33 interspersed=True)
34 35 modeChoices=["separate","timesInOne","fieldsInOne","linesInOne","complete"] 36
37 - def addOptions(self):
38 data=OptionGroup(self.parser, 39 "Data", 40 "Select the data to plot") 41 self.parser.add_option_group(data) 42 43 data.add_option("--line", 44 action="append", 45 default=None, 46 dest="line", 47 help="Thesample line from which data is plotted (can be used more than once)") 48 data.add_option("--field", 49 action="append", 50 default=None, 51 dest="field", 52 help="The fields that are plotted (can be used more than once). If none are specified all found fields are used") 53 data.add_option("--postfix-for-field-names", 54 action="append", 55 default=[], 56 dest="fieldPostfix", 57 help="Possible postfix for field names of the form 'name_postfix'. Note that this should not be a possible field name") 58 data.add_option("--prefix-for-field-names", 59 action="append", 60 default=[], 61 dest="fieldPrefix", 62 help="Possible prefix for field names of the form 'prefix_name'. Note that this should not be a possible field name") 63 data.add_option("--directory-name", 64 action="store", 65 default="samples", 66 dest="dirName", 67 help="Alternate name for the directory with the samples (Default: %default)") 68 data.add_option("--preferred-component", 69 action="store", 70 type="int", 71 default=None, 72 dest="component", 73 help="The component that should be used for vectors. Otherwise the absolute value is used") 74 data.add_option("--reference-directory", 75 action="store", 76 default=None, 77 dest="reference", 78 help="A reference directory. If fitting sample data is found there it is plotted alongside the regular data") 79 data.add_option("--reference-case", 80 action="store", 81 default=None, 82 dest="referenceCase", 83 help="A reference case where a directory with the same name is looked for. Mutual exclusive with --reference-directory") 84 85 scale=OptionGroup(self.parser, 86 "Scale", 87 "Scale the data before comparing (not used during plotting)") 88 self.parser.add_option_group(scale) 89 scale.add_option("--scale-data", 90 action="store", 91 type="float", 92 default=1, 93 dest="scaleData", 94 help="Scale the data by this factor. Default: %default") 95 scale.add_option("--offset-data", 96 action="store", 97 type="float", 98 default=0, 99 dest="offsetData", 100 help="Offset the data by this factor. Default: %default") 101 scale.add_option("--scale-x-axis", 102 action="store", 103 type="float", 104 default=1, 105 dest="scaleXAxis", 106 help="Scale the x-axis by this factor. Default: %default") 107 scale.add_option("--offset-x-axis", 108 action="store", 109 type="float", 110 default=0, 111 dest="offsetXAxis", 112 help="Offset the x-axis by this factor. Default: %default") 113 114 scale.add_option("--scale-reference-data", 115 action="store", 116 type="float", 117 default=1, 118 dest="scaleReferenceData", 119 help="Scale the reference data by this factor. Default: %default") 120 scale.add_option("--offset-reference-data", 121 action="store", 122 type="float", 123 default=0, 124 dest="offsetReferenceData", 125 help="Offset the reference data by this factor. Default: %default") 126 scale.add_option("--scale-reference-x-axis", 127 action="store", 128 type="float", 129 default=1, 130 dest="scaleReferenceXAxis", 131 help="Scale the reference x-axis by this factor. Default: %default") 132 scale.add_option("--offset-reference-x-axis", 133 action="store", 134 type="float", 135 default=0, 136 dest="offsetReferenceXAxis", 137 help="Offset the reference x-axis by this factor. Default: %default") 138 139 time=OptionGroup(self.parser, 140 "Time", 141 "Select the times to plot") 142 self.parser.add_option_group(time) 143 144 time.add_option("--time", 145 action="append", 146 default=None, 147 dest="time", 148 help="The times that are plotted (can be used more than once). If none are specified all found times are used") 149 time.add_option("--min-time", 150 action="store", 151 type="float", 152 default=None, 153 dest="minTime", 154 help="The smallest time that should be used") 155 time.add_option("--max-time", 156 action="store", 157 type="float", 158 default=None, 159 dest="maxTime", 160 help="The biggest time that should be used") 161 time.add_option("--fuzzy-time", 162 action="store_true", 163 default=False, 164 dest="fuzzyTime", 165 help="Try to find the next timestep if the time doesn't match exactly") 166 time.add_option("--latest-time", 167 action="store_true", 168 default=False, 169 dest="latestTime", 170 help="Take the latest time from the data") 171 time.add_option("--reference-time", 172 action="store", 173 default=None, 174 dest="referenceTime", 175 help="Take this time from the reference data (instead of using the same time as the regular data)") 176 time.add_option("--tolerant-reference-time", 177 action="store_true", 178 default=False, 179 dest="tolerantReferenceTime", 180 help="Take the reference-time that is nearest to the selected time") 181 182 output=OptionGroup(self.parser, 183 "Appearance", 184 "How it should be plotted") 185 self.parser.add_option_group(output) 186 187 output.add_option("--mode", 188 type="choice", 189 default="separate", 190 dest="mode", 191 action="store", 192 choices=self.modeChoices, 193 help="What kind of plots are generated: a) separate for every time, line and field b) all times of a field in one plot c) all fields of a time in one plot d) all lines in one plot e) everything in one plot (Names: "+string.join(self.modeChoices,", ")+") Default: %default") 194 output.add_option("--unscaled", 195 action="store_false", 196 dest="scaled", 197 default=True, 198 help="Don't scale a value to the same range for all plots") 199 output.add_option("--scale-all", 200 action="store_true", 201 dest="scaleAll", 202 default=False, 203 help="Use the same scale for all fields (else use one scale for each field)") 204 output.add_option("--gnuplot-file", 205 action="store", 206 dest="gnuplotFile", 207 default=None, 208 help="Write the necessary gnuplot commands to this file. Else they are written to the standard output") 209 output.add_option("--picture-destination", 210 action="store", 211 dest="pictureDest", 212 default=None, 213 help="Directory the pictures should be stored to") 214 output.add_option("--name-prefix", 215 action="store", 216 dest="namePrefix", 217 default=None, 218 help="Prefix to the picture-name") 219 output.add_option("--csv-file", 220 action="store", 221 dest="csvFile", 222 default=None, 223 help="Write the data to a CSV-file instead of the gnuplot-commands") 224 225 data.add_option("--info", 226 action="store_true", 227 dest="info", 228 default=False, 229 help="Print info about the sampled data and exit") 230 output.add_option("--style", 231 action="store", 232 default="lines", 233 dest="style", 234 help="Gnuplot-style for the data (Default: %default)") 235 output.add_option("--clean-filename", 236 action="store_true", 237 dest="cleanFilename", 238 default=False, 239 help="Clean filenames so that they can be used in HTML or Latex-documents") 240 output.add_option("--reference-prefix", 241 action="store", 242 dest="refprefix", 243 default="Reference", 244 help="Prefix that gets added to the reference lines. Default: %default") 245 output.add_option("--resample-reference", 246 action="store_true", 247 dest="resampleReference", 248 default=False, 249 help="Resample the reference value to the current x-axis (for CSV-output)") 250 output.add_option("--extend-data", 251 action="store_true", 252 dest="extendData", 253 default=False, 254 help="Extend the data range if it differs (for CSV-files)") 255 output.add_option("--silent", 256 action="store_true", 257 dest="silent", 258 default=False, 259 help="Don't write to screen (with the silent and the compare-options)") 260 261 numerics=OptionGroup(self.parser, 262 "Quantify", 263 "Metrics of the data and numerical comparisons") 264 self.parser.add_option_group(numerics) 265 numerics.add_option("--metrics", 266 action="store_true", 267 dest="metrics", 268 default=None, 269 help="Print the metrics of the data sets") 270 numerics.add_option("--compare", 271 action="store_true", 272 dest="compare", 273 default=None, 274 help="Compare all data sets that are also in the reference data") 275 numerics.add_option("--common-range-compare", 276 action="store_true", 277 dest="commonRange", 278 default=None, 279 help="When comparing two datasets only use the common time range") 280 numerics.add_option("--index-tolerant-compare", 281 action="store_true", 282 dest="indexTolerant", 283 default=None, 284 help="Compare two data sets even if they have different indizes") 285 numerics.add_option("--use-reference-for-comparison", 286 action="store_false", 287 dest="compareOnOriginal", 288 default=True, 289 help="Use the reference-data as the basis for the numerical comparison. Otherwise the original data will be used")
290
291 - def run(self):
292 # remove trailing slashif present 293 if self.opts.dirName[-1]==path.sep: 294 self.opts.dirName=self.opts.dirName[:-1] 295 296 usedDirName=self.opts.dirName.replace("/","_") 297 298 samples=SampleDirectory(self.parser.getArgs()[0], 299 dirName=self.opts.dirName, 300 postfixes=self.opts.fieldPostfix, 301 prefixes=self.opts.fieldPrefix) 302 reference=None 303 if self.opts.reference and self.opts.referenceCase: 304 self.error("Options --reference-directory and --reference-case are mutual exclusive") 305 if self.opts.csvFile and (self.opts.compare or self.opts.metrics): 306 self.error("Options --csv-file and --compare/--metrics are mutual exclusive") 307 308 if self.opts.reference: 309 reference=SampleDirectory(self.parser.getArgs()[0], 310 dirName=self.opts.reference, 311 postfixes=self.opts.fieldPostfix, 312 prefixes=self.opts.fieldPrefix) 313 elif self.opts.referenceCase: 314 reference=SampleDirectory(self.opts.referenceCase, 315 dirName=self.opts.dirName, 316 postfixes=self.opts.fieldPostfix, 317 prefixes=self.opts.fieldPrefix) 318 319 if reference: 320 if path.samefile(reference.dir,samples.dir): 321 self.error("Used sample directory",samples.dir, 322 "and reference directory",reference.dir, 323 "are the same") 324 325 lines=samples.lines() 326 times=samples.times 327 328 if self.opts.info: 329 if not self.opts.silent: 330 print_("Times : ",samples.times) 331 print_("Lines : ",samples.lines()) 332 print_("Fields: ",list(samples.values())) 333 334 self.setData({'times' : samples.times, 335 'lines' : samples.lines(), 336 'values' : list(samples.values())}) 337 338 if reference: 339 if not self.opts.silent: 340 print_("\nReference Data:") 341 print_("Times : ",reference.times) 342 print_("Lines : ",reference.lines()) 343 print_("Fields: ",list(reference.values())) 344 self.setData({'reference':{'times' : samples.times, 345 'lines' : samples.lines(), 346 'values' : list(samples.values())}}) 347 348 return 0 349 350 if self.opts.line==None: 351 # error("At least one line has to be specified. Found were",samples.lines()) 352 self.opts.line=lines 353 else: 354 for l in self.opts.line: 355 if l not in lines: 356 error("The line",l,"does not exist in",lines) 357 358 if self.opts.latestTime: 359 if self.opts.time: 360 self.opts.time.append(samples.times[-1]) 361 else: 362 self.opts.time=[samples.times[-1]] 363 364 if self.opts.maxTime or self.opts.minTime: 365 if self.opts.time: 366 error("Times",self.opts.time,"and range [",self.opts.minTime,",",self.opts.maxTime,"] set: contradiction") 367 self.opts.time=[] 368 if self.opts.maxTime==None: 369 self.opts.maxTime= 1e20 370 if self.opts.minTime==None: 371 self.opts.minTime=-1e20 372 373 for t in times: 374 if float(t)<=self.opts.maxTime and float(t)>=self.opts.minTime: 375 self.opts.time.append(t) 376 377 if len(self.opts.time)==0: 378 error("No times in range [",self.opts.minTime,",",self.opts.maxTime,"] found: ",times) 379 elif self.opts.time: 380 iTimes=self.opts.time 381 self.opts.time=[] 382 for t in iTimes: 383 if t in samples.times: 384 self.opts.time.append(t) 385 elif self.opts.fuzzyTime: 386 tf=float(t) 387 use=None 388 dist=1e20 389 for ts in samples.times: 390 if abs(tf-float(ts))<dist: 391 use=ts 392 dist=abs(tf-float(ts)) 393 if use and use not in self.opts.time: 394 self.opts.time.append(use) 395 else: 396 pass 397 # self.warning("Time",t,"not found in the sample-times. Use option --fuzzy") 398 if self.opts.tolerantReferenceTime: 399 if self.opts.referenceTime: 400 self.error("--tolerant-reference-time and --reference-time can't be used at the same time") 401 refTimes={} 402 for t in self.opts.time: 403 dist=1e20 404 for rt in reference.times: 405 if abs(float(t)-float(rt))<dist: 406 refTimes[t]=rt 407 dist=abs(float(t)-float(rt)) 408 409 plots=[] 410 oPlots=[] 411 rPlots=[] 412 413 if self.opts.mode=="separate": 414 if self.opts.time==None: 415 self.opts.time=samples.times 416 if self.opts.field==None: 417 self.opts.field=list(samples.values()) 418 if self.opts.line==None: 419 self.opts.line=samples.lines() 420 for t in self.opts.time: 421 for f in self.opts.field: 422 for l in self.opts.line: 423 plot=samples.getData(line=[l], 424 value=[f], 425 time=[t], 426 scale=(self.opts.scaleXAxis, 427 self.opts.scaleData), 428 offset=(self.opts.offsetXAxis, 429 self.opts.offsetData)) 430 oPlots.append(plot[:]) 431 if reference: 432 rT=[t] 433 if self.opts.referenceTime: 434 rT=[self.opts.referenceTime] 435 elif self.opts.tolerantReferenceTime: 436 rT=[refTimes[t]] 437 p=reference.getData(line=[l], 438 value=[f], 439 time=rT, 440 note=self.opts.refprefix+" ", 441 scale=(self.opts.scaleReferenceXAxis, 442 self.opts.scaleReferenceData), 443 offset=(self.opts.offsetReferenceXAxis, 444 self.opts.offsetReferenceData)) 445 rPlots.append(p) 446 plot+=p 447 plots.append(plot) 448 449 elif self.opts.mode=="timesInOne": 450 if self.opts.field==None: 451 self.opts.field=list(samples.values()) 452 if self.opts.line==None: 453 self.opts.line=samples.lines() 454 for f in self.opts.field: 455 for l in self.opts.line: 456 plot=samples.getData(line=[l], 457 value=[f], 458 time=self.opts.time) 459 oPlots.append(plot[:]) 460 461 if reference: 462 rT=self.opts.time 463 if self.opts.referenceTime: 464 rT=[self.opts.referenceTime] 465 elif self.opts.tolerantReferenceTime: 466 rT=[refTimes[t]] 467 p=reference.getData(line=[l], 468 value=[f], 469 time=rT, 470 note=self.opts.refprefix+" ") 471 rPlots.append(p) 472 plot+=p 473 474 plots.append(plot) 475 476 elif self.opts.mode=="fieldsInOne": 477 if self.opts.scaled and not self.opts.scaleAll: 478 warning("In mode '",self.opts.mode,"' all fields are scaled to the same value") 479 self.opts.scaleAll=True 480 481 if self.opts.time==None: 482 self.opts.time=samples.times 483 if self.opts.line==None: 484 self.opts.line=samples.lines() 485 for t in self.opts.time: 486 for l in self.opts.line: 487 plot=samples.getData(line=[l], 488 value=self.opts.field, 489 time=[t]) 490 oPlots.append(plot[:]) 491 if reference: 492 rT=t 493 if self.opts.referenceTime: 494 rT=self.opts.referenceTime 495 elif self.opts.tolerantReferenceTime: 496 rT=refTimes[t] 497 p=reference.getData(line=[l], 498 value=self.opts.field, 499 time=[rT], 500 note=self.opts.refprefix+" ") 501 rPlots.append(p) 502 plot+=p 503 504 plots.append(plot) 505 506 elif self.opts.mode=="linesInOne": 507 if self.opts.field==None: 508 self.opts.field=list(samples.values()) 509 if self.opts.time==None: 510 self.opts.time=samples.times 511 for f in self.opts.field: 512 for t in self.opts.time: 513 plot=samples.getData(line=self.opts.line, 514 value=[f], 515 time=[t]) 516 oPlots.append(plot[:]) 517 518 if reference: 519 rT=t 520 if self.opts.referenceTime: 521 rT=self.opts.referenceTime 522 elif self.opts.tolerantReferenceTime: 523 rT=refTimes[t] 524 p=reference.getData(line=self.opts.line, 525 value=[f], 526 time=[rT], 527 note=self.opts.refprefix+" ") 528 rPlots.append(p) 529 plot+=p 530 531 plots.append(plot) 532 533 elif self.opts.mode=="complete": 534 if self.opts.scaled and not self.opts.scaleAll: 535 warning("In mode '",self.opts.mode,"' all fields are scaled to the same value") 536 self.opts.scaleAll=True 537 538 plot=samples.getData(line=self.opts.line, 539 value=self.opts.field, 540 time=self.opts.time) 541 oPlots.append(plot[:]) 542 if reference: 543 rT=self.opts.time 544 if self.opts.referenceTime: 545 rT=[self.opts.referenceTime] 546 elif self.opts.tolerantReferenceTime: 547 rT=[refTimes[t]] 548 p=reference.getData(line=self.opts.line, 549 value=self.opts.field, 550 time=rT, 551 note=self.opts.refprefix+" ") 552 plot+=p 553 rPlots.append(p) 554 555 plots.append(plot) 556 557 if self.opts.scaled: 558 if self.opts.scaleAll: 559 vRange=None 560 else: 561 vRanges={} 562 563 for p in plots: 564 for d in p: 565 mi,ma=d.range(component=self.opts.component) 566 nm=d.name 567 if not self.opts.scaleAll: 568 if nm in vRanges: 569 vRange=vRanges[nm] 570 else: 571 vRange=None 572 573 if vRange==None: 574 vRange=mi,ma 575 else: 576 vRange=min(vRange[0],mi),max(vRange[1],ma) 577 if not self.opts.scaleAll: 578 vRanges[nm]=vRange 579 580 result="set term png\n" 581 582 plots=[p for p in plots if len(p)>0] 583 584 if len(plots)<1: 585 self.error("No plots produced. Nothing done") 586 587 for p in plots: 588 if len(p)<1: 589 continue 590 591 name="" 592 593 if self.opts.namePrefix: 594 name+=self.opts.namePrefix+"_" 595 name+=usedDirName 596 title=None 597 tIndex=times.index(p[0].time()) 598 599 # name+="_"+string.join(self.opts.line,"_") 600 601 if self.opts.mode=="separate": 602 name+="_%s" % (p[0].line()) 603 name+="_%s_%04d" % (p[0].name,tIndex) 604 title="%s at t=%f on %s" % (p[0].name,float(p[0].time()),p[0].line()) 605 elif self.opts.mode=="timesInOne": 606 name+="_%s" % (p[0].line()) 607 if self.opts.time!=None: 608 name+="_"+"_".join(["t="+t for t in self.opts.time]) 609 name+="_%s" % p[0].name 610 title="%s on %s" % (p[0].name,p[0].line()) 611 elif self.opts.mode=="fieldsInOne": 612 name+="_%s" % (p[0].line()) 613 if self.opts.field!=None: 614 name+="_"+string.join(self.opts.field,"_") 615 if self.opts.time!=None: 616 name+="_"+"_".join(["t="+t for t in self.opts.time]) 617 name+="_%04d" % tIndex 618 title="t=%f on %s" % (float(p[0].time()),p[0].line()) 619 elif self.opts.mode=="linesInOne": 620 name+="_%s" % (p[0].name) 621 if self.opts.line!=None: 622 name+="_"+string.join(self.opts.line,"_") 623 name+="_t=%f" % float(p[0].time()) 624 title="%s at t=%f" % (p[0].name,float(p[0].time())) 625 elif self.opts.mode=="complete": 626 pass 627 628 name+=".png" 629 if self.opts.pictureDest: 630 name=path.join(self.opts.pictureDest,name) 631 632 if self.opts.cleanFilename: 633 name=cleanFilename(name) 634 635 result+='set output "%s"\n' % name 636 if title!=None: 637 result+='set title "%s"\n' % title.replace("_","\\_") 638 639 result+="plot " 640 if self.opts.scaled: 641 if not self.opts.scaleAll: 642 vRange=vRanges[p[0].name] 643 644 # only scale if extremas are sufficiently different 645 if abs(vRange[0]-vRange[1])>1e-5*max(abs(vRange[0]),abs(vRange[1])) and max(abs(vRange[0]),abs(vRange[1]))>1e-10: 646 result+="[][%g:%g] " % vRange 647 648 first=True 649 650 for d in p: 651 if first: 652 first=False 653 else: 654 result+=", " 655 656 colSpec=d.index+1 657 if d.isVector(): 658 if self.opts.component!=None: 659 colSpec=d.index+1+self.opts.component 660 else: 661 colSpec="(sqrt($%d**2+$%d**2+$%d**2))" % (d.index+1,d.index+2,d.index+3) 662 663 # result+='"%s" using 1:%s ' % (d.file,colSpec) 664 665 def makeCol(spec,sc,off): 666 if type(spec)==str: 667 pre="" 668 else: 669 pre="$" 670 spec=str(spec) 671 if sc==1: 672 if off==0: 673 return spec 674 else: 675 return "(%s%s+%f)" % (pre,spec,off) 676 else: 677 if off==0: 678 return "(%s%s*%f)" % (pre,spec,sc) 679 else: 680 return "(%s%s*%f+%f)" % (pre,spec,sc,off)
681 682 result+='"%s" using %s:%s ' % (d.file, 683 makeCol(1,d.scale[0],d.offset[0]), 684 makeCol(colSpec,d.scale[1],d.offset[1])) 685 686 title=d.note 687 if self.opts.mode=="separate": 688 title+="" 689 elif self.opts.mode=="timesInOne": 690 title+="t=%f" % float(d.time()) 691 elif self.opts.mode=="fieldsInOne": 692 title+="%s" % d.name 693 elif self.opts.mode=="linesInOne": 694 title+="t=%f" % float(d.time()) 695 elif self.opts.mode=="complete": 696 title+="%s at t=%f" % (d.name,float(d.time())) 697 698 if len(self.opts.line)>1: 699 title+=" on %s" % d.line() 700 701 if title=="": 702 result+="notitle " 703 else: 704 result+='title "%s" ' % title.replace("_","\\_") 705 706 result+="with %s " % self.opts.style 707 708 result+="\n" 709 710 if self.opts.csvFile: 711 tmp=sum(plots,[]) 712 c=tmp[0]() 713 for p in tmp[1:]: 714 try: 715 c+=p() 716 except WrongDataSize: 717 if self.opts.resampleReference: 718 sp=p() 719 for n in sp.names()[1:]: 720 data=c.resample(sp, 721 n, 722 extendData=self.opts.extendData) 723 try: 724 c.append(n,data) 725 except ValueError: 726 c.append(self.opts.refprefix+" "+n,data) 727 else: 728 self.warning("Try the --resample-option") 729 raise 730 731 c.writeCSV(self.opts.csvFile) 732 elif self.opts.compare or self.opts.metrics: 733 statData={} 734 if self.opts.compare: 735 statData["compare"]={} 736 if self.opts.metrics: 737 statData["metrics"]={} 738 for p in self.opts.line: 739 if self.opts.compare: 740 statData["compare"][p]={} 741 if self.opts.metrics: 742 statData["metrics"][p]={} 743 744 oPlots=[item for sublist in oPlots for item in sublist] 745 rPlots=[item for sublist in rPlots for item in sublist] 746 if len(rPlots)!=len(oPlots) and self.opts.compare: 747 self.error("Number of original data sets",len(oPlots), 748 "is not equal to the reference data sets", 749 len(rPlots)) 750 if len(rPlots)==0 and self.opts.metrics: 751 rPlots=[None]*len(oPlots) 752 753 for o,r in zip(oPlots,rPlots): 754 data=o(scaleData=self.opts.scaleData, 755 offsetData=self.opts.offsetData, 756 scaleX=self.opts.scaleXAxis, 757 offsetX=self.opts.offsetXAxis) 758 if self.opts.compare: 759 if o.name!=r.name or (o.index!=r.index and not self.opts.indexTolerant): 760 self.error("Data from original",o.name,o.index, 761 "and reference",r.name,r.index, 762 "do not match. Try --index-tolerant-compare if you're sure that the data is right") 763 ref=r(scaleData=self.opts.scaleReferenceData, 764 offsetData=self.opts.offsetReferenceData, 765 scaleX=self.opts.scaleReferenceXAxis, 766 offsetX=self.opts.offsetReferenceXAxis) 767 else: 768 ref=None 769 for i,n in enumerate(data.names()): 770 if i==0: 771 continue 772 indexName=o.name 773 if n.split(" ")[-1]!=indexName: 774 indexName=n.split(" ")[-1] 775 776 if self.opts.metrics: 777 if not self.opts.silent: 778 print_("Metrics for",indexName,"(Path:",o.file,")") 779 result=data.metrics(data.names()[i], 780 minTime=self.opts.minTime, 781 maxTime=self.opts.maxTime) 782 statData["metrics"][o.line()][indexName]=result 783 if not self.opts.silent: 784 print_(" Min :",result["min"]) 785 print_(" Max :",result["max"]) 786 print_(" Average :",result["average"]) 787 print_(" Weighted average :",result["wAverage"]) 788 if not self.opts.compare: 789 print_("Data size:",data.size()) 790 print_(" Time Range :",result["tMin"],result["tMax"]) 791 if self.opts.compare: 792 oname=data.names()[i] 793 if self.opts.referenceTime or self.opts.tolerantReferenceTime: 794 oname=ref.names()[i] 795 if not self.opts.silent: 796 print_("Comparing",indexName,"with name",oname,"(Path:",r.file,")",end="") 797 if self.opts.compareOnOriginal: 798 if not self.opts.silent: 799 print_("on original data points") 800 result=data.compare(ref, 801 data.names()[i], 802 otherName=oname,common=self.opts.commonRange, 803 minTime=self.opts.minTime, 804 maxTime=self.opts.maxTime) 805 else: 806 if not self.opts.silent: 807 print_("on reference data points") 808 result=ref.compare(data, 809 oname, 810 otherName=data.names()[i], 811 common=self.opts.commonRange, 812 minTime=self.opts.minTime, 813 maxTime=self.opts.maxTime) 814 statData["compare"][o.line()][indexName]=result 815 if not self.opts.silent: 816 print_(" Max difference :",result["max"],"(at",result["maxPos"],")") 817 print_(" Average difference :",result["average"]) 818 print_(" Weighted average :",result["wAverage"]) 819 print_("Data size:",data.size(),"Reference:",ref.size()) 820 if not self.opts.metrics: 821 print_(" Time Range :",result["tMin"],result["tMax"]) 822 if not self.opts.silent: 823 print_() 824 825 self.setData(statData) 826 else: 827 dest=sys.stdout 828 if self.opts.gnuplotFile: 829 dest=open(self.opts.gnuplotFile,"w") 830 831 dest.write(result)
832 833 # Should work with Python3 and Python2 834