LDMX Software
recon::OverlayProducer Class Reference

Class to overlay in-time pile-up events from an overlay file. More...

#include <OverlayProducer.h>

Public Member Functions

 OverlayProducer (const std::string &name, framework::Process &process)
 
void configure (framework::config::Parameters &parameters) override
 Configure the processor with input parameters from the python cofig.
 
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, using the RNSS.
 
void produce (framework::Event &event) override
 Based on the list of collections to overlay, and the desired number of events, loop through all relevant collections and copy the sim event (once), and then add the corresponding collection from the pileup 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.
 
void onProcessStart () override
 At the start of processing, the pileup overlay file is set up.
 
- 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 onProcessEnd ()
 Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.
 
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

framework::config::Parameters params_
 The parameters used to configure this producer.
 
std::string overlay_filename_
 Pileup overlay events input file name.
 
std::unique_ptr< framework::EventFileoverlay_file_
 Pileup overlay events input file.
 
framework::Event overlay_event_
 The overlay ldmx event bus.
 
std::vector< std::string > calo_collections_
 List of SimCalorimeterHit collection(s) to loop over and add hits from, combining sim and pileup.
 
std::vector< std::string > tracker_collections_
 List of SimTrackerHit collection(s) to loop over and add hits from, combining sim and pileup.
 
std::vector< std::string > particle_collections_
 List of SimParticle collection(s) to loop over and add hits from, combining sim and pileup.
 
std::vector< std::string > contrib_collections_
 List of SimCalorimeterHit collections which keep track of hit contribs.
 
std::string overlay_passname_
 Pileup overlay events input pass name.
 
std::string sim_passname_
 To use for finding the sim event bus passengers, mostly a disambiguation.
 
std::string out_coll_postfix_
 Postfix to add to the collection name of the overlayed collections.
 
bool do_poisson_in_time_ {false}
 Let the total number of in-time events be poisson distributed, or fix at the chosen value, poissonMu_.
 
bool do_poisson_out_of_time_ {false}
 Let the total number of out-of-time events be poisson distributed, or fix at the chosen value, poissonMu_.
 
double poisson_mu_ {0.}
 (average) total number of events
 
std::unique_ptr< TRandom2 > rndm_
 Random number generator for number of overlaid events.
 
std::unique_ptr< TRandom2 > rndm_time_
 Random number generator for pileup event time offset.
 
double time_sigma_ {0.}
 Width of pileup bunch spread in time (in [ns]), specified as a sigma of a Gaussian distribution.
 
double time_mean_ {0.}
 Average position in time (in [ns]) of pileup bunches, relative to the sim event.
 
double bunch_spacing_ {0.}
 Spacing in time (in [ns]) between electron bunches.
 
int n_earlier_ {0}
 Number of bunches before the sim event to pull pileup events from.
 
int n_later_ {0}
 Number of bunches after the sim event to pull pileup events from.
 
int start_event_min_ {1}
 Minimum event number to start overlaying from.
 
int start_event_max_ {10000}
 Maximum event number to start overlaying from.
 
unsigned track_id_encoding_ {0}
 Track ID encoding scheme version.
 

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

Class to overlay in-time pile-up events from an overlay file.

Definition at line 30 of file OverlayProducer.h.

Constructor & Destructor Documentation

◆ OverlayProducer()

recon::OverlayProducer::OverlayProducer ( const std::string & name,
framework::Process & process )
inline

Definition at line 32 of file OverlayProducer.h.

33 : framework::Producer(name, process), overlay_event_{"overlay"} {}
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.
framework::Event overlay_event_
The overlay ldmx event bus.

Member Function Documentation

◆ configure()

void recon::OverlayProducer::configure ( framework::config::Parameters & parameters)
overridevirtual

Configure the processor with input parameters from the python cofig.

Print the parameters actually set. Helpful in case of typos.

Reimplemented from framework::EventProcessor.

Definition at line 5 of file OverlayProducer.cxx.

