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::EventFile > overlay_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
 
NtupleManager & ntuple_ {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 22 of file OverlayProducer.h.

Constructor & Destructor Documentation

◆ OverlayProducer()

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

Definition at line 24 of file OverlayProducer.h.

25 : 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 15 of file OverlayProducer.cxx.

15 {
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()
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:75
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 544 of file OverlayProducer.cxx.

546 {
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}

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

91 {
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()
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:57
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 603 of file OverlayProducer.cxx.

603 {
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

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

112 {
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()
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
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
Stores simulated calorimeter hit information.
Class representing a simulated particle.
Definition SimParticle.h:25
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 183 of file OverlayProducer.h.

183{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 101 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 118 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 140 of file OverlayProducer.h.

140{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 146 of file OverlayProducer.h.

146{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 190 of file OverlayProducer.h.

190{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 197 of file OverlayProducer.h.

197{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 134 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 95 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 90 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 85 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 123 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 80 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 113 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 151 of file OverlayProducer.h.

151{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 158 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 165 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 128 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 209 of file OverlayProducer.h.

209{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 203 of file OverlayProducer.h.

203{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 178 of file OverlayProducer.h.

178{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 171 of file OverlayProducer.h.

171{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 221 of file OverlayProducer.h.

221{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 107 of file OverlayProducer.h.

Referenced by configure(), and produce().


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