diff --git a/Blinding/CMakeLists.txt b/Blinding/CMakeLists.txt index 134c529921..251cb4b9d9 100755 --- a/Blinding/CMakeLists.txt +++ b/Blinding/CMakeLists.txt @@ -80,6 +80,7 @@ cet_build_plugin(MergeDigis art::module LIBRARIES REG Offline::Blinding Offline::TrackerMC + Offline::CaloMC ) cet_build_plugin(TrackDigiExtractor art::module diff --git a/Blinding/src/MergeDigis_module.cc b/Blinding/src/MergeDigis_module.cc index ab17296d64..f9c4ff2afd 100644 --- a/Blinding/src/MergeDigis_module.cc +++ b/Blinding/src/MergeDigis_module.cc @@ -24,6 +24,8 @@ #include "Offline/TrackerConditions/inc/StrawElectronics.hh" #include "Offline/TrackerMC/inc/StrawDigiBundle.hh" #include "Offline/TrackerMC/inc/StrawDigiBundleCollection.hh" +#include "Offline/RecoDataProducts/inc/CaloDigi.hh" +#include "Offline/CaloMC/inc/CaloDigiWrapperCollection.hh" #include "Offline/CRVConditions/inc/CRVCalib.hh" #include "Offline/CRVConditions/inc/CRVADCRange.hh" #include "Offline/CRVResponse/inc/CrvMCHelper.hh" @@ -40,6 +42,14 @@ namespace mu2e{ fhicl::Name("MergeStrawDigiMCs"), fhicl::Comment("True/false to merge tracker MC truth") }; + fhicl::Sequence calo_digi_tags{ + fhicl::Name("CaloDigiCollections"), + fhicl::Comment("art::InputTags of source CaloDigis") + }; + fhicl::Atom calo_adc_bits{ + fhicl::Name("CalorimeterADCBitDepth"), + fhicl::Comment("Bit depth of calorimeter adc readings (temporary)") + }; fhicl::Sequence crv_digi_tags{ fhicl::Name("CrvDigiCollections"), fhicl::Comment("art::InputTags of source CrvDigi") @@ -58,6 +68,11 @@ namespace mu2e{ std::vector _tracker_digi_tags; bool _tracker_mc; ProditionsHandle _tracker_conditions_handle; + + // calorimeter + std::vector _calo_digi_tags; + CaloDigiWrapper::sample_t _calo_max_adc; + // crv std::vector _crv_digi_tags; std::vector _crv_digimc_tags; @@ -73,9 +88,10 @@ namespace mu2e{ art::EDProducer(config), _tracker_digi_tags(config().tracker_digi_tags()), _tracker_mc(config().tracker_mc()), + _calo_digi_tags(config().calo_digi_tags()), + _calo_max_adc((1 << config().calo_adc_bits()) - 1), _crv_digi_tags(config().crv_digi_tags()), _crv_digimc_tags(config().crv_digimc_tags()){ - // tracker for (const auto& tag: _tracker_digi_tags){ this->consumes(tag); @@ -84,6 +100,18 @@ namespace mu2e{ this->produces(); this->produces(); + // calorimeter... + for (const auto& tag: _calo_digi_tags){ + this->consumes(tag); + } + this->produces(); + + // crv... + for (const auto& tag: _crv_digi_tags) this->consumes(tag); + for (const auto& tag: _crv_digimc_tags) this->consumes(tag); + this->produces(); + + // mc truth if (_tracker_mc){ for (const auto& tag: _tracker_digi_tags){ @@ -91,14 +119,9 @@ namespace mu2e{ } this->produces(); } - - // calorimeter... - - // crv... - for (const auto& tag: _crv_digi_tags) this->consumes(tag); - for (const auto& tag: _crv_digimc_tags) this->consumes(tag); - this->produces(); - if(!_crv_digimc_tags.empty()) this->produces(); + if(!_crv_digimc_tags.empty()){ + this->produces(); + } } void MergeDigis::produce(art::Event& event){ @@ -129,7 +152,18 @@ namespace mu2e{ event.put(std::move(dgmc)); } - // calorimeter... + // calorimeter: two easy steps: + // i) read all digis into a CaloDigiWrapperCollection + // ii) defer collision resolution to that collection + CaloDigiWrapperCollection wrappers; + for (const auto& tag: _calo_digi_tags){ + auto handle = event.getValidHandle(tag); + wrappers.Append(*handle); + } + CaloDigiWrapperCollection calo_resolved; + wrappers.ResolveCollisions(_calo_max_adc, calo_resolved); + auto calo_digis = calo_resolved.GetDigis(); + event.put(std::move(calo_digis)); // crv... mergeCrvDigis(event); diff --git a/Blinding/src/SConscript b/Blinding/src/SConscript index 18335f5df8..3b7009c547 100644 --- a/Blinding/src/SConscript +++ b/Blinding/src/SConscript @@ -38,6 +38,7 @@ helper.make_plugins([ 'mu2e_SeedService', 'mu2e_TrackerConditions', 'mu2e_TrackerMC', + 'mu2e_CaloMC', ]) helper.make_dict_and_map([ @@ -54,4 +55,5 @@ helper.make_dict_and_map([ 'mu2e_SeedService', 'mu2e_TrackerConditions', 'mu2e_TrackerMC', + 'mu2e_CaloMC', ]) diff --git a/CaloMC/CMakeLists.txt b/CaloMC/CMakeLists.txt index a631ff4e95..915621ac7b 100644 --- a/CaloMC/CMakeLists.txt +++ b/CaloMC/CMakeLists.txt @@ -4,6 +4,8 @@ cet_make_library( src/CaloPhotonPropagation.cc src/CaloWFExtractor.cc src/ShowerStepUtil.cc + src/CaloDigiWrapper.cc + src/CaloDigiWrapperCollection.cc LIBRARIES PUBLIC Offline::CalorimeterGeom diff --git a/CaloMC/inc/CaloDigiWrapper.hh b/CaloMC/inc/CaloDigiWrapper.hh new file mode 100644 index 0000000000..c1677edb60 --- /dev/null +++ b/CaloMC/inc/CaloDigiWrapper.hh @@ -0,0 +1,31 @@ +// Ed Callaghan +// Simple wrapper around calorimeter digis to interface into a partitioning scheme +// September 2025 + +#ifndef CaloMC_CaloDigiWrapper_hh +#define CaloMC_CaloDigiWrapper_hh + +// mu2e +#include "Offline/RecoDataProducts/inc/CaloDigi.hh" + +namespace mu2e{ + class CaloDigiWrapper{ + public: + using SiPMID_t = int; + using sample_t = int; + using pos_t = size_t; + CaloDigiWrapper(const CaloDigi&); + const CaloDigi& Digi() const; + + // interface for sorting into buckets of overlapping digitization windows + const double time() const; + + protected: + const CaloDigi _digi; + + private: + /**/ + }; +} // namespace mu2e + +#endif diff --git a/CaloMC/inc/CaloDigiWrapperCollection.hh b/CaloMC/inc/CaloDigiWrapperCollection.hh new file mode 100644 index 0000000000..eca4f4dc9e --- /dev/null +++ b/CaloMC/inc/CaloDigiWrapperCollection.hh @@ -0,0 +1,62 @@ +// Ed Callaghan +// Container for CaloDigiWrappers, with functionality to resolve overlapping digitization windows +// September 2025 + +#ifndef CaloMC_CaloDigiWrapperCollection_hh +#define CaloMC_CaloDigiWrapperCollection_hh + +// stl +#include +#include +#include +#include + +// mu2e +#include "Offline/CaloMC/inc/CaloDigiWrapper.hh" +#include "Offline/TrackerMC/inc/TimeBasedBucket.hh" + +namespace mu2e{ + using CDWC_iterator = std::vector::iterator; + using CDWC_const_iterator = std::vector::const_iterator; + + class CaloDigiWrapperCollection{ + public: + using SiPMID_t = CaloDigiWrapper::SiPMID_t; + using sample_t = CaloDigiWrapper::sample_t; + using pos_t = CaloDigiWrapper::pos_t; + // forwarded calls to underlying container + size_t size() const; + CDWC_iterator begin(); + CDWC_const_iterator begin() const; + CDWC_iterator end(); + CDWC_const_iterator end() const; + CaloDigiWrapper& operator[](size_t); + const CaloDigiWrapper& operator[](size_t) const; + CaloDigiWrapper& front(); + const CaloDigiWrapper& front() const; + CaloDigiWrapper& back(); + const CaloDigiWrapper& back() const; + + // insertion + void Append(const CaloDigiCollection&); + void Append(const CaloDigiWrapper&); + + // accessor + std::unique_ptr GetDigis() const; + + // identify sets of digis with overlapping digitization windows, and + // reduce each such set to a single digi, representing their "sum" + void ResolveCollisions(sample_t, CaloDigiWrapperCollection&); + + protected: + std::vector _wrappers; + void ResolveCollision(sample_t, + CaloDigiWrapperCollection&, + CaloDigiWrapperCollection&); + + private: + /**/ + }; +} // namespace mu2e + +#endif diff --git a/CaloMC/src/CaloDigiMaker_module.cc b/CaloMC/src/CaloDigiMaker_module.cc index 2f654a269e..5e9705b687 100644 --- a/CaloMC/src/CaloDigiMaker_module.cc +++ b/CaloMC/src/CaloDigiMaker_module.cc @@ -82,7 +82,7 @@ namespace mu2e { digiSampling_ (config().digiSampling()), bufferDigi_ (config().bufferDigi()), startTimeBuffer_ (config().digiSampling()*config().bufferDigi()), - maxADCCounts_ (1 << config().nBits()), + maxADCCounts_ ((1 << config().nBits()) - 1), pulseShape_ (CaloPulseShape(config().digiSampling())), wfExtractor_ (config().bufferDigi(),config().nBinsPeak(),config().minPeakADC(),config().bufferDigi()), engine_ (createEngine(art::ServiceHandle()->getSeed())), diff --git a/CaloMC/src/CaloDigiWrapper.cc b/CaloMC/src/CaloDigiWrapper.cc new file mode 100644 index 0000000000..66a8816b6d --- /dev/null +++ b/CaloMC/src/CaloDigiWrapper.cc @@ -0,0 +1,23 @@ +// Ed Callaghan +// Simple wrapper around calorimeter digis to interface into a partitioning scheme +// September 2025 + +#include "Offline/CaloMC/inc/CaloDigiWrapper.hh" + +namespace mu2e{ + CaloDigiWrapper::CaloDigiWrapper(const CaloDigi& digi): + _digi(digi.SiPMID(), digi.t0(), digi.waveform(), digi.peakpos()){ + /**/ + } + + const CaloDigi& CaloDigiWrapper::Digi() const{ + const auto& rv = _digi; + return rv; + } + + const double CaloDigiWrapper::time() const{ + auto t0 = _digi.t0(); + auto rv = static_cast(t0); + return rv; + } +} // namespace mu2e diff --git a/CaloMC/src/CaloDigiWrapperCollection.cc b/CaloMC/src/CaloDigiWrapperCollection.cc new file mode 100644 index 0000000000..9e4f86310f --- /dev/null +++ b/CaloMC/src/CaloDigiWrapperCollection.cc @@ -0,0 +1,208 @@ +// Ed Callaghan +// Container for CaloDigiWrappers, with functionality to resolve overlapping digitization windows +// September 2025 + +#include "Offline/CaloMC/inc/CaloDigiWrapperCollection.hh" + +namespace mu2e{ + // forward size query to underlying container + size_t CaloDigiWrapperCollection::size() const{ + auto rv = _wrappers.size(); + return rv; + } + + // forward iterator access to underlying wrappers + CDWC_iterator CaloDigiWrapperCollection::begin(){ + auto rv = _wrappers.begin(); + return rv; + } + + CDWC_const_iterator CaloDigiWrapperCollection::begin() const{ + auto rv = _wrappers.begin(); + return rv; + } + + CDWC_iterator CaloDigiWrapperCollection::end(){ + auto rv = _wrappers.end(); + return rv; + } + + CDWC_const_iterator CaloDigiWrapperCollection::end() const{ + auto rv = _wrappers.end(); + return rv; + } + + // forward lookups to underlying container + CaloDigiWrapper& CaloDigiWrapperCollection::operator[](size_t i){ + auto& rv = _wrappers[i]; + return rv; + } + + const CaloDigiWrapper& CaloDigiWrapperCollection::operator[](size_t i) const{ + const auto& rv = _wrappers[i]; + return rv; + } + + CaloDigiWrapper& CaloDigiWrapperCollection::front(){ + auto& rv = _wrappers.front(); + return rv; + } + + const CaloDigiWrapper& CaloDigiWrapperCollection::front() const{ + const auto& rv = _wrappers.front(); + return rv; + } + + CaloDigiWrapper& CaloDigiWrapperCollection::back(){ + auto& rv = _wrappers.back(); + return rv; + } + + const CaloDigiWrapper& CaloDigiWrapperCollection::back() const{ + const auto& rv = _wrappers.back(); + return rv; + } + + // insertion + void CaloDigiWrapperCollection::Append(const CaloDigiCollection& digis){ + for (size_t i = 0 ; i < digis.size() ; i++){ + const auto& digi = digis.at(i); + CaloDigiWrapper wrapper(digi); + _wrappers.emplace_back(digi); + continue; + } + } + + void CaloDigiWrapperCollection::Append(const CaloDigiWrapper& wrapper){ + _wrappers.push_back(wrapper); + } + + // accessor + std::unique_ptr CaloDigiWrapperCollection::GetDigis() const{ + auto rv = std::make_unique(); + rv->reserve(_wrappers.size()); + for (const auto& wrapper: _wrappers){ + const auto& digi = wrapper.Digi(); + rv->push_back(digi); + } + + return rv; + } + + // collision resolution + // auxiliary comparison to facilitate time-sorting + bool compare_t0s(const CaloDigiWrapper* lhs, const CaloDigiWrapper* rhs){ + bool rv = (lhs->Digi().t0() < rhs->Digi().t0()); + return rv; + } + + void CaloDigiWrapperCollection::ResolveCollisions(sample_t max_adc, CaloDigiWrapperCollection& rv){ + // identify time-overlapped chains: this is a 3 step process + // first, partition wrappers according to SiPMID_t + std::map unsorted_map; + for (const auto& wrapper: (*this)){ + const auto& digi = wrapper.Digi(); + SiPMID_t id = digi.SiPMID(); + unsorted_map[id].Append(wrapper); + } + + // next, (approximately) sort all subsets via time, to avoid + // pathological situations where timing buckets are misconstructed + // we shamefully and begrudgingly do this indirectly via bare pointers + std::map wrappers_map; + for (const auto& pair: unsorted_map){ + const auto& id = pair.first; + auto& wrappers = pair.second; + std::vector sortable(wrappers.size()); + for (size_t i = 0 ; i < wrappers.size() ; i++){ + sortable[i] = const_cast(&wrappers[i]); + } + std::sort(sortable.begin(), sortable.end(), compare_t0s); + CaloDigiWrapperCollection sorted; + for (size_t i = 0 ; i < wrappers.size() ; i++){ + sorted.Append(*sortable[i]); + } + wrappers_map.emplace(id, sorted); + } + + // then, filter each subset into buckets based on overlapping time windows + std::map< SiPMID_t, TimeBasedBuckets > buckets_map; + for (const auto& pair: wrappers_map){ + const auto& id = pair.first; + const auto& wrappers = pair.second; + TimeBasedBuckets buckets; + for (const auto& wrapper: wrappers){ + double window = static_cast(wrapper.Digi().waveform().size()); + buckets.Insert(wrapper, window); + } + buckets_map.emplace(id, buckets); + } + + // finally, recast each bucket as a regular container + // and resolve the set of degenerate digis into one + for (const auto& pair: buckets_map){ + const auto& buckets = pair.second; + for (const auto& bucket: buckets){ + CaloDigiWrapperCollection wrappers; + for (const auto& wrapper: bucket){ + wrappers.Append(wrapper); + } + this->ResolveCollision(max_adc, wrappers, rv); + } + } + } + + void CaloDigiWrapperCollection::ResolveCollision(sample_t max_adc, CaloDigiWrapperCollection& collided, CaloDigiWrapperCollection& rv){ + // if only one digi present, then nothing to do + if (collided.size() < 2){ + rv.Append(collided.front()); + return; + } + + // multiple digis must be summed into a single waveform + // here we determine the length of that waveform, by finding + // how far past the end of the first it extends, if at all + const auto& first = collided.front().Digi(); + size_t length = 0; + for (const auto& wrapper: collided){ + const auto& digi = wrapper.Digi(); + size_t proposed = (digi.t0() - first.t0()) + digi.waveform().size(); + if (length < proposed){ + length = proposed; + } + } + std::vector samples(length, 0); + + // sum each individual waveform into the total + for (const auto& wrapper: collided){ + const auto& digi = wrapper.Digi(); + const auto& waveform = digi.waveform(); + const size_t shift = digi.t0() - first.t0(); + for (size_t i = 0 ; i < waveform.size() ; i++){ + samples[i + shift] += waveform[i]; + } + } + + // enforce saturation of waveforms from adc word size + for (size_t i = 0 ; i < samples.size() ; i++){ + samples[i] = std::min(max_adc, samples[i]); + } + + // now find the peak position + pos_t peakpos = 0; + sample_t peak = 0; + for (size_t i = 0 ; i < samples.size() ; i++){ + const auto sample = samples[i]; + if (peak < sample){ + peakpos = i; + peak = sample; + } + } + + const auto id = first.SiPMID(); + const auto t0 = first.t0(); + const auto digi = CaloDigi(id, t0, samples, peakpos); + const auto wrapper = CaloDigiWrapper(digi); + rv.Append(wrapper); + } +} diff --git a/EventMixing/inc/Mu2eProductMixer.hh b/EventMixing/inc/Mu2eProductMixer.hh index 08f718fa63..b230a78c1a 100644 --- a/EventMixing/inc/Mu2eProductMixer.hh +++ b/EventMixing/inc/Mu2eProductMixer.hh @@ -45,6 +45,8 @@ #include "Offline/RecoDataProducts/inc/StrawDigi.hh" #include "Offline/RecoDataProducts/inc/CrvDigi.hh" #include "Offline/MCDataProducts/inc/StrawDigiMC.hh" +#include "Offline/RecoDataProducts/inc/CaloDigi.hh" +#include "Offline/MCDataProducts/inc/CaloShowerSim.hh" #include "Offline/MCDataProducts/inc/CrvDigiMC.hh" #include "Offline/DataProducts/inc/EventWindowMarker.hh" @@ -111,6 +113,8 @@ namespace mu2e { fhicl::Table strawDigiMixer { fhicl::Name("strawDigiMixer") }; fhicl::Table strawDigiADCWaveformMixer { fhicl::Name("strawDigiADCWaveformMixer") }; fhicl::Table strawDigiMCMixer { fhicl::Name("strawDigiMCMixer") }; + fhicl::Table caloDigiMixer { fhicl::Name("caloDigiMixer") }; + fhicl::Table caloShowerSimMixer { fhicl::Name("caloShowerSimMixer") }; fhicl::Table crvDigiMixer { fhicl::Name("crvDigiMixer") }; fhicl::Table crvDigiMCMixer { fhicl::Name("crvDigiMCMixer") }; //needs to be index-matched with crvDigiMixer fhicl::Table eventWindowMarkerMixer { fhicl::Name("eventWindowMarkerMixer") }; @@ -176,6 +180,14 @@ namespace mu2e { StrawDigiMCCollection& out, art::PtrRemapper const& remap); + bool mixCaloDigis(std::vector const& in, + CaloDigiCollection& out, + art::PtrRemapper const& remap); + + bool mixCaloShowerSims(std::vector const& in, + CaloShowerSimCollection& out, + art::PtrRemapper const& remap); + bool mixCrvDigis(std::vector const& in, CrvDigiCollection& out, art::PtrRemapper const& remap); @@ -221,6 +233,8 @@ namespace mu2e { typedef StrawGasStepCollection::size_type SGSOffset; std::vector sgsOffsets_; + typedef CaloShowerStepCollection::size_type CSSOffset; + std::vector cssOffsets_; typedef CrvStepCollection::size_type CSOffset; std::vector csOffsets_; diff --git a/EventMixing/src/Mu2eProductMixer.cc b/EventMixing/src/Mu2eProductMixer.cc index 03deea604c..620f96f859 100644 --- a/EventMixing/src/Mu2eProductMixer.cc +++ b/EventMixing/src/Mu2eProductMixer.cc @@ -117,6 +117,16 @@ namespace mu2e { (e.inTag, e.resolvedInstanceName(), &Mu2eProductMixer::mixStrawDigiMCs, *this); } + for(const auto& e: conf.caloDigiMixer().mixingMap()) { + helper.declareMixOp + (e.inTag, e.resolvedInstanceName(), &Mu2eProductMixer::mixCaloDigis, *this); + } + + for(const auto& e: conf.caloShowerSimMixer().mixingMap()) { + helper.declareMixOp + (e.inTag, e.resolvedInstanceName(), &Mu2eProductMixer::mixCaloShowerSims, *this); + } + for(const auto& e: conf.crvDigiMixer().mixingMap()) { helper.declareMixOp (e.inTag, e.resolvedInstanceName(), &Mu2eProductMixer::mixCrvDigis, *this); @@ -361,11 +371,10 @@ namespace mu2e { CaloShowerStepCollection& out, art::PtrRemapper const& remap) { - std::vector stepOffsets; - art::flattenCollections(in, out, stepOffsets); + art::flattenCollections(in, out, cssOffsets_); for(CaloShowerStepCollection::size_type i=0; i const& in, + CaloDigiCollection& out, + art::PtrRemapper const& remap) + { + art::flattenCollections(in, out); + return true; + } + bool Mu2eProductMixer::mixCrvDigis(std::vector const& in, CrvDigiCollection& out, art::PtrRemapper const& remap) @@ -497,6 +514,31 @@ namespace mu2e { return true; } + bool Mu2eProductMixer::mixCaloShowerSims(std::vector const& in, + CaloShowerSimCollection& out, + art::PtrRemapper const& remap) + { + std::vector cssimOffsets; + art::flattenCollections(in, out, cssimOffsets); + + // remap art::Ptrs + for (CaloShowerSimCollection::size_type i=0; i < out.size(); ++i) { + auto& sim = out[i]; + auto ie = getInputEventIndex(i, cssimOffsets); + auto cssOffset = cssOffsets_[ie]; + + // remap CaloShowerSteps + auto& steps = sim.caloShowerSteps(); + CaloShowerSim::StepPtrs remapped; + for (size_t is = 0 ; is < steps.size(); is++){ + remapped.push_back(remap(steps[is], cssOffset)); + } + sim.setCaloShowerSteps(std::move(remapped)); + } + + return true; + } + bool Mu2eProductMixer::mixCrvDigiMCs(std::vector const& in, CrvDigiMCCollection& out, art::PtrRemapper const& remap) diff --git a/Mu2eKinKal/inc/KKFit.hh b/Mu2eKinKal/inc/KKFit.hh index bce34f050e..24de58d236 100644 --- a/Mu2eKinKal/inc/KKFit.hh +++ b/Mu2eKinKal/inc/KKFit.hh @@ -47,6 +47,9 @@ #include #include #include + +using std::endl; + namespace mu2e { using KinKal::SensorLine; using KinKal::TimeRange; diff --git a/TrackerMC/inc/TimeBasedBucket.hh b/TrackerMC/inc/TimeBasedBucket.hh index ff2f76cf78..0acad79e68 100644 --- a/TrackerMC/inc/TimeBasedBucket.hh +++ b/TrackerMC/inc/TimeBasedBucket.hh @@ -18,7 +18,7 @@ namespace mu2e{ template class TimeBasedBucket{ public: - TimeBasedBucket(double); + TimeBasedBucket(); // forwarded calls to underlying container size_t size() const; @@ -28,12 +28,12 @@ namespace mu2e{ TBB_const_iterator end() const; // whether a candidate item "fits" into this bucket's gross time window - bool Accepts(T); + bool Accepts(T, double); // insertion --- assumes that appends are pre-sorted - void Append(T); + void Append(T, double); protected: std::vector _container; - double _window; + std::vector _windows; private: /**/ }; @@ -49,7 +49,7 @@ namespace mu2e{ template class TimeBasedBuckets{ public: - TimeBasedBuckets(double); + TimeBasedBuckets(); // forwarded calls to underlying container size_t size() const; @@ -59,16 +59,15 @@ namespace mu2e{ TBBS_const_iterator end() const; // insertion - void Insert(T); + void Insert(T, double); protected: std::vector< TimeBasedBucket > _buckets; - double _window; private: /**/ }; template - TimeBasedBucket::TimeBasedBucket(double window): _window(window){ + TimeBasedBucket::TimeBasedBucket(){ /**/ } @@ -106,15 +105,15 @@ namespace mu2e{ // whether a candidate item "fits" into this bucket's gross time window template - bool TimeBasedBucket::Accepts(T candidate){ + bool TimeBasedBucket::Accepts(T candidate, double window){ // empty bucket rejects nothing if (this->size() < 1){ return true; } // otherwise, check between first/last times, accounting for windowing - double lower = _container.front().time() - _window; - double upper = _container.back().time() + _window; + double lower = _container.front().time() - window; + double upper = _container.back().time() + _windows.back(); double now = candidate.time(); bool rv = (lower <= now) && (now <= upper); return rv; @@ -122,12 +121,13 @@ namespace mu2e{ // insertion --- assumes that appends are pre-sorted template - void TimeBasedBucket::Append(T candidate){ + void TimeBasedBucket::Append(T candidate, double window){ _container.push_back(candidate); + _windows.push_back(window); } template - TimeBasedBuckets::TimeBasedBuckets(double window): _window(window){ + TimeBasedBuckets::TimeBasedBuckets(){ /**/ } @@ -165,12 +165,12 @@ namespace mu2e{ // insertion template - void TimeBasedBuckets::Insert(T item){ + void TimeBasedBuckets::Insert(T item, double window){ // if the item belongs in a preexisting bucket, put it there bool inserted = false; for (auto& bucket: (*this)){ - if (bucket.Accepts(item)){ - bucket.Append(item); + if (bucket.Accepts(item, window)){ + bucket.Append(item, window); inserted = true; return; } @@ -178,9 +178,9 @@ namespace mu2e{ // otherwise, this item defines a new bucket if (!inserted){ - TimeBasedBucket bucket(_window); + TimeBasedBucket bucket; _buckets.push_back(bucket); - this->Insert(item); + this->Insert(item, window); } } } diff --git a/TrackerMC/src/StrawDigiBundleCollection.cc b/TrackerMC/src/StrawDigiBundleCollection.cc index 3ebfbb29c8..8f3492c18e 100644 --- a/TrackerMC/src/StrawDigiBundleCollection.cc +++ b/TrackerMC/src/StrawDigiBundleCollection.cc @@ -191,9 +191,9 @@ namespace mu2e{ for (const auto& pair: bundles_map){ const auto& id = pair.first; const auto& bundles = pair.second; - TimeBasedBuckets buckets(window); + TimeBasedBuckets buckets; for (const auto& bundle: bundles){ - buckets.Insert(bundle); + buckets.Insert(bundle, window); } buckets_map.emplace(id, buckets); }