diff --git a/DDG4/CMakeLists.txt b/DDG4/CMakeLists.txt index 6affa3857d1c47c3b867233cc31c58c9475bdac0..310f08b6dd7ea0703ffb6bd902d961fe9788fa1c 100644 --- a/DDG4/CMakeLists.txt +++ b/DDG4/CMakeLists.txt @@ -8,7 +8,6 @@ find_package(Geant4 REQUIRED gdml ui_all vis_all) #endif() INCLUDE(${Geant4_USE_FILE}) # this also takes care of geant 4 definitions and include dirs - include(DD4hep_XML_setup) #---Includedirs------------------------------------------------------------------- @@ -20,16 +19,22 @@ include_directories(${CMAKE_SOURCE_DIR}/DDCore/include ${Geant4_INCLUDE_DIRS}) #---Add Library------------------------------------------------------------------- -file(GLOB sources src/*.cpp) +if(DD4HEP_USE_BOOST) + list(APPEND include_directories ${BOOST_INCLUDE_DIR}) + file(GLOB sources src/*.cpp parsers/*.cpp) + add_definitions(-DDD4HEP_USE_BOOST) +else() + file(GLOB sources src/*.cpp) +endif() + if(NOT DD4HEP_USE_XERCESC) list(REMOVE_ITEM sources ${CMAKE_CURRENT_SOURCE_DIR}/src/Geant4XML.cpp) endif() + add_library(DD4hepG4 SHARED ${sources}) target_link_libraries(DD4hepG4 DD4hepCore ${ROOT_LIBRARIES} Reflex ${Geant4_LIBRARIES}) SET_TARGET_PROPERTIES( DD4hepG4 PROPERTIES VERSION ${DD4hep_VERSION} SOVERSION ${DD4hep_SOVERSION}) - - if(APPLE) dd4hep_generate_rootmap_apple(DD4hepG4) else() @@ -39,6 +44,9 @@ endif() #----------------------------------------------------------------------------------- add_executable(g4gdmlDisplay g4gdmlDisplay.cpp) target_link_libraries(g4gdmlDisplay DD4hepG4 DD4hepCore) +#----------------------------------------------------------------------------------- +add_executable(g4FromXML g4FromXML.cpp) +target_link_libraries(g4FromXML DD4hepG4 DD4hepCore) #--- install target------------------------------------- install(DIRECTORY include/DDG4 @@ -49,5 +57,10 @@ install(TARGETS DD4hepG4 g4gdmlDisplay RUNTIME DESTINATION bin LIBRARY DESTINATION lib ) + +install(TARGETS DD4hepG4 g4FromXML + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ) # to do: add corresponding uninstall... #------------------------------------------------------- diff --git a/DDG4/examples/README.txt b/DDG4/examples/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..09d38c9748d9843bceff0a05a1b2e208b5ec595b --- /dev/null +++ b/DDG4/examples/README.txt @@ -0,0 +1,14 @@ +DDG4 setup +---------- + +Starting Geant4 as ROTO AClick +------------------------------ +- First adapt the initAClick script to fit your include/library pathes +- load the script in root: .x initAClick.C +- Then start the configuration in compiled mode in ROOT + .L exampleAClick.C+ + or + .L xmlAClick.C+ + +Note: these are examples only and do not necessarily produce +meaningful results. diff --git a/DDG4/examples/exampleAClick.C b/DDG4/examples/exampleAClick.C new file mode 100644 index 0000000000000000000000000000000000000000..06340d54f1bf55ffead1a93d7d59e41eabb1ad93 --- /dev/null +++ b/DDG4/examples/exampleAClick.C @@ -0,0 +1,90 @@ +#include "DDG4/Geant4Config.h" +#include "DDG4/Geant4TestActions.h" +#include "DDG4/Geant4TrackHandler.h" +#include <iostream> + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Simulation; +using namespace DD4hep::Simulation::Test; +using namespace DD4hep::Simulation::Setup; + +#if defined(__MAKECINT__) +#pragma link C++ class Geant4RunActionSequence; +#pragma link C++ class Geant4EventActionSequence; +#pragma link C++ class Geant4SteppingActionSequence; +#pragma link C++ class Geant4StackingActionSequence; +#pragma link C++ class Geant4GeneratorActionSequence; +#pragma link C++ class Geant4Action; +#pragma link C++ class Geant4Kernel; +#endif + +SensitiveSeq::handled_type* setupDetector(Kernel& kernel, const std::string& name) { + SensitiveSeq sd = SensitiveSeq(kernel,name); + Sensitive sens = Sensitive(kernel,"Geant4TestSensitive/"+name+"Handler",name); + sd->adopt(sens); + sens = Sensitive(kernel,"Geant4TestSensitive/"+name+"Monitor",name); + sd->adopt(sens); + return sd; +} + +void setupG4_CINT() { + Geant4Kernel& kernel = Geant4Kernel::instance(LCDD::getInstance()); + + Phase p; + kernel.loadGeometry("file:../DD4hep.trunk/DDExamples/CLICSiD/compact/compact.xml"); + kernel.loadXML("../geant4/sensitive_detectors.xml"); + + GenAction gun(kernel,"Geant4ParticleGun/Gun"); + gun["energy"] = 0.5*GeV; + gun["particle"] = "e-"; + gun["multiplicity"] = 1; + kernel.generatorAction().adopt(gun); + + Action run_init(kernel,"Geant4TestRunAction/RunInit"); + run_init["Property_int"] = 12345; + kernel.runAction().callAtBegin (run_init.get(),&Geant4TestRunAction::begin); + kernel.eventAction().callAtBegin(run_init.get(),&Geant4TestRunAction::beginEvent); + kernel.eventAction().callAtEnd (run_init.get(),&Geant4TestRunAction::endEvent); + + Action evt_1(kernel,"Geant4TestEventAction/UserEvent_1"); + evt_1["Property_int"] = 12345; + evt_1["Property_string"] = "Events"; + + p = kernel.addPhase<const G4Run*>("BeginRun"); + p->add(evt_1.get(),&Geant4TestEventAction::beginRun); + kernel.runAction().callAtBegin(p.get(),&Geant4ActionPhase::call<const G4Run*>); + + p = kernel.addPhase<const G4Run*>("EndRun"); + p->add(evt_1.get(),&Geant4TestEventAction::endRun); + kernel.runAction().callAtEnd(p.get(),&Geant4ActionPhase::call<const G4Run*>); + + EventAction evt_2(kernel,"Geant4TestEventAction/UserEvent_2"); + kernel.eventAction().adopt(evt_2); + + setupDetector(kernel,"SiVertexBarrel"); + setupDetector(kernel,"SiVertexEndcap"); + setupDetector(kernel,"SiTrackerBarrel"); + setupDetector(kernel,"SiTrackerEndcap"); + setupDetector(kernel,"SiTrackerForward"); + setupDetector(kernel,"EcalBarrel"); + setupDetector(kernel,"EcalEndcap"); + setupDetector(kernel,"HcalBarrel"); + setupDetector(kernel,"HcalEndcap"); + setupDetector(kernel,"HcalPlug"); + setupDetector(kernel,"MuonBarrel"); + setupDetector(kernel,"MuonEndcap"); + setupDetector(kernel,"LumiCal"); + setupDetector(kernel,"BeamCal"); + + kernel.configure(); + kernel.initialize(); + kernel.run(); + std::cout << "Successfully executed application .... " << std::endl; + kernel.terminate(); +} + +void exampleAClick() { + setupG4_CINT(); +} + diff --git a/DDG4/examples/initAClick.C b/DDG4/examples/initAClick.C new file mode 100644 index 0000000000000000000000000000000000000000..44fb3ed015493b020331360dbb603b71f4d24d88 --- /dev/null +++ b/DDG4/examples/initAClick.C @@ -0,0 +1,24 @@ +#include "TSystem.h" +#include <iostream> +#include <string> + +using namespace std; + +void init() { + string base = gSystem->Getenv("SW"); + string inc = " -I"+base+"/DD4hep/DD4hep.trunk/"; + gSystem->AddIncludePath((inc + "DDSegmentation/include ").c_str()); + gSystem->AddIncludePath((inc + "DDCore/include ").c_str()); + gSystem->AddIncludePath((inc + "DDG4/include ").c_str()); + gSystem->AddIncludePath((" -I" + base + "/geant4/include/Geant4 -Wno-shadow -g -O0 ").c_str()); + string lib = " -L"+base+"/"; + gSystem->AddLinkedLibs((lib+"geant4/lib -lG4event -lG4tracking -lG4particles ").c_str()); + gSystem->AddLinkedLibs((lib+"DD4hep/build/lib -lDD4hepCore -lDD4hepG4 -lDDSegmentation ").c_str()); + cout << "Includes: " << gSystem->GetIncludePath() << endl; + cout << "Linked libs:" << gSystem->GetLinkedLibs() << endl; +} + +void initAClick() { + init(); +} + diff --git a/DDG4/examples/physics.xml b/DDG4/examples/physics.xml new file mode 100644 index 0000000000000000000000000000000000000000..098ba7340d6d993250f5ec1883eaf5b69bbedf4f --- /dev/null +++ b/DDG4/examples/physics.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> +<geant4_setup> + + <!-- Definition of the physics list. + -- + -- Ordering values: + -- ordInActive = -1, // ordering parameter to indicate InActive DoIt + -- ordDefault = 1000, // default ordering parameter + -- ordLast = 9999 // ordering parameter to indicate the last DoIt + --> + <!-- + <sequences> + <sequence name="Geant4PhysicsListSequence/PhysicsList" transportation="true" decays="true"/> + </sequences> + + <physicslist name="Geant4PhysicsList/MyPhysics.0"> + <particles> + <construct name="G4Geantino"/> + <construct name="G4ChargedGeantino"/> + <construct name="G4Electron"/> + <construct name="G4Gamma"/> + <construct name="G4BosonConstructor"/> + <construct name="G4LeptonConstructor"/> + <construct name="G4MesonConstructor"/> + <construct name="G4BaryonConstructor"/> + </particles> + + <physics> + <construct name="G4EmStandardPhysics"/> + <construct name="HadronPhysicsQGSP"/> + </physics> + + <processes> + <particle name="gamma"> + </particle> + + <particle name="e[+-]" cut="1*mm"> + <process name="G4eMultipleScattering" ordAtRestDoIt="-1" ordAlongSteptDoIt="1" ordPostStepDoIt="1"/> + <process name="G4eIonisation" ordAtRestDoIt="-1" ordAlongSteptDoIt="2" ordPostStepDoIt="2"/> + </particle> + + <particle name="mu[+-]"> + <process name="G4MuMultipleScattering" ordAtRestDoIt="-1" ordAlongSteptDoIt="1" ordPostStepDoIt="1"/> + <process name="G4MuIonisation" ordAtRestDoIt="-1" ordAlongSteptDoIt="2" ordPostStepDoIt="2"/> + </particle> + + <particle name="pi[+-]"> + <process name="G4hMultipleScattering" ordAtRestDoIt="-1" ordAlongSteptDoIt="1" ordPostStepDoIt="1"/> + <process name="G4hIonisation" ordAtRestDoIt="-1" ordAlongSteptDoIt="2" ordPostStepDoIt="2"/> + </particle> + </processes> + </physicslist> + + <physicslist name="Geant4PhysicsList/MyPhysics.0"> + <physics> + <construct name="G4EmStandardPhysics"/> + </physics> + </physicslist> + --> + +</geant4_setup> diff --git a/DDG4/examples/sensitive_detectors.xml b/DDG4/examples/sensitive_detectors.xml new file mode 100644 index 0000000000000000000000000000000000000000..cfa19ea096509659c5c8c39710c3cc880b974d02 --- /dev/null +++ b/DDG4/examples/sensitive_detectors.xml @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="UTF-8"?> +<geant4_setup> + <sensitive_detectors> + <sd name="SiVertexBarrel" + type="Geant4SensDet" + ecut="10.0*MeV" + verbose="true" + hit_aggregation="position"> + </sd> + <sd name="SiVertexEndcap" + type="Geant4SensDet" + ecut="10.0*MeV" + verbose="true" + hit_aggregation="position"> + </sd> + <sd name="SiTrackerBarrel" + type="Geant4SensDet" + ecut="10.0*MeV" + verbose="true" + hit_aggregation="position"> + </sd> + <sd name="SiTrackerEndcap" + type="Geant4SensDet" + ecut="10.0*MeV" + verbose="true" + hit_aggregation="position"> + </sd> + <sd name="SiTrackerForward" + type="Geant4SensDet" + ecut="10.0*MeV" + verbose="true" + hit_aggregation="position"> + </sd> + <sd name="EcalBarrel" + type="Geant4SensDet" + ecut="100.0*MeV" + verbose="true" + hit_aggregation="position"> + </sd> + <sd name="EcalEndcap" + type="Geant4SensDet" + ecut="100.0*MeV" + verbose="true" + hit_aggregation="position"> + </sd> + <sd name="HcalBarrel" + type="Geant4SensDet" + ecut="100.0*MeV" + verbose="true" + hit_aggregation="position"> + </sd> + <sd name="HcalEndcap" + type="Geant4SensDet" + ecut="100.0*MeV" + verbose="true" + hit_aggregation="position"> + </sd> + <sd name="HcalPlug" + type="Geant4SensDet" + ecut="100.0*MeV" + verbose="true" + hit_aggregation="position"> + </sd> + <sd name="MuonBarrel" + type="Geant4SensDet" + ecut="100.0*MeV" + limits="cal_limits" + verbose="true" + hit_aggregation="position"> + </sd> + <sd name="MuonEndcap" + type="Geant4SensDet" + ecut="100.0*MeV" + verbose="true" + hit_aggregation="position"> + </sd> + <sd name="LumiCal" + type="Geant4SensDet" + ecut="100.0*MeV" + verbose="true" + hit_aggregation="position"> + </sd> + <sd name="BeamCal" + type="Geant4SensDet" + ecut="100.0*MeV" + verbose="true" + hit_aggregation="position"> + </sd> + </sensitive_detectors> + + <properties> + <attributes name="geant4_field" + id="0" + type="Geant4FieldSetup" + object="GlobalSolenoid" + global="true" + min_chord_step="0.01*mm" + delta_chord="0.25*mm" + delta_intersection="1e-05*mm" + delta_one_step="0.001*mm" + eps_min="5e-05*mm" + eps_max="0.001*mm" + stepper="HelixSimpleRunge" + equation="Mag_UsualEqRhs"> + </attributes> + </properties> + +</geant4_setup> diff --git a/DDG4/examples/sequences.xml b/DDG4/examples/sequences.xml new file mode 100644 index 0000000000000000000000000000000000000000..868360e00ae8b625ce3248841f8dd9238d008bd6 --- /dev/null +++ b/DDG4/examples/sequences.xml @@ -0,0 +1,150 @@ +<?xml version="1.0" encoding="UTF-8"?> +<geant4_setup> + + + + <!-- List of globally known actions. These actions will be registered with the Geant4Kernel + -- object and may be retrieved by there using the action name. + -- + -- Note: registered actions MUST be unique. + -- However, not all actions need to registered.... + -- Only register those, you later need to retrieve by name. + --> + <actions> + <action name="Geant4TestRunAction/RunInit"> + <properties Property_int="12345" + Property_double="-5e15" + Property_string="Startrun: Hello_2"/> + </action> + <action name="Geant4TestEventAction/UserEvent_2"> + <properties Property_int="1234" + Property_double="5e15" + Property_string="Hello_2"/> + </action> + </actions> + + <!-- List of known phases. + -- Note: Phases can only be attached to the program at very well defined moments, + -- which are explained in the documentation. + -- These are typically the "standard" moments: BeginRun, EndRun, BeginEvent, etc. + -- and the calls after processing the hits of each sensitive detector. + -- + --> + <phases> + <phase type="RunAction/begin"> + <action name="RunInit"/> + <action name="Geant4TestRunAction/UserRunInit"> + <properties Property_int="1234" + Property_double="5e15" + Property_string="'Hello_2'"/> + </action> + </phase> + <phase type="EventAction/begin"> + <action name="UserEvent_2"/> + </phase> + <phase type="EventAction/end"> + <action name="UserEvent_2"/> + </phase> + </phases> + + <!-- List of globally known filters. Filters are called by Geant4 before the + -- hit processing in the sensitive detectors start. The global filters + -- may be shared between many sensitive detectors. Alternatively filters + -- may be directly attached to the sensitive detector in question. + -- Attributes are directly passed as properties to the filter action. + -- + -- Note: registered global filters MUST be unique. + -- However, not all filters need to registered.... + --> + <filters> + <filter name="GeantinoRejectFilter/GeantinoRejector"/> + <filter name="ParticleRejectFilter/OpticalPhotonRejector"> + <properties particle="opticalphoton"/> + </filter> + <filter name="ParticleSelectFilter/OpticalPhotonSelector"> + <properties particle="opticalphoton"/> + </filter> + <filter name="EnergyDepositMinimumCut"> + <properties Cut="10*MeV"/> + </filter> + </filters> + + <!-- List of known action sequences. + -- Note: Action sequences exist for each of the various geant4 callback, + -- which are explained in the documentation, such as EventAction, RunAction, etc + -- and the calls after processing the hits of each sensitive detector. + -- + --> + <sequences> + <sequence name="Geant4EventActionSequence/EventAction"> + <action name="Geant4TestEventAction/UserEvent_1"> + <properties Property_int="01234" + Property_double="1e11" + Property_string="'Hello_1'"/> + </action> + <action name="UserEvent_2"/> + </sequence> + <sequence name="Geant4GeneratorActionSequence/GeneratorAction"> + <action name="Geant4ParticleGun/Gun"> + <properties energy="0.5*GeV" + particle="'e-'" + multiplicity="1"/> + </action> + </sequence> + + <sequence sd="SiVertexBarrel" type="Geant4SensDetActionSequence"> + <filter name="GeantinoRejector"/> + <filter name="EnergyDepositMinimumCut"/> + <action name="Geant4SimpleTrackerAction/SiVertexBarrelHandler"/> + </sequence> + <sequence sd="SiVertexEndcap" type="Geant4SensDetActionSequence"> + <filter name="GeantinoRejector"/> + <filter name="EnergyDepositMinimumCut"/> + <action name="Geant4SimpleTrackerAction/SiVertexEndcapHandler"/> + </sequence> + <sequence sd="SiTrackerBarrel" type="Geant4SensDetActionSequence"> + <filter name="GeantinoRejector"/> + <filter name="EnergyDepositMinimumCut"/> + <action name="Geant4SimpleTrackerAction/SiTrackerBarrelHandler"/> + </sequence> + <sequence sd="SiTrackerEndcap" type="Geant4SensDetActionSequence"> + <action name="Geant4SimpleTrackerAction/SiTrackerEndcapHandler"/> + </sequence> + <sequence sd="SiTrackerForward" type="Geant4SensDetActionSequence"> + <action name="Geant4SimpleTrackerAction/SiTrackerForwardHandler"/> + </sequence> + <sequence sd="EcalBarrel" type="Geant4SensDetActionSequence"> + <action name="Geant4SimpleCalorimeterAction/EcalBarrelHandler"/> + </sequence> + <sequence sd="EcalEndcap" type="Geant4SensDetActionSequence"> + <action name="Geant4SimpleCalorimeterAction/EcalEndCapHandler"/> + </sequence> + <sequence sd="HcalBarrel" type="Geant4SensDetActionSequence"> + <action name="Geant4SimpleCalorimeterAction/HcalBarrelHandler"> + <filter name="OpticalPhotonRejector"/> + </action> + <action name="Geant4SimpleOpticalCalorimeterAction/HcalBarrelHandler"> + <filter name="OpticalPhotonSelector"/> + </action> + </sequence> + <sequence sd="HcalEndcap" type="Geant4SensDetActionSequence"> + <action name="Geant4SimpleCalorimeterAction/HcalEndcapHandler"/> + </sequence> + <sequence sd="HcalPlug" type="Geant4SensDetActionSequence"> + <action name="Geant4SimpleCalorimeterAction/HcalPlugHandler"/> + </sequence> + <sequence sd="MuonBarrel" type="Geant4SensDetActionSequence"> + <action name="Geant4SimpleCalorimeterAction/MuonBarrelHandler"/> + </sequence> + <sequence sd="MuonEndcap" type="Geant4SensDetActionSequence"> + <action name="Geant4SimpleCalorimeterAction/MuonEndcapHandler"/> + </sequence> + <sequence sd="LumiCal" type="Geant4SensDetActionSequence"> + <action name="Geant4SimpleCalorimeterAction/LumiCalHandler"/> + </sequence> + <sequence sd="BeamCal" type="Geant4SensDetActionSequence"> + <action name="Geant4SimpleCalorimeterAction/BeamCalHandler"/> + </sequence> + </sequences> + +</geant4_setup> diff --git a/DDG4/examples/xmlAClick.C b/DDG4/examples/xmlAClick.C new file mode 100644 index 0000000000000000000000000000000000000000..9ed4153de34c27e30083be531f4ab5268a48c8c1 --- /dev/null +++ b/DDG4/examples/xmlAClick.C @@ -0,0 +1,23 @@ +#include "DDG4/Geant4Config.h" +#include <iostream> +using namespace DD4hep::Simulation::Setup; + +void setupG4_XML() { + DD4hep::Geometry::LCDD& lcdd = DD4hep::Geometry::LCDD::getInstance(); + Kernel& kernel = Kernel::instance(lcdd); + kernel.loadGeometry("file:../DD4hep.trunk/DDExamples/CLICSiD/compact/compact.xml"); + kernel.loadXML("../geant4/sensitive_detectors.xml"); + kernel.loadXML("../geant4/sequences.xml"); + kernel.loadXML("../geant4/physics.xml"); + kernel.configure(); + kernel.initialize(); + kernel.run(); + std::cout << "Successfully executed application .... " << std::endl; + kernel.terminate(); +} + + +void xmlAClick() { + setupG4_XML(); +} + diff --git a/DDG4/g4FromXML.cpp b/DDG4/g4FromXML.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e81fee6030c6e49ae39687591561df63ffe065cf --- /dev/null +++ b/DDG4/g4FromXML.cpp @@ -0,0 +1,23 @@ +#include "DDG4/Geant4Config.h" +#include <iostream> +using namespace DD4hep::Simulation::Setup; + +void setupG4_XML() { + DD4hep::Geometry::LCDD& lcdd = DD4hep::Geometry::LCDD::getInstance(); + Kernel& kernel = Kernel::instance(lcdd); + kernel.loadGeometry("file:../DD4hep.trunk/DDExamples/CLICSiD/compact/compact.xml"); + kernel.loadXML("sensitive_detectors.xml"); + kernel.loadXML("sequences.xml"); + kernel.loadXML("physics.xml"); + kernel.configure(); + kernel.initialize(); + kernel.run(); + std::cout << "Successfully executed application .... " << std::endl; + kernel.terminate(); +} + + +int main(int, char**) { + setupG4_XML(); + return 1; +} diff --git a/DDG4/include/DDG4/ComponentUtils.h b/DDG4/include/DDG4/ComponentUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..fb62f7a48febf40b24641e2c30d8a3b770be1807 --- /dev/null +++ b/DDG4/include/DDG4/ComponentUtils.h @@ -0,0 +1,217 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_COMPONENTTUILS_H +#define DD4HEP_DDG4_COMPONENTTUILS_H + +// C/C++ include files +#include <stdexcept> +#include <typeinfo> +#include <string> +#include <map> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /// ABI information about type names + std::string typeinfoName(const std::type_info& type); + void typeinfoCheck(const std::type_info& typ1, const std::type_info& typ2, const std::string& text=""); + + /** @class unrelated_type_error + * + * @author M.Frank + * @date 13.08.2013 + */ + struct unrelated_type_error : public std::runtime_error { + static std::string msg(const std::type_info& typ1, const std::type_info& typ2, const std::string& text); + unrelated_type_error(const std::type_info& typ1, const std::type_info& typ2,const std::string& text="") + : std::runtime_error(msg(typ1,typ2,text)) {} + }; + + struct Property; + struct PropertyGrammar; + struct PropertyConfigurator { + protected: + virtual ~PropertyConfigurator(); + public: + virtual void set(const PropertyGrammar& setter,const std::string&,const std::string&,void* ptr) const = 0; + }; + + /** @class PropertyGrammar + * + * @author M.Frank + * @date 13.08.2013 + */ + struct PropertyGrammar { + protected: + friend class Property; + + /// Default constructor + PropertyGrammar(); + /// Default destructor + virtual ~PropertyGrammar(); + /// Error callback on invalid conversion + static void invalidConversion(const std::type_info& from, const std::type_info& to); + /// Access to the type information + virtual const std::type_info& type() const = 0; + /// Serialize an opaque value to a string + virtual std::string str(const void* ptr) const = 0; + /// Set value from serialized string. On successful data conversion TRUE is returned. + virtual bool fromString(void* ptr, const std::string& value) const = 0; + }; + + /** @class Property + * + * Standard implementation of a property mechanism. + * The data conversion mechanism between various properties + * uses internally boost::spirit to allow also conversions + * between types, which are initially unrelated such as + * e.g. vector<int> and list<short>. + * + * @author M.Frank + * @date 13.08.2013 + */ + class Property { + protected: + /// Pointer to the data location + void* m_par; + const PropertyGrammar* m_hdl; + + /// Setup property + template <typename TYPE> void make(TYPE& value); + public: + /// Default constructor + Property(); + /// Copy constructor + Property(const Property& p); + /// User constructor + template <typename TYPE> Property(TYPE& val) + : m_par(0), m_hdl(0) + { + make(val); + } + /// Property type name + static std::string type(const Property& proptery); + /// Property type name + static std::string type(const std::type_info& proptery); + /// Property type name + std::string type() const; + /// Access void data pointer + void* ptr() const { return m_par; } + /// Access grammar object + const PropertyGrammar& grammar() const; + /// Conversion to string value + std::string str() const; + /// Conversion from string value + Property& str(const std::string& input); + /// Assignment operator + Property& operator=(const Property& p); + /// Assignment operator / set new balue + Property& operator=(const char* val); + /// Assignment operator / set new balue + Property& operator=(const std::string& val); + /// Assignment operator / set new balue + template <typename TYPE> Property& operator=(const TYPE& val); + /// Retrieve value + template <typename TYPE> TYPE value() const; + /// Retrieve value from stack (large values e.g. vectors etc.) + template <typename TYPE> void value(TYPE& value) const; + /// Set value of this property + template <typename TYPE> void set(const TYPE& value); + }; + + /** @class PropertyValue + * + * @author M.Frank + * @date 13.08.2013 + */ + template <class TYPE> class PropertyValue : private Property { + public: + TYPE data; + PropertyValue() : Property(data) {} + /// Assignment operator + PropertyValue& operator=(const TYPE& val) { + data = val; + return *this; + } + // Equality operator + bool operator==(const TYPE& val) const { + return val == data; + } + /// Access grammar object + const PropertyGrammar& grammar() const { + return this->Property::grammar(); + } + /// Conversion to string value + std::string str() const { + return this->Property::str(); + } + /// Retrieve value with data conversion + template <typename T> T value() const { + return this->Property::value<T>(); + } + /// Retrieve value from stack with data conversion (large values e.g. vectors etc.) + template <typename T> void value(TYPE& val) const { + this->Property::value(val); + } + /// Set value of this property with data conversion + template <typename T> void set(const T& val) { + this->Property::set(val); + } + }; + + /** @class PropertyManager + * + * @author M.Frank + * @date 13.08.2013 + */ + class PropertyManager { + public: + /// Property array definition + typedef std::map<std::string,Property> Properties; + protected: + /// Property array/map + Properties m_properties; + + /// Verify that this property does not exist (throw exception if the name was found) + void verifyNonExistence(const std::string& name) const; + /// Verify that this property exists (throw exception if the name was not found) + Properties::iterator verifyExistence(const std::string& name); + /// Verify that this property exists (throw exception if the name was not found) + Properties::const_iterator verifyExistence(const std::string& name) const; + + public: + /// Default constructor + PropertyManager(); + /// Default destructor + virtual ~PropertyManager(); + /// Access property by name (CONST) + const Property& property(const std::string& name) const; + /// Access property by name + Property& property(const std::string& name); + /// Access property by name + Property& operator[](const std::string& name); + /// Access property by name + const Property& operator[](const std::string& name) const; + /// Add a new property + void add(const std::string& name, const Property& property); + /// Add a new property + template <typename T> void add(const std::string& name, T& value) { + add(name,Property(value)); + } + /// Bulk set of all properties + void set(const std::string& component_name, PropertyConfigurator& setup); + /// Dump string values + void dump() const; + }; + +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_COMPONENTTUILS_H diff --git a/DDG4/include/DDG4/ComponentUtils_inl.h b/DDG4/include/DDG4/ComponentUtils_inl.h new file mode 100644 index 0000000000000000000000000000000000000000..93f36cbf63c11ff31faefc680184f383de252176 --- /dev/null +++ b/DDG4/include/DDG4/ComponentUtils_inl.h @@ -0,0 +1,151 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_COMPONENTTUILS_INL_H +#define DD4HEP_DDG4_COMPONENTTUILS_INL_H + +// Framework include files +#include "DDG4/ComponentUtils.h" + +#ifdef DD4HEP_USE_BOOST +#include "DDG4/Parsers.h" +#include "DDG4/ToStream.h" +#endif + +// C/C++ include files +#include <sstream> +#include <string> +#include <vector> +#include <list> +#include <set> +#include <map> +#include <stdexcept> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /** @class PropertyGrammarCollection + * + * @author M.Frank + * @date 13.08.2013 + */ + template <typename TYPE> struct Grammar : public PropertyGrammar { + /// Standarsd constructor + Grammar(); + /// Default destructor + virtual ~Grammar(); + /// Singleton instantiator + static const Grammar& instance(); + /// PropertyGrammar overload: Access to the type information + virtual const std::type_info& type() const; + /// PropertyGrammar overload: Serialize a property to a string + virtual std::string str(const void* ptr) const; + /// PropertyGrammar overload: Retrieve value from string + virtual bool fromString(void* ptr, const std::string& value) const; + }; + + /// Standarsd constructor + template <typename TYPE> Grammar<TYPE>::Grammar() { + } + + /// Default destructor + template <typename TYPE> Grammar<TYPE>::~Grammar() { + } + + /// Access concrete Grammar object + template <class TYPE> const Grammar<TYPE>& Grammar<TYPE>::instance() { + static Grammar<TYPE> s; + return s; + } + + /// PropertyGrammar overload: Access to the type information + template <typename TYPE> const std::type_info& Grammar<TYPE>::type() const { + return typeid(TYPE); + } + /// PropertyGrammar overload: Retrieve value from string + template <typename TYPE> bool Grammar<TYPE>::fromString(void* ptr, const std::string& str) const { +#ifdef DD4HEP_USE_BOOST + TYPE temp; + int sc = Parsers::parse(temp,str); + std::cout << "Converting value: " << str << " to type " << typeid(TYPE).name() << std::endl; + if ( sc ) { + *(TYPE*)ptr = temp; + return true; + } + return false; +#else + if ( !ptr || str.length() == 0 ) {} + throw std::runtime_error("This version of DD4HEP is not compiled to use boost::spirit.\n" + "To enable elaborated property handling set DD4HEP_USE_BOOST=ON\n" + "and BOOST_INCLUDE_DIR=<boost include path>"); +#endif + } + + /// Serialize a property to a string + template <typename TYPE> std::string Grammar<TYPE>::str(const void* ptr) const { +#ifdef DD4HEP_USE_BOOST + std::stringstream string_rep; + Utils::toStream(*(TYPE*)ptr,string_rep); + return string_rep.str(); +#else + if ( ptr ) {} + throw std::runtime_error("This version of DD4HEP is not compiled to use boost::spirit.\n" + "To enable elaborated property handling set DD4HEP_USE_BOOST=ON\n" + "and BOOST_INCLUDE_DIR=<boost include path>"); +#endif + } + + /// Setup property + template <typename TYPE> void Property::make(TYPE& val) { + m_hdl = &Grammar<TYPE>::instance(); + m_par = &val; + } + + /// Set value of this property + template <typename TYPE> void Property::set(const TYPE& value) { + const PropertyGrammar& g = grammar(); + if ( g.type() == typeid(TYPE) ) + *(TYPE*)m_par = value; + else if ( !g.fromString(m_par,Grammar<TYPE>::instance().str(&value)) ) + PropertyGrammar::invalidConversion(typeid(TYPE),g.type()); + } + + /// Assignment operator / set new balue + template <typename TYPE> Property& Property::operator=(const TYPE& val) { + this->set(val); + return *this; + } + + /// Retrieve value from stack (large values e.g. vectors etc.) + template <typename TYPE> void Property::value(TYPE& value) const { + const PropertyGrammar& g = grammar(); + if ( g.type() == typeid(TYPE) ) + value = *(TYPE*)m_par; + else if ( !Grammar<TYPE>::instance().fromString(&value,this->str()) ) + PropertyGrammar::invalidConversion(g.type(),typeid(TYPE)); + } + + /// Retrieve value + template <typename TYPE> TYPE Property::value() const { + TYPE temp; + this->value(temp); + return temp; + } + +#define DD4HEP_INSTANTIATE_PROPERTY_TYPE(x) \ + template x Property::value() const; \ + template void Property::value(x& value) const; \ + template void Property::set(const x& value); \ + template Property& Property::operator=(const x& value); \ + template void Property::make(x& value) + +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_COMPONENTTUILS_INL_H diff --git a/DDG4/include/DDG4/Factories.h b/DDG4/include/DDG4/Factories.h index 5f0d4fcffd053130d3183208fc4d8b586da90cae..d6ed3ca4213275a8cd7376c1e463838860b5afb0 100644 --- a/DDG4/include/DDG4/Factories.h +++ b/DDG4/include/DDG4/Factories.h @@ -20,11 +20,14 @@ #include <map> // Forward declarations +class G4ParticleDefinition; class G4VSensitiveDetector; class G4MagIntegratorStepper; class G4EquationOfMotion; class G4MagneticField; class G4Mag_EqRhs; +class G4VPhysicsConstructor; +class G4VProcess; namespace DD4hep { namespace Geometry { @@ -91,38 +94,37 @@ namespace { template <typename P> class Factory<P, DD4hep::Simulation::Geant4Action*(DD4hep::Simulation::Geant4Context*,std::string)> { public: typedef DD4hep::Simulation::Geant4Action ACT; static void Func(void *retaddr, void*, const std::vector<void*>& arg, void*) - { *(ACT**)retaddr = (ACT*)new P((DD4hep::Simulation::Geant4Context*)arg[0], *(std::string*)arg[1]); } + { *(ACT**)retaddr = (ACT*)new P((DD4hep::Simulation::Geant4Context*)arg[0], *(std::string*)arg[1]); } }; - /// Factory to create Geant4 steppers - template <typename P> class Factory<P, G4MagIntegratorStepper*(G4EquationOfMotion*)> { - public: static void Func(void *retaddr, void*, const std::vector<void*>& arg, void*) { - P* stepper = new P((G4EquationOfMotion*)arg[0]); - *(G4MagIntegratorStepper**)retaddr = (G4MagIntegratorStepper*)stepper; - } + /// Templated Factory for constructors without argument + template <typename P,typename R> struct FF0 { + static void Func(void *ret, void*, const std::vector<void*>&, void*) { *(R*)ret = (R)(new P()); } }; - - /// Factory to create Geant4 steppers - template <typename P> class Factory<P, G4MagIntegratorStepper*(G4Mag_EqRhs*)> { - public: static void Func(void *retaddr, void*, const std::vector<void*>& arg, void*) { - P* stepper = new P((G4Mag_EqRhs*)arg[0]); - *(G4MagIntegratorStepper**)retaddr = (G4MagIntegratorStepper*)stepper; - } + /// Templated Factory for constructors with exactly 1 argument + template <typename P,typename R,typename A0> struct FF1 { + static void Func(void *ret, void*, const std::vector<void*>& arg, void*) { *(R*)ret = (R)(new P((A0)arg[0])); } }; + /// Factory to create Geant4 steppers + template <typename P> class Factory<P, G4MagIntegratorStepper*(G4EquationOfMotion*)> : public FF1<P,G4MagIntegratorStepper*,G4EquationOfMotion*>{}; + /// Factory to create Geant4 steppers + template <typename P> class Factory<P, G4MagIntegratorStepper*(G4Mag_EqRhs*)> : public FF1<P,G4MagIntegratorStepper*,G4Mag_EqRhs*> {}; /// Factory to create Geant4 equations of motion for magnetic fields - template <typename P> class Factory<P, G4Mag_EqRhs*(G4MagneticField*)> { - public: static void Func(void *retaddr, void*, const std::vector<void*>& arg, void*) { - P* o = new P((G4MagneticField*)arg[0]); - *(G4Mag_EqRhs**)retaddr = (G4Mag_EqRhs*)o; - } - }; + template <typename P> class Factory<P, G4Mag_EqRhs*(G4MagneticField*)> : public FF1<P,G4Mag_EqRhs*,G4MagneticField*> {}; -} + /// Factory to create Geant4 Processes + template <typename P> class Factory<P, G4VProcess*()> : public FF0<P,G4VProcess*> {}; + /// Factory to create Geant4 Processes + template <typename P> class Factory<P, G4VPhysicsConstructor*()> : public FF0<P,G4VPhysicsConstructor*> {}; -// Plugin definition to create Geant4 sensitive detectors -#define DECLARE_G4SDFACTORY(name) namespace DD4hep { namespace Simulation { }} using DD4hep::Simulation::name; \ - PLUGINSVC_FACTORY_WITH_ID(name,std::string(#name),DD4hep::Simulation::G4SDFactory*()) + template <typename P> class Factory<P, G4ParticleDefinition*()> { public: + static void Func(void *ret, void*, const std::vector<void*>&, void*) { *(G4ParticleDefinition**)ret = P::Definition(); } + }; + template <typename P> class Factory<P, long()> { public: + static void Func(void *ret, void*, const std::vector<void*>&, void*) { P::ConstructParticle(); *(long*)ret = 1L; } + }; +} #define DECLARE_EXTERNAL_GEANT4SENSITIVEDETECTOR(name,func) \ namespace DD4hep { namespace Simulation { struct external_geant4_sd_##name {}; \ @@ -144,18 +146,25 @@ namespace { #define DECLARE_GEANT4SENSITIVE(name) namespace DD4hep { namespace Simulation { }} using DD4hep::Simulation::name; \ PLUGINSVC_FACTORY_WITH_ID(name,std::string(#name),DD4hep::Simulation::Geant4Sensitive*(DD4hep::Simulation::Geant4Context*,std::string,DD4hep::Geometry::DetElement*,DD4hep::Geometry::LCDD*)) +/// Plugin defintion to create Geant4Action objects #define DECLARE_GEANT4ACTION(name) namespace DD4hep { namespace Simulation { }} using DD4hep::Simulation::name; \ PLUGINSVC_FACTORY_WITH_ID(name,std::string(#name),DD4hep::Simulation::Geant4Action*(DD4hep::Simulation::Geant4Context*,std::string)) - -/// Plugin definition to create Geant4 stpper objects +/// Plugin definition to create Geant4 stepper objects #define DECLARE_GEANT4_STEPPER(name) PLUGINSVC_FACTORY_WITH_ID(G4##name,std::string(#name),G4MagIntegratorStepper*(G4EquationOfMotion*)) #define DECLARE_GEANT4_MAGSTEPPER(name) PLUGINSVC_FACTORY_WITH_ID(G4##name,std::string(#name),G4MagIntegratorStepper*(G4Mag_EqRhs*)) - /// Plugin definition to create Geant4 equations of motion for magnetic fields #define DECLARE_GEANT4_MAGMOTION(name) PLUGINSVC_FACTORY_WITH_ID(G4##name,std::string(#name),G4Mag_EqRhs*(G4MagneticField*)) +/// Plugin definition to create Geant4 physics processes (G4VProcess) +#define DECLARE_GEANT4_PROCESS(name) PLUGINSVC_FACTORY_WITH_ID(name,std::string(#name),G4VProcess*()) +/// Plugin definition to create Geant4 physics constructors (G4VPhysicsConstructor) +#define DECLARE_GEANT4_PHYSICS(name) PLUGINSVC_FACTORY_WITH_ID(name,std::string(#name),G4VPhysicsConstructor*()) +/// Plugin definition to force particle constructors for GEANT4 (G4ParticleDefinition) +#define DECLARE_GEANT4_PARTICLE(name) PLUGINSVC_FACTORY_WITH_ID(name,std::string(#name),G4ParticleDefinition*()) +/// Plugin definition to force particle constructors for GEANT4 (G4XXXXConstructor) +#define DECLARE_GEANT4_PARTICLEGROUP(name) PLUGINSVC_FACTORY_WITH_ID(name,std::string(#name),long()) #define DECLARE_GEANT4_SETUP(name,func) \ - namespace DD4hep { namespace Simulation { namespace { struct xml_g4_setup_##name {}; } \ + namespace DD4hep { namespace Simulation { struct xml_g4_setup_##name {}; \ template <> long Geant4SetupAction<DD4hep::Simulation::xml_g4_setup_##name>::create(LCDD& l,const DD4hep::Simulation::Geant4Converter& e, const std::map<std::string,std::string>& a) {return func(l,e,a);} }} \ PLUGINSVC_FACTORY_WITH_ID(xml_g4_setup_##name,std::string(#name "_Geant4_action"),long(DD4hep::Geometry::LCDD*,const DD4hep::Simulation::Geant4Converter*,const std::map<std::string,std::string>*)) #endif // DDG4_FACTORIES_H diff --git a/DDG4/include/DDG4/Geant4Action.h b/DDG4/include/DDG4/Geant4Action.h new file mode 100644 index 0000000000000000000000000000000000000000..95f04fcf3cdf6eee43a7cb59815888471aa79535 --- /dev/null +++ b/DDG4/include/DDG4/Geant4Action.h @@ -0,0 +1,283 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4ACTION_H +#define DD4HEP_DDG4_GEANT4ACTION_H + +// Framework include files +#include "DDG4/Geant4Context.h" +#include "DDG4/ComponentUtils.h" +#include "DDG4/Geant4Callback.h" + +#include "G4VUserTrackInformation.hh" +// Geant4 forward declarations +class G4Run; +class G4Event; +class G4Step; +class G4Track; +class G4TrackStack; +class G4EventGenerator; +class G4VTrajectory; +class G4TrackingManager; + +// C/C++ include files +#include <string> +#include <cstdarg> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + template <typename TO,typename FROM> TO fast_cast(FROM from) { +#ifdef USE_FASTCAST + return static_cast<TO>(from); +#else + return dynamic_cast<TO>(from); +#endif + } + + struct TypeName : public std::pair<std::string,std::string> { + TypeName() : std::pair<std::string,std::string>() {} + TypeName(const std::pair<std::string,std::string>& c) + : std::pair<std::string,std::string>(c) {} + TypeName(const std::string& typ,const std::string& nam) + : std::pair<std::string,std::string>(typ,nam) {} + static TypeName split(const std::string& type_name); + }; + + /** @class Geant4TrackInformation Geant4Action.h DDG4/Geant4Action.h + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4TrackInformation : public G4VUserTrackInformation { + enum { + STORE = 1<<0, + LAST = 1<<31 + }; + int m_flags; + /// Default constructor + Geant4TrackInformation(); + /// Standard destructor + virtual ~Geant4TrackInformation(); + /// Access flag if track should be stored + bool storeTrack() const { return (m_flags&STORE) != 0; } + /// Access flag if track should be stored + Geant4TrackInformation& storeTrack(bool value); + }; + +#if 0 + /** @class Geant4UserTrajectory Geant4Action.h DDG4/Geant4Action.h + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4UserTrajectory { + /// Default constructor + Geant4UserTrajectory(); + /// Standard destructor + virtual ~Geant4UserTrajectory(); + /// accessors + virtual int trackID() const = 0; + virtual int parentID() const = 0; + virtual std::string particleName() const = 0; + virtual double charge() const = 0; + virtual int pdgID() const = 0; + virtual G4ThreeVector momentum() const = 0; + virtual int numPoints() const = 0; + virtual G4VTrajectoryPoint* point(int i) const = 0; + }; + + /** @class Geant4Trajectory Geant4Action.h DDG4/Geant4Action.h + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4Trajectory : public G4VTrajectory { + std::auto_ptr<Geant4UserTrajectory> trajectory; + /// Default constructor + Geant4Trajectory(Geant4UserTrajectory* traj); + /// Standard destructor + virtual ~Geant4Trajectory(); + /// Mandatory G4 overloads: Get/Set functions + virtual G4int GetTrackID() const { return trajectory->trackID; } + virtual G4int GetParentID() const { return trajectory->parentID(); } + virtual G4String GetParticleName() const { return trajectory->particleName(); } + /// Mandatory G4 overloads: Charge is that of G4DynamicParticle + virtual G4double GetCharge() const { return trajectory->charge(); } + /// Mandatory G4 overloads: Zero will be returned if the particle does not have PDG code. + virtual G4int GetPDGEncoding() const { return trajectory->pdgID(); } + /// Mandatory G4 overloads: Momentum at the origin of the track in global coordinate system. + virtual G4ThreeVector GetInitialMomentum() const { return trajectory->momentum(); } + + /// Mandatory G4 overloads: Returns the number of trajectory points + virtual int GetPointEntries() const { return trajectory->numPoints(); } + virtual G4VTrajectoryPoint* GetPoint(G4int i) const { return trajectory->point(i); } + }; +#endif + + /** @class Invoke Geant4Action.h DDG4/Geant4Action.h + * + * Default base class for all geant 4 actions and derivates thereof. + * + * @author M.Frank + * @version 1.0 + */ + class Geant4Action { + protected: + /// Reference to the Geant4 context + Geant4Context* m_context; + /// Action name + std::string m_name; + /// Property pool + PropertyManager m_properties; + /// Reference count. Initial value: 1 + long m_refCount; + + template <typename T> struct Actors { + typedef std::vector<T*> _V; + _V m_v; + Actors() { } + ~Actors() { } + void clear() { m_v.clear(); } + void add(T* obj) { m_v.push_back(obj); } + operator const _V&() const { return m_v; } + operator _V&() { return m_v; } + const _V* operator->() const { return &m_v; } + _V* operator->() { return &m_v; } + /// NON-CONST actions + template <typename R, typename Q> void operator()(R (Q::*pmf)() ) { + if ( m_v.empty() ) return; + for(typename _V::iterator i=m_v.begin(); i!=m_v.end(); ++i) + ((*i)->*pmf)(); + } + template <typename R, typename Q, typename A0> void operator()(R (Q::*pmf)(A0), A0 a0) { + if ( m_v.empty() ) return; + for(typename _V::iterator i=m_v.begin(); i!=m_v.end();++i) + ((*i)->*pmf)(a0); + } + template <typename R, typename Q, typename A0, typename A1> void operator()(R (Q::*pmf)(A0,A1), A0 a0, A1 a1) { + if ( m_v.empty() ) return; + for(typename _V::iterator i=m_v.begin(); i!=m_v.end();++i) + ((*i)->*pmf)(a0,a1); + } + /// CONST actions + template <typename R, typename Q> void operator()(R (Q::*pmf)() const ) const { + if ( m_v.empty() ) return; + for(typename _V::const_iterator i=m_v.begin(); i!=m_v.end(); ++i) + ((*i)->*pmf)(); + } + template <typename R, typename Q, typename A0> void operator()(R (Q::*pmf)(A0) const, A0 a0) const { + if ( m_v.empty() ) return; + for(typename _V::const_iterator i=m_v.begin(); i!=m_v.end();++i) + ((*i)->*pmf)(a0); + } + template <typename R, typename Q, typename A0, typename A1> void operator()(R (Q::*pmf)(A0,A1)const, A0 a0, A1 a1) const { + if ( m_v.empty() ) return; + for(typename _V::const_iterator i=m_v.begin(); i!=m_v.end();++i) + ((*i)->*pmf)(a0,a1); + } + /// CONST filters + template <typename Q> bool filter(bool (Q::*pmf)() const ) const { + if ( !m_v.empty() ) return true; + for(typename _V::const_iterator i=m_v.begin(); i!=m_v.end(); ++i) + if ( !((*i)->*pmf)() ) return false; + return true; + } + template <typename Q, typename A0> bool filter(bool (Q::*pmf)(A0) const, A0 a0) const { + if ( m_v.empty() ) return true; + for(typename _V::const_iterator i=m_v.begin(); i!=m_v.end();++i) + if ( !((*i)->*pmf)(a0) ) return false; + return true; + } + template <typename Q, typename A0, typename A1> bool filter(bool (Q::*pmf)(A0,A1) const, A0 a0, A1 a1) const { + if ( m_v.empty() ) return true; + for(typename _V::const_iterator i=m_v.begin(); i!=m_v.end();++i) + if ( !((*i)->*pmf)(a0,a1) ) return false; + return true; + } + }; + + /// Default destructor + virtual ~Geant4Action(); + + public: + /// Standard constructor + Geant4Action(Geant4Context* context, const std::string& nam); + /// Increase reference count + long addRef(); + /// Decrease reference count. Implicit destruction + long release(); + /// Set the context pointer + void setContext(Geant4Context* context); + /// Access the context + Geant4Context* context() const { return m_context; } + /// Access name of the action + const std::string& name() const { return m_name; } + /// Access name of the action + const char* c_name() const { return m_name.c_str(); } + /// Set the object name. + void setName(const std::string& new_name) { m_name = new_name; } + /// Access to the properties of the object + PropertyManager& properties() { return m_properties; } + /// Declare property + template <typename T> Geant4Action& declareProperty(const std::string& nam, T& val); + /// Declare property + template <typename T> Geant4Action& declareProperty(const char* nam, T& val); + /// Set object properties + Geant4Action& setProperties(PropertyConfigurator& setup); + /// Support of debug messages. + void debug(const std::string& fmt, ...) const; + /// Support of info messages. + void info(const std::string& fmt, ...) const; + /// Support of warning messages. + void warning(const std::string& fmt, ...) const; + /// Support of error messages. + void error(const std::string& fmt, ...) const; + /// Action to support error messages. + bool error(bool return_value, const std::string& fmt, ...) const; + /// Support of fatal messages. Throws exception + void fatal(const std::string& fmt, ...) const; + /// Support of exceptions: Print fatal message and throw runtime_error. + void except(const std::string& fmt, ...) const; + + /// Access to the main run action sequence from the kernel object + Geant4RunActionSequence& runAction() const; + /// Access to the main event action sequence from the kernel object + Geant4EventActionSequence& eventAction() const; + /// Access to the main stepping action sequence from the kernel object + Geant4SteppingActionSequence& steppingAction() const; + /// Access to the main tracking action sequence from the kernel object + Geant4TrackingActionSequence& trackingAction() const; + /// Access to the main stacking action sequence from the kernel object + Geant4StackingActionSequence& stackingAction() const; + /// Access to the main generator action sequence from the kernel object + Geant4GeneratorActionSequence& generatorAction() const; + }; + + /// Declare property + template <typename T> Geant4Action& Geant4Action::declareProperty(const std::string& nam, T& val) { + m_properties.add(nam,val); + return *this; + } + + /// Declare property + template <typename T> Geant4Action& Geant4Action::declareProperty(const char* nam, T& val) { + m_properties.add(nam,val); + return *this; + } + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4ACTION_H diff --git a/DDG4/include/DDG4/Geant4ActionPhase.h b/DDG4/include/DDG4/Geant4ActionPhase.h new file mode 100644 index 0000000000000000000000000000000000000000..96a7f1604912a66d0981e7bf0801452670130a72 --- /dev/null +++ b/DDG4/include/DDG4/Geant4ActionPhase.h @@ -0,0 +1,127 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4ACTIONPHASE_H +#define DD4HEP_DDG4_GEANT4ACTIONPHASE_H + +// Framework include files +#include "DDG4/Geant4Action.h" + +// C/C++ include files +#include <vector> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + /* + + Geant4Phase, G4EventGenerator --> G4VUserPrimaryGeneratorAction::GeneratePrimaries + Geant4Begin, G4Run --> G4UserRunAction::BeginOfRunAction + Geant4End, G4Run --> G4UserRunAction::EndOfRunAction + Geant4Begin, G4Event --> G4UserEventAction::BeginOfEventAction + Geant4End, G4Event --> G4UserEventAction::EndOfEventAction + Geant4Begin, G4Track --> G4UserTrackingAction::PreUserTrackingAction + Geant4End, G4Track --> G4UserTrackingAction::PostUserTrackingAction + Geant4Phase, G4Step --> G4UserSteppingAction::UserSteppingAction + Geant4Begin, G4TrackStack --> G4UserStackingAction::NewStage + Geant4End, G4TrackStack --> G4UserStackingAction::PrepareNewEvent + + */ + + /** @class Invoke Geant4ActionPhase.h DDG4/Geant4ActionPhase.h + * + * Default base class for all geant 4 actions and derivates thereof. + * + * @author M.Frank + * @version 1.0 + */ + class Geant4ActionPhase : public Geant4Action { + public: + typedef std::vector<Callback> Members; + protected: + /// Phase members (actions) being called for a particular phase + Members m_members; + /// Type information of the argument type of the callback + const std::type_info* m_argTypes[3]; + + public: + /// Standard constructor + Geant4ActionPhase(Geant4Context* context, const std::string& name, const std::type_info& arg_type0, + const std::type_info& arg_type1, const std::type_info& arg_type2); + /// Default destructor + virtual ~Geant4ActionPhase(); + /// Access phase members + const Members& members() const { return m_members; } + /// Type of the first phase callback-argument + const std::type_info* const * argTypes() const { return m_argTypes; } + /// Execute all members in the phase context + void execute(void* argument); + /// Add a new member to the phase + virtual bool add(Callback callback); + /// Remove an existing member from the phase. If not existing returns false + virtual bool remove(Callback callback); + /// Add a new member to the phase + template <typename TYPE, typename IF_TYPE, typename A0, typename R> + bool add(TYPE* member, R (IF_TYPE::*callback)(A0 arg)) { + typeinfoCheck(typeid(A0),*m_argTypes[0],"Invalid ARG0 type. Failed to add phase callback."); + if ( dynamic_cast<IF_TYPE*>(member) ) { + //member->addRef(); + return add(Callback(member).make(callback)); + } + throw unrelated_type_error(typeid(TYPE),typeid(IF_TYPE),"Failed to add phase callback."); + } + /// Add a new member to the phase + template <typename TYPE, typename IF_TYPE, typename A0, typename A1, typename R> + bool add(TYPE* member, R (IF_TYPE::*callback)(A0 arg0, A1 arg1)) { + typeinfoCheck(typeid(A0),*m_argTypes[0],"Invalid ARG0 type. Failed to add phase callback."); + typeinfoCheck(typeid(A1),*m_argTypes[1],"Invalid ARG1 type. Failed to add phase callback."); + if ( dynamic_cast<IF_TYPE*>(member) ) { + //member->addRef(); + return add(Callback(member).make(callback)); + } + throw unrelated_type_error(typeid(TYPE),typeid(IF_TYPE),"Failed to add phase callback."); + } + /// Add a new member to the phase + template <typename TYPE, typename IF_TYPE, typename A0, typename A1, typename A2, typename R> + bool add(TYPE* member, R (IF_TYPE::*callback)(A0 arg0, A1 arg1)) { + typeinfoCheck(typeid(A0),*m_argTypes[0],"Invalid ARG0 type. Failed to add phase callback."); + typeinfoCheck(typeid(A1),*m_argTypes[1],"Invalid ARG1 type. Failed to add phase callback."); + typeinfoCheck(typeid(A2),*m_argTypes[2],"Invalid ARG2 type. Failed to add phase callback."); + if ( dynamic_cast<IF_TYPE*>(member) ) { + //member->addRef(); + return add(Callback(member).make(callback)); + } + throw unrelated_type_error(typeid(TYPE),typeid(IF_TYPE),"Failed to add phase callback."); + } + /// Remove all member callbacks from the phase. If not existing returns false + template <typename TYPE, typename PMF> bool remove(TYPE* member) { + return remove(Callback(member)); + } + /// Remove an existing member callback from the phase. If not existing returns false + template <typename TYPE, typename PMF> bool remove(TYPE* member, PMF callback) { + Callback cb(member); + return remove(cb.make(callback)); + } + /// Create action to execute phase members + void call(); + template <typename A0> void call(A0 a0); + template <typename A0, typename A1> void call(A0 a0, A1 a1); + template <typename A0, typename A1, typename A2> void call(A0 a0, A1 a1, A2 a2); + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4ACTIONPHASE_H diff --git a/DDG4/include/DDG4/Geant4Callback.h b/DDG4/include/DDG4/Geant4Callback.h new file mode 100644 index 0000000000000000000000000000000000000000..a443eb4182f10849b2ef0b9986aa3c4f7b5bedce --- /dev/null +++ b/DDG4/include/DDG4/Geant4Callback.h @@ -0,0 +1,318 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4CALLBACK_H +#define DD4HEP_DDG4_GEANT4CALLBACK_H + +// C/C++ include files +#include <algorithm> +#include <typeinfo> +#include <vector> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + + /**@class Callback Callback.h CPP/Callback.h + * + * Definition of the generic callback structure for member functions + * + * @author M.Frank + * @date 01/03/2013 + * @version 0.1 + */ + struct Callback { + typedef unsigned long (*func_t)(void* obj,const void* fun,const void* args[]); + typedef struct { + void *first, *second; + } mfunc_t; + typedef unsigned long ulong; + + void* par; + func_t call; + mfunc_t func; + Callback() : par(0), call(0) { func.first=func.second=0; } + Callback(void* p) : par(p), call(0) { func.first=func.second=0; } + Callback(void* p, void* mf, func_t c) : par(p), call(c) { func = *(mfunc_t*)mf; } + + operator bool() const { return (call && par && func.first); } + unsigned long execute(const void* user_param[]) const { + return (*this) ? call(par,&func,user_param) : 0; + } + + template <typename T> static T* cast(void* p) { return (T*)p; } + template <typename T> static const T* c_cast(const void* p) { return (const T*)p; } + template <typename T> struct Wrapper { + public: + typedef T pmf_t; + union Functor { + mfunc_t ptr; + pmf_t pmf; + Functor(const void* f) { ptr = *(mfunc_t*)f; } + Functor(pmf_t f) { pmf = f; } + }; + static mfunc_t pmf(pmf_t f) { + const Functor func(f); + return func.ptr; + } + }; + // + // Callback with no arguments + // + template <typename T> const Callback& _make(ulong (*fptr)(void* o, const void* f, const void* u[]), T pmf) { + typename Wrapper<T>::Functor f(pmf); + func = f.ptr; + call = fptr; + return *this; + } + template <typename R, typename T> const Callback& make(R (T::*pmf)()) { + typedef R (T::*pfunc_t)(); + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void*[]) + { return (ulong) (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))(); } + }; + return _make(_Wrapper::call, pmf); + } + template <typename R, typename T> const Callback& make(R (T::*pmf)() const) { + typedef R (T::*pfunc_t)() const; + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void*[]) + { return (ulong) (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))(); } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T> const Callback& make(void (T::*pmf)() ) { + typedef void (T::*pfunc_t)() const; + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void*[]) { + (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))(); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T> const Callback& make(void (T::*pmf)() const) { + typedef void (T::*pfunc_t)() const; + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void*[]) { + (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))(); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + // + // Callback with 1 argument + // + template <typename R, typename T, typename A> const Callback& make(R (T::*pmf)(A)) { + typedef R (T::*pfunc_t)(A); + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void* u[]) + { return (ulong) (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))((A)u[0]); } + }; + return _make(_Wrapper::call, pmf); + } + template <typename R, typename T, typename A> const Callback& make(R (T::*pmf)(A) const) { + typedef R (T::*pfunc_t)(A) const; + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void* u[]) + { return (ulong) (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))((A)u[0]); } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T, typename A> const Callback& make(void (T::*pmf)(A)) { + typedef void (T::*pfunc_t)(const A); + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void* u[]) + { (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))((A)u[0]); return 1; } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T, typename A> const Callback& make(void (T::*pmf)(A) const) { + typedef void (T::*pfunc_t)(const A) const; + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void* u[]) + { (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))((A)u[0]); return 1; } + }; + return _make(_Wrapper::call, pmf); + } + // + // Callback with 3 arguments + // + template <typename R, typename T, typename A0, typename A1> const Callback& make(R (T::*pmf)(A0, A1)) { + typedef R (T::*pfunc_t)(A0,A1); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + return (ulong) (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0)u[0],(A1)u[1]); + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename R, typename T, typename A0, typename A1> const Callback& make(R (T::*pmf)(A0, A1) const) { + typedef R (T::*pfunc_t)(A0,A1); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + return (ulong) (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0)u[0],(A1)u[1]); + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T, typename A0, typename A1> const Callback& make(void (T::*pmf)(A0, A1)) { + typedef void (T::*pfunc_t)(A0,A1); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0)u[0],(A1)u[1]); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T, typename A0, typename A1> const Callback& make(void (T::*pmf)(A0, A1) const) { + typedef void (T::*pfunc_t)(A0,A1); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0)u[0],(A1)u[1]); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + // + // Callback with 3 arguments + // + template <typename R, typename T, typename A0, typename A1, typename A2> const Callback& make(R (T::*pmf)(A0, A1, A2)) { + typedef R (T::*pfunc_t)(A0,A1); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + return (ulong) (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0)u[0],(A1)u[1],(A2)u[2]); + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename R, typename T, typename A0, typename A1, typename A2> const Callback& make(R (T::*pmf)(A0, A1, A2) const) { + typedef R (T::*pfunc_t)(A0,A1); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + return (ulong) (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0)u[0],(A1)u[1],(A2)u[2]); + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T, typename A0, typename A1, typename A2> const Callback& make(void (T::*pmf)(A0, A1, A2)) { + typedef void (T::*pfunc_t)(A0,A1); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0)u[0],(A1)u[1],(A2)u[2]); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T, typename A0, typename A1, typename A2> const Callback& make(void (T::*pmf)(A0, A1, A2) const) { + typedef void (T::*pfunc_t)(A0,A1); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0)u[0],(A1)u[1],(A2)u[2]); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + + template <typename T> static Callback make(void* p, T pmf) { return Callback(p).make(pmf); } + + template <typename P, typename R, typename T> static + T* dyn_cast(P* p, R (T::*)()) { return dynamic_cast<T*>(p); } + template <typename P, typename R, typename T> static + const T* dyn_cast(const P* p, R (T::*)() const) { return dynamic_cast<const T*>(p); } + + template <typename P, typename R, typename T, typename A> static + T* dyn_cast(P* p, R (T::*)(A)) { return dynamic_cast<T*>(p); } + template <typename P, typename R, typename T, typename A> static + const T* dyn_cast(const P* p, R (T::*)(A) const) { return dynamic_cast<const T*>(p); } + }; + + struct CallbackSequence { + typedef std::vector<Callback> Callbacks; + Callbacks callbacks; + CallbackSequence() {} + CallbackSequence(const CallbackSequence& c) : callbacks(c.callbacks) {} + //template <typename TYPE, typename R, typename OBJECT> + // CallbackSequence(const std::vector<TYPE*>& objects, R (TYPE::value_type::*pmf)()) { + //} + bool empty() const { return callbacks.empty();} + void clear() { callbacks.clear(); } + void add(const Callback& cb) { callbacks.push_back(cb); } + void operator()() const; + template <typename A0> void operator()(A0 a0) const; + template <typename A0, typename A1> void operator()(A0 a0, A1 a1) const; + template <typename A0, typename A1, typename A2> void operator()(A0 a0, A1 a1, A2 a2) const; + /// Check the compatibility of two typed objects. The test is the result of a dynamic_cast + static void checkTypes(const std::type_info& typ1, const std::type_info& typ2, void* test); + + template <typename TYPE, typename R, typename OBJECT> + void add(TYPE* pointer, R (OBJECT::*pmf)()) { + checkTypes(typeid(TYPE),typeid(OBJECT),dynamic_cast<OBJECT*>(pointer)); + add(Callback(pointer).make(pmf)); + } + template <typename TYPE, typename R, typename OBJECT, typename A> + void add(TYPE* pointer, R (OBJECT::*pmf)(A)) { + checkTypes(typeid(TYPE),typeid(OBJECT),dynamic_cast<OBJECT*>(pointer)); + add(Callback(pointer).make(pmf)); + } + template <typename TYPE, typename R, typename OBJECT, typename A1, typename A2> + void add(TYPE* pointer, R (OBJECT::*pmf)(A1,A2)) { + checkTypes(typeid(TYPE),typeid(OBJECT),dynamic_cast<OBJECT*>(pointer)); + add(Callback(pointer).make(pmf)); + } + }; + + inline void CallbackSequence::operator()() const { + if ( !callbacks.empty() ) { + const void* args[1] = { 0 }; + for(Callbacks::const_iterator i=callbacks.begin(); i != callbacks.end(); ++i) + (*i).execute(args); + } + } + template <typename A0> inline + void CallbackSequence::operator()(A0 a0) const { + if ( !callbacks.empty() ) { + const void* args[1] = { a0 }; + for(Callbacks::const_iterator i=callbacks.begin(); i != callbacks.end(); ++i) + (*i).execute(args); + } + } + template <typename A0, typename A1> inline + void CallbackSequence::operator()(A0 a0,A1 a1) const { + if ( !callbacks.empty() ) { + const void* args[2] = { a0, a1 }; + for(Callbacks::const_iterator i=callbacks.begin(); i != callbacks.end(); ++i) + (*i).execute(args); + } + } + template <typename A0, typename A1, typename A2> inline + void CallbackSequence::operator()(A0 a0,A1 a1,A2 a2) const { + if ( !callbacks.empty() ) { + const void* args[3] = { a0, a1, a2 }; + for(Callbacks::const_iterator i=callbacks.begin(); i != callbacks.end(); ++i) + (*i).execute(args); + } + } + +} // End namespace DD4hep +#endif // DD4HEP_DDG4_GEANT4CALLBACK_H diff --git a/DDG4/include/DDG4/Geant4Config.h b/DDG4/include/DDG4/Geant4Config.h new file mode 100644 index 0000000000000000000000000000000000000000..058c1815fbee1c152cec768e0034ff00ad235c4d --- /dev/null +++ b/DDG4/include/DDG4/Geant4Config.h @@ -0,0 +1,95 @@ +// $Id: Geant4config.h 615 2013-06-18 11:13:35Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Small helper file with abbreviations to write configurations +// for CINT; also used when writing the XML configuration. +// +// Author : M.Frank +// +//==================================================================== +#ifndef DDG4_GEANT4CONFIG_H +#define DDG4_GEANT4CONFIG_H + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + + template <typename TYPE> class Geant4Handle; + class Geant4Kernel; + class Geant4Action; + class Geant4Filter; + class Geant4RunAction; + class Geant4EventAction; + class Geant4TrackingAction; + class Geant4StackingAction; + class Geant4SteppingAction; + class Geant4Sensitive; + class Geant4ActionPhase; + class Geant4GeneratorAction; + class Geant4PhysicsList; + + class Geant4GeneratorActionSequence; + class Geant4RunActionSequence; + class Geant4EventActionSequence; + class Geant4TrackingActionSequence; + class Geant4SteppingActionSequence; + class Geant4StackingActionSequence; + class Geant4PhysicsListActionSequence; + class Geant4SensDetActionSequence; + + /* + * Simulation setup namespace declaration + */ + namespace Setup { + // Basics + typedef Geant4Kernel Kernel; + // Actions + typedef Geant4Handle<Geant4Action> Action; + typedef Geant4Handle<Geant4Filter> Filter; + typedef Geant4Handle<Geant4GeneratorAction> GenAction; + typedef Geant4Handle<Geant4RunAction> RunAction; + typedef Geant4Handle<Geant4EventAction> EventAction; + typedef Geant4Handle<Geant4TrackingAction> TrackAction; + typedef Geant4Handle<Geant4StackingAction> StackAction; + typedef Geant4Handle<Geant4SteppingAction> StepAction; + typedef Geant4Handle<Geant4PhysicsList> PhysicsList; + typedef Geant4Handle<Geant4ActionPhase> Phase; + typedef Geant4Handle<Geant4Sensitive> Sensitive; + // Sequences + typedef Geant4Handle<Geant4SensDetActionSequence> SensitiveSeq; + typedef Geant4Handle<Geant4GeneratorActionSequence> GeneratorSeq; + typedef Geant4Handle<Geant4RunActionSequence> RunActionSeq; + typedef Geant4Handle<Geant4EventActionSequence> EventActionSeq; + typedef Geant4Handle<Geant4TrackingActionSequence> TrackActionSeq; + typedef Geant4Handle<Geant4SteppingActionSequence> StepActionSeq; + typedef Geant4Handle<Geant4StackingActionSequence> StackActionSeq; + typedef Geant4Handle<Geant4PhysicsListActionSequence> PhysicsActionSeq; + } + + } // End namespace Simulation +} // End namespace DD4hep + +#include "DDG4/Geant4Handle.h" +#include "DDG4/Geant4Kernel.h" +#include "DDG4/Geant4PhysicsList.h" +#include "DDG4/Geant4GeneratorAction.h" +#include "DDG4/Geant4RunAction.h" +#include "DDG4/Geant4EventAction.h" +#include "DDG4/Geant4TrackingAction.h" +#include "DDG4/Geant4SteppingAction.h" +#include "DDG4/Geant4StackingAction.h" +#include "DDG4/Geant4ActionPhase.h" +#include "DDG4/Geant4SensDetAction.h" +#include "DDG4/ComponentUtils.h" +#include "DD4hep/LCDD.h" + +#endif // DDG4_GEANT4CONFIG_H diff --git a/DDG4/include/DDG4/Geant4Context.h b/DDG4/include/DDG4/Geant4Context.h new file mode 100644 index 0000000000000000000000000000000000000000..4be082f38b8a33a5cc36ea5fbeef7af5b72b4808 --- /dev/null +++ b/DDG4/include/DDG4/Geant4Context.h @@ -0,0 +1,85 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4CONTEXT_H +#define DD4HEP_DDG4_GEANT4CONTEXT_H + +// Forward declarations +class G4Track; +class G4VTrajectory; +class G4TrackingManager; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + // Forward declarations + namespace Geometry { + class LCDD; + class DetElement; + } + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + class Geant4Kernel; + class Geant4RunActionSequence; + class Geant4EventActionSequence; + class Geant4SteppingActionSequence; + class Geant4TrackingActionSequence; + class Geant4StackingActionSequence; + class Geant4GeneratorActionSequence; + class Geant4SensDetSequences; + + + /** @class Geant4Context Geant4Context.h DDG4/Geant4Context.h + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4Context { + typedef Geometry::LCDD LCDD; + + Geant4Kernel* m_kernel; + /// Reference to Geant4 track manager + G4TrackingManager* m_trackMgr; + /// Default constructor + Geant4Context(Geant4Kernel* kernel); + /// Default destructor + virtual ~Geant4Context(); + /// Access the tracking manager + G4TrackingManager* trackMgr() const { return m_trackMgr; } + /// Access to the kernel object + Geant4Kernel& kernel() { return *m_kernel; } + /// Access to detector description + LCDD& lcdd() const; + /// Create a user trajectory + virtual G4VTrajectory* createTrajectory(const G4Track* track) const; + /// Access to the main run action sequence from the kernel object + Geant4RunActionSequence& runAction() const; + /// Access to the main event action sequence from the kernel object + Geant4EventActionSequence& eventAction() const; + /// Access to the main stepping action sequence from the kernel object + Geant4SteppingActionSequence& steppingAction() const; + /// Access to the main tracking action sequence from the kernel object + Geant4TrackingActionSequence& trackingAction() const; + /// Access to the main stacking action sequence from the kernel object + Geant4StackingActionSequence& stackingAction() const; + /// Access to the main generator action sequence from the kernel object + Geant4GeneratorActionSequence& generatorAction() const; + /// Access to the sensitive detector sequences from the kernel object + Geant4SensDetSequences& sensitiveActions() const; + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4CONTEXT_H diff --git a/DDG4/include/DDG4/Geant4Data.h b/DDG4/include/DDG4/Geant4Data.h new file mode 100644 index 0000000000000000000000000000000000000000..ca21546d861ffdda030820a81dd0a20286b30aa5 --- /dev/null +++ b/DDG4/include/DDG4/Geant4Data.h @@ -0,0 +1,162 @@ +// $Id: Geant4Data.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_GEANT4DATA_H +#define DD4HEP_GEANT4DATA_H + +// Framework include files +#include "DD4hep/Objects.h" +#include "G4Step.hh" + + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + typedef Geometry::Position Position; + typedef Geometry::Position Direction; + + /** @class HitCompare Geant4Data.h DDG4/Geant4Data.h + * + * Base class for hit comparisons. + * + * @author M.Frank + * @version 1.0 + */ + template<class HIT> struct HitCompare { + /// Comparison function + virtual bool operator()(const HIT* h) const = 0; + }; + + /** @class HitPositionCompare Geant4Data.h DDG4/Geant4Data.h + * + * Seek the hits of an arbitrary collection for the same position. + * + * @author M.Frank + * @version 1.0 + */ + template<class HIT> struct HitPositionCompare : public HitCompare<HIT> { + const Position& pos; + /// Constructor + HitPositionCompare(const Position& p) : pos(p) { } + /// Comparison function + virtual bool operator()(const HIT* h) const { return pos == h->position; } + }; + + + struct SimpleHit { + // cellID + long long int cellID ; + + /** @class MonteCarloContrib + */ + struct MonteCarloContrib { + /// Geant 4 Track identifier + int trackID; + /// Particle ID from the PDG table + int pdgID; + /// Total energy deposit in this hit + double deposit; + /// Timestamp when this energy was deposited + double time; + /// Default constructor + MonteCarloContrib() : trackID(-1), pdgID(-1), deposit(0.0), time(0.0) {} + /// Initializing constructor + MonteCarloContrib(int track_id, double dep, double time_stamp) + : trackID(track_id), pdgID(-1), deposit(dep), time(time_stamp) {} + /// Initializing constructor + MonteCarloContrib(int track_id, int pdg, double dep, double time_stamp) + : trackID(track_id), pdgID(pdg), deposit(dep), time(time_stamp) {} + /// Copy constructor + MonteCarloContrib(const MonteCarloContrib& c) + : trackID(c.trackID), pdgID(c.pdgID), deposit(c.deposit), time(c.time) {} + // Clear data content + void clear() { + time = deposit = 0.0; + pdgID = trackID = -1; + } + }; + typedef MonteCarloContrib Contribution; + typedef std::vector<MonteCarloContrib> Contributions; + public: + /// Default constructor + SimpleHit() : cellID(0) {} + /// Default destructor + virtual ~SimpleHit(); + /// Extract the MC contribution for a given hit from the step information + static Contribution extractContribution(G4Step* step); + }; + + struct SimpleTracker { + /** @class SimpleTracker::Hit Geant4Data.h DDG4/Geant4Data.h + * + * Geant4 tracker hit class. Tracker hits contain the momentum + * direction as well as the hit position. + * + * @author M.Frank + * @version 1.0 + */ + struct Hit : public SimpleHit { + /// Hit position + Position position; + /// Hit direction + Direction momentum; + /// Length of the track segment contributing to this hit + double length; + /// Monte Carlo / Geant4 information + Contribution truth; + /// Energy deposit in the tracker hit + double energyDeposit; + /// Default constructor + Hit(); + /// Initializing constructor + Hit(int track_id, int pdg_id, double deposit, double time_stamp); + /// Default destructor + virtual ~Hit(); + /// Assignment operator + Hit& operator=(const Hit& c); + /// Clear hit content + Hit& clear(); + /// Store Geant4 point and step information into tracker hit structure. + Hit& storePoint(G4Step* step, G4StepPoint* point); + }; + }; + + struct SimpleCalorimeter { + /** @class SimpleCalorimeter::Hit Geant4Data.h DDG4/Geant4Data.h + * + * Geant4 tracker hit class. Calorimeter hits contain the momentum + * direction as well as the hit position. + * + * @author M.Frank + * @version 1.0 + */ + struct Hit : public SimpleHit { + public: + /// Hit position + Position position; + /// Hit contributions by individual particles + Contributions truth; + /// Total energy deposit + double energyDeposit; + public: + /// Standard constructor + Hit(const Position& cell_pos); + /// Default destructor + virtual ~Hit(); + }; + }; + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_GEANT4DATA_H diff --git a/DDG4/include/DDG4/Geant4EventAction.h b/DDG4/include/DDG4/Geant4EventAction.h new file mode 100644 index 0000000000000000000000000000000000000000..08f61cbf279ecdaa6652518c416b26ba48def56b --- /dev/null +++ b/DDG4/include/DDG4/Geant4EventAction.h @@ -0,0 +1,83 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4EVENTACTION_H +#define DD4HEP_DDG4_GEANT4EVENTACTION_H + +// Framework include files +#include "DDG4/Geant4Action.h" +// Forward declarations +class G4Event; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + /** @class Geant4EventAction Geant4Action.h DDG4/Geant4Action.h + * + * Concrete basic implementation of the Geant4 event action + * + * @author M.Frank + * @version 1.0 + */ + class Geant4EventAction : public Geant4Action { + public: + /// Standard constructor + Geant4EventAction(Geant4Context* context, const std::string& nam); + /// Default destructor + virtual ~Geant4EventAction(); + /// begin-of-event callback + virtual void begin(const G4Event* event); + /// End-of-event callback + virtual void end(const G4Event* event); + }; + + /** @class Geant4EventActionSequence Geant4Action.h DDG4/Geant4Action.h + * + * Concrete implementation of the Geant4 event action sequence + * + * @author M.Frank + * @version 1.0 + */ + class Geant4EventActionSequence : public Geant4Action { + protected: + /// Callback sequence for event initialization action + CallbackSequence m_begin; + /// Callback sequence for event finalization action + CallbackSequence m_end; + /// The list of action objects to be called + Actors<Geant4EventAction> m_actors; + public: + /// Standard constructor + Geant4EventActionSequence(Geant4Context* context, const std::string& nam); + /// Default destructor + virtual ~Geant4EventActionSequence(); + /// Register begin-of-event callback + template <typename Q, typename T> + void callAtBegin(Q* p, void (T::*f)(const G4Event*)) { m_begin.add(p,f);} + /// Register end-of-event callback + template <typename Q, typename T> + void callAtEnd(Q* p, void (T::*f)(const G4Event*)) { m_end.add(p,f); } + /// Add an actor responding to all callbacks. Sequence takes ownership. + void adopt(Geant4EventAction* action); + /// begin-of-event callback + virtual void begin(const G4Event* event); + /// End-of-event callback + virtual void end(const G4Event* event); + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4EVENTACTION_H diff --git a/DDG4/include/DDG4/Geant4GeneratorAction.h b/DDG4/include/DDG4/Geant4GeneratorAction.h new file mode 100644 index 0000000000000000000000000000000000000000..a5412ec2e5fce7df35bb8045294250b458307afd --- /dev/null +++ b/DDG4/include/DDG4/Geant4GeneratorAction.h @@ -0,0 +1,76 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4GENERATORACTION_H +#define DD4HEP_DDG4_GEANT4GENERATORACTION_H + +// Framework include files +#include "DDG4/Geant4Action.h" + +class G4Event; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + /** @class Geant4GeneratorAction Geant4GeneratorAction.h DDG4/Geant4GeneratorAction.h + * + * Concrete implementation of the Geant4 generator action base class + * + * @author M.Frank + * @version 1.0 + */ + class Geant4GeneratorAction : public Geant4Action { + protected: + Callback m_calls; + public: + /// Standard constructor + Geant4GeneratorAction(Geant4Context* context, const std::string& name); + /// Default destructor + virtual ~Geant4GeneratorAction(); + /// Callback to generate primary particles + virtual void operator()(G4Event* ) {} + }; + + /** @class Geant4GeneratorActionSequence Geant4GeneratorAction.h DDG4/Geant4GeneratorAction.h + * + * Concrete implementation of the Geant4 generator action sequence + * + * @author M.Frank + * @version 1.0 + */ + class Geant4GeneratorActionSequence : public Geant4Action { + protected: + /// Callback sequence to generate primary particles + CallbackSequence m_calls; + /// The list of action objects to be called + Actors<Geant4GeneratorAction> m_actors; + public: + /// Standard constructor + Geant4GeneratorActionSequence(Geant4Context* context, const std::string& name); + /// Default destructor + virtual ~Geant4GeneratorActionSequence(); + /// Register begin-of-run callback. Types Q and T must be polymorph! + template <typename Q, typename T> + void call(Q* p, void (T::*f)(G4Event*)) { m_calls.add(p,f); } + /// Add an actor responding to all callbacks. Sequence takes ownership. + void adopt(Geant4GeneratorAction* action); + /// Callback to generate primary particles + virtual void operator()(G4Event* event); + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4GENERATORACTION_H diff --git a/DDG4/include/DDG4/Geant4Handle.h b/DDG4/include/DDG4/Geant4Handle.h new file mode 100644 index 0000000000000000000000000000000000000000..bd6f7869c8f75f1f32b68735b6e4999258a50c67 --- /dev/null +++ b/DDG4/include/DDG4/Geant4Handle.h @@ -0,0 +1,70 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4SETUP_H +#define DD4HEP_DDG4_GEANT4SETUP_H + +// Framework include files +#include "DDG4/ComponentUtils.h" +#include "DD4hep/LCDD.h" + +// C/C++ include files +#include <string> +#include <memory> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + /// Forward declarations + class Geant4Kernel; + class Geant4Action; + + /** @class Geant4Handle Geant4Handle.h DDG4/Geant4Handle.h + * + * Handle to Geant4 actions with built-in creation mechanism + * + * @author M.Frank + * @version 1.0 + */ + template <typename TYPE> struct Geant4Handle { + protected: + void checked_assign(TYPE* p); + public: + typedef TYPE handled_type; + mutable handled_type* value; + Geant4Handle(); + Geant4Handle(handled_type* typ); + template <typename T> Geant4Handle(T* typ) : value(0) + { checked_assign(dynamic_cast<TYPE*>(typ)); } + Geant4Handle(Geant4Handle& handle); + Geant4Handle(const Geant4Kernel&,const std::string& type_name); + /// Constructor only implemented for sensitive objects + Geant4Handle(const Geant4Kernel& ctxt, + const std::string& type_name, + const std::string& detector); + ~Geant4Handle(); + Property& operator[](const std::string& property_name) const; + Geant4Handle& operator=(Geant4Handle& handle); + Geant4Handle& operator=(handled_type* ptr); + bool operator!() const; + operator handled_type*() const; + handled_type* get() const; + handled_type* operator->() const; + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4SETUP_H diff --git a/DDG4/include/DDG4/Geant4HitCollection.h b/DDG4/include/DDG4/Geant4HitCollection.h new file mode 100644 index 0000000000000000000000000000000000000000..06e9566885842566aa2c486b78f16d1572b34158 --- /dev/null +++ b/DDG4/include/DDG4/Geant4HitCollection.h @@ -0,0 +1,244 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4HITCOLLECTION_H +#define DD4HEP_DDG4_GEANT4HITCOLLECTION_H + +// Framework include files +#include "G4VHitsCollection.hh" +#include "G4VHit.hh" + +// C/C++ include files +#include <vector> +#include <string> +#include <typeinfo> +#include <stdexcept> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + // Forward declarations + class Geant4HitCollection; + class Geant4HitWrapper; + + /** @class Geant4HitWrapper Geant4HitCollection.h DDG4/Geant4HitCollection.h + * + * Default base class for all geant 4 created hits. + * The hit is stored in an opaque way and can be accessed by the + * collection. + * + * @author M.Frank + * @version 1.0 + */ + class Geant4HitWrapper : public G4VHit { + private: + public: + struct InvalidHit { virtual ~InvalidHit(); }; + + struct HitManipulator { + public: + typedef std::pair<void*,HitManipulator*> Wrapper; + typedef void (*destroy_t)(Wrapper& data); + typedef void* (*cast_t)(const Wrapper& data); + const std::type_info& type; + destroy_t destroy; + cast_t cast; + + /// Initializing Constructor + HitManipulator(const std::type_info& t, destroy_t d, cast_t c); + /// Check to collection type against the argument (used during insertion) + void checkHitType(const std::type_info& type) const; + /// Check pointer to be of proper type + template <typename TYPE> Wrapper checkHit(TYPE* obj) { + if ( obj ) { + Wrapper wrap(obj,this); + HitManipulator* obj_type = HitManipulator::instance<TYPE>(); + if ( obj_type == this ) { + return wrap; + } + wrap.first = (obj_type->cast)(wrap); + if ( wrap.first ) { + return wrap; + } + checkHitType(obj_type->type); + } + throw std::runtime_error("Invalid hit pointer passed to collection!"); + } + /// Static function to delete contained hits + template <typename TYPE> static void deleteHit(Wrapper& obj) { + TYPE* p = (TYPE*)obj.first; + if ( p ) delete p; + obj.first = 0; + } + /// Static function to cast to the desired type + template <typename TYPE> static void* castHit(const Wrapper& obj) { + HitManipulator* me = HitManipulator::instance<TYPE>(); + if ( me == obj.second ) { + return (TYPE*)obj.first; + } + G4VHit* hit = (G4VHit*)obj.first; + TYPE* p = dynamic_cast<TYPE*>(hit); + if ( p ) { + return p; + } + if ( obj.first ) { + obj.second->checkHitType(me->type); + } + return 0; + } + /// Static function to cast to the desired type + template <typename TYPE> static const void* castHit(const Wrapper& obj) { + HitManipulator* me = HitManipulator::instance<TYPE>(); + if ( me == obj.second ) { + return (const TYPE*)obj.first; + } + G4VHit* hit = (G4VHit*)obj.first; + const TYPE* p = dynamic_cast<const TYPE*>(hit); + if ( p ) { + return p; + } + if ( obj.first ) { + obj.second->checkHitType(me->type); + } + return 0; + } + template <typename TYPE> static HitManipulator* instance() { + static HitManipulator m(typeid(TYPE),deleteHit<TYPE>,castHit<TYPE>); + return &m; + } + }; + + protected: + typedef HitManipulator::Wrapper Wrapper; + mutable Wrapper m_data; + + public: + + /// Default constructor + Geant4HitWrapper() { + m_data.second = manipulator<InvalidHit>(); + m_data.first = 0; + } + /// Copy constructor + Geant4HitWrapper(const Geant4HitWrapper& v) { + m_data = v.m_data; + v.m_data.first = 0; + //v.release(); + } + /// Copy constructor + Geant4HitWrapper(const Wrapper& v) { + m_data = v; + } + /// Default destructor + virtual ~Geant4HitWrapper(); + /// Geant4 required object allocator + void *operator new(size_t); + /// Geat4 required object destroyer + void operator delete(void *ptr); + /// Pointer/Object release + void* release(); + /// Release data for copy + Wrapper releaseData(); + /// Generate manipulator object + template <typename TYPE> static HitManipulator* manipulator() { + return HitManipulator::instance<TYPE>(); + } + /// Assignment transfers the pointer ownership + Geant4HitWrapper& operator=(const Geant4HitWrapper& v) { + m_data = v.m_data; + v.m_data.first = 0; + //v.release(); + return *this; + } + /// Automatic conversion to the desired type + template <typename TYPE> operator TYPE*() const { + return (TYPE*)(m_data.second->cast(m_data)); + } + }; + + /** @class Geant4HitCollection Geant4HitCollection.h DDG4/Geant4HitCollection.h + * + * Opaque hit collection. + * This hit collection is for good reasons homomorph, + * Polymorphism without an explicit type would only + * confuse most users. + * + * @author M.Frank + * @version 1.0 + */ + class Geant4HitCollection : public G4VHitsCollection { + public: + typedef std::vector<Geant4HitWrapper> WrappedHits; + typedef Geant4HitWrapper::HitManipulator Manip; + + /** @class Compare Geant4HitCollection.h DDG4/Geant4HitCollection.h + * + * Base class for hit comparisons. + * + * @author M.Frank + * @version 1.0 + */ + struct Compare { + /// Comparison function + virtual void* operator()(const Geant4HitWrapper& w) const = 0; + }; + + protected: + /// The collection of hit pointers in the wrapped format + WrappedHits m_hits; + /// The type of the objects in this collection. Set by the constructor + Manip* m_manipulator; + + protected: + /// Notification to increase the instance counter + void newInstance(); + /// Find hit in a collection by comparison of attributes + void* findHit(const Compare& cmp) const; + + public: + /// Initializing constructor + template <typename TYPE> + Geant4HitCollection(const std::string& det, const std::string& coll, const TYPE*) + : G4VHitsCollection(det,coll), m_manipulator(Geant4HitWrapper::manipulator<TYPE>()) + { + newInstance(); + m_hits.reserve(200); + } + /// Default destructor + virtual ~Geant4HitCollection(); + /// Access individual hits + virtual G4VHit* GetHit(size_t which) const { return (G4VHit*)&m_hits.at(which); } + /// Access the collection size + virtual size_t GetSize() const { return m_hits.size(); } + /// Access the hit wrapper + Geant4HitWrapper& hit(size_t which) { return m_hits.at(which); } + /// Access the hit wrapper (CONST) + const Geant4HitWrapper& hit(size_t which) const { return m_hits.at(which); } + /// Add a new hit with a check, that the hit is of the same type + template <typename TYPE> void add(TYPE* hit) { + Geant4HitWrapper w(m_manipulator->checkHit(hit)); + m_hits.push_back(w); + } + /// Find hits in a collection by comparison of attributes + template <typename TYPE> TYPE* find(const Compare& cmp) const { + return (TYPE*)findHit(cmp); + } + + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4HITCOLLECTION_H diff --git a/DDG4/include/DDG4/Geant4Kernel.h b/DDG4/include/DDG4/Geant4Kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..c7352a0309440a4490d8c31f9b36ff77d9e34b07 --- /dev/null +++ b/DDG4/include/DDG4/Geant4Kernel.h @@ -0,0 +1,247 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4KERNEL_H +#define DD4HEP_DDG4_GEANT4KERNEL_H + +// Framework include files +#include "DDG4/Geant4Primitives.h" +#include "DDG4/Geant4Action.h" + +// C/C++ include files +#include <map> +#include <string> +#include <typeinfo> + +class G4RunManager; +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + // Forward declarations + class Geant4ActionPhase; + class Geant4Context; + class Geant4Action; + class Geant4RunAction; + class Geant4EventAction; + class Geant4SteppingAction; + class Geant4TrackingAction; + class Geant4StackingAction; + class Geant4GeneratorAction; + class Geant4PhysicsList; + class Geant4RunActionSequence; + class Geant4EventActionSequence; + class Geant4SteppingActionSequence; + class Geant4TrackingActionSequence; + class Geant4StackingActionSequence; + class Geant4GeneratorActionSequence; + class Geant4PhysicsListActionSequence; + class Geant4SensDetActionSequence; + class Geant4SensDetSequences; + + + /** @class Invoke Geant4Kernel.h DDG4/Geant4Kernel.h + * + * Default base class for all geant 4 actions and derivates thereof. + * + * @author M.Frank + * @version 1.0 + */ + class Geant4Kernel { + public: + typedef DD4hep::Geometry::LCDD LCDD; + typedef std::map<std::string,Geant4ActionPhase*> Phases; + typedef std::map<std::string,Geant4Action*> GlobalActions; + + protected: + /// Reference to execution context + Geant4Context* m_context; + /// Reference to the run manager + G4RunManager* m_runManager; + /// Property pool + PropertyManager m_properties; + /// Reference to the Geant4 primary generator action + Geant4GeneratorActionSequence* m_generatorAction; + /// Reference to the Geant4 run action + Geant4RunActionSequence* m_runAction; + /// Reference to the Geant4 event action + Geant4EventActionSequence* m_eventAction; + /// Reference to the Geant4 track action + Geant4TrackingActionSequence* m_trackingAction; + /// Reference to the Geant4 step action + Geant4SteppingActionSequence* m_steppingAction; + /// Reference to the Geant4 stacking action + Geant4StackingActionSequence* m_stackingAction; + /// Reference to the Geant4 sensitive action sequences + Geant4SensDetSequences* m_sensDetActions; + /// Reference to the geant4 physics list + Geant4PhysicsListActionSequence* m_physicsList; + /// Action phases + Phases m_phases; + /// Globally registered actions + GlobalActions m_globalActions; + /// Globally registered filters of sensitive detectors + GlobalActions m_globalFilters; + /// Detector description object + LCDD& m_lcdd; + /// Helper to register an action sequence + template <typename C> bool registerSequence(C*& seq,const std::string& name); + + /// Standard constructor + Geant4Kernel(LCDD& lcdd); + public: + + /** @class PhaseSelector Geant4Kernel.h DDG4/Geant4Kernel.h + * + * Embedded helper class to facilitate map access to the phases. + * + * @author M.Frank + * @version 1.0 + */ + struct PhaseSelector { + /// Reference to embedding object + Geant4Kernel* m_kernel; + /// Standard constructor + PhaseSelector(Geant4Kernel* kernel); + /// Copy constructor + PhaseSelector(const PhaseSelector& c); + /// Phase access to the map + Geant4ActionPhase& operator[](const std::string& name) const; + } phase; + + + enum State { + SETTING_UP, + INITIALIZED + }; + /// Default destructor + virtual ~Geant4Kernel(); + /// Instance accessor + static Geant4Kernel& instance(LCDD& lcdd); + /// Accessof the Geant4Kernel object from the LCDD reference extension (if present and registered) + static Geant4Kernel& access(LCDD& lcdd); + /// Access the context + Geant4Context* context() const { return m_context; } + /// Automatic conversion to the context + operator Geant4Context* () const { return m_context; } + /// Access to the properties of the object + PropertyManager& properties() { return m_properties; } + /// Access phase phases + const Phases& phases() const { return m_phases; } + /// Access to detector description + LCDD& lcdd() const { return m_lcdd; } + /// Access to the Geant4 run manager + G4RunManager& runManager(); + /// Register action by name to be retrieved when setting up and connecting action objects + /** Note: registered actions MUST be unique. + * However, not all actions need to registered.... + * Only register those, you later need to retrieve by name. + */ + Geant4Kernel& registerGlobalAction(Geant4Action* action); + /// Retrieve action from repository + Geant4Action* globalAction(const std::string& action_name, bool throw_if_not_present=true); + /// Register filter by name to be retrieved when setting up and connecting filter objects + /** Note: registered filters MUST be unique. + * However, not all filters need to registered.... + * Only register those, you later need to retrieve by name. + */ + Geant4Kernel& registerGlobalFilter(Geant4Action* filter); + /// Retrieve filter from repository + Geant4Action* globalFilter(const std::string& filter_name, bool throw_if_not_present=true); + + /// Access phase by name + Geant4ActionPhase* getPhase(const std::string& name); + /// Add a new phase to the phase + virtual Geant4ActionPhase* addPhase(const std::string& name, const std::type_info& arg1, + const std::type_info& arg2, const std::type_info& arg3, bool throw_on_exist); + /// Add a new phase to the phase + template <typename A0> Geant4ActionPhase* addPhase(const std::string& name, bool throw_on_exist=true) { + return addPhase(name,typeid(A0),typeid(void),typeid(void),throw_on_exist); + } + /// Add a new phase to the phase + template <typename A0, typename A1> + Geant4ActionPhase* addPhase(const std::string& name, bool throw_on_exist=true) { + return addPhase(name,typeid(A0),typeid(A1),typeid(void),throw_on_exist); + } + /// Add a new phase to the phase + template <typename A0, typename A1, typename A2> + Geant4ActionPhase* addPhase(const std::string& name, bool throw_on_exist=true) { + return addPhase(name,typeid(A0),typeid(A1),typeid(A2),throw_on_exist); + } + /// Remove an existing phase from the phase. If not existing returns false + virtual bool removePhase(const std::string& name); + /// Destroy all phases. To be called only at shutdown. + virtual void destroyPhases(); + + /// Access generator action sequence + Geant4GeneratorActionSequence* generatorAction(bool create); + /// Access generator action sequence + Geant4GeneratorActionSequence& generatorAction() { return *generatorAction(true); } + + /// Access run action sequence + Geant4RunActionSequence* runAction(bool create); + /// Access run action sequence + Geant4RunActionSequence& runAction() { return *runAction(true); } + + /// Access run action sequence + Geant4EventActionSequence* eventAction(bool create); + /// Access run action sequence + Geant4EventActionSequence& eventAction() { return *eventAction(true); } + + /// Access stepping action sequence + Geant4SteppingActionSequence* steppingAction(bool create); + /// Access stepping action sequence + Geant4SteppingActionSequence& steppingAction() { return *steppingAction(true); } + + /// Access tracking action sequence + Geant4TrackingActionSequence* trackingAction(bool create); + /// Access tracking action sequence + Geant4TrackingActionSequence& trackingAction() { return *trackingAction(true); } + + /// Access stacking action sequence + Geant4StackingActionSequence* stackingAction(bool create); + /// Access stacking action sequence + Geant4StackingActionSequence& stackingAction() { return *stackingAction(true); } + + /// Access to the sensitive detector sequences from the kernel object + Geant4SensDetSequences& sensitiveActions() const; + /// Access to the sensitive detector action from the kernel object + Geant4SensDetActionSequence* sensitiveAction(const std::string& name) const; + + /// Access to the physics list + Geant4PhysicsListActionSequence* physicsList(bool create); + /// Access to the physics list + Geant4PhysicsListActionSequence& physicsList() { return *physicsList(true); } + + /// Construct detector geometry using lcdd plugin + void loadGeometry(const std::string& compact_file); + /// Run the simulation + void configure(); + void initialize(); + void run(); + void terminate(); + void loadXML(const char* fname); + }; + + struct Geant4Exec { + static int configure(Geant4Kernel& kernel); + static int initialize(Geant4Kernel& kernel); + static int run(Geant4Kernel& kernel); + static int terminate(Geant4Kernel& kernel); + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4KERNEL_H diff --git a/DDG4/include/DDG4/Geant4PhysicsList.h b/DDG4/include/DDG4/Geant4PhysicsList.h new file mode 100644 index 0000000000000000000000000000000000000000..d9e9e03767b6a6c4817e5737a16806b9ed23dfc6 --- /dev/null +++ b/DDG4/include/DDG4/Geant4PhysicsList.h @@ -0,0 +1,185 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4PHYSICSLIST_H +#define DD4HEP_DDG4_GEANT4PHYSICSLIST_H + +// Framework include files +#include "DDG4/Geant4Action.h" + +// C/C++ include files +#include <map> +#include <vector> + +// Forward declarations +class G4VPhysicsConstructor; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + /** @class Geant4UserPhysics Geant4PhysicsList.h DDG4/Geant4PhysicsList.h + * + * Interface class exposing some of the G4VUserPhysicsList class. + * + * @author M.Frank + * @version 1.0 + */ + class Geant4UserPhysics { + protected: + /// Standard constructor with initailization parameters + Geant4UserPhysics(); + /// Default destructor + virtual ~Geant4UserPhysics(); + public: + /// Enable transportation + virtual void AddTransportation() = 0; + /// Register physics constructor + virtual void RegisterPhysics(G4VPhysicsConstructor* physics) = 0; + }; + + /** @class Geant4PhysicsList Geant4PhysicsList.h DDG4/Geant4PhysicsList.h + * + * Concrete basic implementation of the Geant4 event action + * + * @author M.Frank + * @version 1.0 + */ + class Geant4PhysicsList : public Geant4Action { + public: + + /** @class PhysicsConstructor Geant4PhysicsList.h DDG4/Geant4PhysicsList.h + * + * Image of a physics constructor holding all stub information to attach + * the concrete process contributing to the user physics list. + * + * @author M.Frank + * @version 1.0 + */ + struct Process { + std::string name; + int ordAtRestDoIt, ordAlongSteptDoIt, ordPostStepDoIt; + /// Default constructor + Process(); + /// Copy constructor + Process(const Process& p); + /// Assignment operator + Process& operator=(const Process& p); + }; + struct ParticleConstructor : public std::string { + ParticleConstructor() : std::string() {} + ParticleConstructor(const std::string& s) : std::string(s) {} + ~ParticleConstructor() {} + }; + struct PhysicsConstructor : public std::string { + PhysicsConstructor() : std::string() {} + PhysicsConstructor(const std::string& s) : std::string(s) {} + ~PhysicsConstructor() {} + }; + + typedef std::vector<Process> ParticleProcesses; + typedef std::map<std::string, ParticleProcesses > PhysicsProcesses; + + PhysicsProcesses m_processes; + + typedef std::vector<ParticleConstructor> ParticleConstructors; + ParticleConstructors m_particles; + + typedef std::vector<PhysicsConstructor> PhysicsConstructors; + PhysicsConstructors m_physics; + + public: + /// Standard constructor with initailization parameters + Geant4PhysicsList(Geant4Context* context, const std::string& nam); + /// Default destructor + virtual ~Geant4PhysicsList(); + + /// Access all physics processes + PhysicsProcesses& processes() { return m_processes; } + /// Access all physics processes + const PhysicsProcesses& processes() const { return m_processes; } + /// Access processes for one particle type + ParticleProcesses& processes(const std::string& part_name); + /// Access processes for one particle type (CONST) + const ParticleProcesses& processes(const std::string& part_name) const; + /// Access all physics particles + ParticleConstructors& particles() { return m_particles; } + /// Access all physics particles + const ParticleConstructors& particles() const { return m_particles; } + /// Access all physics constructors + PhysicsConstructors& physics() { return m_physics; } + /// Access all physics constructors + const PhysicsConstructors& physics() const { return m_physics; } + + /// Callback to construct the physics list + virtual void constructProcess(Geant4UserPhysics* interface); + /// constructParticle callback + virtual void constructParticles(Geant4UserPhysics* particle); + /// constructPhysics callback + virtual void constructPhysics(Geant4UserPhysics* physics); + /// Callback to construct processes (uses the G4 particle table) + virtual void constructProcesses(Geant4UserPhysics* physics); + }; + + + /** @class Geant4PhysicsListActionSequence Geant4Action.h DDG4/Geant4Action.h + * + * Concrete implementation of the Geant4 physics list sequence. + * A list to setup the physics content in a modular form + * + * @author M.Frank + * @version 1.0 + */ + class Geant4PhysicsListActionSequence : public Geant4Action { + protected: + /// Callback sequence for event finalization action + CallbackSequence m_process; + /// Callback sequence for event finalization action + CallbackSequence m_particle; + /// The list of action objects to be called + Actors<Geant4PhysicsList> m_actors; + /// Callback to construct particle decays + virtual void constructDecays(Geant4UserPhysics* physics); + public: + /// Flag if particle transportation is to be added + bool m_transportation; + /// Flag if particle decays are to be added + bool m_decays; + public: + /// Standard constructor + Geant4PhysicsListActionSequence(Geant4Context* context, const std::string& nam); + /// Default destructor + virtual ~Geant4PhysicsListActionSequence(); + /// Update transportation flag + void setTransportation(bool value) { m_transportation = value; } + /// Access the transportation flag + bool transportation() const { return m_transportation; } + /// Register process construction callback + template <typename Q, typename T> + void constructProcess(Q* p, void (T::*f)(Geant4UserPhysics*)) { m_process.add(p,f);} + /// Register particle construction callback + template <typename Q, typename T> + void constructParticle(Q* p, void (T::*f)(Geant4UserPhysics*)) { m_particle.add(p,f);} + /// Add an actor responding to all callbacks. Sequence takes ownership. + void adopt(Geant4PhysicsList* action); + /// begin-of-event callback + void constructProcess(Geant4UserPhysics* physics); + /// begin-of-event callback + void constructParticles(Geant4UserPhysics* physics); + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4PHYSICSLIST_H diff --git a/DDG4/include/DDG4/Geant4RunAction.h b/DDG4/include/DDG4/Geant4RunAction.h new file mode 100644 index 0000000000000000000000000000000000000000..5f48ef0f703ec058c704d5b3c43375a5b4dd13a4 --- /dev/null +++ b/DDG4/include/DDG4/Geant4RunAction.h @@ -0,0 +1,82 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4RUNACTION_H +#define DD4HEP_DDG4_GEANT4RUNACTION_H + +// Framework include files +#include "DDG4/Geant4Action.h" +// Forward declaration +class G4Run; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + /* + * Simulation namespace declaration + */ + namespace Simulation { + + /** @class Geant4RunAction Geant4Action.h DDG4/Geant4Action.h + * + * Concrete basic implementation of the Geant4 run action + * + * @author M.Frank + * @version 1.0 + */ + class Geant4RunAction : public Geant4Action { + public: + /// Standard constructor + Geant4RunAction(Geant4Context* context, const std::string& nam); + /// Default destructor + virtual ~Geant4RunAction(); + /// begin-of-run callback + virtual void begin(const G4Run* run); + /// End-of-run callback + virtual void end(const G4Run* run); + }; + + /** @class Geant4RunActionSequence Geant4Action.h DDG4/Geant4Action.h + * + * Concrete implementation of the Geant4 run action sequence + * + * @author M.Frank + * @version 1.0 + */ + class Geant4RunActionSequence : public Geant4Action { + protected: + /// Callback sequence for begin-run action + CallbackSequence m_begin; + /// Callback sequence for end-run action + CallbackSequence m_end; + /// The list of action objects to be called + Actors<Geant4RunAction> m_actors; + public: + /// Standard constructor + Geant4RunActionSequence(Geant4Context* context, const std::string& nam); + /// Default destructor + virtual ~Geant4RunActionSequence(); + /// Register begin-of-run callback. Types Q and T must be polymorph! + template <typename Q, typename T> + void callAtBegin(Q* p, void (T::*f)(const G4Run*)) { m_begin.add(p,f); } + /// Register end-of-run callback. Types Q and T must be polymorph! + template <typename Q,typename T> + void callAtEnd (Q* p, void (T::*f)(const G4Run*)) { m_end.add(p,f); } + /// Add an actor responding to all callbacks. Sequence takes ownership. + void adopt(Geant4RunAction* action); + /// begin-of-run callback + virtual void begin(const G4Run* run); + /// End-of-run callback + virtual void end(const G4Run* run); + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4RUNACTION_H diff --git a/DDG4/include/DDG4/Geant4SensDetAction.h b/DDG4/include/DDG4/Geant4SensDetAction.h new file mode 100644 index 0000000000000000000000000000000000000000..10c1496c8566d4167139924a12530123a31ebd61 --- /dev/null +++ b/DDG4/include/DDG4/Geant4SensDetAction.h @@ -0,0 +1,348 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4SENSDETACTION_H +#define DD4HEP_DDG4_GEANT4SENSDETACTION_H + +// Framework include files +#include "DD4hep/LCDD.h" +#include "DDG4/Geant4Action.h" +#include "DDG4/Geant4HitCollection.h" + +// C/C++ include files +#include <vector> + +// Forward declarations +class G4HCofThisEvent; +class G4Step; +class G4Event; +class G4TouchableHistory; +class G4VHitsCollection; +class G4VReadOutGeometry; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + // Forward declarations + class Geant4StepHandler; + class Geant4HitCollection; + class Geant4Sensitive; + class Geant4SensDetActionSequence; + class Geant4SensDetSequences; + + /** @class Geant4ActionSD Geant4SensDetAction.h DDG4/Geant4SensDetAction.h + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4ActionSD : virtual public Geant4Action { + protected: + /// Standard action constructor + Geant4ActionSD(const std::string& name); + /// Default destructor + virtual ~Geant4ActionSD(); + public: + /// Initialize the usage of a hit collection. Returns the collection identifier + virtual size_t defineCollection(const std::string& name) = 0; + /// Access to the readout geometry of the sensitive detector + virtual G4VReadOutGeometry* readoutGeometry() const = 0; + /// This is a utility method which returns the hits collection ID + virtual G4int GetCollectionID(G4int i) = 0; + /// Is the detector active? + virtual bool isActive() const = 0; + /// G4VSensitiveDetector internals: Access to the detector path name + virtual std::string path() const = 0; + /// G4VSensitiveDetector internals: Access to the detector path name + virtual std::string fullPath() const = 0; + }; + + /** @class Geant4Filter Geant4SensDetAction.h DDG4/Geant4SensDetAction.h + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4Filter : public Geant4Action { + /// Standard constructor + Geant4Filter(Geant4Context* context, const std::string& name); + /// Standard destructor + virtual ~Geant4Filter(); + /// Filter action. Return true if hits should be processed + virtual bool operator()(const G4Step* step) const; + }; + + /** @class Geant4Sensitive Geant4SensDetAction.h DDG4/Geant4SensDetAction.h + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4Sensitive : public Geant4Action { + typedef Geometry::LCDD LCDD; + typedef Geometry::Readout Readout; + typedef Geometry::DetElement DetElement; + typedef Geometry::SensitiveDetector SensitiveDetector; + typedef Geant4StepHandler StepHandler; + typedef Geant4HitCollection HitCollection; + + private: + /// Reference to G4 sensitive detector + Geant4ActionSD* m_sensitiveDetector; + /// Reference to the containing action sequence + Geant4SensDetActionSequence* m_sequence; + + protected: + /// Reference to the detector description object + LCDD& m_lcdd; + /// Reference to the detector element describing this sensitive element + DetElement m_detector; + /// Reference to the sensitive detector element + SensitiveDetector m_sensitive; + /// Reference to the readout structure + Readout m_readout; + /// The list of sensitive detector filter objects + Actors<Geant4Filter> m_filters; + + public: + /// Constructor. The sensitive detector element is identified by the detector name + Geant4Sensitive(Geant4Context* context, const std::string& name, DetElement det, LCDD& lcdd); + + /// Standard destructor + virtual ~Geant4Sensitive(); + + /// Access to the sensitive detector object + Geant4ActionSD& detector() const; + + /// Access to the sensitive detector object + void setDetector(Geant4ActionSD* sens_det); + + /// G4VSensitiveDetector internals: Access to the detector name + std::string detectorName() const + { return detector().name(); } + + /// G4VSensitiveDetector internals: Access to the detector path name + std::string path() const + { return detector().path(); } + + /// G4VSensitiveDetector internals: Access to the detector path name + std::string fullPath() const + { return detector().fullPath(); } + + /// G4VSensitiveDetector internals: Is the detector active? + bool isActive() const + { return detector().isActive(); } + + /// Access to the readout geometry of the sensitive detector + G4VReadOutGeometry* readoutGeometry() const + { return detector().readoutGeometry(); } + + /// Access to the hosting sequence + Geant4SensDetActionSequence& sequence() const; + + /// Add an actor responding to all callbacks. Sequence takes ownership. + void adopt(Geant4Filter* filter); + + /// Callback before hit processing starts. Invoke all filters. + /** Return fals if any filter returns false + */ + bool accept(const G4Step* step) const; + + /// Initialize the usage of a single hit collection. Returns the collection ID + template<typename TYPE> size_t defineCollection(const std::string& coll_name); + + /// Access HitCollection container names + const std::string& hitCollectionName(size_t which) const; + + /// Retrieve the hits collection associated with this detector by its serial number + HitCollection* collection(size_t which); + + /// Retrieve the hits collection associated with this detector by its collection identifier + HitCollection* collectionByID(size_t id); + + /// G4VSensitiveDetector interface: Method invoked at the begining of each event. + /** The hits collection(s) created by this sensitive detector must + * be set to the G4HCofThisEvent object at one of these two methods. + */ + virtual void begin(G4HCofThisEvent* hce); + + /// G4VSensitiveDetector interface: Method invoked at the end of each event. + virtual void end(G4HCofThisEvent* hce); + + /// G4VSensitiveDetector interface: Method for generating hit(s) using the information of G4Step object. + virtual bool process(G4Step* step,G4TouchableHistory* history); + + /// G4VSensitiveDetector interface: Method invoked if the event was aborted. + /** Hits collections created but not being set to G4HCofThisEvent + * at the event should be deleted. + * Collection(s) which have already set to G4HCofThisEvent + * will be deleted automatically. + */ + virtual void clear(G4HCofThisEvent* hce); + + /// Returns the volumeID of the sensitive volume corresponding to the step + /** Combining the VolIDS of the complete geometry path (Geant4TouchableHistory) + * from the current sensitive volume to the world volume + */ + long long int volumeID(G4Step* step); + + }; + + /** @class Geant4SensDetActionSequence Geant4SensDetAction.h DDG4/Geant4SensDetAction.h + * + * Concrete implementation of the sensitive detector action sequence + * + * @author M.Frank + * @version 1.0 + */ + class Geant4SensDetActionSequence : public Geant4Action { + public: + typedef G4VHitsCollection* (*create_t)(const std::string&,const std::string&); + typedef std::vector<std::pair<std::string,create_t> > HitCollections; + + protected: + /// Geant4 hit collection context + G4HCofThisEvent* m_hce; + /// Callback sequence for event initialization action + CallbackSequence m_begin; + /// Callback sequence for event finalization action + CallbackSequence m_end; + /// Callback sequence for step processing + CallbackSequence m_process; + /// Callback sequence to invoke the event deletion + CallbackSequence m_clear; + /// The list of sensitive detector objects + Actors<Geant4Sensitive> m_actors; + /// The list of sensitive detector filter objects + Actors<Geant4Filter> m_filters; + + /// Hit collection creators + HitCollections m_collections; + /// Reference to G4 sensitive detector + Geant4ActionSD* m_detector; + /// Create a new typed hit collection + template <typename TYPE> static G4VHitsCollection* _create(const std::string& det, const std::string& coll) { + return new Geant4HitCollection(det,coll,(TYPE*)0); + } + + public: + /// Standard constructor + Geant4SensDetActionSequence(Geant4Context* context, const std::string& name); + + /// Default destructor + virtual ~Geant4SensDetActionSequence(); + + /// Called at construction time of the sensitive detector to declare all hit collections + size_t defineCollections(Geant4ActionSD* sens_det); + + /// Initialize the usage of a hit collection. Returns the collection identifier + size_t defineCollection(const std::string& name,create_t func); + + /// Define a named collection containing hist of a specified type + template <typename TYPE> size_t defineCollection(const std::string& coll_name) { + return defineCollection(coll_name,Geant4SensDetActionSequence::_create<TYPE>); + } + + /// Access HitCollection container names + const std::string& hitCollectionName(size_t which) const; + /// Retrieve the hits collection associated with this detector by its serial number + Geant4HitCollection* collection(size_t which) const; + /// Retrieve the hits collection associated with this detector by its collection identifier + Geant4HitCollection* collectionByID(size_t id) const; + /// Register begin-of-event callback + template <typename T> void callAtBegin(T* p, void (T::*f)(G4HCofThisEvent*)) + { m_begin.add(p,f);} + + /// Register end-of-event callback + template <typename T> void callAtEnd(T* p, void (T::*f)(G4HCofThisEvent*)) + { m_end.add(p,f);} + + /// Register process-hit callback + template <typename T> void callAtProcess(T* p, void (T::*f)(G4Step*,G4TouchableHistory*)) + { m_process.add(p,f);} + + /// Register clear callback + template <typename T> void callAtClear(T* p, void (T::*f)(G4HCofThisEvent*)) + { m_clear.add(p,f);} + + /// Add an actor responding to all callbacks. Sequence takes ownership. + void adopt(Geant4Sensitive* sensitive); + + /// Add an actor responding to all callbacks. Sequence takes ownership. + void adopt(Geant4Filter* filter); + + /// Callback before hit processing starts. Invoke all filters. + /** Return fals if any filter returns false + */ + bool accept(const G4Step* step) const; + + /// Function to process hits + virtual bool process(G4Step* step, G4TouchableHistory* hist); + + /// G4VSensitiveDetector interface: Method invoked at the begining of each event. + /** The hits collection(s) created by this sensitive detector must + * be set to the G4HCofThisEvent object at one of these two methods. + */ + virtual void begin(G4HCofThisEvent* hce); + + /// G4VSensitiveDetector interface: Method invoked at the end of each event. + + virtual void end(G4HCofThisEvent* hce); + /// G4VSensitiveDetector interface: Method invoked if the event was aborted. + /** Hits collections created but not beibg set to G4HCofThisEvent + * at the event should be deleted. + * Collection(s) which have already set to G4HCofThisEvent + * will be deleted automatically. + */ + virtual void clear(); + }; + + /** @class Geant4SensDetActionSequences Geant4SensDetAction.h DDG4/Geant4SensDetAction.h + * + * Concrete implementation of the sensitive detector action sequence + * + * @author M.Frank + * @version 1.0 + */ + class Geant4SensDetSequences { + public: + friend class Geant4Kernel; + friend class Geant4SensDetActionSequence; + typedef std::map<std::string,Geant4SensDetActionSequence*> Members; + private: + Members m_sequences; + /// Insert sequence member + void insert(const std::string& name,Geant4SensDetActionSequence* seq); + public: + /// Default constructor + Geant4SensDetSequences(); + /// Default destructor + virtual ~Geant4SensDetSequences(); + /// Access sequence member by name + Geant4SensDetActionSequence* operator[](const std::string& name) const; + /// Access sequence member by name + Geant4SensDetActionSequence* find(const std::string& name) const; + /// Access to the members + Members& sequences() { return m_sequences; } + /// Access to the members CONST + const Members& sequences() const { return m_sequences; } + }; + + /// Initialize the usage of a single hit collection. Returns the collection ID + template<typename TYPE> inline size_t Geant4Sensitive::defineCollection(const std::string& coll_name) + { return sequence().defineCollection<TYPE>(coll_name); } + + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4RUNACTION_H diff --git a/DDG4/include/DDG4/Geant4SensitiveDetector_inline.h b/DDG4/include/DDG4/Geant4SensitiveDetector_inline.h index 0abb7f389ad8360e66267c40f4a088638efa70c2..23f8ad580e3d5f22064398a1a298333ec5c81244 100644 --- a/DDG4/include/DDG4/Geant4SensitiveDetector_inline.h +++ b/DDG4/include/DDG4/Geant4SensitiveDetector_inline.h @@ -17,6 +17,7 @@ template<class SD> DD4hep::Simulation::Geant4GenericSD<SD>::Geant4GenericSD(const std::string& name, LCDD& lcdd) : Geant4SensitiveDetector(name,lcdd) { + defineCollection(m_sensitive.hitsCollection()); } /// Initialize the sensitive detector for the usage of a single hit collection diff --git a/DDG4/include/DDG4/Geant4StackingAction.h b/DDG4/include/DDG4/Geant4StackingAction.h new file mode 100644 index 0000000000000000000000000000000000000000..c96bb20ceb0ef78288dc56611198ed38421a1fe8 --- /dev/null +++ b/DDG4/include/DDG4/Geant4StackingAction.h @@ -0,0 +1,79 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4STACKINGACTION_H +#define DD4HEP_DDG4_GEANT4STACKINGACTION_H + +// Framework include files +#include "DDG4/Geant4Action.h" + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + /** @class Geant4StackingAction Geant4Action.h DDG4/Geant4Action.h + * + * Concrete implementation of the Geant4 stacking action base class + * + * @author M.Frank + * @version 1.0 + */ + class Geant4StackingAction : public Geant4Action { + public: + /// Standard constructor + Geant4StackingAction(Geant4Context* context, const std::string& name); + /// Default destructor + virtual ~Geant4StackingAction(); + /// New-stage callback + virtual void newStage() {} + /// Preparation callback + virtual void prepare() {} + }; + + /** @class Geant4StackingActionSequence Geant4Action.h DDG4/Geant4Action.h + * + * Concrete implementation of the Geant4 stacking action sequence + * + * @author M.Frank + * @version 1.0 + */ + class Geant4StackingActionSequence : public Geant4Action { + protected: + /// Callback sequence for the newStage call + CallbackSequence m_newStage; + // Callback sequence for the prepare call + CallbackSequence m_prepare; + /// The list of action objects to be called + Actors<Geant4StackingAction> m_actors; + public: + /// Standard constructor + Geant4StackingActionSequence(Geant4Context* context, const std::string& name); + /// Default destructor + virtual ~Geant4StackingActionSequence(); + /// Register begin-of-event callback. Types Q and T must be polymorph! + template <typename T> void callAtNewStage(T* p, void (T::*f)()) { m_newStage.add(p,f);} + /// Register end-of-event callback. Types Q and T must be polymorph! + template <typename T> void callAtPrepare(T* p, void (T::*f)()) { m_prepare.add(p,f); } + /// Add an actor responding to all callbacks. Sequence takes ownership. + void adopt(Geant4StackingAction* action); + /// New-stage callback + virtual void newStage(); + /// Preparation callback + virtual void prepare(); + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4STACKINGACTION_H diff --git a/DDG4/include/DDG4/Geant4SteppingAction.h b/DDG4/include/DDG4/Geant4SteppingAction.h new file mode 100644 index 0000000000000000000000000000000000000000..9c59c7eeb542f262a415d2ef2f1d2f534ab7e605 --- /dev/null +++ b/DDG4/include/DDG4/Geant4SteppingAction.h @@ -0,0 +1,77 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4STEPPINGACTION_H +#define DD4HEP_DDG4_GEANT4STEPPINGACTION_H + +// Framework include files +#include "DDG4/Geant4Action.h" + +// Forward declarations +class G4SteppingManager; +class G4Step; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + /** @class Geant4SteppingAction Geant4Action.h DDG4/Geant4Action.h + * + * Concrete implementation of the Geant4 stepping action sequence + * + * @author M.Frank + * @version 1.0 + */ + class Geant4SteppingAction : public Geant4Action { + public: + /// Standard constructor + Geant4SteppingAction(Geant4Context* context, const std::string& name); + /// Default destructor + virtual ~Geant4SteppingAction(); + /// User stepping callback + virtual void operator()(const G4Step* step, G4SteppingManager* mgr); + }; + + /** @class Geant4SteppingActionSequence Geant4Action.h DDG4/Geant4Action.h + * + * Concrete implementation of the Geant4 stepping action sequence + * + * @author M.Frank + * @version 1.0 + */ + class Geant4SteppingActionSequence : public Geant4Action { + protected: + /// Callback sequence for user stepping action calls + CallbackSequence m_calls; + /// The list of action objects to be called + Actors<Geant4SteppingAction> m_actors; + + public: + /// Standard constructor + Geant4SteppingActionSequence(Geant4Context* context, const std::string& name); + /// Default destructor + virtual ~Geant4SteppingActionSequence(); + /// Register stepping action callback. Types Q and T must be polymorph! + template <typename Q, typename T> + void call(Q* p, void (T::*f)(const G4Step*,G4SteppingManager*)) { m_calls.add(p,f); } + /// Add an actor responding to all callbacks. Sequence takes ownership. + void adopt(Geant4SteppingAction* action); + /// User stepping callback + virtual void operator()(const G4Step* step, G4SteppingManager* mgr); + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4STEPPINGACTION_H diff --git a/DDG4/include/DDG4/Geant4TestActions.h b/DDG4/include/DDG4/Geant4TestActions.h new file mode 100644 index 0000000000000000000000000000000000000000..da7ae03c59230b234f4981c2402e602561001a93 --- /dev/null +++ b/DDG4/include/DDG4/Geant4TestActions.h @@ -0,0 +1,115 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4TESTACTIONS_H +#define DD4HEP_DDG4_GEANT4TESTACTIONS_H + +// Framework include files +#include "DDG4/Geant4Handle.h" +#include "DDG4/Geant4Kernel.h" +#include "DDG4/Geant4GeneratorAction.h" +#include "DDG4/Geant4RunAction.h" +#include "DDG4/Geant4EventAction.h" +#include "DDG4/Geant4TrackingAction.h" +#include "DDG4/Geant4SteppingAction.h" +#include "DDG4/Geant4StackingAction.h" +#include "DDG4/Geant4ActionPhase.h" +#include "DDG4/Geant4SensDetAction.h" + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + namespace Test { + /** @class Geant4TestRunAction + * + * @author M.Frank + * @version 1.0 + */ + class Geant4TestBase { + protected: + int m_value1; + double m_value2; + std::string m_value3; + std::string m_type; + public: + /// Standard constructor + Geant4TestBase(Geant4Action* action, const std::string& typ); + /// Default destructor + virtual ~Geant4TestBase(); + }; + struct Geant4TestRunAction : public Geant4RunAction, public Geant4TestBase { + /// Standard constructor with initializing arguments + Geant4TestRunAction(Geant4Context* c, const std::string& n); + /// Default destructor + virtual ~Geant4TestRunAction(); + /// begin-of-run callback + void begin(const G4Run* ); + /// End-of-run callback + void end (const G4Run* ); + /// begin-of-event callback + void beginEvent(const G4Event* ); + /// End-of-event callback + void endEvent (const G4Event* ); + }; + struct Geant4TestEventAction : public Geant4EventAction, public Geant4TestBase { + /// Standard constructor with initializing arguments + Geant4TestEventAction(Geant4Context* c, const std::string& n); + /// Default destructor + virtual ~Geant4TestEventAction(); + /// begin-of-event callback + virtual void begin(const G4Event* ); + /// End-of-event callback + virtual void end (const G4Event* ); + /// begin-of-run callback + void beginRun(const G4Run* ); + /// End-of-run callback + void endRun (const G4Run* ); + }; + struct Geant4TestTrackAction : public Geant4TrackingAction, public Geant4TestBase { + /// Standard constructor with initializing arguments + Geant4TestTrackAction(Geant4Context* c, const std::string& n); + /// Default destructor + virtual ~Geant4TestTrackAction(); + /// Begin-of-tracking callback + virtual void begin(const G4Track* ); + /// End-of-tracking callback + virtual void end(const G4Track* ); + }; + struct Geant4TestStepAction : public Geant4SteppingAction, public Geant4TestBase { + /// Standard constructor with initializing arguments + Geant4TestStepAction(Geant4Context* c, const std::string& n); + /// Default destructor + virtual ~Geant4TestStepAction(); + /// User stepping callback + void operator()(const G4Step* , G4SteppingManager* ); + }; + struct Geant4TestSensitive : public Geant4Sensitive, public Geant4TestBase { + size_t m_collectionID; + /// Standard constructor with initializing arguments + Geant4TestSensitive(Geant4Context* c, const std::string& n, DetElement det, LCDD& lcdd); + /// Default destructor + virtual ~Geant4TestSensitive(); + /// Begin-of-tracking callback + virtual void begin(G4HCofThisEvent* ); + /// End-of-tracking callback + virtual void end(G4HCofThisEvent* ); + /// Method for generating hit(s) using the information of G4Step object. + virtual bool process(G4Step* ,G4TouchableHistory* ); + }; + } // End namespace Test + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4TESTACTIONS_H diff --git a/DDG4/include/DDG4/Geant4TrackHandler.h b/DDG4/include/DDG4/Geant4TrackHandler.h new file mode 100644 index 0000000000000000000000000000000000000000..f56428bb968808fb77bec81e953946eb8c4275c5 --- /dev/null +++ b/DDG4/include/DDG4/Geant4TrackHandler.h @@ -0,0 +1,102 @@ +// $Id: Geant4TrackHandler.h 683 2013-08-08 16:18:20Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_GEANT4TRACKHANDLER_H +#define DD4HEP_GEANT4TRACKHANDLER_H + +// Framework include files +#include "DDG4/Defs.h" + +// Geant4 include files +#include "G4Track.hh" +#include "G4TrajectoryPoint.hh" +#include "G4VTouchable.hh" +#include "G4VSensitiveDetector.hh" + +// Forward declarations +class G4VTouchableHandle; +class G4VUserTrackInformation; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + // Forward declarations; + class Geant4TrackHandler; + + /** @class Geant4TrackHandler Geant4SensitiveDetector.h DDG4/Geant4SensitiveDetector.h + * + * Tiny helper/utility class to easily access Geant4 track information. + * Born by lazyness: Avoid typing millions of statements! + * + * @author M.Frank + * @version 1.0 + */ + class Geant4TrackHandler { + public: + typedef G4VUserTrackInformation Info; + typedef G4ReferenceCountedHandle<G4VTouchable> Touchable; + /// Reference to the track object + const G4Track* track; + /// Initializing constructor + Geant4TrackHandler(const G4Track* t) : track(t) { } + /// Conversion to G4Track + operator const G4Track* () const { return track; } + /// Track's particle definition + G4ParticleDefinition* trackDef() const { return track->GetDefinition(); } + /// Track position + const G4ThreeVector& position() const { return track->GetPosition(); } + /// Track energy + double energy() const { return track->GetTotalEnergy(); } + /// Track velocity + double velocity() const { return track->GetVelocity(); } + /// Track length + double length() const { return track->GetTrackLength(); } + /// Track time + double time() const { return track->GetGlobalTime(); } + /// Physical (original) volume of the track + G4VPhysicalVolume* vol() const { return track->GetVolume(); } + /// Next physical volume of the track + G4VPhysicalVolume* nextVol() const { return track->GetNextVolume(); } + /// Logical volume of the origine vertex + const G4LogicalVolume* vertexVol() const { return track->GetLogicalVolumeAtVertex(); } + + /// Touchable of the track + const Touchable& touchable() const { return track->GetTouchableHandle(); } + /// Next touchable of the track + const Touchable& nextTouchable() const { return track->GetNextTouchableHandle(); } + + /// Physical process of the track generation + const G4VProcess* creatorProcess() const { return track->GetCreatorProcess(); } + /// User information block + Info* userInfo() const { return track->GetUserInformation(); } + /// Set user information block (const mis-match) + //void setUserInfo(Info* info) { track->SetUserInformation(info); } + /// Specific user information block + template <typename T> T* info() const { return (T*)userInfo(); } + /// Step information + const G4Step* step() const { return track->GetStep(); } + /// Step number + G4int stepNumber() const { return track->GetCurrentStepNumber(); } + + int pdgID() const { + G4ParticleDefinition* def = trackDef(); + return def ? def->GetPDGEncoding() : 0; + } + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_GEANT4HITS_H diff --git a/DDG4/include/DDG4/Geant4TrackingAction.h b/DDG4/include/DDG4/Geant4TrackingAction.h new file mode 100644 index 0000000000000000000000000000000000000000..c695714af50f67e14f27a3ca226373047b59c8f0 --- /dev/null +++ b/DDG4/include/DDG4/Geant4TrackingAction.h @@ -0,0 +1,94 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4TRACKINGACTION_H +#define DD4HEP_DDG4_GEANT4TRACKINGACTION_H + +// Framework include files +#include "DDG4/Geant4Action.h" +#include "G4VUserTrackInformation.hh" + +class G4TrackingManager; +class G4Track; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + // Forward declarations + class Geant4TrackInformation; + + /** @class Geant4TrackingAction Geant4Action.h DDG4/Geant4Action.h + * + * Default base class for all geant 4 tracking actions. + * + * @author M.Frank + * @version 1.0 + */ + class Geant4TrackingAction : public Geant4Action { + public: + /// Standard constructor + Geant4TrackingAction(Geant4Context* context, const std::string& name=""); + /// Default destructor + virtual ~Geant4TrackingAction(); + /// Access the tracking manager + G4TrackingManager* trackMgr() const { return m_context->trackMgr(); } + /// Get the valid Geant4 tarck information + Geant4TrackInformation* trackInfo(G4Track* track) const; + /// Mark all children of the track to be stored + bool storeChildren() const; + /// Mark a single child of the track to be stored + bool storeChild(Geant4TrackInformation* info) const; + /// Pre-track action callback + virtual void begin(const G4Track* trk); + /// Post-track action callback + virtual void end(const G4Track* trk); + }; + + /** @class Geant4EventActionSequence Geant4Action.h DDG4/Geant4Action.h + * + * Concrete implementation of the Geant4 tracking action sequence + * + * @author M.Frank + * @version 1.0 + */ + class Geant4TrackingActionSequence : public Geant4Action { + protected: + /// Callback sequence for pre tracking action + CallbackSequence m_begin; + /// Callback sequence for post tracking action + CallbackSequence m_end; + /// The list of action objects to be called + Actors<Geant4TrackingAction> m_actors; + public: + /// Standard constructor + Geant4TrackingActionSequence(Geant4Context* context, const std::string& name); + /// Default destructor + virtual ~Geant4TrackingActionSequence(); + /// Register Pre-track action callback + template <typename Q, typename T> void callAtBegin(Q* p, void (T::*f)(const G4Track*)) { m_begin.add(p,f);} + /// Register Post-track action callback + template <typename Q, typename T> void callAtEnd(Q* p, void (T::*f)(const G4Track*)) { m_end.add(p,f); } + /// Add an actor responding to all callbacks. Sequence takes ownership. + void adopt(Geant4TrackingAction* action); + /// Pre-track action callback + virtual void begin(const G4Track* trk); + /// Post-track action callback + virtual void end(const G4Track* trk); + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4TRACKINGACTION_H diff --git a/DDG4/include/DDG4/Geant4TrackingPostAction.h b/DDG4/include/DDG4/Geant4TrackingPostAction.h new file mode 100644 index 0000000000000000000000000000000000000000..f7bcc8a5d7b596f29f8e2ff665f546f897a02215 --- /dev/null +++ b/DDG4/include/DDG4/Geant4TrackingPostAction.h @@ -0,0 +1,56 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4TRACKINGPOSTACTION_H +#define DD4HEP_DDG4_GEANT4TRACKINGPOSTACTION_H + +// Framework include files +#include "DDG4/Geant4TrackingAction.h" +#include <vector> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + /** @class Geant4TrackingPostAction Geant4TrackingPostAction.h DDG4/Geant4TrackingPostAction.h + * + * Default base class for all geant 4 tracking actions. + * + * @author M.Frank + * @version 1.0 + */ + class Geant4TrackingPostAction : public Geant4TrackingAction { + protected: + typedef std::vector<std::string> StringV; + StringV m_requiredProcs; + StringV m_ignoredProcs; + bool m_storeMarkedTracks; + public: + /// Standard constructor + Geant4TrackingPostAction(Geant4Context* context, const std::string& name=""); + /// Default destructor + virtual ~Geant4TrackingPostAction(); + + /// + void saveTrack(const G4Track* track); + + /// Begin-of-tracking callback + virtual void begin(const G4Track* track); + /// End-of-tracking callback + virtual void end(const G4Track* track); + }; + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4TRACKINGPOSTACTION_H diff --git a/DDG4/include/DDG4/Geant4TrackingPreAction.h b/DDG4/include/DDG4/Geant4TrackingPreAction.h new file mode 100644 index 0000000000000000000000000000000000000000..b3b75c4d097f6454b6cfebc4439a981ce7f9455a --- /dev/null +++ b/DDG4/include/DDG4/Geant4TrackingPreAction.h @@ -0,0 +1,46 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4TRACKINGPREACTION_H +#define DD4HEP_DDG4_GEANT4TRACKINGPREACTION_H + +// Framework include files +#include "DDG4/Geant4TrackingAction.h" + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + /** @class Geant4TrackingPreAction Geant4TrackingPreAction.h DDG4/Geant4TrackingPreAction.h + * + * Default base class for all geant 4 tracking actions. + * + * @author M.Frank + * @version 1.0 + */ + class Geant4TrackingPreAction : public Geant4TrackingAction { + public: + /// Standard constructor + Geant4TrackingPreAction(Geant4Context* context, const std::string& name=""); + /// Default destructor + virtual ~Geant4TrackingPreAction(); + /// Begin-of-tracking callback + virtual void begin(const G4Track* track); + /// End-of-tracking callback + virtual void end(const G4Track* track); + }; + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4TRACKINGPREACTION_H diff --git a/DDG4/include/DDG4/Parsers.h b/DDG4/include/DDG4/Parsers.h new file mode 100644 index 0000000000000000000000000000000000000000..0634e77fa560dfbcd9012bb276bc919c4792be6e --- /dev/null +++ b/DDG4/include/DDG4/Parsers.h @@ -0,0 +1,533 @@ +// ============================================================================ +#ifndef DD4HEP_PARSERS_H +#define DD4HEP_PARSERS_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <string> +#include <vector> +#include <list> +#include <set> +#include <map> + +// ============================================================================ +#define PARSERS_DECL_FOR_SINGLE(Type) \ + int parse(Type& result, const std::string& input); + +#define PARSERS_DECL_FOR_PAIR(FirstType, SecondType) \ + int parse(std::pair<FirstType, SecondType >& result,const std::string& input); + +#define PARSERS_DECL_FOR_LIST(InnerType) \ + int parse(std::vector<InnerType>& result,const std::string& input); \ + int parse(std::list<InnerType>& result,const std::string& input); \ + int parse(std::set<InnerType>& result,const std::string& input); +// ============================================================================ +/** @file + * The declaration of major parsing functions used e.g + * for (re)implementation of new extended properties see class Property + * These function also could be used in a different, much wider contex. + * all of them have the semantic: + * <c>int parse ( TYPE& result , const std::string& input )</c> + * where <c>input</c> is the input string to be parsed, + * and <c>result</c> is the the result of parsing + * + * @code + * + * const std::string input = ... ; + * std::vector<std::string> result ; + * + * // parse the input + * int sc = parse ( result , input ) ; + * if ( sc.isFailure() ) + * { + * // error here ... + * } + * std::cout << "vector size " << result.size() << std::endl ; + * + * @endcode + * + * @see DD4hep::Parsers::parse + * @see Property + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ +// ============================================================================ +namespace DD4hep { + namespace Parsers { + // ======================================================================== + /** parse the <c>bool</c> value + * @see DD4hep::Parsers::BoolGrammar + * @param result (output) boolean result + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + PARSERS_DECL_FOR_SINGLE(bool) + // ======================================================================== + /** parse the <c>char</c> value + * + * @see DD4hep::Parsers::CharGrammar + * @param result (output) boolean result + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + PARSERS_DECL_FOR_SINGLE(char) + /// @see DD4hep::Parsers::parser(char&,std::string&) + PARSERS_DECL_FOR_SINGLE(unsigned char) + /// @see DD4hep::Parsers::parser(char&,std::string&) + PARSERS_DECL_FOR_SINGLE(signed char) + // ======================================================================== + /** parse the <c>int</c> value + * + * @see DD4hep::Parsers::IntGrammar + * @param result (output) integer result + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + PARSERS_DECL_FOR_SINGLE(int) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(short) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(unsigned short) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(unsigned int) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(long) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(unsigned long) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(long long) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(unsigned long long) + // ======================================================================== + /** parse the <c>double</c> value + * + * @see DD4hep::Parsers::RealGrammar + * @param result (output) double result + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + PARSERS_DECL_FOR_SINGLE(double) + /// @see DD4hep::Parsers::parser( double&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(float) + /// @see DD4hep::Parsers::parser( double&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(long double) + // ======================================================================== + /** parse the <c>std::string</c> value + * + * @see DD4hep::Parsers::StringGrammar + * @param result (output) string result + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + PARSERS_DECL_FOR_SINGLE(std::string) + // ======================================================================== + + PARSERS_DECL_FOR_LIST(bool) + PARSERS_DECL_FOR_LIST(char) + PARSERS_DECL_FOR_LIST(unsigned char) + PARSERS_DECL_FOR_LIST(signed char) + + PARSERS_DECL_FOR_LIST(int) + PARSERS_DECL_FOR_LIST(short) + PARSERS_DECL_FOR_LIST(unsigned short) + PARSERS_DECL_FOR_LIST(unsigned int) + PARSERS_DECL_FOR_LIST(long) + PARSERS_DECL_FOR_LIST(unsigned long) + PARSERS_DECL_FOR_LIST(long long) + PARSERS_DECL_FOR_LIST(unsigned long long) + + PARSERS_DECL_FOR_LIST(double) + PARSERS_DECL_FOR_LIST(float) + PARSERS_DECL_FOR_LIST(long double) + + PARSERS_DECL_FOR_LIST(std::string) + // ======================================================================== + // Advanced parses + // ======================================================================== + /** parse the <c>std::pair\<double,double\></c> value + * + * @see DD4hep::Parsers::PairGrammar + * @see DD4hep::Parsers::RealGrammar + * @param result (output) pair of doubles + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + PARSERS_DECL_FOR_PAIR(double,double) + // ======================================================================== + /** parse the <c>std::pair\<int,int\></c> value + * + * @see DD4hep::Parsers::PairGrammar + * @see DD4hep::Parsers::IntGrammar + * @param result (output) pair of integers + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + PARSERS_DECL_FOR_PAIR(int, int) + // ======================================================================== + /** parse the <c>std::vector\<std::pair\<double,double\> \></c> value + * + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::PairGrammar + * @see DD4hep::Parsers::RealGrammar + * @param result (output) vector with pairs of doubles + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::vector< std::pair<double,double> >& result,const std::string& input); + // ======================================================================== + /** parse the <c>std::vector\<std::pair\<int,int\> \></c> value + * + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::PairGrammar + * @see DD4hep::Parsers::IntGrammar + * @param result (output) vector with pairs of int + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse + ( std::vector< std::pair<int,int> >& result , + const std::string& input ) ; + // ======================================================================== + // vector< vector< TYPE > > + // ======================================================================== + /** parse the <c>std::vector\<std::vector\<std::string\> \></c> value + * + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::StringGrammar + * @param result (output) vector with vectors of strings + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::vector< std::vector<std::string> >& result,const std::string& input); + // ======================================================================== + /** parse the <c>std::vector\<std::vector\<double\> \></c> value + * + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::RealGrammar + * @param result (output) vector with vectors of doubles + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::vector< std::vector<double> >& result,const std::string& input); + // ======================================================================== + // map< TYPE, TYPE > + // ======================================================================== + /** parse the <c>std::map\<int , int\></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::IntGrammar + * @param result (output) map with integer key and double value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse + ( std::map< int , int >& result , + const std::string& input ) ; + // ======================================================================== + /** parse the <c>std::map\<int , double\></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::IntGrammar + * @see DD4hep::Parsers::RealGrammar + * @param result (output) map with integer key and double value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse + ( std::map< int , double >& result , + const std::string& input ) ; + // ======================================================================== + /** parse the <c>std::map\<std::string , std::string\></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::StringGrammar + * @param result (output) map with string key and value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse + ( std::map< std::string , std::string >& result , + const std::string& input ) ; + // ======================================================================== + /** parse the <c>std::map\<std::string , int\></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::StringGrammar + * @see DD4hep::Parsers::IntGrammar + * @param result (output) map with string key and integer value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse + ( std::map< std::string , int >& result , + const std::string& input ) ; + // ======================================================================== + /** parse the <c>std::map\<std::string , double\></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::StringGrammar + * @see DD4hep::Parsers::RealGrammar + * @param result (output) map with string key and integer value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse + ( std::map< std::string , double >& result , + const std::string& input ) ; + // ======================================================================== + /** parse the <c>std::map\<std::string , std::vector\<std::string\> \></c> + * value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::StringGrammar + * @see DD4hep::Parsers::VectorGrammar + * @param result (output) map with string value and + * vector of strings as value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse + ( std::map< std::string , std::vector< std::string> >& result , + const std::string& input ) ; + // ======================================================================== + /** parse the <c>std::map\<std::string , std::vector\<int\> \></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::StringGrammar + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::IntGrammar + * @param result (output) map with string value and + * vector of integers as value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse + ( std::map< std::string , std::vector< int > >& result , + const std::string& input ) ; + // ======================================================================== + /** parse the <c>std::map\<std::string , std::vector\<double\> \></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::StringGrammar + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::RealGrammar + * @param result (output) map with string value and + * vector of doubles as value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse + ( std::map< std::string , std::vector< double > >& result , + const std::string& input ) ; + // ======================================================================== + /** parse the <c>std::map\<int,std::string\> \></c> objects + * + * @see DD4hep::Parsers::MapGrammar + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @date 2007-12-06 + */ + int parse + ( std::map<int, std::string>& result , + const std::string& input ) ; + // ======================================================================== + /** parse the <c>std::map\<unsigned int,std::string\> \></c> objects + * + * @see DD4hep::Parsers::MapGrammar + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @date 2007-12-06 + */ + int parse(std::map<unsigned int, std::string>& result,const std::string& input); + // ======================================================================== + /** parse the <c>std::map\<unsigned int,std::string\> \></c> objects + * + * @see DD4hep::Parsers::MapGrammar + */ + int parse(std::map<std::string, unsigned int>& result, const std::string& input); + + // ======================================================================== + /** parse the pair expression (map-component) " 'name' :value" + * + * @code + * + * const std::string input = "'PackageName':DD4hepKernel" ; + * std::string name ; + * std::string value ; + * int sc = DD4hep::Parsers::parse ( name , value , input ) ; + * if ( sc.isFailure() ) { ... } + * std::cout << "\tParsed name is " << name + * << "\tParsed value is " << value << std::endl + * @endcode + * + * @param name (output) the parsed name of the component, defined + * as 'name' or "name" before the column symbol ":", + * the leading and trailing blans are omitted + * @param value (output) the parsed value of the component, + * defined as everything after the column symbol ":" + * till the end of the string + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + int parse + ( std::string& name , + std::string& value , + const std::string& input ) ; + + // ======================================================================== + /** helper function, needed for implementation of map of pairs + * It is very useful construction for monitoring to + * represent the value and error or the allowed range for + * some parameter + * @param params the map of pair + * @param input the string to be parsed + * @return status code + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @date 2009-05-19 + */ + int parse + ( std::map<std::string,std::pair<double,double> >& params , + const std::string& input ) ; + // ======================================================================== + /** parser function for C-arrays + * @param params C-array + * @param input the string to be parsed + * @return status code + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-15 + */ + template <class T, unsigned int N> + int parse ( T(&result)[N] , const std::string& input ) + { + typedef std::vector<T> _Vct ; + // create the temporary vector + _Vct tmp ; + int sc = parse ( tmp , input ) ; + if ( !sc ) { return sc; } // RETURN + if ( N != tmp.size() ) { return 0; } // RETURN + // + std::copy ( tmp.begin() , tmp.end() , result ) ; + // + return 1; // RETURN + } + // ======================================================================== + /** parser function for C-strings + * @param params C-string + * @param input the string to be parsed + * @return status code + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-15 + */ + template <unsigned int N> + int parse ( char(&result)[N] , const std::string& input ) + { + // clear the string + std::fill_n ( result , N , ' ' ) ; + // create the temporary string + std::string tmp ; + int sc = parse ( tmp , input ) ; + if ( !sc ) { return sc ; } // RETURN + if ( N == tmp.size() ) + { std::copy ( tmp.begin() , tmp.end() , result ) ; } + else if ( N + 2 == tmp.size() && + ( '\'' == tmp[0] || '\"' == tmp[0] ) && + ( tmp[0] == tmp[tmp.size()-1] )) + { std::copy ( tmp.begin() + 1 , tmp.end() -1 , result ) ; } + else { return 0; } + // + return 1; // RETURN + } + // ======================================================================== + } // end of namespace Parsers + // ========================================================================== +} // end of namespace DD4hep +// ============================================================================ +// The END +// ============================================================================ +#endif // DD4HEP_PARSERS_H +// ============================================================================ diff --git a/DDG4/include/DDG4/ToStream.h b/DDG4/include/DDG4/ToStream.h new file mode 100644 index 0000000000000000000000000000000000000000..3297598170300116145049af0350a0b7b8af13b9 --- /dev/null +++ b/DDG4/include/DDG4/ToStream.h @@ -0,0 +1,309 @@ +// $Id: ToStream.h,v 1.8 2008/10/30 23:38:46 marcocle Exp $ +// ============================================================================ +// CVS tag $Name: $, version $Revision: 1.8 $ +// ============================================================================ +#ifndef DD4HEPPROPERTYPARSERS_PARSERVALUETOSTREAM_H +#define DD4HEPPROPERTYPARSERS_PARSERVALUETOSTREAM_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <iostream> +#include <iomanip> +#include <vector> +#include <map> +#include <set> +#include <list> +#include <string> +#include <sstream> + +// ============================================================================ +/** @file DD4hepKernel/ToStream.h + * implemenattiono fvarioud functions for streaming. + * this functionality is essenital for usag eof varuodu types as property for + * the various DD4hep components + * @attention the implemenation of the specific specializations must be done + * before the inclusion of this file + * @todo ToStream.h : reimplement in terms of functors, to allow + * easier especializations + */ +// ============================================================================ +namespace DD4hep +{ + // ========================================================================== + namespace Utils + { + // ======================================================================== + /** the generic implementation of the printout to the std::ostream + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template<class TYPE> + std::ostream& toStream ( const TYPE& obj, std::ostream& s ) ; + // ======================================================================== + /** the helper function to print the sequence + * @param first (INPUT) begin-iterator for the sequence + * @param last (INPUT) end-iterator for the sequence + * @param s (UPDATE) the stream itself + * @param open (INPUT) "open"-symbol + * @param close (INPUT) "close"-symbol + * @param delim (INPUT) "delimiter"-symbol + * @return the stream + * @author Vanya BELYAEV Ivan.BElyaev@nikhef.nl + * @date 2009-09-15 + */ + template <class ITERATOR> + inline std::ostream& toStream + ( ITERATOR first , // begin of the sequence + ITERATOR last , // end of the sequence + std::ostream& s , // the stream + const std::string& open , // opening + const std::string& close , // closing + const std::string& delim ) ; // delimiter + // ======================================================================== + /** the printtout of the strings. + * the string is printed a'la Python using the quotes + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + inline std::ostream& toStream + ( const std::string& obj , std::ostream& s ) + { + if ( std::string::npos == obj.find('\'') ) + { s << "\'" << obj << "\'" ; } + else + { s << "\"" << obj << "\"" ; } + return s ; + } + /** the printout of boolean values "a'la Python" + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-09-09 + */ + inline std::ostream& toStream + ( const bool obj , std::ostream& s ) + { return s << ( obj ? "True" : "False" ) ; } + /** the printout of float values with the reasonable precision + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-09-09 + */ + inline std::ostream& toStream + ( const float obj , std::ostream& s , const int prec = 6 ) + { + const int p = s.precision() ; + return s << std::setprecision ( prec ) << obj << std::setprecision ( p ) ; + } + /** the printout of double values with the reasonable precision + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-09-09 + */ + inline std::ostream& toStream + ( const double obj , std::ostream& s , const int prec = 8 ) + { + const int p = s.precision() ; + return s << std::setprecision ( prec ) << obj << std::setprecision ( p ) ; + } + /** the printout of long double values with the reasonable precision + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-09-09 + */ + inline std::ostream& toStream + ( const long double obj , std::ostream& s , const int prec = 10 ) + { + const int p = s.precision() ; + return s << std::setprecision ( prec ) << obj << std::setprecision ( p ) ; + } + // ======================================================================== + /** the partial template specialization of + * <c>std::pair<KTYPE,VTYPE></c> printout + * the pair is printed a'la Python tuple: " ( a , b )" + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template<class KTYPE, class VTYPE> + inline std::ostream& toStream + ( const std::pair<KTYPE,VTYPE>& obj, std::ostream& s) + { + s << "( " ; + toStream ( obj.first , s ) ; + s << " , " ; + toStream ( obj.second , s ) ; + return s << " )" ; + } + // ======================================================================== + /** the partial template specialization of <c>std::vector<TYPE,ALLOCATOR></c> + * printout. The vector is printed a'la Python list: "[ a, b, c ]" + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template<class TYPE,class ALLOCATOR> + inline std::ostream& toStream + ( const std::vector<TYPE,ALLOCATOR>& obj, std::ostream& s) + { + return toStream ( obj.begin() , obj.end () , s , "[ " , " ]" , " , " ) ; + } + // ======================================================================== + /** the partial template specialization of <c>std::list<TYPE,ALLOCATOR></c> + * printout. The vector is printed a'la Python list: "[ a, b, c ]" + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2007-04-08 + */ + template<class TYPE,class ALLOCATOR> + inline std::ostream& toStream + ( const std::list<TYPE,ALLOCATOR>& obj, std::ostream& s) + { + return toStream ( obj.begin() , obj.end () , s , "[ " , " ]" , " , " ) ; + } + // ======================================================================== + /** the partial template specialization of <c>std::set<TYPE,CMP,ALLOCATOR></c> + * printout. The vector is printed a'la Python list: "[ a, b, c ]" + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template<class TYPE,class CMP,class ALLOCATOR> + inline std::ostream& toStream + ( const std::set<TYPE,CMP,ALLOCATOR>& obj, std::ostream& s) + { + return toStream ( obj.begin() , obj.end () , s , "[ " , " ]" , " , " ) ; + } + // ======================================================================== + /** the partial template specialization of + * <c>std::map<KTYPE,VTYPE,CMP,ALLOCATOR></c> printout + * the map is printed a'la Python dict: " ( a : b , c: d , e : f )" + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template<class KTYPE, class VTYPE,class CMP,class ALLOCATOR> + inline std::ostream& toStream + ( const std::map<KTYPE,VTYPE,CMP,ALLOCATOR>& obj, std::ostream& s ) + { + s << "{ "; + for ( typename std::map<KTYPE,VTYPE,CMP,ALLOCATOR>::const_iterator cur = + obj.begin() ; obj.end() != cur ; ++cur ) + { + if ( obj.begin() != cur ) { s << " , " ; } + toStream ( cur -> first , s ) ; + s << " : " ; + toStream ( cur -> second , s ) ; + } + return s << " }"; + } + + // ======================================================================== + /** the specialization for C-arrays, a'la python tuple + * @author Vanya BELYAEV Ivan.Belyaev@nikhenf.nl + * @date 2009-10-05 + */ + template <class TYPE, unsigned int N> + std::ostream& toStream ( TYPE(&obj)[N] , std::ostream& s ) + { + return toStream ( obj , obj + N , s , "( " , " )" , " , " ) ; + } + // ======================================================================== + /** the specialization for C-arrays, a'la python tuple + * @author Vanya BELYAEV Ivan.Belyaev@nikhenf.nl + * @date 2009-10-05 + */ + template <class TYPE, unsigned int N> + std::ostream& toStream ( const TYPE(&obj)[N] , std::ostream& s ) + { + return toStream ( obj , obj + N , s , "( " , " )" , " , " ) ; + } + // ======================================================================== + /** the specialization for C-string, a'la python tuple + * @author Vanya BELYAEV Ivan.Belyaev@nikhenf.nl + * @date 2009-10-05 + */ + template <unsigned int N> + std::ostream& toStream ( char (&obj)[N] , std::ostream& s ) + { return toStream ( std::string ( obj , obj+N ) , s ) ; } + // ======================================================================== + /** the specialization for C-string, a'la python tuple + * @author Vanya BELYAEV Ivan.Belyaev@nikhenf.nl + * @date 2009-10-05 + */ + template <unsigned int N> + std::ostream& toStream ( const char (&obj)[N] , std::ostream& s ) + { return toStream ( std::string ( obj , obj+N ) , s ) ; } + // ======================================================================== + /** the specialization for C-string, a'la python tuple + * @author Vanya BELYAEV Ivan.Belyaev@nikhenf.nl + * @date 2009-10-05 + */ + inline std::ostream& toStream ( const char* obj , std::ostream& s ) + { return toStream ( std::string ( obj ) , s ) ; } + // ======================================================================== + /** the generic implementation of the printout to the std::ostream + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template<class TYPE> + inline std::ostream& toStream ( const TYPE& obj, std::ostream& s ) + { return s << obj ; } + // ======================================================================== + /** the helper function to print the sequence + * @param first (INPUT) begin-iterator for the sequence + * @param last (INPUT) end-iterator for the sequence + * @param s (UPDATE) the stream itself + * @param open (INPUT) "open"-symbol + * @param close (INPUT) "close"-symbol + * @param delim (INPUT) "delimiter"-symbol + * @return the stream + * @author Vanya BELYAEV Ivan.BElyaev@nikhef.nl + * @date 2009-09-15 + */ + template <class ITERATOR> + inline std::ostream& toStream + ( ITERATOR first , // begin of the sequence + ITERATOR last , // end of the sequence + std::ostream& s , // the stream + const std::string& open , // opening + const std::string& close , // closing + const std::string& delim ) // delimiter + { + s << open ; + for ( ITERATOR curr = first ; curr != last ; ++curr ) + { + if ( first != curr ) { s << delim ; } + toStream ( *curr , s ) ; + } + s << close ; + // + return s ; + } + // ======================================================================== + /** the generic implementation of the type conversion to the string + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + * @see DD4hep::Utils::toStream + * @todo need to be compared with boost::lexical_cast + */ + template <class TYPE> + inline std::string toString ( const TYPE& obj ) + { + std::ostringstream s; + std::ios::fmtflags orig_flags = s.flags(); + s.setf(std::ios::showpoint); // to display correctly floats + toStream ( obj , s); + s.flags(orig_flags); + return s.str(); + } + // ======================================================================== + } // end of namespace DD4hep::Utils + // ========================================================================== +} // end of namespace DD4hep +// ============================================================================ +// The END +// ============================================================================ +#endif +// ============================================================================ + diff --git a/DDG4/parsers/Grammars.h b/DDG4/parsers/Grammars.h new file mode 100644 index 0000000000000000000000000000000000000000..81140ff5464758857924d5017b0d0a68ade5f607 --- /dev/null +++ b/DDG4/parsers/Grammars.h @@ -0,0 +1,530 @@ +// ============================================================================ +#ifndef DD4HEPKERNEL_GRAMMARS_H +#define DD4HEPKERNEL_GRAMMARS_H 1 +#ifdef __GNUC__ +#warning \ + The headers GaudiKernel/Grammars.h and GaudiKernel/Parsers.icpp are deprecated \ + and will be removed from the next release of Gaudi. You should migrate your \ + code the new pasers based on Boost.Spirit 2. +#endif +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <cctype> +// ============================================================================ +// Boost.Spirit +// ============================================================================ +#include <boost/version.hpp> +#if BOOST_VERSION >= 103800 +// FIXME: Move to the new boost::spirit::classic namespace +#if !defined(BOOST_SPIRIT_USE_OLD_NAMESPACE) +#define BOOST_SPIRIT_USE_OLD_NAMESPACE +#endif +#include <boost/spirit/include/classic.hpp> +#include <boost/spirit/include/phoenix1.hpp> +#else +#include <boost/spirit.hpp> +#include <boost/spirit/phoenix.hpp> +#endif +#include <boost/bind.hpp> + +// ============================================================================ +/** @file + * Collection of grammars for property types + * + * @see Dd4hep::Parsers::parse + * @see Property + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ +// ============================================================================ +namespace DD4hep +{ + namespace Parsers + { + // ======================================================================== + using namespace boost::spirit ; + // ======================================================================== + using namespace phoenix ; + // ======================================================================== + /** @struct ClosureGrammar + * Grammar or grammar rule which derive from this struct will have + * attribute of type <c>T</c> and name <c>val</c> + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template <typename T> + struct ClosureGrammar : public boost::spirit::closure < ClosureGrammar<T>,T > + { + typedef boost::spirit::closure<ClosureGrammar, T> closure; + typename closure::member1 val; + }; + // ======================================================================== + /** @struct AttributesClosureGrammar + * + * Grammar or grammar rule which derive from this struct will have + * two attributes: type <c>T1</c> and name <c>val</c>, type <c>T2</c> + * and name <c>attrs</c> + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template <typename T1,typename T2> + struct AttributesClosureGrammar + : public boost::spirit::closure<AttributesClosureGrammar<T1,T2>,T1,T2> + { + typedef boost::spirit::closure<AttributesClosureGrammar, T1,T2> closure; + typename closure::member1 val; + typename closure::member2 attrs; + }; + // ======================================================================== + /** @class BoolGrammar + * + * The valid represenation of boolean values are: + * + * - true , True , TRUE or 1 + * - false , False , FALSE or 0 + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + class BoolGrammar : public grammar + < + BoolGrammar, + ClosureGrammar<bool>::context_t + > + { + public: + typedef bool ResultT; + public: + template <typename ScannerT> + struct definition + { + definition( BoolGrammar const &self) + { + boolean_literal + = true_literal[self.val = true] | false_literal[self.val = false]; + true_literal + = str_p("true" ) | str_p("True" ) | str_p("TRUE" ) | str_p("1"); + false_literal + = str_p("false") | str_p("False") | str_p("FALSE") | str_p("0"); + } + rule<ScannerT> const& start() const + { return boolean_literal;} + rule<ScannerT> boolean_literal,true_literal,false_literal; + }; + }; + // ======================================================================== + /** @class CharGrammar + * + * The valid represenation of char values are: + * + * - 'a', 'b','\'' + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template<typename RT=char> + class CharGrammar : public grammar + < + CharGrammar<RT> , typename ClosureGrammar<RT>::context_t + > + { + public: + typedef RT ResultT; + public: + template <typename ScannerT> + struct definition + { + definition( CharGrammar<RT> const &self) + { + char_literal + = int_parser<RT>()[self.val=arg1] + | ('\'' + >> ( str_p("\\'")[self.val='\''] + | (anychar_p[self.val=arg1]-'\'') )>>'\''); + } + rule<ScannerT> const& start() const + { return char_literal; } + rule<ScannerT> char_literal; + }; + }; + // ======================================================================== + /** @class IntGrammar + * + * The valid representation of integers values are: + * + * - 1, 100, 123 + * + * @todo implement suffixes u U l L + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template<typename RT=int> + class IntGrammar : public grammar + < + IntGrammar<RT>, + typename ClosureGrammar<RT>::context_t + > + { + public: + typedef RT ResultT; + public: + template <typename ScannerT> + struct definition + { + definition( IntGrammar<RT> const &self) + { + int_literal = lexeme_d[int_parser<RT>()[self.val=arg1] + >> !(ch_p('u') | ch_p('U') | ch_p('l') | ch_p('L'))]; + } + rule<ScannerT> const& start() const { return int_literal; } + rule<ScannerT> int_literal; + }; + }; + // ======================================================================== + /** @class RealGrammar + * + * The valid represenation of real values are: + * + * - 1, 1.0 ,1.123, 1E+2, 0.5e-2 + * + * @todo implement suffixes f l F L + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template<typename RT=double> + class RealGrammar : public grammar + < + RealGrammar<RT>,typename ClosureGrammar<RT>::context_t + > + { + public: + typedef RT ResultT; + public: + template <typename ScannerT> + struct definition + { + definition( RealGrammar const &self) + { + real_literal + = lexeme_d[real_parser<RT, + real_parser_policies<RT> >()[self.val = arg1] + >> !(ch_p('f') | ch_p('F') | ch_p('l') | ch_p('L'))]; + } + rule<ScannerT> const& start() const + { return real_literal; } + rule<ScannerT> real_literal; + }; + }; + // ======================================================================== + /** @class StringGrammar + * + * The valid represenation of string values are: + * + * - "abc" , "\"abc\"" + * - 'abs' , '\'abc\'' + * + * @todo implement not ASCII chars in strings + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + + class StringGrammar : public grammar + < + StringGrammar, ClosureGrammar<std::string>::context_t + > + { + public: + typedef std::string ResultT; + /** remove CR/LF symbols form the parsed strings + * @attention it is a bit dangerous operation + * The operation allows to write "very long" input strings + * for opts-files (it is actual e.g. for DataOnDemandSvc configuration) + * by splitting the strings into few lines + * All new-line symbols (as well as '\n', '\t', CR/LF etc + * are substituted by ordinary blanks. + */ + void matchString() const + { + for ( std::string::iterator cur=this->val().begin(); + cur!=this->val().end();cur++) + { if(std::isspace(*cur) ) { *cur = ' '; } } + } + public: + template <typename ScannerT> + struct definition + { + definition( StringGrammar const &self ) + { + string_literal = (lexeme_d + [ + ('"' >> (*( str_p("\\\"") + | + (anychar_p-'"') )) + [self.val = construct_<std::string> + (arg1,arg2)] >> + '"') + | + ('\'' >> (*( str_p("\\'") + | + (anychar_p-'\'') )) + [self.val = construct_<std::string> + (arg1,arg2)]>> + '\'')])[boost::bind(&StringGrammar::matchString,&self)]; + } + rule<ScannerT> const& start() const { return string_literal; } + rule<ScannerT> string_literal; + }; + }; + // ======================================================================== + /** @class SkipperGrammar + * + * Skipping spaces and comments. Comments can be + * + * - // ... - one line + * - \/\* ... \*\/ - multiline + * + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + class SkipperGrammar : public grammar<SkipperGrammar> + { + public: + /** Constructor + * @param skipnewline Skip new line symbols or not + */ + SkipperGrammar ( const bool skipnewline = true ) + : m_skipnewline(skipnewline){} + public: + /// @return true - skip new line symbols, false - not skip + bool skipnewline() const{return m_skipnewline;} + public: + template <typename ScannerT> + struct definition + { + definition( SkipperGrammar const& self) + { + if ( self.skipnewline() ) + { + skip + = space_p + | comment_p("//") // C++ comment + | comment_p("/*", "*/") // C comment + ; + } + else + { + skip + = (space_p-eol_p) + | comment_p("//") // C++ comment + | comment_p("/*", "*/") // C comment + ; + } + } + rule<ScannerT> skip; + rule<ScannerT> const& start() const { return skip; } + }; + private: + bool m_skipnewline; + }; + // ======================================================================== + /** @class PairGrammar + * + * The valid represenation of pairs are: + * ("abc",123) or ("abc","def") + * Inner types of pair depends on KeyGrammarT and ValueGrammarT grammars + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template <typename KeyGrammarT, typename ValueGrammarT> + class PairGrammar : public grammar + < + PairGrammar<KeyGrammarT,ValueGrammarT>, + typename ClosureGrammar< + std::pair<typename KeyGrammarT::ResultT, + typename ValueGrammarT::ResultT> >::context_t + > + { + public: + typedef typename KeyGrammarT::ResultT KeyT; + typedef typename ValueGrammarT::ResultT ValueT; + typedef std::pair<KeyT,ValueT> ResultT; + public: + /** Constructor + * @param delim Delimiter for pair values + */ + PairGrammar ( const std::string& delim = "," ) + : m_delim(delim) {} + public: + /// callback. Action when we match first value + void matchFirst ( const KeyT& first ) const { this->val().first = first; } + /// callback. Action when we match second value + void matchSecond ( const ValueT& second ) const { this->val().second = second; } + public: + template <typename ScannerT> + struct definition + { + definition( PairGrammar const &self) + { + para + = ( + str_p("(") + >> (grkey[boost::bind(&PairGrammar::matchFirst,&self,_1)]) + >> self.delim().c_str() + >> (grvalue[boost::bind(&PairGrammar::matchSecond,&self,_1)]) + >> str_p(")") + ) ; + } + rule<ScannerT> const& start() const { return para; } + rule<ScannerT> para; + KeyGrammarT grkey; + ValueGrammarT grvalue; + }; + public: + /// @return Delimiter for pair values + const std::string& delim() const { return m_delim ; } + /** Set delimiters for pair values + * @param delim Delimiter + */ + void setDelim ( const std::string& delim ) { m_delim = delim;} + private: + std::string m_delim; + }; + // ======================================================================== + /** @class VectorGrammar + * + * The valid represenation of vector are: + * - {"abc","defj","i"} or {1,2,3,4,5} + * - ["abc","defj","i"] or [1,2,3,4,5] + * Inner type depends on GrammarT grammar + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template <typename GrammarT> + class VectorGrammar : public grammar + < + VectorGrammar<GrammarT> , + typename ClosureGrammar<std::vector<typename GrammarT::ResultT> >::context_t + > + { + public: + typedef typename GrammarT::ResultT ValueT; + typedef std::vector<ValueT> ResultT; + typedef VectorGrammar<GrammarT> SelfT; + public: + /// callback. Action when we match inner value + void matchItem(const ValueT& value) const { this->val().push_back(value); } + public: + template <typename ScannerT> + struct definition + { + definition(SelfT const &self) + { + inner = + !(gr[boost::bind(&VectorGrammar::matchItem,&self,_1)] + >> *(','>>gr[boost::bind(&VectorGrammar::matchItem,&self,_1)])); + vec = + '[' >> inner >> ']' | // a'la python list + '(' >> inner >> ')' | // a'la python tuple + '{' >> inner >> '}' ; // like obsolete list from opts-grammar + } + rule<ScannerT> const& start() const { return vec; } + rule<ScannerT> vec,inner; + GrammarT gr; + }; + }; + // ======================================================================== + /** @class MapGrammar + * + * The valid represenation of map are: + * - {"file1":"path1","something":"nothing"} + * - {"file1"="path1","something"="nothing"} + * - ["file1":10,"something":20] + * - ["file1"=30,"something"=40] + * Inner key type depends on KeyGrammarT grammar + * Inner value type depends on ValueGrammarT grammar + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template <typename KeyGrammarT, typename ValueGrammarT> + class MapGrammar : public grammar + < + MapGrammar<KeyGrammarT,ValueGrammarT>, + typename AttributesClosureGrammar + < std::map<typename KeyGrammarT::ResultT, + typename ValueGrammarT::ResultT>, + std::pair<typename KeyGrammarT::ResultT, + typename ValueGrammarT::ResultT> >::context_t + > + { + public: + typedef typename KeyGrammarT::ResultT KeyT; + typedef typename ValueGrammarT::ResultT ValueT; + typedef std::map<KeyT,ValueT> ResultT; + public: + /// call backs. Action when we match pair in map + void matchItem () const + { + //this->val().insert(this->attrs()); + this->val()[this->attrs().first] = this->attrs().second ; + } + /// call backs. Action when we match key of pair + void matchFirst ( const KeyT& value ) const { this->attrs().first = value ; } + /// call backs. Action when we match value pf pair + void matchSecond( const ValueT& value ) const { this->attrs().second = value ; } + public: + template <typename ScannerT> + struct definition + { + definition( MapGrammar const &self) + { + vec + = ('{'>> inner_list >> '}') | ('['>>inner_list>>']'); + inner_list + = + !( inner[boost::bind(&MapGrammar::matchItem,&self)] + >> *( ch_p(',') >> + inner[boost::bind(&MapGrammar::matchItem,&self)] ) + ); + inner + = + grKey[boost ::bind(&MapGrammar::matchFirst,&self,_1)] + >> ( ch_p('=') | ch_p(':')) + >> grValue[boost::bind(&MapGrammar::matchSecond,&self,_1)] ; + } + KeyGrammarT grKey; + ValueGrammarT grValue; + rule<ScannerT> const& start() const { return vec; } + rule<ScannerT> vec,inner, inner_list ; + }; + }; + // ======================================================================== + } // end of namespace Dd4hep::Parsers +} // end of namespace Dd4hep +// ============================================================================ +// The END +// ============================================================================ +#endif // DD4HEPKERNEL_GRAMMARS_H +// ============================================================================ diff --git a/DDG4/parsers/GrammarsV2.h b/DDG4/parsers/GrammarsV2.h new file mode 100644 index 0000000000000000000000000000000000000000..419de5d6529461d98187844c1f69e28560658db2 --- /dev/null +++ b/DDG4/parsers/GrammarsV2.h @@ -0,0 +1,365 @@ +// ============================================================================ +#ifndef DD4HEPKERNEL_GRAMMARSV2_H +#define DD4HEPKERNEL_GRAMMARSV2_H 1 +#ifdef __GNUC__ +#pragma GCC system_header +#endif +// ============================================================================ +// Include files +// ============================================================================ +// STD: +//============================================================================== +#include <string> +#include <vector> +#include <list> +#include <set> +#include <map> +//============================================================================== +// Boost: +//============================================================================== +#include <boost/spirit/include/qi.hpp> +#include <boost/fusion/include/unused.hpp> +#include <boost/fusion/include/std_pair.hpp> + +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> + +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits.hpp> + +#include <boost/spirit/repository/include/qi_confix.hpp> + +//============================================================================== +namespace DD4hep { namespace Parsers { + //============================================================================== + // Namespace aliases: + //============================================================================== + namespace sp = boost::spirit; + namespace ph = boost::phoenix; + namespace qi = sp::qi; + namespace enc = sp::ascii; + namespace rep = sp::repository; + //============================================================================== + // Grammars + //============================================================================== + typedef std::string::const_iterator DefaultIterator; + typedef enc::space_type DefaultSkipper; + //============================================================================== + template <typename Iterator, typename T, typename Skipper, + class Enable = void> + struct Grammar_ { + /* READ THIS IF YOUR COMPILE BREAKS ON THE FOLLOWING LINE + * + * To users: You have to ask developers to implement parser for your type T + * To developer: You have to implement and register Grammar for type T + * + */ + BOOST_MPL_ASSERT_MSG(false, GRAMMAR_FOR_TYPE_DOES_NOT_EXISTS, (T)); + }; + +#define REGISTER_GRAMMAR(ResultType, GrammarName) \ + template <typename Iterator, typename Skipper> \ + struct Grammar_<Iterator, ResultType, Skipper> \ + { \ + typedef GrammarName<Iterator, Skipper> Grammar; \ + } + //============================================================================== + template< typename Iterator> + struct SkipperGrammar : qi::grammar<Iterator> + { + SkipperGrammar() : SkipperGrammar::base_type(comments) { + comments = enc::space | rep::confix("/*", "*/")[*(qi::char_ - "*/")] + | + rep::confix("//", (sp::eol | sp::eoi))[*(qi::char_ - (sp::eol|sp::eoi))]; + } + qi::rule<Iterator> comments; + }; + //============================================================================== + template< typename Iterator, typename Skipper> + struct StringGrammar : qi::grammar<Iterator, std::string(), qi::locals<char>, + Skipper> + { + //------------------------------------------------------------------------------ + typedef std::string ResultT; + //------------------------------------------------------------------------------ + StringGrammar() : StringGrammar::base_type( str ) { + begin_quote = enc::char_("\"'"); + quote = enc::char_(qi::_r1); + + str = qi::lexeme[begin_quote[qi::_a = qi::_1] + > *( (enc::char_('\\') >> quote(qi::_a))[qi::_val += qi::_a] + | (enc::char_[qi::_val += qi::_1] - quote(qi::_a))) > + quote(qi::_a)] + ; + } + //------------------------------------------------------------------------------ + qi::rule<Iterator, std::string(), qi::locals<char>, Skipper> str; + qi::rule<Iterator, char()> begin_quote; + qi::rule<Iterator, void(char)> quote; + //------------------------------------------------------------------------------ + }; + REGISTER_GRAMMAR(std::string, StringGrammar); + //============================================================================== + template< typename Iterator, typename Skipper> + struct CharGrammar : qi::grammar<Iterator, char(), Skipper> + { + typedef char ResultT; + CharGrammar() : CharGrammar::base_type( ch ) { + ch = qi::int_parser<char>() + | + '\'' >> (qi::char_-'\'') >> '\''; + } + qi::rule<Iterator, char(), Skipper> ch; + }; + REGISTER_GRAMMAR(char, CharGrammar); + //============================================================================== + template< typename Iterator, typename Skipper> + struct BoolGrammar : qi::grammar<Iterator, bool(), Skipper> + { + typedef bool ResultT; + BoolGrammar() : BoolGrammar::base_type( boolean_literal ) { + boolean_literal = + (qi::lit("true") | "True" | "TRUE" | "1")[qi::_val=true] + | + (qi::lit("false") | "False" | "FALSE" | "0")[qi::_val=false]; + } + qi::rule<Iterator, bool(), Skipper> boolean_literal; + }; + REGISTER_GRAMMAR(bool, BoolGrammar); + //============================================================================== + template< typename Iterator, typename RT , typename Skipper> + struct IntGrammar : qi::grammar<Iterator, RT(), Skipper> + { + typedef RT ResultT; + IntGrammar() : IntGrammar::base_type( integer ) { + integer = qi::int_parser<RT>()[qi::_val = qi::_1] + >> -qi::no_case[qi::char_('L')]; + } + qi::rule<Iterator, RT(), Skipper> integer; + }; + // ---------------------------------------------------------------------------- + // Register IntGrammar: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename T, typename Skipper> + struct Grammar_<Iterator, T, Skipper, + typename boost::enable_if<boost::is_integral<T> >::type> + { + typedef IntGrammar<Iterator, T, Skipper> Grammar; + }; + //============================================================================== + template< typename Iterator, typename RT, typename Skipper> + struct RealGrammar : qi::grammar<Iterator, RT(), Skipper> + { + typedef RT ResultT; + RealGrammar() : RealGrammar::base_type(real) { + real = qi::real_parser<RT>(); + } + qi::rule<Iterator, RT(), Skipper> real; + }; + // ---------------------------------------------------------------------------- + // Register RealGrammar: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename T, typename Skipper > + struct Grammar_<Iterator, T, Skipper, + typename boost::enable_if<boost::is_floating_point<T> >::type > + { + typedef RealGrammar<Iterator, T, Skipper> Grammar; + }; + //============================================================================== + template< typename Iterator, typename VectorT, typename Skipper> + struct VectorGrammar : qi::grammar<Iterator, + VectorT(), qi::locals<char>,Skipper> + { + //------------------------------------------------------------------------------ + typedef VectorT ResultT; + //------------------------------------------------------------------------------ + VectorGrammar() : VectorGrammar::base_type(vec) { + begin = enc::char_('[')[qi::_val=']'] | enc::char_('{')[qi::_val='}'] + | enc::char_('(')[qi::_val=')']; + end = enc::char_(qi::_r1); + list = elementGrammar % ','; + vec = begin[qi::_a = qi::_1] >> -list[qi::_val=qi::_1] >> end(qi::_a); + } + // ---------------------------------------------------------------------------- + typename + Grammar_<Iterator, typename VectorT::value_type, Skipper>::Grammar + elementGrammar; + qi::rule<Iterator, char()> begin; + qi::rule<Iterator, void(char)> end; + + qi::rule<Iterator, ResultT(), qi::locals<char>,Skipper> vec; + qi::rule<Iterator, ResultT(), Skipper> list; + // ---------------------------------------------------------------------------- + }; + // ---------------------------------------------------------------------------- + // Register VectorGrammar for std::vector: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename InnerT, typename AllocatorT, + typename Skipper> + struct Grammar_<Iterator, std::vector<InnerT, AllocatorT>, Skipper > + { + typedef + VectorGrammar<Iterator, std::vector<InnerT, AllocatorT>,Skipper> + Grammar; + }; + // ---------------------------------------------------------------------------- + // Register VectorGrammar for std::list: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename InnerT, typename AllocatorT, + typename Skipper> + struct Grammar_<Iterator, std::list<InnerT, AllocatorT>, Skipper > + { + typedef + VectorGrammar<Iterator, std::list<InnerT, AllocatorT>,Skipper> + Grammar; + }; + // ---------------------------------------------------------------------------- + // Register VectorGrammar for std::set: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename InnerT, typename CompareT, + typename AllocatorT, typename Skipper> + struct Grammar_<Iterator, std::set<InnerT, CompareT, AllocatorT>, Skipper > + { + typedef + VectorGrammar<Iterator, std::set<InnerT, CompareT, AllocatorT>,Skipper> + Grammar; + }; + + //============================================================================== + template< typename Iterator, typename PairT, typename Skipper> + struct PairGrammar : + qi::grammar<Iterator,PairT(), qi::locals<char>, Skipper> { + //------------------------------------------------------------------------------ + typedef PairT ResultT; + typedef typename PairT::first_type first_type; + typedef typename PairT::second_type second_type; + //------------------------------------------------------------------------------ + PairGrammar() : PairGrammar::base_type(pair) { + init(","); + } + + PairGrammar(const std::string& delimeter) : PairGrammar::base_type(pair) { + init(delimeter); + } + //------------------------------------------------------------------------------ + struct first {}; + struct second {}; + void init(const std::string& delimeter) { + begin = enc::char_('(')[qi::_val=')'] + | + enc::char_('[')[qi::_val=']']; + end = qi::char_(qi::_r1); + pair = begin[qi::_a = qi::_1] >> pair_in[qi::_val = qi::_1] >> end(qi::_a); + pair_in = key >> qi::lit(delimeter) >> value; + } + // ---------------------------------------------------------------------------- + typename + Grammar_<Iterator, typename PairT::first_type, Skipper>::Grammar key; + typename + Grammar_<Iterator, typename PairT::second_type, Skipper>::Grammar + value; + qi::rule<Iterator, char()> begin; + qi::rule<Iterator, void(char)> end; + qi::rule<Iterator, ResultT(), qi::locals<char>, Skipper> pair; + qi::rule<Iterator, ResultT(), Skipper> pair_in; + //ph::function<Operations> op; + // ---------------------------------------------------------------------------- + }; // END PairGrammar + // ---------------------------------------------------------------------------- + // Register PairGrammar: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename KeyT, typename ValueT, + typename Skipper> + struct Grammar_<Iterator, std::pair<KeyT, ValueT>, Skipper > + { + typedef PairGrammar<Iterator, std::pair<KeyT, ValueT>, Skipper> Grammar; + }; + // ============================================================================ + template< typename Iterator, typename MapT, typename Skipper> + struct MapGrammar : qi::grammar<Iterator,MapT(), Skipper> + { + //------------------------------------------------------------------------------ + typedef MapT ResultT; + typedef typename MapT::key_type KeyT; + typedef typename MapT::mapped_type MappedT; + typedef std::pair<KeyT, MappedT> PairT; + + typedef std::vector<PairT> VectorPairT; + //------------------------------------------------------------------------------ + struct tag_key{}; + struct tag_mapped{}; + struct Operations + { + template <typename A, typename B = boost::fusion::unused_type, + typename C = boost::fusion::unused_type, + typename D = boost::fusion::unused_type> + struct result { typedef void type; }; + //---------------------------------------------------------------------- + void operator()(ResultT& res, const VectorPairT& vec) const{ + for(typename VectorPairT::const_iterator cur = vec.begin(); + cur != vec.end(); cur++){ + res.insert(*cur); + } + } + void operator()(PairT& res, const KeyT& key, tag_key) const{ + res.first = key; + } + void operator()(PairT& res, const MappedT& value, tag_mapped) const{ + res.second = value; + } + //---------------------------------------------------------------------- + }; + //------------------------------------------------------------------------------ + MapGrammar() : MapGrammar::base_type(map) { + pair = key[op(qi::_val,qi::_1, tag_key())] > (qi::lit(':') | '=') > + value[op(qi::_val,qi::_1, tag_mapped())]; + list = -(pair % enc::char_(',')); + map = (('[' >> list >> ']') + | ('{' >> list >> '}'))[op(qi::_val,qi::_1)]; + } + // ---------------------------------------------------------------------------- + typename + Grammar_<Iterator, typename MapT::key_type, Skipper>::Grammar key; + typename + Grammar_<Iterator, typename MapT::mapped_type, Skipper>::Grammar value; + qi::rule<Iterator, PairT(), Skipper> pair; + qi::rule<Iterator, VectorPairT(), Skipper> list; + qi::rule<Iterator, ResultT(), Skipper> map; + ph::function<Operations> op; + // ---------------------------------------------------------------------------- + }; + // ---------------------------------------------------------------------------- + // Register MapGrammar for std::map: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename KeyT, typename ValueT, + typename KeyCompareT, typename AllocatorT, typename Skipper> + struct Grammar_<Iterator, std::map<KeyT, ValueT, KeyCompareT, AllocatorT>, + Skipper > { + typedef MapGrammar<Iterator, + std::map<KeyT, ValueT, KeyCompareT, AllocatorT>, Skipper> Grammar; + }; + + // ============================================================================ + template< typename Iterator, typename Skipper> + struct KeyValueGrammar : + qi::grammar<Iterator, std::pair<std::string, std::string>(), Skipper> { + //------------------------------------------------------------------------------ + typedef std::pair<std::string, std::string> ResultT; + //------------------------------------------------------------------------------ + struct first {}; + struct second {}; + + KeyValueGrammar() : KeyValueGrammar::base_type(pair) { + //------------------------------------------------------------------------------ + pair = gstring >> ":" >> +enc::char_; + } + // ---------------------------------------------------------------------------- + StringGrammar<Iterator, Skipper> gstring; + qi::rule<Iterator, ResultT(), Skipper> pair; + // ---------------------------------------------------------------------------- + }; // END KeyValueGrammar + // We don't register KeyalueGrammar because it's a special parser + // ============================================================================ + }} // DD4hep::Parsers +//============================================================================ +#endif diff --git a/DDG4/parsers/Parsers.icpp b/DDG4/parsers/Parsers.icpp new file mode 100644 index 0000000000000000000000000000000000000000..a4e1421e60e5741f503864ae27dd6d90f85ad76b --- /dev/null +++ b/DDG4/parsers/Parsers.icpp @@ -0,0 +1,232 @@ +// $Id: Parsers.icpp,v 1.5 2008/10/28 14:02:18 marcocle Exp $ +// ============================================================================ +#ifndef GAUDIKERNEL_PARSERS_ICPP +#define GAUDIKERNEL_PARSERS_ICPP 1 +// ============================================================================ +// Include files +// ============================================================================ +// STD&STL +// ============================================================================ +#include <vector> +#include <map> +#include <string> +// ============================================================================ +// Boost.Bind +// ============================================================================ +#include "boost/bind.hpp" +// ============================================================================ +// Boost.Spirit, Boost.Spirit.Phoenix +// ============================================================================ +#include <boost/version.hpp> +#if BOOST_VERSION >= 103800 +// FIXME: Move to the new boost::spirit::classic namespace +#if !defined(BOOST_SPIRIT_USE_OLD_NAMESPACE) +#define BOOST_SPIRIT_USE_OLD_NAMESPACE +#endif +#include <boost/spirit/include/classic.hpp> +#include <boost/spirit/include/phoenix1.hpp> +#else +#include <boost/spirit.hpp> +#include <boost/spirit/phoenix.hpp> +#endif +// ============================================================================ +// DD4hepKernel +// ============================================================================ +#include "DDG4/Parsers.h" +#include "Grammars.h" +// ============================================================================ +/** @file + * + * Helper inline functions for implementation of real parsing function + * from the namespace DD4hep::Parsers + * + * For adding new type you should have only grammar class which recognize + * this type. Then by combining this grammar with such already implemented + * grammars like VectorGrammar, MapGrammar, PairGrammar you can very simply + * implement container types which will work with your type. + * + * If you want your type can be handled in property file - see ValueGrammar + * in JobOptionsSvc which lays in DD4hepCoreSvc. + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ +// ============================================================================ +namespace DD4hep { + namespace Parsers { + using namespace std; + using namespace boost::spirit ; + + /// the actual type of position iterator + typedef boost::spirit::position_iterator<string::const_iterator> IteratorT; + + /// create the position iterator from the input + inline IteratorT createIterator( const std::string& input) + { return IteratorT ( input.begin(), input.end() ) ; } + + // ======================================================================== + /** helper function to "merge" the implementation of all parsers + * for integer-like quantities into one templated grammar + * @see DD4hep::Parsers::IntGrammar + * + * @param result (output) parsing result + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + // ======================================================================== + template<typename IntegerT> + inline StatusCode parse_integer + (IntegerT& result,const string& input) + { + IntGrammar<IntegerT> g; + return parse + ( createIterator(input), + IteratorT(), + g[var(result)=arg1]).full; + } + // ======================================================================== + /** helper function to "merge" the implementation of all parsers + * for vector of integer-like quantities + * into the combination of templated grammars + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::IntGrammar + * @see DD4hep::Parsers::SkipperGrammar + * + * @param result (output) parsing result + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + // ======================================================================== + template<typename IntegerT> + inline StatusCode parse_integer_vector + ( std::vector<IntegerT>& result,const string& input) + { + VectorGrammar<IntGrammar<IntegerT> > g; + return parse + ( createIterator(input), + IteratorT(), + g[var(result)=arg1], + SkipperGrammar()).full; + } + // ======================================================================== + /** helper function to "merge" the implementation of all parsers + * for "char-like" quantities into one templated grammar + * @see DD4hep::Parsers::CharGrammar + * + * @param result (output) parsing result + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + // ======================================================================== + template<typename CharT> + inline StatusCode parse_char + ( CharT& result , const string& input ) + { + CharGrammar<CharT> g; + return parse + ( createIterator(input), + IteratorT(), + g[var(result)=arg1]).full; + } + // ======================================================================== + /** helper function to "merge" the implementation of all parsers + * for vector of 'char-like' quantities + * into the combination of templated grammars + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::CharGrammar + * @see DD4hep::Parsers::SkipperGrammar + * + * @param result (output) parsing result + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + // ======================================================================== + template<typename CharT> + inline StatusCode parse_char_vector + (std::vector<CharT>& result,const string& input) + { + VectorGrammar<CharGrammar<CharT> > g; + return parse + ( createIterator(input), + IteratorT(), + g[var(result)=arg1], + SkipperGrammar()).full; + } + // ======================================================================== + /** helper function to "merge" the implementation of all parsers + * for "float-like" quantities into one templated grammar + * @see DD4hep::Parsers::RealGrammar + * + * @param result (output) parsing result + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template<typename RealT> + inline StatusCode parse_real + ( RealT& result , const string& input) + { + RealGrammar<RealT> g; + return parse + ( createIterator(input), + IteratorT(), + g[var(result)=arg1], + SkipperGrammar()).full; + } + // ======================================================================== + /** helper function to "merge" the implementation of all parsers + * for vector of 'char-like' quantities + * into the combination of templated grammars + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::RealGrammar + * @see DD4hep::Parsers::SkipperGrammar + * + * @param result (output) parsing result + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + // ======================================================================== + template<typename RealT> + StatusCode parse_real_vector + ( std::vector<RealT>& result,const string& input) + { + VectorGrammar< RealGrammar<RealT> > g; + return parse + ( createIterator(input), + IteratorT(), + g[var(result)=arg1], + SkipperGrammar()).full; + } + } // end of namespace Parsers +} // end of namespace DD4hep +// ============================================================================ +#endif +// ============================================================================ +// The END +// ============================================================================ + + diff --git a/DDG4/parsers/ParsersFactory.h b/DDG4/parsers/ParsersFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..b0b936b0b1bf322dabef638864b8609f81318f4c --- /dev/null +++ b/DDG4/parsers/ParsersFactory.h @@ -0,0 +1,53 @@ +// ============================================================================ +#ifndef DD4HEPPROPERTYPARSERS_PARSERSGENERATOR_H +#define DD4HEPPROPERTYPARSERS_PARSERSGENERATOR_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <string> +#include <vector> +#include <map> +// ============================================================================ +// Boost: +// ============================================================================ +#include <boost/mpl/assert.hpp> +#include <boost/type_traits.hpp> +// ============================================================================ +// DD4hep +// ============================================================================ +#include "GrammarsV2.h" +// ============================================================================ +namespace DD4hep { + namespace Parsers { + // ======================================================================== + typedef std::string::const_iterator IteratorT; + //typedef boost::spirit::ascii::space_type Skipper; + typedef SkipperGrammar<IteratorT> Skipper; + // ======================================================================== + template<typename ResultT> inline int + parse_(ResultT& result, const std::string& input){ + Skipper skipper; + typename Grammar_<IteratorT, ResultT, Skipper>::Grammar g; + IteratorT iter = input.begin(), end = input.end(); + return qi::phrase_parse( iter, end, g, skipper , result) && (iter==end); + } + //========================================================================= + template<> inline int + parse_(std::string& result, const std::string& input){ + Skipper skipper; + Grammar_<IteratorT, std::string, Skipper>::Grammar g; + IteratorT iter = input.begin(), end = input.end(); + if (!(qi::phrase_parse( iter, end, g, skipper, result) && (iter==end))){ + result = input; + } + //@attention always + return true; + } + //========================================================================= + }/* Parsers */ +} /* DD4hep */ +//============================================================================= +#endif // DD4HEPPROPERTYPARSERS_PARSERSGENERATOR_H + diff --git a/DDG4/parsers/ParsersStandardList1.cpp b/DDG4/parsers/ParsersStandardList1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad28873f7132249f02c247b9797fc6d6c3b1d193 --- /dev/null +++ b/DDG4/parsers/ParsersStandardList1.cpp @@ -0,0 +1,5 @@ +#include "ParsersStandardListCommon.h" +PARSERS_DEF_FOR_LIST(bool) +PARSERS_DEF_FOR_LIST(char) +PARSERS_DEF_FOR_LIST(unsigned char) +PARSERS_DEF_FOR_LIST(signed char) diff --git a/DDG4/parsers/ParsersStandardList2.cpp b/DDG4/parsers/ParsersStandardList2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f32362c9b1caaec0fb66ead59a0c53384a779d96 --- /dev/null +++ b/DDG4/parsers/ParsersStandardList2.cpp @@ -0,0 +1,5 @@ +#include "ParsersStandardListCommon.h" +PARSERS_DEF_FOR_LIST(int) +PARSERS_DEF_FOR_LIST(short) +PARSERS_DEF_FOR_LIST(unsigned short) +PARSERS_DEF_FOR_LIST(unsigned int) diff --git a/DDG4/parsers/ParsersStandardList3.cpp b/DDG4/parsers/ParsersStandardList3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f7e32e55d37973fecb5f74d570df4c121d0fc9c8 --- /dev/null +++ b/DDG4/parsers/ParsersStandardList3.cpp @@ -0,0 +1,5 @@ +#include "ParsersStandardListCommon.h" +PARSERS_DEF_FOR_LIST(long) +PARSERS_DEF_FOR_LIST(unsigned long) +PARSERS_DEF_FOR_LIST(long long) +PARSERS_DEF_FOR_LIST(unsigned long long) diff --git a/DDG4/parsers/ParsersStandardList4.cpp b/DDG4/parsers/ParsersStandardList4.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04d9c51502b8effae50f8a01316266aa4e60f393 --- /dev/null +++ b/DDG4/parsers/ParsersStandardList4.cpp @@ -0,0 +1,5 @@ +#include "ParsersStandardListCommon.h" +PARSERS_DEF_FOR_LIST(double) +PARSERS_DEF_FOR_LIST(float) +PARSERS_DEF_FOR_LIST(long double) +PARSERS_DEF_FOR_LIST(std::string) diff --git a/DDG4/parsers/ParsersStandardListCommon.h b/DDG4/parsers/ParsersStandardListCommon.h new file mode 100644 index 0000000000000000000000000000000000000000..a169872b2e9fb5b2353f025bdff4a5ca2891fe39 --- /dev/null +++ b/DDG4/parsers/ParsersStandardListCommon.h @@ -0,0 +1,18 @@ +#ifndef PARSERS_STANDARD_LIST_COMMON_H +#define PARSERS_STANDARD_LIST_COMMON_H 1 +// ============================================================================ +// Include files +// ============================================================================ +#include "DDG4/Parsers.h" +#include "ParsersFactory.h" +// ============================================================================ +#define PARSERS_DEF_FOR_LIST(InnerType)\ + int DD4hep::Parsers::parse(std::vector<InnerType>& result,const std::string& input)\ + { return DD4hep::Parsers::parse_(result, input); } \ + int DD4hep::Parsers::parse(std::list<InnerType>& result,const std::string& input)\ + { return DD4hep::Parsers::parse_(result, input); } \ + int DD4hep::Parsers::parse(std::set<InnerType>& result,const std::string& input)\ + { return DD4hep::Parsers::parse_(result, input); } \ + +// ============================================================================ +#endif /* PARSERS_STANDARD_LIST_COMMON_H */ diff --git a/DDG4/parsers/ParsersStandardMisc1.cpp b/DDG4/parsers/ParsersStandardMisc1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ae34a8c2283fbe1f7fbd30af96b9365de9b8941 --- /dev/null +++ b/DDG4/parsers/ParsersStandardMisc1.cpp @@ -0,0 +1,21 @@ +#include "ParsersStandardMiscCommon.h" + +int DD4hep::Parsers::parse(std::pair<double,double>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::pair<int, int>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::vector<std::pair<double, double> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::vector<std::pair<int, int> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::vector<std::vector<std::string> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} diff --git a/DDG4/parsers/ParsersStandardMisc2.cpp b/DDG4/parsers/ParsersStandardMisc2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb4ed696a6d7cc85ed181ca8ce146116337d0123 --- /dev/null +++ b/DDG4/parsers/ParsersStandardMisc2.cpp @@ -0,0 +1,17 @@ +#include "ParsersStandardMiscCommon.h" + +int DD4hep::Parsers::parse(std::vector<std::vector<double> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<int, int>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<int, double>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<std::string, std::string>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} diff --git a/DDG4/parsers/ParsersStandardMisc3.cpp b/DDG4/parsers/ParsersStandardMisc3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9cc2a0348a745e8173285d56658c45aece719682 --- /dev/null +++ b/DDG4/parsers/ParsersStandardMisc3.cpp @@ -0,0 +1,17 @@ +#include "ParsersStandardMiscCommon.h" + +int DD4hep::Parsers::parse(std::map<std::string, int>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<std::string, unsigned int>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<std::string, double>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<std::string, std::vector<std::string> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} diff --git a/DDG4/parsers/ParsersStandardMisc4.cpp b/DDG4/parsers/ParsersStandardMisc4.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5867cd25e3a0090f627666468dbc5f5b9c016d62 --- /dev/null +++ b/DDG4/parsers/ParsersStandardMisc4.cpp @@ -0,0 +1,13 @@ +#include "ParsersStandardMiscCommon.h" + +int DD4hep::Parsers::parse(std::map<std::string, std::vector<int> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<std::string, std::vector<double> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<int, std::string>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} diff --git a/DDG4/parsers/ParsersStandardMisc5.cpp b/DDG4/parsers/ParsersStandardMisc5.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5984100beba3ab1901e939c0979b7dcadcb37a67 --- /dev/null +++ b/DDG4/parsers/ParsersStandardMisc5.cpp @@ -0,0 +1,24 @@ +#include "ParsersStandardMiscCommon.h" + +int DD4hep::Parsers::parse(std::map<unsigned int, std::string>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::string& name, std::string& value , + const std::string& input ) { + Skipper skipper; + KeyValueGrammar<IteratorT, Skipper> g; + KeyValueGrammar<IteratorT, Skipper>::ResultT result; + std::string::const_iterator iter = input.begin(); + bool parse_result = qi::phrase_parse(iter, input.end(), g, skipper, + result) && (iter==input.end()); + if (parse_result) { + name = result.first; + value = result.second; + } + return parse_result; +} + +int DD4hep::Parsers::parse(std::map<std::string, std::pair<double, double> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} diff --git a/DDG4/parsers/ParsersStandardMiscCommon.h b/DDG4/parsers/ParsersStandardMiscCommon.h new file mode 100644 index 0000000000000000000000000000000000000000..b062b11611fa25086a6100529484913c1984bf04 --- /dev/null +++ b/DDG4/parsers/ParsersStandardMiscCommon.h @@ -0,0 +1,9 @@ +#ifndef PARSERS_STANDARD_MISC_COMMON_H +#define PARSERS_STANDARD_MISC_COMMON_H 1 +// ============================================================================ +// Include files +// ============================================================================ +#include "DDG4/Parsers.h" +#include "ParsersFactory.h" +// ============================================================================ +#endif /* PARSERS_STANDARD_MISC_COMMON_H */ diff --git a/DDG4/parsers/ParsersStandardSingle.cpp b/DDG4/parsers/ParsersStandardSingle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..258f0f881825c00365906a7d3108667a661f7332 --- /dev/null +++ b/DDG4/parsers/ParsersStandardSingle.cpp @@ -0,0 +1,26 @@ +// ============================================================================ +// Include files +// ============================================================================ +#include "DDG4/Parsers.h" +#include "ParsersFactory.h" +// ============================================================================ +#define PARSERS_DEF_FOR_SINGLE(Type)\ + int DD4hep::Parsers::parse(Type& result, const std::string& input) \ + { return DD4hep::Parsers::parse_(result, input); } +// ============================================================================ +PARSERS_DEF_FOR_SINGLE(bool) +PARSERS_DEF_FOR_SINGLE(char) +PARSERS_DEF_FOR_SINGLE(unsigned char) +PARSERS_DEF_FOR_SINGLE(signed char) +PARSERS_DEF_FOR_SINGLE(int) +PARSERS_DEF_FOR_SINGLE(short) +PARSERS_DEF_FOR_SINGLE(unsigned short) +PARSERS_DEF_FOR_SINGLE(unsigned int) +PARSERS_DEF_FOR_SINGLE(long) +PARSERS_DEF_FOR_SINGLE(unsigned long) +PARSERS_DEF_FOR_SINGLE(long long) +PARSERS_DEF_FOR_SINGLE(unsigned long long) +PARSERS_DEF_FOR_SINGLE(double) +PARSERS_DEF_FOR_SINGLE(float) +PARSERS_DEF_FOR_SINGLE(long double) +PARSERS_DEF_FOR_SINGLE(std::string) diff --git a/DDG4/src/ComponentUtils.cpp b/DDG4/src/ComponentUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ced2d43f9a6492937fad6a9c5a5f9ebc55ba9fef --- /dev/null +++ b/DDG4/src/ComponentUtils.cpp @@ -0,0 +1,354 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/Printout.h" +#include "DDG4/ComponentUtils_inl.h" + +// C/C++ include files +#include <stdexcept> +#include <cstring> +#include <map> + +#ifndef _WIN32 +#include <cxxabi.h> +#endif + +using namespace std; +using namespace DD4hep; + +namespace { + + const std::string __typename( const char* class_name) { + std::string result; +#ifdef _WIN32 + long off = 0; + if ( ::strncmp(class_name, "class ", 6) == 0 ) { + // The returned name is prefixed with "class " + off = 6; + } + if ( ::strncmp(class_name, "struct ", 7) == 0 ) { + // The returned name is prefixed with "struct " + off = 7; + } + if ( off > 0 ) { + std::string tmp = class_name + off; + long loc = 0; + while( (loc = tmp.find("class ")) > 0 ) { + tmp.erase(loc, 6); + } + loc = 0; + while( (loc = tmp.find("struct ")) > 0 ) { + tmp.erase(loc, 7); + } + result = tmp; + } + else { + result = class_name; + } + // Change any " *" to "*" + while ( (off=result.find(" *")) != std::string::npos ) { + result.replace(off, 2, "*"); + } + // Change any " &" to "&" + while ( (off=result.find(" &")) != std::string::npos ) { + result.replace(off, 2, "&"); + } + +#elif defined(__linux) || defined(__APPLE__) + if ( ::strlen(class_name) == 1 ) { + // See http://www.realitydiluted.com/mirrors/reality.sgi.com/dehnert_engr/cxx/abi.pdf + // for details + switch(class_name[0]) { + case 'v': + result = "void"; + break; + case 'w': + result = "wchar_t"; + break; + case 'b': + result = "bool"; + break; + case 'c': + result = "char"; + break; + case 'a': + result = "signed char"; + break; + case 'h': + result = "unsigned char"; + break; + case 's': + result = "short"; + break; + case 't': + result = "unsigned short"; + break; + case 'i': + result = "int"; + break; + case 'j': + result = "unsigned int"; + break; + case 'l': + result = "long"; + break; + case 'm': + result = "unsigned long"; + break; + case 'x': + result = "long long"; + break; + case 'y': + result = "unsigned long long"; + break; + case 'n': + result = "__int128"; + break; + case 'o': + result = "unsigned __int128"; + break; + case 'f': + result = "float"; + break; + case 'd': + result = "double"; + break; + case 'e': + result = "long double"; + break; + case 'g': + result = "__float128"; + break; + case 'z': + result = "ellipsis"; + break; + } + } + else { + int status; + char* realname; + realname = abi::__cxa_demangle(class_name, 0, 0, &status); + if (realname == 0) return class_name; + result = realname; + free(realname); + /// substitute ', ' with ',' + std::string::size_type pos = result.find(", "); + while( std::string::npos != pos ) { + result.replace( pos , 2 , "," ) ; + pos = result.find(", "); + } + } +#endif + return result; + } +} + +/// ABI information about type names +std::string DD4hep::typeinfoName(const std::type_info& type) { + return __typename(type.name()); +} + +void DD4hep::typeinfoCheck(const std::type_info& typ1, const std::type_info& typ2, const std::string& text) { + if ( typ1 != typ2 ) { + throw unrelated_type_error(typ1,typ2,text); + } +} + +string unrelated_type_error::msg(const std::type_info& typ1, const std::type_info& typ2,const string& text) { + std::string m = "The types "+__typename(typ1.name())+" and "+__typename(typ2.name())+ + " are not related. "+text; + return m; +} + +/// Default constructor +PropertyGrammar::PropertyGrammar() { +} + +/// Default destructor +PropertyGrammar::~PropertyGrammar() { +} + +/// Error callback on invalid conversion +void PropertyGrammar::invalidConversion(const type_info& from, const type_info& to) { + string to_name = __typename(to.name()); + string from_name = __typename(from.name()); + throw unrelated_type_error(from,to, + "The Property data conversion from type "+from_name+ + " to "+to_name+" is not implemented."); +} + +/// Default constructor +Property::Property() + : m_par(0), m_hdl(0) +{ +} + +/// Copy constructor +Property::Property(const Property& property) + : m_par(property.m_par), m_hdl(property.m_hdl) +{ +} + +/// Assignment operator +Property& Property::operator=(const Property& property) { + m_par = property.m_par; + m_hdl = property.m_hdl; + return *this; +} + +/// Property type name +string Property::type(const Property& property) { + return type(property.grammar().type()); +} + +/// Property type name +string Property::type(const type_info& typ) { + return __typename(typ.name()); +} + +/// Property type name +string Property::type() const { + return Property::type(grammar().type()); +} + +const PropertyGrammar& Property::grammar() const { + if ( m_hdl ) return *m_hdl; + throw runtime_error("Attempt to access property grammar from invalid object."); +} + +/// Conversion to string value +string Property::str() const { + if ( m_hdl && m_par ) { + return m_hdl->str(m_par); + } + throw runtime_error("Attempt to access property grammar from invalid object."); +} + +/// Conversion from string value +Property& Property::str(const std::string& input) { + if ( m_hdl && m_par ) { + m_hdl->fromString(m_par,input); + return *this; + } + throw runtime_error("Attempt to access property grammar from invalid object."); +} + +/// Assignment operator / set new balue +Property& Property::operator=(const string& val) { + this->set<string>(val); + return *this; +} + +/// Assignment operator / set new balue +Property& Property::operator=(const char* val) { + if ( val ) { + this->set<string>(val); + return *this; + } + throw runtime_error("Attempt to set invalid string to property!"); +} + +/// Default constructor +PropertyManager::PropertyManager() { +} + +/// Default destructor +PropertyManager::~PropertyManager() { + m_properties.clear(); +} + +/// Verify that this property does not exist (throw exception if the name was found) +void PropertyManager::verifyNonExistence(const string& name) const { + Properties::const_iterator i = m_properties.find(name); + if ( i == m_properties.end() ) return; + throw runtime_error("The property:"+name+" already exists for this component."); +} + +/// Verify that this property exists (throw exception if the name was not found) +PropertyManager::Properties::const_iterator +PropertyManager::verifyExistence(const string& name) const { + Properties::const_iterator i = m_properties.find(name); + if ( i != m_properties.end() ) return i; + throw runtime_error("PropertyManager: Unknown property:"+name); +} + +/// Verify that this property exists (throw exception if the name was not found) +PropertyManager::Properties::iterator +PropertyManager::verifyExistence(const string& name) { + Properties::iterator i = m_properties.find(name); + if ( i != m_properties.end() ) return i; + throw runtime_error("PropertyManager: Unknown property:"+name); +} + +/// Access property by name (CONST) +Property& PropertyManager::property(const string& name) { + return (*verifyExistence(name)).second; +} + +/// Access property by name +const Property& PropertyManager::property(const string& name) const { + return (*verifyExistence(name)).second; +} + +/// Access property by name +Property& PropertyManager::operator[](const string& name) { + return (*verifyExistence(name)).second; +} + +/// Access property by name +const Property& PropertyManager::operator[](const string& name) const { + return (*verifyExistence(name)).second; +} + +/// Add a new property +void PropertyManager::add(const string& name, const Property& property) { + verifyNonExistence(name); + m_properties.insert(make_pair(name,property)); +} + +/// Bulk set of all properties +void PropertyManager::set(const string& component_name, PropertyConfigurator& cfg) { + for(Properties::iterator i = m_properties.begin(); i!=m_properties.end(); ++i) { + Property& p = (*i).second; + cfg.set(p.grammar(),component_name,(*i).first,p.ptr()); + } +} + +/// Dump string values +void PropertyManager::dump() const { + for(Properties::const_iterator i = m_properties.begin(); i!=m_properties.end(); ++i) { + const Property& p = (*i).second; + printout(ALWAYS,"PropertyManager","Property %s = %s",(*i).first.c_str(),p.str().c_str()); + } +} + +#define DD4HEP_INSTANTIATE_PROPERTY_TYPE1(x) DD4HEP_INSTANTIATE_PROPERTY_TYPE(x); \ + DD4HEP_INSTANTIATE_PROPERTY_TYPE(std::vector<x>); \ + DD4HEP_INSTANTIATE_PROPERTY_TYPE(std::list<x>); \ + DD4HEP_INSTANTIATE_PROPERTY_TYPE(std::set<x>) + +#define DD4HEP_INSTANTIATE_PROPERTY_TYPE2(x) \ + DD4HEP_INSTANTIATE_PROPERTY_TYPE1(x); \ + DD4HEP_INSTANTIATE_PROPERTY_TYPE1(unsigned x) + +DD4HEP_INSTANTIATE_PROPERTY_TYPE2(char); +DD4HEP_INSTANTIATE_PROPERTY_TYPE2(short); +DD4HEP_INSTANTIATE_PROPERTY_TYPE2(int); +DD4HEP_INSTANTIATE_PROPERTY_TYPE2(long); +DD4HEP_INSTANTIATE_PROPERTY_TYPE2(long long); + +DD4HEP_INSTANTIATE_PROPERTY_TYPE1(bool); +DD4HEP_INSTANTIATE_PROPERTY_TYPE1(float); +DD4HEP_INSTANTIATE_PROPERTY_TYPE1(double); +DD4HEP_INSTANTIATE_PROPERTY_TYPE1(string); + +typedef map<string,int> map_string_int; +DD4HEP_INSTANTIATE_PROPERTY_TYPE(map_string_int); + diff --git a/DDG4/src/Geant4Action.cpp b/DDG4/src/Geant4Action.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bfe77565668a202d9b7ab52e4c77548b87912291 --- /dev/null +++ b/DDG4/src/Geant4Action.cpp @@ -0,0 +1,175 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#include <algorithm> +#include "DD4hep/Printout.h" +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4Context.h" +#include "DDG4/Geant4Action.h" +#include "DDG4/Geant4Kernel.h" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Simulation; + +TypeName TypeName::split(const string& type_name) { + size_t idx = type_name.find("/"); + string typ=type_name, nam=type_name; + if ( idx != string::npos ) { + typ = type_name.substr(0,idx); + nam = type_name.substr(idx+1); + } + return TypeName(typ,nam); +} + +/// Default constructor +Geant4TrackInformation::Geant4TrackInformation() +: G4VUserTrackInformation(), m_flags(0) +{ +} + +/// Standard destructor +Geant4TrackInformation::~Geant4TrackInformation() { +} + +/// Access flag if track should be stored +Geant4TrackInformation& Geant4TrackInformation::storeTrack(bool value) { + value ? m_flags |= STORE : m_flags &= ~STORE; + return *this; +} + +/// Standard constructor +Geant4Action::Geant4Action(Geant4Context* context, const string& nam) +: m_context(context), m_name(nam), m_refCount(1) +{ + InstanceCount::increment(this); + declareProperty("name",m_name); +} + +/// Default destructor +Geant4Action::~Geant4Action() { + InstanceCount::decrement(this); +} + +/// Implicit destruction +long Geant4Action::addRef() { + return ++m_refCount; +} + +/// Decrease reference count. Implicit destruction +long Geant4Action::release() { + long count = --m_refCount; + if ( m_refCount <= 0 ) { + cout << "Geant4Action: Deleting object " << name() + << " of type " << typeinfoName(typeid(*this)) << endl; + delete this; + } + return count; +} + +/// Set the context pointer +void Geant4Action::setContext(Geant4Context* context) { + m_context = context; +} + +/// Set object properties +Geant4Action& Geant4Action::setProperties(PropertyConfigurator& setup) { + m_properties.set(m_name,setup); + return *this; +} + +/// Support of debug messages. +void Geant4Action::debug(const string& fmt, ...) const { + va_list args; + va_start(args,fmt); + DD4hep::printout(DD4hep::DEBUG,"Geant4Action",fmt,args); + va_end(args); +} + +/// Support of info messages. +void Geant4Action::info(const string& fmt, ...) const { + va_list args; + va_start(args,fmt); + DD4hep::printout(DD4hep::INFO,"Geant4Action",fmt,args); + va_end(args); +} + +/// Support of warning messages. +void Geant4Action::warning(const string& fmt, ...) const { + va_list args; + va_start(args,fmt); + DD4hep::printout(DD4hep::WARNING,"Geant4Action",fmt,args); + va_end(args); +} + +/// Action to support error messages. +void Geant4Action::error(const string& fmt, ...) const { + va_list args; + va_start(args,fmt); + DD4hep::printout(DD4hep::ERROR,"Geant4Action",fmt,args); + va_end(args); +} + +/// Action to support error messages. +bool Geant4Action::error(bool return_value, const string& fmt, ...) const { + va_list args; + va_start(args,fmt); + DD4hep::printout(DD4hep::ERROR,"Geant4Action",fmt,args); + va_end(args); + return return_value; +} + +/// Support of fatal messages. Throws exception if required. +void Geant4Action::fatal(const string& fmt, ...) const { + string err; + va_list args; + va_start(args,fmt); + DD4hep::printout(DD4hep::FATAL,"Geant4Action",fmt,args); + va_end(args); +} + +/// Support of exceptions: Print fatal message and throw runtime_error. +void Geant4Action::except(const string& fmt, ...) const { + string err; + va_list args; + va_start(args,fmt); + DD4hep::printout(DD4hep::FATAL,"Geant4Action",fmt,args); + err = DD4hep::format("Geant4Action",fmt,args); + va_end(args); + throw runtime_error(err); +} + +/// Access to the main run action sequence from the kernel object +Geant4RunActionSequence& Geant4Action::runAction() const { + return m_context->runAction(); +} + +/// Access to the main event action sequence from the kernel object +Geant4EventActionSequence& Geant4Action::eventAction() const { + return m_context->eventAction(); +} + +/// Access to the main stepping action sequence from the kernel object +Geant4SteppingActionSequence& Geant4Action::steppingAction() const { + return m_context->steppingAction(); +} + +/// Access to the main tracking action sequence from the kernel object +Geant4TrackingActionSequence& Geant4Action::trackingAction() const { + return m_context->trackingAction(); +} + +/// Access to the main stacking action sequence from the kernel object +Geant4StackingActionSequence& Geant4Action::stackingAction() const { + return m_context->stackingAction(); +} + +/// Access to the main generator action sequence from the kernel object +Geant4GeneratorActionSequence& Geant4Action::generatorAction() const { + return m_context->generatorAction(); +} diff --git a/DDG4/src/Geant4ActionPhase.cpp b/DDG4/src/Geant4ActionPhase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c0f3366d96440d22422ca0e8cd36fdb98e444c4 --- /dev/null +++ b/DDG4/src/Geant4ActionPhase.cpp @@ -0,0 +1,114 @@ +// $Id: Geant4ActionPhase.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4ActionPhase.h" + +using namespace std; +using namespace DD4hep::Simulation; + +/// Standard constructor +Geant4ActionPhase::Geant4ActionPhase(Geant4Context* context, const string& nam, const type_info& arg_type0, + const type_info& arg_type1, const type_info& arg_type2) +: Geant4Action(context,nam) +{ + m_argTypes[0] = &arg_type0; + m_argTypes[1] = &arg_type1; + m_argTypes[2] = &arg_type2; + InstanceCount::increment(this); +} + +/// Default destructor +Geant4ActionPhase::~Geant4ActionPhase() { + m_members.clear(); + InstanceCount::decrement(this); +} + +/// Add a new member to the phase +bool Geant4ActionPhase::add(Callback callback) { + m_members.push_back(callback); + return true; +} + +/// Remove an existing member from the phase. If not existing returns false +bool Geant4ActionPhase::remove(Callback callback) { + if ( callback.func.first ) { + Members::iterator i = find(m_members.begin(),m_members.end(),callback); + if ( i != m_members.end() ) { + m_members.erase(i); + return true; + } + return false; + } + size_t len = m_members.size(); + for(Members::iterator i = m_members.begin(); i != m_members.end(); ++i) { + if ( (*i).par == callback.par ) { + m_members.erase(i); + i = m_members.begin(); + } + } + return (len > m_members.size()); +} + +/// Execute all members in the phase context +void Geant4ActionPhase::execute(void* argument) { + for(Members::iterator i=m_members.begin(); i!=m_members.end(); ++i) { + (*i).execute((const void**)&argument); + } +} + +class G4HCofThisEvent; +class G4TouchableHistory; +#include "DDG4/Geant4RunAction.h" +#include "DDG4/Geant4EventAction.h" +#include "DDG4/Geant4TrackingAction.h" +#include "DDG4/Geant4SteppingAction.h" +#include "DDG4/Geant4GeneratorAction.h" +namespace DD4hep { namespace Simulation { + /// Callback in Begin stacking action + void Geant4ActionPhase::call() { + this->execute(0); + } + /// Callback in BeginRun/EndRun + template <> void Geant4ActionPhase::call<const G4Run*>(const G4Run* run) { + this->execute((const void**)&run); + } + /// Callback in prepare primaries + template <> void Geant4ActionPhase::call<G4Event*>(G4Event* event) { + this->execute((const void**)&event); + } + /// Callback in BeginEvent/EndEvent + template <> void Geant4ActionPhase::call<const G4Event*>(const G4Event* event) { + this->execute((const void**)&event); + } + /// Callback in Begin/End tracking action + template <> void Geant4ActionPhase::call<const G4Track*>(const G4Track* track) { + this->execute((const void**)&track); + } + /// Callback in Begin/End stepping action + template <> void Geant4ActionPhase::call<const G4Step*>(const G4Step* step) { + this->execute((const void**)&step); + } + /// Callback for user stepping action + template <> void Geant4ActionPhase::call<const G4Step*,G4SteppingManager*>(const G4Step* step,G4SteppingManager* mgr) { + const void * args[] = {step,mgr}; + this->execute(args); + } + /// Callback for sensitives begin/end/clear + template <> void Geant4ActionPhase::call<G4HCofThisEvent*>(G4HCofThisEvent* hce) { + this->execute((const void**)&hce); + } + /// Callback for sensitives + template <> void Geant4ActionPhase::call<G4Step*,G4TouchableHistory*>(G4Step* step,G4TouchableHistory* history) { + const void * args[] = {step,history}; + this->execute(args); + } + } +} diff --git a/DDG4/src/Geant4Callback.cpp b/DDG4/src/Geant4Callback.cpp new file mode 100644 index 0000000000000000000000000000000000000000..46b87a7c06d6782011b7439ddde23c73c759c10f --- /dev/null +++ b/DDG4/src/Geant4Callback.cpp @@ -0,0 +1,21 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#include <algorithm> +#include "DDG4/Geant4Callback.h" +#include "DDG4/ComponentUtils.h" + +using namespace DD4hep; + +/// Check the compatibility of two typed objects. The test is the result of a dynamic_cast +void CallbackSequence::checkTypes(const std::type_info& typ1, const std::type_info& typ2, void* test) { + if ( !test ) { + throw unrelated_type_error(typ1,typ2,"Cannot install a callback for these 2 types."); + } +} + diff --git a/DDG4/src/Geant4Context.cpp b/DDG4/src/Geant4Context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..31311a41575eb1b3fce04e71fd5161decdc73eae --- /dev/null +++ b/DDG4/src/Geant4Context.cpp @@ -0,0 +1,74 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#include <algorithm> +#include "DD4hep/Printout.h" +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4Context.h" +#include "DDG4/Geant4Kernel.h" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Simulation; + +/// Default constructor +Geant4Context::Geant4Context(Geant4Kernel* kernel) +: m_kernel(kernel), m_trackMgr(0) +{ +} + +/// Default destructor +Geant4Context::~Geant4Context() { +} + +/// Access to detector description +Geometry::LCDD& Geant4Context::lcdd() const { + return m_kernel->lcdd(); +} + +/// Create a user trajectory +G4VTrajectory* Geant4Context::createTrajectory(const G4Track* /* track */) const { + string err = DD4hep::format("Geant4Kernel","createTrajectory: Purely virtual method. requires overloading!"); + DD4hep::printout(DD4hep::FATAL,"Geant4Kernel","createTrajectory: Purely virtual method. requires overloading!"); + throw runtime_error(err); +} + +/// Access to the main run action sequence from the kernel object +Geant4RunActionSequence& Geant4Context::runAction() const { + return m_kernel->runAction(); +} + +/// Access to the main event action sequence from the kernel object +Geant4EventActionSequence& Geant4Context::eventAction() const { + return m_kernel->eventAction(); +} + +/// Access to the main stepping action sequence from the kernel object +Geant4SteppingActionSequence& Geant4Context::steppingAction() const { + return m_kernel->steppingAction(); +} + +/// Access to the main tracking action sequence from the kernel object +Geant4TrackingActionSequence& Geant4Context::trackingAction() const { + return m_kernel->trackingAction(); +} + +/// Access to the main stacking action sequence from the kernel object +Geant4StackingActionSequence& Geant4Context::stackingAction() const { + return m_kernel->stackingAction(); +} + +/// Access to the main generator action sequence from the kernel object +Geant4GeneratorActionSequence& Geant4Context::generatorAction() const { + return m_kernel->generatorAction(); +} + +/// Access to the main generator action sequence from the kernel object +Geant4SensDetSequences& Geant4Context::sensitiveActions() const { + return m_kernel->sensitiveActions(); +} diff --git a/DDG4/src/Geant4Converter.cpp b/DDG4/src/Geant4Converter.cpp index 82ea256e651f7cf7e625eeff4b68de9c21f56679..53ddf9748853f330ac4e9b9679b35f3dc5a9daf2 100644 --- a/DDG4/src/Geant4Converter.cpp +++ b/DDG4/src/Geant4Converter.cpp @@ -38,11 +38,12 @@ #include "TClass.h" #include "TMath.h" +// Geant4 include files #include "G4VSensitiveDetector.hh" #include "G4VisAttributes.hh" #include "G4ProductionCuts.hh" #include "G4VUserRegionInformation.hh" -// Geant4 include files + #include "G4Element.hh" #include "G4SDManager.hh" #include "G4Assembly.hh" @@ -58,11 +59,8 @@ #include "G4Paraboloid.hh" #include "G4SubtractionSolid.hh" #include "G4IntersectionSolid.hh" - #include "G4Region.hh" #include "G4UserLimits.hh" -#include "G4VSensitiveDetector.hh" - #include "G4LogicalVolume.hh" #include "G4Material.hh" #include "G4Element.hh" @@ -72,7 +70,6 @@ #include "G4PVPlacement.hh" #include "G4ElectroMagneticField.hh" #include "G4FieldManager.hh" - #include "G4ReflectionFactory.hh" #include <iostream> diff --git a/DDG4/src/Geant4Converter.cpp.save b/DDG4/src/Geant4Converter.cpp.save new file mode 100644 index 0000000000000000000000000000000000000000..26608774a6ad129b18a25d923c154d5b67cd03c4 --- /dev/null +++ b/DDG4/src/Geant4Converter.cpp.save @@ -0,0 +1,937 @@ +// $Id: Geant4Converter.cpp 788 2013-09-20 17:04:50Z gaede $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +#include "DD4hep/LCDD.h" +#include "DD4hep/Plugins.h" +#include "DD4hep/Volumes.h" +#include "DD4hep/Printout.h" +#include "DDG4/Geant4Field.h" +#include "DDG4/Geant4Converter.h" +#include "DDG4/Factories.h" +#include "DDG4/Geant4SensitiveDetector.h" + +// ROOT includes +#include "TROOT.h" +#include "TColor.h" +#include "TGeoNode.h" +#include "TGeoShape.h" +#include "TGeoCone.h" +#include "TGeoPcon.h" +#include "TGeoPgon.h" +#include "TGeoSphere.h" +#include "TGeoTorus.h" +#include "TGeoTube.h" +#include "TGeoTrd1.h" +#include "TGeoTrd2.h" +#include "TGeoArb8.h" +#include "TGeoMatrix.h" +#include "TGeoBoolNode.h" +#include "TGeoParaboloid.h" +#include "TGeoCompositeShape.h" +#include "TGeoShapeAssembly.h" +#include "TClass.h" +#include "TMath.h" + +#include "G4VSensitiveDetector.hh" +#include "G4VisAttributes.hh" +#include "G4ProductionCuts.hh" +#include "G4VUserRegionInformation.hh" +// Geant4 include files +#include "G4Element.hh" +#include "G4SDManager.hh" +#include "G4Assembly.hh" +#include "G4Box.hh" +#include "G4Trd.hh" +#include "G4Tubs.hh" +#include "G4Cons.hh" +#include "G4Torus.hh" +#include "G4Sphere.hh" +#include "G4Polycone.hh" +#include "G4Polyhedra.hh" +#include "G4UnionSolid.hh" +#include "G4Paraboloid.hh" +#include "G4SubtractionSolid.hh" +#include "G4IntersectionSolid.hh" + +#include "G4Region.hh" +#include "G4UserLimits.hh" +#include "G4VSensitiveDetector.hh" + +#include "G4LogicalVolume.hh" +#include "G4Material.hh" +#include "G4Element.hh" +#include "G4Isotope.hh" +#include "G4Transform3D.hh" +#include "G4ThreeVector.hh" +#include "G4PVPlacement.hh" +#include "G4ElectroMagneticField.hh" +#include "G4FieldManager.hh" + +#include "G4ReflectionFactory.hh" + +#include <iostream> +#include <iomanip> +#include <sstream> + +using namespace DD4hep::Simulation; +using namespace DD4hep::Geometry; +using namespace DD4hep; +using namespace std; + +#define private public +#include "G4AssemblyVolume.hh" +#undef private + +struct Geant4AssemblyVolume : public G4AssemblyVolume { + Geant4AssemblyVolume() {} + size_t placeVolume(G4LogicalVolume* pPlacedVolume, + G4Transform3D& transformation) { + size_t id = fTriplets.size(); + this->AddPlacedVolume(pPlacedVolume,transformation); + return id; + } + void imprint( std::vector<G4VPhysicalVolume*>& nodes, + G4LogicalVolume* pMotherLV, + G4Transform3D& transformation, + G4int copyNumBase, + G4bool surfCheck ); + +}; + +void Geant4AssemblyVolume::imprint( std::vector<G4VPhysicalVolume*>& nodes, + G4LogicalVolume* pMotherLV, + G4Transform3D& transformation, + G4int copyNumBase, + G4bool surfCheck ) +{ + G4AssemblyVolume* pAssembly = this; + unsigned int numberOfDaughters; + if( copyNumBase == 0 ) { + numberOfDaughters = pMotherLV->GetNoDaughters(); + } + else { + numberOfDaughters = copyNumBase; + } + // We start from the first available index + numberOfDaughters++; + ImprintsCountPlus(); + + std::vector<G4AssemblyTriplet> triplets = pAssembly->fTriplets; + for( unsigned int i = 0; i < triplets.size(); i++ ) { + G4Transform3D Ta( *(triplets[i].GetRotation()), + triplets[i].GetTranslation() ); + if ( triplets[i].IsReflection() ) { Ta = Ta * G4ReflectZ3D(); } + + G4Transform3D Tfinal = transformation * Ta; + + if ( triplets[i].GetVolume() ) + { + // Generate the unique name for the next PV instance + // The name has format: + // + // av_WWW_impr_XXX_YYY_ZZZ + // where the fields mean: + // WWW - assembly volume instance number + // XXX - assembly volume imprint number + // YYY - the name of a log. volume we want to make a placement of + // ZZZ - the log. volume index inside the assembly volume + // + std::stringstream pvName; + pvName << "av_" + << GetAssemblyID() + << "_impr_" + << GetImprintsCount() + << "_" + << triplets[i].GetVolume()->GetName().c_str() + << "_pv_" + << i + << std::ends; + + // Generate a new physical volume instance inside a mother + // (as we allow 3D transformation use G4ReflectionFactory to + // take into account eventual reflection) + // + G4PhysicalVolumesPair pvPlaced + = G4ReflectionFactory::Instance()->Place( Tfinal, + pvName.str().c_str(), + triplets[i].GetVolume(), + pMotherLV, + false, + numberOfDaughters + i, + surfCheck ); + + // Register the physical volume created by us so we can delete it later + // + fPVStore.push_back( pvPlaced.first ); + nodes.push_back(pvPlaced.first); + if ( pvPlaced.second ) { // Supported by G4, but not by TGeo! + fPVStore.push_back( pvPlaced.second ); + G4Exception("G4AssemblyVolume::MakeImprint(..)", + "GeomVol0003", FatalException, + "Fancy construct popping new mother from the stack!"); + } + } + else if ( triplets[i].GetAssembly() ) { + // Place volumes in this assembly with composed transformation + G4Exception("G4AssemblyVolume::MakeImprint(..)", + "GeomVol0003", FatalException, + "Assemblies within assembliesare not supported."); + } + else { + G4Exception("G4AssemblyVolume::MakeImprint(..)", + "GeomVol0003", FatalException, + "Triplet has no volume and no assembly"); + } + } +} + +namespace { + static TGeoNode* s_topPtr; + static string indent = ""; + struct MyTransform3D : public G4Transform3D { + MyTransform3D(double XX, double XY, double XZ, double DX, + double YX, double YY, double YZ, double DY, + double ZX, double ZY, double ZZ, double DZ) + : G4Transform3D(XX,XY,XZ,DX,YX,YY,YZ,DY,ZX,ZY,ZZ,DZ) {} + }; + + void handleName(const TGeoNode* n) { + TGeoVolume* v = n->GetVolume(); + TGeoMedium* m = v->GetMedium(); + TGeoShape* s = v->GetShape(); + string nam; + printout(DEBUG,"G4","TGeoNode:'%s' Vol:'%s' Shape:'%s' Medium:'%s'", + n->GetName(),v->GetName(),s->GetName(),m->GetName()); + } + + class G4UserRegionInformation : public G4VUserRegionInformation { + public: + Region region; + double threshold; + bool storeSecondaries; + G4UserRegionInformation() : threshold(0.0), storeSecondaries(false) {} + virtual ~G4UserRegionInformation() {} + virtual void Print() const { + if ( region.isValid() ) + printout(DEBUG,"Region","Name:%s",region.name()); + } + }; +} + +/// Initializing Constructor +Geant4Converter::Geant4Converter( LCDD& lcdd ) + : Geant4Mapping(lcdd), m_checkOverlaps(true) +{ + this->Geant4Mapping::init(); +} + +/// Standard destructor +Geant4Converter::~Geant4Converter() { +} + +/// Dump element in GDML format to output stream +void* Geant4Converter::handleElement(const string& name, const TGeoElement* element) const { + G4Element* g4e = data().g4Elements[element]; + if ( !g4e ) { + g4e = G4Element::GetElement(name,false); + if ( !g4e ) { + if ( element->GetNisotopes() > 1 ) { + g4e = new G4Element(name,element->GetTitle(),element->GetNisotopes()); + for(int i=0, n=element->GetNisotopes(); i<n; ++i) { + TGeoIsotope* iso = element->GetIsotope(i); + G4Isotope* g4iso = G4Isotope::GetIsotope(iso->GetName(),false); + if ( !g4iso ) { + g4iso = new G4Isotope(iso->GetName(),iso->GetZ(),iso->GetN(),iso->GetA()); + } + g4e->AddIsotope(g4iso,element->GetRelativeAbundance(i)); + } + } + else { + g4e = new G4Element(element->GetTitle(),name,element->Z(),element->A()*(g/mole)); + } + stringstream str; + str << (*g4e); + printout(DEBUG,"Geant4Converter","++ Created G4 %s",str.str().c_str()); + } + data().g4Elements[element] = g4e; + } + return g4e; +} + +/// Dump material in GDML format to output stream +void* Geant4Converter::handleMaterial(const string& name, const TGeoMedium* medium) const { + G4Material* mat = data().g4Materials[medium]; + if ( !mat ) { + mat = G4Material::GetMaterial(name,false); + if ( !mat ) { + TGeoMaterial* m = medium->GetMaterial(); + G4State state = kStateUndefined; + double density = m->GetDensity()*(gram/cm3); + if ( density < 1e-25 ) density = 1e-25; + switch(m->GetState()) { + case TGeoMaterial::kMatStateSolid: + state = kStateSolid; + break; + case TGeoMaterial::kMatStateLiquid: + state = kStateLiquid; + break; + case TGeoMaterial::kMatStateGas: + state = kStateGas; + break; + default: + case TGeoMaterial::kMatStateUndefined: + state = kStateUndefined; + break; + } + if ( m->IsMixture() ) { + double A_total = 0.0; + TGeoMixture* mix = (TGeoMixture*)m; + int nElements = mix->GetNelements(); + mat = new G4Material(name,density,nElements, + state, + m->GetTemperature(), + m->GetPressure()); + for(int i=0; i<nElements; ++i) + A_total += (mix->GetAmixt())[i]; + for(int i=0; i<nElements; ++i) { + TGeoElement* e = mix->GetElement(i); + G4Element* g4e = (G4Element*)handleElement(e->GetName(),e); + if ( !g4e ) { + printout(ERROR,"Material","Missing component %s for material %s.", + e->GetName(), mix->GetName()); + } + mat->AddElement(g4e,(mix->GetAmixt())[i]/A_total); + } + } + else { + mat = new G4Material(name,m->GetZ(),m->GetA(),density,state, + m->GetTemperature(),m->GetPressure()); + } + stringstream str; + str << (*mat); + printout(DEBUG,"Geant4Converter","++ Created G4 %s",str.str().c_str()); + } + data().g4Materials[medium] = mat; + } + return mat; +} + +/// Dump solid in GDML format to output stream +void* Geant4Converter::handleSolid(const string& name, const TGeoShape* shape) const { + G4VSolid* solid = 0; + if ( shape ) { + if ( 0 != (solid=data().g4Solids[shape]) ) { + return solid; + } + else if ( shape->IsA() == TGeoShapeAssembly::Class() ) { + solid = (G4VSolid*)new G4Assembly(); + } + else if ( shape->IsA() == TGeoBBox::Class() ) { + const TGeoBBox* s = (const TGeoBBox*)shape; + solid = new G4Box(name,s->GetDX()*CM_2_MM,s->GetDY()*CM_2_MM,s->GetDZ()*CM_2_MM); + } + else if ( shape->IsA() == TGeoTube::Class() ) { + const TGeoTube* s = (const TGeoTube*)shape; + solid = new G4Tubs(name,s->GetRmin()*CM_2_MM,s->GetRmax()*CM_2_MM,s->GetDz()*CM_2_MM,0,2.*M_PI); + } + else if ( shape->IsA() == TGeoTubeSeg::Class() ) { + const TGeoTubeSeg* s = (const TGeoTubeSeg*)shape; + solid = new G4Tubs(name,s->GetRmin()*CM_2_MM,s->GetRmax()*CM_2_MM,s->GetDz()*CM_2_MM,s->GetPhi1()*DEGREE_2_RAD,s->GetPhi2()*DEGREE_2_RAD); + } + else if ( shape->IsA() == TGeoTrd1::Class() ) { + const TGeoTrd1* s = (const TGeoTrd1*)shape; + solid = new G4Trd(name,s->GetDx1()*CM_2_MM,s->GetDx2()*CM_2_MM,s->GetDy()*CM_2_MM,s->GetDy()*CM_2_MM,s->GetDz()*CM_2_MM); + } + else if ( shape->IsA() == TGeoTrd2::Class() ) { + const TGeoTrd2* s = (const TGeoTrd2*)shape; + solid = new G4Trd(name,s->GetDx1()*CM_2_MM,s->GetDx2()*CM_2_MM,s->GetDy1()*CM_2_MM,s->GetDy2()*CM_2_MM,s->GetDz()*CM_2_MM); + } + else if ( shape->IsA() == TGeoPgon::Class() ) { + const TGeoPgon* s = (const TGeoPgon*)shape; + double phi_start = s->GetPhi1()*DEGREE_2_RAD; + double phi_total = (s->GetDphi()+s->GetPhi1())*DEGREE_2_RAD; + vector<double> rmin, rmax, z; + for( Int_t i=0; i<s->GetNz(); ++i ) { + rmin.push_back(s->GetRmin(i)*CM_2_MM); + rmax.push_back(s->GetRmax(i)*CM_2_MM); + z.push_back(s->GetZ(i)*CM_2_MM); + } + solid = new G4Polyhedra(name,phi_start,phi_total,s->GetNedges(),s->GetNz(),&z[0],&rmin[0],&rmax[0]); + } + else if ( shape->IsA() == TGeoPcon::Class() ) { + const TGeoPcon* s = (const TGeoPcon*)shape; + double phi_start = s->GetPhi1()*DEGREE_2_RAD; + double phi_total = (s->GetDphi()+s->GetPhi1())*DEGREE_2_RAD; + vector<double> rmin, rmax, z; + for( Int_t i=0; i<s->GetNz(); ++i ) { + rmin.push_back(s->GetRmin(i)*CM_2_MM); + rmax.push_back(s->GetRmax(i)*CM_2_MM); + z.push_back(s->GetZ(i)*CM_2_MM); + } + solid = new G4Polycone(name,phi_start,phi_total,s->GetNz(),&z[0],&rmin[0],&rmax[0]); + } + else if ( shape->IsA() == TGeoConeSeg::Class() ) { + const TGeoConeSeg* s = (const TGeoConeSeg*)shape; + solid = new G4Cons(name, + s->GetRmin1()*CM_2_MM, + s->GetRmax1()*CM_2_MM, + s->GetRmin2()*CM_2_MM, + s->GetRmax2()*CM_2_MM, + s->GetDz()*CM_2_MM, + s->GetPhi1()*DEGREE_2_RAD, + s->GetPhi2()*DEGREE_2_RAD); + } + else if ( shape->IsA() == TGeoParaboloid::Class() ) { + const TGeoParaboloid* s = (const TGeoParaboloid*)shape; + solid = new G4Paraboloid(name,s->GetDz()*CM_2_MM,s->GetRlo()*CM_2_MM,s->GetRhi()*CM_2_MM); + } + else if ( shape->IsA() == TGeoSphere::Class() ) { + const TGeoSphere* s = (const TGeoSphere*)shape; + solid = new G4Sphere(name,s->GetRmin()*CM_2_MM,s->GetRmax()*CM_2_MM, + s->GetPhi1()*DEGREE_2_RAD,s->GetPhi2()*DEGREE_2_RAD, + s->GetTheta1()*DEGREE_2_RAD,s->GetTheta2()*DEGREE_2_RAD); + } + else if ( shape->IsA() == TGeoTorus::Class() ) { + const TGeoTorus* s = (const TGeoTorus*)shape; + solid = new G4Torus(name,s->GetRmin()*CM_2_MM,s->GetRmax()*CM_2_MM, s->GetR()*CM_2_MM, + s->GetPhi1()*DEGREE_2_RAD,s->GetDphi()*DEGREE_2_RAD); + } + else if ( shape->IsA() == TGeoCompositeShape::Class() ) { + const TGeoCompositeShape* s = (const TGeoCompositeShape*)shape; + const TGeoBoolNode* boolean = s->GetBoolNode(); + TGeoBoolNode::EGeoBoolType oper = boolean->GetBooleanOperator(); + TGeoMatrix* m = boolean->GetRightMatrix(); + G4VSolid* left = (G4VSolid*)handleSolid(name+"_left", boolean->GetLeftShape()); + G4VSolid* right = (G4VSolid*)handleSolid(name+"_right",boolean->GetRightShape()); + const Double_t *t = m->GetTranslation(); + const Double_t *r = m->GetRotationMatrix(); + + if ( !left ) { + throw runtime_error("G4Converter: No left Geant4 Solid present for composite shape:"+name); + } + if ( !right ) { + throw runtime_error("G4Converter: No right Geant4 Solid present for composite shape:"+name); + } + + if ( m->IsRotation() ) { + MyTransform3D transform(r[0],r[1],r[2],t[0]*CM_2_MM, + r[3],r[4],r[5],t[1]*CM_2_MM, + r[6],r[7],r[8],t[2]*CM_2_MM); + if ( oper == TGeoBoolNode::kGeoSubtraction ) + solid = new G4SubtractionSolid(name,left,right,transform); + else if ( oper == TGeoBoolNode::kGeoUnion ) + solid = new G4UnionSolid(name,left,right,transform); + else if ( oper == TGeoBoolNode::kGeoIntersection ) + solid = new G4IntersectionSolid(name,left,right,transform); + } + else { + G4ThreeVector transform(t[0]*CM_2_MM,t[1]*CM_2_MM,t[2]*CM_2_MM); + if ( oper == TGeoBoolNode::kGeoSubtraction ) + solid = new G4SubtractionSolid(name,left,right,0,transform); + else if ( oper == TGeoBoolNode::kGeoUnion ) + solid = new G4UnionSolid(name,left,right,0,transform); + else if ( oper == TGeoBoolNode::kGeoIntersection ) + solid = new G4IntersectionSolid(name,left,right,0,transform); + } + } + + if ( !solid ) { + string err = "Failed to handle unknown solid shape:" + + name + " of type " + string(shape->IsA()->GetName()); + throw runtime_error(err); + } + data().g4Solids[shape] = solid; + } + return solid; +} + +/// Dump logical volume in GDML format to output stream +void* Geant4Converter::handleVolume(const string& name, const TGeoVolume* volume) const { + Geant4GeometryInfo& info = data(); + G4LogicalVolume* vol = info.g4Volumes[volume]; + if ( !vol ) { + const TGeoVolume* v = volume; + Volume _v = Ref_t(v); + string n = v->GetName(); + TGeoMedium* m = v->GetMedium(); + TGeoShape* s = v->GetShape(); + G4VSolid* solid = (G4VSolid*)handleSolid(s->GetName(),s); + G4Material* medium = 0; + bool assembly = s->IsA() == TGeoShapeAssembly::Class(); + + SensitiveDetector det = _v.sensitiveDetector(); + G4VSensitiveDetector* sd = 0; + + if ( det.isValid() ) { + sd = info.g4SensDets[det.ptr()]; + if ( !sd ) { + throw runtime_error("G4Cnv::volume["+name+"]: + FATAL Failed to " + "access Geant4 sensitive detector."); + } + sd->Activate(true); + } + LimitSet lim = _v.limitSet(); + G4UserLimits* user_limits = 0; + if ( lim.isValid() ) { + user_limits = info.g4Limits[lim.ptr()]; + if ( !user_limits ) { + throw runtime_error("G4Cnv::volume["+name+"]: + FATAL Failed to " + "access Geant4 user limits."); + } + } + VisAttr vis = _v.visAttributes(); + G4VisAttributes* vis_attr = 0; + if ( vis.isValid() ) { + vis_attr = (G4VisAttributes*)handleVis(vis.name(),vis.ptr()); + } + Region reg = _v.region(); + G4Region* region = 0; + if ( reg.isValid() ) { + region = info.g4Regions[reg.ptr()]; + if ( !region ) { + throw runtime_error("G4Cnv::volume["+name+"]: + FATAL Failed to " + "access Geant4 region."); + } + } + + printout(DEBUG,"Geant4Converter","++ Convert Volume %-32s: %p %s/%s assembly:%s sensitive:%s", + n.c_str(),v,s->IsA()->GetName(),v->IsA()->GetName(),(assembly ? "YES" : "NO"), + (det.isValid() ? "YES" : "NO")); + + + if ( assembly ) { + vol = (G4LogicalVolume*)new G4AssemblyVolume(); + info.g4Volumes[v] = vol; + return vol; + } + medium = (G4Material*)handleMaterial(m->GetName(),m); + if ( !solid ) { + throw runtime_error("G4Converter: No Geant4 Solid present for volume:"+n); + } + if ( !medium ) { + throw runtime_error("G4Converter: No Geant4 material present for volume:"+n); + } + if ( user_limits ) { + printout(DEBUG,"++ Volume + Apply LIMITS settings:%-24s to volume %s.",lim.name(),_v.name()); + } + vol = new G4LogicalVolume(solid,medium,n,0,sd,user_limits); + if ( region ) { + printout(DEBUG,"Geant4Converter","++ Volume + Apply REGION settings: %s to volume %s.",reg.name(),_v.name()); + vol->SetRegion(region); + region->AddRootLogicalVolume(vol); + } + if ( vis_attr ) { + vol->SetVisAttributes(vis_attr); + } + if ( sd ) { + printout(DEBUG,"Geant4Converter","++ Volume: + %s <> %s Solid:%s Mat:%s SD:%s", + name.c_str(),vol->GetName().c_str(),solid->GetName().c_str(), + medium->GetName().c_str(),sd->GetName().c_str()); + } + info.g4Volumes[v] = vol; + printout(DEBUG,"Geant4Converter", "++ Volume + %s converted: %p ---> G4: %p",n.c_str(),v,vol); + } + return vol; +} + +/// Dump logical volume in GDML format to output stream +void* Geant4Converter::collectVolume(const string& /* name */, const TGeoVolume* volume) const { + Geant4GeometryInfo& info = data(); + const TGeoVolume* v = volume; + Volume _v = Ref_t(v); + Region reg = _v.region(); + LimitSet lim = _v.limitSet(); + SensitiveDetector det = _v.sensitiveDetector(); + + if ( lim.isValid() ) info.limits[lim.ptr()].insert(v); + if ( reg.isValid() ) info.regions[reg.ptr()].insert(v); + if ( det.isValid() ) info.sensitives[det.ptr()].insert(v); + return (void*)v; +} + +/// Dump volume placement in GDML format to output stream +void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) const { + static Double_t identity_rot[] = { 1., 0., 0., 0., 1., 0., 0., 0., 1. }; + Geant4GeometryInfo& info = data(); + PlacementMap::const_iterator g4it = info.g4Placements.find(node); + G4VPhysicalVolume* g4 = (g4it == info.g4Placements.end()) ? 0 : (*g4it).second; + if ( !g4 ) { + TGeoVolume* mot_vol = node->GetMotherVolume(); + TGeoVolume* vol = node->GetVolume(); + TGeoMatrix* trafo = node->GetMatrix(); + if ( !trafo ) { + printout(FATAL,"Geant4Converter","++ Attempt to handle placement without transformation:%p %s of type %s vol:%p", + node,node->GetName(),node->IsA()->GetName(),vol); + } + else if ( 0 == vol ) { + printout(FATAL,"Geant4Converter","++ Unknown G4 volume:%p %s of type %s vol:%s ptr:%p", + node,node->GetName(),node->IsA()->GetName(),vol->IsA()->GetName(),vol); + } + else { + int copy = node->GetNumber(); + G4LogicalVolume* g4vol = info.g4Volumes[vol]; + G4LogicalVolume* g4mot = info.g4Volumes[mot_vol]; + Geant4AssemblyVolume* ass_mot = (Geant4AssemblyVolume*)g4mot; + Geant4AssemblyVolume* ass_dau = (Geant4AssemblyVolume*)g4vol; + const Double_t* trans = trafo->GetTranslation(); + const Double_t* rot = trafo->IsRotation() ? trafo->GetRotationMatrix() : identity_rot; + bool daughter_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class(); + bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() : false; + MyTransform3D transform(rot[0],rot[1],rot[2],trans[0]*CM_2_MM, + rot[3],rot[4],rot[5],trans[1]*CM_2_MM, + rot[6],rot[7],rot[8],trans[2]*CM_2_MM); + CLHEP::HepRotation rotmat=transform.getRotation(); + + if ( mother_is_assembly ) { // Mother is an assembly: + printout(DEBUG,"Geant4Converter","++ Assembly: AddPlacedVolume: %16p dau:%s " + "Tr:x=%8.3f y=%8.3f z=%8.3f Rot:phi=%7.3f theta=%7.3f psi=%7.3f\n", + ass_mot,g4vol ? g4vol->GetName().c_str() : "---", + transform.dx(),transform.dy(),transform.dz(), + rotmat.getPhi(),rotmat.getTheta(),rotmat.getPsi()); + size_t id = ass_mot->placeVolume(g4vol,transform); + info.g4AssemblyChildren[ass_mot].push_back(make_pair(id,node)); + return 0; + } + else if ( daughter_is_assembly ) { + printout(DEBUG,"Geant4Converter","++ Assembly: makeImprint: %16p dau:%s " + "Tr:x=%8.3f y=%8.3f z=%8.3f Rot:phi=%7.3f theta=%7.3f psi=%7.3f\n", + ass_dau,g4mot ? g4mot->GetName().c_str() : "---", + transform.dx(),transform.dy(),transform.dz(), + rotmat.getPhi(),rotmat.getTheta(),rotmat.getPsi()); + std::vector<G4VPhysicalVolume*> phys_volumes; + AssemblyChildMap::iterator i = info.g4AssemblyChildren.find(ass_dau); + if ( i == info.g4AssemblyChildren.end() ) { + printout(ERROR, "Geant4Converter", "++ Non-existing assembly [%p]",ass_dau); + } + const AssemblyChildren& v = (*i).second; + ass_dau->imprint(phys_volumes,g4mot,transform,copy,m_checkOverlaps); + if ( v.size() != phys_volumes.size() ) { + printout(ERROR, "Geant4Converter", "++ Unexpected number of placements in assembly: %ld <> %ld.", + v.size(), phys_volumes.size()); + } + for(size_t j=0; j<v.size(); ++j) { + info.g4Placements[v[j].second] = phys_volumes[j]; + } + return 0; + } + g4 = new G4PVPlacement(transform, // no rotation + g4vol, // its logical volume + name, // its name + g4mot, // its mother (logical) volume + false, // no boolean operations + copy, // its copy number + m_checkOverlaps); + } + info.g4Placements[node] = g4; + } + else { + printout(ERROR, "Geant4Converter", "++ Attempt to DOUBLE-place physical volume: %s No:%d", + name.c_str(),node->GetNumber()); + } + return g4; +} + +/// Convert the geometry type region into the corresponding Geant4 object(s). +void* Geant4Converter::handleRegion(const TNamed* region, const set<const TGeoVolume*>& /* volumes */) const { + G4Region* g4 = data().g4Regions[region]; + if ( !g4 ) { + Region r = Ref_t(region); + g4 = new G4Region(r.name()); + // set production cut + G4ProductionCuts* cuts = new G4ProductionCuts(); + cuts->SetProductionCut(r.cut()); + g4->SetProductionCuts(cuts); + + // create region info with storeSecondaries flag + G4UserRegionInformation* info = new G4UserRegionInformation(); + info->region = r; + info->threshold = r.threshold(); + info->storeSecondaries = r.storeSecondaries(); + g4->SetUserInformation(info); + + printout(INFO, "Geant4Converter", "++ Converted region settings of:%s.",r.name()); + vector<string>& limits = r.limits(); + for(vector<string>::const_iterator i=limits.begin(); i!=limits.end(); ++i) { + const string& nam = *i; + LimitSet ls = m_lcdd.limitSet(nam); + if ( ls.isValid() ) { + bool found = false; + const LimitMap& lm = data().g4Limits; + for(LimitMap::const_iterator j=lm.begin(); j!=lm.end();++j) { + if ( nam == (*j).first->GetName() ) { + g4->SetUserLimits((*j).second); + found = true; + break; + } + } + if ( found ) continue; + } + throw runtime_error("G4Region: Failed to resolve user limitset:"+*i); + } + data().g4Regions[region] = g4; + } + return g4; +} + +/// Convert the geometry type LimitSet into the corresponding Geant4 object(s). +void* Geant4Converter::handleLimitSet(const TNamed* limitset, const set<const TGeoVolume*>& /* volumes */) const { + G4UserLimits* g4 = data().g4Limits[limitset]; + if ( !g4 ) { + LimitSet ls = Ref_t(limitset); + g4 = new G4UserLimits(limitset->GetName()); + const set<Limit>& limits = ls.limits(); + for(LimitSet::Object::const_iterator i=limits.begin(); i!=limits.end(); ++i) { + const Limit& l = *i; + if ( l.name == "step_length_max" ) + g4->SetMaxAllowedStep(l.value); + else if ( l.name == "track_length_max" ) + g4->SetMaxAllowedStep(l.value); + else if ( l.name == "time_max" ) + g4->SetUserMaxTime(l.value); + else if ( l.name == "ekin_min" ) + g4->SetUserMinEkine(l.value); + else if ( l.name == "range_min" ) + g4->SetUserMinRange(l.value); + else + throw runtime_error("Unknown Geant4 user limit: "+l.toString()); + } + data().g4Limits[limitset] = g4; + } + return g4; +} + +/// Convert the geometry type SensitiveDetector into the corresponding Geant4 object(s). +void* Geant4Converter::handleSensitive(const TNamed* sens_det, const set<const TGeoVolume*>& /* volumes */) const { + Geant4GeometryInfo& info = data(); + G4VSensitiveDetector* g4 = info.g4SensDets[sens_det]; + if ( !g4 ) { + SensitiveDetector sd = Ref_t(sens_det); + string type = sd.type(), name = sd.name(); + g4 = PluginService::Create<G4VSensitiveDetector*>(type,name,&m_lcdd); + if ( !g4 ) { + string tmp = type; + tmp[0] = ::toupper(tmp[0]); + type = "Geant4"+tmp; + g4 = PluginService::Create<G4VSensitiveDetector*>(type,name,&m_lcdd); + if ( !g4 ) { + PluginDebug dbg; + g4 = ROOT::Reflex::PluginService::Create<G4VSensitiveDetector*>(type,name,&m_lcdd); + throw runtime_error("Geant4Converter<SensitiveDetector>: FATAL Failed to " + "create Geant4 sensitive detector factory "+name+" of type "+type+"."); + } + } + g4->Activate(true); + G4SDManager::GetSDMpointer()->AddNewDetector(g4); + info.g4SensDets[sens_det] = g4; + } + return g4; +} + +/// Convert the geometry visualisation attributes to the corresponding Geant4 object(s). +void* Geant4Converter::handleVis(const string& /* name */, const TNamed* vis) const { + Geant4GeometryInfo& info = data(); + G4VisAttributes* g4 = info.g4Vis[vis]; + if ( !g4 ) { + float r=0, g=0, b=0; + VisAttr attr = Ref_t(vis); + int style = attr.lineStyle(); + attr.rgb(r,g,b); + g4 = new G4VisAttributes(attr.visible(),G4Colour(r,g,b,attr.alpha())); + //g4->SetLineWidth(attr->GetLineWidth()); + g4->SetDaughtersInvisible(!attr.showDaughters()); + if ( style == VisAttr::SOLID ) { + g4->SetLineStyle(G4VisAttributes::unbroken); + g4->SetForceWireframe(false); + g4->SetForceSolid(true); + } + else if ( style == VisAttr::WIREFRAME || style == VisAttr::DASHED ) { + g4->SetLineStyle(G4VisAttributes::dashed); + g4->SetForceSolid(false); + g4->SetForceWireframe(true); + } + info.g4Vis[vis] = g4; + } + return g4; +} + +/// Handle the geant 4 specific properties +void Geant4Converter::handleProperties(LCDD::Properties& prp) const { + map<string,string> processors; + static int s_idd = 9999999; + string id; + for(LCDD::Properties::const_iterator i=prp.begin(); i!=prp.end(); ++i) { + const string& nam = (*i).first; + const LCDD::PropertyValues& vals = (*i).second; + if ( nam.substr(0,6) == "geant4" ) { + LCDD::PropertyValues::const_iterator id_it = vals.find("id"); + if ( id_it != vals.end() ) { + id= (*id_it).second; + } + else { + char txt[32]; + ::sprintf(txt,"%d",++s_idd); + id = txt; + } + processors.insert(make_pair(id,nam)); + } + } + for(map<string,string>::const_iterator i=processors.begin(); i!=processors.end(); ++i) { + const Geant4Converter* ptr = this; + string nam = (*i).second; + const LCDD::PropertyValues& vals = prp[nam]; + string type = vals.find("type")->second; + string tag = type + "_Geant4_action"; + long result = ROOT::Reflex::PluginService::Create<long>(tag,&m_lcdd,ptr,&vals); + if ( 0 == result ) { + throw runtime_error("Failed to locate plugin to interprete files of type" + " \""+tag+"\" - no factory:"+type); + } + result = *(long*)result; + if ( result != 1 ) { + throw runtime_error("Failed to invoke the plugin "+tag+" of type "+type); + } + printout(INFO, "Geant4Converter", "+++++ Executed Successfully Geant4 setup module *%s*.",type.c_str()); + } +} + + +/// Convert the geometry type SensitiveDetector into the corresponding Geant4 object(s). +void* Geant4Converter::printSensitive(const TNamed* sens_det, const set<const TGeoVolume*>& /* volumes */) const { + Geant4GeometryInfo& info = data(); + G4VSensitiveDetector* g4 = info.g4SensDets[sens_det]; + ConstVolumeSet& volset = info.sensitives[sens_det]; + SensitiveDetector sd = Ref_t(sens_det); + stringstream str; + + printout(INFO, "Geant4Converter", "++ SensitiveDetector: %-18s %-20s Hits:%-16s", + sd.name(), ("["+sd.type()+"]").c_str(),sd.hitsCollection().c_str()); + str << " | " + << "Cutoff:" << setw(6) << left << sd.energyCutoff() + << setw(5) << right << volset.size() << " volumes "; + if ( sd.region().isValid() ) str << " Region:" << setw(12) << left << sd.region().name(); + if ( sd.limits().isValid() ) str << " Limits:" << setw(12) << left << sd.limits().name(); + str << "."; + printout(INFO, "Geant4Converter", str.str().c_str()); + + for(ConstVolumeSet::iterator i=volset.begin(); i!=volset.end();++i) { + map<const TGeoVolume*, G4LogicalVolume*>::iterator v = info.g4Volumes.find(*i); + G4LogicalVolume* vol = (*v).second; + str.str(""); + str << " | " + << "Volume:" << setw(24) << left << vol->GetName() + << " " << vol->GetNoDaughters() << " daughters."; + printout(INFO, "Geant4Converter", str.str().c_str()); + } + return g4; +} + +string printSolid(G4VSolid* sol) { + stringstream str; + if ( typeid(*sol) == typeid(G4Box) ) { + const G4Box* b = (G4Box*)sol; + str << "++ Box: x=" << b->GetXHalfLength() << " y=" << b->GetYHalfLength() << " z=" << b->GetZHalfLength(); + } + else if ( typeid(*sol) == typeid(G4Tubs) ) { + const G4Tubs* t = (const G4Tubs*)sol; + str << " Tubs: Ri=" << t->GetInnerRadius() << " Ra=" << t->GetOuterRadius() + << " z/2=" << t->GetZHalfLength() << " Phi=" << t->GetStartPhiAngle() + << "..." << t->GetDeltaPhiAngle (); + } + return str.str(); +} + +/// Print G4 placement +void* Geant4Converter::printPlacement(const string& name, const TGeoNode* node) const { + Geant4GeometryInfo& info = data(); + G4VPhysicalVolume* g4 = info.g4Placements[node]; + G4LogicalVolume* vol = info.g4Volumes[node->GetVolume()]; + G4LogicalVolume* mot = info.g4Volumes[node->GetMotherVolume()]; + G4VSolid* sol = vol->GetSolid(); + G4ThreeVector tr = g4->GetObjectTranslation(); + + G4VSensitiveDetector* sd = vol->GetSensitiveDetector(); + if ( !sd ) return g4; + + stringstream str; + str << "G4Cnv::placement: + " << name << " No:" << node->GetNumber() + << " Vol:" << vol->GetName() << " Solid:" << sol->GetName(); + printout(DEBUG,"G4Placement",str.str().c_str()); + str.str(""); + str << " |" + << " Loc: x=" << tr.x() << " y=" << tr.y() << " z=" << tr.z(); + printout(DEBUG,"G4Placement",str.str().c_str()); + printout(DEBUG,"G4Placement",printSolid(sol).c_str()); + str.str(""); + str << " |" + << " Ndau:" << vol->GetNoDaughters() << " physvols." + << " Mat:" << vol->GetMaterial()->GetName() + << " Mother:" << (char*)(mot ? mot->GetName().c_str() : "---"); + printout(DEBUG,"G4Placement",str.str().c_str()); + str.str(""); + str << " |" + << " SD:" << (char*)(sd ? sd->GetName().c_str() : "---"); + printout(DEBUG,"G4Placement",str.str().c_str()); + return g4; +} + +template <typename O, typename C, typename F> void handle(const O* o, const C& c, F pmf) { + for(typename C::const_iterator i=c.begin(); i != c.end(); ++i) { + (o->*pmf)((*i)->GetName(),*i); + } +} + +template <typename O, typename C, typename F> void handleMap(const O* o, const C& c, F pmf) { + for(typename C::const_iterator i=c.begin(); i != c.end(); ++i) + (o->*pmf)((*i).first, (*i).second); +} + +template <typename O, typename C, typename F> void handleRMap(const O* o, const C& c, F pmf) { + for(typename C::const_reverse_iterator i=c.rbegin(); i != c.rend(); ++i) + handle(o, (*i).second, pmf); +} + +/// Create geometry conversion +Geant4Converter& Geant4Converter::create(DetElement top) { + Geant4GeometryInfo& geo = this->init(); + m_data->clear(); + collect(top, geo); + s_topPtr = top.placement().ptr(); + m_checkOverlaps = false; + + // We do not have to handle defines etc. + // All positions and the like are not really named. + // Hence, start creating the G4 objects for materials, solids and log volumes. + Material mat = m_lcdd.material("Argon"); + handleMaterial(mat.name(),mat.ptr()); + mat = m_lcdd.material("Silicon"); + handleMaterial(mat.name(),mat.ptr()); + + handle(this, geo.volumes, &Geant4Converter::collectVolume); + handle(this, geo.solids, &Geant4Converter::handleSolid); + printout(INFO,"Geant4Converter","++ Handled %ld solids.",geo.solids.size()); + handle(this, geo.vis, &Geant4Converter::handleVis); + printout(INFO,"Geant4Converter","++ Handled %ld visualization attributes.",geo.vis.size()); + handleMap(this, geo.sensitives, &Geant4Converter::handleSensitive); + printout(INFO,"Geant4Converter","++ Handled %ld sensitive detectors.",geo.sensitives.size()); + handleMap(this, geo.limits, &Geant4Converter::handleLimitSet); + printout(INFO,"Geant4Converter","++ Handled %ld limit sets.",geo.limits.size()); + handleMap(this, geo.regions, &Geant4Converter::handleRegion); + printout(INFO,"Geant4Converter","++ Handled %ld regions.",geo.regions.size()); + handle(this, geo.volumes, &Geant4Converter::handleVolume); + printout(INFO,"Geant4Converter","++ Handled %ld volumes.",geo.volumes.size()); + // Now place all this stuff appropriately + handleRMap(this, *m_data, &Geant4Converter::handlePlacement); + //==================== Fields + handleProperties(m_lcdd.properties()); + + //handleMap(this, geo.sensitives, &Geant4Converter::printSensitive); + //handleRMap(this, *m_data, &Geant4Converter::printPlacement); + geo.valid = true; + return *this; +} diff --git a/DDG4/src/Geant4Data.cpp b/DDG4/src/Geant4Data.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3eee1e47931ca225daf2743b9f010ff29540dc15 --- /dev/null +++ b/DDG4/src/Geant4Data.cpp @@ -0,0 +1,101 @@ +// $Id: Geant4Hits.cpp 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4Data.h" + +// Geant4 include files +#include "G4Allocator.hh" +#include "G4OpticalPhoton.hh" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Simulation; + + +/// Default destructor +SimpleHit::~SimpleHit() { +} + +/// Extract the MC contribution for a given hit from the step information +SimpleHit::Contribution SimpleHit::extractContribution(G4Step* step) { + G4Track* trk = step->GetTrack(); + double energy_deposit = (trk->GetDefinition() == G4OpticalPhoton::OpticalPhotonDefinition()) + ? trk->GetTotalEnergy() : step->GetTotalEnergyDeposit(); + Contribution contrib(trk->GetTrackID(), + trk->GetDefinition()->GetPDGEncoding(), + energy_deposit, + trk->GetGlobalTime()); + return contrib; +} + +/// Default constructor +SimpleTracker::Hit::Hit() : SimpleHit(), position(), momentum(), length(0.0), truth() +{ + InstanceCount::increment(this); +} + +/// Standard initializing constructor +SimpleTracker::Hit::Hit(int track_id, int pdg_id, double deposit, double time_stamp) + : SimpleHit(), position(), momentum(), length(0.0), truth(track_id, pdg_id, deposit, time_stamp) +{ + InstanceCount::increment(this); +} + +/// Default destructor +SimpleTracker::Hit::~Hit() { + InstanceCount::decrement(this); +} + +/// Assignment operator +SimpleTracker::Hit& SimpleTracker::Hit::operator=(const Hit& c) { + position = c.position; + momentum = c.momentum; + length = c.length; + truth = c.truth; + return *this; +} + +/// Clear hit content +SimpleTracker::Hit& SimpleTracker::Hit::clear() { + position.SetXYZ(0,0,0); + momentum.SetXYZ(0,0,0); + length = 0.0; + truth.clear(); + return *this; +} + +/// Store Geant4 point and step information into tracker hit structure. +SimpleTracker::Hit& SimpleTracker::Hit::storePoint(G4Step* step, G4StepPoint* pnt) { + G4Track* trk = step->GetTrack(); + G4ThreeVector pos = pnt->GetPosition(); + G4ThreeVector mom = pnt->GetMomentum(); + + truth.trackID = trk->GetTrackID(); + truth.pdgID = trk->GetDefinition()->GetPDGEncoding(); + truth.deposit = step->GetTotalEnergyDeposit(); + truth.time = trk->GetGlobalTime(); + position.SetXYZ(pos.x(),pos.y(),pos.z()); + momentum.SetXYZ(mom.x(),mom.y(),mom.z()); + length = 0; + return *this; +} + +/// Standard constructor +SimpleCalorimeter::Hit::Hit(const Position& pos) + : SimpleHit(), position(pos), truth(), energyDeposit(0) +{ + InstanceCount::increment(this); +} + +/// Default destructor +SimpleCalorimeter::Hit::~Hit() { + InstanceCount::decrement(this); +} diff --git a/DDG4/src/Geant4EventAction.cpp b/DDG4/src/Geant4EventAction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3579bf25a8395591ba8d19e9da41a1b6a0870359 --- /dev/null +++ b/DDG4/src/Geant4EventAction.cpp @@ -0,0 +1,74 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4EventAction.h" +// C/C++ include files +#include <stdexcept> + +using namespace DD4hep::Simulation; + +/// Standard constructor +Geant4EventAction::Geant4EventAction(Geant4Context* context, const std::string& nam) +: Geant4Action(context,nam) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4EventAction::~Geant4EventAction() { + InstanceCount::decrement(this); +} + +/// begin-of-event callback +void Geant4EventAction::begin(const G4Event* ) { +} + +/// End-of-event callback +void Geant4EventAction::end(const G4Event* ) { +} + +/// Standard constructor +Geant4EventActionSequence::Geant4EventActionSequence(Geant4Context* context, const std::string& name) +: Geant4Action(context,name) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4EventActionSequence::~Geant4EventActionSequence() { + m_actors(&Geant4Action::release); + m_actors.clear(); + m_begin.clear(); + m_end.clear(); + InstanceCount::decrement(this); +} + +/// Add an actor responding to all callbacks. Sequence takes ownership. +void Geant4EventActionSequence::adopt(Geant4EventAction* action) { + if ( action ) { + action->addRef(); + m_actors.add(action); + return; + } + throw std::runtime_error("Geant4EventActionSequence: Attempt to add invalid actor!"); +} + +/// Pre-track action callback +void Geant4EventActionSequence::begin(const G4Event* event) { + m_actors(&Geant4EventAction::begin,event); + m_begin(event); +} + +/// Post-track action callback +void Geant4EventActionSequence::end(const G4Event* event) { + m_end(event); + m_actors(&Geant4EventAction::end,event); +} diff --git a/DDG4/src/Geant4Exec.cpp b/DDG4/src/Geant4Exec.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae9ac3edd7ee0df1114a9dbec04c9485a0a0d12c --- /dev/null +++ b/DDG4/src/Geant4Exec.cpp @@ -0,0 +1,412 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#include "DD4hep/Printout.h" +#include "DD4hep/Primitives.h" +#include "DD4hep/InstanceCount.h" + +#include "G4UserRunAction.hh" +#include "G4UserEventAction.hh" +#include "G4UserTrackingAction.hh" +#include "G4UserStackingAction.hh" +#include "G4UserSteppingAction.hh" +#include "G4UserReactionAction.hh" +#include "G4VUserPhysicsList.hh" +#include "G4VModularPhysicsList.hh" +#include "G4VUserPrimaryGeneratorAction.hh" +#include "G4VSensitiveDetector.hh" + +#include "DD4hep/Handle.h" +#include "DDG4/Geant4RunAction.h" +#include "DDG4/Geant4EventAction.h" +#include "DDG4/Geant4SteppingAction.h" +#include "DDG4/Geant4TrackingAction.h" +#include "DDG4/Geant4StackingAction.h" +#include "DDG4/Geant4GeneratorAction.h" +#include "DDG4/Geant4PhysicsList.h" +#include "DDG4/Geant4SensDetAction.h" +#include "DDG4/Geant4HitCollection.h" +#include "DDG4/Geant4Kernel.h" + +#include <memory> +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + template <typename T> struct _Seq { + typedef _Seq<T> Base; + T* m_sequence; + _Seq() : m_sequence(0) { } + _Seq(T* seq) { _aquire(seq); } + virtual ~_Seq() { _release(); } + void _aquire(T* s) { + InstanceCount::increment(this); + m_sequence = s; + m_sequence->addRef(); + } + void _release() { + releasePtr(m_sequence); + InstanceCount::decrement(this); + } + }; + + /** @class Geant4UserRunAction + * + * Concrete implementation of the Geant4 run action + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4UserRunAction : public G4UserRunAction, public _Seq<Geant4RunActionSequence> { + /// Standard constructor + Geant4UserRunAction(Geant4RunActionSequence* seq) : Base(seq) { } + /// Default destructor + virtual ~Geant4UserRunAction() { } + /// begin-of-run callback + virtual void BeginOfRunAction(const G4Run* run) { m_sequence->begin(run); } + /// End-of-run callback + virtual void EndOfRunAction(const G4Run* run) { m_sequence->end(run); } + }; + + /** @class Geant4UserEventAction + * + * Concrete implementation of the Geant4 event action + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4UserEventAction : public G4UserEventAction, public _Seq<Geant4EventActionSequence> { + /// Standard constructor + Geant4UserEventAction(Geant4EventActionSequence* seq) : Base(seq) { } + /// Default destructor + virtual ~Geant4UserEventAction() { } + /// begin-of-event callback + virtual void BeginOfEventAction(const G4Event* evt) { m_sequence->begin(evt); } + /// End-of-event callback + virtual void EndOfEventAction(const G4Event* evt) { m_sequence->end(evt); } + }; + + /** @class Geant4UserTrackingAction + * + * Concrete implementation of the Geant4 tracking action + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4UserTrackingAction : public G4UserTrackingAction, public _Seq<Geant4TrackingActionSequence> { + /// Standard constructor + Geant4UserTrackingAction(Geant4TrackingActionSequence* seq) : Base(seq) { } + /// Default destructor + virtual ~Geant4UserTrackingAction() { } + /// Pre-track action callback + virtual void PreUserTrackingAction(const G4Track* trk) { m_sequence->begin(trk); } + /// Post-track action callback + virtual void PostUserTrackingAction(const G4Track* trk) { m_sequence->end(trk); } + }; + + /** @class Geant4UserStackingAction + * + * Concrete implementation of the Geant4 stacking action sequence + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4UserStackingAction : public G4UserStackingAction, public _Seq<Geant4StackingActionSequence> { + /// Standard constructor + Geant4UserStackingAction(Geant4StackingActionSequence* seq) : Base(seq) { } + /// Default destructor + virtual ~Geant4UserStackingAction() { } + /// New-stage callback + virtual void NewStage() { m_sequence->newStage(); } + /// Preparation callback + virtual void PrepareNewEvent() { m_sequence->prepare(); } + }; + + /** @class Geant4UserGeneratorAction + * + * Concrete implementation of the Geant4 generator action + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4UserGeneratorAction : public G4VUserPrimaryGeneratorAction, public _Seq<Geant4GeneratorActionSequence> { + /// Standard constructor + Geant4UserGeneratorAction(Geant4GeneratorActionSequence* seq) + : G4VUserPrimaryGeneratorAction(), Base(seq) { } + /// Default destructor + virtual ~Geant4UserGeneratorAction() { } + /// Generate primary particles + virtual void GeneratePrimaries(G4Event* event) { (*m_sequence)(event); } + }; + + /** @class Geant4UserSteppingAction + * + * Concrete implementation of the Geant4 stepping action + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4UserSteppingAction : public G4UserSteppingAction, public _Seq<Geant4SteppingActionSequence> { + /// Standard constructor + Geant4UserSteppingAction(Geant4SteppingActionSequence* seq) : Base(seq) { } + /// Default destructor + virtual ~Geant4UserSteppingAction() { } + /// User stepping callback + virtual void UserSteppingAction(const G4Step* s) { (*m_sequence)(s,fpSteppingManager); } + }; + + /** @class Geant4UserPhysicsList + * + * Concrete implementation of the Geant4 user physics list + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4UserPhysicsList : virtual public G4VModularPhysicsList, + virtual public Geant4UserPhysics, + virtual public _Seq<Geant4PhysicsListActionSequence> + { + /// Standard constructor + Geant4UserPhysicsList(Geant4PhysicsListActionSequence* seq) + : G4VModularPhysicsList(), Geant4UserPhysics(), Base(seq) { } + /// Default destructor + virtual ~Geant4UserPhysicsList() { } + /// User construction callback + virtual void ConstructProcess() { m_sequence->constructProcess(this); } + /// User construction callback + virtual void ConstructParticle() { m_sequence->constructParticles(this); } + /// Enable transportation + virtual void AddTransportation() { this->G4VUserPhysicsList::AddTransportation(); } + // Register Physics Constructor + virtual void RegisterPhysics(G4VPhysicsConstructor* physics) + { this->G4VModularPhysicsList::RegisterPhysics(physics); } + }; + + struct Geant4SensDet : virtual public G4VSensitiveDetector, + virtual public G4VSDFilter, + virtual public Geant4ActionSD, + virtual public _Seq<Geant4SensDetActionSequence> + { + /// Constructor. The detector element is identified by the name + Geant4SensDet(const std::string& nam, Geometry::LCDD& lcdd) + : G4VSensitiveDetector(nam), G4VSDFilter(nam), + Geant4Action(0,nam), Geant4ActionSD(nam), Base() + { + Geant4Kernel& kernel = Geant4Kernel::access(lcdd); + setContext(kernel.context()); + _aquire(kernel.sensitiveAction(nam)); + m_sequence->defineCollections(this); + this->G4VSensitiveDetector::SetFilter(this); + } + + /// Destructor + virtual ~Geant4SensDet() { } + /// Overload to avoid ambiguity between G4VSensitiveDetector and G4VSDFilter + inline G4String GetName() const + { return this->G4VSensitiveDetector::SensitiveDetectorName; } + /// G4VSensitiveDetector internals: Access to the detector path name + virtual std::string path() const + { return this->G4VSensitiveDetector::GetPathName(); } + /// G4VSensitiveDetector internals: Access to the detector path name + virtual std::string fullPath() const + { return this->G4VSensitiveDetector::GetFullPathName(); } + /// Is the detector active? + virtual bool isActive() const + { return this->G4VSensitiveDetector::isActive(); } + /// This is a utility method which returns the hits collection ID + virtual G4int GetCollectionID(G4int i) + { return this->G4VSensitiveDetector::GetCollectionID(i); } + /// Access to the readout geometry of the sensitive detector + virtual G4VReadOutGeometry* readoutGeometry() const + { return this->G4VSensitiveDetector::GetROgeometry(); } + /// Callback if the sequence should be accepted or filtered off + virtual G4bool Accept(const G4Step* step) const + { return m_sequence->accept(step); } + /// Method invoked at the begining of each event. + virtual void Initialize(G4HCofThisEvent* hce) + { m_sequence->begin(hce); } + /// Method invoked at the end of each event. + virtual void EndOfEvent(G4HCofThisEvent* hce) + { m_sequence->end(hce); } + /// Method for generating hit(s) using the information of G4Step object. + virtual G4bool ProcessHits(G4Step* step,G4TouchableHistory* hist) + { return m_sequence->process(step,hist); } + /// G4VSensitiveDetector interface: Method invoked if the event was aborted. + virtual void clear() + { m_sequence->clear(); } + /// Initialize the usage of a hit collection. Returns the collection identifier + virtual size_t defineCollection(const std::string& coll) { + if ( coll.empty() ) { + except("Geant4Sensitive: No collection defined for %s [Invalid name]",c_name()); + } + collectionName.push_back(coll); + return collectionName.size()-1; + } + + }; + } // End namespace Simulation +} // End namespace DD4hep + + +#include "DDG4/Factories.h" + +typedef DD4hep::Simulation::Geant4SensDet Geant4SensDet; +typedef DD4hep::Simulation::Geant4SensDet Geant4tracker; +typedef DD4hep::Simulation::Geant4SensDet Geant4calorimeter; + +DECLARE_GEANT4SENSITIVEDETECTOR(Geant4SensDet) +DECLARE_GEANT4SENSITIVEDETECTOR(Geant4tracker) +DECLARE_GEANT4SENSITIVEDETECTOR(Geant4calorimeter) + + +#include "DD4hep/LCDD.h" +#include "DDG4/Geant4DetectorConstruction.h" + +#include "QGSP_BERT.hh" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Simulation; + +// Geant4 include files +#include "G4RunManager.hh" + +//-- +#define G4VIS_USE_OPENGL +#include "G4UImanager.hh" +#include "G4UIsession.hh" +#ifdef G4VIS_USE_OPENGLX +#include "G4OpenGLImmediateX.hh" +#include "G4OpenGLStoredX.hh" +#endif +#include "G4VisManager.hh" +#include "G4VisExecutive.hh" +#include "G4UIExecutive.hh" + + +/// Configure the simulation +int Geant4Exec::configure(Geant4Kernel& kernel) { + CLHEP::HepRandom::setTheEngine(new CLHEP::RanecuEngine); + Geometry::LCDD& lcdd = kernel.lcdd(); + + // Construct the default run manager + G4RunManager& runManager = kernel.runManager(); + + // Check if the geometry was loaded + if ( lcdd.detectors().size() <= 2 ) { + cout << "Error, no geometry." << endl; + } + // Get the detector constructed + Geant4DetectorConstruction* detector = new Geant4DetectorConstruction(lcdd); + + runManager.SetUserInitialization(detector); + G4VUserPhysicsList* physics = 0; + if ( kernel.physicsList(false) ) + physics = new Geant4UserPhysicsList(kernel.physicsList(false)); + else { + printout(INFO,"Geant4Exec","+++ Using Geant4 physics constructor QGSP_BERT"); + physics = new QGSP_BERT(); // physics from N04 + } + runManager.SetUserInitialization(physics); + + // Set user generator action sequence + if ( kernel.generatorAction(false) ) { + Geant4UserGeneratorAction* action = new Geant4UserGeneratorAction(kernel.generatorAction(false)); + runManager.SetUserAction(action); + } + // Set the run action sequence + if ( kernel.runAction(false) ) { + Geant4UserRunAction* action = new Geant4UserRunAction(kernel.runAction(false)); + runManager.SetUserAction(action); + } + // Set the event action sequence + if ( kernel.eventAction(false) ) { + Geant4UserEventAction* action = new Geant4UserEventAction(kernel.eventAction(false)); + runManager.SetUserAction(action); + } + // Set the stepping action sequence + if ( kernel.steppingAction(false) ) { + Geant4UserSteppingAction* action = new Geant4UserSteppingAction(kernel.steppingAction(false)); + runManager.SetUserAction(action); + } + // Set the stacking action sequence + if ( kernel.stackingAction(false) ) { + Geant4UserStackingAction* action = new Geant4UserStackingAction(kernel.stackingAction(false)); + runManager.SetUserAction(action); + } + return 1; +} + +/// Initialize the simulation +int Geant4Exec::initialize(Geant4Kernel& kernel) { + // Construct the default run manager + G4RunManager& runManager = kernel.runManager(); + // + // Initialize G4 engine + // + runManager.Initialize(); + return 1; +} + +/// Run the simulation +int Geant4Exec::run(Geant4Kernel& ) { + bool is_visual = false; + string gui_setup, vis_setup, gui_type="tcsh"; + + // Initialize visualization + G4VisManager* visManager = 0; + if ( is_visual ) { + visManager = new G4VisExecutive(); +#ifdef G4VIS_USE_OPENGLX + //visManager->RegisterGraphicsSystem (new G4OpenGLImmediateX()); + //visManager->RegisterGraphicsSystem (new G4OpenGLStoredX()); +#endif + visManager->Initialize(); + } + + // Get the pointer to the User Interface manager + G4UImanager* UImanager = G4UImanager::GetUIpointer(); + G4String command = "/control/execute run.mac"; + cout << "++++++++++++++++++++++++++++ executing command:" << command << endl; + UImanager->ApplyCommand(command); + + G4UIExecutive* ui = 0; + if ( !gui_type.empty() ) { // interactive mode : define UI session + const char* args[] = {"cmd"}; + ui = new G4UIExecutive(1,(char**)args);//,gui_type); + if ( is_visual && !vis_setup.empty() ) { + UImanager->ApplyCommand("/control/execute vis.mac"); + cout << "++++++++++++++++++++++++++++ executed vis.mac" << endl; + } + if (ui->IsGUI()) { + if ( !gui_setup.empty() ) { + UImanager->ApplyCommand("/control/execute "+gui_setup); + cout << "++++++++++++++++++++++++++++ executed gui.mac" << endl; + } + } + ui->SessionStart(); + delete ui; + } + // Job termination + // Free the store: user actions, physics_list and detector_description are + // owned and deleted by the run manager, so they should not + // be deleted in the main() program ! + if ( visManager ) delete visManager; + return 1; +} + +/// Run the simulation +int Geant4Exec::terminate(Geant4Kernel& ) { + return 1; +} diff --git a/DDG4/src/Geant4Factories.cpp b/DDG4/src/Geant4Factories.cpp new file mode 100644 index 0000000000000000000000000000000000000000..77aa3fe0256ad713da0bfa8033fd31e772569f59 --- /dev/null +++ b/DDG4/src/Geant4Factories.cpp @@ -0,0 +1,42 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#include "DDG4/Factories.h" +using namespace DD4hep::Simulation; + +#include "DDG4/Geant4RunAction.h" +DECLARE_GEANT4ACTION(Geant4RunActionSequence) + +#include "DDG4/Geant4EventAction.h" +DECLARE_GEANT4ACTION(Geant4EventActionSequence) + +#include "DDG4/Geant4SteppingAction.h" +DECLARE_GEANT4ACTION(Geant4SteppingActionSequence) + +#include "DDG4/Geant4TrackingAction.h" +DECLARE_GEANT4ACTION(Geant4TrackingActionSequence) + +#include "DDG4/Geant4StackingAction.h" +DECLARE_GEANT4ACTION(Geant4StackingActionSequence) + +#include "DDG4/Geant4GeneratorAction.h" +DECLARE_GEANT4ACTION(Geant4GeneratorActionSequence) + +#include "DDG4/Geant4PhysicsList.h" +DECLARE_GEANT4ACTION(Geant4PhysicsList) +DECLARE_GEANT4ACTION(Geant4PhysicsListActionSequence) + +#include "DDG4/Geant4SensDetAction.h" +DECLARE_GEANT4ACTION(Geant4SensDetActionSequence) + +//============================= +#include "DDG4/Geant4TrackingPreAction.h" +DECLARE_GEANT4ACTION(Geant4TrackingPreAction) + +#include "DDG4/Geant4TrackingPostAction.h" +DECLARE_GEANT4ACTION(Geant4TrackingPostAction) diff --git a/DDG4/src/Geant4Field.cpp b/DDG4/src/Geant4Field.cpp index ddc3cd52352aa21a8955745655ce230a1d93d577..7c82916716aa8ebb8ba26a87fc10cc3671c53883 100644 --- a/DDG4/src/Geant4Field.cpp +++ b/DDG4/src/Geant4Field.cpp @@ -19,6 +19,7 @@ G4bool Geant4Field::DoesFieldChangeEnergy() const { } void Geant4Field::GetFieldValue(const double pos[4], double *field) const { + field[0] = field[1] = field[2] = 0.0; return m_field.magneticField(pos,field); } diff --git a/DDG4/src/Geant4GDMLDetector.cpp b/DDG4/src/Geant4GDMLDetector.cpp index b8a4e337527f857399ce2a040ea3a255d174a54c..535e25e1a11f483ce3d92697f2aa075d4dbe2ce0 100644 --- a/DDG4/src/Geant4GDMLDetector.cpp +++ b/DDG4/src/Geant4GDMLDetector.cpp @@ -1,7 +1,7 @@ #include "DDG4/Geant4GDMLDetector.h" #include <iostream> -#define GEANT4_HAS_GDML +//#define GEANT4_HAS_GDML #ifdef GEANT4_HAS_GDML #include "G4GDMLParser.hh" @@ -10,20 +10,16 @@ using namespace std; using namespace DD4hep; - -DD4hep::Simulation::Geant4GDMLDetector::Geant4GDMLDetector(const std::string& gdmlFile ) : m_fileName( gdmlFile) , m_world(0) { } - +DD4hep::Simulation::Geant4GDMLDetector::Geant4GDMLDetector(const std::string& gdmlFile ) +: m_fileName(gdmlFile), m_world(0) +{ +} G4VPhysicalVolume* DD4hep::Simulation::Geant4GDMLDetector::Construct() { - #ifdef GEANT4_HAS_GDML - G4GDMLParser parser; - parser.Read( m_fileName ); - m_world = parser.GetWorldVolume(); - #endif return m_world; } diff --git a/DDG4/src/Geant4GeneratorAction.cpp b/DDG4/src/Geant4GeneratorAction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13c3b2856feaa45443c883d9dff0b0ee0635beb0 --- /dev/null +++ b/DDG4/src/Geant4GeneratorAction.cpp @@ -0,0 +1,59 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4GeneratorAction.h" +// C/C++ include files +#include <stdexcept> + +using namespace DD4hep::Simulation; + +/// Standard constructor +Geant4GeneratorAction::Geant4GeneratorAction(Geant4Context* context, const std::string& name) +: Geant4Action(context,name) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4GeneratorAction::~Geant4GeneratorAction() { + InstanceCount::decrement(this); +} + +/// Standard constructor +Geant4GeneratorActionSequence::Geant4GeneratorActionSequence(Geant4Context* context, const std::string& name) +: Geant4Action(context,name) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4GeneratorActionSequence::~Geant4GeneratorActionSequence() { + m_actors(&Geant4GeneratorAction::release); + m_actors.clear(); + m_calls.clear(); + InstanceCount::decrement(this); +} + +/// Add an actor responding to all callbacks. Sequence takes ownership. +void Geant4GeneratorActionSequence::adopt(Geant4GeneratorAction* action) { + if ( action ) { + action->addRef(); + m_actors.add(action); + return; + } + throw std::runtime_error("Geant4GeneratorActionSequence: Attempt to add invalid actor!"); +} + +/// Generator callback +void Geant4GeneratorActionSequence::operator()(G4Event* event) { + m_actors(&Geant4GeneratorAction::operator(),event); + m_calls(event); +} diff --git a/DDG4/src/Geant4Handle.cpp b/DDG4/src/Geant4Handle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..862da65305ccc687add3383b36dc755df184f326 --- /dev/null +++ b/DDG4/src/Geant4Handle.cpp @@ -0,0 +1,184 @@ +// $Id: Geant4Setup.cpp 796 2013-10-03 19:19:39Z markus.frank@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/LCDD.h" +#include "DD4hep/Plugins.h" +#include "DD4hep/Printout.h" + +#include "DDG4/Geant4Handle.h" +#include "DDG4/Geant4Kernel.h" +#include "DDG4/Geant4GeneratorAction.h" +#include "DDG4/Geant4RunAction.h" +#include "DDG4/Geant4EventAction.h" +#include "DDG4/Geant4TrackingAction.h" +#include "DDG4/Geant4SteppingAction.h" +#include "DDG4/Geant4StackingAction.h" +#include "DDG4/Geant4SensDetAction.h" +#include "DDG4/Geant4PhysicsList.h" +#include "DDG4/Geant4ActionPhase.h" + + +// C/C++ include files +#include <stdexcept> + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Simulation; + +template <typename TYPE> static inline TYPE* checked_value(TYPE* p) { + if ( p ) { + return p; + } + throw runtime_error(format("Geant4Handle","Attempt to access an invalid object of type:%s!", + typeinfoName(typeid(TYPE)).c_str())); +} + +template <typename TYPE> Geant4Handle<TYPE>::Geant4Handle() : value(0) +{ +} + +template <typename TYPE> Geant4Handle<TYPE>::Geant4Handle(TYPE* typ) : value(typ) +{ + if ( value ) value->addRef(); +} + +template <typename TYPE> Geant4Handle<TYPE>::Geant4Handle(Geant4Handle<TYPE>& handle) +: value(0) +{ + value = handle.get(); + if ( value ) value->addRef(); +} + +template <typename TYPE> Geant4Handle<TYPE>::Geant4Handle(const Geant4Kernel& kernel,const string& type_name) +: value(0) +{ + TypeName typ = TypeName::split(type_name); + Geant4Context* ctxt = kernel.context(); + Geant4Action* object = PluginService::Create<Geant4Action*>(typ.first,ctxt,typ.second); + if ( !object && typ.first == typ.second ) { + typ.first = typeinfoName(typeid(TYPE)); + printout(DEBUG,"Geant4Handle<Geant4Sensitive>", + "Object factory for %s not found. Try out %s", + typ.second.c_str(),typ.first.c_str()); + object = PluginService::Create<Geant4Action*>(typ.first,ctxt,typ.second); + if ( !object ) { + size_t idx = typ.first.rfind(':'); + if ( idx != string::npos ) typ.first = string(typ.first.substr(idx+1)); + printout(DEBUG,"Geant4Handle<Geant4Sensitive>", + "Try out object factory for %s",typ.first.c_str()); + object = PluginService::Create<Geant4Action*>(typ.first,ctxt,typ.second); + } + } + if ( object ) { + TYPE* ptr = dynamic_cast<TYPE*>(object); + if ( ptr ) { + value = ptr; + return; + } + throw runtime_error(format("Geant4Handle", + "Failed to convert object of type %s to handle of type %s!", + type_name.c_str(),typeinfoName(typeid(TYPE)).c_str())); + } + throw runtime_error(format("Geant4Handle","Failed to create object of type %s!",type_name.c_str())); +} + +template <typename TYPE> Geant4Handle<TYPE>::~Geant4Handle() { + if ( value ) value->release(); + value = 0; +} + +template <typename TYPE> void Geant4Handle<TYPE>::checked_assign(TYPE* p) { + if ( value ) value->release(); + value = checked_value(p); + if ( value ) value->addRef(); +} + +template <typename TYPE> Property& Geant4Handle<TYPE>::operator[](const string& property_name) const { + PropertyManager& pm = checked_value(value)->properties(); + return pm[property_name]; +} + +template <typename TYPE> Geant4Handle<TYPE>::operator TYPE*() const { + return checked_value(value); +} + +template <typename TYPE> bool Geant4Handle<TYPE>::operator!() const { + return 0 == value; +} + +template <typename TYPE> TYPE* Geant4Handle<TYPE>::get() const { + return checked_value(value); +} + +template <typename TYPE> TYPE* Geant4Handle<TYPE>::operator->() const { + return checked_value(value); +} + +template <typename TYPE> Geant4Handle<TYPE>& Geant4Handle<TYPE>::operator=(Geant4Handle& handle) { + if ( value ) value->release(); + value = handle.get(); + if ( value ) value->addRef(); + return *this; +} + +template <typename TYPE> Geant4Handle<TYPE>& Geant4Handle<TYPE>::operator=(TYPE* typ) { + if ( value ) value->release(); + value = typ; + if ( value ) value->addRef(); + return *this; +} + +namespace DD4hep { namespace Simulation { + + template <> Geant4Handle<Geant4Sensitive>::Geant4Handle(const Geant4Kernel& kernel, const string& type_name, const string& detector) { + try { + Geant4Context* ctxt = kernel.context(); + TypeName typ = TypeName::split(type_name); + Geometry::LCDD& lcdd = kernel.lcdd(); + Geometry::DetElement det = lcdd.detector(detector); + Geant4Sensitive* object = PluginService::Create<Geant4Sensitive*>(typ.first,ctxt,typ.second,&det,&lcdd); + if ( object ) { + value = object; + return; + } + } + catch(const exception& e) { + printout(ERROR,"Geant4Handle<Geant4Sensitive>","Exception: %s",e.what()); + } + catch(...) { + printout(ERROR,"Geant4Handle<Geant4Sensitive>","Exception: Unknown exception"); + } + throw runtime_error(format("Geant4Handle<Geant4Sensitive>", + "Failed to create sensitive object of type %s for detector %s!", + type_name.c_str(),detector.c_str())); + } + } +} + +template class Geant4Handle<Geant4Action>; +template class Geant4Handle<Geant4Filter>; +template class Geant4Handle<Geant4Sensitive>; +template class Geant4Handle<Geant4ActionPhase>; +template class Geant4Handle<Geant4GeneratorAction>; +template class Geant4Handle<Geant4RunAction>; +template class Geant4Handle<Geant4EventAction>; +template class Geant4Handle<Geant4TrackingAction>; +template class Geant4Handle<Geant4SteppingAction>; +template class Geant4Handle<Geant4StackingAction>; +template class Geant4Handle<Geant4PhysicsList>; + +template class Geant4Handle<Geant4GeneratorActionSequence>; +template class Geant4Handle<Geant4PhysicsListActionSequence>; +template class Geant4Handle<Geant4RunActionSequence>; +template class Geant4Handle<Geant4EventActionSequence>; +template class Geant4Handle<Geant4TrackingActionSequence>; +template class Geant4Handle<Geant4SteppingActionSequence>; +template class Geant4Handle<Geant4StackingActionSequence>; +template class Geant4Handle<Geant4SensDetActionSequence>; diff --git a/DDG4/src/Geant4HitCollection.cpp b/DDG4/src/Geant4HitCollection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cacc1471c4637538b3902863e5481bb395eea032 --- /dev/null +++ b/DDG4/src/Geant4HitCollection.cpp @@ -0,0 +1,86 @@ +// $Id: Geant4Mapping.cpp 588 2013-06-03 11:41:35Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4HitCollection.h" +#include "DDG4/ComponentUtils.h" +#include "G4Allocator.hh" + +using namespace DD4hep::Simulation; + +static G4Allocator<Geant4HitWrapper> HitWrapperAllocator; + +Geant4HitWrapper::InvalidHit::~InvalidHit() { +} + +Geant4HitWrapper::HitManipulator::HitManipulator(const std::type_info& t, destroy_t d, cast_t c) : type(t), destroy(d), cast(c) +{ +} + +void Geant4HitWrapper::HitManipulator::checkHitType(const std::type_info& test_type) const { + if ( test_type != type ) { + throw unrelated_type_error(test_type,type, + "This hit cannot be passed to this hit collection!"); + } +} + +/// Default destructor +Geant4HitWrapper::~Geant4HitWrapper() { + if ( m_data.first && m_data.second ) { + (m_data.second->destroy)(m_data); + } +} + + +/// Geant4 required object allocator +void* Geant4HitWrapper::operator new(size_t) { + return HitWrapperAllocator.MallocSingle(); +} + +/// Geat4 required object destroyer +void Geant4HitWrapper::operator delete(void *p) { + HitWrapperAllocator.FreeSingle((Geant4HitWrapper*)p); +} + +/// Pointer/Object release +void* Geant4HitWrapper::release() { + void* p = m_data.first; + m_data.first = 0; + m_data.second = manipulator<InvalidHit>(); + return p; +} + +/// Pointer/Object release +Geant4HitWrapper::Wrapper Geant4HitWrapper::releaseData() { + Wrapper w = m_data; + m_data.first = 0; + m_data.second = manipulator<InvalidHit>(); + return w; +} + +/// Default destructor +Geant4HitCollection::~Geant4HitCollection() { + m_hits.clear(); + InstanceCount::decrement(this); +} + +/// Notification to increase the instance counter +void Geant4HitCollection::newInstance() { + InstanceCount::increment(this); +} + +/// Find hit in a collection by comparison of attributes +void* Geant4HitCollection::findHit(const Compare& cmp) const { + void* p = 0; + for(WrappedHits::const_iterator i=m_hits.begin(); i !=m_hits.end(); ++i) + if ( (p=cmp(*i)) !=0 ) return p; + return p; +} + diff --git a/DDG4/src/Geant4Kernel.cpp b/DDG4/src/Geant4Kernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7200c8d73e4b57ba4aae1a1d2dfc8290c30affb --- /dev/null +++ b/DDG4/src/Geant4Kernel.cpp @@ -0,0 +1,339 @@ +// $Id: Geant4Kernel.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/LCDD.h" +#include "DD4hep/Printout.h" +#include "DD4hep/Primitives.h" +#include "DD4hep/InstanceCount.h" + +#include "DDG4/Geant4Kernel.h" +#include "DDG4/Geant4ActionPhase.h" + +#include "DDG4/Geant4RunAction.h" +#include "DDG4/Geant4PhysicsList.h" +#include "DDG4/Geant4EventAction.h" +#include "DDG4/Geant4SteppingAction.h" +#include "DDG4/Geant4TrackingAction.h" +#include "DDG4/Geant4StackingAction.h" +#include "DDG4/Geant4GeneratorAction.h" +#include "DDG4/Geant4SensDetAction.h" +#include "DDG4/Geant4DetectorConstruction.h" + +#include "G4RunManager.hh" + +// C/C++ include files +#include <stdexcept> +#include <algorithm> + +using namespace std; +using namespace DD4hep::Simulation; + + +/// Standard constructor +Geant4Kernel::PhaseSelector::PhaseSelector(Geant4Kernel* kernel) : m_kernel(kernel) { +} + +/// Copy constructor +Geant4Kernel::PhaseSelector::PhaseSelector(const PhaseSelector& c) : m_kernel(c.m_kernel) { +} + +/// Phase access to the map +Geant4ActionPhase& Geant4Kernel::PhaseSelector::operator[](const std::string& name) const { + Geant4ActionPhase* phase = m_kernel->getPhase(name); + if ( phase ) { + return *phase; + } + throw runtime_error(format("Geant4Kernel","Attempt to access the nonexisting phase '%s'",name.c_str())); +} + +/// Standard constructor +Geant4Kernel::Geant4Kernel(LCDD& lcdd) +: m_context(0), m_runManager(0), m_generatorAction(0), m_runAction(0), m_eventAction(0), + m_trackingAction(0), m_steppingAction(0), m_stackingAction(0), m_sensDetActions(0), + m_physicsList(0), m_lcdd(lcdd), phase(this) +{ +#if 0 + registerSequence(m_runAction, "RunAction"); + registerSequence(m_eventAction, "EventAction"); + registerSequence(m_steppingAction, "SteppingAction"); + registerSequence(m_trackingAction, "TrackingAction"); + registerSequence(m_stackingAction, "StackingAction"); + registerSequence(m_generatorAction,"GeneratorAction"); +#endif + m_sensDetActions = new Geant4SensDetSequences(); + m_context = new Geant4Context(this); + m_lcdd.addExtension<Geant4Kernel>(this); + InstanceCount::increment(this); +} + +/// Default destructor +Geant4Kernel::~Geant4Kernel() { + destroyPhases(); + for_each(m_globalFilters.begin(),m_globalFilters.end(),releaseObjects(m_globalFilters)); + for_each(m_globalActions.begin(),m_globalActions.end(),releaseObjects(m_globalActions)); + deletePtr(m_runManager); + releasePtr(m_physicsList); + releasePtr(m_stackingAction); + releasePtr(m_steppingAction); + releasePtr(m_trackingAction); + releasePtr(m_eventAction); + releasePtr(m_generatorAction); + releasePtr(m_runAction); + deletePtr(m_sensDetActions); + deletePtr(m_context); + m_lcdd.destroyInstance(); + InstanceCount::decrement(this); +} + +/// Instance accessor +Geant4Kernel& Geant4Kernel::instance(LCDD& lcdd) { + static Geant4Kernel obj(lcdd); + return obj; +} + +/// Accessof the Geant4Kernel object from the LCDD reference extension (if present and registered) +Geant4Kernel& Geant4Kernel::access(LCDD& lcdd) { + Geant4Kernel* kernel = lcdd.extension<Geant4Kernel>(); + if ( !kernel ) { + throw runtime_error(format("Geant4Kernel","DDG4: The LCDD object has no registered " + "extension of type Geant4Kernel [No-Extension]")); + } + return *kernel; +} + +/// Access to the Geant4 run manager +G4RunManager& Geant4Kernel::runManager() { + if ( m_runManager ) return *m_runManager; + return *(m_runManager = new G4RunManager); +} + +/// Construct detector geometry using lcdd plugin +void Geant4Kernel::loadGeometry(const std::string& compact_file) { + char* arg = (char*)compact_file.c_str(); + m_lcdd.apply("DD4hepXMLLoader",1,&arg); + //return *this; +} + +// Utility function to load XML files +void Geant4Kernel::loadXML(const char* fname) { + const char* args[] = {fname,0}; + m_lcdd.apply("DD4hepXMLLoader",1,(char**)args); + //return *this; +} + +void Geant4Kernel::configure() { + Geant4Exec::configure(*this); + //return *this; +} + +void Geant4Kernel::initialize() { + Geant4Exec::initialize(*this); + //return *this; +} + +void Geant4Kernel::run() { + Geant4Exec::run(*this); + //return *this; +} + +void Geant4Kernel::terminate() { + Geant4Exec::terminate(*this); + destroyPhases(); + for_each(m_globalFilters.begin(),m_globalFilters.end(),releaseObjects(m_globalFilters)); + for_each(m_globalActions.begin(),m_globalActions.end(),releaseObjects(m_globalActions)); + deletePtr(m_runManager); + releasePtr(m_physicsList); + releasePtr(m_stackingAction); + releasePtr(m_steppingAction); + releasePtr(m_trackingAction); + releasePtr(m_eventAction); + releasePtr(m_generatorAction); + releasePtr(m_runAction); + deletePtr(m_sensDetActions); + deletePtr(m_context); + //return *this; +} + + +template <class C> bool +Geant4Kernel::registerSequence(C*& seq,const std::string& name) { + if ( !name.empty() ) { + seq = new C(m_context,name); + return true; + } + throw runtime_error(format("Geant4Kernel","DDG4: The action '%s' not found. [Action-NotFound]",name.c_str())); +} + +/// Register action by name to be retrieved when setting up and connecting action objects +/** Note: registered actions MUST be unique. + * However, not all actions need to registered.... + * Only register those, you later need to retrieve by name. + */ +Geant4Kernel& Geant4Kernel::registerGlobalAction(Geant4Action* action) { + if ( action ) { + string nam = action->name(); + GlobalActions::const_iterator i = m_globalActions.find(nam); + if ( i == m_globalActions.end() ) { + action->addRef(); + m_globalActions[nam] = action; + return *this; + } + throw runtime_error(format("Geant4Kernel","DDG4: The action '%s' is already globally " + "registered. [Action-Already-Registered]",nam.c_str())); + } + throw runtime_error(format("Geant4Kernel","DDG4: Attempt to globally register an invalid " + "action. [Action-Invalid]")); +} + +/// Retrieve action from repository +Geant4Action* Geant4Kernel::globalAction(const std::string& action_name, bool throw_if_not_present) { + GlobalActions::iterator i = m_globalActions.find(action_name); + if ( i == m_globalActions.end() ) { + if ( throw_if_not_present ) { + throw runtime_error(format("Geant4Kernel","DDG4: The action '%s' is not already globally " + "registered. [Action-Missing]",action_name.c_str())); + } + return 0; + } + return (*i).second; +} + +/// Register filter by name to be retrieved when setting up and connecting filter objects +/** Note: registered filters MUST be unique. + * However, not all filters need to registered.... + * Only register those, you later need to retrieve by name. + */ +Geant4Kernel& Geant4Kernel::registerGlobalFilter(Geant4Action* filter) { + if ( filter ) { + string nam = filter->name(); + GlobalActions::const_iterator i = m_globalFilters.find(nam); + if ( i == m_globalFilters.end() ) { + filter->addRef(); + m_globalFilters[nam] = filter; + return *this; + } + throw runtime_error(format("Geant4Kernel","DDG4: The filter '%s' is already globally " + "registered. [Filter-Already-Registered]",nam.c_str())); + } + throw runtime_error(format("Geant4Kernel","DDG4: Attempt to globally register an invalid " + "filter. [Filter-Invalid]")); +} + +/// Retrieve filter from repository +Geant4Action* Geant4Kernel::globalFilter(const std::string& filter_name, bool throw_if_not_present) { + GlobalActions::iterator i = m_globalFilters.find(filter_name); + if ( i == m_globalFilters.end() ) { + if ( throw_if_not_present ) { + throw runtime_error(format("Geant4Kernel","DDG4: The filter '%s' is not already globally " + "registered. [Filter-Missing]",filter_name.c_str())); + } + return 0; + } + return (*i).second; +} + +/// Access phase by name +Geant4ActionPhase* Geant4Kernel::getPhase(const std::string& nam) { + Phases::const_iterator i=m_phases.find(nam); + if ( i != m_phases.end() ) { + return (*i).second; + } + throw runtime_error(format("Geant4Kernel","DDG4: The Geant4 action phase '%s' " + "does not exist. [No-Entry]", nam.c_str())); +} + +/// Add a new phase +Geant4ActionPhase* Geant4Kernel::addPhase(const std::string& nam, const type_info& arg0, + const type_info& arg1, const type_info& arg2, bool throw_on_exist) { + Phases::const_iterator i = m_phases.find(nam); + if ( i == m_phases.end() ) { + Geant4ActionPhase* p = new Geant4ActionPhase(m_context,nam,arg0,arg1,arg2); + m_phases.insert(make_pair(nam,p)); + return p; + } + else if ( throw_on_exist ) { + throw runtime_error(format("Geant4Kernel","DDG4: The Geant4 action phase %s " + "already exists. [Already-Exists]", nam.c_str())); + } + return (*i).second; +} + +/// Remove an existing phase from the phase. If not existing returns false +bool Geant4Kernel::removePhase(const std::string& nam) { + Phases::iterator i=m_phases.find(nam); + if ( i != m_phases.end() ) { + delete (*i).second; + m_phases.erase(i); + return true; + } + return false; +} + +/// Destroy all phases. To be called only at shutdown +void Geant4Kernel::destroyPhases() { + for_each(m_phases.begin(),m_phases.end(),destroyObjects(m_phases)); +} + +/// Access generator action sequence +Geant4GeneratorActionSequence* Geant4Kernel::generatorAction(bool create) { + if ( !m_generatorAction && create ) registerSequence(m_generatorAction,"GeneratorAction"); + return m_generatorAction; +} + +/// Access run action sequence +Geant4RunActionSequence* Geant4Kernel::runAction(bool create) { + if ( !m_runAction && create ) registerSequence(m_runAction,"RunAction"); + return m_runAction; +} + +/// Access event action sequence +Geant4EventActionSequence* Geant4Kernel::eventAction(bool create) { + if ( !m_eventAction && create ) registerSequence(m_eventAction,"EventAction"); + return m_eventAction; +} + +/// Access stepping action sequence +Geant4SteppingActionSequence* Geant4Kernel::steppingAction(bool create) { + if ( !m_steppingAction && create ) registerSequence(m_steppingAction,"SteppingAction"); + return m_steppingAction; +} + +/// Access tracking action sequence +Geant4TrackingActionSequence* Geant4Kernel::trackingAction(bool create) { + if ( !m_trackingAction && create ) registerSequence(m_trackingAction,"TrackingAction"); + return m_trackingAction; +} + +/// Access stacking action sequence +Geant4StackingActionSequence* Geant4Kernel::stackingAction(bool create) { + if ( !m_stackingAction && create ) registerSequence(m_stackingAction,"StackingAction"); + return m_stackingAction; +} + +/// Access to the sensitive detector sequences from the kernel object +Geant4SensDetSequences& Geant4Kernel::sensitiveActions() const { + return *m_sensDetActions; +} + +/// Access to the sensitive detector action from the kernel object +Geant4SensDetActionSequence* Geant4Kernel::sensitiveAction(const string& nam) const { + Geant4SensDetActionSequence* ptr = m_sensDetActions->find(nam); + if ( ptr ) return ptr; + ptr = new Geant4SensDetActionSequence(context(),nam); + m_sensDetActions->insert(nam,ptr); + return ptr; +} + +/// Access to the physics list +Geant4PhysicsListActionSequence* Geant4Kernel::physicsList(bool create) { + if ( !m_physicsList && create ) registerSequence(m_physicsList,"PhysicsList"); + return m_physicsList; +} + diff --git a/DDG4/src/Geant4ParticleGun.cpp b/DDG4/src/Geant4ParticleGun.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f502c87065b7a42a2a84f3a6de0ae5e4be326477 --- /dev/null +++ b/DDG4/src/Geant4ParticleGun.cpp @@ -0,0 +1,125 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4PARTICLEGUN_H +#define DD4HEP_DDG4_GEANT4PARTICLEGUN_H + +// Framework include files +#include "DDG4/Geant4GeneratorAction.h" + +// Forward declarations +class G4ParticleDefinition; +class G4ParticleGun; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + /** @class Geant4ParticleGun Geant4ParticleGun.h DDG4/Geant4ParticleGun.h + * + * Implementation wrapper of the Geant4 particle gun + * + * @author M.Frank + * @version 1.0 + */ + class Geant4ParticleGun : public Geant4GeneratorAction { + protected: + /// Position and shooting direction of the gun + struct { double x,y,z; } m_position, m_direction; + /// Particle energy + double m_energy; + /// Desired multiplicity of the particles to be shot + int m_multiplicity; + /// Particle name + std::string m_particleName; + /// Pointer to geant4 particle definition + G4ParticleDefinition* m_particle; + /// Pointer to the particle gun itself + G4ParticleGun* m_gun; + public: + /// Standard constructor + Geant4ParticleGun(Geant4Context* context, const std::string& name); + /// Default destructor + virtual ~Geant4ParticleGun(); + /// Callback to generate primary particles + virtual void operator()(G4Event* event); + }; + } // End namespace Simulation +} // End namespace DD4hep +#endif /* DD4HEP_DDG4_GEANT4PARTICLEGUN_H */ + +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +//#include "DDG4/Geant4ParticleGun.h" +#include "DDG4/Factories.h" + +#include "G4ParticleGun.hh" +#include "G4ParticleTable.hh" +#include "G4ParticleDefinition.hh" + +// C/C++ include files +#include <stdexcept> + +using namespace DD4hep::Simulation; + +DECLARE_GEANT4ACTION(Geant4ParticleGun) + +/// Standard constructor +Geant4ParticleGun::Geant4ParticleGun(Geant4Context* context, const std::string& name) +: Geant4GeneratorAction(context,name), m_particle(0), m_gun(0) +{ + InstanceCount::increment(this); + declareProperty("energy", m_energy=50*MeV); + declareProperty("multiplicity", m_multiplicity=1); + declareProperty("pos_x", m_position.x = 0); + declareProperty("pos_y", m_position.y = 0); + declareProperty("pos_z", m_position.z = 0); + declareProperty("direction_x", m_direction.x = 1); + declareProperty("direction_y", m_direction.y = 1); + declareProperty("direction_z", m_direction.z = 0.3); + declareProperty("particle", m_particleName= "e-"); +} + +/// Default destructor +Geant4ParticleGun::~Geant4ParticleGun() { + if ( m_gun ) delete m_gun; + InstanceCount::decrement(this); +} + +/// Callback to generate primary particles +void Geant4ParticleGun::operator()(G4Event* event) { + if ( 0 == m_gun ) { + m_gun = new G4ParticleGun(m_multiplicity); + } + if ( 0 == m_particle || m_particle->GetParticleName() != m_particleName.c_str() ) { + G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable(); + m_particle = particleTable->FindParticle(m_particleName); + if ( 0 == m_particle ) { + throw std::runtime_error("Bad particle type!"); + } + } + m_gun->SetParticleDefinition(m_particle); + m_gun->SetParticleEnergy(m_energy); + m_gun->SetParticleMomentumDirection(G4ThreeVector(m_direction.x,m_direction.y,m_direction.z)); + m_gun->SetParticlePosition(G4ThreeVector(m_position.x,m_position.y,m_position.z)); + m_gun->GeneratePrimaryVertex(event); +} diff --git a/DDG4/src/Geant4Particles.cpp b/DDG4/src/Geant4Particles.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d352dffe3130cecbab5eec2aa01b0d4cb1a93a74 --- /dev/null +++ b/DDG4/src/Geant4Particles.cpp @@ -0,0 +1,276 @@ +// $Id: Factories.h 797 2013-10-03 19:20:32Z markus.frank@cern.ch $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DDG4/Factories.h" + +// ---- Adjoint particles +#include "G4AdjointAlpha.hh" +DECLARE_GEANT4_PARTICLE(G4AdjointAlpha) +#include "G4AdjointDeuteron.hh" +DECLARE_GEANT4_PARTICLE(G4AdjointDeuteron) +#include "G4AdjointElectron.hh" +DECLARE_GEANT4_PARTICLE(G4AdjointElectron) +#include "G4AdjointGamma.hh" +DECLARE_GEANT4_PARTICLE(G4AdjointGamma) +#include "G4AdjointHe3.hh" +DECLARE_GEANT4_PARTICLE(G4AdjointHe3) +#include "G4AdjointPositron.hh" +DECLARE_GEANT4_PARTICLE(G4AdjointPositron) +#include "G4AdjointProton.hh" +DECLARE_GEANT4_PARTICLE(G4AdjointProton) +#include "G4AdjointTriton.hh" +DECLARE_GEANT4_PARTICLE(G4AdjointTriton) + +// ---- bosons +#include "G4Geantino.hh" +DECLARE_GEANT4_PARTICLE(G4Geantino) +#include "G4ChargedGeantino.hh" +DECLARE_GEANT4_PARTICLE(G4ChargedGeantino) +#include "G4Gamma.hh" +DECLARE_GEANT4_PARTICLE(G4Gamma) +#include "G4OpticalPhoton.hh" +DECLARE_GEANT4_PARTICLE(G4OpticalPhoton) +#include "G4BosonConstructor.hh" +DECLARE_GEANT4_PARTICLEGROUP(G4BosonConstructor) + +// ---- barions +#include "G4XibZero.hh" +DECLARE_GEANT4_PARTICLE(G4XibZero) +#include "G4SigmabPlus.hh" +DECLARE_GEANT4_PARTICLE(G4SigmabPlus) +#include "G4Lambda.hh" +DECLARE_GEANT4_PARTICLE(G4Lambda) +#include "G4Proton.hh" +DECLARE_GEANT4_PARTICLE(G4Proton) +#include "G4SigmabMinus.hh" +DECLARE_GEANT4_PARTICLE(G4SigmabMinus) +#include "G4AntiXiMinus.hh" +DECLARE_GEANT4_PARTICLE(G4AntiXiMinus) +#include "G4AntiSigmabMinus.hh" +DECLARE_GEANT4_PARTICLE(G4AntiSigmabMinus) +#include "G4XiMinus.hh" +DECLARE_GEANT4_PARTICLE(G4XiMinus) +#include "G4LambdacPlus.hh" +DECLARE_GEANT4_PARTICLE(G4LambdacPlus) +#include "G4AntiOmegabMinus.hh" +DECLARE_GEANT4_PARTICLE(G4AntiOmegabMinus) +#include "G4Neutron.hh" +DECLARE_GEANT4_PARTICLE(G4Neutron) +#include "G4AntiXibZero.hh" +DECLARE_GEANT4_PARTICLE(G4AntiXibZero) +#include "G4OmegacZero.hh" +DECLARE_GEANT4_PARTICLE(G4OmegacZero) +#include "G4SigmacPlus.hh" +DECLARE_GEANT4_PARTICLE(G4SigmacPlus) +#include "G4AntiXibMinus.hh" +DECLARE_GEANT4_PARTICLE(G4AntiXibMinus) +#include "G4Lambdab.hh" +DECLARE_GEANT4_PARTICLE(G4Lambdab) +#include "G4AntiXicZero.hh" +DECLARE_GEANT4_PARTICLE(G4AntiXicZero) +#include "G4AntiOmegacZero.hh" +DECLARE_GEANT4_PARTICLE(G4AntiOmegacZero) +#include "G4AntiLambdacPlus.hh" +DECLARE_GEANT4_PARTICLE(G4AntiLambdacPlus) +#include "G4AntiSigmaZero.hh" +DECLARE_GEANT4_PARTICLE(G4AntiSigmaZero) +#include "G4AntiSigmaPlus.hh" +DECLARE_GEANT4_PARTICLE(G4AntiSigmaPlus) +#include "G4SigmaZero.hh" +DECLARE_GEANT4_PARTICLE(G4SigmaZero) +#include "G4AntiLambda.hh" +DECLARE_GEANT4_PARTICLE(G4AntiLambda) +#include "G4XiZero.hh" +DECLARE_GEANT4_PARTICLE(G4XiZero) +#include "G4AntiSigmabZero.hh" +DECLARE_GEANT4_PARTICLE(G4AntiSigmabZero) +#include "G4AntiSigmaMinus.hh" +DECLARE_GEANT4_PARTICLE(G4AntiSigmaMinus) +#include "G4AntiProton.hh" +DECLARE_GEANT4_PARTICLE(G4AntiProton) +#include "G4XicPlus.hh" +DECLARE_GEANT4_PARTICLE(G4XicPlus) +#include "G4BaryonConstructor.hh" +DECLARE_GEANT4_PARTICLEGROUP(G4BaryonConstructor) +#include "G4AntiSigmacPlusPlus.hh" +DECLARE_GEANT4_PARTICLE(G4AntiSigmacPlusPlus) +#include "G4XibMinus.hh" +DECLARE_GEANT4_PARTICLE(G4XibMinus) +#include "G4AntiSigmabPlus.hh" +DECLARE_GEANT4_PARTICLE(G4AntiSigmabPlus) +#include "G4AntiSigmacPlus.hh" +DECLARE_GEANT4_PARTICLE(G4AntiSigmacPlus) +#include "G4SigmaMinus.hh" +DECLARE_GEANT4_PARTICLE(G4SigmaMinus) +#include "G4SigmacPlusPlus.hh" +DECLARE_GEANT4_PARTICLE(G4SigmacPlusPlus) +#include "G4AntiXicPlus.hh" +DECLARE_GEANT4_PARTICLE(G4AntiXicPlus) +#include "G4SigmabZero.hh" +DECLARE_GEANT4_PARTICLE(G4SigmabZero) +#include "G4AntiXiZero.hh" +DECLARE_GEANT4_PARTICLE(G4AntiXiZero) +#include "G4AntiOmegaMinus.hh" +DECLARE_GEANT4_PARTICLE(G4AntiOmegaMinus) +#include "G4OmegabMinus.hh" +DECLARE_GEANT4_PARTICLE(G4OmegabMinus) +#include "G4OmegaMinus.hh" +DECLARE_GEANT4_PARTICLE(G4OmegaMinus) +#include "G4AntiSigmacZero.hh" +DECLARE_GEANT4_PARTICLE(G4AntiSigmacZero) +#include "G4AntiNeutron.hh" +DECLARE_GEANT4_PARTICLE(G4AntiNeutron) +#include "G4SigmaPlus.hh" +DECLARE_GEANT4_PARTICLE(G4SigmaPlus) +#include "G4AntiLambdab.hh" +DECLARE_GEANT4_PARTICLE(G4AntiLambdab) +#include "G4XicZero.hh" +DECLARE_GEANT4_PARTICLE(G4XicZero) +#include "G4SigmacZero.hh" +DECLARE_GEANT4_PARTICLE(G4SigmacZero) + +// ---- ions +#include "G4AntiHe3.hh" +DECLARE_GEANT4_PARTICLE(G4AntiHe3) +#include "G4Deuteron.hh" +DECLARE_GEANT4_PARTICLE(G4Deuteron) +#include "G4He3.hh" +DECLARE_GEANT4_PARTICLE(G4He3) +#include "G4IonConstructor.hh" +DECLARE_GEANT4_PARTICLEGROUP(G4IonConstructor) +#include "G4Alpha.hh" +DECLARE_GEANT4_PARTICLE(G4Alpha) +#include "G4AntiAlpha.hh" +DECLARE_GEANT4_PARTICLE(G4AntiAlpha) +#include "G4AntiTriton.hh" +DECLARE_GEANT4_PARTICLE(G4AntiTriton) +#include "G4GenericIon.hh" +DECLARE_GEANT4_PARTICLE(G4GenericIon) +#include "G4AntiDeuteron.hh" +DECLARE_GEANT4_PARTICLE(G4AntiDeuteron) +#include "G4Triton.hh" +DECLARE_GEANT4_PARTICLE(G4Triton) + +// ---- mesons +#include "G4Eta.hh" +DECLARE_GEANT4_PARTICLE(G4Eta) +#include "G4KaonMinus.hh" +DECLARE_GEANT4_PARTICLE(G4KaonMinus) +#include "G4KaonZeroLong.hh" +DECLARE_GEANT4_PARTICLE(G4KaonZeroLong) +#include "G4DsMesonPlus.hh" +DECLARE_GEANT4_PARTICLE(G4DsMesonPlus) +#include "G4BMesonPlus.hh" +DECLARE_GEANT4_PARTICLE(G4BMesonPlus) +#include "G4PionPlus.hh" +DECLARE_GEANT4_PARTICLE(G4PionPlus) +#include "G4KaonZeroShort.hh" +DECLARE_GEANT4_PARTICLE(G4KaonZeroShort) +#include "G4MesonConstructor.hh" +DECLARE_GEANT4_PARTICLEGROUP(G4MesonConstructor) +#include "G4DsMesonMinus.hh" +DECLARE_GEANT4_PARTICLE(G4DsMesonMinus) +#include "G4AntiBsMesonZero.hh" +DECLARE_GEANT4_PARTICLE(G4AntiBsMesonZero) +#include "G4DMesonZero.hh" +DECLARE_GEANT4_PARTICLE(G4DMesonZero) +#include "G4AntiDMesonZero.hh" +DECLARE_GEANT4_PARTICLE(G4AntiDMesonZero) +#include "G4BsMesonZero.hh" +DECLARE_GEANT4_PARTICLE(G4BsMesonZero) +#include "G4BMesonMinus.hh" +DECLARE_GEANT4_PARTICLE(G4BMesonMinus) +#include "G4PionZero.hh" +DECLARE_GEANT4_PARTICLE(G4PionZero) +#include "G4KaonPlus.hh" +DECLARE_GEANT4_PARTICLE(G4KaonPlus) +#include "G4DMesonMinus.hh" +DECLARE_GEANT4_PARTICLE(G4DMesonMinus) +#include "G4BcMesonMinus.hh" +DECLARE_GEANT4_PARTICLE(G4BcMesonMinus) +#include "G4BMesonZero.hh" +DECLARE_GEANT4_PARTICLE(G4BMesonZero) +#include "G4AntiKaonZero.hh" +DECLARE_GEANT4_PARTICLE(G4AntiKaonZero) +#include "G4EtaPrime.hh" +DECLARE_GEANT4_PARTICLE(G4EtaPrime) +#include "G4Upsiron.hh" +DECLARE_GEANT4_PARTICLE(G4Upsiron) +#include "G4AntiBMesonZero.hh" +DECLARE_GEANT4_PARTICLE(G4AntiBMesonZero) +#include "G4JPsi.hh" +DECLARE_GEANT4_PARTICLE(G4JPsi) +#include "G4KaonZero.hh" +DECLARE_GEANT4_PARTICLE(G4KaonZero) +#include "G4DMesonPlus.hh" +DECLARE_GEANT4_PARTICLE(G4DMesonPlus) +#include "G4PionMinus.hh" +DECLARE_GEANT4_PARTICLE(G4PionMinus) +#include "G4Etac.hh" +DECLARE_GEANT4_PARTICLE(G4Etac) +#include "G4BcMesonPlus.hh" +DECLARE_GEANT4_PARTICLE(G4BcMesonPlus) + +// ---- leptons +#include "G4MuonPlus.hh" +DECLARE_GEANT4_PARTICLE(G4MuonPlus) +#include "G4TauPlus.hh" +DECLARE_GEANT4_PARTICLE(G4TauPlus) +#include "G4AntiNeutrinoTau.hh" +DECLARE_GEANT4_PARTICLE(G4AntiNeutrinoTau) +#include "G4MuonMinus.hh" +DECLARE_GEANT4_PARTICLE(G4MuonMinus) +#include "G4NeutrinoE.hh" +DECLARE_GEANT4_PARTICLE(G4NeutrinoE) +#include "G4TauMinus.hh" +DECLARE_GEANT4_PARTICLE(G4TauMinus) +#include "G4Positron.hh" +DECLARE_GEANT4_PARTICLE(G4Positron) +#include "G4AntiNeutrinoMu.hh" +DECLARE_GEANT4_PARTICLE(G4AntiNeutrinoMu) +#include "G4LeptonConstructor.hh" +DECLARE_GEANT4_PARTICLEGROUP(G4LeptonConstructor) +#include "G4NeutrinoMu.hh" +DECLARE_GEANT4_PARTICLE(G4NeutrinoMu) +#include "G4AntiNeutrinoE.hh" +DECLARE_GEANT4_PARTICLE(G4AntiNeutrinoE) +#include "G4Electron.hh" +DECLARE_GEANT4_PARTICLE(G4Electron) +#include "G4NeutrinoTau.hh" +DECLARE_GEANT4_PARTICLE(G4NeutrinoTau) + +// ---- shortlived +#include "G4ExcitedXiConstructor.hh" +//DECLARE_GEANT4_PARTICLEGROUP(G4ExcitedXiConstructor) +#include "G4ExcitedLambdaConstructor.hh" +//DECLARE_GEANT4_PARTICLEGROUP(G4ExcitedLambdaConstructor) +#include "G4ShortLivedConstructor.hh" +//DECLARE_GEANT4_PARTICLEGROUP(G4ShortLivedConstructor) +#include "G4ExcitedSigmaConstructor.hh" +//DECLARE_GEANT4_PARTICLEGROUP(G4ExcitedSigmaConstructor) +#include "G4ExcitedBaryons.hh" +//DECLARE_GEANT4_PARTICLEGROUP(G4ExcitedBaryons) +#include "G4DiQuarks.hh" +//DECLARE_GEANT4_PARTICLEGROUP(G4DiQuarks) +#include "G4VShortLivedParticle.hh" +//DECLARE_GEANT4_PARTICLE(G4VShortLivedParticle) +#include "G4Quarks.hh" +//DECLARE_GEANT4_PARTICLEGROUP(G4Quarks) +#include "G4ExcitedDeltaConstructor.hh" +//DECLARE_GEANT4_PARTICLEGROUP(G4ExcitedDeltaConstructor) +#include "G4ExcitedBaryonConstructor.hh" +//DECLARE_GEANT4_PARTICLEGROUP(G4ExcitedBaryonConstructor) +#include "G4ExcitedNucleonConstructor.hh" +//DECLARE_GEANT4_PARTICLEGROUP(G4ExcitedNucleonConstructor) +#include "G4ExcitedMesonConstructor.hh" +//DECLARE_GEANT4_PARTICLEGROUP(G4ExcitedMesonConstructor) +#include "G4ExcitedMesons.hh" +//DECLARE_GEANT4_PARTICLEGROUP(G4ExcitedMesons) + diff --git a/DDG4/src/Geant4PhysicsList.cpp b/DDG4/src/Geant4PhysicsList.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa8c0290444a887c9e830014768f7ec5143d0d0d --- /dev/null +++ b/DDG4/src/Geant4PhysicsList.cpp @@ -0,0 +1,377 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DDG4/Geant4PhysicsList.h" +#include "DD4hep/InstanceCount.h" +#include "DD4hep/Printout.h" +#include "DD4hep/Plugins.h" + +#include "G4VPhysicsConstructor.hh" +#include "G4ParticleTable.hh" +#include "G4ProcessManager.hh" +#include "G4VProcess.hh" +#include "G4Decay.hh" + +// C/C++ include files +#include <stdexcept> +#include <regex.h> + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Simulation; + +namespace { + void _findDef(const string& expression, vector<G4ParticleDefinition*>& results) { + string exp = expression; //'^'+expression+"$"; + G4ParticleTable* pt = G4ParticleTable::GetParticleTable(); + G4ParticleTable::G4PTblDicIterator* iter = pt->GetIterator(); + char msgbuf[128]; + regex_t reg; + int ret = ::regcomp(®,exp.c_str(),0); + if ( ret ) { + throw runtime_error(format("Geant4PhysicsList", + "REGEX: Failed to compile particle name %s",exp.c_str())); + } + results.clear(); + iter->reset(); + while( (*iter)() ){ + G4ParticleDefinition* p = iter->value(); + ret = ::regexec(®,p->GetParticleName().c_str(), 0, NULL, 0); + if( !ret ) + results.push_back(p); + else if( ret == REG_NOMATCH ) + continue; + else { + ::regerror(ret, ®, msgbuf, sizeof(msgbuf)); + ::regfree(®); + throw runtime_error(format("Geant4PhysicsList", + "REGEX: Failed to match particle name %s err=%s", + exp.c_str(),msgbuf)); + } + } + ::regfree(®); + } +} + +/// Standard constructor with initailization parameters +Geant4UserPhysics::Geant4UserPhysics() +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4UserPhysics::~Geant4UserPhysics() { + InstanceCount::decrement(this); +} + +/// Default constructor +Geant4PhysicsList::Process::Process() : ordAtRestDoIt(-1), ordAlongSteptDoIt(-1), ordPostStepDoIt(-1) +{ +} +/// Copy constructor +Geant4PhysicsList::Process::Process(const Process& p) +: name(p.name), ordAtRestDoIt(p.ordAtRestDoIt), + ordAlongSteptDoIt(p.ordAlongSteptDoIt), ordPostStepDoIt(p.ordPostStepDoIt) +{ +} + +/// Assignment operator +Geant4PhysicsList::Process& Geant4PhysicsList::Process::operator=(const Process& p) { + name = p.name; + ordAtRestDoIt = p.ordAtRestDoIt; + ordAlongSteptDoIt = p.ordAlongSteptDoIt; + ordPostStepDoIt = p.ordPostStepDoIt; + return *this; +} + +/// Standard constructor +Geant4PhysicsList::Geant4PhysicsList(Geant4Context* context, const string& nam) +: Geant4Action(context,nam) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4PhysicsList::~Geant4PhysicsList() { + InstanceCount::decrement(this); +} + +/// Access processes for one particle type +Geant4PhysicsList::ParticleProcesses& Geant4PhysicsList::processes(const string& nam) +{ + PhysicsProcesses::iterator i = m_processes.find(nam); + if ( i != m_processes.end() ) { + return (*i).second; + } + pair<PhysicsProcesses::iterator,bool> ret = + m_processes.insert(make_pair(nam,ParticleProcesses())); + return (*(ret.first)).second; +} + +/// Access processes for one particle type (CONST) +const Geant4PhysicsList::ParticleProcesses& Geant4PhysicsList::processes(const string& nam) const +{ + PhysicsProcesses::const_iterator i = m_processes.find(nam); + if ( i != m_processes.end() ) { + return (*i).second; + } + throw runtime_error(format("Geant4PhysicsList", + "Failed to access the physics process '%s' [Unknown-Process]", + nam.c_str())); +} + +/// Callback to construct particle decays +void Geant4PhysicsList::constructPhysics(Geant4UserPhysics* physics) { + for(PhysicsConstructors::const_iterator i=m_physics.begin(); i != m_physics.end(); ++i) { + const PhysicsConstructors::value_type& ctor = *i; + G4VPhysicsConstructor* p = PluginService::Create<G4VPhysicsConstructor*>(ctor); + if ( !p ) { + throw runtime_error(format("Geant4PhysicsList","Failed to create the physics entities " + "for the G4VPhysicsConstructor '%s'",ctor.c_str())); + } + physics->RegisterPhysics(p); + printout(INFO,"Geant4PhysicsList","%s> registered Geant4 physics %s",name().c_str(),ctor.c_str()); + } +} + +/// constructParticle callback +void Geant4PhysicsList::constructParticles(Geant4UserPhysics* physics) { + printout(INFO,"Geant4PhysicsList","%s> constructParticles %p",name().c_str(),physics); + for(ParticleConstructors::const_iterator i=m_particles.begin(); i!=m_particles.end(); ++i) { + const ParticleConstructors::value_type& ctor = *i; + G4ParticleDefinition* def = PluginService::Create<G4ParticleDefinition*>(ctor); + if ( !def ) { + /// Check if we have here a particle group constructor + long* result = (long*)PluginService::Create<long>(ctor); + if ( !result || *result != 1L ) { + throw runtime_error(format("Geant4PhysicsList","Failed to create particle type '%s' result=%d", + ctor.c_str(),result)); + } + } + printout(INFO,"Geant4PhysicsList","%s> constructed Geant4 particle %s",name().c_str(),ctor.c_str()); + } +} + +#if 0 +#include "G4BosonConstructor.hh" +#include "G4MesonConstructor.hh" +#include "G4BaryonConstructor.hh" +#include "G4LeptonConstructor.hh" +#include "G4OpticalPhoton.hh" +#include "G4DecayTable.hh" +#include "G4PhaseSpaceDecayChannel.hh" + + G4BosonConstructor::ConstructParticle(); + G4LeptonConstructor::ConstructParticle(); + G4BaryonConstructor::ConstructParticle(); + G4MesonConstructor::ConstructParticle(); + G4OpticalPhoton::Definition(); + + G4ParticleTable* pt = G4ParticleTable::GetParticleTable(); + G4ParticleDefinition* d; + G4DecayTable* table; + G4VDecayChannel* mode; + // Bohr Magnetron + G4double muB = 0.5*eplus*hbar_Planck/(electron_mass_c2/c_squared) ; + d=new G4ParticleDefinition( + "gamma", 0.0*MeV, 0.0*MeV, 0.0, + 2, -1, -1, + 0, 0, 0, + "gamma", 0, 0, 22, + true, 0.0, NULL, + false, "photon", 22 + ); + d=new G4ParticleDefinition( + "geantino", 0.0*MeV, 0.0*MeV, 0.0, + 0, 0, 0, + 0, 0, 0, + "geantino", 0, 0, 0, + true, 0.0, NULL, + false, "geantino", 0 + ); + //----------------------------------------------------------------------------------- + d=new G4ParticleDefinition( + "e-", electron_mass_c2, 0.0*MeV, -1.*eplus, + 1, 0, 0, + 0, 0, 0, + "lepton", 1, 0, 11, + true, -1.0, NULL, + false, "e" + ); + d->SetPDGMagneticMoment( muB * 2.* 1.0011596521859 ); + //----------------------------------------------------------------------------------- + d=new G4ParticleDefinition( + "e+", electron_mass_c2, 0.0*MeV, +1.*eplus, + 1, 0, 0, + 0, 0, 0, + "lepton", -1, 0, -11, + true, -1.0, NULL, + false, "e" + ); + d->SetPDGMagneticMoment( muB * 2.* 1.0011596521859 ); + //----------------------------------------------------------------------------------- + d = new G4ParticleDefinition( + "mu+", 0.105658367*GeV, 2.995912e-16*MeV, +1.*eplus, + 1, 0, 0, + 0, 0, 0, + "lepton", -1, 0, -13, + false, 2197.03*ns, NULL, + false, "mu" + ); + d->SetPDGMagneticMoment( muB * 2.* 1.0011659208); + //----------------------------------------------------------------------------------- + d = new G4ParticleDefinition( + "mu-", 0.105658367*GeV, 2.995912e-16*MeV, -1.*eplus, + 1, 0, 0, + 0, 0, 0, + "lepton", 1, 0, 13, + false, 2197.03*ns, NULL, + false, "mu" + ); + d->SetPDGMagneticMoment( muB * 2. * 1.0011659208); + //----------------------------------------------------------------------------------- + d = new G4ParticleDefinition( + "pi+", 0.1395701*GeV, 2.5284e-14*MeV, +1.*eplus, + 0, -1, 0, + 2, +2, -1, + "meson", 0, 0, 211, + false, 26.033*ns, NULL, + false, "pi"); + table = new G4DecayTable(); + // create a decay channel + // pi+ -> mu+ + nu_mu + mode = new G4PhaseSpaceDecayChannel("pi+",1.00,2,"mu+","nu_mu"); + table->Insert(mode); + d->SetDecayTable(table); + //----------------------------------------------------------------------------------- + d = new G4ParticleDefinition( + "pi-", 0.1395701*GeV, 2.5284e-14*MeV, -1.*eplus, + 0, -1, 0, + 2, -2, -1, + "meson", 0, 0, -211, + false, 26.033*ns, NULL, + false, "pi"); + table = new G4DecayTable(); + // create a decay channel + // pi+ -> mu+ + nu_mu + mode = new G4PhaseSpaceDecayChannel("pi-",1.00,2,"mu-","anti_nu_mu"); + table->Insert(mode); + d->SetDecayTable(table); + //----------------------------------------------------------------------------------- +#endif + +/// Callback to construct the physics list +void Geant4PhysicsList::constructProcess(Geant4UserPhysics* physics) { + printout(INFO,"Geant4PhysicsList","%s> constructProcess %p",name().c_str(),physics); + constructPhysics(physics); + constructProcesses(physics); +} + +/// Callback to construct processes (uses the G4 particle table) +void Geant4PhysicsList::constructProcesses(Geant4UserPhysics* physics) { + printout(INFO,"Geant4PhysicsList","%s> constructProcesses %p",name().c_str(),physics); + for(PhysicsProcesses::const_iterator i = m_processes.begin(); i!=m_processes.end(); ++i) { + const string& part_name = (*i).first; + const ParticleProcesses& procs = (*i).second; + vector<G4ParticleDefinition*> defs; + _findDef(part_name, defs); + if ( defs.empty() ) { + throw runtime_error(format("Geant4PhysicsList", "Particle:%s " + "Cannot find the corresponding entry in the particle table.", + part_name.c_str())); + } + for(vector<G4ParticleDefinition*>::const_iterator id=defs.begin(); id!=defs.end(); ++id) { + G4ParticleDefinition* particle = *id; + G4ProcessManager* mgr = particle->GetProcessManager(); + for (ParticleProcesses::const_iterator ip=procs.begin(); ip != procs.end(); ++ip) { + const Process& p = (*ip); + G4VProcess* g4 = PluginService::Create<G4VProcess*>(p.name); + if ( !g4 ) { // Error no factory for this process + throw runtime_error(format("Geant4PhysicsList","Particle:%s -> [%s] " + "Cannot create physics process %s", + part_name.c_str(),particle->GetParticleName().c_str(), + p.name.c_str())); + } + mgr->AddProcess(g4,p.ordAtRestDoIt,p.ordAlongSteptDoIt,p.ordPostStepDoIt); + printout(INFO,"Geant4PhysicsList","Particle:%s -> [%s] " + "added process %s with flags (%d,%d,%d)", + part_name.c_str(),particle->GetParticleName().c_str(), + p.name.c_str(),p.ordAtRestDoIt,p.ordAlongSteptDoIt, + p.ordPostStepDoIt); + } + } + } +} + +/// Standard constructor +Geant4PhysicsListActionSequence::Geant4PhysicsListActionSequence(Geant4Context* context, const string& nam) +: Geant4Action(context,nam), m_transportation(false), m_decays(false) +{ + InstanceCount::increment(this); + declareProperty("transportation",m_transportation); + declareProperty("decays",m_decays); +} + +/// Default destructor +Geant4PhysicsListActionSequence::~Geant4PhysicsListActionSequence() { + m_actors(&Geant4Action::release); + m_actors.clear(); + m_process.clear(); + InstanceCount::decrement(this); +} + +/// Add an actor responding to all callbacks. Sequence takes ownership. +void Geant4PhysicsListActionSequence::adopt(Geant4PhysicsList* action) { + if ( action ) { + action->addRef(); + m_actors.add(action); + return; + } + throw runtime_error("Geant4EventActionSequence: Attempt to add invalid actor!"); +} + +/// begin-of-event callback +void Geant4PhysicsListActionSequence::constructParticles(Geant4UserPhysics* physics) { + m_particle(physics); + m_actors(&Geant4PhysicsList::constructParticles,physics); +} + +/// constructProcess callback +void Geant4PhysicsListActionSequence::constructProcess(Geant4UserPhysics* physics) { + m_actors(&Geant4PhysicsList::constructProcess,physics); + m_process(physics); + if ( m_decays ) { + constructDecays(physics); + } + if ( m_transportation ) { + physics->AddTransportation(); + } +} + +/// Callback to construct particle decays +void Geant4PhysicsListActionSequence::constructDecays(Geant4UserPhysics* physics) { + G4ParticleTable* pt = G4ParticleTable::GetParticleTable(); + G4ParticleTable::G4PTblDicIterator* iter = pt->GetIterator(); + // Add Decay Process + G4Decay* decay = new G4Decay(); + printout(INFO,"Geant4PhysicsList","%s> constructDecays %p",name().c_str(),physics); + iter->reset(); + while( (*iter)() ) { + G4ParticleDefinition* p = iter->value(); + G4ProcessManager* mgr = p->GetProcessManager(); + if (decay->IsApplicable(*p)) { + mgr->AddProcess(decay); + // set ordering for PostStepDoIt and AtRestDoIt + mgr->SetProcessOrdering(decay, idxPostStep); + mgr->SetProcessOrdering(decay, idxAtRest); + } + } +} + diff --git a/DDG4/src/Geant4Processes.cpp b/DDG4/src/Geant4Processes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..09faecd3ed13737a792c5473f6fe13fa27b2a6a0 --- /dev/null +++ b/DDG4/src/Geant4Processes.cpp @@ -0,0 +1,167 @@ +// $Id: Factories.h 797 2013-10-03 19:20:32Z markus.frank@cern.ch $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DDG4/Factories.h" + +// Geant4 physics lists +#include "G4DecayPhysics.hh" + +// EM physics +#include "G4EmStandardPhysics_option1.hh" +DECLARE_GEANT4_PHYSICS(G4EmStandardPhysics_option1) +#include "G4EmStandardPhysics_option2.hh" +DECLARE_GEANT4_PHYSICS(G4EmStandardPhysics_option2) +#include "G4EmStandardPhysics_option3.hh" +DECLARE_GEANT4_PHYSICS(G4EmStandardPhysics_option3) +#include "G4EmStandardPhysics.hh" +DECLARE_GEANT4_PHYSICS(G4EmStandardPhysics) +#include "G4EmExtraPhysics.hh" +DECLARE_GEANT4_PHYSICS(G4EmExtraPhysics) + + +// Ion and hadrons +#include "G4IonPhysics.hh" +DECLARE_GEANT4_PHYSICS(G4IonPhysics) +#include "G4QStoppingPhysics.hh" +DECLARE_GEANT4_PHYSICS(G4QStoppingPhysics) +#include "G4HadronElasticPhysics.hh" +DECLARE_GEANT4_PHYSICS(G4HadronElasticPhysics) +#include "G4HadronElasticPhysicsLHEP.hh" +DECLARE_GEANT4_PHYSICS(G4HadronElasticPhysicsLHEP) +#include "G4HadronElasticPhysicsHP.hh" +DECLARE_GEANT4_PHYSICS(G4HadronElasticPhysicsHP) +#include "G4NeutronTrackingCut.hh" +DECLARE_GEANT4_PHYSICS(G4NeutronTrackingCut) + +// LHEP hadrons +#include "HadronPhysicsLHEP.hh" +DECLARE_GEANT4_PHYSICS(HadronPhysicsLHEP) + +// QGSP hadrons +#include "HadronPhysicsQGSP.hh" +DECLARE_GEANT4_PHYSICS(HadronPhysicsQGSP) +#include "HadronPhysicsQGSP_BERT.hh" +DECLARE_GEANT4_PHYSICS(HadronPhysicsQGSP_BERT) +#include "HadronPhysicsQGSP_BERT_HP.hh" +DECLARE_GEANT4_PHYSICS(HadronPhysicsQGSP_BERT_HP) +#include "HadronPhysicsQGSP_BERT_CHIPS.hh" +DECLARE_GEANT4_PHYSICS(HadronPhysicsQGSP_BERT_CHIPS) +#include "HadronPhysicsQGSP_FTFP_BERT.hh" +DECLARE_GEANT4_PHYSICS(HadronPhysicsQGSP_FTFP_BERT) + +// FTFP hadrons +#include "HadronPhysicsFTFP_BERT.hh" +DECLARE_GEANT4_PHYSICS(HadronPhysicsFTFP_BERT) + +// Photon Processes: +#include "G4GammaConversion.hh" +DECLARE_GEANT4_PROCESS(G4GammaConversion) +#include "G4PhotoElectricEffect.hh" +DECLARE_GEANT4_PROCESS(G4PhotoElectricEffect) +#include "G4ComptonScattering.hh" +DECLARE_GEANT4_PROCESS(G4ComptonScattering) +#include "G4RayleighScattering.hh" +DECLARE_GEANT4_PROCESS(G4RayleighScattering) +#include "G4GammaConversionToMuons.hh" +DECLARE_GEANT4_PROCESS(G4GammaConversionToMuons) + +// Electron/positron processes +#include "G4eIonisation.hh" +DECLARE_GEANT4_PROCESS(G4eIonisation) +#include "G4eBremsstrahlung.hh" +DECLARE_GEANT4_PROCESS(G4eBremsstrahlung) +#include "G4eMultipleScattering.hh" +DECLARE_GEANT4_PROCESS(G4eMultipleScattering) +#include "G4eplusAnnihilation.hh" +DECLARE_GEANT4_PROCESS(G4eplusAnnihilation) +#include "G4AnnihiToMuPair.hh" +DECLARE_GEANT4_PROCESS(G4AnnihiToMuPair) +#include "G4eeToHadrons.hh" +DECLARE_GEANT4_PROCESS(G4eeToHadrons) + +// Muon processes +#include "G4MuIonisation.hh" +DECLARE_GEANT4_PROCESS(G4MuIonisation) +#include "G4MuBremsstrahlung.hh" +DECLARE_GEANT4_PROCESS(G4MuBremsstrahlung) +#include "G4MuPairProduction.hh" +DECLARE_GEANT4_PROCESS(G4MuPairProduction) +#include "G4MuMultipleScattering.hh" +DECLARE_GEANT4_PROCESS(G4MuMultipleScattering) + +// Hadron/ion processes +#include "G4hIonisation.hh" +DECLARE_GEANT4_PROCESS(G4hIonisation) +#include "G4ionIonisation.hh" +DECLARE_GEANT4_PROCESS(G4ionIonisation) +#include "G4hhIonisation.hh" +DECLARE_GEANT4_PROCESS(G4hhIonisation) +#include "G4mplIonisation.hh" +DECLARE_GEANT4_PROCESS(G4mplIonisation) +#include "G4hMultipleScattering.hh" +DECLARE_GEANT4_PROCESS(G4hMultipleScattering) +#include "G4hBremsstrahlung.hh" +DECLARE_GEANT4_PROCESS(G4hBremsstrahlung) +#include "G4hPairProduction.hh" +DECLARE_GEANT4_PROCESS(G4hPairProduction) + +// Coulomb scattering +#include "G4CoulombScattering.hh" +DECLARE_GEANT4_PROCESS(G4CoulombScattering) + +// Processes for simulation of polarized electron and gamma beams +#include "G4PolarizedCompton.hh" +DECLARE_GEANT4_PROCESS(G4PolarizedCompton) +#include "G4PolarizedGammaConversion.hh" +DECLARE_GEANT4_PROCESS(G4PolarizedGammaConversion) +#include "G4PolarizedPhotoElectricEffect.hh" +DECLARE_GEANT4_PROCESS(G4PolarizedPhotoElectricEffect) +#include "G4ePolarizedBremsstrahlung.hh" +DECLARE_GEANT4_PROCESS(G4ePolarizedBremsstrahlung) +#include "G4ePolarizedIonisation.hh" +DECLARE_GEANT4_PROCESS(G4ePolarizedIonisation) +#include "G4eplusPolarizedAnnihilation.hh" +DECLARE_GEANT4_PROCESS(G4eplusPolarizedAnnihilation) + +// Processes for simulation of X-rays and optical protons production by charged particles +#include "G4SynchrotronRadiation.hh" +DECLARE_GEANT4_PROCESS(G4SynchrotronRadiation) +#include "G4TransitionRadiation.hh" +//DECLARE_GEANT4_PROCESS(G4TransitionRadiation) !!virtual abstract!! +#include "G4Cerenkov.hh" +DECLARE_GEANT4_PROCESS(G4Cerenkov) +#include "G4Scintillation.hh" +DECLARE_GEANT4_PROCESS(G4Scintillation) + +// Others +#include "G4PAIModel.hh" +DECLARE_GEANT4_PROCESS(G4PAIModel) +#include "G4BraggIonGasModel.hh" +DECLARE_GEANT4_PROCESS(G4BraggIonGasModel) +#include "G4BetheBlochIonGasModel.hh" +DECLARE_GEANT4_PROCESS(G4BetheBlochIonGasModel) +#include "G4WentzelVIModel.hh" +DECLARE_GEANT4_PROCESS(G4WentzelVIModel) +#include "G4UrbanMscModel93.hh" +DECLARE_GEANT4_PROCESS(G4UrbanMscModel93) +#include "G4hImpactIonisation.hh" +DECLARE_GEANT4_PROCESS(G4hImpactIonisation) + +//#include "G4InversePEEffect.hh" +//DECLARE_GEANT4_PROCESS(G4InversePEEffect) +//#include "G4hInverseIonisation.hh" +//DECLARE_GEANT4_PROCESS(G4hInverseIonisation) +//#include "G4IonInverseIonisation.hh" +//DECLARE_GEANT4_PROCESS(G4IonInverseIonisation) + +#if 0 +#include ".hh" +DECLARE_GEANT4_PROCESS() +#endif diff --git a/DDG4/src/Geant4RunAction.cpp b/DDG4/src/Geant4RunAction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3341c681f92dde4214668cf5540883490d005b00 --- /dev/null +++ b/DDG4/src/Geant4RunAction.cpp @@ -0,0 +1,74 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4RunAction.h" +// C/C++ include files +#include <stdexcept> + +using namespace DD4hep::Simulation; + +/// Standard constructor +Geant4RunAction::Geant4RunAction(Geant4Context* context, const std::string& nam) +: Geant4Action(context,nam) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4RunAction::~Geant4RunAction() { + InstanceCount::decrement(this); +} + +/// begin-of-run callback +void Geant4RunAction::begin(const G4Run* ) { +} + +/// End-of-run callback +void Geant4RunAction::end(const G4Run* ) { +} + +/// Standard constructor +Geant4RunActionSequence::Geant4RunActionSequence(Geant4Context* context, const std::string& name) +: Geant4Action(context,name) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4RunActionSequence::~Geant4RunActionSequence() { + m_actors(&Geant4RunAction::release); + m_actors.clear(); + m_begin.clear(); + m_end.clear(); + InstanceCount::decrement(this); +} + +/// Add an actor responding to all callbacks. Sequence takes ownership. +void Geant4RunActionSequence::adopt(Geant4RunAction* action) { + if ( action ) { + action->addRef(); + m_actors.add(action); + return; + } + throw std::runtime_error("Geant4RunActionSequence: Attempt to add invalid actor!"); +} + +/// Pre-track action callback +void Geant4RunActionSequence::begin(const G4Run* run) { + m_actors(&Geant4RunAction::begin,run); + m_begin(run); +} + +/// Post-track action callback +void Geant4RunActionSequence::end(const G4Run* run) { + m_end(run); + m_actors(&Geant4RunAction::end,run); +} diff --git a/DDG4/src/Geant4SDActions.cpp b/DDG4/src/Geant4SDActions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..11a97fb3022f547ab243700ffec5c5024e862adc --- /dev/null +++ b/DDG4/src/Geant4SDActions.cpp @@ -0,0 +1,324 @@ +// $Id: Geant4Field.cpp 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +// Framework include files +#include "DDG4/Geant4SensDetAction.h" +#include "DDG4/Geant4Data.h" +#include "DD4hep/Printout.h" + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + template <typename T> class Geant4SensitiveAction : public Geant4Sensitive { + protected: + /// Collection identifiers + size_t m_collectionID; + public: + typedef SimpleHit::Contribution HitContribution; + /// Standard , initializing constructor + Geant4SensitiveAction(Geant4Context* context, const std::string& name, DetElement det, LCDD& lcdd); + /// Default destructor + virtual ~Geant4SensitiveAction(); + /// Define collections created by this sensitivie action object + virtual void defineCollections() {} + /// G4VSensitiveDetector interface: Method invoked at the begining of each event. + virtual void begin(G4HCofThisEvent* hce); + /// G4VSensitiveDetector interface: Method invoked at the end of each event. + virtual void end(G4HCofThisEvent* hce); + /// G4VSensitiveDetector interface: Method for generating hit(s) using the G4Step object. + virtual bool process(G4Step* step,G4TouchableHistory* history); + /// G4VSensitiveDetector interface: Method invoked if the event was aborted. + virtual void clear(G4HCofThisEvent* hce); + }; + } +} +#include "DD4hep/InstanceCount.h" + +namespace DD4hep { + namespace Simulation { + + /// Standard , initializing constructor + template <typename T> + Geant4SensitiveAction<T>::Geant4SensitiveAction(Geant4Context* context, + const std::string& name, + DetElement det, + LCDD& lcdd) + : Geant4Sensitive(context,name,det,lcdd), m_collectionID(0) + { + defineCollections(); + InstanceCount::increment(this); + } + + /// Default destructor + template <typename T> Geant4SensitiveAction<T>::~Geant4SensitiveAction() { + InstanceCount::decrement(this); + } + + /// G4VSensitiveDetector interface: Method invoked at the begining of each event. + template <typename T> void Geant4SensitiveAction<T>::begin(G4HCofThisEvent* hce) { + Geant4Sensitive::begin(hce); + } + + /// G4VSensitiveDetector interface: Method invoked at the end of each event. + template <typename T> void Geant4SensitiveAction<T>::end(G4HCofThisEvent* hce) { + Geant4Sensitive::end(hce); + } + + /// G4VSensitiveDetector interface: Method for generating hit(s) using the G4Step object. + template <typename T> bool Geant4SensitiveAction<T>::process(G4Step* step,G4TouchableHistory* history) { + return Geant4Sensitive::process(step,history); + } + + /// G4VSensitiveDetector interface: Method invoked if the event was aborted. + template <typename T> void Geant4SensitiveAction<T>::clear(G4HCofThisEvent* hce) { + Geant4Sensitive::clear(hce); + } + + } +} + +#include "DDG4/Geant4StepHandler.h" +#include "G4OpticalPhoton.hh" +#include "G4VProcess.hh" + + +namespace DD4hep { + namespace Simulation { + + template<typename TYPE> struct PositionCompare : public Geant4HitCollection::Compare { + const Position& pos; + Geant4HitWrapper::HitManipulator* manip; + /// Constructor + PositionCompare(const Position& p) : pos(p), manip(Geant4HitWrapper::HitManipulator::instance<TYPE>()) { } + /// Comparison function + virtual void* operator()(const Geant4HitWrapper& w) const { + TYPE* h = w;//(const TYPE*)manip->castHit<TYPE>(w); + return pos == h->position ? h : 0; + } + }; + + /// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + /// Geant4SensitiveAction<SimpleTracker> + /// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + /// Define collections created by this sensitivie action object + template <> void Geant4SensitiveAction<SimpleTracker>::defineCollections() { + m_collectionID = defineCollection<SimpleTracker::Hit>(name()+"Hits"); + } + + /// Method for generating hit(s) using the information of G4Step object. + template <> bool Geant4SensitiveAction<SimpleTracker>::process(G4Step* step,G4TouchableHistory* /*hist*/ ) { + typedef SimpleTracker::Hit Hit; + StepHandler h(step); + Position prePos = h.prePos(); + Position postPos = h.postPos(); + Position direction = postPos - prePos; + Position position = mean_direction(prePos,postPos); + double hit_len = direction.R(); + if (hit_len > 0) { + double new_len = mean_length(h.preMom(),h.postMom())/hit_len; + direction *= new_len/hit_len; + } + printout(INFO,"SimpleTracker","%s> Add hit with deposit:%f Pos:%f %f %f", + c_name(),step->GetTotalEnergyDeposit(),position.X(),position.Y(),position.Z()); + Hit* hit = new Hit(h.track->GetTrackID(), + h.track->GetDefinition()->GetPDGEncoding(), + step->GetTotalEnergyDeposit(), + h.track->GetGlobalTime()); + + HitContribution contrib = Hit::extractContribution(step); + hit->cellID = volumeID( step ) ; + hit->energyDeposit = contrib.deposit ; + hit->position = position; + hit->momentum = direction; + hit->length = hit_len; + collection(m_collectionID)->add(hit); + return hit != 0; + } + typedef Geant4SensitiveAction<SimpleTracker> Geant4SimpleTrackerAction; + + /// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + /// Geant4SensitiveAction<Calorimeter> + /// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + /// Define collections created by this sensitivie action object + template <> void Geant4SensitiveAction<SimpleCalorimeter>::defineCollections() { + m_collectionID = defineCollection<SimpleCalorimeter::Hit>(name()+"Hits"); + } + /// Method for generating hit(s) using the information of G4Step object. + template <> bool Geant4SensitiveAction<SimpleCalorimeter>::process(G4Step* step,G4TouchableHistory*) { + typedef SimpleCalorimeter::Hit Hit; + StepHandler h(step); + Position pos = 0.5 * (h.prePos() + h.postPos()); + HitContribution contrib = Hit::extractContribution(step); + HitCollection* coll = collection(m_collectionID); + Hit* hit = coll->find<Hit>(PositionCompare<Hit>(pos)); + if ( !hit ) { + hit = new Hit(pos) ; + hit->cellID = volumeID( step ) ; + coll->add(hit) ; + printout(INFO,"SimpleTracker","%s> CREATE hit with deposit:%f Pos:%f %f %f", + c_name(),contrib.deposit,pos.X(),pos.Y(),pos.Z()); + } + else { + printout(INFO,"SimpleTracker","%s> UPDATE hit with deposit:%f Pos:%f %f %f", + c_name(),contrib.deposit,pos.X(),pos.Y(),pos.Z()); + } + hit->truth.push_back(contrib); + hit->energyDeposit += contrib.deposit; + return true; + } + typedef Geant4SensitiveAction<SimpleCalorimeter> Geant4SimpleCalorimeterAction; + + /// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + /// Geant4SensitiveAction<OpticalCalorimeter> + /// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + struct SimpleOpticalCalorimeter {}; + /// Define collections created by this sensitivie action object + template <> void Geant4SensitiveAction<SimpleOpticalCalorimeter>::defineCollections() { + m_collectionID = defineCollection<SimpleCalorimeter::Hit>("Ceren_"+name()+"Hits"); + } + /// Method for generating hit(s) using the information of G4Step object. + template <> bool Geant4SensitiveAction<SimpleOpticalCalorimeter>::process(G4Step* step,G4TouchableHistory*) { + G4Track * track = step->GetTrack(); + // check that particle is optical photon: + if( track->GetDefinition() != G4OpticalPhoton::OpticalPhotonDefinition() ) { + return false; + } + else if ( track->GetCreatorProcess()->G4VProcess::GetProcessName() != "Cerenkov") { + track->SetTrackStatus(fStopAndKill); + return false; + } + else { + typedef SimpleCalorimeter::Hit Hit; + StepHandler h(step); + HitCollection* coll = collection(m_collectionID); + HitContribution contrib = Hit::extractContribution(step); + Position pos = h.prePos(); + Hit* hit = coll->find<Hit>(PositionCompare<Hit>(pos)); + if ( !hit ) { + hit=new Hit(pos); + coll->add(hit); + } + hit->energyDeposit += contrib.deposit; + hit->truth.push_back(contrib); + track->SetTrackStatus(fStopAndKill); // don't step photon any further + return true; + } + } + typedef Geant4SensitiveAction<SimpleOpticalCalorimeter> Geant4SimpleOpticalCalorimeterAction; + +#if 0 + /// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + /// Geant4SensitiveAction<TrackerCombine> + /// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + struct TrackerCombine { + Geant4TrackerHit pre; + Geant4TrackerHit post; + G4Track* track; + double e_cut; + int current; + TrackerCombine() : pre(), post(), track(0), e_cut(0.0), current(-1) { + } + void start(G4Step* step, G4StepPoint* point) { + pre.storePoint(step,point); + current = pre.truth.trackID; + track = step->GetTrack(); + post = pre; + } + void update(G4Step* step) { + post.storePoint(step,step->GetPostStepPoint()); + pre.truth.deposit += post.truth.deposit; + } + void clear() { + pre.truth.clear(); + current = -1; + track = 0; + } + Geant4TrackerHit* extractHit(Geant4SensitiveDetector::HitCollection* c) { + if ( current == -1 || !track ) { + return 0; + } + else if ( pre.truth.deposit <= e_cut && !Geant4Hit::isGeantino(track) ) { + clear(); + return 0; + } + Position pos = 0.5 * (pre.position + post.position); + Momentum mom = 0.5 * (pre.momentum + post.momentum); + double path_len = (post.position - pre.position).R(); + Geant4TrackerHit* hit = new Geant4TrackerHit(pre.truth.trackID, + pre.truth.pdgID, + pre.truth.deposit, + pre.truth.time); + hit->position = pos; + hit->momentum = mom; + hit->length = path_len; + clear(); + c->insert(hit); + return hit; + } + }; + + /// Method invoked at the begining of each event. + template <> void Geant4SensitiveAction<TrackerCombine>::Initialize(G4HCofThisEvent* HCE) { + userData.e_cut = m_sensitive.energyCutoff(); + this->Geant4SensitiveDetector::Initialize(HCE); + } + + /// Method for generating hit(s) using the information of G4Step object. + template <> void Geant4SensitiveAction<TrackerCombine>::clear() { + userData.clear(); + this->Geant4SensitiveDetector::clear(); + } + + /// Method for generating hit(s) using the information of G4Step object. + template <> G4bool Geant4SensitiveAction<TrackerCombine>::ProcessHits(G4Step* step,G4TouchableHistory* ) { + StepHandler h(step); + bool return_code = false; + + if ( !userData.track || userData.current != h.track->GetTrackID() ) { + return_code = userData.extractHit(collection(0)) != 0; + userData.start(step, h.pre); + } + + // ....update ..... + userData.update(step); + + void *prePV = h.volume(h.pre), *postPV = h.volume(h.post); + if ( prePV != postPV ) { + void* postSD = h.sd(h.post); + return_code = userData.extractHit(collection(0)) != 0; + if ( 0 != postSD ) { + void* preSD = h.sd(h.pre); + if ( preSD == postSD ) { + userData.start(step,h.post); + } + } + } + else if ( userData.track->GetTrackStatus() == fStopAndKill ) { + return_code = userData.extractHit(collection(0)) != 0; + } + return return_code; + } + typedef Geant4SensitiveAction<TrackerCombine> Geant4TrackerCombine; +#endif + + } +} + +using namespace DD4hep::Simulation; + +#include "DDG4/Factories.h" +DECLARE_GEANT4SENSITIVE(Geant4SimpleTrackerAction) +DECLARE_GEANT4SENSITIVE(Geant4SimpleCalorimeterAction) +DECLARE_GEANT4SENSITIVE(Geant4SimpleOpticalCalorimeterAction) diff --git a/DDG4/src/Geant4SensDetAction.cpp b/DDG4/src/Geant4SensDetAction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0031edaf71d8f76014ac0849572907188406b9c2 --- /dev/null +++ b/DDG4/src/Geant4SensDetAction.cpp @@ -0,0 +1,351 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/Printout.h" +#include "DD4hep/Primitives.h" +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4Kernel.h" +#include "DDG4/Geant4Mapping.h" +#include "DDG4/Geant4SensDetAction.h" +#include "DDG4/Geant4StepHandler.h" +#include "DDG4/Geant4VolumeManager.h" + +#include <G4SDManager.hh> +#include <G4VSensitiveDetector.hh> + +// C/C++ include files +#include <stdexcept> + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Simulation; + +namespace { + Geant4ActionSD* _getSensitiveDetector(const string& name) { + G4SDManager* mgr = G4SDManager::GetSDMpointer(); + G4VSensitiveDetector* sd = mgr->FindSensitiveDetector(name); + if ( 0 == sd ) { + throw runtime_error(format("Geant4Sensitive","DDG4: You requested to configure actions " + "for the sensitive detector %s,\nDDG4: which is not known to Geant4. " + "Are you sure you already converted the geometry?",name.c_str())); + } + Geant4ActionSD* action_sd = dynamic_cast<Geant4ActionSD*>(sd); + if ( 0 == action_sd ) { + throw runtime_error(format("Geant4Sensitive","DDG4: You may only configure actions " + "for sensitive detectors of type Geant4ActionSD.\n" + "DDG4: The sensitive detector of %s is of type %s, which is incompatible.", + name.c_str(),typeinfoName(typeid(*sd)).c_str())); + } + return action_sd; + } +} + +/// Standard action constructor +Geant4ActionSD::Geant4ActionSD(const std::string& name) +: Geant4Action(0,name) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4ActionSD::~Geant4ActionSD() +{ + InstanceCount::decrement(this); +} + +/// Standard constructor +Geant4Filter::Geant4Filter(Geant4Context* context, const std::string& name) +: Geant4Action(context,name) +{ + InstanceCount::increment(this); +} + +/// Standard destructor +Geant4Filter::~Geant4Filter() { + InstanceCount::decrement(this); +} + +/// Filter action. Return true if hits should be processed +bool Geant4Filter::operator()(const G4Step*) const { + return true; +} + +/// Constructor. The detector element is identified by the name +Geant4Sensitive::Geant4Sensitive(Geant4Context* ctxt, const string& name, DetElement det, LCDD& lcdd) +: Geant4Action(ctxt,name), m_sensitiveDetector(0), m_sequence(0), m_lcdd(lcdd), + m_detector(det), m_sensitive(), m_readout() +{ + InstanceCount::increment(this); + if ( !det.isValid() ) { + throw runtime_error(format("Geant4Sensitive","DDG4: Detector elemnt for %s is invalid.",name.c_str())); + } + m_sequence = ctxt->kernel().sensitiveAction(m_detector.name()); + m_sensitive = lcdd.sensitiveDetector(det.name()); + m_readout = m_sensitive.readout(); +} + +/// Standard destructor +Geant4Sensitive::~Geant4Sensitive() { + m_filters(&Geant4Filter::release); + m_filters.clear(); + InstanceCount::decrement(this); +} + +/// Add an actor responding to all callbacks. Sequence takes ownership. +void Geant4Sensitive::adopt(Geant4Filter* filter) { + if ( filter ) { + filter->addRef(); + m_filters.add(filter); + return; + } + throw runtime_error("Geant4SensDetActionSequence: Attempt to add invalid sensitive filter!"); +} + +/// Callback before hit processing starts. Invoke all filters. +bool Geant4Sensitive::accept(const G4Step* step) const { + bool result = m_filters.filter(&Geant4Filter::operator(),step); + return result; +} + +/// Access to the sensitive detector object +void Geant4Sensitive::setDetector(Geant4ActionSD* sens_det) { + m_sensitiveDetector = sens_det; +} + +/// Access to the sensitive detector object +Geant4ActionSD& Geant4Sensitive::detector() const { + if ( m_sensitiveDetector ) return *m_sensitiveDetector; + //m_sensitiveDetector = _getSensitiveDetector(m_detector.name()); + //if ( m_sensitiveDetector ) return *m_sensitiveDetector; + throw runtime_error(format("Geant4Sensitive","DDG4: The sensitive detector for action %s " + "was not properly configured.",name().c_str())); +} + +/// Access to the hosting sequence +Geant4SensDetActionSequence& Geant4Sensitive::sequence() const { + return *m_sequence; +} + +/// Access HitCollection container names +const string& Geant4Sensitive::hitCollectionName(size_t which) const { + return sequence().hitCollectionName(which); +} + +/// Retrieve the hits collection associated with this detector by its serial number +Geant4HitCollection* Geant4Sensitive::collection(size_t which) { + return sequence().collection(which); +} + +/// Retrieve the hits collection associated with this detector by its collection identifier +Geant4HitCollection* Geant4Sensitive::collectionByID(size_t id) { + return sequence().collectionByID(id); +} + +/// Method invoked at the begining of each event. +void Geant4Sensitive::begin(G4HCofThisEvent* /* HCE */) { +} + +/// Method invoked at the end of each event. +void Geant4Sensitive::end(G4HCofThisEvent* /* HCE */) { +} + +/// Method for generating hit(s) using the information of G4Step object. +bool Geant4Sensitive::process(G4Step* /* step */, G4TouchableHistory* /* history */) { + return false; +} + +/// Method is invoked if the event abortion is occured. +void Geant4Sensitive::clear(G4HCofThisEvent* /* HCE */) { +} + +/// Returns the volumeID of the sensitive volume corresponding to the step +long long int Geant4Sensitive::volumeID(G4Step* s) { + Geant4StepHandler step(s); + Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager(); + VolumeID id = volMgr.volumeID(step.preTouchable()); + return id; +} + +/// Standard constructor +Geant4SensDetActionSequence::Geant4SensDetActionSequence(Geant4Context* context,const string& nam) +: Geant4Action(context,nam), m_hce(0) +{ + InstanceCount::increment(this); + context->sensitiveActions().insert(name(),this); +} + +/// Default destructor +Geant4SensDetActionSequence::~Geant4SensDetActionSequence() { + m_filters(&Geant4Filter::release); + m_actors(&Geant4Sensitive::release); + m_filters.clear(); + m_actors.clear(); + InstanceCount::decrement(this); +} + +/// Add an actor responding to all callbacks +void Geant4SensDetActionSequence::adopt(Geant4Sensitive* sensitive) { + if ( sensitive ) { + sensitive->addRef(); + m_actors.add(sensitive); + return; + } + throw runtime_error("Geant4SensDetActionSequence: Attempt to add invalid sensitive actor!"); +} + +/// Add an actor responding to all callbacks. Sequence takes ownership. +void Geant4SensDetActionSequence::adopt(Geant4Filter* filter) { + if ( filter ) { + filter->addRef(); + m_filters.add(filter); + return; + } + throw runtime_error("Geant4SensDetActionSequence: Attempt to add invalid sensitive filter!"); +} + +/// Initialize the usage of a hit collection. Returns the collection identifier +size_t Geant4SensDetActionSequence::defineCollection(const std::string& name,create_t func) { + m_collections.push_back(make_pair(name,func)); + return m_collections.size()-1; +} + +/// Called at construction time of the sensitive detector to declare all hit collections +size_t Geant4SensDetActionSequence::Geant4SensDetActionSequence::defineCollections(Geant4ActionSD* sens_det) { + size_t count = 0; + m_detector = sens_det; + m_actors(&Geant4Sensitive::setDetector,sens_det); + for(HitCollections::const_iterator i=m_collections.begin(); i!=m_collections.end(); ++i) { + sens_det->defineCollection((*i).first); + ++count; + } + return count; +} + +/// Access HitCollection container names +const std::string& Geant4SensDetActionSequence::hitCollectionName(size_t which) const { + if ( which < m_collections.size() ) { + return m_collections[which].first; + } + static string blank=""; + except("The collection name index for subdetector %s is out of range!",c_name()); + return blank; +} + +/// Retrieve the hits collection associated with this detector by its serial number +Geant4HitCollection* Geant4SensDetActionSequence::collection(size_t which) const { + if ( which < m_collections.size() ) { + int hc_id = m_detector->GetCollectionID(which); + Geant4HitCollection* c = (Geant4HitCollection*)m_hce->GetHC(hc_id); + if ( c ) return c; + except("The collection index for subdetector %s is wrong!",c_name()); + } + except("The collection name index for subdetector %s is out of range!",c_name()); + return 0; +} + +/// Retrieve the hits collection associated with this detector by its collection identifier +Geant4HitCollection* Geant4SensDetActionSequence::collectionByID(size_t id) const { + Geant4HitCollection* c = (Geant4HitCollection*)m_hce->GetHC(id); + if ( c ) return c; + except("The collection index for subdetector %s is wrong!",c_name()); + return 0; +} + +/// Callback before hit processing starts. Invoke all filters. +bool Geant4SensDetActionSequence::accept(const G4Step* step) const { + bool result = m_filters.filter(&Geant4Filter::operator(),step); + return result; +} + +/// Function to process hits +bool Geant4SensDetActionSequence::process(G4Step* step, G4TouchableHistory* hist) { + bool result = false; + for(vector<Geant4Sensitive*>::iterator i=m_actors->begin(); i != m_actors->end(); ++i) { + Geant4Sensitive* s = *i; + if ( s->accept(step) ) result |= s->process(step,hist); + } + m_process(step,hist); + return result; +} + +/** G4VSensitiveDetector interface: Method invoked at the begining of each event. + * The hits collection(s) created by this sensitive detector must + * be set to the G4HCofThisEvent object at one of these two methods. + */ +void Geant4SensDetActionSequence::begin(G4HCofThisEvent* hce) { + m_hce = hce; + for(size_t count = 0; count < m_collections.size(); ++count) { + const std::pair<string,create_t>& cr = m_collections[count]; + G4VHitsCollection* c = (*cr.second)(name(), cr.first); + int id = m_detector->GetCollectionID(count); + m_hce->AddHitsCollection(id,c); + } + m_actors(&Geant4Sensitive::begin,m_hce); + m_begin(m_hce); +} + +/// G4VSensitiveDetector interface: Method invoked at the end of each event. +void Geant4SensDetActionSequence::end(G4HCofThisEvent* hce) { + m_end(hce); + m_actors(&Geant4Sensitive::end,hce); + m_hce = 0; +} + +/// G4VSensitiveDetector interface: Method invoked if the event was aborted. +/** Hits collections created but not beibg set to G4HCofThisEvent + * at the event should be deleted. + * Collection(s) which have already set to G4HCofThisEvent + * will be deleted automatically. + */ +void Geant4SensDetActionSequence::clear() { + m_clear(m_hce); + m_actors(&Geant4Sensitive::clear,m_hce); +} + +/// Default constructor +Geant4SensDetSequences::Geant4SensDetSequences() { +} + +/// Default destructor +Geant4SensDetSequences::~Geant4SensDetSequences() { + for_each(m_sequences.begin(),m_sequences.end(),releaseObjects(m_sequences)); + m_sequences.clear(); +} + +/// Access sequence member by name +Geant4SensDetActionSequence* Geant4SensDetSequences::operator[](const string& name) const { + string nam = "SD_Seq_"+name; + Members::const_iterator i=m_sequences.find(nam); + if ( i != m_sequences.end() ) + return (*i).second; + throw runtime_error("Attempt to access undefined SensDetActionSequence!"); +} + +/// Access sequence member by name +Geant4SensDetActionSequence* Geant4SensDetSequences::find(const std::string& name) const { + string nam = "SD_Seq_"+name; + Members::const_iterator i=m_sequences.find(nam); + if ( i != m_sequences.end() ) + return (*i).second; + return 0; +} + +/// Insert sequence member +void Geant4SensDetSequences::insert(const string& name,Geant4SensDetActionSequence* seq) { + if ( seq ) { + string nam = "SD_Seq_"+name; + seq->addRef(); + m_sequences[nam] = seq; + return; + } + throw runtime_error(format("Geant4SensDetSequences","Attempt to add invalid sensitive " + "sequence with name:%s",name.c_str())); +} + diff --git a/DDG4/src/Geant4SensDetFilters.cpp b/DDG4/src/Geant4SensDetFilters.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d283da00e0f9dced88b9bfdc2487719e87456c67 --- /dev/null +++ b/DDG4/src/Geant4SensDetFilters.cpp @@ -0,0 +1,243 @@ +// $Id: Geant4Field.cpp 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +// Framework include files +#include "DDG4/Geant4SensDetAction.h" + +// Forward declarations +class G4ParticleDefinition; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + /** @class ParticleFilter + * + * Geant4 sensitive detector filter base class for particle filters + * + * @author M.Frank + * @version 1.0 + */ + struct ParticleFilter : public Geant4Filter { + protected: + /// name of the particle to be filtered + std::string m_particle; + /// Corresponding geant4 particle definiton + mutable G4ParticleDefinition* m_definition; + public: + /// Constructor. + ParticleFilter(Geant4Context* context, const std::string& name); + /// Standard destructor + virtual ~ParticleFilter(); + /// Safe access to the definition + const G4ParticleDefinition* definition() const; + /// Check if a track is of the same type + bool isSameType(const G4Track* track) const; + /// Check if the particle is a geantino + bool isGeantino(const G4Track* track) const; + }; + + /** @class ParticleRejectFilter + * + * Geant4 sensitive detector filter implementing a particle rejector + * + * @author M.Frank + * @version 1.0 + */ + struct ParticleRejectFilter : public ParticleFilter { + /// Constructor. + ParticleRejectFilter(Geant4Context* c, const std::string& n); + /// Standard destructor + virtual ~ParticleRejectFilter(); + /// Filter action. Return true if hits should be processed + virtual bool operator()(const G4Step* step) const; + }; + + /** @class ParticleSelectFilter + * + * Geant4 sensitive detector filter implementing a particle selector + * + * @author M.Frank + * @version 1.0 + */ + struct ParticleSelectFilter : public ParticleFilter { + /// Constructor. + ParticleSelectFilter(Geant4Context* c, const std::string& n); + /// Standard destructor + virtual ~ParticleSelectFilter(); + /// Filter action. Return true if hits should be processed + virtual bool operator()(const G4Step* step) const; + }; + + /** @class GeantinoRejectFilter + * + * Geant4 sensitive detector filter implementing a Geantino rejector + * + * @author M.Frank + * @version 1.0 + */ + struct GeantinoRejectFilter : public ParticleFilter { + /// Constructor. + GeantinoRejectFilter(Geant4Context* c, const std::string& n); + /// Standard destructor + virtual ~GeantinoRejectFilter(); + /// Filter action. Return true if hits should be processed + virtual bool operator()(const G4Step* step) const; + }; + + /** @class EnergyDepositMinimumCut + * + * Geant4 sensitive detector filter implementing an energy cut. + * + * @author M.Frank + * @version 1.0 + */ + struct EnergyDepositMinimumCut : public Geant4Filter { + /// Energy cut value + double m_energyCut; + public: + /// Constructor. + EnergyDepositMinimumCut(Geant4Context* c, const std::string& n); + /// Standard destructor + virtual ~EnergyDepositMinimumCut(); + /// Filter action. Return true if hits should be processed + virtual bool operator()(const G4Step* step) const; + }; + } +} + +/// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDG4/Factories.h" + +// Geant4 include files +#include "G4ParticleTable.hh" +#include "G4ChargedGeantino.hh" +#include "G4Geantino.hh" +#include "G4Track.hh" +#include "G4Step.hh" + +using namespace DD4hep::Simulation; +using namespace DD4hep; +using namespace std; + +//DECLARE_GEANT4ACTION() +DECLARE_GEANT4ACTION(GeantinoRejectFilter) +DECLARE_GEANT4ACTION(ParticleRejectFilter) +DECLARE_GEANT4ACTION(ParticleSelectFilter) +DECLARE_GEANT4ACTION(EnergyDepositMinimumCut) + +/// Constructor. +ParticleFilter::ParticleFilter(Geant4Context* context, const std::string& name) + : Geant4Filter(context,name) +{ + declareProperty("particle",m_particle); + InstanceCount::increment(this); +} + +/// Standard destructor +ParticleFilter::~ParticleFilter() { + InstanceCount::decrement(this); +} + +/// Safe access to the definition +const G4ParticleDefinition* ParticleFilter::definition() const { + if ( m_definition ) return m_definition; + m_definition = G4ParticleTable::GetParticleTable()->FindParticle(m_particle); + if ( 0 == m_definition ) { + throw runtime_error("Invalid particle name:'"+m_particle+"' [Not-in-particle-table]"); + } + return m_definition; +} + +/// Check if a track is of the same type +bool ParticleFilter::isSameType(const G4Track* track) const { + G4ParticleDefinition* def = track->GetDefinition(); + return definition() == def; +} + +/// Check if the particle is a geantino +bool ParticleFilter::isGeantino(const G4Track* track) const { + if ( track ) { + G4ParticleDefinition* def = track->GetDefinition(); + if ( def == G4ChargedGeantino::Definition() ) + return true; + if ( def == G4Geantino::Definition() ) { + return true; + } + } + return false; +} + +/// Constructor. +GeantinoRejectFilter::GeantinoRejectFilter(Geant4Context* c, const std::string& n): ParticleFilter(c,n) { + InstanceCount::increment(this); +} + +/// Standard destructor +GeantinoRejectFilter::~GeantinoRejectFilter() { + InstanceCount::decrement(this); +} + +/// Filter action. Return true if hits should be processed +bool GeantinoRejectFilter::operator()(const G4Step* step) const { + return !isGeantino(step->GetTrack()); +} + +/// Constructor. +ParticleRejectFilter::ParticleRejectFilter(Geant4Context* c, const std::string& n): ParticleFilter(c,n) { + InstanceCount::increment(this); +} + +/// Standard destructor +ParticleRejectFilter::~ParticleRejectFilter() { + InstanceCount::decrement(this); +} + +/// Filter action. Return true if hits should be processed +bool ParticleRejectFilter::operator()(const G4Step* step) const { + return isSameType(step->GetTrack()); +} + +/// Constructor. +ParticleSelectFilter::ParticleSelectFilter(Geant4Context* c, const std::string& n) : ParticleFilter(c,n) { + InstanceCount::increment(this); +} + +/// Standard destructor +ParticleSelectFilter::~ParticleSelectFilter() { + InstanceCount::decrement(this); +} + +/// Filter action. Return true if hits should be processed +bool ParticleSelectFilter::operator()(const G4Step* step) const { + return !isSameType(step->GetTrack()); +} + +/// Constructor. +EnergyDepositMinimumCut::EnergyDepositMinimumCut(Geant4Context* c, const std::string& n) : Geant4Filter(c,n) { + InstanceCount::increment(this); + declareProperty("Cut",m_energyCut=0.0); +} + +/// Standard destructor +EnergyDepositMinimumCut::~EnergyDepositMinimumCut() { + InstanceCount::decrement(this); +} + +/// Filter action. Return true if hits should be processed +bool EnergyDepositMinimumCut::operator()(const G4Step* step) const { + return step->GetTotalEnergyDeposit() > m_energyCut; +} + diff --git a/DDG4/src/Geant4StackingAction.cpp b/DDG4/src/Geant4StackingAction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f8cba61fdfe49a7af95015f5e3e5827a7c6d1ee --- /dev/null +++ b/DDG4/src/Geant4StackingAction.cpp @@ -0,0 +1,67 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4StackingAction.h" + +// C/C++ include files +#include <stdexcept> + +using namespace DD4hep::Simulation; + +/// Standard constructor +Geant4StackingAction::Geant4StackingAction(Geant4Context* context, const std::string& name) +: Geant4Action(context,name) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4StackingAction::~Geant4StackingAction() { + InstanceCount::decrement(this); +} + +/// Standard constructor +Geant4StackingActionSequence::Geant4StackingActionSequence(Geant4Context* context, const std::string& name) +: Geant4Action(context,name) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4StackingActionSequence::~Geant4StackingActionSequence() { + m_actors(&Geant4StackingAction::release); + m_actors.clear(); + m_newStage.clear(); + m_prepare.clear(); + InstanceCount::decrement(this); +} + +/// Add an actor responding to all callbacks. Sequence takes ownership. +void Geant4StackingActionSequence::adopt(Geant4StackingAction* action) { + if ( action ) { + action->addRef(); + m_actors.add(action); + return; + } + throw std::runtime_error("Geant4StackingActionSequence: Attempt to add invalid actor!"); +} + +/// Pre-track action callback +void Geant4StackingActionSequence::newStage() { + m_actors(&Geant4StackingAction::newStage); + m_newStage(); +} + +/// Post-track action callback +void Geant4StackingActionSequence::prepare() { + m_actors(&Geant4StackingAction::prepare); + m_prepare(); +} diff --git a/DDG4/src/Geant4SteppingAction.cpp b/DDG4/src/Geant4SteppingAction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4536e8503ad3d0517e6c5428196e9c157f0d707b --- /dev/null +++ b/DDG4/src/Geant4SteppingAction.cpp @@ -0,0 +1,60 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4SteppingAction.h" +using namespace DD4hep::Simulation; + +/// Standard constructor +Geant4SteppingAction::Geant4SteppingAction(Geant4Context* context, const std::string& name) +: Geant4Action(context,name) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4SteppingAction::~Geant4SteppingAction() { + InstanceCount::decrement(this); +} + +/// User stepping callback +void Geant4SteppingAction::operator()(const G4Step*, G4SteppingManager*) { +} + +/// Standard constructor +Geant4SteppingActionSequence::Geant4SteppingActionSequence(Geant4Context* context, const std::string& name) +: Geant4Action(context,name) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4SteppingActionSequence::~Geant4SteppingActionSequence() { + m_actors(&Geant4SteppingAction::release); + m_actors.clear(); + m_calls.clear(); + InstanceCount::decrement(this); +} + +/// Pre-track action callback +void Geant4SteppingActionSequence::operator()(const G4Step* step, G4SteppingManager* mgr) { + m_actors(&Geant4SteppingAction::operator(),step,mgr); + m_calls(step,mgr); +} + +/// Add an actor responding to all callbacks. Sequence takes ownership. +void Geant4SteppingActionSequence::adopt(Geant4SteppingAction* action) { + if ( action ) { + action->addRef(); + m_actors.add(action); + return; + } + throw std::runtime_error("Geant4SteppingActionSequence: Attempt to add invalid actor!"); +} diff --git a/DDG4/src/Geant4TestActions.cpp b/DDG4/src/Geant4TestActions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..70115fa565f5d1e05e5d9248dbcbb8f6ca54ec58 --- /dev/null +++ b/DDG4/src/Geant4TestActions.cpp @@ -0,0 +1,187 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/Printout.h" +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4TestActions.h" +#include "DDG4/Factories.h" +#include "G4Run.hh" +#include "G4Event.hh" +#include "G4Step.hh" +#include "G4Track.hh" + +// C/C++ include files +#include <stdexcept> + +using namespace std; +using namespace DD4hep::Simulation; +using namespace DD4hep::Simulation::Test; + +namespace { + struct TestHit { + TestHit() {} + virtual ~TestHit() {} + }; +} + +/// Standard constructor +Geant4TestBase::Geant4TestBase(Geant4Action* a,const std::string& typ) +: m_type(typ) { + a->declareProperty("Property_int", m_value1=0); + a->declareProperty("Property_double",m_value2=0e0); + a->declareProperty("Property_string",m_value3); + InstanceCount::increment(this); +} +/// Default destructor +Geant4TestBase::~Geant4TestBase() { + InstanceCount::decrement(this); +} + +Geant4TestRunAction::Geant4TestRunAction(Geant4Context* c, const std::string& n) +: Geant4RunAction(c,n), Geant4TestBase(this,"Geant4TestRunAction") { + InstanceCount::increment(this); +} +Geant4TestRunAction::~Geant4TestRunAction() { + InstanceCount::decrement(this); +} +/// begin-of-run callback +void Geant4TestRunAction::begin(const G4Run* run) { + printout(INFO,name(),"%s> calling begin(run_id=%d,num_event=%d)", + m_type.c_str(),run->GetRunID(),run->GetNumberOfEventToBeProcessed()); +} +/// End-of-run callback +void Geant4TestRunAction::end (const G4Run* run) { + printout(INFO,name(),"%s> calling end(run_id=%d, num_event=%d)", + m_type.c_str(),run->GetRunID(),run->GetNumberOfEvent()); +} +/// begin-of-event callback +void Geant4TestRunAction::beginEvent(const G4Event* evt) { + printout(INFO,name(),"%s> calling beginEvent(event_id=%d)",m_type.c_str(),evt->GetEventID()); +} +/// End-of-event callback +void Geant4TestRunAction::endEvent (const G4Event* evt) { + printout(INFO,name(),"%s> calling endEvent(event_id=%d)",m_type.c_str(), evt->GetEventID()); +} + +Geant4TestEventAction::Geant4TestEventAction(Geant4Context* c, const std::string& n) +: Geant4EventAction(c,n), Geant4TestBase(this,"Geant4TestEventAction") { + InstanceCount::increment(this); +} +Geant4TestEventAction::~Geant4TestEventAction() { + InstanceCount::decrement(this); +} +/// begin-of-event callback +void Geant4TestEventAction::begin(const G4Event* evt) { + printout(INFO,name(),"%s> calling begin(event_id=%d)",m_type.c_str(),evt->GetEventID()); +} + +/// End-of-event callback +void Geant4TestEventAction::end (const G4Event* evt) { + printout(INFO,name(),"%s> calling end(event_id=%d)",m_type.c_str(),evt->GetEventID()); +} + +/// begin-of-run callback +void Geant4TestEventAction::beginRun(const G4Run* run) { + printout(INFO,name(),"%s> calling beginRun(run_id=%d,num_event=%d)", + m_type.c_str(),run->GetRunID(),run->GetNumberOfEventToBeProcessed()); +} + +/// End-of-run callback +void Geant4TestEventAction::endRun (const G4Run* run) { + printout(INFO,name(),"%s> calling endRun(run_id=%d, num_event=%d)", + m_type.c_str(),run->GetRunID(),run->GetNumberOfEvent()); +} + +Geant4TestTrackAction::Geant4TestTrackAction(Geant4Context* c, const std::string& n) +: Geant4TrackingAction(c,n), Geant4TestBase(this,"Geant4TestTrackAction") { + InstanceCount::increment(this); +} +Geant4TestTrackAction::~Geant4TestTrackAction() { + InstanceCount::decrement(this); +} +/// Begin-of-tracking callback +void Geant4TestTrackAction::begin(const G4Track* trk) { + printout(INFO,name(),"%s> calling begin(track=%d, parent=%d, position=(%f,%f,%f))", + m_type.c_str(),trk->GetTrackID(),trk->GetParentID(), + trk->GetPosition().x(),trk->GetPosition().y(),trk->GetPosition().z()); +} + +/// End-of-tracking callback +void Geant4TestTrackAction::end(const G4Track* trk) { + printout(INFO,name(),"%s> calling end(track=%d, parent=%d, position=(%f,%f,%f))", + m_type.c_str(),trk->GetTrackID(),trk->GetParentID(), + trk->GetPosition().x(),trk->GetPosition().y(),trk->GetPosition().z()); +} + +Geant4TestStepAction::Geant4TestStepAction(Geant4Context* c, const std::string& n) +: Geant4SteppingAction(c,n), Geant4TestBase(this,"Geant4TestStepAction") { + InstanceCount::increment(this); +} +Geant4TestStepAction::~Geant4TestStepAction() { + InstanceCount::decrement(this); +} +/// User stepping callback +void Geant4TestStepAction::operator()(const G4Step* , G4SteppingManager* ) { + printout(INFO,name(),"%s> calling operator()",m_type.c_str()); +} + +Geant4TestSensitive::Geant4TestSensitive(Geant4Context* c, const std::string& n, DetElement det, LCDD& lcdd) +: Geant4Sensitive(c,n,det,lcdd), Geant4TestBase(this,"Geant4TestSensitive") { + InstanceCount::increment(this); + m_collectionID = defineCollection<TestHit>(n); + printout(INFO,name(),"%s> Collection ID is %d",m_type.c_str(),int(m_collectionID)); +} +Geant4TestSensitive::~Geant4TestSensitive() { + InstanceCount::decrement(this); +} + +/// Begin-of-tracking callback +void Geant4TestSensitive::begin(G4HCofThisEvent* hce) { + Geant4HitCollection* c = collectionByID(m_collectionID); + printout(INFO,name(),"%s> calling begin(num_coll=%d, coll=%s)", + m_type.c_str(),hce->GetNumberOfCollections(), + c ? c->GetName().c_str() : "None"); +} + +/// End-of-tracking callback +void Geant4TestSensitive::end(G4HCofThisEvent* hce) { + Geant4HitCollection* c = collection(m_collectionID); + printout(INFO,name(),"%s> calling end(num_coll=%d, coll=%s)", + m_type.c_str(),hce->GetNumberOfCollections(), + c ? c->GetName().c_str() : "None"); +} + +/// Method for generating hit(s) using the information of G4Step object. +bool Geant4TestSensitive::process(G4Step* step,G4TouchableHistory* ) { + Geant4HitCollection* c = collection(m_collectionID); + printout(INFO,name(),"%s> calling process(track=%d, dE=%f, dT=%f len=%f, First,last in Vol=(%c,%c), coll=%s)", + m_type.c_str(),step->GetTrack()->GetTrackID(), + step->GetTotalEnergyDeposit(), step->GetDeltaTime(), step->GetStepLength(), + step->IsFirstStepInVolume() ? 'Y' : 'N', + step->IsLastStepInVolume() ? 'Y' : 'N', + c ? c->GetName().c_str() : "None"); + return true; +} +namespace DD4hep { namespace Simulation { + //using namespace Test; + using namespace DD4hep::Simulation::Test; + typedef Geant4TestSensitive Geant4TestSensitiveTracker; + typedef Geant4TestSensitive Geant4TestSensitiveCalorimeter; + }} + +DECLARE_GEANT4ACTION(Geant4TestRunAction) +DECLARE_GEANT4ACTION(Geant4TestEventAction) +DECLARE_GEANT4ACTION(Geant4TestStepAction) +DECLARE_GEANT4ACTION(Geant4TestTrackAction) +//DECLARE_GEANT4ACTION(Geant4TestStackingAction) +//DECLARE_GEANT4ACTION(Geant4TestGeneratorAction) +DECLARE_GEANT4SENSITIVE(Geant4TestSensitive) +DECLARE_GEANT4SENSITIVE(Geant4TestSensitiveTracker) +DECLARE_GEANT4SENSITIVE(Geant4TestSensitiveCalorimeter) diff --git a/DDG4/src/Geant4TrackingAction.cpp b/DDG4/src/Geant4TrackingAction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..023c95f6183f210fe231df415ba839c05378f098 --- /dev/null +++ b/DDG4/src/Geant4TrackingAction.cpp @@ -0,0 +1,130 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4TrackingAction.h" + +// Geant4 include files +#include "G4Track.hh" +#include "G4TrackingManager.hh" +#include "G4VUserTrackInformation.hh" + +// C/C++ include files +#include <stdexcept> + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Simulation; +class G4Step; +class G4TouchableHistory; + +/// Standard constructor +Geant4TrackingActionSequence::Geant4TrackingActionSequence(Geant4Context* context, const std::string& name) +: Geant4Action(context,name) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4TrackingActionSequence::~Geant4TrackingActionSequence() { + m_actors(&Geant4TrackingAction::release); + m_actors.clear(); + m_begin.clear(); + m_end.clear(); + InstanceCount::decrement(this); +} + +/// Add an actor responding to all callbacks. Sequence takes ownership. +void Geant4TrackingActionSequence::adopt(Geant4TrackingAction* action) { + if ( action ) { + action->addRef(); + m_actors.add(action); + return; + } + throw std::runtime_error("Geant4TrackingActionSequence: Attempt to add invalid actor!"); +} + +/// Pre-track action callback +void Geant4TrackingActionSequence::begin(const G4Track* track) { + m_actors(&Geant4TrackingAction::begin,track); + m_begin(track); +} + +/// Post-track action callback +void Geant4TrackingActionSequence::end(const G4Track* track) { + m_end(track); + m_actors(&Geant4TrackingAction::end,track); +} + +/// Standard constructor +Geant4TrackingAction::Geant4TrackingAction(Geant4Context* context, const std::string& name) +: Geant4Action(context,name) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4TrackingAction::~Geant4TrackingAction() { + InstanceCount::decrement(this); +} + +/// Pre-track action callback +void Geant4TrackingAction::begin(const G4Track* ) { +} + +/// Post-track action callback +void Geant4TrackingAction::end(const G4Track* ) { +} + +/// Get the valid Geant4 tarck information +Geant4TrackInformation* Geant4TrackingAction::trackInfo(G4Track* track) const { + if ( track ) { + Geant4TrackInformation* gau = 0; + G4VUserTrackInformation* g4 = track->GetUserInformation(); + if ( 0 == g4 ) { + gau = new Geant4TrackInformation(); + track->SetUserInformation(gau); + return gau; // RETURN + } + gau = fast_cast<Geant4TrackInformation*>(g4); + if( !gau ) { + error("trackInfo: invalid cast to Geant4TrajckInformation"); + } + return gau ; + } + error("trackInfo: [Invalid G4Track]"); + return 0; +} + +/// Mark all children of the track to be stored +bool Geant4TrackingAction::storeChildren() const { + G4TrackVector* v = trackMgr()->GimmeSecondaries(); + if( v ) { // loop over all children + for(G4TrackVector::const_iterator i = v->begin(); i != v->end(); ++i) { + G4Track* t = *i ; + if ( t ) { + storeChild(trackInfo(t)); + } + } + return true; + } + return false; +} + +/// Mark a single child of the track to be stored +bool Geant4TrackingAction::storeChild(Geant4TrackInformation* info) const { + if ( 0 != info ) { + if ( !info->storeTrack() ) { + info->storeTrack(true); + } + return true; + } + return error(false,"storeChild: Geant4TrackInformation points to NULL!"); +} diff --git a/DDG4/src/Geant4TrackingPostAction.cpp b/DDG4/src/Geant4TrackingPostAction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26e0c71d1541baae8cbf6bc88e61409f2a681b50 --- /dev/null +++ b/DDG4/src/Geant4TrackingPostAction.cpp @@ -0,0 +1,91 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4TrackingPostAction.h" +#include "DDG4/Geant4TrackHandler.h" + +// Geant4 include files +#include "G4TrackingManager.hh" + +#include <algorithm> + +using namespace std; +using namespace DD4hep::Simulation; + +struct FindString { + const std::string& m_name; + FindString(const std::string& n) : m_name(n) {} + bool operator()(const std::string& n) const { return m_name == n; } + //template <class T> bool operator==(const std::pair<std::string,T>& cmp) const + //{ return cmp.first == m_name; } + //template <class T> bool operator==(const std::pair<T,std::string>& cmp) const + //{ return cmp.second == m_name; } +}; + +/// Standard constructor +Geant4TrackingPostAction::Geant4TrackingPostAction(Geant4Context* context, const std::string& name) +: Geant4TrackingAction(context,name) +{ + InstanceCount::increment(this); + declareProperty("IgnoredProcesses",m_ignoredProcs); + declareProperty("RequiredProcesses",m_requiredProcs); +} + +/// Default destructor +Geant4TrackingPostAction::~Geant4TrackingPostAction() { + InstanceCount::decrement(this); +} + +/// Begin-of-tracking callback +void Geant4TrackingPostAction::begin(const G4Track* track) { + + // Is the track valid? Is tracking manager valid? + // Does trajectory already exist? + if( 0 == track || 0 == trackMgr() || 0 != trackMgr()->GimmeTrajectory() ) + return; + trackMgr()->SetStoreTrajectory(true); + // create GaussTrajectory and inform Tracking Manager + G4VTrajectory* tr = m_context->createTrajectory(track); + trackMgr()->SetTrajectory(tr); +} + +/// End-of-tracking callback +void Geant4TrackingPostAction::end(const G4Track* tr) { + if ( 0 == tr ) + return; + else if ( 0 == trackMgr() ) + return; + + Geant4TrackHandler track(tr); + //Geant4TrackInformation* info = track.info<Geant4TrackInformation>(); + const string& proc = track.creatorProcess()->GetProcessName(); + StringV::const_iterator trIt = find_if(m_ignoredProcs.begin(),m_ignoredProcs.end(),FindString(proc)); + if ( trIt != m_ignoredProcs.end() ) { + warning("Particles created by processes of type %s are not kept!",(*trIt).c_str()); + return; + } + trIt = find_if(m_requiredProcs.begin(),m_requiredProcs.end(),FindString(proc)); + if ( trIt != m_requiredProcs.end() ) { + saveTrack(track); + return; + } + + if ( m_storeMarkedTracks ) { + } + + +} + +void Geant4TrackingPostAction::saveTrack(const G4Track* track) { + if ( 0 != track ) { + } +} + diff --git a/DDG4/src/Geant4TrackingPreAction.cpp b/DDG4/src/Geant4TrackingPreAction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..97cf644d4e5b4e1e5b3fe592c2f03b39a06f4bac --- /dev/null +++ b/DDG4/src/Geant4TrackingPreAction.cpp @@ -0,0 +1,44 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDG4/Geant4TrackingPreAction.h" +// Geant4 include files +#include "G4TrackingManager.hh" + +using namespace DD4hep::Simulation; + +/// Standard constructor +Geant4TrackingPreAction::Geant4TrackingPreAction(Geant4Context* context, const std::string& name) +: Geant4TrackingAction(context,name) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Geant4TrackingPreAction::~Geant4TrackingPreAction() { + InstanceCount::decrement(this); +} + +/// Begin-of-tracking callback +void Geant4TrackingPreAction::begin(const G4Track* track) { + // Is the track valid? Is tracking manager valid? + // Does trajectory already exist? + if( 0 == track || 0 == trackMgr() || 0 != trackMgr()->GimmeTrajectory() ) + return; + trackMgr()->SetStoreTrajectory(true); + // create GaussTrajectory and inform Tracking Manager + G4VTrajectory* tr = m_context->createTrajectory(track); + trackMgr()->SetTrajectory(tr); +} + +/// End-of-tracking callback +void Geant4TrackingPreAction::end(const G4Track* /* track */) { +} diff --git a/DDG4/src/Geant4VolumeManager.cpp b/DDG4/src/Geant4VolumeManager.cpp index 53cdbd35daba2412b912c231991e73790a17a748..a473ef1087c44018eb8338d95bafd6b094cbcc5c 100644 --- a/DDG4/src/Geant4VolumeManager.cpp +++ b/DDG4/src/Geant4VolumeManager.cpp @@ -93,17 +93,16 @@ namespace { chain.pop_back(); } - void add_entry(SensitiveDetector sd, const TGeoNode* n, const PlacedVolume::VolIDs& ids, const Chain& nodes) { + void add_entry(SensitiveDetector sd, const TGeoNode* /* n */, const PlacedVolume::VolIDs& ids, const Chain& nodes) { Readout ro = sd.readout(); IDDescriptor iddesc = ro.idSpec(); VolumeID code = iddesc.encode(ids); if ( m_entries.find(code) == m_entries.end() ) { - PlacedVolume place = Ref_t(n); Geant4Mapping::PlacementPath path; path.reserve(nodes.size()); for(Chain::const_reverse_iterator i=nodes.rbegin(); i != nodes.rend(); ++i) { - const TGeoNode* n = *i; - PlacementMap::const_iterator g4pit = m_geo.g4Placements.find(n); + const TGeoNode* node = *i; + PlacementMap::const_iterator g4pit = m_geo.g4Placements.find(node); if ( g4pit != m_geo.g4Placements.end() ) { path.push_back((*g4pit).second); } diff --git a/DDG4/src/Geant4XMLSetup.cpp b/DDG4/src/Geant4XMLSetup.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a1fe3191a6ed392f2317c480ee2eb0c02d4057e --- /dev/null +++ b/DDG4/src/Geant4XMLSetup.cpp @@ -0,0 +1,380 @@ +// $Id: Geant4Setup.cpp 578 2013-05-17 22:33:09Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +// Framework include files +#include "DD4hep/Handle.h" +#include "DD4hep/Printout.h" +#include "XML/Conversions.h" +#include "XML/XMLElements.h" +#include "DD4hep/DetFactoryHelper.h" +#include "DDG4/Factories.h" +#include "DDG4/Geant4Converter.h" +#include "DDG4/Geant4Config.h" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Simulation; +typedef DD4hep::Geometry::LCDD lcdd_t; + +namespace DD4hep { + + struct XMLSetup; + struct ActionSequence; + using namespace DD4hep::Simulation; + using namespace DD4hep::Simulation::Setup; + + template <typename TYPE, typename PTR> TYPE* _action(PTR* in) { + return dynamic_cast<TYPE*>(in); + } + template <typename T> static void _setAttributes(const T& handle, xml_h& e) { + XML::Handle_t props(e); + // Now we set the object properties + vector<XML::Attribute> attrs = props.attributes(); + for(vector<XML::Attribute>::iterator i=attrs.begin(); i!=attrs.end(); ++i) { + XML::Attribute a = *i; + handle[props.attr_name(a)].str(props.attr<string>(a)); + } + } + template <typename T> static void _setProperties(const T& handle, xml_h& e) { + xml_comp_t action(e); + // Now we set the object properties + XML::Handle_t props = action.child(_Unicode(properties),false); + if ( props ) { + _setAttributes(handle, props); + } + } + static Action _convertSensitive(LCDD& lcdd, xml_h e, const string& detector) { + xml_comp_t action(e); + Kernel& kernel = Kernel::access(lcdd); + TypeName tn = TypeName::split(action.attr<string>(_U(name))); + // Create the object using the factory method + Sensitive handle(kernel,action.attr<string>(_U(name)),detector); + _setProperties(Action(handle.get()),e); + for(xml_coll_t f(e,_Unicode(filter)); f; ++f) { + string nam = f.attr<string>(_U(name)); + Filter filter(kernel.globalFilter(nam,false)); + handle->adopt(filter); + } + cout << "Added Sensitive " << tn.second << " of type " << tn.first << endl; + return Action(handle); + } + static Action _convertAction(LCDD& lcdd, xml_h e) { + xml_comp_t action(e); + Kernel& kernel = Kernel::access(lcdd); + TypeName tn = TypeName::split(action.attr<string>(_U(name))); + // Create the object using the factory method + Action handle(kernel,action.attr<string>(_U(name))); + _setProperties(handle,e); + cout << "Added Action " << tn.second << " of type " << tn.first << endl; + return handle; + } + enum { SENSITIVE, ACTION, FILTER }; + Action _createAction(LCDD& lcdd, xml_h a, const std::string& seqType, int what) { + string nam = a.attr<string>(_U(name)); + TypeName typ = TypeName::split(nam); + Kernel& kernel = Kernel::access(lcdd); + Action action((what==FILTER) ? (Geant4Action*)kernel.globalFilter(typ.second,false) + : (what==ACTION) ? kernel.globalAction(typ.second,false) + : (what==FILTER) ? kernel.globalAction(typ.second,false) + : 0); + // Create the object using the factory method + if ( !action ) { + action = (what == SENSITIVE) ? Action(_convertSensitive(lcdd, a, seqType)) + : (what==ACTION) ? _convertAction(lcdd, a) + : (what==FILTER) ? _convertAction(lcdd, a) + : Action(); + if ( !action ) { + throw runtime_error(format("Geant4ActionSequence","DDG4: The action '%s'" + " cannot be created. [Action-Missing]",nam.c_str())); + } + } + return action; + } + + /** Convert Geant4Action objects + * <actions> + * <action name="Geant4PostTrackingAction/PostTrackAction" + * <properties + * NAME1="Value1" + * NAME2="Value2" /> + * </action> + * </actions> + */ + template <> void Converter<Action>::operator()(xml_h e) const { + Action a = _convertAction(lcdd, e); + Kernel::access(lcdd).registerGlobalAction(a); + } + + /** Convert Sensitive detector filters + * <filters> + * <filter name="GeantinoRejector"/> + * <filter name="EnergyDepositMinimumCut"> + * <properties cut="10*MeV"/> + * </filter> + * </filters> + */ + template <> void Converter<Filter>::operator()(xml_h e) const { + Action a = _convertAction(lcdd, e); + Kernel::access(lcdd).registerGlobalFilter(a); + } + + /** Convert Geant4Phase objects + * <phases> + * <phase name="Geant4PostTrackingPhase/PostTrackPhase" + * <properties + * NAME1="Value1" + * NAME2="Value2" /> + * </phase> + * </phases> + */ + template <> void Converter<Phase>::operator()(xml_h e) const { + xml_comp_t x_phase(e); + Kernel& kernel = Kernel::access(lcdd); + string nam = x_phase.attr<string>(_U(type)); + typedef Geant4ActionPhase PH; + Phase p; + + if ( nam == "RunAction/begin" ) + kernel.runAction().callAtBegin((p=kernel.addPhase<const G4Run*>(nam)).get(), + &PH::call<const G4Run*>); + else if ( nam == "RunAction/end" ) + kernel.runAction().callAtEnd((p=kernel.addPhase<const G4Run*>(nam)).get(), + &PH::call<const G4Run*>); + else if ( nam == "EventAction/begin" ) + kernel.eventAction().callAtBegin((p=kernel.addPhase<const G4Event*>(nam)).get(), + &PH::call<const G4Event*>); + else if ( nam == "EventAction/end" ) + kernel.eventAction().callAtEnd((p=kernel.addPhase<const G4Event*>(nam)).get(), + &PH::call<const G4Event*>); + else if ( nam == "TrackingAction/begin" ) + kernel.trackingAction().callAtBegin((p=kernel.addPhase<const G4Track*>(nam)).get(), + &PH::call<const G4Track*>); + else if ( nam == "TrackingAction/end" ) + kernel.trackingAction().callAtEnd((p=kernel.addPhase<const G4Track*>(nam,false)).get(), + &PH::call<const G4Track*>); + else if ( nam == "StackingAction/newStage" ) + kernel.stackingAction().callAtNewStage((p=kernel.addPhase<void>(nam,false)).get(),&PH::call); + else if ( nam == "StackingAction/prepare" ) + kernel.stackingAction().callAtPrepare((p=kernel.addPhase<void>(nam,false)).get(),&PH::call); + else if ( nam == "SteppingAction" ) + kernel.steppingAction().call((p=kernel.addPhase<const G4Step*>(nam)).get(), + &PH::call<const G4Step*,G4SteppingManager*>); + else if ( nam == "GeneratorAction/primaries" ) + kernel.generatorAction().call((p=kernel.addPhase<G4Event*>(nam)).get(), + &PH::call<G4Event*>); + else { + TypeName tn = TypeName::split(nam); + DetElement det = lcdd.detector(tn.first); + if ( !det.isValid() ) { + throw runtime_error(format("Phase","DDG4: The phase '%s' of type SensitiveSeq" + " cannot be attached to a non-existing detector" + " [Detector-Missing]",nam.c_str())); + } + + Geometry::SensitiveDetector sd = lcdd.sensitiveDetector(tn.first); + if ( !sd.isValid() ) { + throw runtime_error(format("Phase","DDG4: The phase '%s' of type SensitiveSeq" + " cannot be attached to a non-existing sensitive detector" + " [Sensitive-Missing]",nam.c_str())); + } + SensitiveSeq sdSeq = SensitiveSeq(kernel,tn.first); + if ( tn.second == "begin" ) + sdSeq->callAtBegin((p=kernel.addPhase<G4HCofThisEvent*>(tn.second)).get(), + &PH::call<G4HCofThisEvent*>); + else if ( tn.second == "end" ) + sdSeq->callAtEnd((p=kernel.addPhase<G4HCofThisEvent*>(tn.second)).get(), + &PH::call<G4HCofThisEvent*>); + else if ( tn.second == "clear" ) + sdSeq->callAtClear((p=kernel.addPhase<G4HCofThisEvent*>(tn.second)).get(), + &PH::call<G4HCofThisEvent*>); + else if ( tn.second == "process" ) + sdSeq->callAtProcess((p=kernel.addPhase<G4Step*>(tn.second)).get(), + &PH::call<G4Step*,G4TouchableHistory*>); + else + throw runtime_error(format("Phase","DDG4: The phase '%s' of type SensitiveSeq" + " cannot be attached to the call '%s'." + " [Callback-Missing]",tn.first.c_str(), tn.second.c_str())); + } + } + + /** Convert Action sequences into objects + * <sequences> + * <sequence name="Geant4EventActionSequence/EventAction" + * <member name="" type="Geant4TrackerEventMonitor/TrackerEvtAction"/> + * </sequence> + * <sequence name="Geant4SensdetActionSequence/SiVertexBarrel" + * <member type="Geant4TrackerSensitiveMonitor/TrackerHitMonitor"> + * <properties + * NAME1="Value1" + * NAME2="Value2" /> + * </member> + * </sequence> + * </sequences> + */ + template <> void Converter<ActionSequence>::operator()(xml_h e) const { + xml_comp_t seq(e); + SensitiveSeq sdSeq; + string seqNam; + TypeName seqType; + int what = ACTION; + Kernel& kernel = Kernel::access(lcdd); + + if ( seq.hasAttr(_U(sd)) ) { + seqNam = seq.attr<string>(_U(type))+"/"+seq.attr<string>(_U(sd)); + seqType = TypeName::split(seqNam); + sdSeq = SensitiveSeq(kernel,seqNam); + what = SENSITIVE; + } + else { + seqNam = seq.attr<string>(_U(name)); + seqType = TypeName::split(seqNam); + } + cout << "Add Sequence " << seqType.second << " of type " + << seqType.first << endl; + + if ( seqType.second == "PhysicsList" ) { + PhysicsActionSeq pl(&kernel.physicsList()); + PropertyManager& m = kernel.physicsList().properties(); + m.dump(); + _setAttributes(pl,e); + m.dump(); + } + + for(xml_coll_t a(seq,_Unicode(action)); a; ++a) { + string nam = a.attr<string>(_U(name)); + Action action(_createAction(lcdd,a,seqType.second,what)); + if ( seqType.second == "RunAction" ) + kernel.runAction().adopt(_action<RunAction::handled_type>(action.get())); + else if ( seqType.second == "EventAction" ) + kernel.eventAction().adopt(_action<EventAction::handled_type>(action.get())); + else if ( seqType.second == "GeneratorAction" ) + kernel.generatorAction().adopt(_action<GenAction::handled_type>(action.get())); + else if ( seqType.second == "TrackingAction" ) + kernel.trackingAction().adopt(_action<TrackAction::handled_type>(action.get())); + else if ( seqType.second == "StackingAction" ) + kernel.stackingAction().adopt(_action<StackAction::handled_type>(action.get())); + else if ( seqType.second == "SteppingAction" ) + kernel.steppingAction().adopt(_action<StepAction::handled_type>(action.get())); + else if ( seqType.second == "PhysicsList" ) + kernel.physicsList().adopt(_action<PhysicsList::handled_type>(action.get())); + else if ( sdSeq.get() ) + sdSeq->adopt(_action<Sensitive::handled_type>(action.get())); + else { + throw runtime_error(format("ActionSequence","DDG4: The action '%s'" + " cannot be attached to any sequence '%s'." + " [Sequence-Missing]",nam.c_str(), seqNam.c_str())); + } + cout << "Sequence: " << seqType.second << " Added filter: " << action->name() << endl; + } + if ( what == SENSITIVE ) { + for(xml_coll_t a(seq,_Unicode(filter)); a; ++a) { + string nam = a.attr<string>(_U(name)); + Action action(_createAction(lcdd,a,"",FILTER)); + cout << "Sequence: " << seqType.second << " Added filter: " << action->name() << endl; + if ( sdSeq.get() ) + sdSeq->adopt(_action<Filter::handled_type>(action.get())); + else { + throw runtime_error(format("ActionSequence","DDG4: The action '%s'" + " cannot be attached to any sequence '%s'." + " [Sequence-Missing]",nam.c_str(), seqNam.c_str())); + } + } + } + } + + /** Convert PhysicsList objects + * <physicslist> + * <processes> + * <particle name="'e-'"> + * <process name="G4eMultipleScattering" ordAtRestDoIt="-1" ordAlongSteptDoIt="1" ordPostStepDoIt="1"/> + * <process name="G4eIonisation" ordAtRestDoIt="-1" ordAlongSteptDoIt="2" ordPostStepDoIt="2"/> + * </particle> + * </processes> + * </physicslist> + */ + template <> void Converter<Geant4PhysicsList::ParticleProcesses>::operator()(xml_h e) const { + xml_comp_t part(e); + string part_name = part.nameStr(); + Geant4PhysicsList::ParticleProcesses& procs = + _object<Geant4PhysicsList>().processes(part_name); + for(xml_coll_t q(part,_Unicode(process)); q; ++q) { + xml_comp_t proc(q); + Geant4PhysicsList::Process p; + p.name = proc.nameStr(); + p.ordAtRestDoIt = proc.attr<int>(_Unicode(ordAtRestDoIt)); + p.ordAlongSteptDoIt = proc.attr<int>(_Unicode(ordAlongSteptDoIt)); + p.ordPostStepDoIt = proc.attr<int>(_Unicode(ordPostStepDoIt)); + procs.push_back(p); + printout(INFO,"+++ Converter<ParticleProcesses>","+++ Particle:%s add process %s %d %d %d", + part_name.c_str(),p.name.c_str(),p.ordAtRestDoIt,p.ordAlongSteptDoIt,p.ordPostStepDoIt); + } + } + + /** Convert PhysicsList objects: Particle constructors + * <physicslist> + * <particles> + * <construct name="G4Electron"/> + * <construct name="G4Gamma"/> + * <construct name="G4BosonConstructor"/> + * <construct name="G4LeptonConstructor"/> + * <construct name="G4BaryonConstructor"/> + * </particles> + * </physicslist> + */ + template <> void Converter<Geant4PhysicsList::ParticleConstructor>::operator()(xml_h e) const { + Geant4PhysicsList::ParticleConstructors& parts = _object<Geant4PhysicsList>().particles(); + xml_comp_t part(e); + string n = part.nameStr(); + parts.push_back(n); + printout(INFO,"+++ Converter<ParticleConstructor>","Add particle constructor '%s'",n.c_str()); + } + + /** Convert PhysicsList objects: Physics constructors + * <physicslist> + * <physics> + * <construct name="G4EmStandardPhysics"/> + * <construct name="HadronPhysicsQGSP"/> + * </physics> + * </physicslist> + */ + template <> void Converter<Geant4PhysicsList::PhysicsConstructor>::operator()(xml_h e) const { + Geant4PhysicsList::PhysicsConstructors& parts = _object<Geant4PhysicsList>().physics(); + xml_comp_t part(e); + string n = part.nameStr(); + parts.push_back(n); + printout(INFO,"+++ Converter<PhysicsConstructor>","Add physics constructor '%s'",n.c_str()); + } + + template <> void Converter<PhysicsList>::operator()(xml_h e) const { + string name = e.attr<string>(_U(name)); + Kernel& kernel = Kernel::access(lcdd); + PhysicsList handle(kernel,name); + _setAttributes(handle,e); + xml_coll_t(e,_Unicode(particles)).for_each(_Unicode(construct),Converter<Geant4PhysicsList::ParticleConstructor>(lcdd,handle.get())); + xml_coll_t(e,_Unicode(processes)).for_each(_Unicode(particle),Converter<Geant4PhysicsList::ParticleProcesses>(lcdd,handle.get())); + xml_coll_t(e,_Unicode(physics)).for_each(_Unicode(construct),Converter<Geant4PhysicsList::PhysicsConstructor>(lcdd,handle.get())); + kernel.physicsList().adopt(handle); + } + + template <> void Converter<XMLSetup>::operator()(xml_h seq) const { + xml_elt_t compact(seq); + // First execute the basic setup from the plugins module + ROOT::Reflex::PluginService::Create<TNamed*>("geant4_xml_setup",&lcdd,&seq); + // Now deal with the new stuff..... + xml_coll_t(compact,_Unicode(actions) ).for_each(_Unicode(action),Converter<Action>(lcdd,param)); + xml_coll_t(compact,_Unicode(filters) ).for_each(_Unicode(filter),Converter<Filter>(lcdd,param)); + xml_coll_t(compact,_Unicode(sequences) ).for_each(_Unicode(sequence),Converter<ActionSequence>(lcdd,param)); + xml_coll_t(compact,_Unicode(phases) ).for_each(_Unicode(phase),Converter<Phase>(lcdd,param)); + xml_coll_t(compact,_Unicode(physicslist)).for_each(Converter<PhysicsList>(lcdd,param)); + } +} +static long setup_Geant4(lcdd_t& lcdd, const xml_h& element) { + (Converter<XMLSetup>(lcdd))(element); + return 1; +} +DECLARE_XML_DOC_READER(geant4_setup,setup_Geant4)