Belle II Software development
ElossHarvestingModule Class Reference
Inheritance diagram for ElossHarvestingModule:

Public Member Functions

def __init__ (self, output_file_name)
 
def initialize (self)
 
def prepare (self)
 
def pick (self, track)
 
def peel (self, track)
 

Public Attributes

 mc_track_lookup
 by default, there is no method to find matching MC tracks
 
 track_fitter
 Use the CDCReimannFitter with a constrained origin for track fitting.
 
 mc_hit_lookup
 Method to find matching MC hits.
 
 eloss_estimator
 Method to estimate dE/dx in the CDC.
 
 bfield
 Method to interrogate the magnetic field values.
 

Static Public Attributes

refiners save_tree = refiners.save_tree()
 Refiners to be executed at the end of the harvesting / termination of the module Save a tree of all collected variables in a sub folder.
 
refiners save_histograms
 Save histograms in a sub folder.
 
refiners save_histograms_stackby_charge
 Save the histograms, stacked by charge, in a sub folder.
 
refiners save_scatter
 Save the scatterplots in a sub folder.
 
refiners save_profiles
 Save the profile histograms to the output ROOT file.
 
refiners save_bz_profiles
 Save the magnetic-field profile histogram in a sub folder.
 
refiners save_cid_histogram
 Save the eloss-displacement histograms in a sub folder.
 
refiners save_cid_profiles
 Save the eloss-displacement profile histograms in a sub folder.
 
refiners save_cid_scatters
 Save the eloss-displacement scatterplots in a sub folder.
 
refiners save_energy_cid_histogram
 Save the eloss histograms in a sub folder.
 
refiners save_energy_cid_profiles
 Save the eloss profile histograms in a sub folder.
 
refiners save_energy_cid_scatters
 Save the eloss profile scatterplots in a sub folder.
 

Detailed Description

Module to collect information about the generated segments and
compose validation plots on terminate.

Definition at line 147 of file record.py.

Constructor & Destructor Documentation

◆ __init__()

def __init__ (   self,
  output_file_name 
)
Constructor

Definition at line 152 of file record.py.

152 def __init__(self, output_file_name):
153 """Constructor"""
154 super().__init__(foreach='CDCTrackVector',
155 output_file_name=output_file_name)
156
157
158 self.mc_track_lookup = None
159
160 origin_track_fitter = TFCDC.CDCRiemannFitter()
161 origin_track_fitter.setOriginConstrained()
162
163 self.track_fitter = origin_track_fitter
164

Member Function Documentation

◆ initialize()

def initialize (   self)
Receive signal at the start of event processing

Definition at line 165 of file record.py.

165 def initialize(self):
166 """Receive signal at the start of event processing"""
167 super().initialize()
168
169 self.mc_track_lookup = TFCDC.CDCMCTrackLookUp.getInstance()
170
171 self.mc_hit_lookup = TFCDC.CDCMCHitLookUp.getInstance()
172
173 self.eloss_estimator = TFCDC.EnergyLossEstimator.forCDC()
174
175 self.bfield = TFCDC.CDCBFieldUtil
176

◆ peel()

def peel (   self,
  track 
)
Aggregate the track and MC information for dE/dx analysis

Definition at line 198 of file record.py.

