From 348f10b9dec635b508ac4f8df13099f2f8063655 Mon Sep 17 00:00:00 2001
From: Markus Frank <Markus.Frank@cern.ch>
Date: Tue, 26 Jun 2018 19:12:29 +0200
Subject: [PATCH] Elaborate a bit more the DDG4_MySensDet example and fix the
 persistency of the Geant4 hits

---
 DDG4/include/DDG4/Geant4Data.h                |   6 +-
 DDG4/src/Geant4Data.cpp                       |   1 +
 examples/DDG4_MySensDet/CMakeLists.txt        |   7 +
 examples/DDG4_MySensDet/README.txt            |  33 ++++-
 examples/DDG4_MySensDet/src/MyTrackerHit.h    | 120 ++++++++++++++++++
 .../DDG4_MySensDet/src/MyTrackerSDAction.cpp  |  79 ++----------
 6 files changed, 173 insertions(+), 73 deletions(-)
 create mode 100644 examples/DDG4_MySensDet/src/MyTrackerHit.h

diff --git a/DDG4/include/DDG4/Geant4Data.h b/DDG4/include/DDG4/Geant4Data.h
index 89cd369cf..12347d918 100644
--- a/DDG4/include/DDG4/Geant4Data.h
+++ b/DDG4/include/DDG4/Geant4Data.h
@@ -118,11 +118,11 @@ namespace dd4hep {
         HIT_ENDED_OUTSIDE   = 1<<15
       };
       /// cellID
-      long long int cellID;
+      long long int cellID = 0;
       /// User flag to classify hits
-      long flag;
+      long flag = 0;
       /// Original Geant 4 track identifier of the creating track (debugging)
-      long g4ID;
+      long g4ID = -1;
       /// User data extension if required
 #ifdef DD4HEP_DD4HEP_PTR_AUTO
       dd4hep_ptr<DataExtension> extension;
diff --git a/DDG4/src/Geant4Data.cpp b/DDG4/src/Geant4Data.cpp
index e481fbba5..ac8a87381 100644
--- a/DDG4/src/Geant4Data.cpp
+++ b/DDG4/src/Geant4Data.cpp
@@ -75,6 +75,7 @@ Geant4HitData::Contribution Geant4HitData::extractContribution(const G4Step* ste
   Contribution contrib(h.trkID(),h.trkPdgID(),deposit,h.trkTime(),length,pos);
   return contrib;
 }
