LDMX Software
EcalTrackAnalyzer.cxx
Go to the documentation of this file.
1
7
8#include "Ecal/Event/EcalHit.h"
9
10namespace dqm {
11
13 track_collection_ = ps.get<std::string>("track_collection");
14 track_pass_name_ = ps.get<std::string>("track_pass_name");
15 rec_hit_collection_ = ps.get<std::string>("rec_hit_collection");
16 rec_hit_pass_name_ = ps.get<std::string>("rec_hit_pass_name");
17}
18
20 // Check if track collection exists
22 ldmx_log(debug) << "ECAL track collection does not exist";
23 return;
24 }
25
26 // Get ECAL tracks
27 const auto& ecal_tracks =
28 event.getCollection<ldmx::Track>(track_collection_, track_pass_name_);
29
30 int n_tracks = ecal_tracks.size();
31 histograms_.fill("n_tracks", n_tracks);
32
33 if (n_tracks == 0) {
34 return;
35 }
36
37 // Loop over tracks
38 for (size_t i_track = 0; i_track < ecal_tracks.size(); ++i_track) {
39 const auto& track = ecal_tracks[i_track];
40
41 // Track quality
42 double chi2 = track.getChi2();
43 int ndf = track.getNdf();
44 int nhits = track.getNhits();
45
46 histograms_.fill("track_chi2", chi2);
47 histograms_.fill("track_ndf", ndf);
48 histograms_.fill("track_nhits", nhits);
49
50 if (ndf > 0) {
51 histograms_.fill("track_chi2_ndf", chi2 / ndf);
52 }
53
54 // Track parameters
55 double d0 = track.getD0();
56 double z0 = track.getZ0();
57 double phi = track.getPhi();
58 double theta = track.getTheta();
59 double qop = track.getQoP();
60 int charge = track.getCharge();
61
62 histograms_.fill("track_d0", d0);
63 histograms_.fill("track_z0", z0);
64 histograms_.fill("track_phi", phi);
65 histograms_.fill("track_theta", theta);
66 histograms_.fill("track_qop", qop);
67 histograms_.fill("track_charge", charge);
68
69 // Momentum
70 double p = 0;
71 if (std::abs(qop) > 1e-9) {
72 p = 1.0 / std::abs(qop);
73 }
74 histograms_.fill("track_p", p);
75
76 // Momentum components (approximate from angles and magnitude)
77 double px = p * std::sin(theta) * std::cos(phi);
78 double py = p * std::sin(theta) * std::sin(phi);
79 double pz = p * std::cos(theta);
80
81 double pt = std::sqrt(px * px + py * py);
82 histograms_.fill("track_px", px);
83 histograms_.fill("track_py", py);
84 histograms_.fill("track_pz", pz);
85 histograms_.fill("track_pt", pt);
86
87 // Position at ECAL front (from d0, z0)
88 // d0 and z0 are in the perigee frame
89 double x = -d0 * std::sin(phi); // Approximate x position
90 double y = d0 * std::cos(phi); // Approximate y position
91
92 histograms_.fill("track_x", x);
93 histograms_.fill("track_y", y);
94 histograms_.fill("track_xy", x, y);
95
96 // 2D correlations
97 histograms_.fill("track_nhits_vs_chi2", nhits, chi2);
98 histograms_.fill("track_nhits_vs_chi2_ndf", nhits, (ndf > 0) ? chi2 / ndf : 0.0);
99 histograms_.fill("track_chi2_vs_nhits", chi2, nhits);
100 histograms_.fill("track_p_vs_chi2", p, chi2);
101 histograms_.fill("track_p_vs_nhits", p, nhits);
102 histograms_.fill("track_p_vs_theta", p, theta);
103
104 // If multiple tracks, fill special histograms
105 if (n_tracks > 1) {
106 histograms_.fill("track_p_multitracks", p);
107
108 // Calculate angular separation between tracks
109 for (size_t j_track = i_track + 1; j_track < ecal_tracks.size();
110 ++j_track) {
111 const auto& other_track = ecal_tracks[j_track];
112
113 double phi1 = track.getPhi();
114 double theta1 = track.getTheta();
115 double phi2 = other_track.getPhi();
116 double theta2 = other_track.getTheta();
117
118 // Direction vectors
119 double dx1 = std::sin(theta1) * std::cos(phi1);
120 double dy1 = std::sin(theta1) * std::sin(phi1);
121 double dz1 = std::cos(theta1);
122
123 double dx2 = std::sin(theta2) * std::cos(phi2);
124 double dy2 = std::sin(theta2) * std::sin(phi2);
125 double dz2 = std::cos(theta2);
126
127 // Dot product
128 double dot = dx1 * dx2 + dy1 * dy2 + dz1 * dz2;
129 double angle = std::acos(std::max(-1.0, std::min(1.0, dot)));
130
131 histograms_.fill("track_separation", angle);
132 }
133 }
134 }
135
136 ldmx_log(debug) << "Analyzed " << n_tracks << " ECAL tracks";
137}
138
139} // namespace dqm
140
Analysis of ECAL tracks produced by ACTS track finder.
#define DECLARE_ANALYZER(CLASS)
Macro which allows the framework to construct an analyzer given its name during configuration.
DQM analyzer for ECAL tracks fitted with ACTS zero-B field CKF.
std::string rec_hit_pass_name_
Pass name for RecHits.
void analyze(const framework::Event &event) override
Analyze the event.
void configure(framework::config::Parameters &ps) override
Configure the analyzer.
std::string track_collection_
ECAL track collection name.
std::string rec_hit_collection_
ECAL RecHit collection (for layer occupancy)
std::string track_pass_name_
Pass name for tracks.
HistogramPool histograms_
helper object for making and filling histograms
Implements an event buffer system for storing event data.
Definition Event.h:42
bool exists(const std::string &name, const std::string &passName, bool unique=true) const
Check for the existence of an object or collection with the given name and pass name in the event.
Definition Event.cxx:105
void fill(const std::string &name, const T &val)
Fill a 1D histogram.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:29
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:78
Implementation of a track object.
Definition Track.h:53