diff --git a/DDG4/examples/CLICSidSimu.py b/DDG4/examples/CLICSidSimu.py index 497fc845dd26bfd874707fd6d0d753f07cc4ca98..afbd69536b8b39e9644dfe5313dc7d542729e768 100644 --- a/DDG4/examples/CLICSidSimu.py +++ b/DDG4/examples/CLICSidSimu.py @@ -7,35 +7,23 @@ from SystemOfUnits import * # """ - DD4hep example setup using the python configuration + DD4hep simulation example setup using the python configuration @author M.Frank @version 1.0 """ def run(): + kernel = DDG4.Kernel() install_dir = os.environ['DD4hepINSTALL'] example_dir = install_dir+'/examples/DDG4/examples'; - kernel = DDG4.Kernel() - kernel.UI = "UI" kernel.loadGeometry("file:"+install_dir+"/examples/CLICSiD/compact/compact.xml") kernel.loadXML("file:"+example_dir+"/DDG4_field.xml") - lcdd = kernel.lcdd() - print '+++ List of sensitive detectors:' - for i in lcdd.detectors(): - o = DDG4.DetElement(i.second) - sd = lcdd.sensitiveDetector(o.name()) - if sd.isValid(): - print '+++ %-32s type:%s'%(o.name(), sd.type(), ) - + simple = DDG4.Simple(kernel) + simple.printDetectors() # Configure UI - ui = DDG4.Action(kernel,"Geant4UIManager/UI") - ui.HaveVIS = True - ui.HaveUI = True - ui.SessionType = 'csh' - kernel.registerGlobalAction(ui) - + simple.setupCshUI() # Configure Run actions run1 = DDG4.RunAction(kernel,'Geant4TestRunAction/RunInit') @@ -63,38 +51,27 @@ def run(): kernel.eventAction().add(evt1) kernel.eventAction().add(evt2) + """ - trk = DDG4.Action(kernel,"Geant4TrackPersistency/MonteCarloTruthHandler") - kernel.registerGlobalAction(trk) - trk.release() mc = DDG4.Action(kernel,"Geant4MonteCarloRecordManager/MonteCarloRecordManager") kernel.registerGlobalAction(mc) mc.release() """ # Configure I/O - evt_root = DDG4.EventAction(kernel,'Geant4Output2ROOT/RootOutput') - evt_root.Control = True - evt_root.Output = "CLICSiD_"+time.strftime("%Y-%m-%d_%H-%M")+".root" - evt_root.enableUI() - kernel.eventAction().add(evt_root) - - evt_lcio = DDG4.EventAction(kernel,'Geant4Output2LCIO/LcioOutput') - evt_lcio.Output = "CLICSiD_"+time.strftime("%Y-%m-%d_%H-%M") - evt_lcio.enableUI() - kernel.eventAction().add(evt_lcio) + evt_root = simple.setupROOTOutput('RootOutput','CLICSiD_'+time.strftime('%Y-%m-%d_%H-%M')) + evt_lcio = simple.setupLCIOOutput('LcioOutput','CLICSiD_'+time.strftime('%Y-%m-%d_%H-%M')) gen = DDG4.GeneratorAction(kernel,"Geant4TestGeneratorAction/Generate") kernel.generatorAction().add(gen) # Setup particle gun - gun = DDG4.GeneratorAction(kernel,"Geant4ParticleGun/Gun") - gun.energy = 100*GeV - gun.particle = 'pi-' - gun.multiplicity = 1 - gun.position = (0*mm,0*mm,0*cm) - gun.isotrop = True - gun.enableUI() - kernel.generatorAction().add(gun) + gun = simple.setupGun('Gun','pi-',100*GeV,True) + + trk = DDG4.GeneratorAction(kernel,"Geant4ParticleHandler/ParticleHandler") + kernel.generatorAction().add(trk) + trk.enableUI() + + """ rdr = DDG4.GeneratorAction(kernel,"LcioGeneratorAction/Reader") rdr.zSpread = 0.0 @@ -120,83 +97,31 @@ def run(): kernel.registerGlobalFilter(f4) # First the tracking detectors - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/SiVertexBarrel') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleTrackerAction/SiVertexBarrelHandler','SiVertexBarrel') - seq.add(act) + seq,act = simple.setupTracker('SiVertexBarrel') seq.add(f1) #seq.add(f4) act.add(f1) - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/SiVertexEndcap') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleTrackerAction/SiVertexEndcapHandler','SiVertexEndcap') - seq.add(act) - seq.add(f1) - #seq.add(f4) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/SiTrackerBarrel') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleTrackerAction/SiTrackerBarrelHandler','SiTrackerBarrel') - seq.add(act) + seq,act = simple.setupTracker('SiVertexEndcap') seq.add(f1) #seq.add(f4) - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/SiTrackerEndcap') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleTrackerAction/SiTrackerEndcapHandler','SiTrackerEndcap') - #act.OutputLevel = Output.INFO - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/SiTrackerForward') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleTrackerAction/SiTrackerForwardHandler','SiTrackerForward') - seq.add(act) - + seq,act = simple.setupTracker('SiTrackerBarrel') + seq,act = simple.setupTracker('SiTrackerEndcap') + seq,act = simple.setupTracker('SiTrackerForward') # Now the calorimeters - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/EcalBarrel') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/EcalBarrelHandler','EcalBarrel') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/EcalEndcap') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/EcalEndCapHandler','EcalEndcap') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/HcalBarrel') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/HcalBarrelHandler','HcalBarrel') - act.adoptFilter(kernel.globalFilter('OpticalPhotonRejector')) - seq.add(act) - - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/HcalBarrelHandler','HcalBarrel') - act.adoptFilter(kernel.globalFilter('OpticalPhotonSelector')) - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/HcalEndcap') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/HcalEndcapHandler','HcalEndcap') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/HcalPlug') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/HcalPlugHandler','HcalPlug') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/MuonBarrel') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/MuonBarrelHandler','MuonBarrel') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/MuonEndcap') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/MuonEndcapHandler','MuonEndcap') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/LumiCal') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/LumiCalHandler','LumiCal') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/BeamCal') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/BeamCalHandler','BeamCal') - seq.add(act) + seq,act = simple.setupCalorimeter('EcalBarrel') + seq,act = simple.setupCalorimeter('EcalEndcap') + seq,act = simple.setupCalorimeter('HcalBarrel') + seq,act = simple.setupCalorimeter('HcalEndcap') + seq,act = simple.setupCalorimeter('HcalPlug') + seq,act = simple.setupCalorimeter('MuonBarrel') + seq,act = simple.setupCalorimeter('MuonEndcap') + seq,act = simple.setupCalorimeter('LumiCal') + seq,act = simple.setupCalorimeter('BeamCal') # Now build the physics list: - phys = kernel.physicsList() - phys.extends = 'FTFP_BERT' - #phys.transportation = True - phys.decays = True - phys.enableUI() - + phys = simple.setupPhysics('QGSP_BERT') ph = DDG4.PhysicsList(kernel,'Geant4PhysicsList/Myphysics') ph.addParticleConstructor('G4BosonConstructor') ph.addParticleConstructor('G4LeptonConstructor') diff --git a/DDG4/examples/CLICSidSimuLCIO.py b/DDG4/examples/CLICSidSimuLCIO.py index 1d4f6bc6254150d67e0a681409a41a291403a91a..f3ad1b4e89441fcbe61719b407ca1c0b514a23ef 100644 --- a/DDG4/examples/CLICSidSimuLCIO.py +++ b/DDG4/examples/CLICSidSimuLCIO.py @@ -7,35 +7,23 @@ from SystemOfUnits import * # """ - DD4hep example setup using the python configuration + DD4hep simulation example setup using the python configuration @author M.Frank @version 1.0 """ def run(): + kernel = DDG4.Kernel() install_dir = os.environ['DD4hepINSTALL'] example_dir = install_dir+'/examples/DDG4/examples'; - kernel = DDG4.Kernel() - kernel.UI = "UI" kernel.loadGeometry("file:"+install_dir+"/examples/CLICSiD/compact/compact.xml") kernel.loadXML("file:"+example_dir+"/DDG4_field.xml") - lcdd = kernel.lcdd() - print '+++ List of sensitive detectors:' - for i in lcdd.detectors(): - o = DDG4.DetElement(i.second) - sd = lcdd.sensitiveDetector(o.name()) - if sd.isValid(): - print '+++ %-32s type:%s'%(o.name(), sd.type(), ) - + simple = DDG4.Simple(kernel,tracker='LcioTestTrackerAction') + simple.printDetectors() # Configure UI - ui = DDG4.Action(kernel,"Geant4UIManager/UI") - ui.HaveVIS = True - ui.HaveUI = True - ui.SessionType = 'csh' - kernel.registerGlobalAction(ui) - + simple.setupCshUI() # Configure Run actions run1 = DDG4.RunAction(kernel,'Geant4TestRunAction/RunInit') @@ -72,24 +60,14 @@ def run(): mc.release() """ # Configure I/O - evt_lcio = DDG4.EventAction(kernel,'Geant4Output2LCIO/LcioOutput') - evt_lcio.Control = True - evt_lcio.Output = "CLICSiD_"+time.strftime("%Y-%m-%d_%H-%M") - evt_lcio.enableUI() - kernel.eventAction().add(evt_lcio) + evt_lcio = simple.setupLCIOOutput('LcioOutput','CLICSiD_'+time.strftime('%Y-%m-%d_%H-%M')) gen = DDG4.GeneratorAction(kernel,"Geant4TestGeneratorAction/Generate") kernel.generatorAction().add(gen) # Setup particle gun - gun = DDG4.GeneratorAction(kernel,"Geant4ParticleGun/Gun") - gun.energy = 100*GeV - gun.particle = 'pi-' - gun.multiplicity = 1 - gun.position = (0*mm,0*mm,0*cm) - gun.isotrop = True - gun.enableUI() - kernel.generatorAction().add(gun) + gun = simple.setupGun('Gun','pi-',100*GeV,True) + """ rdr = DDG4.GeneratorAction(kernel,"LcioGeneratorAction/Reader") rdr.zSpread = 0.0 @@ -115,83 +93,31 @@ def run(): kernel.registerGlobalFilter(f4) # First the tracking detectors - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/SiVertexBarrel') - act = DDG4.SensitiveAction(kernel,'LcioTestTrackerAction/SiVertexBarrelHandler','SiVertexBarrel') - seq.add(act) + seq,act = simple.setupTracker('SiVertexBarrel') seq.add(f1) #seq.add(f4) act.add(f1) - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/SiVertexEndcap') - act = DDG4.SensitiveAction(kernel,'LcioTestTrackerAction/SiVertexEndcapHandler','SiVertexEndcap') - seq.add(act) - seq.add(f1) - #seq.add(f4) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/SiTrackerBarrel') - act = DDG4.SensitiveAction(kernel,'LcioTestTrackerAction/SiTrackerBarrelHandler','SiTrackerBarrel') - seq.add(act) + seq,act = simple.setupTracker('SiVertexEndcap') seq.add(f1) #seq.add(f4) - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/SiTrackerEndcap') - act = DDG4.SensitiveAction(kernel,'LcioTestTrackerAction/SiTrackerEndcapHandler','SiTrackerEndcap') - #act.OutputLevel = Output.INFO - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/SiTrackerForward') - act = DDG4.SensitiveAction(kernel,'LcioTestTrackerAction/SiTrackerForwardHandler','SiTrackerForward') - seq.add(act) - + seq,act = simple.setupTracker('SiTrackerBarrel') + seq,act = simple.setupTracker('SiTrackerEndcap') + seq,act = simple.setupTracker('SiTrackerForward') # Now the calorimeters - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/EcalBarrel') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/EcalBarrelHandler','EcalBarrel') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/EcalEndcap') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/EcalEndCapHandler','EcalEndcap') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/HcalBarrel') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/HcalBarrelHandler','HcalBarrel') - act.adoptFilter(kernel.globalFilter('OpticalPhotonRejector')) - seq.add(act) - - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/HcalBarrelHandler','HcalBarrel') - act.adoptFilter(kernel.globalFilter('OpticalPhotonSelector')) - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/HcalEndcap') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/HcalEndcapHandler','HcalEndcap') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/HcalPlug') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/HcalPlugHandler','HcalPlug') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/MuonBarrel') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/MuonBarrelHandler','MuonBarrel') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/MuonEndcap') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/MuonEndcapHandler','MuonEndcap') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/LumiCal') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/LumiCalHandler','LumiCal') - seq.add(act) - - seq = DDG4.SensitiveSequence(kernel,'Geant4SensDetActionSequence/BeamCal') - act = DDG4.SensitiveAction(kernel,'Geant4SimpleCalorimeterAction/BeamCalHandler','BeamCal') - seq.add(act) + seq,act = simple.setupCalorimeter('EcalBarrel') + seq,act = simple.setupCalorimeter('EcalEndcap') + seq,act = simple.setupCalorimeter('HcalBarrel') + seq,act = simple.setupCalorimeter('HcalEndcap') + seq,act = simple.setupCalorimeter('HcalPlug') + seq,act = simple.setupCalorimeter('MuonBarrel') + seq,act = simple.setupCalorimeter('MuonEndcap') + seq,act = simple.setupCalorimeter('LumiCal') + seq,act = simple.setupCalorimeter('BeamCal') # Now build the physics list: - phys = kernel.physicsList() - phys.extends = 'FTFP_BERT' - #phys.transportation = True - phys.decays = True - phys.enableUI() - + phys = simple.setupPhysics('QGSP_BERT') ph = DDG4.PhysicsList(kernel,'Geant4PhysicsList/Myphysics') ph.addParticleConstructor('G4BosonConstructor') ph.addParticleConstructor('G4LeptonConstructor') diff --git a/DDG4/include/DDG4/Geant4ParticleHandler.h b/DDG4/include/DDG4/Geant4ParticleHandler.h new file mode 100644 index 0000000000000000000000000000000000000000..14c1f88018e41c710f7b158dfe92316d06291f3d --- /dev/null +++ b/DDG4/include/DDG4/Geant4ParticleHandler.h @@ -0,0 +1,103 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GEANT4PARTICLEHANDLER_H +#define DD4HEP_DDG4_GEANT4PARTICLEHANDLER_H + +// Framework include files +#include "DDG4/Geant4Action.h" +#include "DDG4/Geant4EventAction.h" +#include "DDG4/Geant4GeneratorAction.h" +#include "DDG4/Geant4MonteCarloTruth.h" +#include "Math/PxPyPzE4D.h" +#include "G4VUserTrackInformation.hh" + +// C/C++ include files +#include <map> +#include <set> +#include <string> +#include <typeinfo> + +// Forward declarations +class G4Step; +class G4Track; +class G4Event; +class G4SteppingManager; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + // Forward declarations + + /** @class Geant4ParticleHandler Geant4ParticleHandler.h DDG4/Geant4ParticleHandler.h + * + * Default base class for all geant 4 actions and derivates thereof. + * + * @author M.Frank + * @version 1.0 + */ + class Geant4ParticleHandler : public Geant4GeneratorAction, public Geant4MonteCarloTruth + { + public: + typedef ROOT::Math::PxPyPzE4D<double> FourMomentum; + typedef std::map<int,void*> ParticleMap; + typedef std::map<int,std::set<int> > TrackIDTree; + typedef std::map<int,long> TrackReasons; + protected: + + /// Property: Steer printout at tracking action begin + bool m_printStartTracking; + /// Property: Steer printout at tracking action end + bool m_printEndTracking; + + public: + TrackIDTree m_trackIDTree; + TrackReasons m_trackReasons; + ParticleMap m_particleMap; + + public: + /// Standard constructor + Geant4ParticleHandler(Geant4Context* context, const std::string& nam); + /// Default destructor + virtual ~Geant4ParticleHandler(); + /// Access the Geant4 tracking manager. Only use between tracking pre- and post action + G4TrackingManager* trackMgr() const { return m_context.trackMgr(); } + /// Event generation action callback + virtual void operator()(G4Event* event); + /// User stepping callback + virtual void step(const G4Step* step, G4SteppingManager* mgr); + /// Pre-event action callback + virtual void beginEvent(const G4Event* event); + /// Post-event action callback + virtual void endEvent(const G4Event* event); + /// Pre-track action callback + virtual void begin(const G4Track* track); + /// Post-track action callback + virtual void end(const G4Track* track); + + /// Mark a Geant4 track to be kept for later MC truth analysis + virtual void mark(const G4Track* track); + /// Store a track + virtual void mark(const G4Track* track, bool created_hit); + /// Mark a Geant4 track of the step to be kept for later MC truth analysis + virtual void mark(const G4Step* step); + /// Store a track produced in a step to be kept for later MC truth analysis + virtual void mark(const G4Step* step, bool created_hit); + + }; + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4PARTICLEHANDLER_H diff --git a/DDG4/include/DDG4/Geant4SensDetAction.h b/DDG4/include/DDG4/Geant4SensDetAction.h index 06c5a2e518fe0672c6c9349d940b86aee0211e71..77674a7c12c2674aad156a751a3d95fd182978f6 100644 --- a/DDG4/include/DDG4/Geant4SensDetAction.h +++ b/DDG4/include/DDG4/Geant4SensDetAction.h @@ -92,6 +92,7 @@ namespace DD4hep { typedef Geometry::LCDD LCDD; typedef Geometry::Readout Readout; typedef Geometry::DetElement DetElement; + typedef Geometry::Segmentation Segmentation; typedef Geometry::SensitiveDetector SensitiveDetector; typedef Geant4StepHandler StepHandler; typedef Geant4HitCollection HitCollection; @@ -111,6 +112,8 @@ namespace DD4hep { SensitiveDetector m_sensitive; /// Reference to the readout structure Readout m_readout; + /// Reference to segmentation + Segmentation m_segmentation; /// The list of sensitive detector filter objects Actors<Geant4Filter> m_filters; @@ -210,6 +213,13 @@ namespace DD4hep { */ long long int volumeID(G4Step* step); + /// Returns the cellID of the sensitive volume corresponding to the step + /** The CellID is the VolumeID + the local coordinates of the sensitive area. + * Calculated by combining the VolIDS of the complete geometry path (Geant4TouchableHistory) + * from the current sensitive volume to the world volume + */ + long long int cellID(G4Step* step); + }; /** @class Geant4SensDetActionSequence Geant4SensDetAction.h DDG4/Geant4SensDetAction.h diff --git a/DDG4/include/DDG4/Geant4StepHandler.h b/DDG4/include/DDG4/Geant4StepHandler.h index fd774307afa4d61a49e2c82df9fbffc3fe07ecfe..57faa0354fb2b461397d85a8af7ed5cef1d046d1 100644 --- a/DDG4/include/DDG4/Geant4StepHandler.h +++ b/DDG4/include/DDG4/Geant4StepHandler.h @@ -64,10 +64,16 @@ namespace DD4hep { const G4ThreeVector& p = pre->GetPosition(); return Position(p.x(), p.y(), p.z()); } + const G4ThreeVector& prePosG4() const { + return pre->GetPosition(); + } Position postPos() const { const G4ThreeVector& p = post->GetPosition(); return Position(p.x(), p.y(), p.z()); } + const G4ThreeVector& postPosG4() const { + return post->GetPosition(); + } Momentum preMom() const { const G4ThreeVector& p = pre->GetMomentum(); return Momentum(p.x(), p.y(), p.z()); diff --git a/DDG4/include/DDG4/Geant4TrackHandler.h b/DDG4/include/DDG4/Geant4TrackHandler.h index de0dafd72493664957c48adf2703c566af5c6937..c5553631c7b095931a60112c30592627233631b5 100644 --- a/DDG4/include/DDG4/Geant4TrackHandler.h +++ b/DDG4/include/DDG4/Geant4TrackHandler.h @@ -93,6 +93,10 @@ namespace DD4hep { const std::string& name() const { return trackDef()->GetParticleName(); } + /// Track's particle type + const std::string& type() const { + return trackDef()->GetParticleType(); + } /// Track's position const G4ThreeVector& position() const { return track->GetPosition(); diff --git a/DDG4/lcio/LCIOConversions.cpp b/DDG4/lcio/LCIOConversions.cpp index fbeac3d3abb01110b8628e74e82d7445c0058802..05d4932cf662700945068c679faffc2a93460a87 100644 --- a/DDG4/lcio/LCIOConversions.cpp +++ b/DDG4/lcio/LCIOConversions.cpp @@ -17,8 +17,12 @@ // LCIO includes #include "IMPL/LCCollectionVec.h" +// +#include "IMPL/ClusterImpl.h" #include "IMPL/SimTrackerHitImpl.h" #include "IMPL/SimCalorimeterHitImpl.h" +#include "IMPL/MCParticleImpl.h" +// #include "UTIL/Operators.h" #include "UTIL/ILDConf.h" using namespace std; @@ -130,6 +134,19 @@ namespace DD4hep { return lc_coll; } + template <typename T> lcio::LCCollectionVec* moveEntries(Geant4HitCollection* coll, lcio::LCCollectionVec* lc_coll) { + size_t nhits = coll->GetSize(); + lc_coll->reserve(nhits); + for(size_t i=0; i<nhits; ++i) { + Geant4HitWrapper& wrap = coll->hit(i); + T* lc_hit = wrap; + wrap.release(); // Now we have ownership! + lc_coll->addElement(lc_hit); + } + coll->clear(); // Since the collection now only contains NULL pointers, better clear it! + return lc_coll; + } + /// Data conversion interface moving lcio::SimTrackerHitImpl objects from a Geant4HitCollection to a LCCollectionVec /** * This converter is to be used, when the sensitive detectors create fill collections @@ -148,19 +165,8 @@ namespace DD4hep { pair<VolMgr,Geant4HitCollection*>, lcio::SimTrackerHitImpl>::operator()(const arg_t& args) const { - Geant4HitCollection* coll = args.second; - lcio::LCCollectionVec* lc_coll = new lcio::LCCollectionVec(lcio::LCIO::SIMTRACKERHIT); - lc_coll->reserve(coll->GetSize()); - printout(DEBUG,"LCIOConversion", - "+++ Converting %s to LCCollectionVec(SIMTRACKERHIT)",coll->GetName().c_str()); - for(size_t i=0, nhits = coll->GetSize(); i<nhits; ++i) { - Geant4HitWrapper& wrap = coll->hit(i); - lcio::SimTrackerHitImpl* lc_hit = wrap; - wrap.release(); // Now we have ownership! - lc_coll->addElement(lc_hit); - } - coll->clear(); // Since the collection now only contains NULL pointers, better clear it! - return lc_coll; + lcio::LCCollectionVec* lc = new lcio::LCCollectionVec(lcio::LCIO::SIMTRACKERHIT); + return moveEntries<lcio::SimTrackerHitImpl>(args.second,lc); } /// Data conversion interface moving lcio::SimCalorimeterHitImpl objects from a Geant4HitCollection to a LCCollectionVec @@ -181,20 +187,38 @@ namespace DD4hep { pair<VolMgr,Geant4HitCollection*>, lcio::SimCalorimeterHitImpl>::operator()(const arg_t& args) const { - Geant4HitCollection* coll = args.second; - lcio::LCCollectionVec* lc_coll = new lcio::LCCollectionVec(lcio::LCIO::SIMCALORIMETERHIT); - lc_coll->setFlag(UTIL::make_bitset32(LCIO::CHBIT_LONG,LCIO::CHBIT_STEP)); - lc_coll->reserve(coll->GetSize()); - printout(DEBUG,"LCIOConversion", - "+++ Converting %s to LCCollectionVec(SIMCALORIMETERHIT)",coll->GetName().c_str()); - for(size_t i=0, nhits = coll->GetSize(); i<nhits; ++i) { - Geant4HitWrapper& wrap = coll->hit(i); - lcio::SimCalorimeterHitImpl* lc_hit = wrap; - wrap.release(); // Now we have ownership! - lc_coll->addElement(lc_hit); - } - coll->clear(); // Since the collection now only contains NULL pointers, better clear it! - return lc_coll; + output_t* lc = new lcio::LCCollectionVec(lcio::LCIO::SIMCALORIMETERHIT); + lc->setFlag(UTIL::make_bitset32(LCIO::CHBIT_LONG,LCIO::CHBIT_STEP)); + return moveEntries<tag_t>(args.second,lc); + } + + /// Data conversion interface moving lcio::ClusterImpl objects from a Geant4HitCollection to a LCCollectionVec + /** Same comments apply as for the data mover for lcio::SimCalorimeterHitImpl and lcio::SimTrackerHitImpl + * + * @author M.Frank + * @version 1.0 + */ + template <> lcio::LCCollectionVec* + Geant4DataConversion<lcio::LCCollectionVec, + pair<VolMgr,Geant4HitCollection*>, + lcio::ClusterImpl>::operator()(const arg_t& args) const + { + output_t* lc = new lcio::LCCollectionVec(lcio::LCIO::CLUSTER); + return moveEntries<tag_t>(args.second,lc); + } + /// Data conversion interface moving lcio::MCParticleImpl objects from a Geant4HitCollection to a LCCollectionVec + /** Same comments apply as for the data mover for lcio::SimCalorimeterHitImpl and lcio::SimTrackerHitImpl + * + * @author M.Frank + * @version 1.0 + */ + template <> lcio::LCCollectionVec* + Geant4DataConversion<lcio::LCCollectionVec, + pair<VolMgr,Geant4HitCollection*>, + lcio::MCParticleImpl>::operator()(const arg_t& args) const + { + output_t* lc = new lcio::LCCollectionVec(lcio::LCIO::MCPARTICLE); + return moveEntries<tag_t>(args.second,lc); } typedef pair<VolMgr,G4VHitsCollection*> RAW_CONVERSION_ARGS; @@ -209,6 +233,8 @@ namespace DD4hep { // Hit converters for standard LCIO objects DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,lcio::SimTrackerHitImpl) DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,lcio::SimCalorimeterHitImpl) + DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,lcio::ClusterImpl) + DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,lcio::MCParticleImpl) } // End namespace Simulation } // End namespace DD4hep diff --git a/DDG4/plugins/Geant4Factories.cpp b/DDG4/plugins/Geant4Factories.cpp index ae990432cd524fd05775ac76c46f6012043a33d5..70bfdccd17ae20b14f9468df5105d5bf4d1327df 100644 --- a/DDG4/plugins/Geant4Factories.cpp +++ b/DDG4/plugins/Geant4Factories.cpp @@ -46,6 +46,9 @@ DECLARE_GEANT4ACTION(Geant4TrackPersistency) #include "DDG4/Geant4MonteCarloRecordManager.h" DECLARE_GEANT4ACTION(Geant4MonteCarloRecordManager) +#include "DDG4/Geant4ParticleHandler.h" +DECLARE_GEANT4ACTION(Geant4ParticleHandler) + //============================= #include "DDG4/Geant4TrackingPreAction.h" DECLARE_GEANT4ACTION(Geant4TrackingPreAction) diff --git a/DDG4/plugins/Geant4SDActions.cpp b/DDG4/plugins/Geant4SDActions.cpp index 63a1425ac2cd16b027f984ee90f80aa0e47bdeb2..5633a393b2022000972c1a31396d35127da6e6bb 100644 --- a/DDG4/plugins/Geant4SDActions.cpp +++ b/DDG4/plugins/Geant4SDActions.cpp @@ -141,7 +141,7 @@ namespace DD4hep { Hit* hit = new Hit(h.trkID(), h.trkPdgID(), h.deposit(), h.track->GetGlobalTime()); if ( hit ) { HitContribution contrib = Hit::extractContribution(step); - hit->cellID = volumeID(step); + hit->cellID = cellID(step); hit->energyDeposit = contrib.deposit; hit->position = position; hit->momentum = direction; diff --git a/DDG4/python/DDG4.py b/DDG4/python/DDG4.py index 62c3b78031aa634046266769eb8ef6efacee49df..010d32afd81230031f795cb59bbeacacca416b4c 100644 --- a/DDG4/python/DDG4.py +++ b/DDG4/python/DDG4.py @@ -153,3 +153,79 @@ _props('PhysicsListActionSequenceHandle') _props('SensDetActionSequenceHandle') _props('Geant4PhysicsListActionSequence') + +""" +Helper object to perform stuff, which occurs very often. +I am sick of typing the same over and over again. + +@author M.Frank +@version 1.0 + +""" +class Simple: + def __init__(self, kernel,calo='Geant4SimpleCalorimeterAction',tracker='Geant4SimpleTrackerAction'): + kernel.UI = "UI" + kernel.printProperties() + self.kernel = kernel + self.calo = calo + self.tracker = tracker + def printDetectors(self): + lcdd = self.kernel.lcdd() + print '+++ List of sensitive detectors:' + for i in lcdd.detectors(): + o = DetElement(i.second) + sd = lcdd.sensitiveDetector(o.name()) + if sd.isValid(): + print '+++ %-32s type:%s'%(o.name(), sd.type(), ) + + def setupDetector(self,name,sensitive_type): + seq = SensitiveSequence(self.kernel,'Geant4SensDetActionSequence/'+name) + act = SensitiveAction(self.kernel,sensitive_type+'/'+name+'Handler',name) + seq.add(act) + return (seq,act) + + def setupCalorimeter(self,name,type=None): + if type is None: type = self.calo + return self.setupDetector(name,type) + + def setupTracker(self,name,type=None): + if type is None: type = self.tracker + return self.setupDetector(name,type) + + def setupPhysics(self,name): + phys = self.kernel.physicsList() + phys.extends = name + phys.decays = True + phys.enableUI() + phys.dump() + return phys + def setupGun(self, name, particle, energy, isotrop=True, multiplicity=1, position=(0.0,0.0,0.0)): + gun = GeneratorAction(self.kernel,"Geant4ParticleGun/"+name) + gun.energy = energy + gun.particle = particle + gun.multiplicity = multiplicity + gun.position = position + gun.isotrop = isotrop + gun.enableUI() + self.kernel.generatorAction().add(gun) + def setupCshUI(self): + # Configure UI + ui = Action(self.kernel,"Geant4UIManager/UI") + ui.HaveVIS = True + ui.HaveUI = True + ui.SessionType = 'csh' + self.kernel.registerGlobalAction(ui) + def setupROOTOutput(self,name,output): + evt_root = EventAction(self.kernel,'Geant4Output2ROOT/'+name) + evt_root.Control = True + evt_root.Output = output+'.root' + evt_root.enableUI() + self.kernel.eventAction().add(evt_root) + return evt_root + def setupLCIOOutput(self,name,output): + evt_lcio = EventAction(self.kernel,'Geant4Output2LCIO/'+name) + evt_lcio.Control = True + evt_lcio.Output = output + evt_lcio.enableUI() + self.kernel.eventAction().add(evt_lcio) + return evt_lcio diff --git a/DDG4/src/Geant4MonteCarloTruth.cpp b/DDG4/src/Geant4MonteCarloTruth.cpp index 2dad969fda58333a4ce3dcc18014fefc75e57c7a..0f4d9d96167e3fae69a8a77ee2f8e4a86af8eeb0 100644 --- a/DDG4/src/Geant4MonteCarloTruth.cpp +++ b/DDG4/src/Geant4MonteCarloTruth.cpp @@ -34,18 +34,18 @@ Geant4DummyTruthHandler::~Geant4DummyTruthHandler() } /// Mark a Geant4 track to be kept for later MC truth analysis -void Geant4DummyTruthHandler::mark(const G4Track* ) { +void Geant4DummyTruthHandler::mark(const G4Track*) { } /// Store a track, with a flag -void Geant4DummyTruthHandler::mark(const G4Track* , bool ) { +void Geant4DummyTruthHandler::mark(const G4Track*, bool ) { } /// Mark a Geant4 track of the step to be kept for later MC truth analysis -void Geant4DummyTruthHandler::mark(const G4Step* ) { +void Geant4DummyTruthHandler::mark(const G4Step*) { } /// Store a track produced in a step to be kept for later MC truth analysis -void Geant4DummyTruthHandler::mark(const G4Step* , bool ) { +void Geant4DummyTruthHandler::mark(const G4Step*, bool ) { } diff --git a/DDG4/src/Geant4ParticleHandler.cpp b/DDG4/src/Geant4ParticleHandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d4334f1e8976499fccd146ba581d2dfd1740f5c8 --- /dev/null +++ b/DDG4/src/Geant4ParticleHandler.cpp @@ -0,0 +1,176 @@ +// $Id: Geant4Field.cpp 888 2013-11-14 15:54:56Z markus.frank@cern.ch $ +//==================================================================== +// 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/Geant4TrackHandler.h" +#include "DDG4/Geant4EventAction.h" +#include "DDG4/Geant4TrackingAction.h" +#include "DDG4/Geant4SteppingAction.h" +#include "DDG4/Geant4MonteCarloRecordManager.h" +#include "DDG4/Geant4ParticleHandler.h" +#include "DDG4/Geant4StepHandler.h" + +#include "G4TrackingManager.hh" +#include "G4ParticleDefinition.hh" +#include "G4Track.hh" +#include "G4Step.hh" +#include "G4TrackStatus.hh" +#include "G4PrimaryParticle.hh" +#include "G4PrimaryVertex.hh" +#include "G4Event.hh" + +#include <set> +#include <stdexcept> + +using namespace std; +using DD4hep::InstanceCount; +using namespace DD4hep; +using namespace DD4hep::Simulation; + +enum { CREATED_HIT=1<<0, + PRIMARY=1<<1, + LAST=1<<63 +}; + +/// Standard constructor +Geant4ParticleHandler::Geant4ParticleHandler(Geant4Context* context, const std::string& nam) + : Geant4GeneratorAction(context,nam), Geant4MonteCarloTruth() +{ + //generatorAction().adopt(this); + eventAction().callAtBegin(this,&Geant4ParticleHandler::beginEvent); + eventAction().callAtFinal(this,&Geant4ParticleHandler::endEvent); + trackingAction().callAtFinal(this,&Geant4ParticleHandler::end,CallbackSequence::FRONT); + trackingAction().callUpFront(this,&Geant4ParticleHandler::begin,CallbackSequence::FRONT); + steppingAction().call(this,&Geant4ParticleHandler::step); + + declareProperty("PrintEndTracking",m_printEndTracking = false); + declareProperty("PrintStartTracking",m_printStartTracking = false); + + InstanceCount::increment(this); +} + +/// Default destructor +Geant4ParticleHandler::~Geant4ParticleHandler() { + InstanceCount::decrement(this); +} + +/// Mark a Geant4 track to be kept for later MC truth analysis +void Geant4ParticleHandler::mark(const G4Track* track, bool created_hit) { + mark(track); // Does all the checking... + if ( created_hit ) { + } +} + +/// Store a track produced in a step to be kept for later MC truth analysis +void Geant4ParticleHandler::mark(const G4Step* step, bool created_hit) { + if ( step ) { + mark(step->GetTrack(),created_hit); + return; + } + except("Cannot mark the G4Track if the step-pointer is invalid!", c_name()); +} + +/// Mark a Geant4 track of the step to be kept for later MC truth analysis +void Geant4ParticleHandler::mark(const G4Step* step) { + if ( step ) { + mark(step->GetTrack()); + return; + } + except("Cannot mark the G4Track if the step-pointer is invalid!", c_name()); +} + +/// Mark a Geant4 track of the step to be kept for later MC truth analysis +void Geant4ParticleHandler::mark(const G4Track* track) { + m_trackReasons[track->GetTrackID()] = CREATED_HIT; +} + +class Particle { +public: + int id; + double px,py,pz; + const G4ParticleDefinition *definition; +}; + +/// Event generation action callback +void Geant4ParticleHandler::operator()(G4Event* evt) { + typedef Geant4MonteCarloTruth _MC; + printout(INFO,name(),"+++ Add EVENT extension of type Geant4ParticleHandler....."); + context()->event().addExtension((_MC*)this, typeid(_MC), 0); + m_trackReasons.clear(); + m_trackIDTree.clear(); + m_particleMap.clear(); + for(int i=0, count=-1; i<evt->GetNumberOfPrimaryVertex(); ++i) { + G4PrimaryVertex* v = evt->GetPrimaryVertex(i); + for(int j=0; j<v->GetNumberOfParticle(); ++j) { + G4PrimaryParticle* p = v->GetPrimary(i); + const G4ParticleDefinition* def = p->GetParticleDefinition(); + Particle* particle = new Particle(); + p->SetTrackID(++count); + particle->px = p->GetPx(); + particle->py = p->GetPy(); + particle->pz = p->GetPz(); + particle->id = p->GetTrackID(); + particle->definition = def; + printout(INFO,name(),"+++ Add Primary particle %d def:%p [%s, %s]", + particle->id, def, + def ? def->GetParticleName().c_str() : "UNKNOWN", + def ? def->GetParticleType().c_str() : "UNKNOWN"); + m_particleMap.insert(make_pair(particle->id,particle)); + TrackIDTree::iterator i = m_trackIDTree.find(p->GetTrackID()); + if ( i == m_trackIDTree.end() ) m_trackIDTree.insert(make_pair(p->GetTrackID(),std::set<int>())); + m_trackReasons[p->GetTrackID()] = PRIMARY; + } + } +} + +/// Pre-event action callback +void Geant4ParticleHandler::beginEvent(const G4Event* ) { +} + +/// Pre-event action callback +void Geant4ParticleHandler::endEvent(const G4Event* ) { + m_particleMap.clear(); + m_trackIDTree.clear(); + m_trackReasons.clear(); +} + +/// User stepping callback +void Geant4ParticleHandler::step(const G4Step* step, G4SteppingManager* /* mgr */) { + typedef std::vector<const G4Track*> _Sec; + const _Sec* sec=step->GetSecondaryInCurrentStep(); + if ( sec->size() > 0 ) { + for(_Sec::const_iterator i=sec->begin(); i!=sec->end(); ++i) { + } + } +} + +/// Pre-track action callback +void Geant4ParticleHandler::begin(const G4Track* track) { + Geant4TrackHandler h(track); + + TrackIDTree::iterator i = m_trackIDTree.find(h.parent()); + printout(INFO,name(),"+++ Tracking preaction: %d par:%d [%s, %s] created by:%s", + h.id(),h.parent(),h.name().c_str(),h.type().c_str(),h.creatorName().c_str()); + m_trackIDTree.insert(make_pair(h.id(),std::set<int>())); + m_trackReasons[h.id()] = 0; + if ( i != m_trackIDTree.end() ) { + (*i).second.insert(h.id()); + return; + } + printout(INFO,name(),"+++ Tracking preaction: UNKNOWN parent %d par:%d",h.id(),h.parent()); +} + +/// Post-track action callback +void Geant4ParticleHandler::end(const G4Track* track) { + int id = track->GetTrackID(); + int pid = track->GetParentID(); + printout(INFO,name(),"+++ Tracking postaction: %d par:%d",id,pid); +} diff --git a/DDG4/src/Geant4SensDetAction.cpp b/DDG4/src/Geant4SensDetAction.cpp index f314f8a36479b510b4ec0d32bee91b8af6586bbe..abf808a1873f23c43482576be75e92a713b3c67f 100644 --- a/DDG4/src/Geant4SensDetAction.cpp +++ b/DDG4/src/Geant4SensDetAction.cpp @@ -79,7 +79,9 @@ bool Geant4Filter::operator()(const G4Step*) const { /// 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() { + : Geant4Action(ctxt, name), m_sensitiveDetector(0), m_sequence(0), m_lcdd(lcdd), + m_detector(det), m_sensitive(), m_readout(), m_segmentation() +{ InstanceCount::increment(this); if (!det.isValid()) { throw runtime_error(format("Geant4Sensitive", "DDG4: Detector elemnt for %s is invalid.", name.c_str())); @@ -87,6 +89,7 @@ Geant4Sensitive::Geant4Sensitive(Geant4Context* ctxt, const string& name, DetEle m_sequence = ctxt->kernel().sensitiveAction(m_detector.name()); m_sensitive = lcdd.sensitiveDetector(det.name()); m_readout = m_sensitive.readout(); + m_segmentation = m_readout.segmentation(); } /// Standard destructor @@ -190,9 +193,26 @@ long long int Geant4Sensitive::volumeID(G4Step* s) { return id; } +/// Returns the cellID(volumeID+local coordinate encoding) of the sensitive volume corresponding to the step +long long int Geant4Sensitive::cellID(G4Step* s) { + StepHandler h(s); + typedef DDSegmentation::Vector3D _V; + Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager(); + VolumeID volID = volMgr.volumeID(h.preTouchable()); + if ( m_segmentation.isValid() ) { + G4ThreeVector global = 0.5 * ( h.prePosG4()+h.postPosG4()); + G4ThreeVector local = h.preTouchable()->GetHistory()->GetTopTransform().TransformPoint(global); + Position loc(local.x(), local.y(), local.z()), glob(global.x(), global.y(), global.z()); + VolumeID cellID = m_segmentation.cellID(loc,glob,volID); + return cellID; + } + return volID; +} + /// Standard constructor Geant4SensDetActionSequence::Geant4SensDetActionSequence(Geant4Context* context, const string& nam) - : Geant4Action(context, nam), m_hce(0) { + : Geant4Action(context, nam), m_hce(0) +{ m_needsControl = true; context->sensitiveActions().insert(name(), this); /// Update the sensitive detector type, so that the proper instance is created