LDMX Software
trigger::TrigMipReco Class Reference

Public Member Functions

 TrigMipReco (const std::string &name, framework::Process &process)
 
void configure (framework::config::Parameters &ps) override
 Callback for the EventProcessor to configure itself from the given set of parameters.
 
void produce (framework::Event &event) override
 Process the event and put new data products into it.
 
void onNewRun (const ldmx::RunHeader &rh) override
 onNewRun is the first function called for each processor after the conditions are fully configured and accessible.
 
void onProcessEnd () override
 Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.
 
- Public Member Functions inherited from framework::Producer
 Producer (const std::string &name, Process &process)
 Class constructor.
 
virtual void process (Event &event) final
 Processing an event for a Producer is calling produce.
 
- Public Member Functions inherited from framework::EventProcessor
 DECLARE_FACTORY (EventProcessor, EventProcessor *, const std::string &, Process &)
 declare that we have a factory for this class
 
 EventProcessor (const std::string &name, Process &process)
 Class constructor.
 
virtual ~EventProcessor ()=default
 Class destructor.
 
virtual void beforeNewRun (ldmx::RunHeader &run_header)
 Callback for Producers to add parameters to the run header before conditions are initialized.
 
virtual void onFileOpen (EventFile &event_file)
 Callback for the EventProcessor to take any necessary action when a new event input ROOT file is opened.
 
virtual void onFileClose (EventFile &event_file)
 Callback for the EventProcessor to take any necessary action when a event input ROOT file is closed.
 
virtual void onProcessStart ()
 Callback for the EventProcessor to take any necessary action when the processing of events starts, such as creating histograms.
 
template<class T >
const T & getCondition (const std::string &condition_name)
 Access a conditions object for the current event.
 
TDirectory * getHistoDirectory ()
 Access/create a directory in the histogram file for this event processor to create histograms and analysis tuples.
 
void setStorageHint (framework::StorageControl::Hint hint)
 Mark the current event as having the given storage control hint from this module_.
 
void setStorageHint (framework::StorageControl::Hint hint, const std::string &purposeString)
 Mark the current event as having the given storage control hint from this module and the given purpose string.
 
int getLogFrequency () const
 Get the current logging frequency from the process.
 
int getRunNumber () const
 Get the run number from the process.
 
std::string getName () const
 Get the processor name.
 
void createHistograms (const std::vector< framework::config::Parameters > &histos)
 Internal function which is used to create histograms passed from the python configuration @parma histos vector of Parameters that configure histograms to create.
 

Private Attributes

int nevents_ {0}
 
double processing_time_ {0.}
 
std::map< std::string, double > profiling_map_
 
std::string hit_coll_name_
 
std::string hit_coll_passname_
 
std::string pass_coll_name_
 
bool calorimeter_type_is_hcal_
 
int max_layer_
 
int min_track_length_
 
float hcal_min_energy_
 
float ecal_min_energy_
 
float ecal_max_energy_
 
float search_radius_
 
float isolation_e_cut_
 
float hole_fraction_max_
 

Additional Inherited Members

- Protected Member Functions inherited from framework::EventProcessor
void abortEvent ()
 Abort the event immediately.
 
- Protected Attributes inherited from framework::EventProcessor
HistogramPool histograms_
 helper object for making and filling histograms
 
NtupleManagerntuple_ {NtupleManager::getInstance()}
 Manager for any ntuples.
 
logging::logger the_log_
 The logger for this EventProcessor.
 

Detailed Description

Definition at line 26 of file TrigMipReco.h.

Constructor & Destructor Documentation

◆ TrigMipReco()

trigger::TrigMipReco::TrigMipReco ( const std::string & name,
framework::Process & process )
inline

Definition at line 28 of file TrigMipReco.h.

Base class for a module which produces a data product.
virtual void process(Event &event) final
Processing an event for a Producer is calling produce.

Member Function Documentation

◆ configure()

void trigger::TrigMipReco::configure ( framework::config::Parameters & parameters)
overridevirtual

Callback for the EventProcessor to configure itself from the given set of parameters.

The parameters a processor has access to are the member variables of the python class in the sequence that has className equal to the EventProcessor class name.

For an example, look at MyProcessor.

Parameters
parametersParameters for configuration.

Reimplemented from framework::EventProcessor.

Definition at line 9 of file TrigMipReco.cxx.