198 def peel(self, track):
199 """Aggregate the track and MC information for dE/dx analysis"""
200 mc_track_lookup = self.mc_track_lookup
201
202 # rl_drift_circle = 1
203 # unit_variance = 0
204 # observations2D = TFCDC.CDCObservations2D(rl_drift_circle, unit_variance)
205
206 # for recoHit3D in track:
207 # observations2D.append(recoHit3D)
208
209 # trajectory2D = track_fitter.fit(observations2D)
210 # trajectory2D.setLocalOrigin(TFCDC.Vector2D(0, 0))
211
212 mc_particle = mc_track_lookup.getMCParticle(track)
213 pdg_code = mc_particle.getPDG()
214 t_vertex = mc_particle.getVertex()
215 t_mom = mc_particle.getMomentum()
216 charge = mc_particle.getCharge()
217 mass = mc_particle.getMass()
218 mc_energy = mc_particle.getEnergy()
219
220 mc_vertex2D = TFCDC.Vector2D(t_vertex.XYvector())
221 mc_mom2D = TFCDC.Vector2D(t_mom.XYvector())
222 mc_trajectory2D = TFCDC.CDCTrajectory2D(mc_vertex2D, 0, mc_mom2D, charge)
223 mc_pt = mc_mom2D.norm()
224
225 first_hit = self.mc_track_lookup.getFirstHit(track)
226 first_sim_hit = first_hit.getRelated("CDCSimHits")
227 if first_sim_hit is None:
228 return
229 # Make sure we start the track in the first layer to avoid some confusion
230 if first_sim_hit.getWireID().getICLayer() != 0:
231 return
232
233 last_hit = self.mc_track_lookup.getLastHit(track)
234 last_sim_hit = last_hit.getRelated("CDCSimHits")
235 if last_sim_hit is None:
236 return
237 # Make sure we start the track in the last layer to avoid some confusion
238 # if last_sim_hit.getWireID().getICLayer() != 55: return
239 # last_sim_mom3D = TFCDC.Vector3D(last_sim_hit.getMomentum())
240
241 first_sim_pos3D = TFCDC.Vector3D(first_sim_hit.getPosTrack())
242 first_sim_mom3D = TFCDC.Vector3D(first_sim_hit.getMomentum())
243 first_sim_tof = first_sim_hit.getFlightTime()
244 first_sim_energy = np.sqrt(first_sim_mom3D.norm() ** 2 + mass ** 2)
245 first_sim_pt = first_sim_mom3D.cylindricalR()
246 first_sim_pz = first_sim_mom3D.z()
247
248 first_sim_mom2D = first_sim_mom3D.xy()
249
250 # first_sim_mom2D.normalizeTo(last_sim_mom3D.cylindricalR())
251 first_sim_trajectory2D = TFCDC.CDCTrajectory2D(first_sim_pos3D.xy(), first_sim_tof, first_sim_mom2D, charge)
252
253 # mc_trajectory3D = mc_track_lookup.getTrajectory3D(track)
254 # mc_trajectory2D = mc_trajectory3D.getTrajectory2D()
255
256 for reco_hit3D in track:
257 sim_hit = self.mc_hit_lookup.getSimHit(reco_hit3D.getWireHit().getHit())
258 if sim_hit is None:
259 continue
260
261 sim_mom3D = TFCDC.Vector3D(sim_hit.getMomentum())
262 sim_energy = np.sqrt(sim_mom3D.norm() ** 2 + mass ** 2)
263 sim_pt = sim_mom3D.cylindricalR()
264 sim_pz = sim_mom3D.z()
265
266 mc_eloss_truth = mc_energy - sim_energy
267 first_eloss_truth = first_sim_energy - sim_energy
268
269 sim_pos3D = TFCDC.Vector3D(sim_hit.getPosTrack())
270 sim_pos2D = sim_pos3D.xy()
271
272 layer_cid = reco_hit3D.getWire().getICLayer()
273 bz = self.bfield.getBFieldZ(sim_pos3D)
274 r = sim_pos3D.cylindricalR()
275
276 # recoPos3D = reco_hit3D.getRecoPos3D()
277 # recoPos3D = TFCDC.Vector3D(sim_hit.getPosTrack())
278 # recoPos2D = recoPos3D.xy()
279 # refPos2D = reco_hit3D.getRefPos2D()
280 # l = reco_hit3D.getSignedRecoDriftLength()
281
282 mc_s2D = mc_trajectory2D.calcArcLength2D(sim_pos2D)
283 first_s2D = first_sim_trajectory2D.calcArcLength2D(sim_pos2D)
284
285 if mc_s2D < 0:
286 # mc_s2D += mc_trajectory2D.getArcLength2DPeriod()
287 continue
288
289 mc_eloss_estimate = self.eloss_estimator.getEnergyLoss(mc_pt, pdg_code, mc_s2D)
290 first_eloss_estimate = self.eloss_estimator.getEnergyLoss(first_sim_pt, pdg_code, first_s2D)
291 first_ploss_factor = self.eloss_estimator.getMomentumLossFactor(first_sim_pt, pdg_code, first_s2D)
292
293 sasha_eloss_estimate = getBetheEnergyLoss(first_sim_pt, pdg_code, first_s2D)
294 sasha_ploss_factor = DeltaR(first_s2D, pdg_code, first_sim_pt)
295
296 # first_residual2D = first_trajectory2D.getDist2D(refPos2D) - l
297 first_residual2D = first_sim_trajectory2D.getDist2D(sim_pos2D)
298 first_disp2D = charge * first_residual2D
299
300 first_loss_disp2D_estimate = abs(self.eloss_estimator.getLossDist2D(first_sim_pt, pdg_code, first_s2D))
301 first_delossed_disp2D = first_disp2D - first_loss_disp2D_estimate
302
303 # mc_residual2D = mc_trajectory2D.getDist2D(refPos2D) - l
304 mc_residual2D = mc_trajectory2D.getDist2D(sim_pos2D)
305 mc_disp2D = charge * mc_residual2D
306
307 mc_loss_disp2D_estimate = abs(self.eloss_estimator.getLossDist2D(mc_pt, pdg_code, mc_s2D))
308 mc_delossed_disp2D = mc_disp2D - mc_loss_disp2D_estimate
309
310 # s2D = trajectory2D.calcArcLength2D(recoPos2D)
311 # if s2D < 0: s2D += trajectory2D.getArcLength2DPeriod()
312
313 # residual2D = trajectory2D.getDist2D(recoPos2D)
314 # disp2D = charge * residual2D
315
316 # # Original approach
317 # center2D = trajectory2D.getGlobalCircle().center()
318 # radius2D = recoPos2D - center2D;
319
320 # eLoss = self.eloss_estimator.getEnergyLoss(mc_pt, pdg_code, mc_s2D)
321 # dx = self.eloss_estimator.getMomentumLossFactor(mc_pt, pdg_code, mc_s2D)
322 # deloss_radius2D = recoPos2D - center2D;
323 # deloss_radius2D.scale (1.0 / dx)
324 # loss_disp2D_estimate2 = (deloss_radius2D - radius2D).norm()
325
326 # loss_disp2D_estimate3 = radius2D.norm() * (1.0 /dx - 1.0)
327 # loss_disp2D_estimate3 = radius2D.norm() * ((1.0 - dx) /dx)
328 # loss_disp2D_estimate3 = radius2D.norm() * (eLoss / (mc_pt - eLoss))
329
330 if abs(mc_residual2D) > 6:
331 continue
332
333 if abs(first_residual2D) > 6:
334 continue
335
336 yield dict(
337 layer_cid=layer_cid,
338 r=r,
339 bz=bz,
340 # pt=trajectory2D.getAbsMom2D(),
341 pdg_code=abs(pdg_code),
342 mass=mass,
343 charge=charge,
344 mc_pt=mc_pt,
345 first_sim_pt=first_sim_pt,
346 sim_pt=sim_pt,
347
348 diff_pt=first_sim_pt - sim_pt,
349 diff_pz=first_sim_pz - sim_pz,
350
351 mc_eloss_truth=mc_eloss_truth,
352 mc_eloss_estimate=mc_eloss_estimate,
353
354 first_eloss_truth=first_eloss_truth,
355
356 first_eloss_estimate=first_eloss_estimate,
357 sasha_eloss_estimate=sasha_eloss_estimate,
358
359 first_ploss_factor=first_ploss_factor,
360 sasha_ploss_factor=sasha_ploss_factor,
361
362 # l=l,
363
364 first_s2D=first_s2D,
365 first_residual2D=first_residual2D,
366 first_disp2D=first_disp2D,
367 first_loss_disp2D_estimate=first_loss_disp2D_estimate,
368 first_delossed_disp2D=first_delossed_disp2D,
369
370 mc_s2D=mc_s2D,
371 mc_residual2D=mc_residual2D,
372 mc_disp2D=mc_disp2D,
373 mc_loss_disp2D_estimate=mc_loss_disp2D_estimate,
374 mc_delossed_disp2D=mc_delossed_disp2D,
375
376 # s2D=s2D,
377 # disp2D=disp2D,
378 # residual2D=residual2D,
379
380 # loss_disp2D_estimate2=loss_disp2D_estimate2,
381 # loss_disp2D_estimate3=loss_disp2D_estimate3,
382 )
383

