25 #include "cetlib/search_path.h" 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" 48 #include "Geant4/G4AutoDelete.hh" 49 #include "Geant4/G4GDMLParser.hh" 50 #include "Geant4/G4LogicalVolume.hh" 51 #include "Geant4/G4LogicalVolumeStore.hh" 52 #include "Geant4/G4PhysicalVolumeStore.hh" 53 #include "Geant4/G4RegionStore.hh" 54 #include "Geant4/G4SDManager.hh" 55 #include "Geant4/G4StepLimiter.hh" 56 #include "Geant4/G4Types.hh" 57 #include "Geant4/G4UnitsTable.hh" 58 #include "Geant4/G4UserLimits.hh" 59 #include "Geant4/G4VPhysicalVolume.hh" 60 #include "Geant4/G4VUserDetectorConstruction.hh" 61 #include "Geant4/globals.hh" 64 #include <unordered_map> 70 auto make_product(T t)
72 return std::make_unique<T>(std::move(t));
78 p.
get<string>(
"name",
"LArG4DetectorService"),
79 p.
get<string>(
"category",
"World"),
80 p.
get<string>(
"mother_category",
""))
81 , gdmlFileName_{p.
get<std::string>(
"gdmlFileName_",
"")}
85 ,
volumeNames_{p.get<std::vector<std::string>>(
"volumeNames", {})}
86 ,
stepLimits_{p.get<std::vector<float>>(
"stepLimits", {})}
88 ,
dumpMP_{p.get<
bool>(
"DumpMaterialProperties",
false)}
91 G4UnitDefinition::GetUnitsTable();
95 throw cet::exception(
"LArG4DetectorService") <<
"Configuration error: volumeNames:[] and" 96 <<
" stepLimits:[] have different sizes!" 101 new G4UnitDefinition(
"volt/cm",
"V/cm",
"Electric field",
CLHEP::volt / CLHEP::cm);
105 <<
"Reading stepLimit(s) from the configuration file, for volume(s):";
110 <<
"Invalid stepLimits found. Step limits must be" 111 <<
" positive! Bad value : stepLimits[" << i <<
"] = " <<
stepLimits_.at(i) <<
" [mm]\n";
125 G4GDMLParser
parser(&reader);
127 cet::search_path sp{
"FW_SEARCH_PATH"};
128 std::string fullGDMLFileName;
132 parser.Read(fullGDMLFileName,
false);
133 G4VPhysicalVolume* World = parser.GetWorldVolume();
135 std::stringstream ss;
136 ss << World->GetTranslation() <<
"\n\n";
137 ss <<
"Found World: " << World->GetName() <<
"\n";
138 ss <<
"World LV: " << World->GetLogicalVolume()->GetName() <<
"\n";
139 G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance();
140 ss <<
"Found " << pLVStore->size() <<
" logical volumes." 142 G4PhysicalVolumeStore* pPVStore = G4PhysicalVolumeStore::GetInstance();
143 ss <<
"Found " << pPVStore->size() <<
" physical volumes." 145 G4SDManager* SDman = G4SDManager::GetSDMpointer();
146 const G4GDMLAuxMapType* auxmap = parser.GetAuxMap();
147 ss <<
"Found " << auxmap->size() <<
" volume(s) with auxiliary information." 149 ss <<
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
150 mf::LogInfo(
"LArG4DetectorService::doBuildLVs") << ss.str();
152 for (
auto const& [volume, auxes] : *auxmap) {
153 G4cout <<
"Volume " << volume->GetName()
154 <<
" has the following list of auxiliary information: \n";
155 for (
auto const& aux : auxes) {
156 G4cout <<
"--> Type: " << aux.type <<
" Value: " << aux.value <<
"\n";
158 G4double
value = atof(aux.value);
159 G4double val_unit = 1;
160 G4String provided_category =
"NONE";
161 if ((aux.unit) && (aux.unit !=
"")) {
162 val_unit = G4UnitDefinition::GetValueOf(aux.unit);
163 provided_category = G4UnitDefinition::GetCategory(aux.unit);
164 mf::LogInfo(
"AuxUnit") <<
" Unit parsed = " << aux.unit
165 <<
" from unit category: " << provided_category.c_str();
170 if (aux.type ==
"StepLimit") {
171 G4UserLimits* fStepLimit =
new G4UserLimits();
172 G4AutoDelete::Register(fStepLimit);
175 G4String steplimit_category =
"Length";
176 if (provided_category == steplimit_category) {
177 mf::LogInfo(
"AuxUnit") <<
"Valid StepLimit unit category obtained: " 178 << provided_category.c_str();
180 value = (value / CLHEP::mm) * CLHEP::mm;
181 fStepLimit->SetMaxAllowedStep(value);
183 <<
"fStepLimit: " << value <<
" " << value / CLHEP::cm <<
" cm\n";
185 else if (provided_category ==
187 MF_LOG_WARNING(
"StepLimitUnit") <<
"StepLimit in geometry file does not have a unit!" 188 <<
" Defaulting to mm...";
190 fStepLimit->SetMaxAllowedStep(value);
192 <<
"fStepLimit: " << value <<
" " << value / CLHEP::cm <<
" cm\n";
196 <<
"StepLimit does not have a valid length unit!\n" 197 <<
" Category of unit provided = " << provided_category <<
".\n";
200 volume->SetUserLimits(fStepLimit);
203 <<
"Set stepLimit for volume: " << volume->GetName() <<
" from the GDML file.";
204 setGDMLVolumes_.insert(std::make_pair(volume->GetName(), (float)(value / CLHEP::mm)));
206 if (aux.type ==
"ExcitationEnergy") {
207 G4String ExcitationEnergy_category =
"Energy";
208 if (provided_category == ExcitationEnergy_category) {
209 G4cout <<
"Valid ExcitationEnergy unit category obtained: " << provided_category.c_str()
211 G4cout <<
" unit Value:" << val_unit <<
" Value: " << value << G4endl;
212 G4cout <<
" unit Value:" << val_unit <<
" Value: " << value / CLHEP::eV <<
" eV" 214 volume->GetMaterial()->GetIonisation()->SetMeanExcitationEnergy(value);
215 G4cout <<
" Mean Ionization energy: " 216 << volume->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy() << G4endl;
220 if (aux.type ==
"SensDet") {
221 if (aux.value ==
"DRCalorimeter") {
222 G4String name = volume->GetName() +
"_DRCalorimeter";
223 artg4tk::DRCalorimeterSD* aDRCalorimeterSD =
new artg4tk::DRCalorimeterSD(name);
224 SDman->AddNewDetector(aDRCalorimeterSD);
225 volume->SetSensitiveDetector(aDRCalorimeterSD);
226 std::cout <<
"Attaching sensitive Detector: " << aux.value
227 <<
" to Volume: " << volume->GetName() <<
"\n";
228 detectors_.emplace_back(volume->GetName(), aux.value);
230 else if (aux.value ==
"Calorimeter") {
231 G4String name = volume->GetName() +
"_Calorimeter";
232 artg4tk::CalorimeterSD* aCalorimeterSD =
new artg4tk::CalorimeterSD(name);
233 SDman->AddNewDetector(aCalorimeterSD);
234 volume->SetSensitiveDetector(aCalorimeterSD);
235 std::cout <<
"Attaching sensitive Detector: " << aux.value
236 <<
" to Volume: " << volume->GetName() <<
"\n";
237 detectors_.emplace_back(volume->GetName(), aux.value);
239 else if (aux.value ==
"PhotonDetector") {
240 G4String name = volume->GetName() +
"_PhotonDetector";
241 artg4tk::PhotonSD* aPhotonSD =
new artg4tk::PhotonSD(name);
242 SDman->AddNewDetector(aPhotonSD);
243 volume->SetSensitiveDetector(aPhotonSD);
244 std::cout <<
"Attaching sensitive Detector: " << aux.value
245 <<
" to Volume: " << volume->GetName() <<
"\n";
246 detectors_.emplace_back(volume->GetName(), aux.value);
248 else if (aux.value ==
"Tracker") {
249 G4String name = volume->GetName() +
"_Tracker";
250 artg4tk::TrackerSD* aTrackerSD =
new artg4tk::TrackerSD(name);
251 SDman->AddNewDetector(aTrackerSD);
252 volume->SetSensitiveDetector(aTrackerSD);
253 std::cout <<
"Attaching sensitive Detector: " << aux.value
254 <<
" to Volume: " << volume->GetName() <<
"\n";
255 detectors_.push_back(std::make_pair(volume->GetName(), aux.value));
257 else if (aux.value ==
"SimEnergyDeposit") {
258 G4String name = volume->GetName() +
"_SimEnergyDeposit";
260 SDman->AddNewDetector(aSimEnergyDepositSD);
261 volume->SetSensitiveDetector(aSimEnergyDepositSD);
262 std::cout <<
"Attaching sensitive Detector: " << aux.value
263 <<
" to Volume: " << volume->GetName() <<
"\n";
264 detectors_.emplace_back(volume->GetName(), aux.value);
266 else if (aux.value ==
"AuxDet") {
267 G4String name = volume->GetName() +
"_AuxDet";
269 SDman->AddNewDetector(aAuxDetSD);
270 volume->SetSensitiveDetector(aAuxDetSD);
271 std::cout <<
"Attaching sensitive Detector: " << aux.value
272 <<
" to Volume: " << volume->GetName() <<
"\n";
273 detectors_.emplace_back(volume->GetName(), aux.value);
275 else if (aux.value ==
"HadInteraction") {
276 G4String name = volume->GetName() +
"_HadInteraction";
277 artg4tk::HadInteractionSD* aHadInteractionSD =
new artg4tk::HadInteractionSD(name);
280 volume->SetSensitiveDetector(aHadInteractionSD);
281 std::cout <<
"Attaching sensitive Detector: " << aux.value
282 <<
" to Volume: " << volume->GetName() <<
"\n";
283 detectors_.emplace_back(volume->GetName(), aux.value);
285 else if (aux.value ==
"HadIntAndEdepTrk") {
286 G4String name = volume->GetName() +
"_HadIntAndEdepTrk";
287 artg4tk::HadIntAndEdepTrkSD* aHadIntAndEdepTrkSD =
new artg4tk::HadIntAndEdepTrkSD(name);
290 volume->SetSensitiveDetector(aHadIntAndEdepTrkSD);
291 std::cout <<
"Attaching sensitive Detector: " << aux.value
292 <<
" to Volume: " << volume->GetName() <<
"\n";
293 detectors_.emplace_back(volume->GetName(), aux.value);
298 <<
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
300 if (
dumpMP_) { G4cout << *(G4Material::GetMaterialTable()) << G4endl; }
302 std::cout <<
"List SD Tree: \n";
304 std::cout <<
" Collection Capacity: " << SDman->GetCollectionCapacity() <<
"\n";
305 G4HCtable* hctable = SDman->GetHCtable();
306 for (G4int j = 0; j < SDman->GetCollectionCapacity(); ++j) {
307 std::cout <<
"HC Name: " << hctable->GetHCname(j) <<
" SD Name: " << hctable->GetSDname(j)
310 std::cout <<
"==================================================\n";
312 std::vector<G4LogicalVolume*> myLVvec;
313 myLVvec.push_back(pLVStore->at(0));
314 std::cout <<
"nr of LV ======================: " << myLVvec.size() <<
"\n";
320 std::vector<G4LogicalVolume*>)
323 std::vector<G4VPhysicalVolume*> myPVvec;
324 G4PhysicalVolumeStore* pPVStore = G4PhysicalVolumeStore::GetInstance();
325 myPVvec.push_back(pPVStore->at(
326 pPVStore->size() - 1));
337 <<
"Setting step limits from configuration" 338 <<
" file. This will OVERRIDE redundant stepLimit(s) set in the GDML file. Note" 339 <<
" that stepLimits are only active if enabled in the physicsListService via the" 340 <<
" appropriate parameter.";
342 std::string volumeName =
"";
343 G4LogicalVolume* setVol =
nullptr;
345 G4double previousStepLimit = 0.;
348 if (setVol = G4LogicalVolumeStore::GetInstance()->GetVolume(name,
false); !setVol) {
350 <<
"Provided volume name : " << name <<
" not found!\n";
354 volumeName = setVol->GetName();
356 <<
"Got logical volume with name: " << volumeName;
358 G4UserLimits* fStepLimitOverride =
new G4UserLimits();
359 G4AutoDelete::Register(fStepLimitOverride);
364 previousStepLimit = (G4double)(search->second);
365 if (newStepLimit != previousStepLimit) {
367 <<
"OVERRIDING PREVIOUSLY SET" 368 <<
" STEPLIMIT FOR VOLUME : " << volumeName <<
" FROM " << previousStepLimit <<
" mm TO " 369 << newStepLimit <<
" mm";
373 <<
"New stepLimit matches previously" 374 <<
" set stepLimit from the GDML file for volume : " << volumeName
375 <<
" stepLimit : " << newStepLimit <<
" mm. Nothing will be changed.";
380 fStepLimitOverride->SetMaxAllowedStep(newStepLimit);
382 <<
"fStepLimitOverride: " << newStepLimit / CLHEP::mm <<
" mm " << newStepLimit / CLHEP::cm
384 <<
"for volume: " << volumeName <<
"\n" 385 <<
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
386 setVol->SetUserLimits(fStepLimitOverride);
392 return myName() + volume_name;
398 for (
auto const& [volume_name, sd_name] :
detectors_) {
399 if (sd_name ==
"DRCalorimeter") {
405 else if (sd_name ==
"Calorimeter") {
408 else if (sd_name ==
"PhotonDetector") {
411 else if (sd_name ==
"Tracker") {
414 else if (sd_name ==
"SimEnergyDeposit") {
417 else if (sd_name ==
"AuxDet") {
420 else if (sd_name ==
"HadInteraction") {
423 else if (sd_name ==
"HadIntAndEdepTrk") {
425 collector.
produces<artg4tk::TrackerHitCollection>();
436 G4SDManager* sdman = G4SDManager::GetSDMpointer();
443 for (
auto const& [volume_name, sd_name] :
detectors_) {
444 auto sd = sdman->FindSensitiveDetector(volume_name +
"_" + sd_name);
445 if (sd_name ==
"HadInteraction") {
446 if (
auto hisd = dynamic_cast<artg4tk::HadInteractionSD*>(sd)) {
447 if (
auto const& inter = hisd->Get1stInteraction(); inter.GetNumOutcoming() > 0) {
448 e.
put(make_product(inter));
453 else if (sd_name ==
"HadIntAndEdepTrk") {
454 if (
auto trksd = dynamic_cast<artg4tk::HadIntAndEdepTrkSD*>(sd)) {
455 if (
auto const& inter = trksd->Get1stInteraction(); inter.GetNumOutcoming() > 0) {
456 e.
put(make_product(inter));
458 if (
auto const& trkhits = trksd->GetEdepTrkHits(); !trkhits.empty()) {
459 e.
put(make_product(trkhits));
464 else if (sd_name ==
"Tracker") {
465 auto trsd =
dynamic_cast<artg4tk::TrackerSD*
>(sd);
468 else if (sd_name ==
"SimEnergyDeposit") {
473 for (
auto&
hit : hitCollection) {
474 hit.setTrackID(tmap[
hit.TrackID()]);
479 else if (sd_name ==
"AuxDet") {
480 auto auxsd =
dynamic_cast<AuxDetSD*
>(sd);
484 for (
auto&
hit : hitCollection) {
485 hit.SetTrackID(tmap[
hit.GetTrackID()]);
490 else if (sd_name ==
"Calorimeter") {
491 auto calsd =
dynamic_cast<artg4tk::CalorimeterSD*
>(sd);
494 else if (sd_name ==
"DRCalorimeter") {
495 auto drcalsd =
dynamic_cast<artg4tk::DRCalorimeterSD*
>(sd);
497 e.
put(make_product(drcalsd->GetHits()), identifier);
498 e.
put(make_product(drcalsd->GetEbyParticle()), identifier +
"Edep");
499 e.
put(make_product(drcalsd->GetNCerenbyParticle()), identifier +
"NCeren");
501 else if (sd_name ==
"PhotonDetector") {
502 auto phsd =
dynamic_cast<artg4tk::PhotonSD*
>(sd);
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::vector< G4LogicalVolume * > doBuildLVs() override
void doCallArtProduces(art::ProducesCollector &collector) override
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_
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
std::string const & myName() const
void produces(std::string const &instanceName={}, Persistable const persistable=Persistable::Yes)
bool updateSimEnergyDeposits_
Use Geant4's user "hooks" to maintain a list of particles generated by Geant4.
T get(std::string const &key) const
const sim::SimEnergyDepositCollection & GetHits() const
volt_as<> volt
Type of potential stored in volts, in double precision.
std::vector< std::string > volumeNames_
CommandLineParser * parser(0)
std::vector< G4VPhysicalVolume * > doPlaceToPVs(std::vector< G4LogicalVolume * >) override
std::vector< float > stepLimits_
Detector simulation of raw signals on wires.
std::vector< AuxDetHit > AuxDetHitCollection
std::map< int, int > GetTargetIDMap()
art::Event & getCurrArtEvent()
std::vector< SimEnergyDeposit > SimEnergyDepositCollection
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
contains information for a single step in the detector simulation
#define MF_LOG_WARNING(category)
const sim::AuxDetHitCollection & GetHits() const
std::map< std::string, G4double > overrideGDMLStepLimit_Map
std::unordered_map< std::string, float > setGDMLVolumes_
cet::coded_exception< error, detail::translate > exception