Skip to content
Snippets Groups Projects
Geant4ParticleHandler.cpp 5.86 KiB
Newer Older
// $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);
}