9 {
10 hit_coll_name_ = ps.get<std::string>("hit_coll_name");
11 pass_coll_name_ = ps.get<std::string>("pass_coll_name");
12 hit_coll_passname_ = ps.get<std::string>("hit_coll_passname");
13 calorimeter_type_is_hcal_ = ps.get<bool>("calorimeter_type_is_hcal");
14
15 max_layer_ = ps.get<int>("max_layer", 32);
16 // mm
17 search_radius_ = ps.get<float>("search_radius", 50.0f);
18 min_track_length_ = ps.get<int>("min_track_length", 5);
19 // MeV; Change as needed
20 isolation_e_cut_ = ps.get<float>("isolation_e_cut", 180.0f);
21 hole_fraction_max_ = ps.get<float>("hole_fraction_max", 0.2f);
22
23 if (calorimeter_type_is_hcal_) {
24 // MIP peak is 10-11 MeV
25 hcal_min_energy_ = ps.get<float>("hcal_min_energy", 8.0f);
26 } else { // ECAL
27 // MIP peak around 17 MeV
28 ecal_min_energy_ = ps.get<float>("ecal_min_energy", 3.0f);
29 ecal_max_energy_ = ps.get<float>("ecal_max_energy", 26.0f);
30 }
31}

References framework::config::Parameters::get().

◆ onNewRun()

void trigger::TrigMipReco::onNewRun ( const ldmx::RunHeader & rh)
overridevirtual

onNewRun is the first function called for each processor after the conditions are fully configured and accessible.

This is where you could create single-processors, multi-event calculation objects.

Reimplemented from framework::EventProcessor.

Definition at line 5 of file TrigMipReco.cxx.

5 {
6 profiling_map_["processing_time_"] = 0;
7}

◆ onProcessEnd()

void trigger::TrigMipReco::onProcessEnd ( )
overridevirtual

Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.

Reimplemented from framework::EventProcessor.

Definition at line 303 of file TrigMipReco.cxx.

303 {
304 ldmx_log(info) << "AVG Time/Event: " << std::fixed << std::setprecision(3)
305 << processing_time_ / nevents_ << " ms";
306}

◆ produce()

void trigger::TrigMipReco::produce ( framework::Event & event)
overridevirtual

Process the event and put new data products into it.

Parameters
eventThe Event to process.

Implements framework::Producer.

Definition at line 33 of file TrigMipReco.cxx.