5 {
6 params_ = parameters;
7
8 // name of file containing events to be overlaid, and a list of collections to
9 // overlay
10 overlay_filename_ = parameters.get<std::string>("overlay_filename");
12 parameters.get<std::vector<std::string>>("calo_collections");
14 parameters.get<std::vector<std::string>>("tracker_collections");
16 parameters.get<std::vector<std::string>>("particle_collections");
18 parameters.get<std::vector<std::string>>("contrib_collections");
19 sim_passname_ = parameters.get<std::string>("sim_passname");
20 overlay_passname_ = parameters.get<std::string>("overlay_passname");
21 out_coll_postfix_ = parameters.get<std::string>("out_coll_postfix");
22 // overlay specifics:
23 poisson_mu_ = parameters.get<double>("poisson_mu");
24 do_poisson_in_time_ = parameters.get<bool>("do_poisson_in_time");
25 do_poisson_out_of_time_ = parameters.get<bool>("do_poisson_out_of_time");
26 time_sigma_ = parameters.get<double>("time_sigma");
27 time_mean_ = parameters.get<double>("time_mean");
28 n_earlier_ = parameters.get<int>("n_earlier");
29 n_later_ = parameters.get<int>("n_later");
30 bunch_spacing_ = parameters.get<double>("bunch_spacing");
31 start_event_min_ = parameters.get<int>("start_event_min");
32 start_event_max_ = parameters.get<int>("start_event_max");
33 track_id_encoding_ = unsigned(parameters.get<int>("track_id_encoding", 0));
34
36 ldmx_log(debug) << "Got parameters \n \t overlayFileName = "
38 << "\n\t sim pass name = " << sim_passname_
39 << "\n\t overlay pass name = " << overlay_passname_;
40 ldmx_log(debug) << "\n\t overlayCaloHitCollections = ";
41 for (const auto &coll : calo_collections_) {
42 ldmx_log(debug) << coll << "; ";
43 }
44
45 ldmx_log(debug) << "\n\t overlayTrackerHitCollections = ";
46 for (const std::string &coll : tracker_collections_) {
47 ldmx_log(debug) << coll << "; ";
48 }
49
50 ldmx_log(debug) << "\n\t overlayParticleCollections = ";
51 for (const std::string &coll : particle_collections_) {
52 ldmx_log(debug) << coll << "; ";
53 }
54
55 ldmx_log(trace) << "\n\t numberOverlaidInteractions = " << poisson_mu_
56 << "\n\t nEarlierBunchesToSample = " << n_earlier_
57 << "\n\t nLaterBunchesToSample = " << n_later_
58 << "\n\t bunchSpacing = " << bunch_spacing_
59 << "\n\t doPoissonIntime = " << do_poisson_in_time_
60 << "\n\t doPoissonOutoftime = " << do_poisson_out_of_time_
61 << "\n\t timeSpread = " << time_sigma_
62 << "\n\t timeMean = " << time_mean_
63 << "\n\t startEventMin = " << start_event_min_
64 << "\n\t startEventMax = " << start_event_max_;
65
66 // given how the contrib collection specification is setup, it's possible for
67 // spelling errors to cause doom here, so we want to flag those
68 for (auto coll_name : contrib_collections_) {
69 if (std::find(calo_collections_.begin(), calo_collections_.end(),
70 coll_name) == calo_collections_.end()) {
71 EXCEPTION_RAISE("CollNameMismatch",
72 "The contrib-using collection " + coll_name +
73 " does not match any SimCalorimeterHit collection in "
74 "'calo_collections_'! Please check your spelling");
75 }
76 }
77
78 return;
79} // end configure()
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:78
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.
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,...
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.
double poisson_mu_
(average) total number of events
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.
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.
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.

References bunch_spacing_, calo_collections_, contrib_collections_, do_poisson_in_time_, do_poisson_out_of_time_, framework::config::Parameters::get(), n_earlier_, n_later_, out_coll_postfix_, overlay_filename_, overlay_passname_, params_, particle_collections_, poisson_mu_, sim_passname_, start_event_max_, start_event_min_, time_mean_, time_sigma_, track_id_encoding_, and tracker_collections_.

◆ encodeTrack()

int recon::OverlayProducer::encodeTrack ( int track_id,
const unsigned int encoding_version,
const unsigned int event_index = 0 )

Encode track ID with overlay event information.

Performs bitwise encoding on track ID integer with version and event index.

VERSION DESCRIPTION

  • 0 : no encoding, leaves track_id alone
  • 1 : four bit version (27-31) plus three bit event index (24-26)

Definition at line 534 of file OverlayProducer.cxx.

536 {
537 ldmx_log(trace) << "Encoding track ID " << track_id
538 << " according to version " << encoding_version;
539 int encoded_id;
540
541 // check if the encoding_version will overflow into the int sign bit
542 if (encoding_version > 15) {
543 EXCEPTION_RAISE("TrackEncodingError",
544 "Track ID encoding version " +
545 std::to_string(encoding_version) +
546 " has exceeded version maximum value of 15");
547 }
548 if (track_id < 0) {
549 // if track_id < 0 it's probably a default nonsense value -1;
550 // encoding at present DOES NOT WORK for negative values because C++ uses
551 // twos complement encoding for negative numbers;
552 // thus when decoding you should first check the first bit, and
553 // set it to a nonsense -1 if the number is negative.
554 // Right now (2026-03-07) the only place where track IDs are -1 are the
555 // origin ids in the SimCalorimeterHit contribs, which aren't used anyways
556 // and present no risk for overwriting data for duplicate track IDs, so we
557 // can leave this alone
558 ldmx_log(warn) << "Track ID has value " << track_id
559 << " < 0; no encoding will be applied";
560 return track_id;
561 }
562
563 // encode Track ID according to provided version
564 switch (encoding_version) {
565 case (unsigned)0: { // need braces for variable init scope control
566 ldmx_log(trace) << "No encoding applied";
567 encoded_id = track_id;
568 break;
569 }
570 case (unsigned)1: {
571 // create bitwise masks for encoding from version number and event index
572 unsigned version_mask = (encoding_version << 27);
573 unsigned index_mask = (event_index << 24);
574
575 // encode track ID using bitwise OR
576 encoded_id = track_id | version_mask | index_mask;
577 ldmx_log(trace) << "Encoding successful! encoded_id = " << encoded_id
578 << ", with bit representation "
579 << std::bitset<32>(encoded_id);
580 break;
581 }
582 default: { // version number has no associated encoding scheme
583 ldmx_log(warn) << "Track ID encoding version " << encoding_version
584 << " has no definition! No encoding will be applied";
585 encoded_id = track_id;
586 }
587 }
588
589 return encoded_id;
590}

