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