33 {
34 auto start = std::chrono::high_resolution_clock::now();
35 nevents_++;
36
37 if (!event.exists(hit_coll_name_, hit_coll_passname_)) return;
38
39 const auto calo_hits = event.getObject<std::vector<TrigCaloHit>>(
40 hit_coll_name_, hit_coll_passname_);
41
42 if (calorimeter_type_is_hcal_) { // HCAL MIP Reconstruction
43 std::vector<TrigCaloHit> sorted_hits;
44 int even_matrix[24][5] = {};
45 int even_start[5] = {99, 99, 99, 99, 99};
46 int even_end[5] = {};
47 int even_counts[5] = {};
48 int odd_matrix[24][5] = {};
49 int odd_start[5] = {99, 99, 99, 99, 99};
50 int odd_end[5] = {};
51 int odd_counts[5] = {};
52 // Start in first 5 layers
53 constexpr int layer_start = 80;
54
55 for (const auto& tp : calo_hits) {
56 if (tp.section() > 0 || tp.energy() < hcal_min_energy_ ||
57 tp.layer() > 47) {
58 continue;
59 }
60
61 sorted_hits.push_back(tp);
62 const int layer_index = tp.layer() / 2;
63 const int strip = tp.strip();
64 if (tp.layer() % 2) {
65 odd_matrix[layer_index][strip] = 1;
66 odd_start[strip] = std::min(odd_start[strip], tp.layer());
67 odd_end[strip] = std::max(odd_end[strip], tp.layer());
68 } else {
69 even_matrix[layer_index][strip] = 1;
70 even_start[strip] = std::min(even_start[strip], tp.layer());
71 even_end[strip] = std::max(even_end[strip], tp.layer());
72 }
73 }
74
75 for (int i = 0; i < 24; i++) {
76 for (int j = 0; j < 5; j++) {
77 if (even_matrix[i][j]) {
78 even_counts[j]++;
79 }
80 if (odd_matrix[i][j]) {
81 odd_counts[j]++;
82 }
83 }
84 }
85
86 // straight MIP reco
87 std::vector<TrigMip> mips;
88 // 5 elements in the even/odd_start matrices
89 for (int i = 0; i < 5; i++) {
90 if (odd_start[i] < layer_start) {
91 TrigMip m;
92 m.setStartLayer(odd_start[i]);
93 m.setEndLayer(odd_end[i]);
94 m.setNHits(odd_counts[i]);
95 m.setLength(odd_end[i] - odd_start[i] + 1);
96 int holes = m.length() / 2 - m.nHits();
97 if (holes < 0) {
98 holes = 0;
99 }
100 m.setNHoles(holes);
101 mips.push_back(m);
102 }
103 if (even_start[i] < layer_start) {
104 TrigMip m;
105 m.setStartLayer(even_start[i]);
106 m.setEndLayer(even_end[i]);
107 m.setNHits(even_counts[i]);
108 m.setLength(even_end[i] - even_start[i] + 1);
109 int holes = m.length() / 2 - m.nHits();
110 if (holes < 0) {
111 holes = 0;
112 }
113 m.setNHoles(holes);
114 mips.push_back(m);
115 }
116 }
117
118 std::sort(mips.begin(), mips.end());
119 event.add(pass_coll_name_, mips);
120
121 auto end = std::chrono::high_resolution_clock::now();
122 auto time_diff = end - start;
123 processing_time_ +=
124 std::chrono::duration<double, std::milli>(time_diff).count();
125
126 return;
127 // ECAL MIP Reconstruction
128 } else {
129 const float radius_cut_2 = search_radius_ * search_radius_;
130 std::map<int, std::vector<TrigCaloHit>> layer_hits;
131 std::set<const TrigCaloHit*> used_hits;
132 std::vector<std::vector<const TrigCaloHit*>> candidate_tracks;
133 std::map<const TrigCaloHit*, size_t> hit_to_best_track;
134
135 // Filter for section = 0 and hits < 33 layers
136 for (const auto& hit : calo_hits) {
137 if (hit.section() > 0 || hit.layer() > max_layer_) continue;
138 layer_hits[hit.layer()].push_back(hit);
139 }
140
141 // Find mip seeds
142 for (const auto& [seed_layer, seeds] : layer_hits) {
143 for (const auto& seed : seeds) {
144 // Skip if hit already used or outside mip energy range
145 if (used_hits.count(&seed) || seed.energy() < ecal_min_energy_ ||
146 seed.energy() > ecal_max_energy_) {
147 continue;
148 }
149
150 std::vector<const TrigCaloHit*> track{&seed};
151 // Most recent hit in track
152 const TrigCaloHit* last = &seed;
153 int holes = 0;
154 float growth_factor = 1.0f;
155
156 // Look layer by layer for next hit within dR
157 for (int l = seed.layer() + 1; l <= max_layer_; ++l) {
158 const TrigCaloHit* best_hit = nullptr;
159 // Grow search window if there is a hole
160 float best_d_r_2 = radius_cut_2 * growth_factor * growth_factor;
161
162 for (const auto& cand : layer_hits[l]) {
163 if (used_hits.count(&cand) || cand.energy() < ecal_min_energy_ ||
164 cand.energy() > ecal_max_energy_) {
165 continue;
166 }
167
168 // Corrects for layer shift in x-direction, calculated as 4.82 mm
169 const float layer_shift_last =
170 (last->layer() % 2 == 0) ? 0.0f : 4.82f;
171 const float layer_shift_cand =
172 (cand.layer() % 2 == 0) ? 0.0f : 4.82f;
173 const float dx = (cand.positionX() - layer_shift_cand) -
174 (last->positionX() - layer_shift_last);
175 const float dy = cand.positionY() - last->positionY();
176 const float d_r_2 = dx * dx + dy * dy;
177
178 if (d_r_2 < best_d_r_2) {
179 best_d_r_2 = d_r_2;
180 // Closest unused hit in next layer
181 best_hit = &cand;
182 }
183 }
184
185 if (best_hit) {
186 // Builds track from best hits
187 track.push_back(best_hit);
188 last = best_hit;
189 holes = 0;
190 // Reset search window
191 growth_factor = 1.0f;
192 } else {
193 holes++;
194 // Keep expanding
195 growth_factor = static_cast<float>(holes + 1);
196 }
197 }
198
199 bool is_isolated = true;
200 if (track.size() >= min_track_length_) {
201 // Isolation area energy check
202 for (const auto* hit : track) {
203 const int layer = hit->layer();
204 const float hit_x = hit->positionX();
205 const float hit_y = hit->positionY();
206 float sum_e = 0.0f;
207
208 for (const auto& cand : layer_hits[layer]) {
209 // Skips self
210 if (&cand == hit) continue;
211
212 const float dx = cand.positionX() - hit_x;
213 const float dy = cand.positionY() - hit_y;
214 const float d_r_2 = dx * dx + dy * dy;
215
216 if (d_r_2 < radius_cut_2) {
217 sum_e += cand.energy();
218 }
219 }
220
221 if (sum_e >= isolation_e_cut_) {
222 is_isolated = false;
223 // Adds used hits to vector so they cannot be used again
224 used_hits.insert(hit);
225 break;
226 }
227 }
228
229 if (!is_isolated) {
230 // Reject track if any hit is not isolated
231 continue;
232 }
233
234 const size_t i = candidate_tracks.size();
235 candidate_tracks.push_back(track);
236
237 for (const auto* hit : track) {
238 if (!hit_to_best_track.count(hit) ||
239 candidate_tracks[i].size() >
240 candidate_tracks[hit_to_best_track[hit]].size()) {
241 hit_to_best_track[hit] = i;
242 // Adds used hits to vector so they cannot be used again
243 used_hits.insert(hit);
244 }
245 }
246 }
247 }
248 }
249
250 std::set<size_t> valid_track_i_ds;
251 for (const auto& [hit, idx] : hit_to_best_track) {
252 valid_track_i_ds.insert(idx);
253 }
254
255 std::vector<TrigMip> mips;
256 for (const size_t idx : valid_track_i_ds) {
257 const auto& track = candidate_tracks[idx];
258 TrigMip mip;
259 mip.setStartLayer(track.front()->layer());
260 mip.setEndLayer(track.back()->layer());
261 mip.setNHits(track.size());
262 mip.setLength(track.back()->layer() - track.front()->layer());
263 int holes = mip.length() - mip.nHits();
264 if (holes < 0) {
265 holes = 0;
266 }
267 mip.setNHoles(holes);
268
269 const float hole_fraction =
270 static_cast<float>(mip.nHoles()) / mip.length();
271 // Remove mip tracks with hole fraction > 0.2
272 if (hole_fraction >= hole_fraction_max_) continue;
273
274 float total_isolation_e_sum = 0.0f;
275 for (const auto* hit : track) {
276 const int layer = hit->layer();
277 const float hit_x = hit->positionX();
278 const float hit_y = hit->positionY();
279 for (const auto& cand : layer_hits[layer]) {
280 if (&cand == hit) continue;
281 const float dx = cand.positionX() - hit_x;
282 const float dy = cand.positionY() - hit_y;
283 const float d_r_2 = dx * dx + dy * dy;
284 if (d_r_2 < radius_cut_2) {
285 total_isolation_e_sum += cand.energy();
286 }
287 }
288 }
289 mip.setSumEinIsolationRegion(total_isolation_e_sum);
290 mips.push_back(mip);
291 }
292
293 std::sort(mips.begin(), mips.end());
294 event.add(pass_coll_name_, mips);
295 }
296
297 auto end = std::chrono::high_resolution_clock::now();
298 auto time_diff = end - start;
299 processing_time_ +=
300 std::chrono::duration<double, std::milli>(time_diff).count();
301}
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

