ATLAS Offline Software
TRTCalib_last_Skeleton.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
3 import sys, os, glob, subprocess, tarfile, fnmatch, smtplib
4 
5 def nextstep(text):
6  print("\n"+"#"*100)
7  print("#")
8  print("# %s" % (text))
9  print("#")
10  print("#"*100,"\n")
11 
12 def tryError(command, error):
13  try:
14  print(" Running: %s\n" % (command))
15  stdout, stderr = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
16  print("OUTPUT: \n%s" % (stdout.decode('ascii')))
17  print("ERRORS: %s" % ("NONE" if stderr.decode('ascii')=='' else "\n"+stderr.decode('ascii')))
18  if stderr:
19  exit(1)
20  except OSError as e:
21  print(error,e)
22  sys.exit(e.errno)
23 
24 
25 def send_statusmail(itera, runNumber, mto, outdir, a, b, c, d, e, f, g, h) :
26  mserver = 'cernmx.cern.ch'
27  mfrom = 'no-reply@cern.ch'
28  msubject = "TRT CALIB TIER0 - Exit Status for Run %d" % (runNumber)
29 
30  # assemble mail body
31  mbody = " Calibration job finished for run %d, iteration: %s \n\n" % (runNumber, itera)
32  mbody += " Here are the residuals obtained at detector level with currently used constants: \n"
33  mbody += " Residual-Barrel A: %s, Time-Residual-Barrel A: %s \n" % (a, b)
34  mbody += " Residual-Barrel C: %s, Time-Residual-Barrel C: %s \n" % (c, d)
35  mbody += " Residual-Endcap A: %s, Time-Residual-Endcap A: %s \n" % (e, f)
36  mbody += " Residual-Endcap C: %s, Time-Residual-Endcap C: %s \n\n" % (g, h)
37  mbody += " Expect Residual 140 +- 10mu in the barrel (Ar) and 130 +- 10mu in EC (Xe). Expect Time-Residual 0.0 +- 0.5ns.\n\n"
38  mbody += " Please check the histograms of the current run, to decide whether to upload new constants.\n"
39  mbody += " Histograms can be found on AFS, directory %s \n\n" % (outdir)
40 
41  print("Email body:\n\n",mbody)
42  print("Email sent to:")
43 
44  try :
45  con = smtplib.SMTP(mserver)
46  if isinstance(mto, str) :
47  print("\t- %s"% (mto))
48  con.sendmail(mfrom, mto, 'Subject:' + str(msubject) + '\n\n' + str(mbody))
49  elif isinstance(mto, list) :
50  for onemto in mto :
51  print("\t- %s"% (onemto))
52  con.sendmail(mfrom, onemto, 'Subject:' + str(msubject) + '\n\n' + str(mbody))
53  con.quit()
54  except OSError as e:
55  print("ERROR: Failed sending email notification\n",e)
56  exit(e.errno)
57 
58 
59 def fromRunArgs(runArgs):
60 
61 
62  nextstep("UNTAR files")
63 
64 
65  print("Uncompressing files:")
66  try:
67  for file in runArgs.inputTARFile:
68  print("\t-",file)
69  tarfile.open(file).extractall(".")
70  except OSError as e:
71  print("ERROR: Failed uncompressing TAR file\n",e)
72  sys.exit(e.errno)
73 
74 
75  nextstep("Filtering files")
76 
77 
78  # RT files (nor merging barrel)
79  files_list_rt =[item for item in glob.glob("*_rt.txt") if "barrel" not in item]
80  files_list_t0 =[item for item in glob.glob("*_t0.txt") if "barrel" not in item]
81  files_list_cal=[item for item in glob.glob("*calibout.root") if "barrel" not in item]
82  # tracks
83  files_list_trk=glob.glob("*tracktuple.root")
84  # straws
85  files_list_stw=glob.glob("*merged.straw.txt")
86  # constants
87  files_list_ctn=glob.glob("*calib_constants_out.txt")
88 
89  def listFiles(v,txt=""):
90  print("Number of files for %s: %i" % (txt,len(v)))
91 
92  if not v:
93  print("ERROR: list of files for %s is empty" % (txt) )
94  sys.exit(1)
95 
96  for i in v:
97  print("\t-%s: %s" % (txt,i))
98 
99  listFiles(files_list_rt ,"RT")
100  listFiles(files_list_t0 ,"T0")
101  listFiles(files_list_cal,"Cal")
102  listFiles(files_list_trk,"Track")
103  listFiles(files_list_stw,"Straws")
104  listFiles(files_list_ctn,"Constants")
105 
106 
107  nextstep("Merging Rt and t0 files")
108 
109 
110  command = "touch calibout.txt ;"
111  command += " echo '# Fileformat=2' >> calibout.txt ; "
112  command += " echo '# RtRelation' >> calibout.txt ; "
113 
114  # Merging Rt files
115  for _f in files_list_rt :
116  command += "cat %s >> calibout.txt ; " % (_f)
117 
118  command += " echo '# StrawT0' >> calibout.txt ; "
119 
120  # Merging t0 files
121  for _f in files_list_t0 :
122  command += "cat %s >> calibout.txt ; " % (_f)
123 
124  # add footer
125  command += " echo '#GLOBALOFFSET 0.0000' >> calibout.txt ; "
126 
127  if os.path.isfile("calibout.txt"):
128  print("calibout.txt.. already exists. Removed.")
129  os.remove("calibout.txt")
130 
131  tryError(command,"ERROR: Not able to merge the Rt and t0 files\n")
132 
133 
134 
135  nextstep("Merging constants files")
136 
137 
138  command = " touch oldt0s.txt ;"
139  for _f in files_list_ctn :
140  command += "cat %s >> oldt0s.txt ; " % (_f)
141 
142  if os.path.isfile("oldt0s.txt"):
143  print("oldt0s.txt.. already exists. Removed.")
144  os.remove("oldt0s.txt")
145 
146  tryError(command,"ERROR: Not able to merge the Rt and t0 files\n")
147 
148 
149 
150  nextstep("Shift text file")
151 
152 
153  command = 'TRTCalib_cfilter.py calibout.txt calibout.txt oldt0s.txt shiftrt'
154 
155  tryError(command,"ERROR: Failed in process TRTCalib_cfilter\n")
156 
157 
158  nextstep("Run hadd to merge root files")
159 
160 
161  # Removing the output file if it exists to avoid problems
162  if os.path.isfile("merge.root"):
163  print("merge.root.. already exists. Removed.")
164  os.remove("merge.root")
165 
166  command = 'hadd merge.root '
167  # merge all the files
168  for _f in files_list_cal :
169  command += "%s " % (_f)
170  # and track tuple, we just need the first one since they are all the same
171  command += "%s " % files_list_trk[0]
172 
173  tryError(command,"ERROR: Failed in process hadd\n")
174 
175 
176  nextstep("Rename root files")
177 
178 
179  outputFile = runArgs.outputTAR_MERGEDFile
180  runNumber = int(runArgs.inputTARFile[0].split('.')[1])
181 
182  # Rename calibout.txt and merge.root
183  command = "mv -v calibout.txt %s.calibout.txt ; " % outputFile
184  command += "mv -v merge.root %s.merge.root ; " % outputFile
185  # only one straw file is needed
186  command += "mv -v %s straws.%d.txt ; " % (files_list_stw[0], runNumber)
187  # copy also db const
188  command += "mv -v dbconst.txt %s.dbconst.txt" % outputFile
189 
190  tryError(command,"ERROR: Failed in process hadd\n")
191 
192 
193  nextstep("Make all plots")
194 
195 
196  # generating the .ps file
197  command = "TRTCalib_makeplots itersum %s.merge.root %s/lastconfigfile" % (outputFile, os.path.abspath('.'))
198 
199  tryError(command,"ERROR: Failed in creating plots (itersum.ps file)\n")
200 
201 
202  nextstep("converting ps to pdf")
203 
204 
205  command = "ps2pdf itersum.ps %s.itersum.pdf" % (outputFile)
206 
207  tryError(command,"ERROR: Failed in creating itersum.pdf from itersum.ps)\n")
208 
209 
210  nextstep("Straw status Report")
211 
212 
213  command = "mkdir -p -v output/ ; TRTCalib_StrawStatusReport %d" % (runNumber)
214 
215  tryError(command,"ERROR: Failed running TRTCalib_StrawStatusReport.cxx\n")
216 
217 
218  nextstep("Straw status plots (root macro)")
219 
220 
221  from ROOT import PathResolver
222  command = "root -l -b -q %s" % (PathResolver.FindCalibFile("TRT_CalibAlgs/TRTCalib_StrawStatusReport.C"))
223 
224  tryError(command,"ERROR: Failed running root macro TRTCalib_StrawStatusReport.C\n")
225 
226 
227  nextstep("TAR'ing files")
228 
229 
230  try:
231  # Getting list of files to be compressed
232  files_list=glob.glob(outputFile+".*")
233  # Compressing
234  tar = tarfile.open(outputFile, "w:gz")
235  print("\nCompressing files in %s output file:" % outputFile)
236  for file in files_list:
237  print("\t-",file)
238  tar.add(file)
239  tar.close()
240  except OSError as e:
241  print("ERROR: Failed compressing the output files\n",e)
242  sys.exit(e.errno)
243 
244 
245 
246  nextstep("Copying files to AFS Directory")
247 
248 
249  outDIR = "%s/run_%d" % (runArgs.attrtcal_dir, runNumber)
250 
251  # Extracting iteration from Tier0 and for emails
252  outputFile_split = outputFile.split('.')
253  itera = '9999' # default iteration for testing only
254  if len(outputFile_split) > 5:
255  if "iter" in outputFile_split[5]:
256  itera = (outputFile_split[5])[-1:] # e.g. data14_cos.00247236.express_express.trtcal.TXT.iter1 --> '1'
257 
258  command = "mkdir -p -v %s ; " % (outDIR)
259  command += "cp -v %s.merge.root %s/trtcalib_0%s_histograms.root ; " % (outputFile, outDIR, itera)
260  command += "cp -v %s.calibout.txt %s/calibout.%d.NoShifted.txt ; " % (outputFile, outDIR, runNumber)
261  command += "cp -v %s.itersum.pdf %s/Plots.%d.pdf ; " % (outputFile, outDIR, runNumber)
262  command += "cp -v %s.dbconst.txt %s/dbconst.%d.txt ; " % (outputFile, outDIR, runNumber)
263  command += "cp -v %s.dbconst.txt %s/calibout.%d.txt ; " % (outputFile, outDIR, runNumber)
264  command += "cp -v straws.%d.txt %s/straws.%d.txt; " % (runNumber, outDIR, runNumber)
265  command += "cp -v TRT_StrawStatusReport.txt %s/TRT_StrawStatusReport.%d.txt; " % (outDIR, runNumber)
266  command += "cp -v allPlots.pdf %s/TRT_StrawStatusReport.%d.pdf; " % (outDIR, runNumber)
267 
268  tryError(command,"ERROR: Files cannot be copied to the chosen directory\n")
269 
270 
271 
272 
273  nextstep("Extractor information")
274 
275 
276  command = "python -m TRT_CalibAlgs.TRTCalib_Extractor %s/trtcalib_0%s_histograms.root > %s/extraction.txt" % (outDIR, itera, outDIR)
277 
278  tryError(command,"ERROR: Extracting information for email notification\n")
279 
280 
281  nextstep("Email notification")
282 
283 
284  res_ba = 0 ; tres_ba = 0
285  res_bc = 0 ; tres_bc = 0
286  res_ea = 0 ; tres_ea = 0
287  res_ec = 0 ; tres_ec = 0
288 
289  try:
290  with open("%s/extraction.txt" % (outDIR)) as exfile:
291  for line in exfile :
292  if fnmatch.fnmatch(line,'* res *') and fnmatch.fnmatch(line, '*part 1*') :
293  res_ba = line.split()[6]
294  if fnmatch.fnmatch(line,'* tresmean *') and fnmatch.fnmatch(line, '*part 1*') :
295  tres_ba = line.split()[6]
296  if fnmatch.fnmatch(line,'* res *') and fnmatch.fnmatch(line, '*part -1*') :
297  res_bc = line.split()[6]
298  if fnmatch.fnmatch(line,'* tresmean *') and fnmatch.fnmatch(line, '*part -1*') :
299  tres_bc = line.split()[6]
300  if fnmatch.fnmatch(line,'* res *') and fnmatch.fnmatch(line, '*part 2*') :
301  res_ea = line.split()[6]
302  if fnmatch.fnmatch(line,'* tresmean *') and fnmatch.fnmatch(line, '*part 2*') :
303  tres_ea = line.split()[6]
304  if fnmatch.fnmatch(line,'* res *') and fnmatch.fnmatch(line, '*part -2*') :
305  res_ec = line.split()[6]
306  if fnmatch.fnmatch(line,'* tresmean *') and fnmatch.fnmatch(line, '*part -2*') :
307  tres_ec = line.split()[6]
308  except OSError as e:
309  print("ERROR: Failed reading %s/extraction.txt file\n" % (outDIR) ,e)
310  sys.exit(e.errno)
311 
312  if runArgs.sendNotification and runArgs.emailList :
313  send_statusmail(itera, runNumber, runArgs.emailList, outDIR, res_ba, tres_ba, res_bc, tres_bc, res_ea, tres_ea, res_ec, tres_ec)
314  else:
315  print("INFO: No email notification sent since --sendNotification=%r or empty --emailList=" % (runArgs.sendNotification), runArgs.emailList)
316 
PathResolver::FindCalibFile
static std::string FindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.h:108
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
TRTCalib_last_Skeleton.nextstep
def nextstep(text)
Definition: TRTCalib_last_Skeleton.py:5
TRTCalib_last_Skeleton.fromRunArgs
def fromRunArgs(runArgs)
Definition: TRTCalib_last_Skeleton.py:59
TRTCalib_last_Skeleton.tryError
def tryError(command, error)
Definition: TRTCalib_last_Skeleton.py:12
calibdata.exit
exit
Definition: calibdata.py:236
Trk::open
@ open
Definition: BinningType.h:40
TRTCalib_last_Skeleton.send_statusmail
def send_statusmail(itera, runNumber, mto, outdir, a, b, c, d, e, f, g, h)
Definition: TRTCalib_last_Skeleton.py:25
str
Definition: BTagTrackIpAccessor.cxx:11
dbg::print
void print(std::FILE *stream, std::format_string< Args... > fmt, Args &&... args)
Definition: SGImplSvc.cxx:70
Trk::split
@ split
Definition: LayerMaterialProperties.h:38