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(trace) << "Track ID has value " << track_id
559 << " < 0; no encoding will be applied (this is expected "
560 "for origin IDs in SimCalorimeterHits)";
561 return track_id;
562 }
563
564 // encode Track ID according to provided version
565 switch (encoding_version) {
566 case (unsigned)0: { // need braces for variable init scope control
567 ldmx_log(trace) << "No encoding applied";
568 encoded_id = track_id;
569 break;
570 }
571 case (unsigned)1: {
572 // create bitwise masks for encoding from version number and event index
573 unsigned version_mask = (encoding_version << 27);
574 unsigned index_mask = (event_index << 24);
575
576 // encode track ID using bitwise OR
577 encoded_id = track_id | version_mask | index_mask;
578 ldmx_log(trace) << "Encoding successful! encoded_id = " << encoded_id
579 << ", with bit representation "
580 << std::bitset<32>(encoded_id);
581 break;
582 }
583 default: { // version number has no associated encoding scheme
584 ldmx_log(warn) << "Track ID encoding version " << encoding_version
585 << " has no definition! No encoding will be applied";
586 encoded_id = track_id;
587 }
588 }
589
590 return encoded_id;
591}

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 593 of file OverlayProducer.cxx.

593 {
594 // replace by this line once the corresponding tweak to EventFile is ready:
596 std::make_unique<framework::EventFile>(params_, overlay_filename_, true);
597 overlay_file_->setupEvent(&overlay_event_);
598 // we update the iterator at the end of each event. so do this once here to
599 // grab the first event in the processor
600 // ldmx_log(trace) << "Used input file: "
601 // << overlay_file_->getFileName() << " Got event info: " <<
602 // overlay_file_->getEvent()->Print();
603
604 return;
605} // 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 // TODO -- figure out if we should also randomly shift the time of the sim
241 // event (likely only needed if time bias gets picked up by BDT or ML by way
242 // of pulse behaviour)
243 for (int bunch_offset{start_bunch}; bunch_offset <= end_bunch;
244 bunch_offset++) {
245 // sample a poisson distribution, or use mu as fixed number of overlay
246 // events
247 int n_events_overlay = do_poisson_out_of_time_
248 ? rndm_->Poisson(poisson_mu_)
249 : static_cast<int>(poisson_mu_);
250
251 // special case: in-time pileup at bunch 0
252 if (bunch_offset == 0) {
253 if (!do_poisson_in_time_) {
254 // fix it to the average
255 n_events_overlay = static_cast<int>(poisson_mu_);
257 // then we haven't set this yet
258 n_events_overlay = rndm_->Poisson(poisson_mu_);
259 }
260
261 // paticularly useful in the poisson fluctuated case
262 event.getEventHeader().setIntParameter("in_time_pu", n_events_overlay);
263
264 // the total number of events is nPU + 1 (it includes the sim event)
265 // in any case, subtract the sim event from nOverlay
266 n_events_overlay -= 1;
267
268 } // end if bunch_offset == 0
269
270 float bunchtime_offset = bunch_spacing_ * bunch_offset;
271 ldmx_log(debug) << "Will overlay " << n_events_overlay
272 << " events on the simulated one";
273
274 for (int i_ev = 0; i_ev < n_events_overlay; i_ev++) {
281 if (!overlay_file_->nextEvent()) {
282 ldmx_log(error) << "Couldn't read next overlay event!";
283 return;
284 }
285 if (i_ev + 1 > 7) {
286 ldmx_log(error) << "Too many overlay events! Maximum events that can "
287 "be overlayed is 7.";
288 return;
289 }
290
291 // a pileup event wide time offset to be applied to all its hits_.
292 float time_offset = rndm_time_->Gaus(time_mean_, time_sigma_);
293 time_offset += bunchtime_offset;
294
295 ldmx_log(trace) << "in overlay loop: overlaying event " << "which is "
296 << i_ev + 1 << " out of " << n_events_overlay
297 << "\n\thit time offset is " << time_offset << " ns"
298 << "\n\tbunch position offset is " << bunch_offset
299 << ", leading to a total time offset of "
300 << bunchtime_offset << " ns";
301
302 /* ----------- first do the SimCalorimeterHits overlay ----------- */
303
304 // again get the calo hits_ collections that we want to overlay
305 for (uint i_coll = 0; i_coll < calo_collections_.size(); i_coll++) {
306 // search for the collection name in the list of collections that
307 // need contribs to be added, contrib_collections_
308 bool needs_contribs_added{
309 std::find(contrib_collections_.begin(), contrib_collections_.end(),
311 ? true
312 : false};
313
314 std::vector<ldmx::SimCalorimeterHit> overlay_hits =
317
318 ldmx_log(debug) << "in loop: size of overlay hits_ vector is "
319 << overlay_hits.size();
320
321 std::string out_coll_name =
323
324 ldmx_log(trace) << "in loop: printing overlay event: ";
325
326 for (ldmx::SimCalorimeterHit &overlay_hit : overlay_hits) {
327 ldmx_log(trace) << overlay_hit;
328
329 // update relevant parameters with overlay modifications
330 overlay_hit.setTime(overlay_hit.getTime() + time_offset);
331 overlay_hit.setPreStepTime(overlay_hit.getPreStepTime() +
332 time_offset);
333 overlay_hit.setPostStepTime(overlay_hit.getPostStepTime() +
334 time_offset);
335 overlay_hit.encodeTracks(
336 [this](int id, unsigned enc, unsigned idx) {
337 return encodeTrack(id, enc, idx);
338 },
339 track_id_encoding_, i_ev + 1);
340
341 if (needs_contribs_added) { // special treatment for (for now only)
342 // ecal
343 auto &this_coll_hit_map{
344 hit_map[calo_collections_[i_coll] + out_coll_postfix_]};
345 int overlay_hit_id = overlay_hit.getID();
346 if (this_coll_hit_map.find(overlay_hit_id) ==
347 this_coll_hit_map
348 .end()) { // there wasn't already a simhit in this id
349 ldmx_log(trace)
350 << "No existing simhit found for ID " << overlay_hit_id
351 << "; copying overlay hit to output collection";
352 auto &output_hit = this_coll_hit_map[overlay_hit_id];
353 output_hit = overlay_hit; // copy hit
354
355 // we need to do some backflips to get the contribs correct later
356 auto id = output_hit.getID();
357 auto pos = output_hit.getPosition();
358 auto time = output_hit.getTime();
359 output_hit.clear(); // with the below adjustments, this will only
360 // clear contribs from the output_hit
361 output_hit.setID(id);
362 output_hit.setPosition(pos[0], pos[1], pos[2]);
363 output_hit.setTime(time);
364 } // if overlay_hit_id not present
365
366 // add the overlay hit contribs to existing hit,
367 // incrementing track IDs and timestamp as needed
368 int n_contribs = overlay_hit.getNumberOfContribs();
369 ldmx_log(trace)
370 << "Copying and reindexing " << n_contribs
371 << " contributors to the sim hit for ID " << overlay_hit_id;
372 for (int i = 0; i < n_contribs; i++) {
374 overlay_hit.getContrib(i)};
375 // tracks were encoded in-place above, so we only need to worry
376 // about times
377 this_coll_hit_map[overlay_hit_id].addContrib(
378 contrib.incident_id_, contrib.track_id_, contrib.pdg_code_,
379 contrib.edep_, contrib.time_ + time_offset,
380 contrib.origin_id_ + i_ev + 1);
381 } // loop over contribs in overlay_hit
382 ldmx_log(trace)
383 << "There are now "
384 << this_coll_hit_map[overlay_hit_id].getNumberOfContribs()
385 << " total contributors in the output collection";
386 } // if add overlay as contribs
387 else {
388 // no need to change contrib timestamps here
389 calo_collection_map[out_coll_name].push_back(overlay_hit);
390
391 ldmx_log(trace) << "Adding non-Ecal overlay hit to outhit vector "
392 << out_coll_name;
393 } // end else !needs_contribs_added
394 } // over overlay calo simhit collection
395
396 if (!needs_contribs_added)
397 ldmx_log(debug) << "Nhits in overlay collection " << out_coll_name
398 << ": " << calo_collection_map[out_coll_name].size();
399
400 } // over calo_collections_
401
402 /* ----------- now do simtracker hits_ overlay ----------- */
403
404 // loop over the SimTrackerHit collections that we want to overlay
405 for (const auto &coll : tracker_collections_) {
406 auto overlay_tracker_hits{
408 coll, overlay_passname_)};
409
410 ldmx_log(debug) << "in loop: size of overlay hits_ vector is "
411 << overlay_tracker_hits.size();
412
413 std::string out_coll_name_tracker{coll + out_coll_postfix_};
414
415 ldmx_log(trace) << "in loop: printing overlay event: ";
416
417 for (auto &overlay_hit : overlay_tracker_hits) {
418 auto overlay_time{overlay_hit.getTime() + time_offset};
419 overlay_hit.setTime(overlay_time);
420 auto overlay_track_id{encodeTrack(overlay_hit.getTrackID(),
421 track_id_encoding_, i_ev + 1)};
422 overlay_hit.setTrackID(overlay_track_id);
423
424 ldmx_log(trace) << overlay_hit;
425 ldmx_log(trace) << "Adding tracker overlay hit to outhit vector "
426 << out_coll_name_tracker;
427
428 tracker_collection_map[out_coll_name_tracker].push_back(overlay_hit);
429 } // over overlay tracker simhit collection
430
431 ldmx_log(debug) << "Nhits in overlay collection "
432 << out_coll_name_tracker << ": "
433 << tracker_collection_map[out_coll_name_tracker].size();
434
435 } // over tracker_collections_
436
437 /* ----------- finally do SimParticles overlay ----------- */
438 for (const auto &coll : particle_collections_) {
439 auto overlay_particles{overlay_event_.getMap<int, ldmx::SimParticle>(
440 coll, overlay_passname_)};
441
442 ldmx_log(debug) << "in loop: size of overlay particles map is "
443 << overlay_particles.size();
444
445 std::string out_coll_name_particles{coll + out_coll_postfix_};
446 auto &output_map = particle_collection_map[out_coll_name_particles];
447
448 ldmx_log(trace) << "in loop: printing overlay event: ";
449
450 for (auto &[track_id, particle] : overlay_particles) {
451 int new_track_id =
452 encodeTrack(track_id, track_id_encoding_, i_ev + 1);
453
454 output_map[new_track_id] = particle;
455 output_map[new_track_id].encodeTracks(
456 [this](int id, unsigned enc, unsigned idx) {
457 return encodeTrack(id, enc, idx);
458 },
459 track_id_encoding_, i_ev + 1);
460 output_map[new_track_id].setTime(particle.getTime() + time_offset);
461
462 ldmx_log(trace) << "Track ID: " << new_track_id << " --- "
463 << output_map[new_track_id];
464 ldmx_log(trace) << "Adding sim particle to output map "
465 << out_coll_name_particles;
466 } // over overlay sim particles collection
467 } // over particle_collections_
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: