LDMX Software
OverlayProducer.cxx
1#include "Recon/OverlayProducer.h"
2
3#include <algorithm>
4#include <bitset>
5#include <map>
6
7#include "Framework/Exception/Exception.h"
10#include "SimCore/Event/SimParticle.h"
12
13namespace recon {
14
16 params_ = parameters;
17
18 // name of file containing events to be overlaid, and a list of collections to
19 // overlay
20 overlay_filename_ = parameters.get<std::string>("overlay_filename");
22 parameters.get<std::vector<std::string>>("calo_collections");
24 parameters.get<std::vector<std::string>>("tracker_collections");
26 parameters.get<std::vector<std::string>>("particle_collections");
28 parameters.get<std::vector<std::string>>("contrib_collections");
29 sim_passname_ = parameters.get<std::string>("sim_passname");
30 overlay_passname_ = parameters.get<std::string>("overlay_passname");
31 out_coll_postfix_ = parameters.get<std::string>("out_coll_postfix");
32 // overlay specifics:
33 poisson_mu_ = parameters.get<double>("poisson_mu");
34 do_poisson_in_time_ = parameters.get<bool>("do_poisson_in_time");
35 do_poisson_out_of_time_ = parameters.get<bool>("do_poisson_out_of_time");
36 time_sigma_ = parameters.get<double>("time_sigma");
37 time_mean_ = parameters.get<double>("time_mean");
38 n_earlier_ = parameters.get<int>("n_earlier");
39 n_later_ = parameters.get<int>("n_later");
40 bunch_spacing_ = parameters.get<double>("bunch_spacing");
41 start_event_min_ = parameters.get<int>("start_event_min");
42 start_event_max_ = parameters.get<int>("start_event_max");
43 track_id_encoding_ = unsigned(parameters.get<int>("track_id_encoding", 0));
44
46 ldmx_log(debug) << "Got parameters \n \t overlayFileName = "
48 << "\n\t sim pass name = " << sim_passname_
49 << "\n\t overlay pass name = " << overlay_passname_;
50 ldmx_log(debug) << "\n\t overlayCaloHitCollections = ";
51 for (const auto& coll : calo_collections_) {
52 ldmx_log(debug) << coll << "; ";
53 }
54
55 ldmx_log(debug) << "\n\t overlayTrackerHitCollections = ";
56 for (const std::string& coll : tracker_collections_) {
57 ldmx_log(debug) << coll << "; ";
58 }
59
60 ldmx_log(debug) << "\n\t overlayParticleCollections = ";
61 for (const std::string& coll : particle_collections_) {
62 ldmx_log(debug) << coll << "; ";
63 }
64
65 ldmx_log(trace) << "\n\t numberOverlaidInteractions = " << poisson_mu_
66 << "\n\t nEarlierBunchesToSample = " << n_earlier_
67 << "\n\t nLaterBunchesToSample = " << n_later_
68 << "\n\t bunchSpacing = " << bunch_spacing_
69 << "\n\t doPoissonIntime = " << do_poisson_in_time_
70 << "\n\t doPoissonOutoftime = " << do_poisson_out_of_time_
71 << "\n\t timeSpread = " << time_sigma_
72 << "\n\t timeMean = " << time_mean_
73 << "\n\t startEventMin = " << start_event_min_
74 << "\n\t startEventMax = " << start_event_max_;
75
76 // given how the contrib collection specification is setup, it's possible for
77 // spelling errors to cause doom here, so we want to flag those
78 for (auto coll_name : contrib_collections_) {
79 if (std::find(calo_collections_.begin(), calo_collections_.end(),
80 coll_name) == calo_collections_.end()) {
81 EXCEPTION_RAISE("CollNameMismatch",
82 "The contrib-using collection " + coll_name +
83 " does not match any SimCalorimeterHit collection in "
84 "'calo_collections_'! Please check your spelling");
85 }
86 }
87
88 return;
89} // end configure()
90
95 rndm_ = std::make_unique<TRandom2>(rnss.getSeed("OverlayProducer::rndm"));
97 std::make_unique<TRandom2>(rnss.getSeed("OverlayProducer::rndmTime"));
98
99 // Pick a random event from the Pileup file
100 int start_event = rndm_->Uniform(start_event_min_, start_event_max_);
101 // EventFile::skipToEvent handles actual number of events in file
102 int ev_number = overlay_file_->skipToEvent(start_event);
103 if (ev_number < 0) {
104 EXCEPTION_RAISE("BadRead", "Couldn't read to starting offset.");
105 }
107 ldmx_log(info) << "Starting overlay process with pileup event number "
108 << ev_number << " (random event number picked was "
109 << start_event << ").";
110} // end onNewRun()
111
113 // using nextEvent to loop, we need to loop over overlay events and in an
114 // inner loop, loop over collections, and store them. after all pileup events
115 // have been added, the vector of collections is iterated over and added to
116 // the event bus.
117 std::map<std::string, std::vector<ldmx::SimCalorimeterHit>>
118 calo_collection_map;
119 std::map<std::string, std::vector<ldmx::SimTrackerHit>>
120 tracker_collection_map;
121 std::map<std::string, std::map<int, ldmx::SimParticle>>
122 particle_collection_map;
123 std::map<std::string, std::map<int, ldmx::SimCalorimeterHit>> hit_map;
124
125 // start by copying over all the collections from the sim event
126
127 /* ----------- first do the SimCalorimeterHits ----------- */
128
129 // get the calo hits_ collections that we want to overlay, by looping over
130 // the list of collections passed to the producer : calo_collections_
131 for (const auto& coll_name : calo_collections_) {
132 // search for the collection name in the list of collections that
133 // need contribs to be added, contrib_collections_
134 bool needs_contribs_added{std::find(contrib_collections_.begin(),
136 coll_name) != contrib_collections_.end()
137 ? true
138 : false};
139
140 // start out by just copying the sim hits, unaltered.
141 auto simhits_calo =
142 event.getCollection<ldmx::SimCalorimeterHit>(coll_name, sim_passname_);
143 // but don't copy contrib using hits immediately: for them, wait until
144 // overlay contribs have been added. then add everything through the hit_map
145 if (!needs_contribs_added) {
146 calo_collection_map[coll_name + out_coll_postfix_] = simhits_calo;
147 // after copying, perform track ID encodings;
148 // the main sample gets the event index 0 by default
149 for (auto& simhit : calo_collection_map[coll_name + out_coll_postfix_]) {
150 simhit.encodeTracks(
151 [this](int id, unsigned enc, unsigned idx) {
152 return encodeTrack(id, enc, idx);
153 },
154 track_id_encoding_, (unsigned)0);
155 }
156 }
157
158 ldmx_log(debug) << "in loop: start of collection " << coll_name
159 << "in loop: printing current sim event: ";
160 ldmx_log(debug) << "in loop: size of sim hits_ vector " << coll_name
161 << " is " << simhits_calo.size();
162
163 // we don't need to touch the hard process sim hits_, really... but we
164 // might need the simhits in the hit map.
165 if (needs_contribs_added) {
166 ldmx_log(trace) << "Collection " << coll_name << " needs contribs added";
167 for (const ldmx::SimCalorimeterHit& simhit : simhits_calo) {
168 ldmx_log(trace) << simhit;
169 // this copies the hit, its ID and its coordinates directly
170 hit_map[coll_name + out_coll_postfix_][simhit.getID()] = simhit;
171 // now encode track IDs on copied object
172 hit_map[coll_name + out_coll_postfix_][simhit.getID()].encodeTracks(
173 [this](int id, unsigned enc, unsigned idx) {
174 return encodeTrack(id, enc, idx);
175 },
176 track_id_encoding_, (unsigned)0);
177 } // over calo simhit collection
178 } // if needContribs
179
180 } // over calo collections for sim event
181
182 /* ----------- then do the same with SimTrackerHits! ----------- */
183
184 // get the SimTrackerHit collections that we want to overlay, by looping
185 // over the list of collections passed to the producer : tracker_collections_
186 for (const auto& coll_name : tracker_collections_) {
187 auto simhits_tracker =
188 event.getCollection<ldmx::SimTrackerHit>(coll_name, sim_passname_);
189 tracker_collection_map[coll_name + out_coll_postfix_] = simhits_tracker;
190 // after copying, perform track ID encoding
191 for (auto& simhit : tracker_collection_map[coll_name + out_coll_postfix_]) {
192 int encoded_track_id =
193 encodeTrack(simhit.getTrackID(), track_id_encoding_, (unsigned)0);
194 simhit.setTrackID(encoded_track_id);
195 }
196
197 // the rest is printouts for debugging
198 ldmx_log(debug) << "in loop: size of sim hits_ vector " << coll_name
199 << " is " << simhits_tracker.size();
200
201 ldmx_log(debug) << "in loop: start of collection " << coll_name
202 << "in loop: printing current sim event: ";
203
204 for (const ldmx::SimTrackerHit& simhit : simhits_tracker) {
205 ldmx_log(trace) << simhit;
206 }
207 } // over tracker collections for sim event
208
209 /* ----------- and finish up with SimParticles ----------- */
210
211 // get the SimParticle collections that we want to overlay, by looping
212 // over the list of collections passed to the producer : particle_collections_
213 for (const auto& coll_name : particle_collections_) {
214 auto sim_particles =
215 event.getMap<int, ldmx::SimParticle>(coll_name, sim_passname_);
216 auto& output_map = particle_collection_map[coll_name + out_coll_postfix_];
217
218 ldmx_log(debug) << "in loop: size of sim particles map " << coll_name
219 << " is " << sim_particles.size();
220
221 ldmx_log(debug) << "in loop: start of collection " << coll_name
222 << "in loop: printing current sim event: ";
223
224 // need to copy SimParticles individually because of std::map key
225 // immutability
226 for (auto& [track_id, particle] : sim_particles) {
227 int encoded_track_id =
228 encodeTrack(track_id, track_id_encoding_, (unsigned)0);
229 output_map[encoded_track_id] = particle;
230 output_map[encoded_track_id].encodeTracks(
231 [this](int id, unsigned enc, unsigned idx) {
232 return encodeTrack(id, enc, idx);
233 },
234 track_id_encoding_, (unsigned)0);
235 ldmx_log(trace) << particle;
236 }
237 } // over particle collections for sim event
238
239 /* ----------- now do the overlay ----------- */
240
241 // we could shift these by a random number, effectively placing the
242 // sim event at random positions in the interval, preserving the
243 // overall interval length
244 // int simBunch= static_cast<int>(rndm_time_->Uniform(
245 // -(n_earlier_+1) , n_later_+1)); // +1 to get
246 // inclusive interval
247 int start_bunch = -n_earlier_;
248 int end_bunch = n_later_;
249
250 // TODO -- figure out if we should also randomly shift the time of the sim
251 // event (likely only needed if time bias gets picked up by BDT or ML by way
252 // of pulse behaviour)
253 for (int bunch_offset{start_bunch}; bunch_offset <= end_bunch;
254 bunch_offset++) {
255 // sample a poisson distribution, or use mu as fixed number of overlay
256 // events
257 int n_events_overlay = do_poisson_out_of_time_
258 ? rndm_->Poisson(poisson_mu_)
259 : static_cast<int>(poisson_mu_);
260
261 // special case: in-time pileup at bunch 0
262 if (bunch_offset == 0) {
263 if (!do_poisson_in_time_) {
264 // fix it to the average
265 n_events_overlay = static_cast<int>(poisson_mu_);
267 // then we haven't set this yet
268 n_events_overlay = rndm_->Poisson(poisson_mu_);
269 }
270
271 // paticularly useful in the poisson fluctuated case
272 event.getEventHeader().setIntParameter("in_time_pu", n_events_overlay);
273
274 // the total number of events is nPU + 1 (it includes the sim event)
275 // in any case, subtract the sim event from nOverlay
276 n_events_overlay -= 1;
277
278 } // end if bunch_offset == 0
279
280 float bunchtime_offset = bunch_spacing_ * bunch_offset;
281 ldmx_log(debug) << "Will overlay " << n_events_overlay
282 << " events on the simulated one";
283
284 for (int i_ev = 0; i_ev < n_events_overlay; i_ev++) {
291 if (!overlay_file_->nextEvent()) {
292 ldmx_log(error) << "Couldn't read next overlay event!";
293 return;
294 }
295 if (i_ev + 1 > 7) {
296 ldmx_log(error) << "Too many overlay events! Maximum events that can "
297 "be overlayed is 7.";
298 return;
299 }
300
301 // a pileup event wide time offset to be applied to all its hits_.
302 float time_offset = rndm_time_->Gaus(time_mean_, time_sigma_);
303 time_offset += bunchtime_offset;
304
305 ldmx_log(trace) << "in overlay loop: overlaying event " << "which is "
306 << i_ev + 1 << " out of " << n_events_overlay
307 << "\n\thit time offset is " << time_offset << " ns"
308 << "\n\tbunch position offset is " << bunch_offset
309 << ", leading to a total time offset of "
310 << bunchtime_offset << " ns";
311
312 /* ----------- first do the SimCalorimeterHits overlay ----------- */
313
314 // again get the calo hits_ collections that we want to overlay
315 for (uint i_coll = 0; i_coll < calo_collections_.size(); i_coll++) {
316 // search for the collection name in the list of collections that
317 // need contribs to be added, contrib_collections_
318 bool needs_contribs_added{
319 std::find(contrib_collections_.begin(), contrib_collections_.end(),
321 ? true
322 : false};
323
324 std::vector<ldmx::SimCalorimeterHit> overlay_hits =
327
328 ldmx_log(debug) << "in loop: size of overlay hits_ vector is "
329 << overlay_hits.size();
330
331 std::string out_coll_name =
333
334 ldmx_log(trace) << "in loop: printing overlay event: ";
335
336 for (ldmx::SimCalorimeterHit& overlay_hit : overlay_hits) {
337 ldmx_log(trace) << overlay_hit;
338
339 // update relevant parameters with overlay modifications
340 overlay_hit.setTime(overlay_hit.getTime() + time_offset);
341 overlay_hit.setPreStepTime(overlay_hit.getPreStepTime() +
342 time_offset);
343 overlay_hit.setPostStepTime(overlay_hit.getPostStepTime() +
344 time_offset);
345 overlay_hit.encodeTracks(
346 [this](int id, unsigned enc, unsigned idx) {
347 return encodeTrack(id, enc, idx);
348 },
349 track_id_encoding_, i_ev + 1);
350
351 if (needs_contribs_added) { // special treatment for (for now only)
352 // ecal
353 auto& this_coll_hit_map{
354 hit_map[calo_collections_[i_coll] + out_coll_postfix_]};
355 int overlay_hit_id = overlay_hit.getID();
356 if (this_coll_hit_map.find(overlay_hit_id) ==
357 this_coll_hit_map
358 .end()) { // there wasn't already a simhit in this id
359 ldmx_log(trace)
360 << "No existing simhit found for ID " << overlay_hit_id
361 << "; copying overlay hit to output collection";
362 auto& output_hit = this_coll_hit_map[overlay_hit_id];
363 output_hit = overlay_hit; // copy hit
364
365 // we need to do some backflips to get the contribs correct later
366 auto id = output_hit.getID();
367 auto pos = output_hit.getPosition();
368 auto time = output_hit.getTime();
369 output_hit.clear(); // with the below adjustments, this will only
370 // clear contribs from the output_hit
371 output_hit.setID(id);
372 output_hit.setPosition(pos[0], pos[1], pos[2]);
373 output_hit.setTime(time);
374 } // if overlay_hit_id not present
375
376 // add the overlay hit contribs to existing hit,
377 // incrementing track IDs and timestamp as needed
378 int n_contribs = overlay_hit.getNumberOfContribs();
379 ldmx_log(trace)
380 << "Copying and reindexing " << n_contribs
381 << " contributors to the sim hit for ID " << overlay_hit_id;
382 for (int i = 0; i < n_contribs; i++) {
384 overlay_hit.getContrib(i)};
385 // tracks were encoded in-place above, so we only need to worry
386 // about times
387 this_coll_hit_map[overlay_hit_id].addContrib(
388 contrib.incident_id_, contrib.track_id_, contrib.pdg_code_,
389 contrib.edep_, contrib.time_ + time_offset,
390 contrib.origin_id_ + i_ev + 1);
391 } // loop over contribs in overlay_hit
392 ldmx_log(trace)
393 << "There are now "
394 << this_coll_hit_map[overlay_hit_id].getNumberOfContribs()
395 << " total contributors in the output collection";
396 } // if add overlay as contribs
397 else {
398 // no need to change contrib timestamps here
399 calo_collection_map[out_coll_name].push_back(overlay_hit);
400
401 ldmx_log(trace) << "Adding non-Ecal overlay hit to outhit vector "
402 << out_coll_name;
403 } // end else !needs_contribs_added
404 } // over overlay calo simhit collection
405
406 if (!needs_contribs_added)
407 ldmx_log(debug) << "Nhits in overlay collection " << out_coll_name
408 << ": " << calo_collection_map[out_coll_name].size();
409
410 } // over calo_collections_
411
412 /* ----------- now do simtracker hits_ overlay ----------- */
413
414 // loop over the SimTrackerHit collections that we want to overlay
415 for (const auto& coll : tracker_collections_) {
416 auto overlay_tracker_hits{
418 coll, overlay_passname_)};
419
420 ldmx_log(debug) << "in loop: size of overlay hits_ vector is "
421 << overlay_tracker_hits.size();
422
423 std::string out_coll_name_tracker{coll + out_coll_postfix_};
424
425 ldmx_log(trace) << "in loop: printing overlay event: ";
426
427 for (auto& overlay_hit : overlay_tracker_hits) {
428 auto overlay_time{overlay_hit.getTime() + time_offset};
429 overlay_hit.setTime(overlay_time);
430 auto overlay_track_id{encodeTrack(overlay_hit.getTrackID(),
431 track_id_encoding_, i_ev + 1)};
432 overlay_hit.setTrackID(overlay_track_id);
433
434 ldmx_log(trace) << overlay_hit;
435 ldmx_log(trace) << "Adding tracker overlay hit to outhit vector "
436 << out_coll_name_tracker;
437
438 tracker_collection_map[out_coll_name_tracker].push_back(overlay_hit);
439 } // over overlay tracker simhit collection
440
441 ldmx_log(debug) << "Nhits in overlay collection "
442 << out_coll_name_tracker << ": "
443 << tracker_collection_map[out_coll_name_tracker].size();
444
445 } // over tracker_collections_
446
447 /* ----------- finally do SimParticles overlay ----------- */
448 for (const auto& coll : particle_collections_) {
449 auto overlay_particles{overlay_event_.getMap<int, ldmx::SimParticle>(
450 coll, overlay_passname_)};
451
452 ldmx_log(debug) << "in loop: size of overlay particles map is "
453 << overlay_particles.size();
454
455 std::string out_coll_name_particles{coll + out_coll_postfix_};
456 auto& output_map = particle_collection_map[out_coll_name_particles];
457
458 ldmx_log(trace) << "in loop: printing overlay event: ";
459
460 for (auto& [track_id, particle] : overlay_particles) {
461 int new_track_id =
462 encodeTrack(track_id, track_id_encoding_, i_ev + 1);
463
464 output_map[new_track_id] = particle;
465 output_map[new_track_id].encodeTracks(
466 [this](int id, unsigned enc, unsigned idx) {
467 return encodeTrack(id, enc, idx);
468 },
469 track_id_encoding_, i_ev + 1);
470 output_map[new_track_id].setTime(particle.getTime() + time_offset);
471
472 ldmx_log(trace) << "Track ID: " << new_track_id << " --- "
473 << output_map[new_track_id];
474 ldmx_log(trace) << "Adding sim particle to output map "
475 << out_coll_name_particles;
476 } // over overlay sim particles collection
477 } // over particle_collections_
478 } // over overlay events
479 } // over bunches
480
481 // after all events are done, the contrib-using collections' hit_maps are
482 // final and can be written to the event output
483 for (uint i_coll = 0; i_coll < contrib_collections_.size(); i_coll++) {
484 // for each SimCalorimeterHit collection that uses contribs, add overlaid
485 // hits_ as contribs/from hit_map rather than as copied simhits
486 ldmx_log(trace) << "Hits in hit_map after overlay of "
487 << contrib_collections_[i_coll] << "Overlay :";
488
489 for (auto& map_hit :
490 hit_map[contrib_collections_[i_coll] + out_coll_postfix_]) {
491 ldmx_log(trace) << map_hit.second;
492
493 if (calo_collection_map.find(contrib_collections_[i_coll] +
495 calo_collection_map.end()) {
496 ldmx_log(debug) << "Adding first hit from hit map as first outhit "
497 "vector to calo_collection_map";
498 calo_collection_map[contrib_collections_[i_coll] + out_coll_postfix_] =
499 {map_hit.second};
500 } else {
501 calo_collection_map[contrib_collections_[i_coll] + out_coll_postfix_]
502 .push_back(map_hit.second);
503 }
504 } // over hit_map
505 } // second loop over contrib using collections, to collect hits_ from
506 // hit_map
507
508 // done collecting hits_.
509
510 // now we can write the calo collections to the event bus
511 for (auto& [name, coll] : calo_collection_map) {
512 ldmx_log(debug) << "Writing " << name << " to event bus.";
513
514 ldmx_log(trace) << "List of hits_ added: ";
515 for (auto& hit : coll) {
516 ldmx_log(trace) << hit;
517 }
518 event.add(name, coll);
519 }
520
521 // and now for the tracker hits_
522 for (auto& [name, coll] : tracker_collection_map) {
523 ldmx_log(debug) << "Writing " << name << " to event bus.";
524 ldmx_log(trace) << "List of hits_ added: ";
525 for (auto& hit : coll) {
526 ldmx_log(trace) << hit;
527 }
528 event.add(name, coll);
529 }
530
531 // and finally for sim particles
532 for (auto& [name, coll] : particle_collection_map) {
533 ldmx_log(debug) << "Writing " << name << " to event bus.";
534 ldmx_log(trace) << "List of particles added: ";
535 for (auto& [track_id, particle] : coll) {
536 ldmx_log(trace) << "Track ID: " << track_id << " --- " << particle;
537 }
538 event.add(name, coll);
539 }
540
541 return;
542} // end produce()
543
545 const unsigned int encoding_version,
546 const unsigned int event_index) {
547 ldmx_log(trace) << "Encoding track ID " << track_id
548 << " according to version " << encoding_version;
549 int encoded_id;
550
551 // check if the encoding_version will overflow into the int sign bit
552 if (encoding_version > 15) {
553 EXCEPTION_RAISE("TrackEncodingError",
554 "Track ID encoding version " +
555 std::to_string(encoding_version) +
556 " has exceeded version maximum value of 15");
557 }
558 if (track_id < 0) {
559 // if track_id < 0 it's probably a default nonsense value -1;
560 // encoding at present DOES NOT WORK for negative values because C++ uses
561 // twos complement encoding for negative numbers;
562 // thus when decoding you should first check the first bit, and
563 // set it to a nonsense -1 if the number is negative.
564 // Right now (2026-03-07) the only place where track IDs are -1 are the
565 // origin ids in the SimCalorimeterHit contribs, which aren't used anyways
566 // and present no risk for overwriting data for duplicate track IDs, so we
567 // can leave this alone
568 ldmx_log(trace) << "Track ID has value " << track_id
569 << " < 0; no encoding will be applied (this is expected "
570 "for origin IDs in SimCalorimeterHits)";
571 return track_id;
572 }
573
574 // encode Track ID according to provided version
575 switch (encoding_version) {
576 case (unsigned)0: { // need braces for variable init scope control
577 ldmx_log(trace) << "No encoding applied";
578 encoded_id = track_id;
579 break;
580 }
581 case (unsigned)1: {
582 // create bitwise masks for encoding from version number and event index
583 unsigned version_mask = (encoding_version << 27);
584 unsigned index_mask = (event_index << 24);
585
586 // encode track ID using bitwise OR
587 encoded_id = track_id | version_mask | index_mask;
588 ldmx_log(trace) << "Encoding successful! encoded_id = " << encoded_id
589 << ", with bit representation "
590 << std::bitset<32>(encoded_id);
591 break;
592 }
593 default: { // version number has no associated encoding scheme
594 ldmx_log(warn) << "Track ID encoding version " << encoding_version
595 << " has no definition! No encoding will be applied";
596 encoded_id = track_id;
597 }
598 }
599
600 return encoded_id;
601}
602
604 // replace by this line once the corresponding tweak to EventFile is ready:
606 std::make_unique<framework::EventFile>(params_, overlay_filename_, true);
607 overlay_file_->setupEvent(&overlay_event_);
608 // we update the iterator at the end of each event. so do this once here to
609 // grab the first event in the processor
610 // ldmx_log(trace) << "Used input file: "
611 // << overlay_file_->getFileName() << " Got event info: " <<
612 // overlay_file_->getEvent()->Print();
613
614 return;
615} // end onProcessStart
616
617} // namespace recon
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Conditions object for random number seeds.
Class which stores simulated calorimeter hit information.
Class which encapsulates information from a hit in a simulated tracking detector.
const T & getCondition(const std::string &condition_name)
Access a conditions object for the current event.
Implements an event buffer system for storing event data.
Definition Event.h:40
const std::map< KeyType, ValType > & getMap(const std::string &collectionName, const std::string &passName) const
Get a map (std::map) of objects from the event bus.
Definition Event.h:426
ldmx::EventHeader & getEventHeader()
Get the event header.
Definition Event.h:57
const std::vector< ContentType > & getCollection(const std::string &collectionName, const std::string &passName) const
Get a collection (std::vector) of objects from the event bus.
Definition Event.h:409
static const std::string CONDITIONS_OBJECT_NAME
Conditions object name.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:26
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:75
void setEventNumber(int eventNumber)
Set the event number.
Run-specific configuration and data stored in its own output TTree alongside the event TTree in the o...
Definition RunHeader.h:68
Stores simulated calorimeter hit information.
Class representing a simulated particle.
Definition SimParticle.h:25
Represents a simulated tracker hit in the simulation.
Class to overlay in-time pile-up events from an overlay file.
int encodeTrack(int track_id, const unsigned int encoding_version, const unsigned int event_index=0)
Encode track ID with overlay event information.
int start_event_max_
Maximum event number to start overlaying from.
std::vector< std::string > particle_collections_
List of SimParticle collection(s) to loop over and add hits from, combining sim and pileup.
std::string overlay_filename_
Pileup overlay events input file name.
std::unique_ptr< framework::EventFile > overlay_file_
Pileup overlay events input file.
bool do_poisson_in_time_
Let the total number of in-time events be poisson distributed, or fix at the chosen value,...
int n_later_
Number of bunches after the sim event to pull pileup events from.
std::string overlay_passname_
Pileup overlay events input pass name.
bool do_poisson_out_of_time_
Let the total number of out-of-time events be poisson distributed, or fix at the chosen value,...
void onNewRun(const ldmx::RunHeader &) override
At the start of the run, the pileup overlay file is set up, and the starting event number is chosen,...
std::vector< std::string > tracker_collections_
List of SimTrackerHit collection(s) to loop over and add hits from, combining sim and pileup.
framework::config::Parameters params_
The parameters used to configure this producer.
std::vector< std::string > contrib_collections_
List of SimCalorimeterHit collections which keep track of hit contribs.
double bunch_spacing_
Spacing in time (in [ns]) between electron bunches.
std::string sim_passname_
To use for finding the sim event bus passengers, mostly a disambiguation.
std::vector< std::string > calo_collections_
List of SimCalorimeterHit collection(s) to loop over and add hits from, combining sim and pileup.
std::unique_ptr< TRandom2 > rndm_time_
Random number generator for pileup event time offset.
std::unique_ptr< TRandom2 > rndm_
Random number generator for number of overlaid events.
void produce(framework::Event &event) override
Based on the list of collections to overlay, and the desired number of events, loop through all relev...
double poisson_mu_
(average) total number of events
void configure(framework::config::Parameters &parameters) override
Configure the processor with input parameters from the python cofig.
unsigned track_id_encoding_
Track ID encoding scheme version.
std::string out_coll_postfix_
Postfix to add to the collection name of the overlayed collections.
void onProcessStart() override
At the start of processing, the pileup overlay file is set up.
double time_sigma_
Width of pileup bunch spread in time (in [ns]), specified as a sigma of a Gaussian distribution.
int start_event_min_
Minimum event number to start overlaying from.
framework::Event overlay_event_
The overlay ldmx event bus.
double time_mean_
Average position in time (in [ns]) of pileup bunches, relative to the sim event.
int n_earlier_
Number of bunches before the sim event to pull pileup events from.
Information about a contribution to the hit in the associated cell.