File indexing completed on 2025-01-30 09:17:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/Detector.h>
0016 #include <DD4hep/Printout.h>
0017 #include <DD4hep/DetFactoryHelper.h>
0018 #include <XML/Conversions.h>
0019 #include <DDG4/Geant4Config.h>
0020
0021
0022 namespace dd4hep {
0023
0024
0025 class ActionSequence;
0026 using namespace dd4hep::sim;
0027 using namespace dd4hep::sim::Setup;
0028
0029
0030 namespace sim {
0031
0032
0033 class XMLSetup;
0034
0035
0036 template <typename TYPE, typename PTR> TYPE* _action(PTR* in) {
0037 return dynamic_cast<TYPE*>(in);
0038 }
0039
0040
0041 template <typename T> static void installMessenger(const T& handle) {
0042 handle->installMessengers();
0043 }
0044
0045
0046 template <typename T> static void _setAttributes(const T& handle, xml_h& e) {
0047 xml::Handle_t props(e);
0048
0049 std::vector<xml::Attribute> attrs = props.attributes();
0050 for(std::vector<xml::Attribute>::iterator i=attrs.begin(); i!=attrs.end(); ++i) {
0051 xml::Attribute a = *i;
0052 handle[xml::_toString(props.attr_name(a))].str(props.attr<std::string>(a));
0053 }
0054 }
0055
0056
0057 template <typename T> static void _setProperties(const T& handle, xml_h& e) {
0058 xml_comp_t action(e);
0059
0060 xml::Handle_t props = action.child(_Unicode(properties),false);
0061 if ( props ) {
0062 _setAttributes(handle, props);
0063 }
0064 if ( action.hasAttr(_Unicode(Control)) ) {
0065 handle["Control"].str(props.attr<std::string>(_Unicode(Control)));
0066 }
0067 }
0068
0069
0070 static Action _convertSensitive(Detector& description, xml_h e, const std::string& detector) {
0071 xml_comp_t action(e);
0072 Kernel& kernel = Kernel::instance(description);
0073 TypeName tn = TypeName::split(action.attr<std::string>(_U(name)));
0074
0075 Sensitive handle(kernel,action.attr<std::string>(_U(name)),detector);
0076 _setProperties(Action(handle.get()),e);
0077 for(xml_coll_t f(e,_Unicode(filter)); f; ++f) {
0078 std::string nam = f.attr<std::string>(_U(name));
0079 Filter filter(kernel.globalFilter(nam,false));
0080 handle->adopt(filter);
0081 }
0082 installMessenger(handle);
0083 printout(INFO,"Geant4Setup","+++ Added sensitive element %s of type %s",
0084 tn.second.c_str(),tn.first.c_str());
0085 return Action(handle);
0086 }
0087
0088
0089 static Action _convertAction(Detector& description, xml_h e) {
0090 xml_comp_t action(e);
0091 Kernel& kernel = Kernel::instance(description);
0092 TypeName tn = TypeName::split(action.attr<std::string>(_U(name)));
0093
0094 Action handle(kernel,action.attr<std::string>(_U(name)));
0095 _setProperties(handle,e);
0096 printout(INFO,"Geant4Setup","+++ Added action %s of type %s",tn.second.c_str(),tn.first.c_str());
0097 installMessenger(handle);
0098
0099 if ( action.hasChild(_Unicode(adopt)) ) {
0100 xml_comp_t child = action.child(_Unicode(adopt));
0101 Geant4Action* user = kernel.globalAction(child.nameStr());
0102 Geant4ParticleHandler* ph = dynamic_cast<Geant4ParticleHandler*>(handle.get());
0103 if ( ph ) {
0104 ph->adopt(user);
0105 }
0106 }
0107 return handle;
0108 }
0109
0110 enum { SENSITIVE, ACTION, FILTER };
0111
0112 Action _createAction(Detector& description, xml_h a, const std::string& seqType, int what) {
0113 std::string nam = a.attr<std::string>(_U(name));
0114 TypeName typ = TypeName::split(nam);
0115 Kernel& kernel = Kernel::instance(description);
0116 Action action((what==FILTER) ? (Geant4Action*)kernel.globalFilter(typ.second,false)
0117 : (what==ACTION) ? kernel.globalAction(typ.second,false)
0118
0119 : 0);
0120
0121 if ( !action ) {
0122 action = (what == SENSITIVE) ? Action(_convertSensitive(description, a, seqType))
0123 : (what==ACTION) ? _convertAction(description, a)
0124 : (what==FILTER) ? _convertAction(description, a)
0125 : Action();
0126 if ( !action ) {
0127 except("Geant4ActionSequence",
0128 "DDG4: The action '%s' cannot be created. [Action-Missing]",nam.c_str());
0129 }
0130 }
0131 return action;
0132 }
0133 }
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145 template <> void Converter<Action>::operator()(xml_h e) const {
0146 Action a = _convertAction(description, e);
0147 Kernel::instance(description).registerGlobalAction(a);
0148 }
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 template <> void Converter<Filter>::operator()(xml_h e) const {
0162 Action a = _convertAction(description, e);
0163 Kernel::instance(description).registerGlobalFilter(a);
0164 }
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176 template <> void Converter<Phase>::operator()(xml_h e) const {
0177 xml_comp_t x_phase(e);
0178 Kernel& kernel = Kernel::instance(description);
0179 std::string nam = x_phase.attr<std::string>(_U(type));
0180 typedef Geant4ActionPhase PH;
0181 Phase p;
0182
0183 if ( nam == "RunAction/begin" ) {
0184 void (Geant4ActionPhase::*func)(const G4Run*) = &Geant4ActionPhase::call;
0185 kernel.runAction().callAtBegin((p=kernel.addPhase<const G4Run*>(nam)).get(),func);
0186
0187 }
0188 else if ( nam == "RunAction/end" ) {
0189 void (Geant4ActionPhase::*func)(const G4Run*) = &Geant4ActionPhase::call;
0190 kernel.runAction().callAtEnd((p=kernel.addPhase<const G4Run*>(nam)).get(),func);
0191
0192 }
0193 else if ( nam == "EventAction/begin" ) {
0194 void (Geant4ActionPhase::*func)(const G4Event*) = &Geant4ActionPhase::call;
0195 kernel.eventAction().callAtBegin((p=kernel.addPhase<const G4Event*>(nam)).get(),func);
0196
0197 }
0198 else if ( nam == "EventAction/end" ) {
0199 void (Geant4ActionPhase::*func)(const G4Event*) = &Geant4ActionPhase::call;
0200 kernel.eventAction().callAtEnd((p=kernel.addPhase<const G4Event*>(nam)).get(),func);
0201
0202 }
0203 else if ( nam == "TrackingAction/begin" ) {
0204 void (Geant4ActionPhase::*func)(const G4Track*) = &Geant4ActionPhase::call;
0205 kernel.trackingAction().callAtBegin((p=kernel.addPhase<const G4Track*>(nam)).get(),func);
0206
0207 }
0208 else if ( nam == "TrackingAction/end" ) {
0209 void (Geant4ActionPhase::*func)(const G4Track*) = &Geant4ActionPhase::call;
0210 kernel.trackingAction().callAtEnd((p=kernel.addPhase<const G4Track*>(nam,false)).get(),func);
0211
0212 }
0213 else if ( nam == "StackingAction/newStage" ) {
0214 kernel.stackingAction().callAtNewStage((p=kernel.addPhase<void>(nam,false)).get(),&PH::call);
0215 }
0216 else if ( nam == "StackingAction/prepare" ) {
0217 kernel.stackingAction().callAtPrepare((p=kernel.addPhase<void>(nam,false)).get(),&PH::call);
0218 }
0219 else if ( nam == "SteppingAction" ) {
0220 void (Geant4ActionPhase::*func)(const G4Step*,G4SteppingManager*) = &Geant4ActionPhase::call;
0221 kernel.steppingAction().call((p=kernel.addPhase<const G4Step*>(nam)).get(),func);
0222
0223 }
0224 else if ( nam == "GeneratorAction/primaries" ) {
0225 void (Geant4ActionPhase::*func)(G4Event*) = &Geant4ActionPhase::call;
0226 kernel.generatorAction().call((p=kernel.addPhase<G4Event*>(nam)).get(),func);
0227
0228 }
0229 else {
0230 TypeName tn = TypeName::split(nam);
0231 DetElement det = description.detector(tn.first);
0232 if ( !det.isValid() ) {
0233 except("Phase","DDG4: The phase '%s' of type SensitiveSeq"
0234 " cannot be attached to a non-existing detector"
0235 " [Detector-Missing]",nam.c_str());
0236 }
0237
0238 SensitiveDetector sd = description.sensitiveDetector(tn.first);
0239 if ( !sd.isValid() ) {
0240 except("Phase","DDG4: The phase '%s' of type SensitiveSeq"
0241 " cannot be attached to a non-existing sensitive detector"
0242 " [Sensitive-Missing]",nam.c_str());
0243 }
0244 SensitiveSeq sdSeq = SensitiveSeq(kernel,tn.first);
0245 if ( tn.second == "begin" )
0246 sdSeq->callAtBegin((p=kernel.addPhase<G4HCofThisEvent*>(tn.second)).get(),
0247 &PH::call<G4HCofThisEvent*>);
0248 else if ( tn.second == "end" )
0249 sdSeq->callAtEnd((p=kernel.addPhase<G4HCofThisEvent*>(tn.second)).get(),
0250 &PH::call<G4HCofThisEvent*>);
0251 else if ( tn.second == "clear" )
0252 sdSeq->callAtClear((p=kernel.addPhase<G4HCofThisEvent*>(tn.second)).get(),
0253 &PH::call<G4HCofThisEvent*>);
0254 else if ( tn.second == "process" )
0255 sdSeq->callAtProcess((p=kernel.addPhase<G4Step*>(tn.second)).get(),
0256 &PH::call<G4Step*,G4TouchableHistory*>);
0257 else
0258 except("Phase","DDG4: The phase '%s' of type SensitiveSeq"
0259 " cannot be attached to the call '%s'."
0260 " [Callback-Missing]",tn.first.c_str(), tn.second.c_str());
0261 }
0262 }
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279 template <> void Converter<ActionSequence>::operator()(xml_h e) const {
0280 xml_comp_t seq(e);
0281 SensitiveSeq sdSeq;
0282 std::string seqNam;
0283 TypeName seqType;
0284 int what = ACTION;
0285 Kernel& kernel = Kernel::instance(description);
0286
0287 if ( seq.hasAttr(_U(sd)) ) {
0288 std::string sd_nam = seq.attr<std::string>(_U(sd));
0289 SensitiveDetector sensitive = description.sensitiveDetector(sd_nam);
0290 seqNam = seq.attr<std::string>(_U(type))+"/"+sd_nam;
0291 if ( !sensitive.isValid() ) {
0292 printout(ALWAYS,"Geant4Setup","+++ ActionSequence %s is defined, "
0293 "but no sensitive detector present.",seqNam.c_str());
0294 printout(ALWAYS,"Geant4Setup","+++ ---> Sequence for detector %s IGNORED on popular request!",
0295 sd_nam.c_str());
0296 return;
0297 }
0298 seqType = TypeName::split(seqNam);
0299 sdSeq = SensitiveSeq(kernel,seqNam);
0300 what = SENSITIVE;
0301 }
0302 else {
0303 seqNam = seq.attr<std::string>(_U(name));
0304 seqType = TypeName::split(seqNam);
0305 }
0306 printout(INFO,"Geant4Setup","+++ ActionSequence %s of type %s added.",
0307 seqType.second.c_str(),seqType.first.c_str());
0308
0309 if ( seqType.second == "PhysicsList" ) {
0310 PhysicsActionSeq pl(&kernel.physicsList());
0311 PropertyManager& props = kernel.physicsList().properties();
0312 props.dump();
0313 _setAttributes(pl,e);
0314 props.dump();
0315 }
0316
0317 for(xml_coll_t a(seq,_Unicode(action)); a; ++a) {
0318 std::string nam = a.attr<std::string>(_U(name));
0319 Action action(_createAction(description,a,seqType.second,what));
0320 if ( seqType.second == "RunAction" )
0321 kernel.runAction().adopt(_action<Geant4RunAction>(action.get()));
0322 else if ( seqType.second == "EventAction" )
0323 kernel.eventAction().adopt(_action<Geant4EventAction>(action.get()));
0324 else if ( seqType.second == "GeneratorAction" )
0325 kernel.generatorAction().adopt(_action<Geant4GeneratorAction>(action.get()));
0326 else if ( seqType.second == "TrackingAction" )
0327 kernel.trackingAction().adopt(_action<Geant4TrackingAction>(action.get()));
0328 else if ( seqType.second == "StackingAction" )
0329 kernel.stackingAction().adopt(_action<Geant4StackingAction>(action.get()));
0330 else if ( seqType.second == "SteppingAction" )
0331 kernel.steppingAction().adopt(_action<Geant4SteppingAction>(action.get()));
0332 else if ( seqType.second == "PhysicsList" )
0333 kernel.physicsList().adopt(_action<Geant4PhysicsList>(action.get()));
0334 else if ( sdSeq.get() )
0335 sdSeq->adopt(_action<Geant4Sensitive>(action.get()));
0336 else {
0337 except("ActionSequence","DDG4: The action '%s'"
0338 " cannot be attached to any sequence '%s'."
0339 " [Sequence-Missing]",nam.c_str(), seqNam.c_str());
0340 }
0341 printout(INFO,"Geant4Setup","+++ ActionSequence %s added filter object:%s",
0342 seqType.second.c_str(),action->name().c_str());
0343 }
0344 if ( what == SENSITIVE ) {
0345 for(xml_coll_t a(seq,_Unicode(filter)); a; ++a) {
0346 std::string nam = a.attr<std::string>(_U(name));
0347 Action action(_createAction(description,a,"",FILTER));
0348 installMessenger(action);
0349 printout(INFO,"Geant4Setup","+++ ActionSequence %s added filter object:%s",
0350 seqType.second.c_str(),action->name().c_str());
0351 if ( sdSeq.get() )
0352 sdSeq->adopt(_action<Geant4Filter>(action.get()));
0353 else {
0354 except("ActionSequence","DDG4: The action '%s'"
0355 " cannot be attached to any sequence '%s'."
0356 " [Sequence-Missing]",nam.c_str(), seqNam.c_str());
0357 }
0358 }
0359 }
0360 }
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373 template <> void Converter<Geant4PhysicsList::ParticleProcesses>::operator()(xml_h e) const {
0374 xml_comp_t part(e);
0375 std::string part_name = part.nameStr();
0376 Geant4PhysicsList::ParticleProcesses& procs =
0377 _object<Geant4PhysicsList>().processes(part_name);
0378 for(xml_coll_t q(part,_Unicode(process)); q; ++q) {
0379 xml_comp_t proc(q);
0380 Geant4PhysicsList::Process p;
0381 p.name = proc.nameStr();
0382 p.ordAtRestDoIt = proc.attr<int>(_Unicode(ordAtRestDoIt));
0383 p.ordAlongSteptDoIt = proc.attr<int>(_Unicode(ordAlongSteptDoIt));
0384 p.ordPostStepDoIt = proc.attr<int>(_Unicode(ordPostStepDoIt));
0385 procs.emplace_back(p);
0386 printout(INFO,"Geant4Setup","+++ Converter<ParticleProcesses: Particle:%s add process %s %d %d %d",
0387 part_name.c_str(),p.name.c_str(),p.ordAtRestDoIt,p.ordAlongSteptDoIt,p.ordPostStepDoIt);
0388 }
0389 }
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403 template <> void Converter<Geant4PhysicsList::ParticleConstructor>::operator()(xml_h e) const {
0404 Geant4PhysicsList::ParticleConstructors& parts = _object<Geant4PhysicsList>().particles();
0405 xml_comp_t part(e);
0406 std::string n = part.nameStr();
0407 parts.emplace_back(n);
0408 printout(INFO,"Geant4Setup","+++ ParticleConstructor: Add Geant4 particle constructor '%s'",n.c_str());
0409 }
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420 template <> void Converter<Geant4PhysicsList::PhysicsConstructor>::operator()(xml_h e) const {
0421 Geant4PhysicsList::PhysicsConstructors& parts = _object<Geant4PhysicsList>().physics();
0422 xml_comp_t part(e);
0423 std::string n = part.nameStr();
0424 parts.emplace_back(n);
0425 printout(INFO,"Geant4Setup","+++ PhysicsConstructor: Add Geant4 physics constructor '%s'",n.c_str());
0426 }
0427
0428
0429
0430
0431
0432
0433
0434
0435 struct PhysicsListExtension;
0436 template <> void Converter<PhysicsListExtension>::operator()(xml_h e) const {
0437 Kernel& kernel = Kernel::instance(description);
0438 std::string ext = xml_comp_t(e).nameStr();
0439 kernel.physicsList().properties()["extends"].str(ext);
0440 printout(INFO,"Geant4Setup","+++ PhysicsListExtension: Set predefined Geant4 physics list to '%s'",ext.c_str());
0441 }
0442
0443
0444 template <> void Converter<PhysicsList>::operator()(xml_h e) const {
0445 std::string name = e.attr<std::string>(_U(name));
0446 Kernel& kernel = Kernel::instance(description);
0447 PhysicsList handle(kernel,name);
0448 _setAttributes(handle,e);
0449 xml_coll_t(e,_Unicode(particles)).for_each(_Unicode(construct),Converter<Geant4PhysicsList::ParticleConstructor>(description,handle.get()));
0450 xml_coll_t(e,_Unicode(processes)).for_each(_Unicode(particle),Converter<Geant4PhysicsList::ParticleProcesses>(description,handle.get()));
0451 xml_coll_t(e,_Unicode(physics)).for_each(_Unicode(construct),Converter<Geant4PhysicsList::PhysicsConstructor>(description,handle.get()));
0452 xml_coll_t(e,_Unicode(extends)).for_each(Converter<PhysicsListExtension>(description,handle.get()));
0453 kernel.physicsList().adopt(handle);
0454 }
0455
0456
0457 template <> void Converter<Kernel>::operator()(xml_h e) const {
0458 Kernel& kernel = Kernel::instance(description);
0459 xml_comp_t k(e);
0460 if ( k.hasAttr(_Unicode(NumEvents)) )
0461 kernel.property("NumEvents").str(k.attr<std::string>(_Unicode(NumEvents)));
0462 if ( k.hasAttr(_Unicode(UI)) )
0463 kernel.property("UI").str(k.attr<std::string>(_Unicode(UI)));
0464 }
0465
0466
0467 template <> void Converter<XMLSetup>::operator()(xml_h seq) const {
0468 xml_elt_t compact(seq);
0469
0470 long result = PluginService::Create<long>("geant4_XML_reader",&description,&seq);
0471 if ( 0 == result ) {
0472 except("PhysicsList", "dd4hep: Failed to locate plugin to interprete files of type"
0473 " \"" + seq.tag() + "\" - no factory of type geant4_XML_reader.");
0474 }
0475 result = *(long*) result;
0476 if (result != 1) {
0477 except("PhysicsList", "dd4hep: Failed to parse the XML tag %s with the plugin geant4_XML_reader", seq.tag().c_str());
0478 }
0479 xml_coll_t(compact,_Unicode(kernel)).for_each(Converter<Kernel>(description,param));
0480
0481 xml_coll_t(compact,_Unicode(actions) ).for_each(_Unicode(action),Converter<Action>(description,param));
0482 xml_coll_t(compact,_Unicode(filters) ).for_each(_Unicode(filter),Converter<Filter>(description,param));
0483 xml_coll_t(compact,_Unicode(sequences) ).for_each(_Unicode(sequence),Converter<ActionSequence>(description,param));
0484 xml_coll_t(compact,_Unicode(phases) ).for_each(_Unicode(phase),Converter<Phase>(description,param));
0485 xml_coll_t(compact,_Unicode(physicslist)).for_each(Converter<PhysicsList>(description,param));
0486 }
0487 }
0488
0489
0490 static long setup_Geant4(dd4hep::Detector& description, const xml_h& element) {
0491 (dd4hep::Converter<dd4hep::sim::XMLSetup>(description))(element);
0492 return 1;
0493 }
0494
0495 DECLARE_XML_DOC_READER(geant4_setup,setup_Geant4)