ATLAS Offline Software
MM_StripsResponseSimulation.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
7 
8 #include <TGraph.h>
9 
10 #include <algorithm>
11 #include <mutex>
12 #include <thread>
13 #include <map>
14 
15 #include "CLHEP/Random/RandFlat.h"
16 #include "CLHEP/Random/RandGamma.h"
17 #include "CLHEP/Random/RandGaussZiggurat.h"
18 #include "CLHEP/Random/RandGeneral.h"
19 #include "CLHEP/Random/RandomEngine.h"
20 #include "GaudiKernel/SystemOfUnits.h"
24 
25 /*
26 
27 To Do List:
28 
29 Check Lorentz Angle is in correct direction...
30 
31 */
32 
33 namespace {
34  constexpr float electronsToFC = 1. / 6241.;
35  constexpr float polyaTheta = 1.765;
36  static std::mutex fillMutex{};
37 } // namespace
38 
39 /*******************************************************************************/
41  AthMessaging("MMStripResponseSimulation"),
42  m_cfg{std::move(mod)} {
43 
44  initHistos();
45  // initialization for the random number generator for the number of secondary electrons
46  // values are from G. Iakovidis
47  std::vector<double> NelectronProb{65.6, 15., 6.4, 3.5, 2.25, 1.55, 1.05, 0.81, 0.61, 0.49, 0.39, 0.3,
48  0.25, 0.2, 0.16, 0.12, 0.095, 0.075, 0.063, 0.054, 0.049, 0.045, 0.044};
49  NelectronProb.reserve(s_NelectronPropBins);
50  for (unsigned int Nelectron = NelectronProb.size(); Nelectron < s_NelectronPropBins; ++Nelectron)
51  NelectronProb.push_back(21.6 / ((Nelectron) * (Nelectron)));
52 
53  m_randNelectrons = std::make_unique<CLHEP::RandGeneral>(NelectronProb.data(), NelectronProb.size(), 1); // 1 means non-continious random numbers
54 
55  ATH_MSG_DEBUG("MM_StripsResponseSimulation::initializationFrom set values");
56  }
57 
58 /*******************************************************************************/
60  if (m_cfg.writeOutputFile) {
61  m_outputFile = std::make_unique<TFile>("MM_StripsResponse_Plots.root", "RECREATE");
62  if (m_outputFile) m_outputFile->cd();
63 
64  m_mapOfHistograms["nInteractions"] = std::make_unique<TH1F>("nInteractions", "nInteractions", 200, 0, 200);
65  m_mapOfHistograms["nElectrons"] = std::make_unique<TH1F>("nElectrons", "nElectrons", 200, 0, 200);
66  m_mapOfHistograms["lorentzAngle"] = std::make_unique<TH1F>("lorentzAngle", "lorentzAngle", 100, 0, 3);
67  m_mapOfHistograms["effectiveCharge"] = std::make_unique<TH1F>("effectiveCharge", "effectiveCharge", 100, 0, 1e5);
68  m_mapOfHistograms["effectiveNElectrons"] = std::make_unique<TH1F>("effectiveNElectrons", "effectiveNElectrons", 200, 0, 200);
69  m_mapOfHistograms["totalEffectiveCharge"] = std::make_unique<TH1F>("totalEffectiveCharge", "totalEffectiveCharge", 400, 0, 200);
70  m_mapOf2DHistograms["totalEffectiveChargeVsTheta"] = std::make_unique<TH2F>("totalEffectiveChargeVsTheta", "totalEffectiveChargeVsTheta", 17, 0, 35, 300, 0, 300);
71 
72  m_mapOf2DHistograms["pathLengthVsTheta"] = std::make_unique<TH2F>("pathLengthVsTheta", "pathLengthVsTheta", 100, 0, 10, 100, -3, 3);
73  m_mapOf2DHistograms["pathLengthVsAlpha"] = std::make_unique<TH2F>("pathLengthVsAlpha", "pathLengthVsAlpha", 100, 0, 10, 100, -3, 3);
74 
75  m_mapOf2DHistograms["lorentzAngleVsTheta"] = std::make_unique<TH2F>("lorentzAngleVsTheta", "lorentzAngleVsTheta", 100, -3, 3, 100, -3, 3);
76  m_mapOf2DHistograms["lorentzAngleVsBy"] = std::make_unique<TH2F>("lorentzAngleVsBy", "lorentzAngleVsBy", 100, -3, 3, 100, -2., 2.);
77 
78  m_mapOf2DHistograms["deltaLorentzAngleVsByForPosTheta"] =
79  std::make_unique<TH2F>("deltaLorentzAngleVsByForPosTheta", "deltaLorentzAngleVsByForPosTheta", 100, -3, 3, 100, -2., 2.);
80  m_mapOf2DHistograms["deltaLorentzAngleVsByForNegTheta"] =
81  std::make_unique<TH2F>("deltaLorentzAngleVsByForNegTheta", "deltaLorentzAngleVsByForNegTheta", 100, -3, 3, 100, -2., 2.);
82 
83  m_mapOf2DHistograms["driftDistanceVsDriftTime"] =
84  std::make_unique<TH2F>("driftDistanceVsDriftTime", "driftDistanceVsDriftTime", 100, 0, 10, 100, 0, 200);
85  }
86 }
87 /*******************************************************************************/
89  if (!m_outputFile) {
90  return;
91  }
92  for (auto& [histo_name, histo] : m_mapOfHistograms) {
93  m_outputFile->WriteObject(histo.get(), histo_name.c_str());
94  }
95  for (auto& [histo_name, histo] : m_mapOf2DHistograms) {
96  m_outputFile->WriteObject(histo.get(), histo_name.c_str());
97  }
98  m_mapOf2DHistograms.clear();
99  m_mapOfHistograms.clear();
100 }
101 /*******************************************************************************/
103  double gainFraction, double stripPitch,
104  CLHEP::HepRandomEngine* rndmEngine) const {
105  ATH_MSG_DEBUG("Starting to get response from strips");
106  DataCache cache{};
107  whichStrips(cache, digiInput, gainFraction, stripPitch, rndmEngine);
108 
109  ATH_MSG_DEBUG("Creating MmDigitToolOutput object");
110 
111  MM_StripToolOutput tmpStripToolOutput(std::move(cache.finalNumberofStrip),
112  std::move(cache.finalqStrip),
113  std::move(cache.finaltStrip));
114 
115  return tmpStripToolOutput;
116 }
117 
118 //__________________________________________________________________________________________________
119 //==================================================================================================
120 // calculate the strips that got fired, charge and time. Assume any angle thetaDegrees....
121 //==================================================================================================
123  const MM_DigitToolInput& digiInput,
124  double gainFraction, double stripPitch,
125  CLHEP::HepRandomEngine* rndmEngine) const {
126  ATH_MSG_DEBUG("Starting to calculate strips that got fired");
127  const float hitx = digiInput.positionWithinStrip();
128  const int stripID = digiInput.stripIDLocal();
129  const float incidentAngleXZ = digiInput.incomingAngleXZ(); // degrees
130  const float incidentAngleYZ = digiInput.incomingAngleYZ(); // degrees
131  const int stripMinID = digiInput.stripMinID();
132  const int stripMaxID = digiInput.stripMaxID();
133 
134  CLHEP::RandGeneral* randDist ATLAS_THREAD_SAFE = m_randNelectrons.get();
135  const float eventTime = digiInput.eventTime();
136  const float theta = incidentAngleXZ * Gaudi::Units::degree; // Important for path length and strip distribution
137  const float alpha = incidentAngleYZ * Gaudi::Units::degree; // Important for path length
138 
139  int nPrimaryIons = 0;
140 
141  Amg::Vector3D b = digiInput.magneticField() * 1000.;
142 
143  // Still need to understand which sign is which... But I think this is correct...
144 
145  float lorentzAngle = (b.y() > 0. ? 1. : -1.) * m_cfg.lorentzAngleFunction(std::abs(b.y())) * Gaudi::Units::deg; // in radians
146  if (m_cfg.writeOutputFile) {
147  std::lock_guard guard{fillMutex};
148  m_mapOf2DHistograms.at("lorentzAngleVsTheta")->Fill(lorentzAngle, theta);
149  m_mapOf2DHistograms.at("lorentzAngleVsBy")->Fill(lorentzAngle, b.y());
150  }
151 
152  ATH_MSG_DEBUG("LorentzAngle vs theta: " << lorentzAngle << " " << theta);
153 
154  float pathLengthTraveled = getPathLengthTraveled(rndmEngine);
155 
156  float pathLength = m_cfg.driftGapWidth / std::cos(theta); // Increasing path length based on XZ angle
157  pathLength /= std::cos(alpha); // Further increasing path length for YZ angle
158 
159  if (m_cfg.writeOutputFile) {
160  std::lock_guard guard{fillMutex};
161  m_mapOf2DHistograms.at("pathLengthVsTheta")->Fill(pathLength, theta);
162  m_mapOf2DHistograms.at("pathLengthVsAlpha")->Fill(pathLength, alpha);
163 
164  if (theta > 0)
165  m_mapOf2DHistograms.at("deltaLorentzAngleVsByForPosTheta")->Fill(lorentzAngle - theta, b.y());
166  else
167  m_mapOf2DHistograms.at("deltaLorentzAngleVsByForNegTheta")->Fill(lorentzAngle - theta, b.y());
168  }
169  while (pathLengthTraveled < pathLength) {
170  // N.B. Needs correction from alpha angle still...
171  std::unique_ptr<MM_IonizationCluster> IonizationCluster =
172  std::make_unique<MM_IonizationCluster>(hitx, pathLengthTraveled * std::sin(theta), pathLengthTraveled * std::cos(theta));
173 
174  // +1 since first entry in electron probability vector corresponds to 1 electron and not to 0 electrons
175  int nElectrons = s_NelectronPropBins * randDist->shoot(rndmEngine) + 1;
176  IonizationCluster->createElectrons(nElectrons);
177 
178  const Amg::Vector2D& initialPosition = IonizationCluster->getIonizationStart();
179 
180  ATH_MSG_DEBUG("New interaction starting at x,y, pathLengthTraveled: " << initialPosition.x() << " " << initialPosition.y() << " "
181  << pathLengthTraveled);
182 
183  for (auto& Electron : IonizationCluster->getElectrons()) {
184  Electron->setOffsetPosition(getTransverseDiffusion(initialPosition.y(), rndmEngine),
185  getLongitudinalDiffusion(initialPosition.y(), rndmEngine));
186  }
187 
188  IonizationCluster->propagateElectrons(lorentzAngle, m_cfg.driftVelocity);
189 
190  int tmpEffectiveNElectrons = 0;
191 
192  for (auto& Electron : IonizationCluster->getElectrons()) {
193  float effectiveCharge = getEffectiveCharge(rndmEngine) * gainFraction;
194 
195  Electron->setCharge(effectiveCharge);
196 
197  ATH_MSG_DEBUG("Electron's effective charge is " << effectiveCharge);
198 
199  if (m_cfg.writeOutputFile) {
200  std::lock_guard guard{fillMutex};
201  m_mapOfHistograms.at("effectiveCharge")->Fill(effectiveCharge);
202  m_mapOf2DHistograms.at("driftDistanceVsDriftTime")->Fill(Electron->getOffsetPosition().mag(), Electron->getTime());
203  }
204  // Add eventTime in Electron time
205  Electron->setTime(Electron->getTime() + eventTime);
206 
207  tmpEffectiveNElectrons += effectiveCharge;
208  }
209 
210  if (m_cfg.writeOutputFile) {
211  std::lock_guard guard{fillMutex};
212  m_mapOfHistograms.at("effectiveNElectrons")->Fill(tmpEffectiveNElectrons / m_cfg.avalancheGain);
213  }
214  //---
215  cache.IonizationClusters.push_back(std::move(IonizationCluster));
216 
217  pathLengthTraveled += getPathLengthTraveled(rndmEngine);
218 
219  ATH_MSG_DEBUG("Path length traveled: " << pathLengthTraveled);
220 
221  ++nPrimaryIons;
222  if (nPrimaryIons >= m_cfg.maxPrimaryIons) break; // don't create more than "MaxPrimaryIons" along a track....
223 
224  } // end of clusters loop
225 
226  float timeresolution = 0.01; // ns
227 
228  MM_StripResponse stripResponseObject(cache.IonizationClusters, timeresolution, stripPitch, stripID, stripMinID, stripMaxID);
229  stripResponseObject.timeOrderElectrons();
230  stripResponseObject.calculateTimeSeries(incidentAngleXZ, digiInput.gasgap());
231  stripResponseObject.simulateCrossTalk(m_cfg.crossTalk1, m_cfg.crossTalk2);
232  stripResponseObject.calculateSummaries(m_cfg.qThreshold);
233 
234  // Connect the output with the rest of the existing code
235  //
236  cache.finalNumberofStrip = stripResponseObject.getStripVec();
237  cache.finalqStrip = stripResponseObject.getTotalChargeVec();
238  cache.finaltStrip = stripResponseObject.getTimeThresholdVec();
239  cache.tStripElectronicsAbThr = stripResponseObject.getTimeMaxChargeVec();
240  cache.qStripElectronics = stripResponseObject.getMaxChargeVec();
241 
242  // Output diagnostic hists and graphs
243  //
244  if (m_cfg.writeOutputFile) {
245  std::lock_guard guard{fillMutex};
246  m_mapOfHistograms.at("nInteractions")->Fill(nPrimaryIons);
247  m_mapOfHistograms.at("nElectrons")->Fill(stripResponseObject.getNElectrons());
248  m_mapOfHistograms.at("totalEffectiveCharge")->Fill(stripResponseObject.totalCharge() * electronsToFC);
249  m_mapOf2DHistograms.at("totalEffectiveChargeVsTheta")->Fill(std::abs(incidentAngleXZ),
250  stripResponseObject.totalCharge() * electronsToFC);
251  ATH_MSG_DEBUG("incidentAngleXZ" << incidentAngleXZ << "charge [fC]" << stripResponseObject.totalCharge() / 6241.);
252  m_mapOfHistograms.at("lorentzAngle")->Fill(lorentzAngle);
253  }
254 
256  std::lock_guard guard{fillMutex};
257  static std::atomic<unsigned> written{0};
258  TGraph grIonizationXZ(cache.IonizationClusters.size());
259  for (size_t iIonization = 0; iIonization < cache.IonizationClusters.size(); ++iIonization) {
260  Amg::Vector2D ionizationPosition(cache.IonizationClusters.at(iIonization)->getIonizationStart());
261  grIonizationXZ.SetPoint(iIonization, ionizationPosition.x(), ionizationPosition.y());
262  }
263  m_outputFile->WriteObject(&grIonizationXZ, Form("ionizationXZ_%u", ++written));
264 
265  TGraph grElectronsXZ(stripResponseObject.getNElectrons());
266  int iElectron = 0;
267  for (const auto& electron : stripResponseObject.getElectrons()) {
268  grElectronsXZ.SetPoint(iElectron, electron->getX(), electron->getY());
269  iElectron++;
270  }
271  m_outputFile->WriteObject(&grElectronsXZ, Form("electronsXZ_%u", ++written));
272  }
273 
274 } // end of whichStrips()
275 
276 float MM_StripsResponseSimulation::generateTransverseDiffusion(float posY, CLHEP::HepRandomEngine* rndmEngine) const {
277  // this is a helper function used in getTransverseDiffusion, generating double gaussian distributions
278 
279  // avoid division by zero in calculation of scale if ypos is 0
280  // also protect against negative values of ypos which should never happen
281  if (posY <= 0.) posY = 0.001;
282 
283  // need to scale weigths since initial distributions were not normalized
284  const double scale = 0.001 / (posY * m_cfg.transverseDiffusionSigma);
285 
286  const double uni = CLHEP::RandFlat::shoot(rndmEngine, 0, 1.0 + scale);
287  if (uni < scale) return CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0, 1.0);
288  return CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0., m_cfg.transverseDiffusionSigma * posY);
289 }
290 
291 float MM_StripsResponseSimulation::getTransverseDiffusion(float posY, CLHEP::HepRandomEngine* rndmEngine) const {
292  // the random numbers are generate from the following function:
293  // "1.*TMath::Exp(-TMath::Power(x,2.)/(2.*[0]*[0])) + 0.001*TMath::Exp(-TMath::Power(x,2)/(2.*[1]*[1]))"
294  // in the range from -1 to 1
295  // Since sampling from a TF1 where its parameters are changed for every random number is slow,
296  // the following approach is used to generate random numbers from the mixture of two Gaussian:
297  // https://stats.stackexchange.com/questions/226834/sampling-from-a-mixture-of-two-gamma-distributions/226837#226837
298  // this approach seems to be around 20000 times faster
299 
300  // if one of the diffusions is off, the tail is not present
301  float diffusion{0.};
303  // limit random number to be -1 < x < 1
304  do {
305  diffusion = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0, posY * m_cfg.transverseDiffusionSigma);
306  ATH_MSG_VERBOSE("getTransverseDiffusion() -- posY x transverseSigma: "<<(posY* m_cfg.transverseDiffusionSigma)<<" engine seed: "<<rndmEngine->getSeed()<<" "<<rndmEngine->flat()<<" diffusion "<<diffusion);
307  } while (std::abs(diffusion) > 1.);
308  return diffusion;
309  }
310  do {
311  diffusion = generateTransverseDiffusion(posY, rndmEngine);
312  ATH_MSG_VERBOSE("getTransverseDiffusion() -- posY: "<<posY<<" engine seed: "<<rndmEngine->getSeed()<<" "<<rndmEngine->flat()<<" diffusion "<<diffusion);
313  } while (std::abs(diffusion)> 1.);
314  return diffusion;
315 }
316 
317 float MM_StripsResponseSimulation::getLongitudinalDiffusion(float posY, CLHEP::HepRandomEngine* rndmEngine) const {
318  float diffusion{0.};
319  // We only want random numbers between -5 and 5
320  do {
321  diffusion= CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0, posY * m_cfg.longitudinalDiffusionSigma);
322  ATH_MSG_VERBOSE("getLongitudinalDiffusion() -- posY: "<<posY<<" engine seed: "<<rndmEngine->getSeed()<<" "<<rndmEngine->flat()<<" diffusion "<<diffusion);
323  } while (std::abs(diffusion) > 5);
324  return diffusion;
325 }
326 
327 float MM_StripsResponseSimulation::getEffectiveCharge(CLHEP::HepRandomEngine* rndmEngine) const {
328  // charge fluctuatation is described by Polya function
329  // To calculate the gain from polya distibution we replace "alpha = 1+theta and beta = 1+theta/mean" in gamma PDF. With this gamma PDF
330  // gives us same sampling values as we get from polya PDF. Idea taken from MR 40547
331  return CLHEP::RandGamma::shoot(rndmEngine, 1. + polyaTheta, (1. + polyaTheta) / m_cfg.avalancheGain);
332 }
333 
334 float MM_StripsResponseSimulation::getPathLengthTraveled(CLHEP::HepRandomEngine* rndmEngine) const {
335  // Probability of having an interaction (per unit length traversed) is sampled from a gaussian provided by G. Iakovidis
336  float rndGaus{0.};
337 
338  // gaussian random number should be in the range from 0 to 10
339  do {
340  rndGaus = CLHEP::RandGaussZiggurat::shoot(rndmEngine, m_cfg.interactionDensityMean, m_cfg.interactionDensitySigma);
341  ATH_MSG_VERBOSE("getPathLengthTraveled() -- engine seed: "<<rndmEngine->getSeed()<<" "<<rndmEngine->flat()<<" rndGaus: "<<rndGaus);
342  } while (rndGaus < 0. || rndGaus > 10.) ;
343 
344  return (1. / rndGaus) * -1. * std::log(CLHEP::RandFlat::shoot(rndmEngine));
345 }
346 
347 /*******************************************************************************/
349  if (m_outputFile) { writeHistos(); }
350 }
351 /*******************************************************************************/
MM_IonizationCluster::createElectrons
void createElectrons(int nElectrons)
Definition: MM_IonizationCluster.cxx:10
NSWCalib::MicroMegaGas::lorentzAngleFunction
angleFunction lorentzAngleFunction
Definition: INSWCalibTool.h:48
MM_StripResponse::getTimeThresholdVec
const std::vector< std::vector< float > > & getTimeThresholdVec() const
Definition: MM_StripResponse.cxx:137
NSWCalib::MicroMegaGas::longitudinalDiffusionSigma
float longitudinalDiffusionSigma
// 0.350/10 diffusSigma=transverse diffusion (350 microm per 1cm ) for 93:7 @ 600 V/cm,...
Definition: INSWCalibTool.h:36
MM_StripsResponseSimulation::ConfigModule::writeEventDisplays
bool writeEventDisplays
Definition: MM_StripsResponseSimulation.h:81
MM_DigitToolInput::stripMaxID
int stripMaxID() const
Definition: MM_DigitToolInput.h:48
MM_StripResponse::getMaxChargeVec
const std::vector< float > & getMaxChargeVec() const
Definition: MM_StripResponse.cxx:139
MM_IonizationCluster::getIonizationStart
const Amg::Vector2D & getIonizationStart() const
Definition: MM_IonizationCluster.h:25
MM_StripResponse::calculateSummaries
void calculateSummaries(float chargeThreshold)
Definition: MM_StripResponse.cxx:91
NSWCalib::MicroMegaGas::interactionDensityMean
float interactionDensityMean
Definition: INSWCalibTool.h:38
MM_StripsResponseSimulation::writeHistos
void writeHistos()
Definition: MM_StripsResponseSimulation.cxx:88
MM_StripsResponseSimulation::DataCache::finalqStrip
std::vector< std::vector< float > > finalqStrip
Definition: MM_StripsResponseSimulation.h:107
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
BeamSpot::mutex
std::mutex mutex
Definition: InDetBeamSpotVertex.cxx:18
theta
Scalar theta() const
theta method
Definition: AmgMatrixBasePlugin.h:71
MM_StripsResponseSimulation::m_cfg
const ConfigModule m_cfg
Definition: MM_StripsResponseSimulation.h:102
MM_StripsResponseSimulation::ConfigModule::crossTalk1
float crossTalk1
crosstalk of neighbor strips, it's 15%
Definition: MM_StripsResponseSimulation.h:70
MM_IonizationCluster.h
MM_StripsResponseSimulation::whichStrips
void whichStrips(DataCache &cache, const MM_DigitToolInput &digiInput, double gainFraction, double stripPitch, CLHEP::HepRandomEngine *rndmEngine) const
Definition: MM_StripsResponseSimulation.cxx:122
deg
#define deg
Definition: SbPolyhedron.cxx:17
MM_StripsResponseSimulation::~MM_StripsResponseSimulation
virtual ~MM_StripsResponseSimulation()
Definition: MM_StripsResponseSimulation.cxx:348
MM_StripResponse::calculateTimeSeries
void calculateTimeSeries(float thetaD, int gasgap)
Definition: MM_StripResponse.cxx:30
MM_StripsResponseSimulation::ConfigModule
Definition: MM_StripsResponseSimulation.h:64
MM_StripsResponseSimulation::DataCache::tStripElectronicsAbThr
std::vector< float > tStripElectronicsAbThr
Definition: MM_StripsResponseSimulation.h:109
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
NSWCalib::MicroMegaGas::driftVelocity
float driftVelocity
//0.050 drift velocity in [mm/ns], driftGap=5 mm +0.128 mm (the amplification gap)
Definition: INSWCalibTool.h:34
MM_DigitToolInput::stripMinID
int stripMinID() const
Definition: MM_DigitToolInput.h:47
MM_DigitToolInput
Definition: MM_DigitToolInput.h:25
yodamerge_tmp.scale
scale
Definition: yodamerge_tmp.py:138
MM_StripsResponseSimulation::m_outputFile
std::unique_ptr< TFile > m_outputFile
Definition: MM_StripsResponseSimulation.h:127
AthMessaging::ATLAS_THREAD_SAFE
std::atomic_flag m_initialized ATLAS_THREAD_SAFE
Messaging initialized (initMessaging)
Definition: AthMessaging.h:141
MM_StripsResponseSimulation::ConfigModule::maxPrimaryIons
int maxPrimaryIons
Definition: MM_StripsResponseSimulation.h:78
MM_DigitToolInput::eventTime
float eventTime() const
Definition: MM_DigitToolInput.h:51
MM_StripsResponseSimulation::ConfigModule::driftGapWidth
float driftGapWidth
Definition: MM_StripsResponseSimulation.h:74
MM_DigitToolInput::magneticField
const Amg::Vector3D & magneticField() const
Definition: MM_DigitToolInput.h:46
MM_DigitToolInput::gasgap
int gasgap() const
Definition: MM_DigitToolInput.h:49
NSWCalib::MicroMegaGas::interactionDensitySigma
float interactionDensitySigma
Definition: INSWCalibTool.h:39
maskDeadModules.mod
mod
Definition: maskDeadModules.py:36
MM_DigitToolInput::incomingAngleYZ
double incomingAngleYZ() const
Definition: MM_DigitToolInput.h:45
MM_StripsResponseSimulation::m_randNelectrons
std::unique_ptr< CLHEP::RandGeneral > m_randNelectrons
Definition: MM_StripsResponseSimulation.h:122
MM_DigitToolInput::incomingAngleXZ
double incomingAngleXZ() const
Definition: MM_DigitToolInput.h:44
MM_StripResponse::getTotalChargeVec
const std::vector< std::vector< float > > & getTotalChargeVec() const
Definition: MM_StripResponse.cxx:138
MM_StripsResponseSimulation::GetResponseFrom
MM_StripToolOutput GetResponseFrom(const MM_DigitToolInput &digiInput, double gainFraction, double stripPitch, CLHEP::HepRandomEngine *rndmEngine) const
Definition: MM_StripsResponseSimulation.cxx:102
MM_StripsResponseSimulation::s_NelectronPropBins
static constexpr unsigned int s_NelectronPropBins
Definition: MM_StripsResponseSimulation.h:124
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
MM_StripResponse::getStripVec
const std::vector< int > & getStripVec() const
Definition: MM_StripResponse.cxx:136
MM_IonizationCluster::getElectrons
std::vector< std::unique_ptr< MM_Electron > > & getElectrons()
Definition: MM_IonizationCluster.cxx:21
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
MM_StripResponse::totalCharge
float totalCharge() const
Definition: MM_StripResponse.cxx:16
MM_StripsResponseSimulation::getLongitudinalDiffusion
float getLongitudinalDiffusion(float posY, CLHEP::HepRandomEngine *rndmEngine) const
Definition: MM_StripsResponseSimulation.cxx:317
MM_StripResponse::timeOrderElectrons
void timeOrderElectrons()
Definition: MM_StripResponse.cxx:24
MM_StripsResponseSimulation::ConfigModule::qThreshold
float qThreshold
qThreshold=2e, we accept a good strip if the charge is >=2e
Definition: MM_StripsResponseSimulation.h:67
MM_StripsResponseSimulation::DataCache::finalNumberofStrip
std::vector< int > finalNumberofStrip
Definition: MM_StripsResponseSimulation.h:106
MM_StripsResponseSimulation::getEffectiveCharge
float getEffectiveCharge(CLHEP::HepRandomEngine *rndmEngine) const
Definition: MM_StripsResponseSimulation.cxx:327
MM_IonizationCluster::propagateElectrons
void propagateElectrons(float lorentzAngle, float driftVel)
Definition: MM_IonizationCluster.cxx:16
PathResolver.h
MM_StripResponse::simulateCrossTalk
void simulateCrossTalk(float crossTalk1, float crossTalk2)
Definition: MM_StripResponse.cxx:50
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
MM_StripsResponseSimulation::getTransverseDiffusion
float getTransverseDiffusion(float posY, CLHEP::HepRandomEngine *rndmEngine) const
Definition: MM_StripsResponseSimulation.cxx:291
MM_StripsResponseSimulation::MM_StripsResponseSimulation
MM_StripsResponseSimulation(ConfigModule &&cfg)
Definition: MM_StripsResponseSimulation.cxx:40
MM_StripResponse::getElectrons
std::vector< std::unique_ptr< MM_Electron > > & getElectrons()
Definition: MM_StripResponse.cxx:22
MM_StripsResponseSimulation.h
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
MM_StripToolOutput
Definition: MM_StripToolOutput.h:9
beamspotman.posY
posY
Definition: beamspotman.py:1624
MM_StripsResponseSimulation::ConfigModule::writeOutputFile
bool writeOutputFile
Definition: MM_StripsResponseSimulation.h:80
NSWCalib::MicroMegaGas::transverseDiffusionSigma
float transverseDiffusionSigma
Definition: INSWCalibTool.h:37
MM_StripsResponseSimulation::ConfigModule::avalancheGain
float avalancheGain
Definition: MM_StripsResponseSimulation.h:77
MM_DigitToolInput::stripIDLocal
int stripIDLocal() const
Definition: MM_DigitToolInput.h:42
MM_StripResponse.h
MM_StripsResponseSimulation::ConfigModule::crossTalk2
float crossTalk2
// crosstalk of second neighbor strips, it's 6%
Definition: MM_StripsResponseSimulation.h:72
MM_StripResponse::getTimeMaxChargeVec
const std::vector< float > & getTimeMaxChargeVec() const
Definition: MM_StripResponse.cxx:140
MM_DigitToolInput::positionWithinStrip
double positionWithinStrip() const
Definition: MM_DigitToolInput.h:43
Electron
Class describing an electron.
MM_StripsResponseSimulation::DataCache::qStripElectronics
std::vector< float > qStripElectronics
Definition: MM_StripsResponseSimulation.h:110
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
xAOD::EgammaParameters::electron
@ electron
Definition: EgammaEnums.h:18
MM_StripsResponseSimulation::initHistos
void initHistos()
Definition: MM_StripsResponseSimulation.cxx:59
MM_StripResponse::getNElectrons
int getNElectrons() const
Definition: MM_StripResponse.cxx:14
MM_StripResponse
Definition: MM_StripResponse.h:20
MM_StripsResponseSimulation::m_mapOfHistograms
std::map< std::string, std::unique_ptr< TH1F > > m_mapOfHistograms
Definition: MM_StripsResponseSimulation.h:119
MM_StripsResponseSimulation::m_mapOf2DHistograms
std::map< std::string, std::unique_ptr< TH2F > > m_mapOf2DHistograms
Definition: MM_StripsResponseSimulation.h:120
MM_StripsResponseSimulation::getPathLengthTraveled
float getPathLengthTraveled(CLHEP::HepRandomEngine *rndmEngine) const
Definition: MM_StripsResponseSimulation.cxx:334
MM_StripsResponseSimulation::DataCache::finaltStrip
std::vector< std::vector< float > > finaltStrip
Definition: MM_StripsResponseSimulation.h:108
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
MM_StripsResponseSimulation::DataCache::IonizationClusters
std::vector< std::unique_ptr< MM_IonizationCluster > > IonizationClusters
Definition: MM_StripsResponseSimulation.h:105
plotBeamSpotCompare.histo
histo
Definition: plotBeamSpotCompare.py:415
MM_StripsResponseSimulation::DataCache
Definition: MM_StripsResponseSimulation.h:104
python.SystemOfUnits.degree
tuple degree
Definition: SystemOfUnits.py:106
MM_StripsResponseSimulation::generateTransverseDiffusion
float generateTransverseDiffusion(float posY, CLHEP::HepRandomEngine *rndmEngine) const
Definition: MM_StripsResponseSimulation.cxx:276