ATLAS Offline Software
compareTCTs.py
Go to the documentation of this file.
1 #!/bin/env python
2 
3 # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
4 
5 import os,sys
6 from PROCTools.getFileLists import tctPath, findTCTFiles
7 sys.argv += [ '-b' ] # tell ROOT to not use graphics
8 from ROOT import TFile,TTree
9 from PROCTools.diffTAGTree import diffTTree
10 import six
11 
12 os.environ['STAGE_SVCCLASS']="atlascerngroupdisk"
13 os.environ['STAGE_HOST']="castoratlast3"
14 
15 ignoreTrees=set(("CollectionMetadata",))
16 
17 def compareTreeFiles(rName,vName,details):
18  if rName.startswith("/castor"):
19  rFile=TFile.Open("root://castoratlas/"+rName)
20  elif rName.startswith("/eos"):
21  rFile=TFile.Open("root://eosatlas.cern.ch/"+rName)
22  else:
23  rFile=TFile.Open(rName)
24 
25  if vName.startswith("/castor"):
26  vFile=TFile.Open("root://castoratlas/"+vName)
27  elif vName.startswith("/eos"):
28  vFile=TFile.Open("root://eosatlas.cern.ch/"+vName)
29  else:
30  vFile=TFile.Open(vName)
31 
32  if rFile is None:
33  print ("Failed to open reference file",rName)
34  return (0,1)
35 
36  if vFile is None:
37  print ("Failed to open validation file",vName)
38  return (0,1)
39 
40  rKeys=set()
41  for k in rFile.GetListOfKeys():
42  rKeys.add(k.GetName())
43  vKeys=set()
44  for k in vFile.GetListOfKeys():
45  vKeys.add(k.GetName())
46  #print (rKeys)
47  #print (vKeys)
48  keys=rKeys & vKeys
49  keys -= ignoreTrees
50 
51  if len(keys)==0:
52  print ("ERROR no common trees names found in files",rName,vName)
53  return 0
54 
55  nGood=0
56  nBad=0
57  for k in keys:
58  rTree=rFile.Get(k)
59  vTree=vFile.Get(k)
60  if not isinstance(rTree,TTree):
61  continue
62  if not isinstance(vTree,TTree):
63  continue
64  print ("Comparing TTree",k)
65  (good,bad)=diffTTree(rTree,vTree,details)
66  nGood+=good
67  nBad+=bad
68  return (nGood,nBad)
69 
70 def diffPoolFiles(ref,chk,details,toIgnore = ['RecoTimingObj_p1_RAWtoESD_timings', 'RecoTimingObj_p1_ESDtoAOD_timings']):
71  import PyUtils.PoolFile as PF
72  try:
73  df = PF.DiffFiles( refFileName = ref, chkFileName = chk, ignoreList = toIgnore)
74  if details is None:
75  df.printSummary()
76  else:
77  df.printSummary(details)
78  stat=df.status()
79  del df
80  except Exception:
81  print ("Exception caught while diff'ing POOL files")
82  stat=True
83  return stat
84 
85 def diffPickleFiles(ref,chk,details):
86  try:
87  ref_nlines = open(ref).readlines()
88  chk_nlines = open(chk).readlines()
89  if len(ref_nlines) == len(chk_nlines):
90  stat=False
91  print ("same number of lines!")
92  else :
93  print (ref," has ",len(ref_nlines)," lines." )
94  print (chk," has ",len(chk_nlines)," lines.")
95  stat=True
96  #print (ref," has ",len(ref_nlines)," lines." )
97  #print (chk," has ",len(chk_nlines)," lines.")
98  #for refer, check in zip(ref_nlines,chk_nlines):
99  # if refer != check:
100  # print ("Expected %r; got %r " % (refer,check))
101  #stat=False
102  except Exception:
103  stat=True
104  print ("Exception caught while comparinging jobReport(_RecoTrf)?.gpickle files")
105  return stat
106 
107 
108 if __name__ == "__main__":
109  if len(sys.argv)<3 or sys.argv[1]=="-h" or sys.argv[1]=="--help":
110  print ("Usage: compareTCTs.py --nRef=<refernce nightly number> --nVal=<validation nightly number> --rRef=<reference nightly> --rVal=<validation nightly> --details=<text file> --file=<pattern> --sum=<summary file> --refPath=<path to ref-nightly> --valPath=<path to val-nightly>")
111  print (" Example: compareTCTs.py --nRef=15.6.X.Y --nVal=15.6.X.Y-VAL --rel=rel_4")
112  sys.exit(-1)
113 
114  import getopt
115  nRef=None
116  nVal=None
117  rRef=None
118  rVal=None
119  detailsFN=None
120  filePattern=[]
121  sumFileName=None
122  refPath=None
123  valPath=None
124  diffroot=False
125  opts,args=getopt.getopt(sys.argv[1:],"b",["nRef=","nVal=","rRef=","rVal=","rel=","nightly=","details=","file=","sum=","refPath=","valPath=","diff-root="])
126  for o,a in opts:
127  if o=="--nRef": nRef=a
128  if o=="--nVal": nVal=a
129  if o=="--rRef": rRef=a
130  if o=="--rVal": rVal=a
131  if o=="--nightly": nRef=nVal=a
132  if o=="--rel": rVal=rRef=a
133  if o=="--details": detailsFN=a
134  if o=="--file": filePattern+=(a,)
135  if o=="--sum": sumFileName=a
136  if o=="--refPath": refPath=a
137  if o=="--valPath": valPath=a
138  if o=="--diff-root":
139  if a=="True": diffroot=True
140 
141  if refPath is None:
142  if nRef is None:
143  print ("Reference nightly not defined! Please use --nRef parameter!")
144  sys.exit(-1)
145 
146  if rRef is None:
147  print ("Reference nightly number not defined! Please use --rRef parameter!")
148  sys.exit(-1)
149 
150  if valPath is None:
151  if nVal is None:
152  print ("Validation nightly not defined! Please use --nVal parameter!")
153  sys.exit(-1)
154  if rVal is None:
155  print ("Validation nightly number not defined! Please use --rVal parameter!")
156  sys.exit(-1)
157 
158  if len(filePattern)==0:
159  filePattern+=(".*myESD.*pool.root$",".*myRDO.*pool.root$",".*myAOD.*pool.root$","myTAG.*.root$","jobReport(_RecoTrf)?.gpickle$")
160  else:
161  for i in range(len(filePattern)):
162  #for fP in filePattern:
163  if filePattern[i].upper()=="ROOT":
164  filePattern[i]="*root$"
165  elif filePattern[i].upper()=="POOL":
166  filePattern[i]="*.pool.root$"
167  elif filePattern[i].upper()=="ESD":
168  filePattern[i]=".*myESD.*pool.root$"
169  elif filePattern[i].upper()=="RDO":
170  filePattern[i]=".*myRDO.*pool.root$"
171  elif filePattern[i].upper()=="AOD":
172  filePattern[i]=".*myAOD.*pool.root$"
173  elif filePattern[i].upper()=="TAGCOMM":
174  filePattern[i]="myTAGCOMM.*root$"
175  elif filePattern[i]=="TAG":
176  filePattern[i]="myTAG.*.root$"
177  elif filePattern[i].upper()=="NONE":
178  filePattern=[]
179  else:
180  pass
181 
182  print ("Comparing files matching:" )
183  print (filePattern)
184 
185  #Hack to process POOL files first (otherwise inifite loop)
186  allPatterns = []
187  for fP in filePattern:
188  if fP.find("pool") == -1:
189  allPatterns.append(fP)
190  else:
191  allPatterns.insert(0, fP)
192 
193  if refPath is None:
194  refPath = tctPath(nRef, rRef)
195 
196  if valPath is None:
197  valPath = tctPath(nVal, rVal)
198 
199  if not os.access(refPath, os.R_OK):
200  print ("Can't access output of reference TCT at",refPath)
201  sys.exit(-1)
202 
203  if not os.access(valPath, os.R_OK):
204  print ("Can't access output of validation TCT at",valPath)
205  sys.exit(-1)
206 
207  msg = "Reference TCT:\n"
208  msg += refPath + "\n"
209  msg += "Validation TCT:\n"
210  msg += valPath + "\n"
211 
212  print (msg)
213  if detailsFN is not None:
214  details = open(detailsFN, "w")
215  details.write(msg)
216  else:
217  details=None
218 
219  ff = findTCTFiles(refPath,valPath)
220  tctlist=ff.getCommonChains()
221  print ("Output from findTCTFile.getCommonChains():")
222  print (tctlist)
223 
224  statPerChain=dict()
225 
226  Summary=""
227  for pattern in allPatterns:
228  nIdenticalFiles = 0
229  nDifferentFiles = 0
230  filesToCompare = ff.findFiles(pattern)
231  print ("Will now look for files matching pattern:", pattern)
232  print ("The found files to compare:", filesToCompare)
233  print ("Comparing files matching [%s]" % pattern)
234  Summary += "Comparing files matching [%s]\n" % pattern
235  #for (tctName,r,v) in filesToCompare:
236  for name,rv in six.iteritems (filesToCompare):
237  #print ("TCT:",name,":",len(rv))
238  print ("Chain %s: Found %i files matching [%s]" % (name,len(rv),pattern))
239  for (r,v) in rv:
240  fileName=r.split('/')[-1]
241  print ("Comparing files",fileName,"of TCT",name)
242  identical=False
243  if (fileName.endswith(".pool.root") and not fileName.startswith("myTAG")):
244  if(r.startswith("/eos")): r = "root://eosatlas.cern.ch/"+r
245  if(v.startswith("/eos")): v = "root://eosatlas.cern.ch/"+v
246  if not diffroot: stat=diffPoolFiles(r,v,details)
247  else:
248  stat=os.system("acmd.py diff-root "+r+" "+v+" --error-mode resilient --ignore-leaves HITStoRDO_timings RecoTimingObj_p1_HITStoRDO_timings RecoTimingObj_p1_RAWtoESD_mems RecoTimingObj_p1_RAWtoESD_timings RAWtoESD_mems RAWtoESD_timings ESDtoAOD_mems ESDtoAOD_timings RAWtoALL_mems RAWtoALL_timings RecoTimingObj_p1_RAWtoALL_mems RecoTimingObj_p1_RAWtoALL_timings --entries 10 > tmp.txt")
249  os.system("cat tmp.txt|grep -v sync")
250  os.system("rm -f tmp.txt")
251  identical=not stat
252  elif fileName.endswith(".root"):
253  #(eq,dif)=compareTreeFiles(r,v,details)
254  #if eq==0 and dif==0: continue
255  #identical=(dif==0)
256  stat=os.system("diffTAGTree.py "+r+" "+v+" > tmp.txt")
257  os.system("cat tmp.txt|grep -v sync")
258  os.system("rm -f tmp.txt")
259  identical=not stat
260  elif fileName.endswith(".pickle"):
261  stat=diffPickleFiles(r,v,details)
262  identical=not stat
263  else:
264  print ("ERROR: Don't know how to compare",fileName)
265 
266  if (identical):
267  nIdenticalFiles+=1
268  if name not in statPerChain:
269  statPerChain[name]=False
270  else:
271  statPerChain[name]|=False
272  print ("Files are identical")
273  else:
274  statPerChain[name]=True
275  nDifferentFiles+=1
276  print ("Files are not identical")
277 
278  Summary+="Found %i identical files and %i different files\n" % (nIdenticalFiles, nDifferentFiles)
279  print ("Found %i identical files and %i different files\n" % (nIdenticalFiles, nDifferentFiles))
280 
281  if details is not None:
282  details.write(Summary)
283  details.close()
284 
285  #print (Summary)
286 
287  #print (tctlist)
288  #Check log,mem & cpu,
289  complain=""
290  for (name,info) in six.iteritems (tctlist):
291  #print (name,info,len(info))
292  if len(info)<2: continue
293  print ("\n"+name+":")
294  if (info[0].loglines>0 and info[1].loglines>0):
295  ratio=100.0*(info[1].loglines-info[0].loglines)/info[0].loglines
296  ln="\tLoglines: %i -> %i (%.2f)" % (info[0].loglines,info[1].loglines,ratio)
297  if abs(ratio)>5:
298  print (ln+"***")
299  complain+=name+" "+ln+"***\n"
300  else:
301  print (ln)
302  if len(info[0].cpulist)>4 and len(info[1].cpulist)>4:
303  #ESD
304  cpu_r=info[0].cpulist[1]
305  cpu_v=info[1].cpulist[1]
306  if (cpu_r>0 and cpu_v>0):
307  ratio=100.0*(cpu_v-cpu_r)/cpu_r
308  ln="\tESD CPU: %i -> %i (%.2f%%)" % (cpu_r,cpu_v,ratio)
309  if abs(ratio)>15:
310  print (ln+"***")
311  complain+=name+" "+ln+"***\n"
312  else:
313  print (ln)
314 
315  #AOD
316  cpu_r=info[0].cpulist[4]
317  cpu_v=info[1].cpulist[4]
318  if (cpu_r>0 and cpu_v>0):
319  ratio=100.0*(cpu_v-cpu_r)/cpu_r
320  ln="\tAOD CPU: %i -> %i (%.2f%%)" % (cpu_r,cpu_v,ratio)
321  if abs(ratio)>15:
322  print (ln+"***")
323  complain+=name+" "+ln+"***\n"
324  else:
325  print (ln)
326 
327  if len(info[0].memlist)>4 and len(info[1].memlist)>4:
328  mem_r=info[0].memlist[1]
329  mem_v=info[1].memlist[1]
330  if (mem_r>0 and mem_v>0):
331  ratio=100.0*(mem_v-mem_r)/mem_r
332  ln="\tESD MEM: %i -> %i (%.2f%%)" % (mem_r,mem_v,ratio)
333  if abs(ratio)>15:
334  print (ln+"***")
335  complain+=name+" "+ln+"***\n"
336  else:
337  print (ln)
338 
339  mem_r=info[0].memlist[4]
340  mem_v=info[1].memlist[4]
341  if (mem_r>0 and mem_v>0):
342  ratio=100.0*(mem_v-mem_r)/mem_r
343  ln="\tAOD MEM: %i -> %i (%.2f%%)" % (mem_r,mem_v,ratio)
344  if abs(ratio)>15:
345  print (ln+"***")
346  complain+=name+" "+ln+"***\n"
347  else:
348  print (ln)
349 
350  isok=True
351  for f,s in six.iteritems (statPerChain):
352  if s:
353  print ("%-70s CHANGED" % f)
354  isok=False
355  else:
356  print ("%-70s IDENTICAL" % f)
357 
358  if sumFileName is not None:
359  sumFile=open(sumFileName,"w")
360  for f,s in six.iteritems (statPerChain):
361  line = "%-70s" % f
362  if s:
363  line += "CHANGED\n"
364  else:
365  line += "IDENTICAL\n"
366  sumFile.write(line)
367 
368  sumFile.write("\n\n")
369  sumFile.write(complain)
370  sumFile.close()
371 
372  #print (statPerChain)
373  del diffTTree
374  if not isok:
375  sys.exit(-1)
python.compareTCTs.diffPickleFiles
def diffPickleFiles(ref, chk, details)
Definition: compareTCTs.py:85
diffPoolFiles
Definition: diffPoolFiles.py:1
upper
int upper(int c)
Definition: LArBadChannelParser.cxx:49
python.compareTCTs.compareTreeFiles
def compareTreeFiles(rName, vName, details)
Definition: compareTCTs.py:17
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
python.getFileLists.tctPath
def tctPath(build, rel)
Definition: getFileLists.py:11
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
Trk::open
@ open
Definition: BinningType.h:40
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
python.compareTCTs.diffPoolFiles
def diffPoolFiles(ref, chk, details, toIgnore=['RecoTimingObj_p1_RAWtoESD_timings', 'RecoTimingObj_p1_ESDtoAOD_timings'])
Definition: compareTCTs.py:70
python.diffTAGTree.diffTTree
def diffTTree(tOld, tNew, details=None)
Definition: diffTAGTree.py:12