CMS 3D CMS Logo

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