10 Full Simultaneous Global and Local VXD and CDC alignment with Millepede II
12 The input collections are:
13 - cosmics (hlt skim) - mandatorry
14 - hadron - for "low" momentum tracks from IP
15 - mumu - mumu_2trk or mumu_tight - for high momentum tracks from IP
16 - offip - tracks from outside IP (beam background, beam-gas)
23 from prompt
import CalibrationSettings, INPUT_DATA_FILTERS
24 from prompt.calibrations.caf_cdc
import settings
as cdc_calibration
25 from prompt.calibrations.caf_svd_time
import settings
as svd_time_calibration
28 from caf.utils
import IoV
29 from caf
import strategies
33 import reconstruction
as reco
34 import modularAnalysis
as ana
37 from random
import choice
38 from random
import seed
40 import millepede_calibration
as mpc
45 collection_names = [
"cosmic",
"hadron",
"mumu",
"offip"]
49 "cosmic.max_processed_events_per_file": 4000,
50 "hadron.max_processed_events_per_file": 1000,
51 "mumu.max_processed_events_per_file": 5000,
52 "offip.max_processed_events_per_file": 2000,
53 "stage1.method":
"decomposition"
56 quality_flags = [INPUT_DATA_FILTERS[
"Run Type"][
"physics"],
57 INPUT_DATA_FILTERS[
"Data Quality Tag"][
"Good Or Recoverable"],
58 INPUT_DATA_FILTERS[
"Magnet"][
"On"]]
61 settings = CalibrationSettings(name=
"Full VXD and CDC Alignment",
62 expert_username=
"bilkat",
64 input_data_formats=[
"raw"],
65 input_data_names=collection_names,
67 "cosmic": [INPUT_DATA_FILTERS[
"Data Tag"][
"cosmic_calib"]] + quality_flags,
68 "mumu": [INPUT_DATA_FILTERS[
"Data Tag"][
"mumu_tight_or_highm_calib"]] + quality_flags,
69 "hadron": [INPUT_DATA_FILTERS[
"Data Tag"][
"hadron_calib"]] + quality_flags,
70 "offip": [INPUT_DATA_FILTERS[
"Data Tag"][
"offip_calib"]] + quality_flags
73 expert_config=default_config,
74 depends_on=[cdc_calibration, svd_time_calibration])
77 def select_files(all_input_files, min_events, max_processed_events_per_file):
83 all_input_files : list(str)
84 List of all input file names
86 Minimum number of events to select from files
87 max_processed_events_per_file : int
88 Maximum number of events to consider per file
90 all_input_files = all_input_files[:]
94 while total_events < min_events:
97 if not all_input_files:
100 new_file_choice = choice(all_input_files)
102 all_input_files.remove(new_file_choice)
104 total_events_in_file = events_in_basf2_file(new_file_choice)
105 if not total_events_in_file:
109 events_contributed = min(total_events_in_file, max_processed_events_per_file)
111 chosen_files.append(new_file_choice)
112 total_events += events_contributed
114 basf2.B2INFO(f
"Total chosen files = {len(chosen_files)}")
115 basf2.B2INFO(f
"Total events in chosen files = {total_events}")
116 if total_events < min_events:
118 f
"There weren't enough files events selected when max_processed_events_per_file={max_processed_events_per_file}")
122 def create_std_path():
124 Returns default path for collections with standard reconstruction
126 path = basf2.create_path()
127 path.add_module(
'Progress')
128 path.add_module(
'RootInput')
129 path.add_module(
'Gearbox')
130 path.add_module(
'Geometry')
131 raw.add_unpackers(path)
132 path.add_module(
'SetupGenfitExtrapolation')
133 reco.add_reconstruction(
136 skipGeometryAdding=
True,
138 path.add_module(
'DAFRecoFitter')
142 def create_cosmics_path():
144 Returns default path for cosmic collection
146 path = basf2.create_path()
147 path.add_module(
'Progress')
148 path.add_module(
'RootInput')
149 path.add_module(
'Gearbox')
150 path.add_module(
'Geometry')
152 raw.add_unpackers(path)
153 path.add_module(
'SetupGenfitExtrapolation')
154 reco.add_cosmics_reconstruction(
157 skipGeometryAdding=
True,
158 addClusterExpertModules=
False,
162 path.add_module(
'SetRecoTrackMomentum', automatic=
True)
163 path.add_module(
'DAFRecoFitter', pdgCodesToUseForFitting=[13])
165 ana.fillParticleList(
166 'mu+:goodForVXDCDCAlignment',
167 '[z0 <= 57. or abs(d0) >= 26.5] and abs(dz) > 0.4 and nTracks == 1',
169 path.add_module(
'SkimFilter', particleLists=[
'mu+:goodForVXDCDCAlignment']).if_false(basf2.create_path())
174 def make_mumu_collection(
177 muon_cut='p > 1.0 and abs(dz) < 2.0
and dr < 0.5
and nTracks==2
', dimuon_cut='9.5 < M and M < 11.',
180 Di-muons with vertex+beam constraint collection
187 List of input data files
189 Cut string to select daughter muons
191 Cut string to apply for reconstructed di-muon decay
193 Process only 'prescale' fraction of events
195 path = basf2.create_path()
196 path.add_module(
'Progress')
197 path.add_module(
'RootInput')
199 path.add_module(
'Prescale', prescale=prescale).if_false(basf2.Path(), basf2.AfterConditionPath.END)
201 path.add_module(
'Gearbox')
202 path.add_module(
'Geometry')
204 raw.add_unpackers(path)
206 reco.add_reconstruction(path, pruneTracks=
False)
208 path.add_module(
'DAFRecoFitter', pdgCodesToUseForFitting=[13])
210 ana.fillParticleList(f
"mu+:{name}", muon_cut, path=path)
211 ana.reconstructDecay(f
"Upsilon(4S):{name} -> mu+:{name} mu-:{name}", dimuon_cut, path=path)
213 vtx.raveFit(f
"Upsilon(4S):{name}", 0.001, daughtersUpdate=
True, silence_warning=
True, path=path, constraint=
"ipprofile")
219 primaryVertices=[f
"Upsilon(4S):{name}"])
222 def create_prompt(files, cfg):
224 Returns configured (original) prompt stage alignment
229 Dictionary with all input files by category (name)
231 Expert config dictionary
233 mumu = select_files(files[
"mumu"], 0.2e6, cfg[
"mumu.max_processed_events_per_file"])
234 cosmic = select_files(files[
"cosmic"], 1e6, cfg[
"cosmic.max_processed_events_per_file"])
235 hadron = select_files(files[
"hadron"], 0.5e5, cfg[
"hadron.max_processed_events_per_file"])
236 offip = select_files(files[
"offip"], 0.2e6, cfg[
"offip.max_processed_events_per_file"])
239 name=
'VXDCDCalignment_prompt',
240 dbobjects=[
'VXDAlignment',
'CDCAlignment'],
242 mpc.make_collection(
"cosmic", path=create_cosmics_path(), tracks=[
"RecoTracks"]),
243 mpc.make_collection(
"hadron", path=create_std_path(), tracks=[
"RecoTracks"]),
244 mpc.make_collection(
"mumu", path=create_std_path(), tracks=[
"RecoTracks"]),
245 mpc.make_collection(
"offip", path=create_std_path(), tracks=[
"RecoTracks"])
248 files=dict(mumu=mumu, cosmic=cosmic, hadron=hadron, offip=offip),
256 "method diagonalization 3 0.1",
259 params=dict(minPValue=0.00001, externalIterations=0, granularity=
"run"),
262 cal.max_iterations = 5
267 def create_beamspot(files, cfg):
269 Returns configured beamspot calibration
274 Dictionary with all input files by category (name)
276 Expert config dictionary
279 mumu = select_files(files[
"mumu"], 10e6, cfg[
"mumu.max_processed_events_per_file"])
284 from ROOT.Belle2
import BeamSpotAlgorithm
285 from basf2
import create_path, register_module
290 from caf.framework
import Calibration, Collection
291 from caf.strategies
import SingleIOV
296 path.add_module(
'Progress')
297 path.add_module(
'RootInput')
298 path.add_module(
'Gearbox')
299 path.add_module(
'Geometry')
300 raw.add_unpackers(path)
301 path.add_module(
'SetupGenfitExtrapolation')
302 reco.add_reconstruction(path, skipGeometryAdding=
True)
304 muSelection =
'[p>1.0]'
305 muSelection +=
' and abs(dz)<2.0 and abs(dr)<0.5'
306 muSelection +=
' and nPXDHits >=1 and nSVDHits >= 8 and nCDCHits >= 20'
307 ana.fillParticleList(
'mu+:BS', muSelection, path=path)
308 ana.reconstructDecay(
'Upsilon(4S):BS -> mu+:BS mu-:BS',
'9.5<M<11.5', path=path)
310 collector_bs = register_module(
'BeamSpotCollector', Y4SPListName=
'Upsilon(4S):BS')
311 algorithm_bs = BeamSpotAlgorithm()
315 collection_bs =
Collection(collector=collector_bs,
317 pre_collector_path=path)
319 calibration_bs =
Calibration(
'VXDCDCalignment_beamspot', algorithms=algorithm_bs)
320 calibration_bs.add_collection(
"mumu", collection_bs)
322 calibration_bs.strategies = SingleIOV
324 return calibration_bs
327 def create_stage1(files, cfg):
329 Returns configured stage1 alignment (full constant alignment with wires, beamspot fixed)
334 Dictionary with all input files by category (name)
336 Expert config dictionary
339 mumu = select_files(files[
"mumu"], 1.5e6, cfg[
"mumu.max_processed_events_per_file"])
340 cosmic = select_files(files[
"cosmic"], 0.7e6, cfg[
"cosmic.max_processed_events_per_file"])
341 hadron_and_offip = select_files(files[
"hadron"] + files[
"offip"], int(4.0e6 / 10.), cfg[
"hadron.max_processed_events_per_file"])
344 name=
'VXDCDCalignment_stage1',
345 dbobjects=[
'VXDAlignment',
'CDCAlignment',
'BeamSpot'],
347 mpc.make_collection(
"cosmic", path=create_cosmics_path(), tracks=[
"RecoTracks"]),
348 mpc.make_collection(
"hadron", path=create_std_path(), tracks=[
"RecoTracks"]),
349 make_mumu_collection(name=
"mumu")
352 files=dict(mumu=mumu, cosmic=cosmic, hadron=hadron_and_offip),
362 f
"method {cfg['stage1.method']} 6 0.001",
365 params=dict(minPValue=0.00001, externalIterations=0, granularity=
"run"),
369 std_components = ROOT.vector(
'string')()
370 for component
in [
'VXDAlignment',
'CDCAlignment']:
371 std_components.push_back(component)
372 cal.algorithms[0].algorithm.setComponents(std_components)
374 cal.max_iterations = 0
379 def create_stage2(files, cfg):
381 Returns configured stage2 alignment (run-dependent alignment)
386 Dictionary with all input files by category (name)
388 Expert config dictionary
390 mumu = select_files(files[
"mumu"], 10e6, cfg[
"mumu.max_processed_events_per_file"])
391 cosmic = select_files(files[
"cosmic"], 2e6, cfg[
"cosmic.max_processed_events_per_file"])
394 name=
'VXDCDCalignment_stage2',
395 dbobjects=[
'VXDAlignment',
'CDCAlignment',
'BeamSpot'],
397 mpc.make_collection(
"cosmic", path=create_cosmics_path(), tracks=[
"RecoTracks"]),
398 make_mumu_collection(name=
"mumu")],
400 files=dict(mumu=mumu, cosmic=cosmic),
407 commands=[
"method inversion 6 0.001",
"entries 1000",
"threads 10 10"],
408 params=dict(minPValue=0.00001, externalIterations=0, granularity=
"run"),
412 std_components = ROOT.vector(
'string')()
413 for component
in [
'VXDAlignment',
'CDCAlignment']:
414 std_components.push_back(component)
415 cal.algorithms[0].algorithm.setComponents(std_components)
418 cal.max_iterations = 0
419 cal.algorithms[0].strategy = strategies.SequentialRunByRun
428 def get_calibrations(input_data, **kwargs):
430 Required function called by b2caf-prompt-run.
431 Returns full configured 4-stage final alignment for prompt
436 cfg = kwargs[
'expert_config']
439 for colname
in collection_names:
440 file_to_iov = input_data[colname]
441 input_files = list(file_to_iov.keys())
442 files[colname] = input_files
444 prompt = create_prompt(files, cfg)
445 beamspot = create_beamspot(files, cfg)
446 stage1 = create_stage1(files, cfg)
447 stage2 = create_stage2(files, cfg)
449 requested_iov = kwargs.get(
"requested_iov",
None)
450 output_iov = IoV(requested_iov.exp_low, requested_iov.run_low, -1, -1)
452 for cal
in [prompt, beamspot, stage1, stage2]:
453 for colname
in collection_names:
454 if colname
not in cal.collections.keys():
456 max_processed_events_per_file = cfg[f
'{colname}.max_processed_events_per_file']
457 basf2.set_module_parameters(
458 cal.collections[colname].pre_collector_path,
460 entrySequences=[f
'0:{max_processed_events_per_file}'], branchNames=HLT_INPUT_OBJECTS)
462 for algorithm
in cal.algorithms:
463 algorithm.params = {
"apply_iov": output_iov}
466 for cal
in [prompt, stage1, stage2]:
468 fix_mille_paths_for_algo(cal.algorithms[0])
470 beamspot.depends_on(prompt)
471 stage1.depends_on(beamspot)
472 stage2.depends_on(stage1)
476 beamspot.save_payloads =
False
478 if cfg[
"only_prompt"]:
481 return [prompt, beamspot, stage1, stage2]
484 if __name__ ==
'__main__':
485 get_calibrations(dict(cosmic=dict(), mumu=dict(), hadron=dict(), offip=dict()),
486 requested_iov=IoV(0, 0, -1, -1), expert_config=default_config)
487 def make_collection(name, files=None, path=None, **argk)
def vxd_sensors(layers=None, rigid=True, surface=True, surface2=True, surface3=True, surface4=True, parameters=None)