+
 /// Extract the MC contribution for a given hit from the step information with BirksLaw effect option
 Geant4HitData::Contribution Geant4HitData::extractContribution(const G4Step* step, bool ApplyBirksLaw) {
   Geant4StepHandler h(step);
diff --git a/examples/DDG4_MySensDet/CMakeLists.txt b/examples/DDG4_MySensDet/CMakeLists.txt
index 020c2bd44..8391f42f8 100644
--- a/examples/DDG4_MySensDet/CMakeLists.txt
+++ b/examples/DDG4_MySensDet/CMakeLists.txt
@@ -27,8 +27,15 @@ dd4hep_configure_scripts(DDG4_MySensDet DEFAULT_SETUP WITH_TESTS)
 if (DD4HEP_USE_GEANT4)
   #
   dd4hep_set_compiler_flags()
+  #---------------------------  Plugin library for the simulation framework  ---------
+  dd4hep_add_dictionary(G__DDG4_MySensDet
+    SOURCES ${DD4hep_DIR}/include/ROOT/Warnings.h src/MyTrackerHit.h
+    LINKDEF ${DD4hep_DIR}/include/ROOT/LinkDef.h
+    )
+
   #----  Example of a client library with user defined plugins  --------------------
   dd4hep_add_plugin( DDG4_MySensDet
+    GENERATED G__DDG4_MySensDet.cxx
     SOURCES   src/*.cpp
     USES      [GEANT4 REQUIRED]
               [ROOT   REQUIRED COMPONENTS Geom GenVector RIO]
diff --git a/examples/DDG4_MySensDet/README.txt b/examples/DDG4_MySensDet/README.txt
index 9f2bb062c..ef65da004 100644
--- a/examples/DDG4_MySensDet/README.txt
+++ b/examples/DDG4_MySensDet/README.txt
@@ -5,4 +5,35 @@ As a hit class it uses the Geant4TrackerHit class.
 1) The example should illustrate how to setup the factory for a specialized sensitive detector action
 2) In the scripts area there is a simple example to illustrate how to setup a small
    simulation and use this factory. (scripts/MyTrackerSD_sim.py)
-   
+
+
+For issues concerning the MC truth and the (consistent) persistency
+please visit the MyTrackerHit include file.
+
+After running DDG4 with the command line:
+$> python $DD4hepExamplesINSTALL/examples/DDG4_MySensDet/scripts/MyTrackerSD_siy \
+  --compact=file:$DD4hepExamplesINSTALL/examples/ClientTests/compact/SiliconBlock.xml
+
+You can then directly inspect the produced hits and the energy deposits:
+
+$> root.exe
+   ------------------------------------------------------------
+  | Welcome to ROOT 6.12/06                http://root.cern.ch |
+  |                               (c) 1995-2017, The ROOT Team |
+  | Built for linuxx8664gcc                                    |
+  | From tag v6-12-06, 9 February 2018                         |
+  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q' |
+   ------------------------------------------------------------
+
+root [0] gSystem->Load("libDDG4_MySensDet.so")
+(int) 0
+root [1] gSystem->Load("libDDG4Plugins.so")
+(int) 0
+root [2] TFile* f=TFile::Open("MySD_2018-06-26_19-03.root")
+(TFile *) 0x41a4ba0
+root [3] TBrowser b
+(TBrowser &) Name: Browser Title: ROOT Object Browser
+root [4] 
+root [4] 
+
+Then click through the browser into the file....
diff --git a/examples/DDG4_MySensDet/src/MyTrackerHit.h b/examples/DDG4_MySensDet/src/MyTrackerHit.h
new file mode 100644
index 000000000..85ec336ea
--- /dev/null
+++ b/examples/DDG4_MySensDet/src/MyTrackerHit.h
@@ -0,0 +1,120 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+#ifndef SOMEEXPERIMENT_MYTRACKERHIT_H
+#define SOMEEXPERIMENT_MYTRACKERHIT_H
+
+#include "DDG4/Geant4Data.h"
+#include "G4Track.hh"
+#include "G4Step.hh"
+
+namespace SomeExperiment {
+
+  /// This is the hit definition.
+  /** I took here the same definition of the default Geant4Tracker class,
+   *  (see DDG4/Geant4Data.h)  but it could be anything else as well.
+   *
+   *  Please note:
+   *  ============
+   *  The MC truth handling as implemented in the Geant4ParticleHandler
+   *  will not work with this class if the object(s) are saved with 
+   *  the standard Geant4Output2ROOT event action. If the hit is 
+   *  specialized, the output writing also must be specialized if
+   *  MC truth handling should be supported.
+   *  Otherwise it is sufficient to provide a ROOT dictionary as long as the
+   *  base class dd4hep::sim::Geant4HitData is kept.
+   *
+   *  \author  M.Frank
+   *  \version 1.0
+   *  \ingroup DD4HEP_SIMULATION
+   */
+  class MyTrackerHit /* : public dd4hep::sim::Geant4HitData  */ {
+
+  public:
+    /// dd4hep::sim::Geant4HitData: cellID
+    long long int cellID = 0;
+    /// dd4hep::sim::Geant4HitData: User flag to classify hits
+    long flag = 0;
+    /// dd4hep::sim::Geant4HitData: Original Geant 4 track identifier of the creating track (debugging)
+    long g4ID = -1;
+
+    
+    /// Hit position
+    dd4hep::Position      position;
+    /// Hit direction
+    dd4hep::Direction     momentum;
+    /// Length of the track segment contributing to this hit
+    double        length = 0;
+    /// Monte Carlo / Geant4 information
+    dd4hep::sim::Geant4HitData::MonteCarloContrib truth;
+    /// Energy deposit in the tracker hit
+    double        energyDeposit = 0;
+
+  public:
+    /// Default constructor
+    MyTrackerHit() = default;
+    /// Initializing constructor
+    MyTrackerHit(int track_id, int pdg_id, double deposit, double time_stamp)
+      : length(0.0), truth(track_id, pdg_id, deposit, time_stamp, 0.), energyDeposit(deposit) {}
+    /// Default destructor
+    virtual ~MyTrackerHit() = default;
+    /// Assignment operator
+    MyTrackerHit& operator=(const MyTrackerHit& c)  {
+      if ( &c != this )  {
+        position = c.position;
+        momentum = c.momentum;
+        length = c.length;
+        truth = c.truth;
+      }
+      return *this;
+    }
+    /// Clear hit content
+    MyTrackerHit& 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.
+    MyTrackerHit& storePoint(const G4Step* step, const 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;
+    }
+  };
+}
+
+// CINT configuration
+#if defined(__CINT__) || defined(__MAKECINT__) || defined(__CLING__) || defined(__ROOTCLING__)
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+/// Define namespaces
+#pragma link C++ namespace dd4hep;
+#pragma link C++ namespace dd4hep::sim;
+#pragma link C++ namespace SomeExperiment;
+#pragma link C++ class     SomeExperiment::MyTrackerHit+;
+#endif
+
+#endif /* SOMEEXPERIMENT_MYTRACKERHIT_H */
diff --git a/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp b/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp
index f960ea8c1..13af17abc 100644
--- a/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp
+++ b/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp
@@ -12,78 +12,17 @@
 //==========================================================================
 
 // Framework include files
+#include "MyTrackerHit.h"
 #include "DDG4/Geant4SensDetAction.inl"
 #include "DDG4/Factories.h"
 
-using namespace CLHEP;
+//using namespace CLHEP;
+
+namespace SomeExperiment {
 
-namespace {
   class MyTrackerSD {
   public:
-    /// This is the hit definition.
-    /** I took here the same definition of the default Geant4Tracker class,
-     *  (see DDG4/Geant4Data.h)  but it could be anything else as well
-     *
-     *  \author  M.Frank
-     *  \version 1.0
-     *  \ingroup DD4HEP_SIMULATION
-     */
-    class MyHit : public dd4hep::sim::Geant4HitData {
-    public:
-      /// Hit position
-      dd4hep::Position      position;
-      /// Hit direction
-      dd4hep::Direction     momentum;
-      /// Length of the track segment contributing to this hit
-      double        length = 0;
-      /// Monte Carlo / Geant4 information
-      Contribution  truth;
-      /// Energy deposit in the tracker hit
-      double        energyDeposit = 0;
-    public:
-      /// Default constructor
-      MyHit() = default;
-      /// Initializing constructor
-      MyHit(int track_id, int pdg_id, double deposit, double time_stamp)
-      : length(0.0), truth(track_id, pdg_id, deposit, time_stamp, 0.), energyDeposit(deposit) {}
-      /// Default destructor
-      virtual ~MyHit() = default;
-      /// Assignment operator
-      MyHit& operator=(const MyHit& c)  {
-        if ( &c != this )  {
-          position = c.position;
-          momentum = c.momentum;
-          length = c.length;
-          truth = c.truth;
-        }
-        return *this;
-      }
-      /// Clear hit content
-      MyHit& 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.
-      MyHit& storePoint(const G4Step* step, const 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;
-      }
-    };
-    
+    typedef MyTrackerHit Hit;
     // If we need special data to personalize the action, be put it here
     int mumDeposits = 0;
     double integratedDeposit = 0;
@@ -96,6 +35,8 @@ namespace dd4hep {
   /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
   namespace sim   {
 
+    using namespace SomeExperiment;
+    
     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     //               Geant4SensitiveAction<MyTrackerSD>
     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -110,7 +51,7 @@ namespace dd4hep {
 
     /// Define collections created by this sensitivie action object
     template <> void Geant4SensitiveAction<MyTrackerSD>::defineCollections()    {
-      m_collectionID = declareReadoutFilteredCollection<MyTrackerSD::MyHit>();
+      m_collectionID = declareReadoutFilteredCollection<MyTrackerSD::Hit>();
     }
 
     /// Method for generating hit(s) using the information of G4Step object.
@@ -123,8 +64,8 @@ namespace dd4hep {
       double   hit_len   = direction.R();
 
       // Somehow extract here the physics you want
-      MyTrackerSD::MyHit* hit = new MyTrackerSD::MyHit(h.trkID(), h.trkPdgID(), h.deposit(), h.track->GetGlobalTime());
-      HitContribution contrib = MyTrackerSD::MyHit::extractContribution(step);
+      MyTrackerSD::Hit* hit = new MyTrackerSD::Hit(h.trkID(), h.trkPdgID(), h.deposit(), h.track->GetGlobalTime());
+      Geant4HitData::MonteCarloContrib contrib = Geant4HitData::extractContribution(step);
       hit->cellID        = cellID(step);
       hit->energyDeposit = contrib.deposit;
       hit->position      = position;
-- 
GitLab