32 #include "artg4tk/pluginDetectors/gdml/ByParticle.hh" 33 #include "artg4tk/pluginDetectors/gdml/CalorimeterHit.hh" 34 #include "artg4tk/pluginDetectors/gdml/CalorimeterSD.hh" 35 #include "artg4tk/pluginDetectors/gdml/ColorReader.hh" 36 #include "artg4tk/pluginDetectors/gdml/DRCalorimeterHit.hh" 37 #include "artg4tk/pluginDetectors/gdml/DRCalorimeterSD.hh" 38 #include "artg4tk/pluginDetectors/gdml/HadIntAndEdepTrkSD.hh" 39 #include "artg4tk/pluginDetectors/gdml/HadInteractionSD.hh" 40 #include "artg4tk/pluginDetectors/gdml/PhotonHit.hh" 41 #include "artg4tk/pluginDetectors/gdml/PhotonSD.hh" 42 #include "artg4tk/pluginDetectors/gdml/TrackerHit.hh" 43 #include "artg4tk/pluginDetectors/gdml/TrackerSD.hh" 50 #include "Geant4/G4AutoDelete.hh" 51 #include "Geant4/G4GDMLParser.hh" 52 #include "Geant4/G4LogicalVolume.hh" 53 #include "Geant4/G4LogicalVolumeStore.hh" 54 #include "Geant4/G4PhysicalVolumeStore.hh" 55 #include "Geant4/G4RegionStore.hh" 56 #include "Geant4/G4SDManager.hh" 57 #include "Geant4/G4StepLimiter.hh" 58 #include "Geant4/G4Types.hh" 59 #include "Geant4/G4UnitsTable.hh" 60 #include "Geant4/G4UserLimits.hh" 61 #include "Geant4/G4VPhysicalVolume.hh" 62 #include "Geant4/G4VUserDetectorConstruction.hh" 63 #include "Geant4/globals.hh" 66 #include <unordered_map> 80 : artg4tk::DetectorBase(p,
81 p.
get<
string>(
"name",
"LArG4DetectorService"),
86 ,
volumeNames_{
p.get<std::vector<std::string>>(
"volumeNames", {})}
87 ,
stepLimits_{
p.get<std::vector<float>>(
"stepLimits", {})}
89 ,
dumpMP_{
p.get<
bool>(
"DumpMaterialProperties",
false)}
92 G4UnitDefinition::GetUnitsTable();
96 throw cet::exception(
"LArG4DetectorService") <<
"Configuration error: volumeNames:[] and" 97 <<
" stepLimits:[] have different sizes!" 106 <<
"Reading stepLimit(s) from the configuration file, for volume(s):";
111 <<
"Invalid stepLimits found. Step limits must be" 112 <<
" positive! Bad value : stepLimits[" << i <<
"] = " <<
stepLimits_.at(i) <<
" [mm]\n";
123 std::vector<G4LogicalVolume*>
127 G4GDMLParser
parser(&reader);
134 parser.Read(fullGDMLFileName);
135 G4VPhysicalVolume* World = parser.GetWorldVolume();
137 std::stringstream ss;
138 ss << World->GetTranslation() <<
"\n\n";
139 ss <<
"Found World: " << World->GetName() <<
"\n";
140 ss <<
"World LV: " << World->GetLogicalVolume()->GetName() <<
"\n";
141 G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance();
142 ss <<
"Found " << pLVStore->size() <<
" logical volumes." 144 G4PhysicalVolumeStore* pPVStore = G4PhysicalVolumeStore::GetInstance();
145 ss <<
"Found " << pPVStore->size() <<
" physical volumes." 147 G4SDManager* SDman = G4SDManager::GetSDMpointer();
148 const G4GDMLAuxMapType* auxmap = parser.GetAuxMap();
149 ss <<
"Found " << auxmap->size() <<
" volume(s) with auxiliary information." 151 ss <<
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
152 mf::LogInfo(
"LArG4DetectorService::doBuildLVs") << ss.str();
154 for (
auto const& [
volume, auxes] : *auxmap) {
155 G4cout <<
"Volume " <<
volume->GetName()
156 <<
" has the following list of auxiliary information: \n";
157 for (
auto const& aux : auxes) {
158 G4cout <<
"--> Type: " << aux.type <<
" Value: " << aux.value <<
"\n";
160 G4double
value = atof(aux.value);
161 G4double val_unit = 1;
162 G4String provided_category =
"NONE";
163 if ((aux.unit) && (aux.unit !=
"")) {
164 val_unit = G4UnitDefinition::GetValueOf(aux.unit);
165 provided_category = G4UnitDefinition::GetCategory(aux.unit);
166 mf::LogInfo(
"AuxUnit") <<
" Unit parsed = " << aux.unit
167 <<
" from unit category: " << provided_category.c_str();
172 if (aux.type ==
"StepLimit") {
173 G4UserLimits* fStepLimit =
new G4UserLimits();
174 G4AutoDelete::Register(fStepLimit);
177 G4String steplimit_category =
"Length";
178 if (provided_category == steplimit_category) {
179 mf::LogInfo(
"AuxUnit") <<
"Valid StepLimit unit category obtained: " 180 << provided_category.c_str();
183 fStepLimit->SetMaxAllowedStep(value);
185 <<
"fStepLimit: " << value <<
" " << value /
CLHEP::cm <<
" cm\n";
187 else if (provided_category ==
189 MF_LOG_WARNING(
"StepLimitUnit") <<
"StepLimit in geometry file does not have a unit!" 190 <<
" Defaulting to mm...";
192 fStepLimit->SetMaxAllowedStep(value);
194 <<
"fStepLimit: " << value <<
" " << value /
CLHEP::cm <<
" cm\n";
198 <<
"StepLimit does not have a valid length unit!\n" 199 <<
" Category of unit provided = " << provided_category <<
".\n";
202 volume->SetUserLimits(fStepLimit);
205 <<
"Set stepLimit for volume: " <<
volume->GetName() <<
" from the GDML file.";
208 if (aux.type ==
"SensDet") {
209 if (aux.value ==
"DRCalorimeter") {
210 G4String
name =
volume->GetName() +
"_DRCalorimeter";
211 artg4tk::DRCalorimeterSD* aDRCalorimeterSD =
new artg4tk::DRCalorimeterSD(name);
212 SDman->AddNewDetector(aDRCalorimeterSD);
213 volume->SetSensitiveDetector(aDRCalorimeterSD);
214 std::cout <<
"Attaching sensitive Detector: " << aux.value
215 <<
" to Volume: " <<
volume->GetName() <<
"\n";
218 else if (aux.value ==
"Calorimeter") {
219 G4String
name =
volume->GetName() +
"_Calorimeter";
220 artg4tk::CalorimeterSD* aCalorimeterSD =
new artg4tk::CalorimeterSD(name);
221 SDman->AddNewDetector(aCalorimeterSD);
222 volume->SetSensitiveDetector(aCalorimeterSD);
223 std::cout <<
"Attaching sensitive Detector: " << aux.value
224 <<
" to Volume: " <<
volume->GetName() <<
"\n";
227 else if (aux.value ==
"PhotonDetector") {
228 G4String
name =
volume->GetName() +
"_PhotonDetector";
229 artg4tk::PhotonSD* aPhotonSD =
new artg4tk::PhotonSD(name);
230 SDman->AddNewDetector(aPhotonSD);
231 volume->SetSensitiveDetector(aPhotonSD);
232 std::cout <<
"Attaching sensitive Detector: " << aux.value
233 <<
" to Volume: " <<
volume->GetName() <<
"\n";
236 else if (aux.value ==
"Tracker") {
237 G4String
name =
volume->GetName() +
"_Tracker";
238 artg4tk::TrackerSD* aTrackerSD =
new artg4tk::TrackerSD(name);
239 SDman->AddNewDetector(aTrackerSD);
240 volume->SetSensitiveDetector(aTrackerSD);
241 std::cout <<
"Attaching sensitive Detector: " << aux.value
242 <<
" to Volume: " <<
volume->GetName() <<
"\n";
245 else if (aux.value ==
"SimEnergyDeposit") {
246 G4String
name =
volume->GetName() +
"_SimEnergyDeposit";
248 SDman->AddNewDetector(aSimEnergyDepositSD);
249 volume->SetSensitiveDetector(aSimEnergyDepositSD);
250 std::cout <<
"Attaching sensitive Detector: " << aux.value
251 <<
" to Volume: " <<
volume->GetName() <<
"\n";
254 else if (aux.value ==
"AuxDet") {
255 G4String
name =
volume->GetName() +
"_AuxDet";
257 SDman->AddNewDetector(aAuxDetSD);
258 volume->SetSensitiveDetector(aAuxDetSD);
259 std::cout <<
"Attaching sensitive Detector: " << aux.value
260 <<
" to Volume: " <<
volume->GetName() <<
"\n";
263 else if (aux.value ==
"HadInteraction") {
264 G4String
name =
volume->GetName() +
"_HadInteraction";
265 artg4tk::HadInteractionSD* aHadInteractionSD =
new artg4tk::HadInteractionSD(name);
268 volume->SetSensitiveDetector(aHadInteractionSD);
269 std::cout <<
"Attaching sensitive Detector: " << aux.value
270 <<
" to Volume: " <<
volume->GetName() <<
"\n";
273 else if (aux.value ==
"HadIntAndEdepTrk") {
274 G4String
name =
volume->GetName() +
"_HadIntAndEdepTrk";
275 artg4tk::HadIntAndEdepTrkSD* aHadIntAndEdepTrkSD =
new artg4tk::HadIntAndEdepTrkSD(name);
278 volume->SetSensitiveDetector(aHadIntAndEdepTrkSD);
279 std::cout <<
"Attaching sensitive Detector: " << aux.value
280 <<
" to Volume: " <<
volume->GetName() <<
"\n";
286 <<
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
288 if (
dumpMP_) { G4cout << *(G4Material::GetMaterialTable()) << G4endl; }
290 std::cout <<
"List SD Tree: \n";
292 std::cout <<
" Collection Capacity: " << SDman->GetCollectionCapacity() <<
"\n";
293 G4HCtable* hctable = SDman->GetHCtable();
294 for (G4int j = 0; j < SDman->GetCollectionCapacity(); ++j) {
295 std::cout <<
"HC Name: " << hctable->GetHCname(j) <<
" SD Name: " << hctable->GetSDname(j)
298 std::cout <<
"==================================================\n";
300 std::vector<G4LogicalVolume*> myLVvec;
301 myLVvec.push_back(pLVStore->at(0));
302 std::cout <<
"nr of LV ======================: " << myLVvec.size() <<
"\n";
307 std::vector<G4VPhysicalVolume*>
311 std::vector<G4VPhysicalVolume*> myPVvec;
312 G4PhysicalVolumeStore* pPVStore = G4PhysicalVolumeStore::GetInstance();
313 myPVvec.push_back(pPVStore->at(
314 pPVStore->size() - 1));
326 <<
"Setting step limits from configuration" 327 <<
" file. This will OVERRIDE redundant stepLimit(s) set in the GDML file. Note" 328 <<
" that stepLimits are only active if enabled in the physicsListService via the" 329 <<
" appropriate parameter.";
332 G4LogicalVolume* setVol =
nullptr;
334 G4double previousStepLimit = 0.;
337 if (setVol = G4LogicalVolumeStore::GetInstance()->GetVolume(
name,
false); !setVol) {
339 <<
"Provided volume name : " <<
name <<
" not found!\n";
343 volumeName = setVol->GetName();
345 <<
"Got logical volume with name: " << volumeName;
347 G4UserLimits* fStepLimitOverride =
new G4UserLimits();
348 G4AutoDelete::Register(fStepLimitOverride);
353 previousStepLimit = (G4double)(
search->second);
354 if (newStepLimit != previousStepLimit) {
356 <<
"OVERRIDING PREVIOUSLY SET" 357 <<
" STEPLIMIT FOR VOLUME : " << volumeName <<
" FROM " << previousStepLimit <<
" mm TO " 358 << newStepLimit <<
" mm";
362 <<
"New stepLimit matches previously" 363 <<
" set stepLimit from the GDML file for volume : " << volumeName
364 <<
" stepLimit : " << newStepLimit <<
" mm. Nothing will be changed.";
369 fStepLimitOverride->SetMaxAllowedStep(newStepLimit);
371 <<
"fStepLimitOverride: " << newStepLimit /
CLHEP::mm <<
" mm " << newStepLimit /
CLHEP::cm 373 <<
"for volume: " << volumeName <<
"\n" 374 <<
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
375 setVol->SetUserLimits(fStepLimitOverride);
390 if (sd_name ==
"DRCalorimeter") {
396 else if (sd_name ==
"Calorimeter") {
399 else if (sd_name ==
"PhotonDetector") {
402 else if (sd_name ==
"Tracker") {
405 else if (sd_name ==
"SimEnergyDeposit") {
408 else if (sd_name ==
"AuxDet") {
411 else if (sd_name ==
"HadInteraction") {
412 collector.
produces<artg4tk::ArtG4tkVtx>();
414 else if (sd_name ==
"HadIntAndEdepTrk") {
415 collector.
produces<artg4tk::ArtG4tkVtx>();
416 collector.
produces<artg4tk::TrackerHitCollection>();
428 G4SDManager* sdman = G4SDManager::GetSDMpointer();
432 auto sd = sdman->FindSensitiveDetector(
volume_name +
"_" + sd_name);
433 if (sd_name ==
"HadInteraction") {
434 if (
auto hisd = dynamic_cast<artg4tk::HadInteractionSD*>(sd)) {
435 if (
auto const& inter = hisd->Get1stInteraction(); inter.GetNumOutcoming() > 0) {
436 e.
put(make_product(inter));
441 else if (sd_name ==
"HadIntAndEdepTrk") {
442 if (
auto trksd = dynamic_cast<artg4tk::HadIntAndEdepTrkSD*>(sd)) {
443 if (
auto const& inter = trksd->Get1stInteraction(); inter.GetNumOutcoming() > 0) {
444 e.
put(make_product(inter));
446 if (
auto const& trkhits = trksd->GetEdepTrkHits(); !trkhits.empty()) {
447 e.
put(make_product(trkhits));
452 else if (sd_name ==
"Tracker") {
453 auto trsd =
dynamic_cast<artg4tk::TrackerSD*
>(sd);
456 else if (sd_name ==
"SimEnergyDeposit") {
460 else if (sd_name ==
"AuxDet") {
461 auto auxsd =
dynamic_cast<AuxDetSD*
>(sd);
464 else if (sd_name ==
"Calorimeter") {
465 auto calsd =
dynamic_cast<artg4tk::CalorimeterSD*
>(sd);
468 else if (sd_name ==
"DRCalorimeter") {
469 auto drcalsd =
dynamic_cast<artg4tk::DRCalorimeterSD*
>(sd);
471 e.
put(make_product(drcalsd->GetHits()), identifier);
472 e.
put(make_product(drcalsd->GetEbyParticle()), identifier +
"Edep");
473 e.
put(make_product(drcalsd->GetNCerenbyParticle()), identifier +
"NCeren");
475 else if (sd_name ==
"PhotonDetector") {
476 auto phsd =
dynamic_cast<artg4tk::PhotonSD*
>(sd);
static constexpr double cm
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::vector< G4LogicalVolume * > doBuildLVs() override
void doCallArtProduces(art::ProducesCollector &collector) override
static const std::string volume[nvol]
const std::string instance
void doFillEventWithArtHits(G4HCofThisEvent *hc) override
LArG4DetectorService(fhicl::ParameterSet const &)
std::string instanceName(std::string const &) const
std::vector< std::pair< std::string, std::string > > detectors_
std::string gdmlFileName_
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
void produces(std::string const &instanceName={}, Persistable const persistable=Persistable::Yes)
T get(std::string const &key) const
volt_as<> volt
Type of potential stored in volts, in double precision.
std::vector< std::string > volumeNames_
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
std::vector< G4VPhysicalVolume * > doPlaceToPVs(std::vector< G4LogicalVolume * >) override
std::vector< float > stepLimits_
std::vector< AuxDetHit > AuxDetHitCollection
#define DEFINE_ART_SERVICE(svc)
std::vector< SimEnergyDeposit > SimEnergyDepositCollection
contains information for a single step in the detector simulation
static constexpr double mm
auto const & get(AssnsNode< L, R, D > const &r)
#define MF_LOG_WARNING(category)
std::map< std::string, G4double > overrideGDMLStepLimit_Map
std::unordered_map< std::string, float > setGDMLVolumes_
cet::coded_exception< error, detail::translate > exception