Referenced by produce().

◆ onNewRun()

void recon::OverlayProducer::onNewRun ( const ldmx::RunHeader & )
overridevirtual

At the start of the run, the pileup overlay file is set up, and the starting event number is chosen, using the RNSS.

set up random seeds

Reimplemented from framework::EventProcessor.

Definition at line 81 of file OverlayProducer.cxx.

81 {
85 rndm_ = std::make_unique<TRandom2>(rnss.getSeed("OverlayProducer::rndm"));
87 std::make_unique<TRandom2>(rnss.getSeed("OverlayProducer::rndmTime"));
88
89 // Pick a random event from the Pileup file
90 int start_event = rndm_->Uniform(start_event_min_, start_event_max_);
91 // EventFile::skipToEvent handles actual number of events in file
92 int ev_number = overlay_file_->skipToEvent(start_event);
93 if (ev_number < 0) {
94 EXCEPTION_RAISE("BadRead", "Couldn't read to starting offset.");
95 }
97 ldmx_log(info) << "Starting overlay process with pileup event number "
98 << ev_number << " (random event number picked was "
99 << start_event << ").";
100} // end onNewRun()
const T & getCondition(const std::string &condition_name)
Access a conditions object for the current event.
ldmx::EventHeader & getEventHeader()
Get the event header.
Definition Event.h:59
static const std::string CONDITIONS_OBJECT_NAME
Conditions object name.
void setEventNumber(int eventNumber)
Set the event number.
std::unique_ptr< framework::EventFile > overlay_file_
Pileup overlay events input file.
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.

References framework::RandomNumberSeedService::CONDITIONS_OBJECT_NAME, framework::EventProcessor::getCondition(), framework::Event::getEventHeader(), overlay_event_, overlay_file_, rndm_, rndm_time_, ldmx::EventHeader::setEventNumber(), start_event_max_, and start_event_min_.

◆ onProcessStart()

void recon::OverlayProducer::onProcessStart ( )
overridevirtual

At the start of processing, the pileup overlay file is set up.

Reimplemented from framework::EventProcessor.

Definition at line 592 of file OverlayProducer.cxx.

592 {
593 // replace by this line once the corresponding tweak to EventFile is ready:
595 std::make_unique<framework::EventFile>(params_, overlay_filename_, true);
596 overlay_file_->setupEvent(&overlay_event_);
597 // we update the iterator at the end of each event. so do this once here to
598 // grab the first event in the processor
599 // ldmx_log(trace) << "Used input file: "
600 // << overlay_file_->getFileName() << " Got event info: " <<
601 // overlay_file_->getEvent()->Print();
602
603 return;
604} // end onProcessStart

References overlay_event_, overlay_file_, overlay_filename_, and params_.

◆ produce()

void recon::OverlayProducer::produce ( framework::Event & event)
overridevirtual

Based on the list of collections to overlay, and the desired number of events, loop through all relevant collections and copy the sim event (once), and then add the corresponding collection from the pileup overlay file.

The event loop is the outer loop, and the inner loop is over the list of collections.

The collections have to be specified separately as a list of SimCalorimeterHit collections and a list of SimTrackerHit collections.

The collection name is parsed for "Ecal" to be flagged as a collection which needs overlay hits to be added as contribs. This is currently hardwired.

The resulting collections inherit the input collection name, with an appended string "Overlay". This name is also currently hardwired.

Go to next overlay event This overlay file has been configured to loop back to the beginning of the TTree when it reaches the end. This means nextEvent() will only return false if an error is occurred or if the overlay file is mis-configured.

Implements framework::Producer.

Definition at line 102 of file OverlayProducer.cxx.

