CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_8_patch3/src/Utilities/RelMon/python/dirstructure.py

Go to the documentation of this file.
00001 ################################################################################
00002 # RelMon: a tool for automatic Release Comparison                              
00003 # https://twiki.cern.ch/twiki/bin/view/CMSPublic/RelMon
00004 #
00005 # $Author: dpiparo $
00006 # $Date: 2012/07/03 05:38:00 $
00007 # $Revision: 1.2 $
00008 #
00009 #                                                                              
00010 # Danilo Piparo CERN - danilo.piparo@cern.ch                                   
00011 #                                                                              
00012 ################################################################################
00013 
00014 from array import array
00015 from copy import deepcopy
00016 from os import chdir,getcwd,listdir,makedirs,rmdir
00017 from os.path import exists,join
00018 
00019 import sys
00020 argv=sys.argv
00021 from ROOT import *
00022 sys.argv=argv
00023 
00024 from definitions import *
00025 from utils import setTDRStyle
00026 
00027 
00028 # Something nice and familiar
00029 setTDRStyle()
00030 
00031 # Do not display the canvases
00032 gROOT.SetBatch(kTRUE)
00033 
00034 
00035 #-------------------------------------------------------------------------------
00036 _log_level=5
00037 def logger(msg_level,message):
00038   if msg_level>=_log_level:
00039     print "[%s] %s" %(asctime(),message)
00040 
00041 #-------------------------------------------------------------------------------
00042 
00043 class Weighted(object):
00044   def __init__(self,name,weight=1):
00045     self.name=name
00046     self.weight=weight
00047 
00048 
00049 #-------------------------------------------------------------------------------
00050 class CompInfo(object):
00051   def __init__(self,sample="",release1="",release2="",run1="",run2="",tier1=0,tier2=0):
00052     self.sample=sample
00053     self.release1=release1
00054     self.release2=release2
00055     self.run1=run1
00056     self.run2=run2
00057     self.tier1=tier1
00058     self.tier2=tier2
00059     
00060 #-------------------------------------------------------------------------------
00061 class Directory(Weighted):
00062   def __init__(self,name,mother_dir="",meta=CompInfo(),draw_success=False,do_pngs=False):
00063     self.mother_dir=mother_dir
00064     self.meta=meta
00065     self.subdirs=[]
00066     self.comparisons=[]   
00067     self.n_fails=0
00068     self.n_successes=0
00069     self.n_nulls=0
00070     self.n_comp_fails=0
00071     self.n_comp_successes=0
00072     self.n_comp_nulls=0 
00073     self.weight=0
00074     self.stats_calculated=False
00075     Weighted.__init__(self,name)
00076     self.draw_success=draw_success
00077     self.do_pngs=do_pngs
00078     self.rank_histo=TH1I("rh%s"%name,"",50,-0.01,1.001)
00079     self.rank_histo.SetDirectory(0)
00080 
00081   def is_empty(self):
00082     if len(self.subdirs)==0 and len(self.comparisons)==0:
00083       return True
00084     return False
00085   
00086   def calcStats(self,make_pie=True):
00087     '''Walk all subdirs and calculate weight,fails and successes.
00088     Moreove propagate the sample and releases names.
00089     '''
00090     if self.stats_calculated:
00091       return 0
00092     
00093     self.n_fails=0
00094     self.n_successes=0
00095     self.n_nulls=0
00096     self.n_comp_fails=0
00097     self.n_comp_successes=0
00098     self.n_comp_nulls=0  
00099     self.weight=0
00100     
00101     # clean from empty dirs    
00102     self.subdirs = filter(lambda subdir: not subdir.is_empty(),self.subdirs)    
00103     
00104     for comp in self.comparisons:
00105       self.rank_histo.Fill(comp.rank)
00106       self.weight+=1
00107       if comp.status == FAIL:
00108         self.n_fails+=1
00109         self.n_comp_fails+=1
00110       elif comp.status == SUCCESS:
00111         self.n_successes+=1
00112         self.n_comp_successes+=1
00113       else:
00114         self.n_nulls+=1
00115         self.n_comp_nulls+=1
00116 
00117     for subdir in self.subdirs:
00118       subdir.mother_dir=join(self.mother_dir,self.name)
00119       subdir.calcStats(make_pie)
00120       subdir.meta=self.meta 
00121       self.weight+=subdir.weight
00122       self.n_fails+=subdir.n_fails
00123       self.n_successes+=subdir.n_successes
00124       self.n_nulls+=subdir.n_nulls
00125       self.rank_histo.Add(subdir.rank_histo)
00126 
00127     self.stats_calculated=True 
00128     #if make_pie:
00129       #self.__create_pie_image()
00130 
00131   def get_subdirs_dict(self):
00132     subdirdict={}
00133     for subdir in self.subdirs:
00134       subdirdict[subdir.name]=subdir
00135     return subdirdict
00136 
00137   def get_subdirs_names(self):
00138     subdirnames=[]
00139     for subdir in self.subdirs:
00140       subdirnames.append(subdir.name)
00141     return subdirnames
00142 
00143   def get_summary_chart_ajax(self,w=400,h=300):
00144     """Emit the ajax to build a pie chart using google apis...
00145     """
00146     url = "https://chart.googleapis.com/chart?"
00147     url+= "cht=p3" # Select the 3d chart
00148     #url+= "&chl=Success|Null|Fail" # give labels
00149     url+= "&chco=00FF00|FFFF00|FF0000" # give colours to labels
00150     url+= "&chs=%sx%s" %(w,h)
00151     #url+= "&chtt=%s" %self.name
00152     url+= "&chd=t:%.2f,%.2f,%.2f"%(self.get_success_rate(),self.get_null_rate(),self.get_fail_rate())
00153     
00154     return url
00155 
00156   def print_report(self,indent="",verbose=False):
00157     if len(indent)==0:
00158       self.calcStats(make_pie=False)
00159     # print small failure report
00160     if verbose:
00161       fail_comps=filter(lambda comp:comp.status==FAIL,self.comparisons)
00162       fail_comps=sorted(fail_comps,key=lambda comp:comp.name )    
00163       if len(fail_comps)>0:
00164         print indent+"* %s/%s:" %(self.mother_dir,self.name)
00165         for comp in fail_comps:
00166           print indent+" - %s: %s Test Failed (pval = %s) " %(comp.name,comp.test_name,comp.rank)
00167       for subdir in self.subdirs:
00168         subdir.print_report(indent+"  ",verbose)
00169     
00170     if len(indent)==0:
00171       print "\n%s - summary of %s tests:" %(self.name,self.weight)
00172       print " o Failiures: %.2f%% (%s/%s)" %(self.get_fail_rate(),self.n_fails,self.weight)
00173       print " o Nulls: %.2f%% (%s/%s) " %(self.get_null_rate(),self.n_nulls,self.weight)
00174       print " o Successes: %.2f%% (%s/%s) " %(self.get_success_rate(),self.n_successes,self.weight)
00175 
00176   def get_fail_rate(self):
00177     if self.weight == 0:return 0
00178     return 100.*self.n_fails/self.weight
00179     
00180   def get_success_rate(self):
00181     if self.weight == 0:return 1    
00182     return 100.*self.n_successes/self.weight
00183     
00184   def get_null_rate(self):
00185     if self.weight == 0:return 0    
00186     return 100.*self.n_nulls/self.weight
00187 
00188   def __get_full_path(self):
00189     #print "Mother is %s" %self.mother_dir
00190     if len(self.mother_dir)==0:
00191       return self.name
00192     return join(self.mother_dir,self.name)
00193     
00194   def __create_on_disk(self):
00195     if not exists(self.mother_dir) and len(self.mother_dir)!=0:
00196       makedirs(self.mother_dir)
00197     full_path=self.__get_full_path()    
00198     if not exists(full_path) and len(full_path)>0:
00199       makedirs(full_path)
00200 
00201   def get_summary_chart_name(self):
00202     return join(self.__get_full_path(),"summary_chart.png") 
00203 
00204   def __create_pie_image(self):
00205     self.__create_on_disk()
00206     vals=[]
00207     colors=[]
00208     for n,col in zip((self.n_fails,self.n_nulls,self.n_successes),(kRed,kYellow,kGreen)):
00209       if n!=0:
00210         vals.append(n)
00211         colors.append(col)
00212     valsa=array('f',vals)
00213     colorsa=array('i',colors)
00214     can = TCanvas("cpie","TPie test",100,100);
00215     try:
00216       pie = TPie("ThePie",self.name,len(vals),valsa,colorsa);
00217       label_n=0
00218       if self.n_fails!=0:
00219         pie.SetEntryLabel(label_n, "Fail: %.1f(%i)" %(self.get_fail_rate(),self.n_fails) );
00220         label_n+=1
00221       if self.n_nulls!=0:
00222         pie.SetEntryLabel(label_n, "Null: %.1f(%i)" %(self.get_null_rate(),self.n_nulls) );      
00223         label_n+=1
00224       if self.n_successes!=0:
00225         pie.SetEntryLabel(label_n, "Success: %.1f(%i)" %(self.get_success_rate(),self.n_successes) );   
00226       pie.SetY(.52);
00227       pie.SetAngularOffset(0.);    
00228       pie.SetLabelsOffset(-.3);
00229       #pie.SetLabelFormat("#splitline{%val (%perc)}{%txt}");
00230       pie.Draw("3d  nol");
00231       can.Print(self.get_summary_chart_name());    
00232     except:
00233       print "self.name = %s" %self.name
00234       print "len(vals) = %s (vals=%s)" %(len(vals),vals)
00235       print "valsa = %s" %valsa
00236       print "colorsa = %s" %colorsa
00237 
00238   def prune(self,expandable_dir):
00239     """Eliminate from the tree the directory the expandable ones.
00240     """
00241     #print "pruning %s" %self.name
00242     exp_index=-1
00243     counter=0
00244     for subdir in self.subdirs:      
00245       # Eliminate any trace of the expandable path in the mother directories
00246       # for depths higher than 1
00247       subdir.mother_dir=subdir.mother_dir.replace("/"+expandable_dir,"")
00248       if subdir.name==expandable_dir:        
00249         exp_index=counter
00250       counter+=1
00251     
00252     # Did we find an expandable?
00253     if exp_index>=0:
00254       exp_dir=self.subdirs[exp_index]
00255       for subsubdir in exp_dir.subdirs:
00256         #print "*******",subsubdir.mother_dir,
00257         subsubdir.mother_dir=subsubdir.mother_dir.replace("/"+expandable_dir,"")
00258         while "//" in subsubdir.mother_dir:
00259           print subsubdir.mother_dir
00260           subsubdir.mother_dir=subsubdir.mother_dir.replace("//","/") 
00261         #print "*******",subsubdir.mother_dir
00262         self.subdirs.append(subsubdir)
00263           
00264         for comp in exp_dir.comparisons:
00265           comp.mother_dir=comp.mother_dir.replace("/"+expandable_dir,"")        
00266           while "//" in comp.mother_dir:
00267               comp.mother_dir
00268               comp.mother_dir=comp.mother_dir.replace("/")              
00269           self.comparisons.append(comp)
00270         
00271       del self.subdirs[exp_index]
00272       self.prune(expandable_dir)
00273     
00274     for subdir in self.subdirs:
00275       subdir.prune(expandable_dir)
00276 
00277   def __repr__(self):
00278     if self.is_empty():
00279       return "%s seems to be empty. Please check!" %self.name
00280     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)   
00281     for subdir in self.subdirs:
00282       content+=" %s\n" % subdir
00283     for comp in self.comparisons:
00284       content+=" %s\n" % comp
00285     return content
00286     
00287 #-------------------------------------------------------------------------------
00288 from multiprocessing import Process
00289 def print_multi_threaded(canvas,img_name):
00290     canvas.Print(img_name)
00291 
00292 tcanvas_print_processes=[]
00293 #-------------------------------------------------------------------------------
00294 
00295 class Comparison(Weighted):
00296   canvas_xsize=500
00297   canvas_ysize=400
00298   def __init__(self,name,mother_dir,h1,h2,stat_test,draw_success=False,do_pngs=False):
00299     self.name=name
00300     self.png_name="placeholder.png"
00301     self.mother_dir=mother_dir
00302     self.img_name=""
00303     #self.draw_success=draw_success
00304     Weighted.__init__(self,name)
00305 
00306     stat_test.set_operands(h1,h2)
00307     self.status=stat_test.get_status()    
00308     self.rank=stat_test.get_rank()        
00309     self.test_name=stat_test.name    
00310     self.test_thr=stat_test.threshold
00311     self.do_pngs=do_pngs
00312     self.draw_success=draw_success or not do_pngs
00313     if ((self.status==FAIL or self.status==NULL or self.draw_success) and self.do_pngs):
00314       self.__make_image(h1,h2)      
00315     #self.__make_image(h1,h2)
00316 
00317   def __make_img_dir(self):    
00318     if not exists(self.mother_dir):
00319       makedirs(self.mother_dir)
00320     
00321   def __get_img_name(self):
00322     #self.__make_img_dir()    
00323     #print "MOTHER: ",self.mother_dir
00324     self.img_name="%s/%s.png"%(self.mother_dir,self.name)
00325     self.img_name=self.img_name.replace("Run summary","")
00326     self.img_name=self.img_name.replace("/","_")
00327     self.img_name=self.img_name.strip("_")
00328     #print "IMAGE NAME: %s " %self.img_name
00329     return self.img_name
00330 
00331   def tcanvas_slow(self,canvas):
00332     #print "About to print %s" %self.img_name
00333     #print_multi_threaded(canvas,self.img_name)
00334     #print "-->Printed"
00335 
00336     p = Process(target=print_multi_threaded, args=(canvas,self.img_name))
00337     p.start()
00338     tcanvas_print_processes.append(p)
00339     n_proc=len(tcanvas_print_processes)
00340     if n_proc>3:
00341       p_to_remove=[]
00342       for iprocess in xrange(0,n_proc):
00343         p=tcanvas_print_processes[iprocess]
00344         p.join()
00345         p_to_remove.append(iprocess)
00346 
00347       adjustment=0
00348       for iprocess in p_to_remove:
00349         tcanvas_print_processes.pop(iprocess-adjustment)
00350         adjustment+=1
00351 
00352   def __make_image(self,obj1,obj2):
00353     self.img_name=self.__get_img_name()
00354     if self.rank==-1:
00355       return 0
00356    
00357     canvas=TCanvas(self.name,self.name,Comparison.canvas_xsize,Comparison.canvas_ysize)
00358     objs=(obj1,obj2)
00359 
00360     # Add some specifics for the graphs
00361     obj1.SetTitle(self.name)
00362     
00363     if obj1.GetNbinsY()!=0 and not "2" in obj1.ClassName() :
00364       obj1 .SetLineWidth(2)
00365       obj2 .SetLineWidth(2)
00366 
00367       obj1.SetMarkerStyle(8)
00368       obj1.SetMarkerSize(.8)
00369 
00370       obj2.SetMarkerStyle(8)
00371       obj2.SetMarkerSize(.8)
00372 
00373       obj1.SetMarkerColor(kBlue)
00374       obj1.SetLineColor(kBlue)
00375 
00376       obj2.SetMarkerColor(kRed)
00377       obj2.SetLineColor(kRed)
00378 
00379       obj1.Draw("EP")
00380       #Statsbox      
00381       obj2.Draw("HistSames")
00382       #gPad.Update()
00383       #if 'stats' in map(lambda o: o.GetName(),list(gPad.GetListOfPrimitives())):
00384         #st = gPad.GetPrimitive("stats")      
00385         #st.SetY1NDC(0.575)
00386         #st.SetY2NDC(0.735)
00387         #st.SetLineColor(kRed)
00388         #st.SetTextColor(kRed)
00389         #print st      
00390     else:
00391       obj1.Draw("Colz")
00392       gPad.Update()
00393       #if 'stats' in map(lambda o: o.GetName(),list(gPad.GetListOfPrimitives())):
00394         #st = gPad.GetPrimitive("stats")      
00395         #st.SetY1NDC(0.575)
00396         #st.SetY2NDC(0.735)
00397         #st.SetLineColor(kRed)
00398         #st.SetTextColor(kRed)
00399         #print st
00400       obj2.Draw("ColSame")
00401 
00402     # Put together the TLatex for the stat test if possible    
00403     color=kGreen+2 # which is green, as everybody knows
00404     if self.status==FAIL:
00405       print "This comparison failed %f" %self.rank
00406       color=kRed
00407     elif self.status==NULL:
00408       color=kYellow
00409     
00410     lat_text="#scale[.7]{#color[%s]{%s: %2.2f}}" %(color,self.test_name,self.rank)
00411     lat=TLatex(.1,.91,lat_text)
00412     lat.SetNDC()
00413     lat.Draw()
00414   
00415     # Put also the stats together!
00416     n1=obj1.GetEntries()
00417     if n1> 100000:
00418       n1="%e"%n1
00419     else:
00420       n1="%s"%n1
00421     n2=obj2.GetEntries()
00422     if n2> 100000:
00423       n2="%e"%n2
00424     else:
00425       n2="%s"%n2
00426 
00427     lat_text1="#scale[.7]{#color[%s]{Entries: %s}}" %(obj1.GetLineColor(),n1)
00428     lat1=TLatex(.3,.91,lat_text1)
00429     lat1.SetNDC()
00430     lat1.Draw()
00431         
00432     
00433     lat_text2="#scale[.7]{#color[%s]{Entries: %s}}" %(obj2.GetLineColor(),n2)
00434     lat2=TLatex(.6,.91,lat_text2)
00435     lat2.SetNDC()
00436     lat2.Draw()
00437     
00438 
00439     self.tcanvas_slow(canvas)
00440 
00441   def __repr__(self):
00442     return "%s , (%s=%s). IMG=%s. status=%s" %(self.name,self.test_name,self.rank,self.img_name,self.status)
00443 
00444 #-------------------------------------------------------------------------------