ATLAS Offline Software
SensitiveDetectorBase.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // STL includes
6 #include <sstream>
7 
8 // Base class
10 
11 // Geant4 includes used in functions
12 //#include "G4RunManager.hh"
13 //#include "G4VUserDetectorConstruction.hh"
14 #include "G4LogicalVolumeStore.hh"
15 #include "G4SDManager.hh"
16 
17 // From this package, borrowed from G4 10.2
18 #include "G4AtlasTools/G4MultiSensitiveDetector.hh"
19 
20 
21 
23  const std::string& name,
24  const IInterface* parent)
25  : base_class(type,name,parent)
26 {
27 }
28 
29 // Athena method used to set up the SDs for the current worker thread.
31 {
32  ATH_MSG_VERBOSE( name() << "::initializeSD()" );
33 
34  // Sanity check for volume configuration problems.
35  // It would be better to have a more robust solution for this.
36  if(m_volumeNames.empty() != m_noVolumes) {
37  ATH_MSG_ERROR("Initializing SD from " << name() << ", NoVolumes = "
38  << (m_noVolumes? "true" : "false") << ", but LogicalVolumeNames = "
39  << m_volumeNames.value());
40  return StatusCode::FAILURE;
41  }
42 
43  // Make sure SD isn't already registered
44  if(getSD())
45  {
46  ATH_MSG_ERROR("Trying to create a SD which already exists!");
47  return StatusCode::FAILURE;
48  }
49 
50  // Make the SD stored by this tool
51  auto* sd = makeSD();
52  if(!sd)
53  {
54  ATH_MSG_ERROR("Failed to create SD!");
55  return StatusCode::FAILURE;
56  }
57  setSD(sd);
58 
59  // Assign the SD to our list of volumes
60  ATH_CHECK( assignSD( getSD(), m_volumeNames.value() ) );
61 
62  ATH_MSG_DEBUG( "Initialized and added SD " << name() );
63  return StatusCode::SUCCESS;
64 }
65 
66 //-----------------------------------------------------------------------------
67 // Assign an SD to a list of volumes
68 //-----------------------------------------------------------------------------
70 assignSD(G4VSensitiveDetector* sd, const std::vector<std::string>& volumes) const
71 {
72  // Propagate verbosity setting to the SD
73  if(msgLvl(MSG::VERBOSE)) sd->SetVerboseLevel(10);
74  else if(msgLvl(MSG::DEBUG)) sd->SetVerboseLevel(5);
75 
76  // Add the sensitive detector to the SD manager in G4 for SDs,
77  // even if it has no volumes associated to it.
78  auto sdMgr = G4SDManager::GetSDMpointer();
79  sdMgr->AddNewDetector(sd);
80 
81  if(!volumes.empty()) {
82  bool gotOne = false;
83  auto logicalVolumeStore = G4LogicalVolumeStore::GetInstance();
84  for(const auto& volumeName : volumes) {
85  // Keep track of how many volumes we find with this name string.
86  // We allow for multiple matches.
87  int numFound = 0;
88 
89  // Find volumes with this name
90  for(auto* logVol : *logicalVolumeStore) {
91 
92  ATH_MSG_VERBOSE("Check whether "<<logVol->GetName()<<" belongs to the set of sensitive detectors "<<volumeName);
93  if( matchStrings( volumeName.data(), logVol->GetName() ) ){
94  ++numFound;
95  SetSensitiveDetector(logVol, sd);
96  }
97 
98  }
99  // Warn if no volumes were found
100  if(numFound == 0) {
101  ATH_MSG_WARNING("Volume " << volumeName <<
102  " not found in G4LogicalVolumeStore.");
103  }
104  else {
105  ATH_MSG_VERBOSE("Found " << numFound << " copies of LV " << volumeName <<
106  "; SD " << sd->GetName() << " assigned.");
107  gotOne = true;
108  }
109 
110  }
111 
112  // Abort if we have failed to assign any volume
113  if(!gotOne) {
114  ATH_MSG_ERROR( "Failed to assign *any* volume to SD " << name() <<
115  " and expected at least one. Size of the volume store "<<G4LogicalVolumeStore::GetInstance()->size() );
116  return StatusCode::FAILURE;
117  }
118  }
119 
120  return StatusCode::SUCCESS;
121 }
122 
123 G4VSensitiveDetector* SensitiveDetectorBase::getSD()
124 {
125 #ifdef G4MULTITHREADED
126  // Get current thread-ID
127  const auto tid = std::this_thread::get_id();
128  // Retrieve it from the SD map
129  auto sdPair = m_sdThreadMap.find(tid);
130  if(sdPair == m_sdThreadMap.end()) return nullptr;
131  return sdPair->second;
132 #else
133  return m_SD;
134 #endif
135 }
136 
137 void SensitiveDetectorBase::setSD(G4VSensitiveDetector* sd)
138 {
139 #ifdef G4MULTITHREADED
140  const auto tid = std::this_thread::get_id();
141  ATH_MSG_DEBUG("Creating and registering SD " << sd << " in thread " << tid);
142  m_sdThreadMap.insert( std::make_pair(tid, sd) );
143 #else
144  m_SD = sd;
145 #endif
146 }
147 
148 //This function was adapted from the example found at
149 //https://www.geeksforgeeks.org/wildcard-character-matching/
150 bool SensitiveDetectorBase::matchStrings(const char *first, const char *second)
151 {
152  // If we reach at the end of both strings, we are done
153  if (*first == '\0' && *second == '\0')
154  return true;
155 
156  // If there are consecutive '*' present in the first string
157  // advance to the next character
158  if(*first == '*' && *(first + 1) == '*')
159  return matchStrings(first + 1, second);
160 
161  // Make sure that the characters after '*' are present in second string.
162  if (*first == '*' && *(first + 1) != '\0' && *second == '\0')
163  return false;
164 
165  // If the current characters of both strings match
166  if (*first == *second)
167  return matchStrings(first + 1, second + 1);
168 
169  // If there is *, then there are two possibilities
170  // a) We consider current character of second string
171  // b) We ignore current character of second string.
172  if (*first == '*')
173  return matchStrings(first + 1, second) || matchStrings(first, second + 1);
174  return false;
175 }
176 
178 SetSensitiveDetector(G4LogicalVolume* logVol, G4VSensitiveDetector* aSD) const
179 {
180  // New Logic: allow for "multiple" SDs being attached to a single LV.
181  // To do that we use a special proxy SD called G4MultiSensitiveDetector
182 
183  // Get existing SD if already set and check if it is of the special type
184  G4VSensitiveDetector* originalSD = logVol->GetSensitiveDetector();
185  if ( originalSD == nullptr )
186  {
187  logVol->SetSensitiveDetector(aSD);
188  }
189  else
190  {
191  G4MultiSensitiveDetector* msd = dynamic_cast<G4MultiSensitiveDetector*>(originalSD);
192  if ( msd != nullptr )
193  {
194  msd->AddSD(aSD);
195  }
196  else
197  {
198  // Construct a unique name using the volume address
199  std::stringstream ss;
200  ss << static_cast<const void*>(logVol);
201  const G4String msdname = "/MultiSD_" + logVol->GetName() + ss.str();
202  //ATH_MSG_INFO("MultiSD name: " << msdname);
203  msd = new G4MultiSensitiveDetector(msdname);
204  // We need to register the proxy to have correct handling of IDs
205  G4SDManager::GetSDMpointer()->AddNewDetector(msd);
206  msd->AddSD(originalSD);
207  msd->AddSD(aSD);
208  logVol->SetSensitiveDetector(msd);
209  }
210  }
211 }
212 
python.SystemOfUnits.second
int second
Definition: SystemOfUnits.py:120
SensitiveDetectorBase::m_SD
G4VSensitiveDetector * m_SD
The sensitive detector to which this thing corresponds.
Definition: SensitiveDetectorBase.h:111
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
SensitiveDetectorBase::SensitiveDetectorBase
SensitiveDetectorBase(const std::string &type, const std::string &name, const IInterface *parent)
Standard constructor.
Definition: SensitiveDetectorBase.cxx:22
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SensitiveDetectorBase::getSD
G4VSensitiveDetector * getSD()
Retrieve the current SD.
Definition: SensitiveDetectorBase.cxx:123
python.selector.AtlRunQuerySelectorLhcOlc.sd
sd
Definition: AtlRunQuerySelectorLhcOlc.py:612
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
test_pyathena.parent
parent
Definition: test_pyathena.py:15
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
SensitiveDetectorBase::initializeSD
StatusCode initializeSD() override
Setup an SD in the current thread.
Definition: SensitiveDetectorBase.cxx:30
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
SensitiveDetectorBase::SetSensitiveDetector
void SetSensitiveDetector(G4LogicalVolume *, G4VSensitiveDetector *) const
Method stolen from G4VUserDetectorConstruction in G4 10.2.
Definition: SensitiveDetectorBase.cxx:178
SensitiveDetectorBase.h
SensitiveDetectorBase::matchStrings
static bool matchStrings(const char *first, const char *second)
Match two strings with wildcard support.
Definition: SensitiveDetectorBase.cxx:150
SensitiveDetectorBase::m_volumeNames
Gaudi::Property< std::vector< std::string > > m_volumeNames
All the volumes to which this SD is assigned.
Definition: SensitiveDetectorBase.h:82
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
SensitiveDetectorBase::m_noVolumes
Gaudi::Property< bool > m_noVolumes
This SensitiveDetector has no volumes associated with it.
Definition: SensitiveDetectorBase.h:87
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
DeMoScan.first
bool first
Definition: DeMoScan.py:536
DEBUG
#define DEBUG
Definition: page_access.h:11
SensitiveDetectorBase::setSD
void setSD(G4VSensitiveDetector *)
Set the current SD.
Definition: SensitiveDetectorBase.cxx:137
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
SensitiveDetectorBase::assignSD
StatusCode assignSD(G4VSensitiveDetector *sd, const std::vector< std::string > &volumes) const
Assign SD to a list of volumes.
Definition: SensitiveDetectorBase.cxx:70