42 cluster_coll_name_ = ps.
get<std::string>(
"cluster_coll_name");
43 ecal_sum_coll_name_ = ps.
get<std::string>(
"ecal_sum_coll_name");
44 hcal_sum_coll_name_ = ps.
get<std::string>(
"hcal_sum_coll_name");
45 input_pass_ = ps.
get<std::string>(
"input_pass");
46 score_coll_name_ = ps.
get<std::string>(
"score_coll_name");
48 const auto model_path{ps.
get<std::string>(
"model_path")};
49 if (model_path.empty()) {
50 EXCEPTION_RAISE(
"NoModel",
51 "model_path is empty. Pass the path to "
52 "ecal_nn_trigger.onnx.");
54 rt_ = std::make_unique<ldmx::ort::ONNXRuntime>(model_path);
57 const std::vector<int64_t> expected_shape{-1,
58 static_cast<int64_t
>(N_CLASSES)};
59 const auto& outputs = rt_->getOutputNames();
60 if (std::find(outputs.begin(), outputs.end(),
"logits") == outputs.end() or
61 rt_->getOutputShape(
"logits") != expected_shape) {
62 EXCEPTION_RAISE(
"BadModel",
"Model '" + model_path +
63 "' does not have a 'logits' output of "
65 std::to_string(N_CLASSES) +
").");
70 const auto start = std::chrono::high_resolution_clock::now();
77 const auto& ecal_sums{
78 event.getCollection<
TrigEnergySum>(ecal_sum_coll_name_, input_pass_)};
79 const auto& hcal_sums{
80 event.getCollection<
TrigEnergySum>(hcal_sum_coll_name_, input_pass_)};
82 fillInputs(clusters, ecal_sums, hcal_sums, data_[0]);
83 const auto inference_start = std::chrono::high_resolution_clock::now();
84 const auto logits{rt_->run({
"x"}, data_, {
"logits"})[0]};
86 std::chrono::duration<double, std::milli>(
87 std::chrono::high_resolution_clock::now() - inference_start)
91 const double p_bkg = std::exp(logSoftmax(logits)[BKG_CLASS]);
93 ldmx_log(debug) <<
"n_clusters = " << clusters.size()
94 <<
", P(bkg) = " << p_bkg;
97 score.setLogits(logits);
99 event.add(score_coll_name_, score);
101 processing_time_ += std::chrono::duration<double, std::milli>(
102 std::chrono::high_resolution_clock::now() - start)
113void TrigClusterNNProducer::fillInputs(
114 const TrigCaloClusterCollection& clusters,
115 const TrigEnergySumCollection& ecal_sums,
116 const TrigEnergySumCollection& hcal_sums, std::vector<float>& inputs) {
117 inputs.assign(MAX_CLUSTERS * N_FEATURES, 0.f);
120 std::vector<std::size_t> order(clusters.size());
121 std::iota(order.begin(), order.end(), 0);
122 std::stable_sort(order.begin(), order.end(),
123 [&clusters](
const std::size_t lhs,
const std::size_t rhs) {
124 return clusters[lhs].e() > clusters[rhs].e();
127 double ecal_sum_e = 0.;
128 for (
const auto& sum : ecal_sums) ecal_sum_e += sum.energy();
130 int hcal_sum_adc = 0;
131 for (
const auto& sum : hcal_sums) hcal_sum_adc += sum.hwEnergy();
133 for (std::size_t slot = 0; slot < MAX_CLUSTERS; ++slot) {
134 float* feats = &inputs[slot * N_FEATURES];
135 if (slot < order.size()) {
136 const auto& cluster = clusters[order[slot]];
137 feats[FEAT_X] = cluster.x();
138 feats[FEAT_Y] = cluster.y();
139 feats[FEAT_Z] = cluster.z();
140 feats[FEAT_E] = cluster.e();
141 feats[FEAT_DEPTH] = cluster.depth();
142 feats[FEAT_N_TP] = cluster.nTP();
145 feats[FEAT_N_CLUSTERS] = clusters.size();
146 feats[FEAT_ECAL_SUM_E] = ecal_sum_e;
147 feats[FEAT_HCAL_SUM_ADC] = hcal_sum_adc;