102 {
103 // using nextEvent to loop, we need to loop over overlay events and in an
104 // inner loop, loop over collections, and store them. after all pileup events
105 // have been added, the vector of collections is iterated over and added to
106 // the event bus.
107 std::map<std::string, std::vector<ldmx::SimCalorimeterHit>>
108 calo_collection_map;
109 std::map<std::string, std::vector<ldmx::SimTrackerHit>>
110 tracker_collection_map;
111 std::map<std::string, std::map<int, ldmx::SimParticle>>
112 particle_collection_map;
113 std::map<std::string, std::map<int, ldmx::SimCalorimeterHit>> hit_map;
114
115 // start by copying over all the collections from the sim event
116
117 /* ----------- first do the SimCalorimeterHits ----------- */
118
119 // get the calo hits_ collections that we want to overlay, by looping over
120 // the list of collections passed to the producer : calo_collections_
121 for (const auto &coll_name : calo_collections_) {
122 // search for the collection name in the list of collections that
123 // need contribs to be added, contrib_collections_
124 bool needs_contribs_added{std::find(contrib_collections_.begin(),
126 coll_name) != contrib_collections_.end()
127 ? true
128 : false};
129
130 // start out by just copying the sim hits, unaltered.
131 auto simhits_calo =
132 event.getCollection<ldmx::SimCalorimeterHit>(coll_name, sim_passname_);
133 // but don't copy contrib using hits immediately: for them, wait until
134 // overlay contribs have been added. then add everything through the hit_map
135 if (!needs_contribs_added) {
136 calo_collection_map[coll_name + out_coll_postfix_] = simhits_calo;
137 // after copying, perform track ID encodings;
138 // the main sample gets the event index 0 by default
139 for (auto &simhit : calo_collection_map[coll_name + out_coll_postfix_]) {
140 simhit.encodeTracks(
141 [this](int id, unsigned enc, unsigned idx) {
142 return encodeTrack(id, enc, idx);
143 },
144 track_id_encoding_, (unsigned)0);
145 }
146 }
147
148 ldmx_log(debug) << "in loop: start of collection " << coll_name
149 << "in loop: printing current sim event: ";
150 ldmx_log(debug) << "in loop: size of sim hits_ vector " << coll_name
151 << " is " << simhits_calo.size();
152
153 // we don't need to touch the hard process sim hits_, really... but we
154 // might need the simhits in the hit map.
155 if (needs_contribs_added) {
156 ldmx_log(trace) << "Collection " << coll_name << " needs contribs added";
157 for (const ldmx::SimCalorimeterHit &simhit : simhits_calo) {
158 ldmx_log(trace) << simhit;
159 // this copies the hit, its ID and its coordinates directly
160 hit_map[coll_name + out_coll_postfix_][simhit.getID()] = simhit;
161 // now encode track IDs on copied object
162 hit_map[coll_name + out_coll_postfix_][simhit.getID()].encodeTracks(
163 [this](int id, unsigned enc, unsigned idx) {
164 return encodeTrack(id, enc, idx);
165 },
166 track_id_encoding_, (unsigned)0);
167 } // over calo simhit collection
168 } // if needContribs
169
170 } // over calo collections for sim event
171
172 /* ----------- then do the same with SimTrackerHits! ----------- */
173
174 // get the SimTrackerHit collections that we want to overlay, by looping
175 // over the list of collections passed to the producer : tracker_collections_
176 for (const auto &coll_name : tracker_collections_) {
177 auto simhits_tracker =
178 event.getCollection<ldmx::SimTrackerHit>(coll_name, sim_passname_);
179 tracker_collection_map[coll_name + out_coll_postfix_] = simhits_tracker;
180 // after copying, perform track ID encoding
181 for (auto &simhit : tracker_collection_map[coll_name + out_coll_postfix_]) {
182 int encoded_track_id =
183 encodeTrack(simhit.getTrackID(), track_id_encoding_, (unsigned)0);
184 simhit.setTrackID(encoded_track_id);
185 }
186
187 // the rest is printouts for debugging
188 ldmx_log(debug) << "in loop: size of sim hits_ vector " << coll_name
189 << " is " << simhits_tracker.size();
190
191 ldmx_log(debug) << "in loop: start of collection " << coll_name
192 << "in loop: printing current sim event: ";
193
194 for (const ldmx::SimTrackerHit &simhit : simhits_tracker) {
195 ldmx_log(trace) << simhit;
196 }
197 } // over tracker collections for sim event
198
199 /* ----------- and finish up with SimParticles ----------- */
200
201 // get the SimParticle collections that we want to overlay, by looping
202 // over the list of collections passed to the producer : particle_collections_
203 for (const auto &coll_name : particle_collections_) {
204 auto sim_particles =
205 event.getMap<int, ldmx::SimParticle>(coll_name, sim_passname_);
206 auto &output_map = particle_collection_map[coll_name + out_coll_postfix_];
207
208 ldmx_log(debug) << "in loop: size of sim particles map " << coll_name
209 << " is " << sim_particles.size();
210
211 ldmx_log(debug) << "in loop: start of collection " << coll_name
212 << "in loop: printing current sim event: ";
213
214 // need to copy SimParticles individually because of std::map key
215 // immutability
216 for (auto &[track_id, particle] : sim_particles) {
217 int encoded_track_id =
218 encodeTrack(track_id, track_id_encoding_, (unsigned)0);
219 output_map[encoded_track_id] = particle;
220 output_map[encoded_track_id].encodeTracks(
221 [this](int id, unsigned enc, unsigned idx) {
222 return encodeTrack(id, enc, idx);
223 },
224 track_id_encoding_, (unsigned)0);
225 ldmx_log(trace) << particle;
226 }
227 } // over particle collections for sim event
228
229 /* ----------- now do the overlay ----------- */
230
231 // we could shift these by a random number, effectively placing the
232 // sim event at random positions in the interval, preserving the
233 // overall interval length
234 // int simBunch= static_cast<int>(rndm_time_->Uniform(
235 // -(n_earlier_+1) , n_later_+1)); // +1 to get
236 // inclusive interval
237 int start_bunch = -n_earlier_;
238 int end_bunch = n_later_;
239
240 // this is the event index number assigned to overlay sample hits and
241 // particles for track ID encoding
242 unsigned overlay_event_index = 1;
243
244 // TODO -- figure out if we should also randomly shift the time of the sim
245 // event (likely only needed if time bias gets picked up by BDT or ML by way
246 // of pulse behaviour)
247 for (int bunch_offset{start_bunch}; bunch_offset <= end_bunch;
248 bunch_offset++) {
249 // sample a poisson distribution, or use mu as fixed number of overlay
250 // events
251 int n_events_overlay = do_poisson_out_of_time_
252 ? rndm_->Poisson(poisson_mu_)
253 : static_cast<int>(poisson_mu_);
254
255 // special case: in-time pileup at bunch 0
256 if (bunch_offset == 0) {
257 if (!do_poisson_in_time_) {
258 // fix it to the average
259 n_events_overlay = static_cast<int>(poisson_mu_);
261 // then we haven't set this yet
262 n_events_overlay = rndm_->Poisson(poisson_mu_);
263 }
264
265 // paticularly useful in the poisson fluctuated case
266 event.getEventHeader().setIntParameter("in_time_pu", n_events_overlay);
267
268 // the total number of events is nPU + 1 (it includes the sim event)
269 // in any case, subtract the sim event from nOverlay
270 n_events_overlay -= 1;
271
272 } // end if bunch_offset == 0
273
274 float bunchtime_offset = bunch_spacing_ * bunch_offset;
275 ldmx_log(debug) << "Will overlay " << n_events_overlay
276 << " events on the simulated one";
277
278 for (int i_ev = 0; i_ev < n_events_overlay; i_ev++) {
285 if (!overlay_file_->nextEvent()) {
286 ldmx_log(error) << "Couldn't read next overlay event!";
287 return;
288 }
289
290 // a pileup event wide time offset to be applied to all its hits_.
291 float time_offset = rndm_time_->Gaus(time_mean_, time_sigma_);
292 time_offset += bunchtime_offset;
293
294 ldmx_log(trace) << "in overlay loop: overlaying event " << "which is "
295 << i_ev + 1 << " out of " << n_events_overlay
296 << "\n\thit time offset is " << time_offset << " ns"
297 << "\n\tbunch position offset is " << bunch_offset
298 << ", leading to a total time offset of "
299 << bunchtime_offset << " ns";
300
301 /* ----------- first do the SimCalorimeterHits overlay ----------- */
302
303 // again get the calo hits_ collections that we want to overlay
304 for (uint i_coll = 0; i_coll < calo_collections_.size(); i_coll++) {
305 // search for the collection name in the list of collections that
306 // need contribs to be added, contrib_collections_
307 bool needs_contribs_added{
308 std::find(contrib_collections_.begin(), contrib_collections_.end(),
310 ? true
311 : false};
312
313 std::vector<ldmx::SimCalorimeterHit> overlay_hits =
316
317 ldmx_log(debug) << "in loop: size of overlay hits_ vector is "
318 << overlay_hits.size();
319
320 std::string out_coll_name =
322
323 ldmx_log(trace) << "in loop: printing overlay event: ";
324
325 for (ldmx::SimCalorimeterHit &overlay_hit : overlay_hits) {
326 ldmx_log(trace) << overlay_hit;
327
328 // update relevant parameters with overlay modifications
329 overlay_hit.setTime(overlay_hit.getTime() + time_offset);
330 overlay_hit.setPreStepTime(overlay_hit.getPreStepTime() +
331 time_offset);
332 overlay_hit.setPostStepTime(overlay_hit.getPostStepTime() +
333 time_offset);
334 overlay_hit.encodeTracks(
335 [this](int id, unsigned enc, unsigned idx) {
336 return encodeTrack(id, enc, idx);
337 },
338 track_id_encoding_, overlay_event_index);
339
340 if (needs_contribs_added) { // special treatment for (for now only)
341 // ecal
342 auto &this_coll_hit_map{
343 hit_map[calo_collections_[i_coll] + out_coll_postfix_]};
344 int overlay_hit_id = overlay_hit.getID();
345 if (this_coll_hit_map.find(overlay_hit_id) ==
346 this_coll_hit_map
347 .end()) { // there wasn't already a simhit in this id
348 ldmx_log(trace)
349 << "No existing simhit found for ID " << overlay_hit_id
350 << "; copying overlay hit to output collection";
351 auto &output_hit = this_coll_hit_map[overlay_hit_id];
352 output_hit = overlay_hit; // copy hit
353
354 // we need to do some backflips to get the contribs correct later
355 auto id = output_hit.getID();
356 auto pos = output_hit.getPosition();
357 auto time = output_hit.getTime();
358 output_hit.clear(); // with the below adjustments, this will only
359 // clear contribs from the output_hit
360 output_hit.setID(id);
361 output_hit.setPosition(pos[0], pos[1], pos[2]);
362 output_hit.setTime(time);
363 } // if overlay_hit_id not present
364
365 // add the overlay hit contribs to existing hit,
366 // incrementing track IDs and timestamp as needed
367 int n_contribs = overlay_hit.getNumberOfContribs();
368 ldmx_log(trace)
369 << "Copying and reindexing " << n_contribs
370 << " contributors to the sim hit for ID " << overlay_hit_id;
371 for (int i = 0; i < n_contribs; i++) {
373 overlay_hit.getContrib(i)};
374 // tracks were encoded in-place above, so we only need to worry
375 // about times
376 this_coll_hit_map[overlay_hit_id].addContrib(
377 contrib.incident_id_, contrib.track_id_, contrib.pdg_code_,
378 contrib.edep_, contrib.time_ + time_offset);
379 } // loop over contribs in overlay_hit
380 ldmx_log(trace)
381 << "There are now "
382 << this_coll_hit_map[overlay_hit_id].getNumberOfContribs()
383 << " total contributors in the output collection";
384 } // if add overlay as contribs
385 else {
386 // no need to change contrib timestamps here
387 calo_collection_map[out_coll_name].push_back(overlay_hit);
388
389 ldmx_log(trace) << "Adding non-Ecal overlay hit to outhit vector "
390 << out_coll_name;
391 } // end else !needs_contribs_added
392 } // over overlay calo simhit collection
393
394 if (!needs_contribs_added)
395 ldmx_log(debug) << "Nhits in overlay collection " << out_coll_name
396 << ": " << calo_collection_map[out_coll_name].size();
397
398 } // over calo_collections_
399
400 /* ----------- now do simtracker hits_ overlay ----------- */
401
402 // loop over the SimTrackerHit collections that we want to overlay
403 for (const auto &coll : tracker_collections_) {
404 auto overlay_tracker_hits{
406 coll, overlay_passname_)};
407
408 ldmx_log(debug) << "in loop: size of overlay hits_ vector is "
409 << overlay_tracker_hits.size();
410
411 std::string out_coll_name_tracker{coll + out_coll_postfix_};
412
413 ldmx_log(trace) << "in loop: printing overlay event: ";
414
415 for (auto &overlay_hit : overlay_tracker_hits) {
416 auto overlay_time{overlay_hit.getTime() + time_offset};
417 overlay_hit.setTime(overlay_time);
418 auto overlay_track_id{encodeTrack(overlay_hit.getTrackID(),
420 overlay_event_index)};
421 overlay_hit.setTrackID(overlay_track_id);
422
423 ldmx_log(trace) << overlay_hit;
424 ldmx_log(trace) << "Adding tracker overlay hit to outhit vector "
425 << out_coll_name_tracker;
426
427 tracker_collection_map[out_coll_name_tracker].push_back(overlay_hit);
428 } // over overlay tracker simhit collection
429
430 ldmx_log(debug) << "Nhits in overlay collection "
431 << out_coll_name_tracker << ": "
432 << tracker_collection_map[out_coll_name_tracker].size();
433
434 } // over tracker_collections_
435
436 /* ----------- finally do SimParticles overlay ----------- */
437 for (const auto &coll : particle_collections_) {
438 auto overlay_particles{overlay_event_.getMap<int, ldmx::SimParticle>(
439 coll, overlay_passname_)};
440
441 ldmx_log(debug) << "in loop: size of overlay particles map is "
442 << overlay_particles.size();
443
444 std::string out_coll_name_particles{coll + out_coll_postfix_};
445 auto &output_map = particle_collection_map[out_coll_name_particles];
446
447 ldmx_log(trace) << "in loop: printing overlay event: ";
448
449 for (auto &[track_id, particle] : overlay_particles) {
450 int new_track_id =
451 encodeTrack(track_id, track_id_encoding_, overlay_event_index);
452
453 output_map[new_track_id] = particle;
454 output_map[new_track_id].encodeTracks(
455 [this](int id, unsigned enc, unsigned idx) {
456 return encodeTrack(id, enc, idx);
457 },
458 track_id_encoding_, overlay_event_index);
459 output_map[new_track_id].setTime(particle.getTime() + time_offset);
460
461 ldmx_log(trace) << "Track ID: " << new_track_id << " --- "
462 << output_map[new_track_id];
463 ldmx_log(trace) << "Adding sim particle to output map "
464 << out_coll_name_particles;
465 } // over overlay sim particles collection
466 } // over particle_collections_
467
468 } // over overlay events
469 } // over bunches
470
471 // after all events are done, the contrib-using collections' hit_maps are
472 // final and can be written to the event output
473 for (uint i_coll = 0; i_coll < contrib_collections_.size(); i_coll++) {
474 // for each SimCalorimeterHit collection that uses contribs, add overlaid
475 // hits_ as contribs/from hit_map rather than as copied simhits
476 ldmx_log(trace) << "Hits in hit_map after overlay of "
477 << contrib_collections_[i_coll] << "Overlay :";
478
479 for (auto &map_hit :
480 hit_map[contrib_collections_[i_coll] + out_coll_postfix_]) {
481 ldmx_log(trace) << map_hit.second;
482
483 if (calo_collection_map.find(contrib_collections_[i_coll] +
485 calo_collection_map.end()) {
486 ldmx_log(debug) << "Adding first hit from hit map as first outhit "
487 "vector to calo_collection_map";
488 calo_collection_map[contrib_collections_[i_coll] + out_coll_postfix_] =
489 {map_hit.second};
490 } else {
491 calo_collection_map[contrib_collections_[i_coll] + out_coll_postfix_]
492 .push_back(map_hit.second);
493 }
494 } // over hit_map
495 } // second loop over contrib using collections, to collect hits_ from
496 // hit_map
497
498 // done collecting hits_.
499
500 // now we can write the calo collections to the event bus
501 for (auto &[name, coll] : calo_collection_map) {
502 ldmx_log(debug) << "Writing " << name << " to event bus.";
503
504 ldmx_log(trace) << "List of hits_ added: ";
505 for (auto &hit : coll) {
506 ldmx_log(trace) << hit;
507 }
508 event.add(name, coll);
509 }
510
511 // and now for the tracker hits_
512 for (auto &[name, coll] : tracker_collection_map) {
513 ldmx_log(debug) << "Writing " << name << " to event bus.";
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 finally for sim particles
522 for (auto &[name, coll] : particle_collection_map) {
523 ldmx_log(debug) << "Writing " << name << " to event bus.";
524 ldmx_log(trace) << "List of particles added: ";
525 for (auto &[track_id, particle] : coll) {
526 ldmx_log(trace) << "Track ID: " << track_id << " --- " << particle;
527 }
528 event.add(name, coll);
529 }
530
531 return;
532} // end produce()
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:428
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:411
Stores simulated calorimeter hit information.
Class representing a simulated particle.
Definition SimParticle.h:24
Represents a simulated tracker hit in the simulation.
int encodeTrack(int track_id, const unsigned int encoding_version, const unsigned int event_index=0)
Encode track ID with overlay event information.
Information about a contribution to the hit in the associated cell.

References bunch_spacing_, calo_collections_, contrib_collections_, do_poisson_in_time_, do_poisson_out_of_time_, encodeTrack(), framework::Event::getCollection(), framework::Event::getMap(), n_earlier_, n_later_, out_coll_postfix_, overlay_event_, overlay_file_, overlay_passname_, particle_collections_, poisson_mu_, rndm_, rndm_time_, sim_passname_, time_mean_, time_sigma_, track_id_encoding_, and tracker_collections_.

Member Data Documentation

◆ bunch_spacing_

double recon::OverlayProducer::bunch_spacing_ {0.}
private

Spacing in time (in [ns]) between electron bunches.

Definition at line 191 of file OverlayProducer.h.

191{0.};

Referenced by configure(), and produce().

◆ calo_collections_

std::vector<std::string> recon::OverlayProducer::calo_collections_
private

List of SimCalorimeterHit collection(s) to loop over and add hits from, combining sim and pileup.

Definition at line 109 of file OverlayProducer.h.

Referenced by configure(), and produce().

◆ contrib_collections_

std::vector<std::string> recon::OverlayProducer::contrib_collections_
private

List of SimCalorimeterHit collections which keep track of hit contribs.

Definition at line 126 of file OverlayProducer.h.

Referenced by configure(), and produce().

◆ do_poisson_in_time_

bool recon::OverlayProducer::do_poisson_in_time_ {false}
private

Let the total number of in-time events be poisson distributed, or fix at the chosen value, poissonMu_.

Definition at line 148 of file OverlayProducer.h.

148{false};

Referenced by configure(), and produce().

◆ do_poisson_out_of_time_

bool recon::OverlayProducer::do_poisson_out_of_time_ {false}
private

Let the total number of out-of-time events be poisson distributed, or fix at the chosen value, poissonMu_.

Definition at line 154 of file OverlayProducer.h.

154{false};

Referenced by configure(), and produce().

◆ n_earlier_

int recon::OverlayProducer::n_earlier_ {0}
private

Number of bunches before the sim event to pull pileup events from.

Defaults to 0 --> all events occur in the same bunch as the sim event.

Definition at line 198 of file OverlayProducer.h.

198{0};

Referenced by configure(), and produce().

◆ n_later_

int recon::OverlayProducer::n_later_ {0}
private

Number of bunches after the sim event to pull pileup events from.

Defaults to 0 --> all events occur in the same bunch as the sim event.

Definition at line 205 of file OverlayProducer.h.

205{0};

Referenced by configure(), and produce().

◆ out_coll_postfix_

std::string recon::OverlayProducer::out_coll_postfix_
private

Postfix to add to the collection name of the overlayed collections.

This is currently set to "Overlay".

Definition at line 142 of file OverlayProducer.h.

Referenced by configure(), and produce().

◆ overlay_event_

framework::Event recon::OverlayProducer::overlay_event_
private

The overlay ldmx event bus.

Definition at line 103 of file OverlayProducer.h.

Referenced by onNewRun(), onProcessStart(), and produce().

◆ overlay_file_

std::unique_ptr<framework::EventFile> recon::OverlayProducer::overlay_file_
private

Pileup overlay events input file.

Definition at line 98 of file OverlayProducer.h.

Referenced by onNewRun(), onProcessStart(), and produce().

◆ overlay_filename_

std::string recon::OverlayProducer::overlay_filename_
private

Pileup overlay events input file name.

Definition at line 93 of file OverlayProducer.h.

Referenced by configure(), and onProcessStart().

◆ overlay_passname_

std::string recon::OverlayProducer::overlay_passname_
private

Pileup overlay events input pass name.

Definition at line 131 of file OverlayProducer.h.

Referenced by configure(), and produce().

◆ params_

framework::config::Parameters recon::OverlayProducer::params_
private

The parameters used to configure this producer.

Definition at line 88 of file OverlayProducer.h.

Referenced by configure(), and onProcessStart().

◆ particle_collections_

std::vector<std::string> recon::OverlayProducer::particle_collections_
private

List of SimParticle collection(s) to loop over and add hits from, combining sim and pileup.

Definition at line 121 of file OverlayProducer.h.

Referenced by configure(), and produce().

◆ poisson_mu_

double recon::OverlayProducer::poisson_mu_ {0.}
private

(average) total number of events

Definition at line 159 of file OverlayProducer.h.

159{0.};

Referenced by configure(), and produce().

◆ rndm_

std::unique_ptr<TRandom2> recon::OverlayProducer::rndm_
private

Random number generator for number of overlaid events.

TRandom2 slightly (~10%) faster than TRandom3; shorter period but our input files will have way shorter period anyway.

Definition at line 166 of file OverlayProducer.h.

Referenced by onNewRun(), and produce().

◆ rndm_time_

std::unique_ptr<TRandom2> recon::OverlayProducer::rndm_time_
private

Random number generator for pileup event time offset.

TRandom2 slightly (~10%) faster than TRandom3; shorter period but our input files will have way shorter period anyway.

Definition at line 173 of file OverlayProducer.h.

Referenced by onNewRun(), and produce().

◆ sim_passname_

std::string recon::OverlayProducer::sim_passname_
private

To use for finding the sim event bus passengers, mostly a disambiguation.

Definition at line 136 of file OverlayProducer.h.

Referenced by configure(), and produce().

◆ start_event_max_

int recon::OverlayProducer::start_event_max_ {10000}
private

Maximum event number to start overlaying from.

Inclusive.

Definition at line 217 of file OverlayProducer.h.

217{10000};

Referenced by configure(), and onNewRun().

◆ start_event_min_

int recon::OverlayProducer::start_event_min_ {1}
private

Minimum event number to start overlaying from.

Inclusive.

Definition at line 211 of file OverlayProducer.h.

211{1};

Referenced by configure(), and onNewRun().

◆ time_mean_

double recon::OverlayProducer::time_mean_ {0.}
private

Average position in time (in [ns]) of pileup bunches, relative to the sim event.

Should realistically be 0. Using a non-zero mean and sigma = 0 is however useful for validation.

Definition at line 186 of file OverlayProducer.h.

186{0.};

Referenced by configure(), and produce().

◆ time_sigma_

double recon::OverlayProducer::time_sigma_ {0.}
private

Width of pileup bunch spread in time (in [ns]), specified as a sigma of a Gaussian distribution.

Definition at line 179 of file OverlayProducer.h.

179{0.};

Referenced by configure(), and produce().

◆ track_id_encoding_

unsigned recon::OverlayProducer::track_id_encoding_ {0}
private

Track ID encoding scheme version.

Version is stored in first 4 bits after the sign bit in the track ID int variables (i.e. bits 28-31)

If this variable is left as the hardcoded default 0, then the OverlayProducer will default to not managing track IDs, instead setting all equal to nonsense values as was the case before the introduction of this track ID management.

Definition at line 229 of file OverlayProducer.h.

229{0};

Referenced by configure(), and produce().

◆ tracker_collections_

std::vector<std::string> recon::OverlayProducer::tracker_collections_
private

List of SimTrackerHit collection(s) to loop over and add hits from, combining sim and pileup.

Definition at line 115 of file OverlayProducer.h.

Referenced by configure(), and produce().


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