Belle II Software development
test_mixing_overlay_equivalence.py
1
8
9import basf2
10import ROOT
11from ROOT import Belle2
12import b2test_utils
13from svd import add_svd_simulation
14
15# ====================================================================
16# This test does the following:
17# 1. Simulate a few hundred ParticleGun events to produce a background
18# sample.
19# 2. Produce background overlay sample from background sample. .
20# 3. Set aside SimHits from a selected sensor to create signal-background
21# collisions.
22# 4. Inject collision SimHits, add background using the background mixer,
23# and digitize. Sort and save.
24# 5. Inject collision SimHits, digitize, and use background overlay
25# to add background. Sort and save.
26# 7. Compare SVDShaperDigits in the two ROOT files.
27#
28# NB: I sort both digit samples before saving. Normally, the digits
29# require sorting only after background overlay, but SVDDigitizer happens
30# to sort digits differently than ShaperDigitSorter. Both sorting are
31# correct, but the sorting to eventually correct is that in the
32# digitizer.
33# NB: Switching off electronic effects in SVDDigitizer prevents it from
34# adding noise digits.
35# ====================================================================
36
37
38xsimhits = []
39
40
41class SetAsideSimHits(basf2.Module):
42 """Set aside all SimHits on a selected sensor/side to create
43 signal/background collisions."""
44
45 def __init__(self):
46 '''initialize python module'''
47 super().__init__()
48
49
51
52 def event(self):
53 '''event'''
54 global xsimhits
55 storesimhits = Belle2.PyStoreArray("SVDSimHits")
56 for h in storesimhits:
57 if h.getSensorID == self.selected_sensorID:
58 xsimhits.append(h)
59
60
61class InjectSimHits(basf2.Module):
62 '''Inject stored SVDSimHits'''
63
64 def __init__(self):
65 '''initialize python module'''
66 super().__init__()
67
68
69 self.simhits = Belle2.PyStoreArray("SVDSimHits")
70
71 def initialize(self):
72 '''initialize'''
73 self.simhits.registerInDataStore()
74
75 def event(self):
76 '''event'''
77
78 global xsimhits
79 for h in xsimhits:
80 simhit = self.simhits.appendNew()
81 simhit.__assign__(h)
82
83
84if __name__ == "__main__":
85
87
88 basf2.B2INFO('Creating background data...')
89
90 create_bgfile = basf2.create_path()
91 create_bgfile.add_module('EventInfoSetter', expList=[0], runList=[0], evtNumList=[100])
92 create_bgfile.add_module('Gearbox')
93 create_bgfile.add_module('Geometry', components=['MagneticField', 'SVD'])
94 create_bgfile.add_module('ParticleGun')
95 create_bgfile.add_module('FullSim')
96 create_bgfile.add_module('BeamBkgTagSetter', backgroundType="twoPhoton", realTime=310.0)
97 create_bgfile.add_module('RootOutput', outputFileName='bgForMixing.root', branchNames=['BackgroundMetaData', 'SVDSimHits'])
99 b2test_utils.safe_process(create_bgfile)
100
101 basf2.B2INFO('Creating overlay data...')
102
103 create_ovrfile = basf2.create_path()
104 create_ovrfile.add_module('EventInfoSetter', expList=[0], runList=[0], evtNumList=[1])
105 create_ovrfile.add_module('Gearbox')
106 create_ovrfile.add_module('Geometry', components=['MagneticField', 'SVD'])
107 create_ovrfile.add_module('BeamBkgMixer', backgroundFiles=['bgForMixing.root'], minTime=-150, maxTime=150)
108 # Turn off generation of noise digits in SVDDigitizer.
109 add_svd_simulation(create_ovrfile)
110
111 create_ovrfile.add_module(SetAsideSimHits())
112 create_ovrfile.add_module('RootOutput', outputFileName='bgForOverlay.root', branchNames=['SVDShaperDigits'])
114 b2test_utils.safe_process(create_ovrfile)
115
116 basf2.B2INFO('Background mixing...')
117
118 produce_mixed = basf2.create_path()
119 produce_mixed.add_module('EventInfoSetter', expList=[0], runList=[0], evtNumList=[1])
120 produce_mixed.add_module('Gearbox')
121 produce_mixed.add_module('Geometry', components=['MagneticField', 'SVD'])
122 # Inject stored simhits
123 produce_mixed.add_module(InjectSimHits())
124 # Time window for background file to just cover one event
125 produce_mixed.add_module('BeamBkgMixer', backgroundFiles=['bgForMixing.root'], minTime=-150, maxTime=150)
126 # Turn off generation of noise digits in SVDDigitizer.
127 add_svd_simulation(produce_mixed)
128
129 produce_mixed.add_module('SVDShaperDigitSorter')
130 produce_mixed.add_module('RootOutput', outputFileName='mixedBg.root')
132 b2test_utils.safe_process(produce_mixed)
133
134 basf2.B2INFO('Background overlay...')
135
136 produce_overlaid = basf2.create_path()
137 produce_overlaid.add_module('EventInfoSetter', expList=[0], runList=[0], evtNumList=[1])
138 produce_overlaid.add_module('Gearbox')
139 produce_overlaid.add_module('Geometry', components=['MagneticField', 'SVD'])
140 produce_overlaid.add_module('BGOverlayInput', inputFileNames=['bgForOverlay.root'])
141 produce_overlaid.add_module(InjectSimHits())
142
143 add_svd_simulation(produce_overlaid)
144
145 produce_overlaid.add_module('BGOverlayExecutor')
146 # Sort digits after overlay
147 produce_overlaid.add_module('SVDShaperDigitSorter')
148 produce_overlaid.add_module('RootOutput', outputFileName='overlaidBg.root')
150 b2test_utils.safe_process(produce_overlaid)
151
152 basf2.B2INFO('Comparing...')
153
154 with ROOT.TFile('mixedBg.root') as f_mixed:
155 tree_mixed = f_mixed.Get('tree')
156
157 with ROOT.TFile('overlaidBg.root') as f_over:
158 tree_over = f_over.Get('tree')
159
160 class_name = "Belle2::SVDShaperDigit"
161
162 digits_mixed = ROOT.TClonesArray(class_name)
163 digits_over = ROOT.TClonesArray(class_name)
164
165 tree_mixed.SetBranchAddress("SVDShaperDigits", digits_mixed)
166 tree_over.SetBranchAddress("SVDShaperDigits", digits_over)
167
168 n_good = 0
169
170 for i in range(tree_mixed.GetEntries()):
171 tree_mixed.GetEntry(i)
172 tree_over.GetEntry(i)
173
174 n_mixed = digits_mixed.GetEntriesFast()
175 n_over = digits_over.GetEntriesFast()
176
177 if n_mixed != n_over:
178 basf2.B2FATAL('Lengths of SVDShaperDigit arrays differ')
179 break
180
181 for d1, d2 in zip(digits_mixed, digits_over):
182 match = (
183 d1.getSensorID() == d2.getSensorID() and
184 d1.isUStrip() == d2.isUStrip() and
185 d1.getCellID() == d2.getCellID()
186 )
187
188 samples1 = d1.getSamples()
189 samples2 = d2.getSamples()
190
191 if len(samples1) != len(samples2):
192 match = False
193 else:
194 for s1, s2 in zip(samples1, samples2):
195 if int(s1) != int(s2):
196 match = False
197 break
198
199 if not match:
200 print(d1.toString())
201 print(d2.toString())
202 basf2.B2FATAL('Digits do not match.')
203 else:
204 n_good += 1
205
206 basf2.B2INFO(f'Processed {n_good} matching digits.')
A (simplified) python wrapper for StoreArray.
Class to uniquely identify a any structure of the PXD and SVD.
Definition VxdID.h:33
show_only_errors()
Definition __init__.py:94
clean_working_directory()
Definition __init__.py:198
safe_process(*args, **kwargs)
Definition __init__.py:245