192 def peel(self, track):
193 """Aggregate the track and MC information for dE/dx analysis"""
194 mc_track_lookup = self.mc_track_lookup
196 # rl_drift_circle = 1
198 # observations2D = TFCDC.CDCObservations2D(rl_drift_circle, unit_variance)
200 # for recoHit3D in track:
201 # observations2D.append(recoHit3D)
203 # trajectory2D = track_fitter.fit(observations2D)
204 # trajectory2D.setLocalOrigin(TFCDC.Vector2D(0, 0))
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()
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()
219 first_hit = self.mc_track_lookup.getFirstHit(track)
220 first_sim_hit = first_hit.getRelated("CDCSimHits")
221 if first_sim_hit is None:
223 # Make sure we start the track in the first layer to avoid some confusion
224 if first_sim_hit.getWireID().getICLayer() != 0:
227 last_hit = self.mc_track_lookup.getLastHit(track)
228 last_sim_hit = last_hit.getRelated("CDCSimHits")
229 if last_sim_hit is None:
231 # Make sure we start the track in the last layer to avoid some confusion
232 # if last_sim_hit.getWireID().getICLayer() != 55: return
233 # last_sim_mom3D = TFCDC.Vector3D(last_sim_hit.getMomentum())
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()
242 first_sim_mom2D = first_sim_mom3D.xy()
244 # first_sim_mom2D.normalizeTo(last_sim_mom3D.cylindricalR())
245 first_sim_trajectory2D = TFCDC.CDCTrajectory2D(first_sim_pos3D.xy(), first_sim_tof, first_sim_mom2D, charge)
247 # mc_trajectory3D = mc_track_lookup.getTrajectory3D(track)
248 # mc_trajectory2D = mc_trajectory3D.getTrajectory2D()
250 for reco_hit3D in track:
251 sim_hit = self.mc_hit_lookup.getSimHit(reco_hit3D.getWireHit().getHit())
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()
260 mc_eloss_truth = mc_energy - sim_energy
261 first_eloss_truth = first_sim_energy - sim_energy
263 sim_pos3D = TFCDC.Vector3D(sim_hit.getPosTrack())
264 sim_pos2D = sim_pos3D.xy()
266 layer_cid = reco_hit3D.getWire().getICLayer()
267 bz = self.bfield.getBFieldZ(sim_pos3D)
268 r = sim_pos3D.cylindricalR()
270 # recoPos3D = reco_hit3D.getRecoPos3D()
271 # recoPos3D = TFCDC.Vector3D(sim_hit.getPosTrack())
272 # recoPos2D = recoPos3D.xy()
273 # refPos2D = reco_hit3D.getRefPos2D()
274 # l = reco_hit3D.getSignedRecoDriftLength()
276 mc_s2D = mc_trajectory2D.calcArcLength2D(sim_pos2D)
277 first_s2D = first_sim_trajectory2D.calcArcLength2D(sim_pos2D)
280 # mc_s2D += mc_trajectory2D.getArcLength2DPeriod()
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)
287 sasha_eloss_estimate = getBetheEnergyLoss(first_sim_pt, pdg_code, first_s2D)
288 sasha_ploss_factor = DeltaR(first_s2D, pdg_code, first_sim_pt)
290 # first_residual2D = first_trajectory2D.getDist2D(refPos2D) - l
291 first_residual2D = first_sim_trajectory2D.getDist2D(sim_pos2D)
292 first_disp2D = charge * first_residual2D
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
297 # mc_residual2D = mc_trajectory2D.getDist2D(refPos2D) - l
298 mc_residual2D = mc_trajectory2D.getDist2D(sim_pos2D)
299 mc_disp2D = charge * mc_residual2D
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
304 # s2D = trajectory2D.calcArcLength2D(recoPos2D)
305 # if s2D < 0: s2D += trajectory2D.getArcLength2DPeriod()
307 # residual2D = trajectory2D.getDist2D(recoPos2D)
308 # disp2D = charge * residual2D
310 # # Original approach
311 # center2D = trajectory2D.getGlobalCircle().center()
312 # radius2D = recoPos2D - center2D;
314 # eLoss = self.eloss_estimator.getEnergyLoss(mc_pt, pdg_code, mc_s2D)
315 # dx = self.eloss_estimator.getMomentumLossFactor(mc_pt, pdg_code, mc_s2D)
316 # deloss_radius2D = recoPos2D - center2D;
317 # deloss_radius2D.scale (1.0 / dx)
318 # loss_disp2D_estimate2 = (deloss_radius2D - radius2D).norm()
320 # loss_disp2D_estimate3 = radius2D.norm() * (1.0 /dx - 1.0)
321 # loss_disp2D_estimate3 = radius2D.norm() * ((1.0 - dx) /dx)
322 # loss_disp2D_estimate3 = radius2D.norm() * (eLoss / (mc_pt - eLoss))
324 if abs(mc_residual2D) > 6:
327 if abs(first_residual2D) > 6:
334 # pt=trajectory2D.getAbsMom2D(),
335 pdg_code=abs(pdg_code),
339 first_sim_pt=first_sim_pt,
342 diff_pt=first_sim_pt - sim_pt,
343 diff_pz=first_sim_pz - sim_pz,
345 mc_eloss_truth=mc_eloss_truth,
346 mc_eloss_estimate=mc_eloss_estimate,
348 first_eloss_truth=first_eloss_truth,
350 first_eloss_estimate=first_eloss_estimate,
351 sasha_eloss_estimate=sasha_eloss_estimate,
353 first_ploss_factor=first_ploss_factor,
354 sasha_ploss_factor=sasha_ploss_factor,
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,
365 mc_residual2D=mc_residual2D,
367 mc_loss_disp2D_estimate=mc_loss_disp2D_estimate,
368 mc_delossed_disp2D=mc_delossed_disp2D,
372 # residual2D=residual2D,
374 # loss_disp2D_estimate2=loss_disp2D_estimate2,
375 # loss_disp2D_estimate3=loss_disp2D_estimate3,