diff --git a/Simulation/DetSimMixing/CMakeLists.txt b/Simulation/DetSimMixing/CMakeLists.txt
old mode 100755
new mode 100644
diff --git a/Simulation/DetSimMixing/src/BackgroundBatch.hh b/Simulation/DetSimMixing/src/BackgroundBatch.hh
old mode 100755
new mode 100644
index bdd16ba14e18dbca6bd5a1aafaf467a62ccad9ef..9672e6a5408e237a224db4b6bde5afac36ef83a1
--- a/Simulation/DetSimMixing/src/BackgroundBatch.hh
+++ b/Simulation/DetSimMixing/src/BackgroundBatch.hh
@@ -5,8 +5,7 @@
#include <vector>
#include "TTimeStamp.h"
-class BackgroundBatch {
-public:
+struct BackgroundBatch {
double start_time; // ns, the start time of the batch, relative to signal event
double duration; // the duration of the batch
int num_events; // the number of events in the batch
diff --git a/Simulation/DetSimMixing/src/BackgroundEvent.hh b/Simulation/DetSimMixing/src/BackgroundEvent.hh
new file mode 100644
index 0000000000000000000000000000000000000000..c6a8bea9ed6b55b14749aaf960f447b06742829f
--- /dev/null
+++ b/Simulation/DetSimMixing/src/BackgroundEvent.hh
@@ -0,0 +1,55 @@
+#ifndef BackgroundEvent_hh
+#define BackgroundEvent_hh
+
+#include <map>
+#include <vector>
+#include <string>
+#include "edm4hep/SimTrackerHitCollection.h"
+#include "edm4hep/SimCalorimeterHitCollection.h"
+#include "edm4hep/CaloHitContributionCollection.h"
+
+/*
+ * Description:
+ * As there are multiple collections for one event, this BackgrounEvent
+ * is used to organize these collections.
+ *
+ * The key is the index of collection.
+ *
+ * BackgroundLoader is resposible to fill its hit collections into the
+ * BackgroundEvent.
+ */
+struct BackgroundEvent {
+ std::map<size_t, edm4hep::SimTrackerHitCollection> tracker_hits;
+ std::map<size_t, edm4hep::SimCalorimeterHitCollection> calorimeter_hits;
+ std::map<size_t, edm4hep::CaloHitContributionCollection> calo_contribs;
+
+ std::map<std::string, size_t> collection_index; // key is collection name, value is index.
+ std::map<std::string, size_t> collection_subdet; // key is collection name, value is subdetector type.
+
+ // in order to reduce the memory usage, need additional filter setup here.
+ // for example, for TPC, we need to load all the hits.
+ // however, for the tracker/calo, we only need to load the hits which are
+ // in an interested event time window.
+ enum SubDetType {
+ kVXD = 0, // 200 ns
+ kITK = 1, // 200 ns
+ kTPC = 2, // 34 us
+ kOTK = 3, // 1 us
+ kECAL = 4, // 150 ns
+ kHCAL = 5, // 1 us
+ kMUON = 6, // 100 ns // from Xiaolong Wang
+ kNSubDetType
+ };
+ std::vector<double> subdet2twindow = {200, 200, 34000, 1000, 150, 1000, 100}; // key is subdet, value is time window.
+ std::vector<std::vector<std::string>> subdet2colnames = {
+ {"VXD"},
+ {"ITK"},
+ {"TPC"},
+ {"OTK"},
+ {"Ecal"},
+ {"Hcal"},
+ {"Muon"}
+ };
+};
+
+#endif
diff --git a/Simulation/DetSimMixing/src/BackgroundLoader.hh b/Simulation/DetSimMixing/src/BackgroundLoader.hh
old mode 100755
new mode 100644
index 7ab42bf9c7128ed71d9378ce847bc98ab2e3b112..6839ec53215523ae09148156ca6a5ec65e108034
--- a/Simulation/DetSimMixing/src/BackgroundLoader.hh
+++ b/Simulation/DetSimMixing/src/BackgroundLoader.hh
@@ -2,6 +2,7 @@
#define BackgroundLoader_hh
#include "IBackgroundLoader.hh"
+#include "BackgroundEvent.hh"
#include <iostream>
#include <vector>
#include <string>
diff --git a/Simulation/DetSimMixing/src/DetSimMixingAlg.cc b/Simulation/DetSimMixing/src/DetSimMixingAlg.cc
old mode 100755
new mode 100644
index 23c9bcb56c4df945ef938afa23a5c3904891b076..cd0e030fbed29ee5fff773ce49475a7b4072ee77
--- a/Simulation/DetSimMixing/src/DetSimMixingAlg.cc
+++ b/Simulation/DetSimMixing/src/DetSimMixingAlg.cc
@@ -9,6 +9,7 @@
#include <CLHEP/Random/RandPoisson.h>
#include "BackgroundLoader.hh"
+#include "BackgroundEvent.hh"
DECLARE_COMPONENT(DetSimMixingAlg)
@@ -21,26 +22,26 @@ StatusCode DetSimMixingAlg::initialize() {
info() << "Initialize DetSimMixingAlg... " << endmsg;
// preparation according to user properties
- if (m_background_rates.value().size() != m_background_filelists.value().size()) {
+ if (m_background_timings.value().size() != m_background_filelists.value().size()) {
error() << "The size of the background rates and filelists should be the same." << endmsg;
return StatusCode::FAILURE;
}
- for (auto [type, rate]: m_background_rates.value()) {
+ for (auto [type, timing]: m_background_timings.value()) {
if (m_background_filelists.value().find(type) == m_background_filelists.value().end()) {
error() << "The input file lists for the background type " << type << " is not provided." << endmsg;
return StatusCode::FAILURE;
}
m_event_types.push_back(type);
- m_event_rates.push_back(rate);
+ m_event_timings.push_back(timing);
m_input_lists.push_back(m_background_filelists.value()[type]);
}
// prepare the loaders
for (size_t i = 0; i < m_event_types.size(); ++i) {
// only the positive rates are considered into total rates
- if (m_event_rates[i] > 0) {
- m_total_rates += m_event_rates[i];
+ if (m_event_timings[i] > 0) {
+ m_total_rates += m_event_timings[i];
}
m_event_loaders.push_back(new BackgroundLoader(m_input_lists[i]));
}
@@ -55,10 +56,10 @@ StatusCode DetSimMixingAlg::initialize() {
}
info() << "Summary of the background events: " << endmsg;
for (size_t i = 0; i < m_event_types.size(); ++i) {
- if (m_event_rates[i] > 0) {
- info() << " Event type: " << m_event_types[i] << ", rate: " << m_event_rates[i] << " Hz" << endmsg;
+ if (m_event_timings[i] > 0) {
+ info() << " Event type: " << m_event_types[i] << ", rate: " << m_event_timings[i] << " Hz" << endmsg;
} else {
- info() << " Event type: " << m_event_types[i] << ", time window: " << fabs(m_event_rates[i]) << " ns" << endmsg;
+ info() << " Event type: " << m_event_types[i] << ", time window: " << fabs(m_event_timings[i]) << " ns" << endmsg;
}
}
@@ -110,8 +111,9 @@ StatusCode DetSimMixingAlg::execute() {
// ========================================================================
std::vector<BackgroundBatch> batches;
- int nbatches = 10; // the total number of batches will be 2*nbatches, [-nbatches, nbatches)
- double duration = 3460; // duration of each batch (ns): Nbunch x TBunchSpacing = 10 x 346 ns = 3460 ns
+ int nbatches = m_nbatches.value(); // the total number of batches will be 2*nbatches, [-nbatches, nbatches)
+ int nbunches = m_nbunches_per_batch.value(); // the total number of bunches per batch
+ double duration = nbunches * m_bunch_crossing_spacing.value(); // duration of each batch (ns): Nbunch x TBunchSpacing = 10 x 277 ns = 2770 ns
for (int i = -nbatches; i < nbatches; ++i) {
BackgroundBatch batch;
@@ -132,10 +134,10 @@ StatusCode DetSimMixingAlg::execute() {
// insert at beginning, align to the begin of batch
for (size_t evttype = 0; evttype < m_event_types.size(); ++evttype) {
// skip the sampled mode type
- if (m_event_rates[evttype] > 0) {
+ if (m_event_timings[evttype] > 0) {
continue;
}
- double time_window_event = fabs(m_event_rates[evttype]);
+ double time_window_event = fabs(m_event_timings[evttype]);
int n_events = std::max(1, static_cast<int>(batch.duration/time_window_event)); // ns
for (size_t j = 0; j < n_events; ++j) {
@@ -157,10 +159,10 @@ StatusCode DetSimMixingAlg::execute() {
double accumulated = 0;
for (size_t evttype = 0; evttype < m_event_types.size(); ++evttype) {
// skip the fixed time mode type
- if (m_event_rates[evttype] <= 0) {
+ if (m_event_timings[evttype] <= 0) {
continue;
}
- accumulated += m_event_rates[evttype];
+ accumulated += m_event_timings[evttype];
if (r < accumulated) {
selected_evttype = evttype;
break;
@@ -191,6 +193,15 @@ StatusCode DetSimMixingAlg::execute() {
// of BackgroundEvent.
// ========================================================================
BackgroundEvent bkg_evt;
+ // setup the time window
+ bkg_evt.subdet2twindow[BackgroundEvent::kVXD] = m_vxd_time_window.value();
+ bkg_evt.subdet2twindow[BackgroundEvent::kITK] = m_itk_time_window.value();
+ bkg_evt.subdet2twindow[BackgroundEvent::kTPC] = m_tpc_time_window.value();
+ bkg_evt.subdet2twindow[BackgroundEvent::kOTK] = m_otk_time_window.value();
+ bkg_evt.subdet2twindow[BackgroundEvent::kECAL] = m_ecal_time_window.value();
+ bkg_evt.subdet2twindow[BackgroundEvent::kHCAL] = m_hcal_time_window.value();
+ bkg_evt.subdet2twindow[BackgroundEvent::kMUON] = m_muon_time_window.value();
+
info() << "Creating a BackgroundEvent..." << endmsg;
for (size_t i = 0; i < batches.size(); ++i) {
info() << " Batch " << i << ": " << endmsg;
@@ -228,8 +239,34 @@ StatusCode DetSimMixingAlg::execute() {
// Put the BackgroundEvent into the event store
// ========================================================================
// add prefix 'Mixed'.
- for (auto [col_name, colidx]: bkg_evt.collection_index) {
+
+ // Need to prepare a complete list of collection names.
+ std::map<std::string, size_t> col_names;
+ for (auto [name, idx]: bkg_evt.collection_index) {
+ ++col_names[name];
+ }
+ for (auto [name, idx]: m_sig_trackerColMap) {
+ if (col_names.find(name) == col_names.end()) {
+ warning() << "Collection " << name << " is not in the background event." << endmsg;
+ }
+ ++col_names[name];
+ }
+ for (auto [name, idx]: m_sig_calorimeterColMap) {
+ if (col_names.find(name) == col_names.end()) {
+ warning() << "Collection " << name << " is not in the background event." << endmsg;
+ }
+ ++col_names[name];
+ }
+
+ for (auto [col_name, cnt]: col_names) {
+
+ if (bkg_evt.collection_index.find(col_name) == bkg_evt.collection_index.end()) {
+ debug() << "Collection " << col_name << " is not in the background event." << endmsg;
+ continue;
+ }
+ auto colidx = bkg_evt.collection_index[col_name];
+
if (bkg_evt.tracker_hits.count(colidx)) {
auto& col = bkg_evt.tracker_hits[colidx];
@@ -252,7 +289,17 @@ StatusCode DetSimMixingAlg::execute() {
if (!sig_col) {
continue;
}
+
+ // keep the same time windows for signal and backgrounds.
+ auto time_window = bkg_evt.subdet2twindow[bkg_evt.collection_subdet[col_name]];
+
for (auto oldhit: *sig_col) {
+ auto t = oldhit.getTime();
+ if (t < -time_window || t > time_window) {
+ // if the hit is not in the time window, skip.
+ continue;
+ }
+
auto newhit = newcol->create();
newhit.setCellID(oldhit.getCellID());
newhit.setEDep(oldhit.getEDep());
@@ -295,7 +342,25 @@ StatusCode DetSimMixingAlg::execute() {
continue;
}
+ // keep the same time windows for signal and backgrounds.
+ auto time_window = bkg_evt.subdet2twindow[bkg_evt.collection_subdet[col_name]];
+
+
for (auto oldhit: *sig_col) {
+ // check whether the hit is in the time window.
+ bool is_in_window = false;
+ for (auto contrib: oldhit.getContributions()) {
+ auto t = contrib.getTime();
+ if (t < -time_window || t > time_window) {
+ continue;
+ }
+ is_in_window = true;
+ break;
+ }
+ if (not is_in_window) {
+ continue;
+ }
+
auto newhit = newcol->create();
newhit.setCellID(oldhit.getCellID());
newhit.setEnergy(oldhit.getEnergy());
@@ -313,7 +378,7 @@ StatusCode DetSimMixingAlg::execute() {
}
} else {
- error() << "The collection " << col_name
+ debug() << "The collection " << col_name
<< " with idx" << colidx
<< " is not found." << endmsg;
continue;
diff --git a/Simulation/DetSimMixing/src/DetSimMixingAlg.hh b/Simulation/DetSimMixing/src/DetSimMixingAlg.hh
old mode 100755
new mode 100644
index 55aa56a7def63ac36ddd554ca49d161a81b41171..d50c9b3f17332f1992a0a47e27a0b92c33117d6f
--- a/Simulation/DetSimMixing/src/DetSimMixingAlg.hh
+++ b/Simulation/DetSimMixing/src/DetSimMixingAlg.hh
@@ -46,8 +46,9 @@
#include "k4FWCore/DataHandle.h"
-#include "BackgroundBatch.hh"
#include "IBackgroundLoader.hh"
+#include "BackgroundBatch.hh"
+#include "BackgroundEvent.hh"
class DetSimMixingAlg: public Algorithm {
public:
@@ -63,7 +64,7 @@ private:
private:
std::vector<std::string> m_event_types; // the event types of the background events
- std::vector<double> m_event_rates; // the rates of the background events
+ std::vector<double> m_event_timings; // the rates or durations of the background events
std::vector<IBackgroundLoader*> m_event_loaders; // the loaders of the background events
std::vector<std::vector<std::string>> m_input_lists; // input files for each backgroud
@@ -94,12 +95,29 @@ private:
// Following properties are used to configure different types of background events.
// * Key: label of one type
// * Value:
- // * rate:
+ // * timing:
// * FixedTimeWindow: if the rate is less than 0, then always mix the background events. fabs(rate) is the time window of the background events.
// * Sampled: if the rate is larger than 0, then the background events will be sampled according to the rate.
// * filelist: the input file list for this type of background events.
- Gaudi::Property<std::map<std::string, double>> m_background_rates{this, "BackgroundRates", {}, "The rates (positive, Hz) or time windows (negative, ns) of the background events"};
+ Gaudi::Property<std::map<std::string, double>> m_background_timings{this, "BackgroundTimings", {}, "The rates (positive, Hz) or time windows (negative, ns) of the background events"};
Gaudi::Property<std::map<std::string, std::vector<std::string>>> m_background_filelists{this, "BackgroundFileLists", {}, "The input file lists for the background events"};
+
+
+ // Bunch Crossing information
+ Gaudi::Property<double> m_bunch_crossing_spacing{this, "BunchCrossingSpacing", 277.0, "The bunch crossing spacing in ns"};
+ Gaudi::Property<int> m_nbunches_per_batch{this, "NbunchesPerBatch", 10, "The number of bunches per batch"};
+ Gaudi::Property<int> m_nbatches{this, "Nbatches", 13, "The number of batches to be mixed"}; // 34us/(277ns*10) = ~13
+
+private:
+ // Time window for VXD, ITK, TPC, OTK, ECAL, HCAL, MUON
+ // Only the hits between [-T, T] ns are loaded
+ Gaudi::Property<double> m_vxd_time_window{this, "VXDTimeWindow", 200.0, "The time window for VXD in ns"};
+ Gaudi::Property<double> m_itk_time_window{this, "ITKTimeWindow", 200.0, "The time window for ITK in ns"};
+ Gaudi::Property<double> m_tpc_time_window{this, "TPCTimeWindow", 34000.0, "The time window for TPC in ns"};
+ Gaudi::Property<double> m_otk_time_window{this, "OTKTimeWindow", 1000.0, "The time window for OTK in ns"};
+ Gaudi::Property<double> m_ecal_time_window{this, "EcalTimeWindow", 150.0, "The time window for ECAL in ns"};
+ Gaudi::Property<double> m_hcal_time_window{this, "HcalTimeWindow", 1000.0, "The time window for HCAL in ns"};
+ Gaudi::Property<double> m_muon_time_window{this, "MuonTimeWindow", 100.0, "The time window for MUON in ns"};
};
#endif
diff --git a/Simulation/DetSimMixing/src/IBackgroundLoader.hh b/Simulation/DetSimMixing/src/IBackgroundLoader.hh
old mode 100755
new mode 100644
index 273bb01a9264c1eebc78cf0b43a54c54f9d9da72..9142a9404ffe21f71937c67963cd375176014a2f
--- a/Simulation/DetSimMixing/src/IBackgroundLoader.hh
+++ b/Simulation/DetSimMixing/src/IBackgroundLoader.hh
@@ -1,56 +1,7 @@
#ifndef IBackgroundLoader_hh
#define IBackgroundLoader_hh
-#include "BackgroundBatch.hh"
-#include <map>
-
-#include "edm4hep/SimTrackerHitCollection.h"
-#include "edm4hep/SimCalorimeterHitCollection.h"
-#include "edm4hep/CaloHitContributionCollection.h"
-
-/*
- * Description:
- * As there are multiple collections for one event, this BackgrounEvent
- * is used to organize these collections.
- *
- * The key is the index of collection.
- *
- * BackgroundLoader is resposible to fill its hit collections into the
- * BackgroundEvent.
- */
-struct BackgroundEvent {
- std::map<size_t, edm4hep::SimTrackerHitCollection> tracker_hits;
- std::map<size_t, edm4hep::SimCalorimeterHitCollection> calorimeter_hits;
- std::map<size_t, edm4hep::CaloHitContributionCollection> calo_contribs;
-
- std::map<std::string, size_t> collection_index; // key is collection name, value is index.
- std::map<std::string, size_t> collection_subdet; // key is collection name, value is subdetector type.
-
- // in order to reduce the memory usage, need additional filter setup here.
- // for example, for TPC, we need to load all the hits.
- // however, for the tracker/calo, we only need to load the hits which are
- // in an interested event time window.
- enum SubDetType {
- kVXD = 0, // 200 ns
- kITK = 1, // 200 ns
- kTPC = 2, // 34 us
- kOTK = 3, // 1 us
- kECAL = 4, // 150 ns
- kHCAL = 5, // 1 us
- kMUON = 6, // 1 us // todo
- kNSubDetType
- };
- std::vector<double> subdet2twindow = {200, 200, 34000, 1000, 150, 1000, 1000}; // key is subdet, value is time window.
- std::vector<std::vector<std::string>> subdet2colnames = {
- {"VXD"},
- {"ITK"},
- {"TPC"},
- {"OTK"},
- {"Ecal"},
- {"Hcal"},
- {"Muon"}
- };
-};
+struct BackgroundEvent;
class IBackgroundLoader {
public: