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