11 #include "G4GeometryManager.hh"
12 #include "G4LogicalVolumeStore.hh"
13 #include "G4PhysicalVolumeStore.hh"
14 #include "G4SDManager.hh"
15 #include "G4SolidStore.hh"
16 #include "G4UIcmdWithAString.hh"
17 #include "G4UImanager.hh"
19 #include "G4GDMLParser.hh"
24 #include "DD4hep/Detector.h"
25 #include "DDG4/Geant4Converter.h"
26 #include "DDG4/Geant4DetectorConstruction.h"
43 class SDBuildMessenger :
public G4UImessenger {
45 SDBuildMessenger(
const G4String &path,
const G4String &dsc);
46 void AddSDBuildCommand(
const std::string &newCommand);
47 void SetNewValue(G4UIcommand *command, G4String newValue);
48 void BuildSD(
const std::string &sdClassName,
const std::string &logVolNameAndParams);
51 std::vector<G4UIcmdWithAString> _sdBuildCommands;
54 G4ThreadLocal std::unique_ptr<SDBuildMessenger> sdBuildMessenger =
nullptr;
56 SDBuildMessenger::SDBuildMessenger(
const G4String &path,
const G4String &dsc) : G4UImessenger(path, dsc) {}
58 void SDBuildMessenger::AddSDBuildCommand(
const std::string &newCommand) {
59 _sdBuildCommands.emplace_back(newCommand.c_str(),
this);
62 void SDBuildMessenger::SetNewValue(G4UIcommand *command, G4String newValue) {
63 std::string path = command->GetCommandPath();
64 if (path.size() > 16 && path.substr(0, 16) ==
"/GGS/scoring/add") {
66 auto sdClassName = path.substr(16);
67 BuildSD(sdClassName, newValue);
71 void SDBuildMessenger::BuildSD(
const std::string &sdClassName,
const std::string &logVolNameAndParams) {
72 static const std::string routineName(
"GGSScoringManager::AddSDToLogVol");
75 G4String logVolName = logVolNameAndParams.substr(0, logVolNameAndParams.find_first_of(
' '));
76 auto separatorPos = logVolNameAndParams.find_first_of(
' ');
78 if (separatorPos != std::string::npos) {
79 params = logVolNameAndParams.substr(logVolNameAndParams.find_first_of(
' ') + 1);
82 auto AddSDToLogVol = [](G4VSensitiveDetector *sd, G4LogicalVolume *logVol) {
84 if (logVol->GetSensitiveDetector() ==
nullptr) {
86 logVol->SetSensitiveDetector(sd);
98 G4SDManager::GetSDMpointer()->AddNewDetector(multiSD);
99 logVol->SetSensitiveDetector(multiSD);
104 if (G4SDManager::GetSDMpointer()->GetHCtable()->GetCollectionID(sd->GetName()) == -1) {
105 G4SDManager::GetSDMpointer()->AddNewDetector(sd);
109 G4LogicalVolumeStore::const_iterator logVol = G4LogicalVolumeStore::GetInstance()->begin();
110 G4VSensitiveDetector *sd =
nullptr;
111 for (; logVol != G4LogicalVolumeStore::GetInstance()->end(); ++logVol) {
112 if ((*logVol)->GetName() == logVolName) {
115 G4String sdName = sdClassName;
117 sdName.append(
".").append(params);
124 G4ExceptionDescription ed;
125 ed <<
"No registered builder for sensitive detector " << sdClassName << std::endl;
126 G4Exception(
"GGSUserActionInitialization::UAIMessenger::SetNewValue",
"Invalid generator",
127 G4ExceptionSeverity::FatalException, ed);
131 if (G4Threading::IsMultithreadedApplication() && G4Threading::IsMasterThread()) {
133 if (G4SDManager::GetSDMpointer()->GetHCtable()->GetCollectionID(sd->GetName()) == -1) {
134 G4SDManager::GetSDMpointer()->AddNewDetector(sd);
137 AddSDToLogVol(sd, *logVol);
143 G4ExceptionDescription ed;
144 ed << routineName <<
": logical volume " << logVolName <<
" not present. Sensitive detector " << sdClassName
145 <<
" not added." << std::endl;
146 G4Exception(
"GGSUserActionInitialization::UAIMessenger::SetNewValue",
"Invalid generator",
147 G4ExceptionSeverity::FatalException, ed);
156 : _physicalWorld(nullptr), _geometry(nullptr), _library(library), _configDataCard(configDataCard), _gdxml(
""),
157 _messenger(this,
"/GGS/"), _nToPrintForVectGeoParams{10} {
158 _messenger.DeclareProperty(
"nToPrintForVectGeoParams", _nToPrintForVectGeoParams,
159 "Maximum number of elemts to print for vector parameters (default: 10; 0 -> all)");
165 const G4String &configDataCard,
bool)
166 : _physicalWorld(nullptr), _geometry(nullptr), _library(library), _configDataCard(configDataCard), _gdxml(
""),
167 _messenger(this,
"/GGS/"), _nToPrintForVectGeoParams{10} {
168 _messenger.DeclareProperty(
"nToPrintForVectGeoParams", _nToPrintForVectGeoParams,
169 "Maximum number of elemts to print for vector parameters (default: 10; 0 -> all)");
175 : _physicalWorld(nullptr), _geometry(nullptr), _library(
""), _configDataCard(
""), _gdxml(gdxml),
176 _messenger(this,
"/GGS/"), _nToPrintForVectGeoParams{10} {
177 _messenger.DeclareProperty(
"nToPrintForVectGeoParams", _nToPrintForVectGeoParams,
178 "Maximum number of elemts to print for vector parameters (default: 10; 0 -> all)");
195 GGSGDMLGeometryConstruction(G4VPhysicalVolume *world) : _world(world) {}
196 G4VPhysicalVolume *
Construct() {
return _world; }
197 G4VPhysicalVolume *
GetVolume() {
return _world; };
200 G4VPhysicalVolume *_world;
204 #ifdef GGS_USE_DD4HEP
211 GGSDD4hepGeometryConstruction(G4VPhysicalVolume *world) : _world(world) {}
212 G4VPhysicalVolume *
Construct() {
return _world; }
213 G4VPhysicalVolume *
GetVolume() {
return _world; };
216 G4VPhysicalVolume *_world;
220 template <
typename T>
void PrintVectParams(
const T ¶msVect,
size_t nToPrint) {
221 for (
auto &par : paramsVect) {
222 GGSCCOUT(INFO) << par.first <<
": {";
223 for (
size_t iVal = 0; iVal < std::min(par.second.size() - 1, nToPrint - 1); ++iVal) {
226 if (nToPrint != 0 && par.second.size() > nToPrint) {
237 static const std::string routineName(
"GGSDetectorConstruction::Construct");
240 if (_library !=
"") {
243 GGSCOUT(ERROR) <<
"Impossible to load geometry library " << _library <<
GGSENDL;
244 throw std::runtime_error(
"Impossible to load geometry library");
248 GGSCOUT(ERROR) <<
"Can't create the geometry." <<
GGSENDL;
250 GGSCOUT(INFO) <<
"Construct the detector." <<
GGSENDL;
254 const std::string geoVersion = _geometry->
GetVersion();
255 if (geoVersion !=
"") {
256 GGSCOUT(INFO) <<
"Geometry version: " << geoVersion <<
GGSENDL;
258 GGSCOUT(INFO) <<
"No geometry version available" <<
GGSENDL;
270 if (intParams.size() != 0 || boolParams.size() != 0 || realParams.size() != 0 || stringParams.size() != 0 ||
271 vectIntParams.size() != 0 || vectBoolParams.size() != 0 || vectRealParams.size() != 0 ||
272 vectStringParams.size() != 0) {
273 GGSCOUT(INFO) <<
"Geometry parameters:\n";
274 for (
auto &par : intParams) {
275 GGSCCOUT(INFO) << par.first <<
": " << par.second <<
"\n";
277 for (
auto &par : boolParams) {
278 GGSCCOUT(INFO) << par.first <<
": " << (par.second ?
"true" :
"false") <<
"\n";
280 for (
auto &par : realParams) {
281 GGSCCOUT(INFO) << par.first <<
": " << par.second <<
"\n";
283 for (
auto &par : stringParams) {
284 GGSCCOUT(INFO) << par.first <<
": " << par.second <<
"\n";
286 PrintVectParams(vectIntParams, _nToPrintForVectGeoParams);
287 PrintVectParams(vectRealParams, _nToPrintForVectGeoParams);
288 PrintVectParams(vectBoolParams, _nToPrintForVectGeoParams);
289 PrintVectParams(vectStringParams, _nToPrintForVectGeoParams);
293 else if (_gdxml.length() > 4 && _gdxml.substr(_gdxml.length() - 5) ==
".gdml") {
295 G4GDMLParser gdmlParser;
296 gdmlParser.SetOverlapCheck(
false);
298 gdmlParser.Read(_gdxml,
false);
300 GGSCOUT(ERROR) <<
"G4GDML: " << ge <<
", missing network connection? wrong schema URL?" <<
GGSENDL;
306 gdmlParser.StripNamePointers();
307 _physicalWorld = gdmlParser.GetWorldVolume();
308 if (!_physicalWorld) {
309 GGSCOUT(ERROR) <<
"Cannot build the GMDL geometry." <<
GGSENDL;
310 throw std::runtime_error(
"Cannot build the GMDL geometry.");
312 _geometry =
new GGSGDMLGeometryConstruction(_physicalWorld);
315 #ifdef GGS_USE_DD4HEP
316 else if (_gdxml.length() > 3 && _gdxml.substr(_gdxml.length() - 4) ==
".xml") {
318 dd4hep::Detector &detDesc = dd4hep::Detector::getInstance();
319 detDesc.fromXML(_gdxml);
320 dd4hep::DetElement world = detDesc.world();
321 dd4hep::sim::Geant4Converter conv(detDesc, dd4hep::NOLOG);
322 dd4hep::sim::Geant4GeometryInfo *geoInfo = conv.create(world).detach();
323 _physicalWorld = geoInfo->world();
324 _geometry =
new GGSDD4hepGeometryConstruction(_physicalWorld);
331 const G4LogicalVolumeStore *logicalVolumeStore = G4LogicalVolumeStore::GetInstance();
332 std::vector<G4LogicalVolume *>::const_iterator i;
334 for (i = logicalVolumeStore->begin(); i != logicalVolumeStore->end(); i++) {
335 std::string logVolName = (*i)->GetName();
336 auto detVolName = logVolName.substr(0, logVolName.find_first_of(
' '));
337 auto spacePos = logVolName.find_last_of(
' ');
338 std::string scorerName(
"");
339 if (spacePos != std::string::npos)
340 scorerName = logVolName.substr(spacePos + 1);
343 GGSCOUT(WARNING) <<
"This version of GGS does not support the definition of sensitive volumes by name ("
344 << detVolName <<
").\n";
345 GGSCCOUT(WARNING) <<
"Please change the name of the volume and make it active using a datacard command."
347 throw std::runtime_error(
"Use of removed feature: definition of sensitive volume by name.");
351 return _physicalWorld;
354 void GGSDetectorConstruction::ConstructSDandField() {
356 sdBuildMessenger = std::make_unique<SDBuildMessenger>(
"/GGS/scoring/",
"Messenger for SD build commands");
357 auto &availableSDBuilders =
359 for (
auto &builder : availableSDBuilders) {
361 sdBuildMessenger->AddSDBuildCommand(
"/GGS/scoring/add" + builder);
#define GGSCCOUT(level)
Smart log utility which prints no header at the beginning of the line.
GGSDetectorConstruction(const G4String &library, const G4String &configDataCard)
Constructor.
const std::map< std::string, std::vector< bool > > & GetVectBoolParameters()
Getter method for vector-of-booleans geometry parameters.
#define GGSCOUT_BACKEND
Smart log macro. It writes on stdout only if the specified verbosity level is lesser than the maximum...
const std::map< std::string, int > & GetIntParameters()
Getter method for integer geometry parameters.
const std::map< std::string, double > & GetRealParameters()
Getter method for real geometry parameters.
Abstract class needed to load GGS geometry.
static GGSGeoPluginManager & GetInstance()
Get the singleton instance.
G4VPhysicalVolume * Construct()
Override of the Construct method.
const std::map< std::string, std::vector< std::string > > & GetVectStringParameters()
Getter method for vector-of-strings geometry parameters.
std::unique_ptr< T > CreateObject(const std::string &name, ConstructorArgs...arguments)
Create an object.
const std::vector< std::string > & GetListOfRegisteredBuilders()
Gets a vector containing the names of available registered builders.
virtual G4VPhysicalVolume * Construct()=0
Construct the detector - virtual method.
const std::map< std::string, std::vector< int > > & GetVectIntParameters()
Getter method for vector-of-integers geometry parameters.
const std::map< std::string, std::string > & GetStringParameters()
Getter method for string geometry parameters.
A multiple sensitive detector.
~GGSDetectorConstruction()
Destructor.
const std::map< std::string, std::vector< double > > & GetVectRealParameters()
Getter method for vector-of-reals geometry parameters.
virtual const std::string GetVersion()
Getter method for geometry version.
const std::map< std::string, bool > & GetBoolParameters()
Getter method for boolean geometry parameters.
virtual bool ExportParameters()
Function for exporting the geometry parameters.
static GGSFactory & GetInstance()
Getter method for singleton pointer.
GGSVGeometryConstruction * GetGeoConstruction()
Returns the geometry construction object.
static GGSNameDecoder & GetInstance()
Get instance of the singleton.
virtual G4VPhysicalVolume * GetVolume()=0
Get the detector VPhysicalVolume - virtual method.
bool IsSensitive(const std::string &volumeName)
Check if the logical volume is sensitive.
void AddSensitiveDetector(G4VSensitiveDetector *sd)
Adds a new sensitive detector to the multidetector.
Class needed to decode sensitive volume names.
void SetGeoDataCard(const G4String &dataCard)
Sets the geometry configuration datacard.