References framework::Event::exists().

Member Data Documentation

◆ calorimeter_type_is_hcal_

bool trigger::TrigMipReco::calorimeter_type_is_hcal_
private

Definition at line 58 of file TrigMipReco.h.

◆ ecal_max_energy_

float trigger::TrigMipReco::ecal_max_energy_
private

Definition at line 67 of file TrigMipReco.h.

◆ ecal_min_energy_

float trigger::TrigMipReco::ecal_min_energy_
private

Definition at line 65 of file TrigMipReco.h.

◆ hcal_min_energy_

float trigger::TrigMipReco::hcal_min_energy_
private

Definition at line 63 of file TrigMipReco.h.

◆ hit_coll_name_

std::string trigger::TrigMipReco::hit_coll_name_
private

Definition at line 53 of file TrigMipReco.h.

◆ hit_coll_passname_

std::string trigger::TrigMipReco::hit_coll_passname_
private

Definition at line 54 of file TrigMipReco.h.

◆ hole_fraction_max_

float trigger::TrigMipReco::hole_fraction_max_
private

Definition at line 74 of file TrigMipReco.h.

◆ isolation_e_cut_

float trigger::TrigMipReco::isolation_e_cut_
private

Definition at line 71 of file TrigMipReco.h.

◆ max_layer_

int trigger::TrigMipReco::max_layer_
private

Definition at line 60 of file TrigMipReco.h.

◆ min_track_length_

int trigger::TrigMipReco::min_track_length_
private

Definition at line 61 of file TrigMipReco.h.

◆ nevents_

int trigger::TrigMipReco::nevents_ {0}
private

Definition at line 49 of file TrigMipReco.h.

49{0};

◆ pass_coll_name_

std::string trigger::TrigMipReco::pass_coll_name_
private

Definition at line 56 of file TrigMipReco.h.

◆ processing_time_

double trigger::TrigMipReco::processing_time_ {0.}
private

Definition at line 50 of file TrigMipReco.h.

50{0.};

◆ profiling_map_

std::map<std::string, double> trigger::TrigMipReco::profiling_map_
private

Definition at line 51 of file TrigMipReco.h.

◆ search_radius_

float trigger::TrigMipReco::search_radius_
private

Definition at line 69 of file TrigMipReco.h.


The documentation for this class was generated from the following files: