LDMX Software
VisiblesVetoProcessor.cxx
1#include "Hcal/VisiblesVetoProcessor.h"
2
3// LDMX
4#include "DetDescr/HcalID.h"
5#include "DetDescr/SimSpecialID.h"
7#include "SimCore/Event/SimParticle.h"
9
10// C++
11#include <algorithm>
12#include <cmath>
13#include <fstream>
14#include <iostream>
15#include <numeric>
16
17namespace hcal {
18void VisiblesVetoProcessor::buildBDTFeatureVector(
19 const ldmx::VisiblesVetoResult &result) {
20 bdt_features_.push_back(result.getNLayersHit());
21 bdt_features_.push_back(result.getXStd());
22 bdt_features_.push_back(result.getYStd());
23 bdt_features_.push_back(result.getZStd());
24 bdt_features_.push_back(result.getXMean());
25 bdt_features_.push_back(result.getYMean());
26 bdt_features_.push_back(result.getRMean());
27 bdt_features_.push_back(result.getIsoHits());
28 bdt_features_.push_back(result.getIsoEnergy());
29 bdt_features_.push_back(result.getNReadoutHits());
30 bdt_features_.push_back(result.getSummedDet());
31 bdt_features_.push_back(result.getDistFromPhotonTrack());
32}
33
36 feature_list_name_ = parameters.get<std::string>("feature_list_name");
37 // Load BDT ONNX file
38 rt_ = std::make_unique<ldmx::ort::ONNXRuntime>(
39 parameters.get<std::string>("bdt_file"));
40
41 bdt_cut_val_ = parameters.get<double>("disc_cut");
42
43 beam_energy_mev_ = parameters.get<double>("beam_energy");
44
45 // collection and pass names
46 collection_name_ = parameters.get<std::string>("collection_name");
47 rec_pass_name_ = parameters.get<std::string>("rec_pass_name");
48 rec_coll_name_ = parameters.get<std::string>("rec_coll_name");
49
50 recoil_from_tracking_ = parameters.get<bool>("recoil_from_tracking");
51 track_collection_ = parameters.get<std::string>("track_collection");
52 track_pass_name_ = parameters.get<std::string>("track_pass_name");
53
54 sp_collection_ = parameters.get<std::string>("sp_coll_name");
55 sp_pass_name_ = parameters.get<std::string>("sp_pass_name");
56 sim_particles_pass_name_ =
57 parameters.get<std::string>("sim_particles_pass_name");
58}
59
60bool VisiblesVetoProcessor::inList(std::vector<int> parents, int track_id) {
61 return std::find(parents.begin(), parents.end(), track_id) != parents.end();
62}
63
64void VisiblesVetoProcessor::clearProcessor() {
65 bdt_features_.clear();
66
67 n_layers_hit_ = 0;
68 x_std_ = 0.;
69 y_std_ = 0.;
70 z_std_ = 0.;
71 x_mean_ = 0.;
72 y_mean_ = 0.;
73 r_mean_ = 0.;
74 iso_hits_ = 0;
75 iso_energy_ = 0.;
76 n_readout_hits_ = 0;
77 summed_det_ = 0.;
78 r_mean_from_photon_track_ = 0.;
79}
80
83
84 clearProcessor();
85
86 const auto &particle_map{event.getMap<int, ldmx::SimParticle>(
87 "SimParticles", sim_particles_pass_name_)};
88
89 // Get target scoring plane hits for recoil electron
90 // Use this to calculate the projected photon line vector
91 // This currently uses truth-level information, but it should be replaced
92 // by reconstructed tracker information, when available
93 std::vector<double> gamma_p(3);
94 std::vector<double> gamma_x0(3);
95 if (recoil_from_tracking_) {
96 const auto &recoil_tracks{
97 event.getCollection<ldmx::Track>(track_collection_, track_pass_name_)};
98 // Fill this in later when you know how to use it
99 for (auto &track : recoil_tracks) {
100 // need to figure out how to best isolate candidate electron track
101 if (track.q() == 1 && track.getNhits() == 5) {
102 gamma_x0 = track.getPosition();
103 gamma_p[0] = -1. * track.getMomentum()[0];
104 gamma_p[1] = -1. * track.getMomentum()[1];
105 gamma_p[2] = beam_energy_mev_ - track.getMomentum()[2];
106 }
107 }
108 } else {
109 if (event.exists(sp_collection_, sp_pass_name_)) {
110 const auto &target_sp_hits = event.getCollection<ldmx::SimTrackerHit>(
111 sp_collection_, sp_pass_name_);
112 for (auto const &it : particle_map) {
113 for (auto const &sphit : target_sp_hits) {
114 if (sphit.getPosition()[2] > 0) {
115 if (it.first == sphit.getTrackID()) {
116 if (it.second.getPdgID() == 11 &&
117 inList(it.second.getParents(), 0)) {
118 /* Since SP hit positions are stored as floats and gamma_x0 is
119 a double vector, the conversion here is a little convolcuted.
120 */
121 std::vector<float> x0_float = sphit.getPosition();
122 std::vector<double> x0_double(x0_float.begin(), x0_float.end());
123 gamma_x0 = x0_double;
124 gamma_p[0] = -1. * sphit.getMomentum()[0];
125 gamma_p[1] = -1. * sphit.getMomentum()[1];
126 gamma_p[2] = beam_energy_mev_ - sphit.getMomentum()[2];
127 }
128 }
129 }
130 }
131 }
132 }
133 }
134
135 // Get Hcal reconstructed hits and loop through them to build features
136 const auto &hcal_rec_hits =
137 event.getCollection<ldmx::HcalHit>(rec_coll_name_, rec_pass_name_);
138
139 double z_mean = 0.; // need this when calculating z_std_
140 std::vector<int> layers_hit;
141 for (const ldmx::HcalHit &hit : hcal_rec_hits) {
142 if (hit.getEnergy() > 0.) {
143 ldmx::HcalID det_id(hit.getID());
144 if (det_id.getSection() != 0) { // skip hits that aren't in main Hcal
145 continue;
146 }
147 n_readout_hits_ += 1;
148 double hit_x = hit.getXPos();
149 double hit_y = hit.getYPos();
150 double hit_z = hit.getZPos();
151 double hit_r = sqrt(hit_x * hit_x + hit_y * hit_y);
152
153 summed_det_ += hit.getEnergy();
154
155 x_mean_ += hit_x * hit.getEnergy();
156 y_mean_ += hit_y * hit.getEnergy();
157 z_mean += hit_z * hit.getEnergy();
158 r_mean_ += hit_r * hit.getEnergy();
159
160 // check if this is a new layer in the collection
161 if (!(std::find(layers_hit.begin(), layers_hit.end(),
162 det_id.getLayerID()) != layers_hit.end())) {
163 layers_hit.push_back(det_id.getLayerID());
164 }
165
166 double proj_x =
167 gamma_x0[0] + (hit_z - gamma_x0[2]) * gamma_p[0] / gamma_p[2];
168 double proj_y =
169 gamma_x0[1] + (hit_z - gamma_x0[2]) * gamma_p[1] / gamma_p[2];
170
171 r_mean_from_photon_track_ +=
172 hit.getEnergy() * sqrt((hit_x - proj_x) * (hit_x - proj_x) +
173 (hit_y - proj_y) * (hit_y - proj_y));
174
175 // Calculate isolated hits
176 double closest_point = 9999.;
177 for (const ldmx::HcalHit &hit2 : hcal_rec_hits) {
178 if (hit2.getEnergy() > 0.) {
179 ldmx::HcalID det_i_d2(hit2.getID());
180 if (det_i_d2.getLayerID() == det_id.getLayerID()) {
181 // Determine if a bar is vertical (along y-axis) or horizontal
182 // (along x-axis) Odd layers have horizontal strips Even layers have
183 // vertical strips
184 if (hit.isOrientationX()) {
185 if (abs(hit2.getYPos() - hit_y) > 0) {
186 if (abs(hit2.getYPos() - hit_y) < closest_point) {
187 closest_point = abs(hit2.getYPos() - hit_y);
188 }
189 }
190 }
191 if (hit.isOrientationY()) {
192 if (abs(hit2.getXPos() - hit_x) > 0) {
193 if (abs(hit2.getXPos() - hit_x) < closest_point) {
194 closest_point = abs(hit2.getXPos() - hit_x);
195 }
196 }
197 }
198 }
199 }
200 }
201 if (closest_point > 50.) {
202 iso_hits_ += 1;
203 iso_energy_ += hit.getEnergy();
204 }
205 }
206 }
207
208 n_layers_hit_ = layers_hit.size();
209
210 if (summed_det_ > 0.) {
211 x_mean_ /= summed_det_;
212 y_mean_ /= summed_det_;
213 z_mean /= summed_det_;
214 r_mean_ /= summed_det_;
215
216 r_mean_from_photon_track_ /= summed_det_;
217 }
218
219 for (const ldmx::HcalHit &hit : hcal_rec_hits) {
220 if (hit.getEnergy() > 0.) {
221 ldmx::HcalID det_id(hit.getID());
222 if (det_id.getSection() == 0) {
223 x_std_ += hit.getEnergy() * (hit.getXPos() - x_mean_) *
224 (hit.getXPos() - x_mean_);
225 y_std_ += hit.getEnergy() * (hit.getYPos() - y_mean_) *
226 (hit.getYPos() - y_mean_);
227 z_std_ += hit.getEnergy() * (hit.getZPos() - z_mean) *
228 (hit.getZPos() - z_mean);
229 }
230 }
231 }
232
233 if (summed_det_ > 0.) {
234 x_std_ = sqrt(x_std_ / summed_det_);
235 y_std_ = sqrt(y_std_ / summed_det_);
236 z_std_ = sqrt(z_std_ / summed_det_);
237 }
238
239 result.setVariables(n_layers_hit_, x_std_, y_std_, z_std_, x_mean_, y_mean_,
240 r_mean_, iso_hits_, iso_energy_, n_readout_hits_,
241 summed_det_, r_mean_from_photon_track_);
242
243 buildBDTFeatureVector(result);
244
245 ldmx::ort::FloatArrays inputs({bdt_features_});
246 float pred =
247 rt_->run({feature_list_name_}, inputs, {"probabilities"})[0].at(1);
248 ldmx_log(info) << " Visibles BDT was ran, score is " << pred;
249
250 event.add(collection_name_, result);
251}
252
253} // namespace hcal
254
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Class that stores Stores reconstructed hit information from the HCAL.
Class that defines an HCal sensitive detector.
Class which encapsulates information from a hit in a simulated tracking detector.
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:92
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
void produce(framework::Event &event) override
Process the event and put new data products into it.
void configure(framework::config::Parameters &parameters) override
Callback for the EventProcessor to configure itself from the given set of parameters.
Stores reconstructed hit information from the HCAL.
Definition HcalHit.h:24
Implements detector ids for HCal subdetector.
Definition HcalID.h:19
unsigned int getLayerID() const
Get the value of the layer field from the ID.
Definition HcalID.h:96
Class representing a simulated particle.
Definition SimParticle.h:23
Represents a simulated tracker hit in the simulation.
Implementation of a track object.
Definition Track.h:53