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.
| 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
|
| |