File indexing completed on 2024-06-13 03:24:15
0001 from __future__ import print_function
0002 from __future__ import absolute_import
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 from builtins import range
0014 from array import array
0015 from copy import deepcopy
0016 from os import chdir,getcwd,listdir,makedirs,rmdir
0017 from os.path import exists,join
0018 import random
0019
0020 import sys
0021 argv=sys.argv
0022 import ROOT
0023 sys.argv=argv
0024
0025 from .definitions import *
0026 from .utils import setTDRStyle
0027
0028
0029
0030 setTDRStyle()
0031
0032
0033 ROOT.gROOT.SetBatch(ROOT.kTRUE)
0034
0035
0036
0037 _log_level=5
0038 def logger(msg_level,message):
0039 if msg_level>=_log_level:
0040 print("[%s] %s" %(asctime(),message))
0041
0042
0043
0044 class Weighted(object):
0045 def __init__(self,name,weight=1):
0046 self.name=name
0047 self.weight=weight
0048
0049
0050
0051 class CompInfo(object):
0052 def __init__(self,sample1="",sample2="",release1="",release2="",run1="",run2="",tier1=0,tier2=0):
0053 self.sample1=sample1
0054 self.sample2=sample2
0055 self.release1=release1
0056 self.release2=release2
0057 self.run1=run1
0058 self.run2=run2
0059 self.tier1=tier1
0060 self.tier2=tier2
0061
0062
0063 class Directory(Weighted):
0064 def __init__(self,name,mother_dir="",meta=CompInfo(),draw_success=False,do_pngs=False):
0065 self.mother_dir=mother_dir
0066 self.meta=meta
0067 self.subdirs=[]
0068 self.comparisons=[]
0069 self.n_fails=0
0070 self.n_successes=0
0071 self.n_nulls=0
0072 self.n_skiped = 0
0073 self.n_comp_skiped = 0
0074 self.n_comp_fails=0
0075 self.n_comp_successes=0
0076 self.n_comp_nulls=0
0077 self.weight=0
0078 self.stats_calculated=False
0079 Weighted.__init__(self,name)
0080 self.draw_success=draw_success
0081 self.do_pngs=do_pngs
0082 self.rank_histo=ROOT.TH1I("rh%s"%name,"",50,-0.01,1.001)
0083 self.rank_histo.SetDirectory(0)
0084 self.different_histograms = {}
0085 self.different_histograms['file1']= {}
0086 self.different_histograms['file2']= {}
0087 self.filename1 = ""
0088 self.filename2 = ""
0089 self.n_missing_objs = 0
0090 self.full_path = ""
0091
0092 def is_empty(self):
0093 if len(self.subdirs)==0 and len(self.comparisons)==0:
0094 return True
0095 return False
0096
0097 def calcStats(self,make_pie=True):
0098 '''Walk all subdirs and calculate weight,fails and successes.
0099 Moreove propagate the sample and releases names.
0100 '''
0101 if self.stats_calculated:
0102 return 0
0103
0104 self.n_fails=0
0105 self.n_successes=0
0106 self.n_nulls=0
0107 self.n_comp_fails=0
0108 self.n_comp_successes=0
0109 self.n_comp_nulls=0
0110 self.weight=0
0111
0112 self.n_skiped = 0
0113 self.n_comp_skiped = 0
0114 self.n_missing_objs = len(self.different_histograms['file1'])+len(self.different_histograms['file2'])
0115 if self.n_missing_objs != 0:
0116 print(" [*] Missing in %s: %s" %(self.filename1, self.different_histograms['file1']))
0117 print(" [*] Missing in %s: %s" %(self.filename2, self.different_histograms['file2']))
0118
0119 self.subdirs = [subdir for subdir in self.subdirs if not subdir.is_empty()]
0120
0121 for comp in self.comparisons:
0122 if comp.status == SKIPED:
0123 self.n_skiped += 1
0124 self.n_comp_skiped += 1
0125 self.weight+=1
0126 else:
0127 self.rank_histo.Fill(comp.rank)
0128 self.weight+=1
0129 if comp.status == FAIL:
0130 self.n_fails+=1
0131 self.n_comp_fails+=1
0132 elif comp.status == SUCCESS:
0133 self.n_successes+=1
0134 self.n_comp_successes+=1
0135 else:
0136 self.n_nulls+=1
0137 self.n_comp_nulls+=1
0138
0139 for subdir in self.subdirs:
0140 subdir.mother_dir=join(self.mother_dir,self.name)
0141 subdir.full_path = join(self.mother_dir,self.name).replace("/Run summary","")
0142 subdir.calcStats(make_pie)
0143 subdir.meta=self.meta
0144 self.weight+=subdir.weight
0145 self.n_fails+=subdir.n_fails
0146 self.n_successes+=subdir.n_successes
0147 self.n_nulls+=subdir.n_nulls
0148
0149 self.n_skiped+=subdir.n_skiped
0150 self.n_missing_objs += subdir.n_missing_objs
0151
0152 self.rank_histo.Add(subdir.rank_histo)
0153
0154 self.stats_calculated=True
0155 self.full_path = join(self.mother_dir,self.name).replace("/Run summary","")
0156
0157
0158
0159 def get_subdirs_dict(self):
0160 subdirdict={}
0161 for subdir in self.subdirs:
0162 subdirdict[subdir.name]=subdir
0163 return subdirdict
0164
0165 def get_subdirs_names(self):
0166 subdirnames=[]
0167 for subdir in self.subdirs:
0168 subdirnames.append(subdir.name)
0169 return subdirnames
0170
0171 def get_piechart_js(self,w=400,link=None):
0172
0173 """
0174 Build the HTML snippet to render a piechart with chart.js
0175 """
0176 if self.get_success_rate()>=99.9:
0177 img_link = "https://raw.githubusercontent.com/cms-PdmV/RelMonService2/5ee98db210c0898fd34b4deac3653fa2bdff269b/report_website/lime_circle.png"
0178 html ='<img src="%s" height=%d width=%d>' %(img_link,w,w)
0179 if link is not None:
0180 html = '<a href="%s"> %s </a>' %(link,html)
0181 return html
0182
0183 name = random.getrandbits(64)
0184 html = ""
0185 html += '<canvas id="%s" height=%d width=%d></canvas>'%(name,w,w)
0186
0187 html += '<script> new Chart("%s",'%(name)
0188 html += '{ type: "pie",'
0189
0190
0191 html += 'data: {'
0192 html += 'labels: ["Success", "Null" , "Failure", "Skipped"],'
0193 html += 'datasets: [{ backgroundColor: ["lime","yellow","red","grey"],'
0194 html += 'data: [%.2f,%.2f,%.2f,%.2f]}] },'%(self.get_success_rate(),self.get_null_rate(),self.get_fail_rate(),self.get_skiped_rate())
0195
0196
0197 html += 'options: { '
0198
0199 if link is not None:
0200 html += 'onClick : function(event) { window.open("%s", "_blank");},'%(link)
0201
0202
0203 html +='legend: { display: false }, responsive : false, hover: {mode: null}, tooltips: {enabled: false}'
0204
0205
0206 html += '}}); </script>'
0207
0208 return html
0209
0210 def print_report(self,indent="",verbose=False):
0211 if len(indent)==0:
0212 self.calcStats(make_pie=False)
0213
0214 if verbose:
0215 fail_comps=[comp for comp in self.comparisons if comp.status==FAIL]
0216 fail_comps=sorted(fail_comps,key=lambda comp:comp.name )
0217 if len(fail_comps)>0:
0218 print(indent+"* %s/%s:" %(self.mother_dir,self.name))
0219 for comp in fail_comps:
0220 print(indent+" - %s: %s Test Failed (pval = %s) " %(comp.name,comp.test_name,comp.rank))
0221 for subdir in self.subdirs:
0222 subdir.print_report(indent+" ",verbose)
0223
0224 if len(indent)==0:
0225 print("\n%s - summary of %s tests:" %(self.name,self.weight))
0226 print(" o Failiures: %.2f%% (%s/%s)" %(self.get_fail_rate(),self.n_fails,self.weight))
0227 print(" o Nulls: %.2f%% (%s/%s) " %(self.get_null_rate(),self.n_nulls,self.weight))
0228 print(" o Successes: %.2f%% (%s/%s) " %(self.get_success_rate(),self.n_successes,self.weight))
0229 print(" o Skipped: %.2f%% (%s/%s) " %(self.get_skiped_rate(),self.n_skiped,self.weight))
0230 print(" o Missing objects: %s" %(self.n_missing_objs))
0231
0232 def get_skiped_rate(self):
0233 if self.weight == 0: return 0
0234 return 100.*self.n_skiped/self.weight
0235 def get_fail_rate(self):
0236 if self.weight == 0:return 0
0237 return 100.*self.n_fails/self.weight
0238
0239 def get_success_rate(self):
0240 if self.weight == 0:return 1
0241 return 100.*self.n_successes/self.weight
0242
0243 def get_null_rate(self):
0244 if self.weight == 0:return 0
0245 return 100.*self.n_nulls/self.weight
0246
0247 def __get_full_path(self):
0248
0249 if len(self.mother_dir)==0:
0250 return self.name
0251 return join(self.mother_dir,self.name)
0252
0253 def __create_on_disk(self):
0254 if not exists(self.mother_dir) and len(self.mother_dir)!=0:
0255 makedirs(self.mother_dir)
0256 full_path=self.__get_full_path()
0257 if not exists(full_path) and len(full_path)>0:
0258 makedirs(full_path)
0259
0260 def get_summary_chart_name(self):
0261 return join(self.__get_full_path(),"summary_chart.png")
0262
0263 def __create_pie_image(self):
0264 self.__create_on_disk()
0265 vals=[]
0266 colors=[]
0267 for n,col in zip((self.n_fails,self.n_nulls,self.n_successes,self.n_skiped),(ROOT.kRed,ROOT.kYellow,ROOT.kGreen,ROOT.kBlue)):
0268 if n!=0:
0269 vals.append(n)
0270 colors.append(col)
0271 valsa=array('f',vals)
0272 colorsa=array('i',colors)
0273 can = ROOT.TCanvas("cpie","TPie test",100,100);
0274 try:
0275 pie = TPie("ThePie",self.name,len(vals),valsa,colorsa);
0276 label_n=0
0277 if self.n_fails!=0:
0278 pie.SetEntryLabel(label_n, "Fail: %.1f(%i)" %(self.get_fail_rate(),self.n_fails) );
0279 label_n+=1
0280 if self.n_nulls!=0:
0281 pie.SetEntryLabel(label_n, "Null: %.1f(%i)" %(self.get_null_rate(),self.n_nulls) );
0282 label_n+=1
0283 if self.n_successes!=0:
0284 pie.SetEntryLabel(label_n, "Success: %.1f(%i)" %(self.get_success_rate(),self.n_successes) );
0285 if self.n_skiped!=0:
0286 pie.SetEntryLabel(label_n, "Skipped: %.1f(%i)" %(self.get_skiped_rate(),self.n_skiped));
0287 pie.SetY(.52);
0288 pie.SetAngularOffset(0.);
0289 pie.SetLabelsOffset(-.3);
0290
0291 pie.Draw("3d nol");
0292 can.Print(self.get_summary_chart_name());
0293 except:
0294 print("self.name = %s" %self.name)
0295 print("len(vals) = %s (vals=%s)" %(len(vals),vals))
0296 print("valsa = %s" %valsa)
0297 print("colorsa = %s" %colorsa)
0298
0299 def prune(self,expandable_dir):
0300 """Eliminate from the tree the directory the expandable ones.
0301 """
0302
0303 exp_index=-1
0304 counter=0
0305 for subdir in self.subdirs:
0306
0307
0308 subdir.mother_dir=subdir.mother_dir.replace("/"+expandable_dir,"")
0309 if subdir.name==expandable_dir:
0310 exp_index=counter
0311 counter+=1
0312
0313
0314 if exp_index>=0:
0315 exp_dir=self.subdirs[exp_index]
0316 for subsubdir in exp_dir.subdirs:
0317
0318 subsubdir.mother_dir=subsubdir.mother_dir.replace("/"+expandable_dir,"")
0319 while "//" in subsubdir.mother_dir:
0320 print(subsubdir.mother_dir)
0321 subsubdir.mother_dir=subsubdir.mother_dir.replace("//","/")
0322
0323 self.subdirs.append(subsubdir)
0324
0325 for comp in exp_dir.comparisons:
0326 comp.mother_dir=comp.mother_dir.replace("/"+expandable_dir,"")
0327 while "//" in comp.mother_dir:
0328 comp.mother_dir
0329 comp.mother_dir=comp.mother_dir.replace("/")
0330 if not comp in self.comparisons:
0331 self.comparisons.append(comp)
0332 self.n_comp_fails = exp_dir.n_comp_fails
0333 self.n_comp_nulls = exp_dir.n_comp_nulls
0334 self.n_comp_successes = exp_dir.n_comp_successes
0335 self.n_comp_skiped = exp_dir.n_comp_skiped
0336
0337 del self.subdirs[exp_index]
0338 self.prune(expandable_dir)
0339
0340 for subdir in self.subdirs:
0341 subdir.prune(expandable_dir)
0342
0343 def __repr__(self):
0344 if self.is_empty():
0345 return "%s seems to be empty. Please check!" %self.name
0346 content="%s , Rates: Success %.2f%%(%s) - Fail %.2f%%(%s) - Null %.2f%%(%s)\n" %(self.name,self.get_success_rate(),self.n_successes,self.get_fail_rate(),self.n_fails,self.get_null_rate(),self.n_nulls)
0347 for subdir in self.subdirs:
0348 content+=" %s\n" % subdir
0349 for comp in self.comparisons:
0350 content+=" %s\n" % comp
0351 return content
0352
0353
0354 from multiprocessing import Process
0355 def print_multi_threaded(canvas,img_name):
0356 canvas.Print(img_name)
0357
0358 tcanvas_print_processes=[]
0359
0360
0361 class Comparison(Weighted):
0362 canvas_xsize=500
0363 canvas_ysize=400
0364 def __init__(self,name,mother_dir,h1,h2,stat_test,draw_success=False,do_pngs=False, skip=False):
0365 self.name=name
0366 self.png_name="placeholder.png"
0367 self.mother_dir=mother_dir
0368 self.img_name=""
0369
0370 Weighted.__init__(self,name)
0371
0372 stat_test.set_operands(h1,h2)
0373 if skip:
0374 self.status = SKIPED
0375 self.test_name=stat_test.name
0376 self.test_name=stat_test.name
0377 self.test_thr=stat_test.threshold
0378 self.rank = 0
0379 else:
0380 self.status=stat_test.get_status()
0381 self.rank=stat_test.get_rank()
0382 self.test_name=stat_test.name
0383 self.test_thr=stat_test.threshold
0384 self.do_pngs=do_pngs
0385 self.draw_success=draw_success or not do_pngs
0386 if ((self.status==FAIL or self.status==NULL or self.status == SKIPED or self.draw_success) and self.do_pngs):
0387 self.__make_image(h1,h2)
0388
0389
0390 def __make_img_dir(self):
0391 if not exists(self.mother_dir):
0392 makedirs(self.mother_dir)
0393
0394 def __get_img_name(self):
0395
0396
0397 self.img_name="%s/%s.png"%(self.mother_dir,self.name)
0398 self.img_name=self.img_name.replace("Run summary","")
0399 self.img_name=self.img_name.replace("/","_")
0400 self.img_name=self.img_name.strip("_")
0401
0402 return self.img_name
0403
0404 def tcanvas_slow(self,canvas):
0405
0406
0407
0408
0409 p = Process(target=print_multi_threaded, args=(canvas,self.img_name))
0410 p.start()
0411 tcanvas_print_processes.append(p)
0412 n_proc=len(tcanvas_print_processes)
0413 if n_proc>3:
0414 p_to_remove=[]
0415 for iprocess in range(0,n_proc):
0416 p=tcanvas_print_processes[iprocess]
0417 p.join()
0418 p_to_remove.append(iprocess)
0419
0420 adjustment=0
0421 for iprocess in p_to_remove:
0422 tcanvas_print_processes.pop(iprocess-adjustment)
0423 adjustment+=1
0424
0425 def __make_image(self,obj1,obj2):
0426 self.img_name=self.__get_img_name()
0427 if self.rank==-1:
0428 return 0
0429
0430 canvas=ROOT.TCanvas(self.name,self.name,Comparison.canvas_xsize,Comparison.canvas_ysize)
0431 objs=(obj1,obj2)
0432
0433
0434 obj1.SetTitle(self.name)
0435
0436 if obj1.GetNbinsY()!=0 and not "2" in obj1.ClassName() :
0437 obj1 .SetLineWidth(2)
0438 obj2 .SetLineWidth(2)
0439
0440 obj1.SetMarkerStyle(8)
0441 obj1.SetMarkerSize(.8)
0442
0443 obj2.SetMarkerStyle(8)
0444 obj2.SetMarkerSize(.8)
0445
0446 obj1.SetMarkerColor(ROOT.kBlue)
0447 obj1.SetLineColor(ROOT.kBlue)
0448
0449 obj2.SetMarkerColor(ROOT.kRed)
0450 obj2.SetLineColor(ROOT.kRed)
0451
0452 obj1.Draw("EP")
0453
0454 obj2.Draw("HistSames")
0455
0456
0457
0458
0459
0460
0461
0462
0463 else:
0464 obj1.Draw("Colz")
0465 ROOT.gPad.Update()
0466
0467
0468
0469
0470
0471
0472
0473 obj2.Draw("ColSame")
0474
0475
0476 color=ROOT.kGreen+2
0477 if self.status==FAIL:
0478 print("This comparison failed %f" %self.rank)
0479 color=ROOT.kRed
0480 elif self.status==NULL:
0481 color=ROOT.kYellow
0482 elif self.status==SKIPED:
0483 color=ROOT.kBlue
0484
0485 lat_text="#scale[.7]{#color[%s]{%s: %2.2f}}" %(color,self.test_name,self.rank)
0486 lat=ROOT.TLatex(.1,.91,lat_text)
0487 lat.SetNDC()
0488 lat.Draw()
0489
0490
0491 n1=obj1.GetEntries()
0492 if n1> 100000:
0493 n1="%e"%n1
0494 else:
0495 n1="%s"%n1
0496 n2=obj2.GetEntries()
0497 if n2> 100000:
0498 n2="%e"%n2
0499 else:
0500 n2="%s"%n2
0501
0502 lat_text1="#scale[.7]{#color[%s]{Entries: %s}}" %(obj1.GetLineColor(),n1)
0503 lat1=ROOT.TLatex(.3,.91,lat_text1)
0504 lat1.SetNDC()
0505 lat1.Draw()
0506
0507
0508 lat_text2="#scale[.7]{#color[%s]{Entries: %s}}" %(obj2.GetLineColor(),n2)
0509 lat2=ROOT.TLatex(.6,.91,lat_text2)
0510 lat2.SetNDC()
0511 lat2.Draw()
0512
0513
0514 self.tcanvas_slow(canvas)
0515
0516 def __repr__(self):
0517 return "%s , (%s=%s). IMG=%s. status=%s" %(self.name,self.test_name,self.rank,self.img_name,self.status)
0518
0519