◆ pick()

def pick (   self,
  track 
)
Select tracks with at least 4 segments and associated primary MC particle with pt >= 0.25 GeV/c

Definition at line 181 of file record.py.

181 def pick(self, track):
182 """Select tracks with at least 4 segments and associated primary MC particle with pt >= 0.25 GeV/c"""
183 if track.size() < 4:
184 return False
185
186 mc_track_lookup = self.mc_track_lookup
187 mc_particle = mc_track_lookup.getMCParticle(track)
188
189 # Check that mc_particle is not a nullptr
190 if mc_particle is None:
191 return False
192
193 if mc_particle.getMomentum().Rho() < 0.250:
194 return False
195
196 return is_primary(mc_particle)
197

◆ prepare()

def prepare (   self)
Initialize the MC-hit lookup method

Definition at line 177 of file record.py.

177 def prepare(self):
178 """Initialize the MC-hit lookup method"""
179 TFCDC.CDCMCHitLookUp.getInstance().fill()
180

Member Data Documentation

◆ bfield

bfield

Method to interrogate the magnetic field values.

Definition at line 175 of file record.py.

◆ eloss_estimator

eloss_estimator

Method to estimate dE/dx in the CDC.

Definition at line 173 of file record.py.

◆ mc_hit_lookup

mc_hit_lookup

Method to find matching MC hits.

Definition at line 171 of file record.py.

◆ mc_track_lookup

mc_track_lookup

by default, there is no method to find matching MC tracks

Method to find matching MC tracks.

Definition at line 158 of file record.py.

◆ save_bz_profiles

refiners save_bz_profiles
static
Initial value:
= refiners.save_profiles(
x='r',
y='bz',
)

Save the magnetic-field profile histogram in a sub folder.

Definition at line 431 of file record.py.

◆ save_cid_histogram

refiners save_cid_histogram
static
Initial value:
= refiners.save_histograms(
select=[
# 'mc_disp2D',
# 'mc_delossed_disp2D',
'first_disp2D',
'first_delossed_disp2D',
'bz',
# 'disp2D',
],
outlier_z_score=5.0,
groupby=["layer_cid"],
# stackby="pdg_code",
)

Save the eloss-displacement histograms in a sub folder.

Definition at line 440 of file record.py.

◆ save_cid_profiles

refiners save_cid_profiles
static
Initial value:
= refiners.save_profiles(
x=["mc_pt"],
y=[
# 'mc_disp2D',
# 'mc_delossed_disp2D',
'first_disp2D',
'first_delossed_disp2D',
],
outlier_z_score=5.0,
groupby=["layer_cid"],
stackby="pdg_code",
)

Save the eloss-displacement profile histograms in a sub folder.

Definition at line 455 of file record.py.

◆ save_cid_scatters

refiners save_cid_scatters
static
Initial value:
= refiners.save_scatters(
x=["mc_pt"],
y=[
# 'mc_disp2D',
# 'mc_delossed_disp2D',
'first_disp2D',
'first_delossed_disp2D',
],
outlier_z_score=5.0,
groupby=["layer_cid"],
stackby="pdg_code",
)

Save the eloss-displacement scatterplots in a sub folder.

Definition at line 469 of file record.py.

◆ save_energy_cid_histogram

refiners save_energy_cid_histogram
static
Initial value:
= refiners.save_histograms(
select=[
'pdg_code',
'first_eloss_estimate',
'first_eloss_truth',
],
outlier_z_score=5.0,
groupby=["layer_cid"],
stackby="pdg_code",
folder_name='energy/{groupby_addition}',
)

Save the eloss histograms in a sub folder.

Definition at line 485 of file record.py.

◆ save_energy_cid_profiles

refiners save_energy_cid_profiles
static
Initial value:
= refiners.save_profiles(
x=["mc_pt"],
y=[
'first_eloss_truth',
'first_eloss_estimate',
],
outlier_z_score=5.0,
groupby=["layer_cid"],
stackby="pdg_code",
folder_name='energy/{groupby_addition}',
)

Save the eloss profile histograms in a sub folder.

Definition at line 498 of file record.py.

◆ save_energy_cid_scatters

refiners save_energy_cid_scatters
static
Initial value:
= refiners.save_scatters(
x=["mc_pt"],
y=[
'first_eloss_truth',
'first_eloss_estimate',
],
outlier_z_score=5.0,
groupby=["layer_cid"],
stackby="pdg_code",
folder_name='energy/{groupby_addition}',
)

Save the eloss profile scatterplots in a sub folder.

Definition at line 511 of file record.py.

◆ save_histograms

refiners save_histograms
static
Initial value:
= refiners.save_histograms(
outlier_z_score=5.0,
allow_discrete=True,
)

Save histograms in a sub folder.

Definition at line 388 of file record.py.

◆ save_histograms_stackby_charge

refiners save_histograms_stackby_charge
static
Initial value:
= refiners.save_histograms(
select=[
# "mc_disp2D",
"first_disp2D",
"charge",
],
outlier_z_score=5.0,
allow_discrete=True,
fit="gaus",
fit_z_score=1,
groupby="charge",
)

Save the histograms, stacked by charge, in a sub folder.

Definition at line 394 of file record.py.

◆ save_profiles

refiners save_profiles
static
Initial value:
= refiners.save_profiles(
x=['mc_s2D'],
y=[
# 'mc_disp2D',
'first_disp2D',
'disp2D',
],
groupby=[None, "charge"],
)

Save the profile histograms to the output ROOT file.

Definition at line 420 of file record.py.

◆ save_scatter

refiners save_scatter
static
Initial value:
= refiners.save_scatters(
x=['mc_s2D'],
y=[
# 'mc_disp2D',
'disp2D',
],
groupby=[None, "charge"],
filter=lambda x: x == 211,
filter_on="pdg_code",
)

Save the scatterplots in a sub folder.

Definition at line 408 of file record.py.

◆ save_tree

refiners save_tree = refiners.save_tree()
static

Refiners to be executed at the end of the harvesting / termination of the module Save a tree of all collected variables in a sub folder.

Definition at line 386 of file record.py.

◆ track_fitter

track_fitter

Use the CDCReimannFitter with a constrained origin for track fitting.

Definition at line 163 of file record.py.


The documentation for this class was generated from the following file: