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