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