ATLAS Offline Software
Loading...
Searching...
No Matches
MM_StripResponse.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
7
8#include <algorithm>
9#include <cmath>
10
11MM_StripResponse::MM_StripResponse(std::vector<std::unique_ptr<MM_IonizationCluster>>& IonizationClusters, float timeResolution,
12 float stripPitch, int stripID, int minstripID, int maxstripID) :
13 m_timeResolution(timeResolution), m_stripPitch(stripPitch), m_stripID(stripID), m_minstripID(minstripID), m_maxstripID(maxstripID) {
14 for (auto& IonizationCluster : IonizationClusters)
15 for (auto& Electron : IonizationCluster->getElectrons()) m_Electrons.push_back(std::move(Electron));
16}
17
18int MM_StripResponse::getNElectrons() const { return m_Electrons.size(); }
19
21 float qtot = 0;
22 for (const std::unique_ptr<MM_Electron>& electron : m_Electrons) { qtot += electron->getCharge(); }
23 return qtot;
24}
25
26std::vector<std::unique_ptr<MM_Electron>>& MM_StripResponse::getElectrons() { return m_Electrons; }
27
30 m_Electrons.begin(), m_Electrons.end(),
31 [](const std::unique_ptr<MM_Electron>& a, const std::unique_ptr<MM_Electron>& b) -> bool { return a->getTime() < b->getTime(); });
32}
33
34void MM_StripResponse::calculateTimeSeries(float /*thetaD*/, int /*gasgap*/) {
35 for (auto& Electron : m_Electrons) {
36 int timeBin = (int)(Electron->getTime() / m_timeResolution);
37 // m_stripID defines the initial strip where the muon entered the gas gap
38
39 int stripVal = 0;
40 if (std::abs(Electron->getX()) > m_stripPitch / 2) {
41 if (Electron->getX() > 0.0)
42 stripVal = m_stripID + int((Electron->getX() - m_stripPitch / 2) / m_stripPitch) + 1;
43 else
44 stripVal = m_stripID + int((Electron->getX() + m_stripPitch / 2) / m_stripPitch) - 1;
45 } else
46 stripVal = m_stripID;
47
48 // Only add the strips that are either read out, or can cross talk to the read out strips
49 if (stripVal < m_minstripID - 2 || stripVal > m_maxstripID + 1) stripVal = -1;
50 if (stripVal > 0) m_stripCharges[timeBin][stripVal] += Electron->getCharge();
51 }
52}
53
54void MM_StripResponse::simulateCrossTalk(float crossTalk1, float crossTalk2) {
55 // if no cross talk is simulate just skip everything and keep m_stripCharges as it was
56 if (crossTalk1 > 0.) {
57 // Unfortunately get stuck in the loop if you edit the map in the loop
58 // So make a copy!
59
60 std::map<int, std::map<int, float>> stripChargesCopy1;
61 stripChargesCopy1.insert(m_stripCharges.begin(), m_stripCharges.end());
62
63 // clear strip charge map since charge on the main strip needs to be scaled
64 m_stripCharges.clear();
65
66 for (auto& stripTimeSeries : stripChargesCopy1) {
67 int timeBin = stripTimeSeries.first;
68 for (auto& stripCharge : stripTimeSeries.second) {
69 int stripVal = stripCharge.first;
70 float stripChargeVal = stripCharge.second;
71
72 if (stripChargeVal == 0.) continue;
73
74 // scale factcor for the charge on the main strip to account for the cross talk charge
75 float chargeScaleFactor = 1.0 / (1. + ((stripVal - 1 > 0) + (stripVal + 1 < m_maxstripID)) * crossTalk1 +
76 ((stripVal - 2 > 0) + (stripVal + 2 < m_maxstripID)) * crossTalk2);
77 stripChargeVal *= chargeScaleFactor;
78
79 m_stripCharges[timeBin][stripVal] += stripChargeVal;
80
81 // Allow crosstalk between strips that exist.
82 // Will check for read out strips in calculateSummaries function
83 if (stripVal - 1 > 0) m_stripCharges[timeBin][stripVal - 1] += stripChargeVal * crossTalk1;
84 if (stripVal + 1 < m_maxstripID) m_stripCharges[timeBin][stripVal + 1] += stripChargeVal * crossTalk1;
85
86 if (crossTalk2 > 0.) {
87 if (stripVal - 2 > 0) m_stripCharges[timeBin][stripVal - 2] += stripChargeVal * crossTalk2;
88 if (stripVal + 2 < m_maxstripID) m_stripCharges[timeBin][stripVal + 2] += stripChargeVal * crossTalk2;
89 }
90 }
91 }
92 }
93}
94
95void MM_StripResponse::calculateSummaries(float chargeThreshold) {
96 std::map<int, std::map<int, float>> stripChargesCopy2;
97 stripChargesCopy2.insert(m_stripCharges.begin(), m_stripCharges.end());
98 for (auto& stripTimeSeries : stripChargesCopy2) {
99 int timeBin = stripTimeSeries.first;
100 for (auto& stripCharge : stripTimeSeries.second) {
101 int stripVal = stripCharge.first;
102 // remove dead (missing) strips
103 // First active strip starts at m_minstripID
104 // Last active strip numbrer is maxStripID-1
105 if (stripVal < m_minstripID || stripVal > m_maxstripID - 1) continue;
106 // remove PCB gap strips
107 if (stripVal == 1024 || stripVal == 1025 || stripVal == 2048 || stripVal == 2049 || stripVal == 3072 || stripVal == 3073 ||
108 stripVal == 4096 || stripVal == 4097)
109 continue;
110 float stripChargeVal = stripCharge.second;
111 if (stripChargeVal < chargeThreshold) continue;
112
113 bool found = false;
114 for (size_t ii = 0; ii < m_v_strip.size(); ii++) {
115 if (m_v_strip.at(ii) == stripVal) {
116 m_v_stripTimeThreshold.at(ii).push_back(timeBin * m_timeResolution);
117 m_v_stripTotalCharge.at(ii).push_back(stripChargeVal);
118 found = true;
119 break;
120 }
121 }
122 if (!found) { // // strip not in vector, add new entry
123 m_v_strip.push_back(stripVal);
124 //construct vector of 1 value of stripChargeVal in-place
125 m_v_stripTotalCharge.emplace_back(1,stripChargeVal);
126 //construct vector of 1 value of timeBin * m_timeResolution in-place
127 m_v_stripTimeThreshold.emplace_back(1, timeBin * m_timeResolution);
128 }
129 }
130 }
131}
132
133// accessors
134const std::map<int, int>& MM_StripResponse::getTimeThreshold() const { return m_stripTimeThreshold; }
135const std::map<int, float>& MM_StripResponse::getTotalCharge() const { return m_stripTotalCharge; }
136const std::map<int, float>& MM_StripResponse::getMaxCharge() const { return m_stripMaxCharge; }
137const std::map<int, int>& MM_StripResponse::getTimeMaxCharge() const { return m_stripTimeMaxCharge; }
138const std::vector<int>& MM_StripResponse::getStripVec() const { return m_v_strip; }
139const std::vector<std::vector<float>>& MM_StripResponse::getTimeThresholdVec() const { return m_v_stripTimeThreshold; }
140const std::vector<std::vector<float>>& MM_StripResponse::getTotalChargeVec() const { return m_v_stripTotalCharge; }
141const std::vector<float>& MM_StripResponse::getMaxChargeVec() const { return m_v_stripMaxCharge; }
142const std::vector<float>& MM_StripResponse::getTimeMaxChargeVec() const { return m_v_stripTimeMaxCharge; }
static Double_t a
std::map< int, float > m_stripMaxCharge
std::vector< std::unique_ptr< MM_Electron > > & getElectrons()
std::vector< int > m_v_strip
const std::map< int, float > & getTotalCharge() const
const std::vector< std::vector< float > > & getTimeThresholdVec() const
std::map< int, int > m_stripTimeMaxCharge
std::vector< std::vector< float > > m_v_stripTimeThreshold
void calculateSummaries(float chargeThreshold)
const std::map< int, int > & getTimeThreshold() const
const std::vector< float > & getMaxChargeVec() const
std::vector< float > m_v_stripTimeMaxCharge
int getNElectrons() const
std::map< int, std::map< int, float > > m_stripCharges
const std::vector< float > & getTimeMaxChargeVec() const
const std::map< int, int > & getTimeMaxCharge() const
void calculateTimeSeries(float thetaD, int gasgap)
std::vector< float > m_v_stripMaxCharge
void simulateCrossTalk(float crossTalk1, float crossTalk2)
const std::vector< std::vector< float > > & getTotalChargeVec() const
std::map< int, int > m_stripTimeThreshold
float totalCharge() const
const std::map< int, float > & getMaxCharge() const
MM_StripResponse()=default
std::vector< std::vector< float > > m_v_stripTotalCharge
std::vector< std::unique_ptr< MM_Electron > > m_Electrons
std::map< int, float > m_stripTotalCharge
const std::vector< int > & getStripVec() const
Class describing an electron.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.