18void EcalPnetVetoProcessor::configure(
20 disc_cut_ = parameters.
get<
double>(
"disc_cut");
21 rt_ = std::make_unique<ldmx::ort::ONNXRuntime>(
22 parameters.
get<std::string>(
"model_path"));
25 collection_name_ = parameters.
get<std::string>(
"collection_name");
27 rec_coll_name_ = parameters.
get<std::string>(
"rec_coll_name");
28 ecal_rec_hits_passname_ =
29 parameters.
get<std::string>(
"ecal_rec_hits_passname");
30 ecal_sp_coll_name_ = parameters.
get<std::string>(
"ecal_sp_coll_name");
31 ecal_sp_hits_passname_ = parameters.
get<std::string>(
"ecal_sp_hits_passname");
32 track_pass_name_ = parameters.
get<std::string>(
"track_pass_name",
"");
33 track_collection_ = parameters.
get<std::string>(
"track_collection");
34 recoil_from_tracking_ = parameters.
get<
bool>(
"recoil_from_tracking");
40 const auto& ecal_geometry = getCondition<ldmx::EcalGeometry>(
41 ldmx::EcalGeometry::CONDITIONS_OBJECT_NAME);
44 const auto ecal_rec_hits =
event.getCollection<
ldmx::EcalHit>(
45 rec_coll_name_, ecal_rec_hits_passname_);
46 auto nhits = std::count_if(
47 ecal_rec_hits.begin(), ecal_rec_hits.end(),
48 [](
const ldmx::EcalHit& hit) { return hit.getEnergy() > 0; });
51 ldmx_log(debug) <<
"nhits = " << nhits <<
" MAX_NUM_HITS = " << MAX_NUM_HITS;
52 if (nhits < MAX_NUM_HITS) {
53 std::array<double, 3> etraj = {-999., -999., -999.};
54 std::array<double, 3> enorm = {-999., -999., -999.};
58 if (!recoil_from_tracking_ &&
59 event.
exists(ecal_sp_coll_name_, ecal_sp_hits_passname_)) {
61 ecal_sp_coll_name_, ecal_sp_hits_passname_);
62 double electron_pz_max = -1.0;
63 for (
auto const& hit : ecal_sp_hits) {
65 if (hit.getPdgID() != 11)
continue;
66 double electron_z = hit.getPosition()[2];
68 if (electron_z <= 239.0 || electron_z >= 240.0)
continue;
69 double electron_pz = hit.getMomentum()[2];
71 if (electron_pz > electron_pz_max) {
72 electron_pz_max = electron_pz;
79 ldmx_log(debug) <<
"Electron Found in the Ecal SP!";
82 ldmx_log(debug) <<
"ECAL SP pos_=(" << pos[0] <<
"," << pos[1] <<
","
84 ldmx_log(debug) <<
"ECAL SP mom=(" << mom[0] <<
"," << mom[1] <<
","
86 etraj = {pos[0], pos[1], pos[2]};
90 enorm = {mom[0] / pz, mom[1] / pz, 1.0};
93 }
else if (recoil_from_tracking_) {
95 auto recoil_tracks{
event.getCollection<
ldmx::Track>(track_collection_,
97 ldmx::TrackStateType ts_at_ecal = ldmx::TrackStateType::AtECAL;
98 auto recoil_track_states_ecal =
100 if (!recoil_track_states_ecal.empty()) {
101 std::array<double, 3> pos = {recoil_track_states_ecal[0],
102 recoil_track_states_ecal[1],
103 recoil_track_states_ecal[2]};
104 std::array<double, 3> mom = {(recoil_track_states_ecal[3]),
105 (recoil_track_states_ecal[4]),
106 (recoil_track_states_ecal[5])};
107 ldmx_log(debug) <<
"Electron track pos_=(" << pos[0] <<
"," << pos[1]
108 <<
"," << pos[2] <<
")";
109 ldmx_log(debug) <<
"Electron track mom=(" << mom[0] <<
"," << mom[1]
110 <<
"," << mom[2] <<
")";
114 enorm = {mom[0] / pz, mom[1] / pz, 1.0};
117 ldmx_log(info) <<
" No recoil track at ECAL";
120 ldmx_log(fatal) <<
" No electron hit at scoring plane or no tracking";
124 makeInputs(ecal_geometry, ecal_rec_hits, etraj, enorm);
126 auto logits = rt_->run(INPUT_NAMES, data_)[0];
129 auto prob = std::exp((logSoftmax(logits)[1]));
130 result.setDiscValue(prob);
132 result.setDiscValue(-99);
135 ldmx_log(debug) <<
"ParticleNet disc value = " << result.getDisc();
137 result.setVetoResult(result.getDisc() > disc_cut_);
146 event.add(collection_name_, result);
149void EcalPnetVetoProcessor::makeInputs(
151 const std::vector<ldmx::EcalHit>& ecal_rec_hits,
152 std::array<double, 3> etraj, std::array<double, 3> enorm) {
154 for (
auto& v : data_) {
155 std::fill(v.begin(), v.end(), 0);
160 for (
const auto& hit : ecal_rec_hits) {
161 if (hit.getEnergy() <= 0) {
163 <<
"Hit with zero energy found, should not happen, skipping it.";
169 double delta_z = hit_z - etraj[2];
170 double etraj_x = etraj[0] + enorm[0] * delta_z;
171 double etraj_y = etraj[1] + enorm[1] * delta_z;
172 data_[0].at(COORDINATE_X_OFFSET + idx) = hit_x - etraj_x;
173 data_[0].at(COORDINATE_Y_OFFSET + idx) = hit_y - etraj_y;
174 data_[0].at(COORDINATE_Z_OFFSET + idx) = hit_z;
176 data_[1].at(FEATURE_X_OFFSET + idx) = hit_x - etraj_x;
177 data_[1].at(FEATURE_Y_OFFSET + idx) = hit_y - etraj_y;
178 data_[1].at(FEATURE_Z_OFFSET + idx) = hit_z;
179 data_[1].at(FEATURE_LAYER_ID_OFFSET + idx) =
id.layer();
180 data_[1].at(FEATURE_ENERGY_OFFSET + idx) = std::log(hit.getEnergy());
185 std::stringstream ss;
186 for (
unsigned iname = 0; iname < INPUT_NAMES.size(); ++iname) {
187 ss <<
"=== " << INPUT_NAMES[iname] <<
" ===";
188 for (
unsigned i = 0; i < INPUT_SIZES[iname]; ++i) {
189 ss << data_[iname].at(i) <<
", ";
190 if ((i + 1) % MAX_NUM_HITS == 0) {
195 ldmx_log(trace) << ss.str();
198std::vector<float> EcalPnetVetoProcessor::logSoftmax(
199 const std::vector<float>& logits) {
201 auto max_val = *std::max_element(logits.begin(), logits.end());
204 std::vector<float> exp_vals(logits.size());
205 for (
size_t i = 0; i < logits.size(); ++i) {
206 exp_vals[i] = std::exp(logits[i] - max_val);
209 float sum_exp = std::accumulate(exp_vals.begin(), exp_vals.end(), 0.0);
210 float log_sum_exp = max_val + std::log(sum_exp);
213 std::vector<float> result(logits.size());
214 for (
size_t i = 0; i < logits.size(); ++i) {
215 result[i] = logits[i] - log_sum_exp;