How can I accumulate energy deposition caused by a particualr process?


G4Track has a pointer to G4VProcess, which inform you the process which generated the particular track. Once this track has an interaction and makes secondaries (grand-daughters with respect to the original track), you have no direct way to trace back from these secondaries to the original process. To distinguish energy deposition originated from a particular process from other energy deposition, an information of original process must be passed to all generation of concerned particles. G4VUserTrackInformation can be used for this purpose.

In your PreUserTrackingAction of UserTrackingAction, if you see a track which does not have UserTrackInformation and it has a pointer of G4VProcess which direct to the process you are interested in, it is a direct product of that process. Thus, you should instanciate a UserTrackInformation and associate it to the track.

In your PostUserTrackingAction, if you see a track which has a UserTrackInformation, this is a track originated from the process you are interested in. Thus if this track has secondaries, you have to copy UserTrackInformation to them.

You do not need to worry about the contents of UserTrackInformation. The existance of UserTrackInformation itself is a flag. For example, you can utilize an example given here.

Here is the sample implementation of G4UserTrackingAction

Header file (T01TrackingAction.hh)

#ifndef T01TrackingAction_h
#define T01TrackingAction_h 1

class G4Track;
#include "G4UserTrackingAction.hh"
#include "globals.hh"

class T01TrackingAction : public G4UserTrackingAction 
{
  public:
    T01TrackingAction();
    virtual ~T01TrackingAction();
   
    virtual void PreUserTrackingAction(const G4Track*);
    virtual void PostUserTrackingAction(const G4Track*);

  private:
    G4String processName;
};

#endif

Source file (T01TrackingAction.cc)

#include "T01TrackingAction.hh"
#include "G4TrackingManager.hh"
#include "G4Track.hh"
#include "G4VProcess.hh"
#include "T01TrackInformation.hh"

T01TrackingAction::T01TrackingAction()
{ processName = "process_name_you_are_interested_in"; }

T01TrackingAction::~T01TrackingAction()
{;}

void T01TrackingAction::PreUserTrackingAction(const G4Track* aTrack)
{
  // Check if the track already has track information
  if(aTrack->GetUserInformation()!=0) return;

  // Check if the track has the creator process (not the case for primaries)
  const G4VProcess* creatorProcess = aTrack->GetCreatorProcess();
  if(!creatorProcess) return;

  // Check if the track was generated by the interested process
  if(creatorProcess->GetProcessName()==processName)
  {
    // If it is the case, create a track information and attach it to the track
    T01TrackInformation* anInfo = new T01TrackInformation(aTrack);
    G4Track* theTrack = (G4Track*)aTrack;
    theTrack->SetUserInformation(anInfo);
  }
}

void T01TrackingAction::PostUserTrackingAction(const G4Track* aTrack)
{
  // Check if the track already has track information
  T01TrackInformation* info
    = (T01TrackInformation*)(aTrack->GetUserInformation());
  if(info==0) return;

  // Copy parent's track information to its daughters
  G4TrackVector* secondaries = fpTrackingManager->GimmeSecondaries();
  if(secondaries)
  {
    size_t nSeco = secondaries->size();
    for(size_t i=0;i<nSeco;i++)
    { 
      T01TrackInformation* infoNew = new T01TrackInformation(info);
      (*secondaries)[i]->SetUserInformation(infoNew);
    }
  }
}

To accumulate energy deposition in your sensitive detector, you have to consider two cases.

  1. A Track has a UserTrackInformation. In this case, you have to collect energy deposition since the track is originated by a process you are interested in.
  2. A track does not have a UserTrackInformation, but the current step was limitted by a process you are interested in. Please note that there is a posibility that some secondaries were produced by a process you are interested in, but G4SteppingManager killed some of them because their ranges are shorther than the production threshold. In such a case, energies of killed secondaries are merged to the energy deposition of the current step.
Here is an example implementation of a sensitive detector which accumulates energy deposition of both of above mentioned cases.

Source file for the case of a sensitive detector

#include "T01Calorimeter.hh"
#include "T01CalorimeterHit.hh"
#include "T01TrackInformation.hh"
#include "G4HCofThisEvent.hh"
#include "G4TouchableHistory.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4SDManager.hh"
#include "G4ios.hh"
#include "G4UnitsTable.hh"
#include "G4ParticleTable.hh"
#include "G4ParticleTypes.hh"
#include "G4VProcess.hh"

T01Calorimeter::T01Calorimeter(G4String name)
:G4VSensitiveDetector(name)
{
  G4String HCname;
  collectionName.insert(HCname="calorimeterColl");
  HCID = -1;
  processName = "process_name_you_are_interested_in"; 
  interestedParticle = particle_definition_you_are_interested_in;
}

 ...............

G4bool T01Calorimeter::ProcessHits(G4Step*aStep,G4TouchableHistory*ROhist)
{
  // return if no energy deposition
  G4double edep = aStep->GetTotalEnergyDeposit();

  T01CalorimeterHit* aHit = (*hitsCollection)[0];

  // add energy deposition
  if(Interested(aStep))
  {
    aHit->AddEdep(edep);
  }

  return true;
}

G4bool T01Calorimeter::Interested(const G4Step* aStep) const
{
  G4Track* aTrack = aStep->GetTrack();

  // check if the track already has UserTrackInformation
  if(aTrack->GetUserInformation()) return true;

  // check if the track is interested particle and the step is limitted by
  // the interested process
  if(aTrack->GetDefinition()!=interestedParticle) return false;
  const G4VProcess* processDefinedTheStep
    = aStep->GetPostStepPoint()->GetProcessDefinedStep();
  if(processDefinedTheStep->GetProcessName()==processName) return true;

  return false;
}


Makoto Asai