CMS 3D CMS Logo

dirstructure.py
Go to the documentation of this file.
1 from __future__ import print_function
2 from __future__ import absolute_import
3 ################################################################################
4 # RelMon: a tool for automatic Release Comparison
5 # https://twiki.cern.ch/twiki/bin/view/CMSPublic/RelMon
6 #
7 #
8 #
9 # Danilo Piparo CERN - danilo.piparo@cern.ch
10 #
11 ################################################################################
12 
13 from builtins import range
14 from array import array
15 from copy import deepcopy
16 from os import chdir,getcwd,listdir,makedirs,rmdir
17 from os.path import exists,join
18 
19 import sys
20 argv=sys.argv
21 from ROOT import *
22 sys.argv=argv
23 
24 from .definitions import *
25 from .utils import setTDRStyle
26 
27 
28 # Something nice and familiar
30 
31 # Do not display the canvases
32 gROOT.SetBatch(kTRUE)
33 
34 
35 #-------------------------------------------------------------------------------
36 _log_level=5
37 def logger(msg_level,message):
38  if msg_level>=_log_level:
39  print("[%s] %s" %(asctime(),message))
40 
41 #-------------------------------------------------------------------------------
42 
44  def __init__(self,name,weight=1):
45  self.name=name
46  self.weight=weight
47 
48 
49 #-------------------------------------------------------------------------------
51  def __init__(self,sample1="",sample2="",release1="",release2="",run1="",run2="",tier1=0,tier2=0):
52  self.sample1=sample1
53  self.sample2=sample2
54  self.release1=release1
55  self.release2=release2
56  self.run1=run1
57  self.run2=run2
58  self.tier1=tier1
59  self.tier2=tier2
60 
61 #-------------------------------------------------------------------------------
63  def __init__(self,name,mother_dir="",meta=CompInfo(),draw_success=False,do_pngs=False):
64  self.mother_dir=mother_dir
65  self.meta=meta
66  self.subdirs=[]
67  self.comparisons=[]
68  self.n_fails=0
69  self.n_successes=0
70  self.n_nulls=0
71  self.n_skiped = 0
72  self.n_comp_skiped = 0
73  self.n_comp_fails=0
75  self.n_comp_nulls=0
76  self.weight=0
77  self.stats_calculated=False
78  Weighted.__init__(self,name)
79  self.draw_success=draw_success
80  self.do_pngs=do_pngs
81  self.rank_histo=TH1I("rh%s"%name,"",50,-0.01,1.001)
82  self.rank_histo.SetDirectory(0)
84  self.different_histograms['file1']= {}
85  self.different_histograms['file2']= {}
86  self.filename1 = ""
87  self.filename2 = ""
88  self.n_missing_objs = 0
89  self.full_path = ""
90 
91  def is_empty(self):
92  if len(self.subdirs)==0 and len(self.comparisons)==0:
93  return True
94  return False
95 
96  def calcStats(self,make_pie=True):
97  '''Walk all subdirs and calculate weight,fails and successes.
98  Moreove propagate the sample and releases names.
99  '''
100  if self.stats_calculated:
101  return 0
102 
103  self.n_fails=0
104  self.n_successes=0
105  self.n_nulls=0
106  self.n_comp_fails=0
107  self.n_comp_successes=0
108  self.n_comp_nulls=0
109  self.weight=0
110 
111  self.n_skiped = 0
112  self.n_comp_skiped = 0
113  self.n_missing_objs = len(self.different_histograms['file1'])+len(self.different_histograms['file2'])
114  if self.n_missing_objs != 0:
115  print(" [*] Missing in %s: %s" %(self.filename1, self.different_histograms['file1']))
116  print(" [*] Missing in %s: %s" %(self.filename2, self.different_histograms['file2']))
117  # clean from empty dirs
118  self.subdirs = [subdir for subdir in self.subdirs if not subdir.is_empty()]
119 
120  for comp in self.comparisons:
121  if comp.status == SKIPED: #in case its in black list & skiped
122  self.n_skiped += 1
123  self.n_comp_skiped += 1
124  self.weight+=1
125  else: #else original code -> to check for Fails and Successes
126  self.rank_histo.Fill(comp.rank)
127  self.weight+=1
128  if comp.status == FAIL:
129  self.n_fails+=1
130  self.n_comp_fails+=1
131  elif comp.status == SUCCESS:
132  self.n_successes+=1
133  self.n_comp_successes+=1
134  else:
135  self.n_nulls+=1
136  self.n_comp_nulls+=1
137 
138  for subdir in self.subdirs:
139  subdir.mother_dir=join(self.mother_dir,self.name)
140  subdir.full_path = join(self.mother_dir,self.name).replace("/Run summary","")
141  subdir.calcStats(make_pie)
142  subdir.meta=self.meta
143  self.weight+=subdir.weight
144  self.n_fails+=subdir.n_fails
145  self.n_successes+=subdir.n_successes
146  self.n_nulls+=subdir.n_nulls
147 
148  self.n_skiped+=subdir.n_skiped
149  self.n_missing_objs += subdir.n_missing_objs
150 
151  self.rank_histo.Add(subdir.rank_histo)
152 
153  self.stats_calculated=True
154  self.full_path = join(self.mother_dir,self.name).replace("/Run summary","")
155  #if make_pie:
156  #self.__create_pie_image()
157 
158  def get_subdirs_dict(self):
159  subdirdict={}
160  for subdir in self.subdirs:
161  subdirdict[subdir.name]=subdir
162  return subdirdict
163 
164  def get_subdirs_names(self):
165  subdirnames=[]
166  for subdir in self.subdirs:
167  subdirnames.append(subdir.name)
168  return subdirnames
169 
170  def get_summary_chart_ajax(self,w=400,h=300):
171  """Emit the ajax to build a pie chart using google apis...
172  """
173  url = "https://chart.googleapis.com/chart?"
174  url+= "cht=p3" # Select the 3d chart
175  #url+= "&chl=Success|Null|Fail" # give labels
176  url+= "&chco=00FF00|FFFF00|FF0000|7A7A7A" # give colours to labels
177  url+= "&chs=%sx%s" %(w,h)
178  #url+= "&chtt=%s" %self.name
179  url+= "&chd=t:%.2f,%.2f,%.2f,%.2f"%(self.get_success_rate(),self.get_null_rate(),self.get_fail_rate(),self.get_skiped_rate())
180 
181  return url
182 
183  def print_report(self,indent="",verbose=False):
184  if len(indent)==0:
185  self.calcStats(make_pie=False)
186  # print small failure report
187  if verbose:
188  fail_comps=[comp for comp in self.comparisons if comp.status==FAIL]
189  fail_comps=sorted(fail_comps,key=lambda comp:comp.name )
190  if len(fail_comps)>0:
191  print(indent+"* %s/%s:" %(self.mother_dir,self.name))
192  for comp in fail_comps:
193  print(indent+" - %s: %s Test Failed (pval = %s) " %(comp.name,comp.test_name,comp.rank))
194  for subdir in self.subdirs:
195  subdir.print_report(indent+" ",verbose)
196 
197  if len(indent)==0:
198  print("\n%s - summary of %s tests:" %(self.name,self.weight))
199  print(" o Failiures: %.2f%% (%s/%s)" %(self.get_fail_rate(),self.n_fails,self.weight))
200  print(" o Nulls: %.2f%% (%s/%s) " %(self.get_null_rate(),self.n_nulls,self.weight))
201  print(" o Successes: %.2f%% (%s/%s) " %(self.get_success_rate(),self.n_successes,self.weight))
202  print(" o Skipped: %.2f%% (%s/%s) " %(self.get_skiped_rate(),self.n_skiped,self.weight))
203  print(" o Missing objects: %s" %(self.n_missing_objs))
204 
205  def get_skiped_rate(self):
206  if self.weight == 0: return 0
207  return 100.*self.n_skiped/self.weight
208  def get_fail_rate(self):
209  if self.weight == 0:return 0
210  return 100.*self.n_fails/self.weight
211 
212  def get_success_rate(self):
213  if self.weight == 0:return 1
214  return 100.*self.n_successes/self.weight
215 
216  def get_null_rate(self):
217  if self.weight == 0:return 0
218  return 100.*self.n_nulls/self.weight
219 
220  def __get_full_path(self):
221  #print "Mother is %s" %self.mother_dir
222  if len(self.mother_dir)==0:
223  return self.name
224  return join(self.mother_dir,self.name)
225 
226  def __create_on_disk(self):
227  if not exists(self.mother_dir) and len(self.mother_dir)!=0:
228  makedirs(self.mother_dir)
229  full_path=self.__get_full_path()
230  if not exists(full_path) and len(full_path)>0:
231  makedirs(full_path)
232 
234  return join(self.__get_full_path(),"summary_chart.png")
235 
237  self.__create_on_disk()
238  vals=[]
239  colors=[]
240  for n,col in zip((self.n_fails,self.n_nulls,self.n_successes,self.n_skiped),(kRed,kYellow,kGreen,kBlue)):
241  if n!=0:
242  vals.append(n)
243  colors.append(col)
244  valsa=array('f',vals)
245  colorsa=array('i',colors)
246  can = TCanvas("cpie","TPie test",100,100);
247  try:
248  pie = TPie("ThePie",self.name,len(vals),valsa,colorsa);
249  label_n=0
250  if self.n_fails!=0:
251  pie.SetEntryLabel(label_n, "Fail: %.1f(%i)" %(self.get_fail_rate(),self.n_fails) );
252  label_n+=1
253  if self.n_nulls!=0:
254  pie.SetEntryLabel(label_n, "Null: %.1f(%i)" %(self.get_null_rate(),self.n_nulls) );
255  label_n+=1
256  if self.n_successes!=0:
257  pie.SetEntryLabel(label_n, "Success: %.1f(%i)" %(self.get_success_rate(),self.n_successes) );
258  if self.n_skiped!=0:
259  pie.SetEntryLabel(label_n, "Skipped: %.1f(%i)" %(self.get_skiped_rate(),self.n_skiped));
260  pie.SetY(.52);
261  pie.SetAngularOffset(0.);
262  pie.SetLabelsOffset(-.3);
263  #pie.SetLabelFormat("#splitline{%val (%perc)}{%txt}");
264  pie.Draw("3d nol");
265  can.Print(self.get_summary_chart_name());
266  except:
267  print("self.name = %s" %self.name)
268  print("len(vals) = %s (vals=%s)" %(len(vals),vals))
269  print("valsa = %s" %valsa)
270  print("colorsa = %s" %colorsa)
271 
272  def prune(self,expandable_dir):
273  """Eliminate from the tree the directory the expandable ones.
274  """
275  #print "pruning %s" %self.name
276  exp_index=-1
277  counter=0
278  for subdir in self.subdirs:
279  # Eliminate any trace of the expandable path in the mother directories
280  # for depths higher than 1
281  subdir.mother_dir=subdir.mother_dir.replace("/"+expandable_dir,"")
282  if subdir.name==expandable_dir:
283  exp_index=counter
284  counter+=1
285 
286  # Did we find an expandable?
287  if exp_index>=0:
288  exp_dir=self.subdirs[exp_index]
289  for subsubdir in exp_dir.subdirs:
290  #print "*******",subsubdir.mother_dir,
291  subsubdir.mother_dir=subsubdir.mother_dir.replace("/"+expandable_dir,"")
292  while "//" in subsubdir.mother_dir:
293  print(subsubdir.mother_dir)
294  subsubdir.mother_dir=subsubdir.mother_dir.replace("//","/")
295  #print "*******",subsubdir.mother_dir
296  self.subdirs.append(subsubdir)
297 
298  for comp in exp_dir.comparisons:
299  comp.mother_dir=comp.mother_dir.replace("/"+expandable_dir,"")
300  while "//" in comp.mother_dir:
301  comp.mother_dir
302  comp.mother_dir=comp.mother_dir.replace("/")
303  if not comp in self.comparisons: #in case not to append same comparisons few times
304  self.comparisons.append(comp) # add a comparison
305  self.n_comp_fails = exp_dir.n_comp_fails #copy to-be removed directory
306  self.n_comp_nulls = exp_dir.n_comp_nulls # numbers to parent directory
307  self.n_comp_successes = exp_dir.n_comp_successes
308  self.n_comp_skiped = exp_dir.n_comp_skiped
309 
310  del self.subdirs[exp_index]
311  self.prune(expandable_dir)
312 
313  for subdir in self.subdirs:
314  subdir.prune(expandable_dir)
315 
316  def __repr__(self):
317  if self.is_empty():
318  return "%s seems to be empty. Please check!" %self.name
319  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)
320  for subdir in self.subdirs:
321  content+=" %s\n" % subdir
322  for comp in self.comparisons:
323  content+=" %s\n" % comp
324  return content
325 
326 #-------------------------------------------------------------------------------
327 from multiprocessing import Process
328 def print_multi_threaded(canvas,img_name):
329  canvas.Print(img_name)
330 
331 tcanvas_print_processes=[]
332 #-------------------------------------------------------------------------------
333 
335  canvas_xsize=500
336  canvas_ysize=400
337  def __init__(self,name,mother_dir,h1,h2,stat_test,draw_success=False,do_pngs=False, skip=False):
338  self.name=name
339  self.png_name="placeholder.png"
340  self.mother_dir=mother_dir
341  self.img_name=""
342  #self.draw_success=draw_success
343  Weighted.__init__(self,name)
344 
345  stat_test.set_operands(h1,h2)
346  if skip:
347  self.status = SKIPED
348  self.test_name=stat_test.name
349  self.test_name=stat_test.name
350  self.test_thr=stat_test.threshold
351  self.rank = 0
352  else:
353  self.status=stat_test.get_status()
354  self.rank=stat_test.get_rank()
355  self.test_name=stat_test.name
356  self.test_thr=stat_test.threshold
357  self.do_pngs=do_pngs
358  self.draw_success=draw_success or not do_pngs
359  if ((self.status==FAIL or self.status==NULL or self.status == SKIPED or self.draw_success) and self.do_pngs):
360  self.__make_image(h1,h2)
361  #self.__make_image(h1,h2)
362 
363  def __make_img_dir(self):
364  if not exists(self.mother_dir):
365  makedirs(self.mother_dir)
366 
367  def __get_img_name(self):
368  #self.__make_img_dir()
369  #print "MOTHER: ",self.mother_dir
370  self.img_name="%s/%s.png"%(self.mother_dir,self.name)
371  self.img_name=self.img_name.replace("Run summary","")
372  self.img_name=self.img_name.replace("/","_")
373  self.img_name=self.img_name.strip("_")
374  #print "IMAGE NAME: %s " %self.img_name
375  return self.img_name
376 
377  def tcanvas_slow(self,canvas):
378  #print "About to print %s" %self.img_name
379  #print_multi_threaded(canvas,self.img_name)
380  #print "-->Printed"
381 
382  p = Process(target=print_multi_threaded, args=(canvas,self.img_name))
383  p.start()
384  tcanvas_print_processes.append(p)
385  n_proc=len(tcanvas_print_processes)
386  if n_proc>3:
387  p_to_remove=[]
388  for iprocess in range(0,n_proc):
389  p=tcanvas_print_processes[iprocess]
390  p.join()
391  p_to_remove.append(iprocess)
392 
393  adjustment=0
394  for iprocess in p_to_remove:
395  tcanvas_print_processes.pop(iprocess-adjustment)
396  adjustment+=1
397 
398  def __make_image(self,obj1,obj2):
399  self.img_name=self.__get_img_name()
400  if self.rank==-1:
401  return 0
402 
403  canvas=TCanvas(self.name,self.name,Comparison.canvas_xsize,Comparison.canvas_ysize)
404  objs=(obj1,obj2)
405 
406  # Add some specifics for the graphs
407  obj1.SetTitle(self.name)
408 
409  if obj1.GetNbinsY()!=0 and not "2" in obj1.ClassName() :
410  obj1 .SetLineWidth(2)
411  obj2 .SetLineWidth(2)
412 
413  obj1.SetMarkerStyle(8)
414  obj1.SetMarkerSize(.8)
415 
416  obj2.SetMarkerStyle(8)
417  obj2.SetMarkerSize(.8)
418 
419  obj1.SetMarkerColor(kBlue)
420  obj1.SetLineColor(kBlue)
421 
422  obj2.SetMarkerColor(kRed)
423  obj2.SetLineColor(kRed)
424 
425  obj1.Draw("EP")
426  #Statsbox
427  obj2.Draw("HistSames")
428  #gPad.Update()
429  #if 'stats' in map(lambda o: o.GetName(),list(gPad.GetListOfPrimitives())):
430  #st = gPad.GetPrimitive("stats")
431  #st.SetY1NDC(0.575)
432  #st.SetY2NDC(0.735)
433  #st.SetLineColor(kRed)
434  #st.SetTextColor(kRed)
435  #print st
436  else:
437  obj1.Draw("Colz")
438  gPad.Update()
439  #if 'stats' in map(lambda o: o.GetName(),list(gPad.GetListOfPrimitives())):
440  #st = gPad.GetPrimitive("stats")
441  #st.SetY1NDC(0.575)
442  #st.SetY2NDC(0.735)
443  #st.SetLineColor(kRed)
444  #st.SetTextColor(kRed)
445  #print st
446  obj2.Draw("ColSame")
447 
448  # Put together the TLatex for the stat test if possible
449  color=kGreen+2 # which is green, as everybody knows
450  if self.status==FAIL:
451  print("This comparison failed %f" %self.rank)
452  color=kRed
453  elif self.status==NULL:
454  color=kYellow
455  elif self.status==SKIPED:
456  color=kBlue #check if kBlue exists ;)
457 
458  lat_text="#scale[.7]{#color[%s]{%s: %2.2f}}" %(color,self.test_name,self.rank)
459  lat=TLatex(.1,.91,lat_text)
460  lat.SetNDC()
461  lat.Draw()
462 
463  # Put also the stats together!
464  n1=obj1.GetEntries()
465  if n1> 100000:
466  n1="%e"%n1
467  else:
468  n1="%s"%n1
469  n2=obj2.GetEntries()
470  if n2> 100000:
471  n2="%e"%n2
472  else:
473  n2="%s"%n2
474 
475  lat_text1="#scale[.7]{#color[%s]{Entries: %s}}" %(obj1.GetLineColor(),n1)
476  lat1=TLatex(.3,.91,lat_text1)
477  lat1.SetNDC()
478  lat1.Draw()
479 
480 
481  lat_text2="#scale[.7]{#color[%s]{Entries: %s}}" %(obj2.GetLineColor(),n2)
482  lat2=TLatex(.6,.91,lat_text2)
483  lat2.SetNDC()
484  lat2.Draw()
485 
486 
487  self.tcanvas_slow(canvas)
488 
489  def __repr__(self):
490  return "%s , (%s=%s). IMG=%s. status=%s" %(self.name,self.test_name,self.rank,self.img_name,self.status)
491 
492 #-------------------------------------------------------------------------------
def __init__(self, name, mother_dir, h1, h2, stat_test, draw_success=False, do_pngs=False, skip=False)
def calcStats(self, make_pie=True)
Definition: dirstructure.py:96
def prune(self, expandable_dir)
def replace(string, replacements)
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:66
def __init__(self, sample1="", sample2="", release1="", release2="", run1="", run2="", tier1=0, tier2=0)
Definition: dirstructure.py:51
def print_report(self, indent="", verbose=False)
OutputIterator zip(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp)
def get_summary_chart_name(self)
def setTDRStyle()
Definition: plotscripts.py:89
def __init__(self, name, mother_dir="", meta=CompInfo(), draw_success=False, do_pngs=False)
Definition: dirstructure.py:63
def tcanvas_slow(self, canvas)
def get_summary_chart_ajax(self, w=400, h=300)
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
def print_multi_threaded(canvas, img_name)
def logger(msg_level, message)
Definition: dirstructure.py:37
def __create_pie_image(self)
def __init__(self, name, weight=1)
Definition: dirstructure.py:44
def __make_image(self, obj1, obj2)