BmnRoot
Loading...
Searching...
No Matches
iterate_reco_align_bmn.py
Go to the documentation of this file.
1# -----------------------------------------------------------------------------
2# Script for finding global alignment corrections iteratively.
3#
4# Reconstruct limited number of events -> run alignment -> run new
5# reconstruction of the same events using corrections obtained at the previous
6# iteration and run the alignment again, and so on, until either corrections
7# become small or the maximal number of iterations is reached. Namely, if
8# maxNumOfIterations==1, then the subset reconstruction run and alignment are
9# run only once i.e. iterativity is degenerate. The obtained corrections then
10# simply used for the full reconstruction run. But starting from
11# maxNumOfIterations==2 the subset reconstruction run and alignment may be run
12# up to maxNumOfIterations times.
13#
14# After each iteration, starting from the second, the newly obtained
15# corrections are added to the existing cumulative corrections that will
16# eventually be used for the full reconstruction run.
17#
18# Now, when to stop? There are several possibilities:
19#
20# 1. a trivial one is to stop at maxNumOfIterations which does not make much
21# sense, of course;
22#
23# 2. relatively cheap, but evidently not perfect, is to stop when the newly
24# obtained corrections are <= their errors;
25#
26# 3. when track reconstruction precision reaches its plateau at a given set of
27# all other conditions; this is perfect, but not so easy to formulate and
28# implement; note, that this approach will generally stop earlier!
29#
30# digiFileName - input file with digis, like file_digi.root. To process
31# experimental data, you can use 'runN-NNN:' prefix, e.g.
32# "run5-458:../digits_run5/bmn_run0458_digi.root"
33# then the geometry is obtained from the Unified Database.
34#
35#
36
60import os
61import re
62import sys
63from optparse import OptionParser
64from distutils import dir_util
65from os.path import expandvars
66from subprocess import *
67from time import sleep
68from time import time
69from time import gmtime, strftime
70import __builtin__
71
72def main() :
73 usage = "usage: %prog [options] arg"
74 parser = OptionParser(usage)
75 parser.add_option("-v", "--verbose", dest="verbose", default=True, help="print this to stdout")
76 parser.add_option("-l", "--list", dest="digiFileListFileName", default='bmn_run06_Glob_digi_filelist.txt', help="take list of digi files from file")
77 parser.add_option("-m", "--maxit", dest="maxNumOfIterations", default=1, help="maximum number of iterations", type="int")
78 parser.add_option("-n", "--nev", dest="nEvents", default=10000, help="number of events to process", type="int")
79 parser.add_option("-i", "--inf", dest="addInfo", default='', help="additional meta-information")
80 parser.add_option("-c", "--corr", dest="startAlignCorrFileName", default='default', help="file name with the starting alignment corrections")
81 (options, args) = parser.parse_args()
82 if options.verbose :
83 print "reading %s..." % options.digiFileListFileName
84 # Here we start iterations, each consisting of these steps:
85 #
86 # 1. reconstruction, either using only geometry from the database
87 # (optionally updated using default or special set of corrections), or
88 # (starting from the 2-nd iteration) additionally updateing it with the
89 # cumulative misalignment corrections updated after each alignment iteration;
90 #
91 # 2. obtaining the misalignment values;
92 #
93 # 3. updating the cumulative misalignment values;
94 #
95 # 4. checking whether this is the last iteration, according to a certain
96 # criterion (TBD).
97 #
98 # maxNumOfIterations is the brutal-force limit.
99
100 # First store the list of digi fileas in vector digiFileNames,
101 # so that the file with their list is read only once.
102 #
103 # Open file with list of input digi files chosen for running the alignment
104 # and store them line-by-line in a list:
105 print 'options.digiFileListFileName = '+options.digiFileListFileName
106 digiFileNames = [line.rstrip('\n') for line in open(options.digiFileListFileName)]
107
108 # Define name of the file that contains up-to-date cumulative misalignment
109 # compensations i.e. initial one (e.g. taken from UniDB) and updated with
110 # new compensation corrections resulting from all preceeding iterations of
111 # this alignment session.
112 #
113 # At the first iteration (we start from 1), the reconstruction does not use
114 # any newly obtained corrections, as they do not exist yet.
115 # It can use the fefault ones, or some special ones, or not use any.
116 if options.startAlignCorrFileName != '' :
117 # In this case the reconstruction will use concrete initial set of
118 # corrections, e.g. current default corrections, when
119 # options.startAlignCorrFileName == '$VMCWORKDIR/input/alignCorrsLocal_GEM.root'
120 #
121 # For the machinery to work correctly, we copy the initial corrections
122 # to an appropriately named file marked as '_it00'.
123 # First form the name:
124 if options.addInfo != '' :
125 sumAlignCorrFileName = options.digiFileListFileName.replace('digi_filelist.txt', options.addInfo+'_sum_align_it00.root')
126 else :
127 sumAlignCorrFileName = options.digiFileListFileName.replace('digi_filelist.txt', 'sum_align_it00.root')
128 # and now create the file with that name:
129 print 'options.startAlignCorrFileName = '+options.startAlignCorrFileName
130 #os.system('cp '+options.startAlignCorrFileName+' '+sumAlignCorrFileName)
131 call([ 'cp', options.startAlignCorrFileName, sumAlignCorrFileName])
132 else :
133 # or we can also set it empty, just keep default
134 # options.startAlignCorrFileName == '', if we want to run the alignment
135 # form scratch;
136 #
137 # in this case a regular sumAlignCorrFileName file will be created only
138 # at the end of the 1-st iteration;
139 #
140 # as to the reconstruction, for the BmnGemStripHitMaker, '' means that
141 # no alignment corrections are to be used this time:
142 sumAlignCorrFileName = ''
143 preAlignCorrFileName = '' # just for consistency
144 newAlignCorrFileName = '' # just for consistency
145 print 'preAlignCorrFileName = '+preAlignCorrFileName
146 print 'newAlignCorrFileName = '+newAlignCorrFileName
147 print 'sumAlignCorrFileName = '+sumAlignCorrFileName
148
149 # file for storing names of files with new corrections
150 if options.addInfo != '' :
151 newAlignCorrFileListFileName = options.digiFileListFileName.replace('digi', options.addInfo+'_new_align')
152 else :
153 newAlignCorrFileListFileName = options.digiFileListFileName.replace('digi', 'new_align')
154 print 'newAlignCorrFileListFileName = '+newAlignCorrFileListFileName
155 # file for storing names of files with sum corrections
156 sumAlignCorrFileListFileName = newAlignCorrFileListFileName.replace('new_', 'sum_')
157 print 'sumAlignCorrFileListFileName = '+sumAlignCorrFileListFileName
158
163
164 # file for storing the plots
165 if options.addInfo != '' :
166 alignCorrPlotsFileName = options.digiFileListFileName.replace('digi_filelist.txt', options.addInfo+'_corr_plots.root')
167 else :
168 alignCorrPlotsFileName = options.digiFileListFileName.replace('digi_filelist.txt', 'corr_plots.root')
169 print 'alignCorrPlotsFileName = '+alignCorrPlotsFileName
170
171 newAlignCorrFileNames = []
172 sumAlignCorrFileNames = []
173 #newAlignCorrFileNames.append(newAlignCorrFileName+'\n')
174 #sumAlignCorrFileNames.append(sumAlignCorrFileName+'\n')
175 # Main loop of iterations.
176
177 # Note that iteration numbering starts with 1,
178 # --------------------------------------------
179
180 # because when things are denoted with it01, it means that they result from
181 # first round of calculations:
182 for iterNr in xrange(1, options.maxNumOfIterations+1) :
183 itNr = str(iterNr).rjust(2, '0') # '1' becomes '01' and so on
184 # The reconstruction is run file-by-file in the following loop below,
185 # and the subsequent alignment corrections are produced using the whole
186 # chain of the newly produced bmndst files with the reconstructed
187 # events.
188
189 # We will need a list for storing bmndstFileName's at the current
190 # iteration:
191 bmndstFileNames = []
192
193 # Run reconstruction on limited number of events from each digi file
194 # from the digiFileNames list
195 # counter of total events processed for the alignment:
196 nEventsTotal = 0
197 for digiFileName in digiFileNames :
198 print 'reconstruction starting'
199 print 'digiFileName = '+digiFileName
200 # Derive bmndstFileName from digiFileListFileName,
201 # adding addInfo and runNumber, extracted from digiFileName:
202 # bmn_run06_Glob_tilted_beams_digi_filelist.txt --> 'bmn_run06_Glob_tilted_beams_test_bmndst_001203_it01.root'
203 # First extract the run number:
204 runNumber = re.search('digi_([\d]+)', digiFileName).group(1)
205 if options.addInfo != '' :
206 bmndstFileName = options.digiFileListFileName.replace('digi_filelist.txt', options.addInfo+'_bmndst_'+runNumber+'_it'+itNr+'.root')
207 else :
208 bmndstFileName = options.digiFileListFileName.replace('digi_filelist.txt', 'bmndst_'+runNumber+'_it'+itNr+'.root')
209 print 'bmndstFileName = '+bmndstFileName
210 # and memorise it in the list that will be used during alignment:
211 bmndstFileNames.append(bmndstFileName+'\n')
212
213 # run the reconstruction
214 print 'digiFileName = '+digiFileName
215 print 'bmndstFileName = '+bmndstFileName
216 print 'startng event = '+str(0)
217 print 'number of events to process = '+str(options.nEvents)
218 print 'sumAlignCorrFileName = '+sumAlignCorrFileName
219 call(['root', '-l', '-q', '$VMCWORKDIR/macro/run/run_reco_bmn.C("'+digiFileName+'", "'+bmndstFileName+'", '+str(0)+', '+str(options.nEvents)+', "'+sumAlignCorrFileName+'")'])
220 # count total number of events processed for the alignment:
221 nEventsTotal += options.nEvents
222 print 'reconstruction ended'
223 # We also prepare a file with the list of these files inside the loop.
224 # It will be used to create a chain inside the determine_align_corrections_bmn.C
225
226 # Form name of file with the list of bmndstFileName's:
227 # replace digi with bmndst and add addInfo and itNr,
228 # e.g. 'bmn_run06_Glob_tilted_beams_digi_filelist.txt' --> 'bmn_run06_Glob_tilted_beams_test_bmndst_filelist_it01.txt'
229 if options.addInfo != '' :
230 bmndstFileListFileName = options.digiFileListFileName.replace('digi_filelist', options.addInfo+'_bmndst_filelist_it'+itNr)
231 else :
232 bmndstFileListFileName = options.digiFileListFileName.replace('digi_filelist', 'bmndst_filelist_it'+itNr)
233 print 'bmndstFileListFileName = '+bmndstFileListFileName
234 # create file with the list of new bmndstFileName's:
235 with open(bmndstFileListFileName, 'w') as f :
236 for fname in bmndstFileNames :
237 f.write(fname)
238
239 # Form name of the new alignment output file:
240 # e.g. 'bmn_run06_Glob_tilted_beams_test_bmndst_filelist_it01.txt' --> 'bmn_run06_Glob_tilted_beams_test_new_align_it01.root'
241 newAlignCorrFileName = bmndstFileListFileName.replace('bmndst_filelist', 'new_align')
242 newAlignCorrFileName = newAlignCorrFileName.replace('.txt', '.root')
243 print 'newAlignCorrFileName = '+newAlignCorrFileName
244
245 # And now run the alignment:
246 print 'alignment starting'
247 call(['root', '-l', '-q', '$VMCWORKDIR/macro/alignment/determine_align_corrections_bmn.C("'+bmndstFileListFileName+'", "'+newAlignCorrFileName+'", '+str(nEventsTotal)+')'])
248 print 'alignment ended'
249 # preserve the Millepede.res result:
250 # 'bmn_run06_Glob_tilted_beams_test_new_align_it01.root' --> 'bmn_run06_Glob_tilted_beams_test_new_align_millepede_it01.res'
251 pedeResultFileName = newAlignCorrFileName.replace('align', 'align_millepede')
252 pedeResultFileName = pedeResultFileName.replace('.root', '.res')
253 print 'pedeResultFileName = '+newAlignCorrFileName
254 call(['cp', 'Millepede.res', pedeResultFileName])
255 # the already used for the reconstruction sumAlignCorrFileName
256 # now becomes the previous one:
257 preAlignCorrFileName = sumAlignCorrFileName
258 sumAlignCorrFileName = newAlignCorrFileName.replace('new_', 'sum_')
259 print 'preAlignCorrFileName = '+preAlignCorrFileName
260 print 'newAlignCorrFileName = '+newAlignCorrFileName
261 print 'sumAlignCorrFileName = '+sumAlignCorrFileName
262 if iterNr==1 and options.startAlignCorrFileName=='' : # if we started from from scratch, newAlignCorrFileName becomes also new sumAlignCorrFileName
263 call(['cp', newAlignCorrFileName, sumAlignCorrFileName])
264 print 'cp newAlignCorrFileName sumAlignCorrFileName'
265 else : # update sumAlignCorrFileName file and at next iteration use it
266 print 'update_align_corrections_bmn.C starting'
267 call(['root', '-l', '-q', '$VMCWORKDIR/macro/alignment/update_align_corrections_bmn.C("'+preAlignCorrFileName+'", "'+newAlignCorrFileName+'", "'+sumAlignCorrFileName+'")'])
268 print 'update_align_corrections_bmn.C ended'
269
270 newAlignCorrFileNames.append(newAlignCorrFileName+'\n')
271 sumAlignCorrFileNames.append(sumAlignCorrFileName+'\n')
272
273 # the iteration loop is finished
274 # add file names with new and sum corrections to the respective lists
275 with open(newAlignCorrFileListFileName, 'w') as f :
276 for fname in newAlignCorrFileNames :
277 f.write(fname)
278 with open(sumAlignCorrFileListFileName, 'w') as f :
279 for fname in sumAlignCorrFileNames :
280 f.write(fname)
281
282 # plot new and sum corrections vs. iteration number, beginning with the start values of sum corrections (at the so-called 'itertaion 0')
283 call(['root', '-l', '-q', '$VMCWORKDIR/macro/alignment/plot_align_corrections_bmn.C("'+newAlignCorrFileListFileName+'")'])
284
285if __name__ == "__main__" :
286 main()