Hits
Hit
A hit is a snapshot of the physical interaction of a track in the
sensitive region of a detector. In it you can store information
associated with a G4Step object. This information can be
the position and time of the step,
the momentum and energy of the track,
the energy deposition of the step,
geometrical information,
or any combination of the above.
G4VHit
G4VHit is an abstract base class which represents a hit.
You must inherit this base class and derive your own concrete hit
class(es). The member data of your concrete hit class can be, and
should be, your choice.
G4VHit has two virtual methods, Draw() and
Print(). To draw or print out your concrete hits, these
methods should be implemented. How to define the drawing method is
described in .
G4THitsCollection
G4VHit is an abstract class from which you derive your
own concrete classes. During the processing of a given event,
represented by a G4Event object, many objects of the hit
class will be produced, collected and associated with the event.
Therefore, for each concrete hit class you must also prepare a
concrete class derived from G4VHitsCollection, an abstract
class which represents a vector collection of user defined
hits.
G4THitsCollection is a template class derived from
G4VHitsCollection, and the concrete hit collection class of
a particular G4VHit concrete class can be instantiated from
this template class. Each object of a hit collection must have a
unique name for each event.
G4Event has a G4HCofThisEvent class
object, that is a container class of collections of hits. Hit collections are
stored by their pointers, whose type is that of the base class.
An example of a concrete hit class
shows an example of a concrete hit class.
An example of a concrete hit class.
#ifndef ExN04TrackerHit_h
#define ExN04TrackerHit_h 1
#include "G4VHit.hh"
#include "G4THitsCollection.hh"
#include "G4Allocator.hh"
#include "G4ThreeVector.hh"
class ExN04TrackerHit : public G4VHit
{
public:
ExN04TrackerHit();
~ExN04TrackerHit();
ExN04TrackerHit(const ExN04TrackerHit &right);
const ExN04TrackerHit& operator=(const ExN04TrackerHit &right);
int operator==(const ExN04TrackerHit &right) const;
inline void * operator new(size_t);
inline void operator delete(void *aHit);
void Draw() const;
void Print() const;
private:
G4double edep;
G4ThreeVector pos;
public:
inline void SetEdep(G4double de)
{ edep = de; }
inline G4double GetEdep() const
{ return edep; }
inline void SetPos(G4ThreeVector xyz)
{ pos = xyz; }
inline G4ThreeVector GetPos() const
{ return pos; }
};
typedef G4THitsCollection<ExN04TrackerHit> ExN04TrackerHitsCollection;
extern G4Allocator<ExN04TrackerHit> ExN04TrackerHitAllocator;
inline void* ExN04TrackerHit::operator new(size_t)
{
void *aHit;
aHit = (void *) ExN04TrackerHitAllocator.MallocSingle();
return aHit;
}
inline void ExN04TrackerHit::operator delete(void *aHit)
{
ExN04TrackerHitAllocator.FreeSingle((ExN04TrackerHit*) aHit);
}
#endif
G4Allocator is a class for fast allocation of objects to
the heap through the paging mechanism. For details of
G4Allocator, refer to .
Use of G4Allocator
is not mandatory, but it is recommended, especially for users who
are not familiar with the C++ memory allocation mechanism or
alternative tools of memory allocation. On the other hand, note
that G4Allocator is to be used
only for the concrete
class that is not used as a base
class of any other classes.
For example, do not use the
G4Trajectory class as a
base class for a customized trajectory class, since
G4Trajectory uses G4Allocator.
G4THitsMap
G4THitsMap is an alternative to
G4THitsCollection.
G4THitsMap does not demand G4VHit,
but instead any variable which can be mapped with an integer key. Typically the key
is a copy number of the volume, and the mapped value could for
example be a double, such as the energy deposition in a volume.
G4THitsMap is convenient for applications which do not need
to output event-by-event data but instead just accumulate them. All
the G4VPrimitiveScorer classes discussed in
use G4THitsMap.
G4THitsMap is derived from the
G4VHitsCollection
abstract base class and all objects of this class are also stored
in G4HCofThisEvent at the end of an event. How to access a
G4THitsMap object is discussed in the
following section ().
Sensitive detector
G4VSensitiveDetector
G4VSensitiveDetector is an abstract base class which
represents a detector. The principal mandate of a sensitive
detector is the construction of hit objects using information from
steps along a particle track. The ProcessHits() method of
G4VSensitiveDetector performs this task using
G4Step
objects as input. In the case of a "Readout" geometry (see
), objects of the
G4TouchableHistory class may be used as an optional input.
Your concrete detector class should be instantiated with the
unique name of your detector. The name can be associated with one
or more global names with "/" as a delimiter for categorizing your
detectors. For example
myEMcal = new MyEMcal("/myDet/myCal/myEMcal");
where myEMcal is the name of your detector. The pointer to
your sensitive detector must be set to one or more
G4LogicalVolume objects to set the sensitivity of these
volumes. The pointer should also be registered to
G4SDManager, as described in
.
G4VSensitiveDetector has three major virtual methods.
ProcessHits()
This method is invoked by G4SteppingManager when a step
is composed in the G4LogicalVolume which has the pointer
to this sensitive detector. The first argument of this method is a
G4Step object of the current step. The second argument is a
G4TouchableHistory object for the ``Readout geometry''
described in the next section. The second argument is NULL
if ``Readout geometry'' is not assigned to this sensitive detector.
In this method, one or more G4VHit objects should be
constructed if the current step is meaningful for your
detector.
Initialize()
This method is invoked at the beginning of each event. The
argument of this method is an object of the G4HCofThisEvent
class. Hit collections, where hits produced in this particular
event are stored, can be associated with the G4HCofThisEvent
object in this method. The hit collections associated with the
G4HCofThisEvent object during this method can be used for
``during the event processing'' digitization.
EndOfEvent()
This method is invoked at the end of each event. The argument
of this method is the same object as the previous method. Hit
collections occasionally created in your sensitive detector can be
associated with the G4HCofThisEvent object.
Readout geometry
This section describes how a ``Readout geometry'' can be defined. A
Readout geometry is a virtual, parallel geometry for obtaining the
channel number.
As an example, the accordion calorimeter of ATLAS
has a complicated tracking geometry, however the readout can be done by
simple cylindrical sectors divided by theta, phi, and depth. Tracks
will be traced in the tracking geometry, the ``real'' one, and the
sensitive detector will have its own readout geometry Geant4 will
message to find to which ``readout'' cell the current hit
belongs.
shows how this association is done in Geant4.
The first step is to associate a sensitive detector to a volume of the
tracking geometry, in the usual way (see
). The next step is to associate your
G4VReadoutGeometry object to the sensitive detector.
At tracking time, the base class G4VReadoutGeometry will
provide to your sensitive detector code the
G4TouchableHistory in the Readout geometry at the beginning
of the step position (position of PreStepPoint of
G4Step) and at this position only.
This G4TouchableHistory is given to your sensitive
detector code through the G4VSensitiveDetector virtual
method:
G4bool processHits(G4Step* aStep, G4TouchableHistory* ROhist);
by the ROhist argument.
Thus, you will be able to use information from both the
G4Step and the G4TouchableHistory
coming from your
Readout geometry. Note that since the association is done through a
sensitive detector object, it is perfectly possible to have several
Readout geometries in parallel.
Definition of a virtual geometry setup
The base class for the implementation of a Readout geometry is
G4VReadoutGeometry. This class has a single pure virtual
protected method:
virtual G4VPhysicalVolume* build() = 0;
which you must override in your concrete class. The
G4VPhysicalVolume pointer you will have to return is of the
physical world of the Readout geometry.
The step by step procedure for constructing a Readout geometry is:
inherit from G4VReadoutGeometry to define a
MyROGeom class;
implement the Readout geometry in the build() method,
returning the physical world of this geometry.
The world is specified in the same way as for the detector
construction: a physical volume with no mother. The axis system of
this world is the same as the one of the world for tracking.
In this geometry you need to declare the sensitive parts in the
same way as in the tracking geometry: by setting a
non-NULLG4VSensitiveDetector
pointer in, say, the
relevant G4LogicalVolume objects. This sensitive class needs
to be there, but will not be used.
You will also need to assign well defined materials to the
volumes you place in this geometry, but these materials are
irrelevant since they will not be seen by the tracking. It is
foreseen to allow the setting of a NULL pointer in this
case of the parallel geometry.
in the construct() method of your concrete
G4VUserDetectorConstruction class:
instantiate your Readout geometry:
MyROGeom* ROgeom = new MyROGeom("ROName");
build it:
ROgeom->buildROGeometry();
That will invoke your build() method.
Instantiate the sensitive detector which will receive the
ROGeom pointer, MySensitive,
and add this sensitive to the G4SDManager.
Associate this sensitive to
the volume(s) of the tracking geometry as usual.
Associate the sensitive to the Readout geometry:
MySensitive->SetROgeometry(ROgeom);
G4SDManager
G4SDManager is the singleton manager class for sensitive
detectors.
Activation/inactivation of sensitive detectors
The user interface commands activate and
inactivate are available to control your sensitive
detectors. For example:
/hits/activate detector_name
/hits/inactivate detector_name
where detector_name can be the detector name or the
category name.
For example, if your EM calorimeter is named
/myDet/myCal/myEMcal
/hits/inactivate myCal
will inactivate all detectors belonging to the myCal
category.
Access to the hit collections
Hit collections are accessed for various cases.
Digitization
Event filtering in G4VUserStackingAction
``End of event'' simple analysis
Drawing / printing hits
The following is an example of how to access the hit collection
of a particular concrete type:
G4SDManager* fSDM = G4SDManager::GetSDMpointer();
G4RunManager* fRM = G4RunManager::GetRunManager();
G4int collectionID = fSDM->GetCollectionID("collection_name");
const G4Event* currentEvent = fRM->GetCurrentEvent();
G4HCofThisEvent* HCofEvent = currentEvent->GetHCofThisEvent();
MyHitsCollection* myCollection = (MyHitsCollection*)(HC0fEvent->GetHC(collectionID));
G4MultiFunctionalDetector and
G4VPrimitiveScorerG4MultiFunctionalDetector is a concrete class derived from
G4VSensitiveDetector. Instead of implementing a
user-specific detector class, G4MultiFunctionalDetector
allows the user to register G4VPrimitiveScorer classes to
build up the sensitivity. G4MultiFunctionalDetector should
be instantiated in the users detector construction with its unique
name and should be assigned to one or more G4LogicalVolumes.
G4VPrimitiveScorer is an abstract base class representing
a class to be registered to G4MultiFunctionalDetector that
creates a G4THitsMap object of one physics quantity for an
event. Geant4 provides many concrete primitive scorer classes
listed in , and the user can
also implement his/her own primitive scorers. Each primitive scorer
object must be instantiated with a name that must be unique among
primitive scorers registered in a G4MultiFunctionalDetector.
Please note that a primitive scorer object must not be
shared by more than one G4MultiFunctionalDetector
object.
As mentioned in ,
each G4VPrimitiveScorer generates one
G4THitsMap object
per event. The name of the map object is the same as the name of
the primitive scorer. Each of the concrete primitive scorers listed
in generates a
G4THitsMap<G4double> that maps a
G4double value
to its key integer number. By default, the key is taken as the copy
number of the G4LogicalVolume to which
G4MultiFunctionalDetector is assigned. In case the logical
volume is uniquely placed in its mother volume and the mother is
replicated, the copy number of its mother volume can be taken by
setting the second argument of the G4VPrimitiveScorer
constructor, "depth" to 1, i.e. one level up. Furthermore,
in case the key must consider more than one copy number of a
different geometry hierarchy, the user can derive his/her own
primitive scorer from the provided concrete class and implement the
GetIndex(G4Step*) virtual method to return the unique
key.
shows an example of primitive sensitivity
class definitions.
An example of defining primitive sensitivity classes taken from
ExN07DetectorConstruction.
void ExN07DetectorConstruction::SetupDetectors()
{
G4String filterName, particleName;
G4SDParticleFilter* gammaFilter =
new G4SDParticleFilter(filterName="gammaFilter",particleName="gamma");
G4SDParticleFilter* electronFilter =
new G4SDParticleFilter(filterName="electronFilter",particleName="e-");
G4SDParticleFilter* positronFilter =
new G4SDParticleFilter(filterName="positronFilter",particleName="e+");
G4SDParticleFilter* epFilter = new G4SDParticleFilter(filterName="epFilter");
epFilter->add(particleName="e-");
epFilter->add(particleName="e+");
for(G4int i=0;i<3;i++)
{
for(G4int j=0;j<2;j++)
{
// Loop counter j = 0 : absorber
// = 1 : gap
G4String detName = calName[i];
if(j==0)
{ detName += "_abs"; }
else
{ detName += "_gap"; }
G4MultiFunctionalDetector* det = new G4MultiFunctionalDetector(detName);
// The second argument in each primitive means the "level" of geometrical hierarchy,
// the copy number of that level is used as the key of the G4THitsMap.
// For absorber (j = 0), the copy number of its own physical volume is used.
// For gap (j = 1), the copy number of its mother physical volume is used, since there
// is only one physical volume of gap is placed with respect to its mother.
G4VPrimitiveScorer* primitive;
primitive = new G4PSEnergyDeposit("eDep",j);
det->RegisterPrimitive(primitive);
primitive = new G4PSNofSecondary("nGamma",j);
primitive->SetFilter(gammaFilter);
det->RegisterPrimitive(primitive);
primitive = new G4PSNofSecondary("nElectron",j);
primitive->SetFilter(electronFilter);
det->RegisterPrimitive(primitive);
primitive = new G4PSNofSecondary("nPositron",j);
primitive->SetFilter(positronFilter);
det->RegisterPrimitive(primitive);
primitive = new G4PSMinKinEAtGeneration("minEkinGamma",j);
primitive->SetFilter(gammaFilter);
det->RegisterPrimitive(primitive);
primitive = new G4PSMinKinEAtGeneration("minEkinElectron",j);
primitive->SetFilter(electronFilter);
det->RegisterPrimitive(primitive);
primitive = new G4PSMinKinEAtGeneration("minEkinPositron",j);
primitive->SetFilter(positronFilter);
det->RegisterPrimitive(primitive);
primitive = new G4PSTrackLength("trackLength",j);
primitive->SetFilter(epFilter);
det->RegisterPrimitive(primitive);
primitive = new G4PSNofStep("nStep",j);
primitive->SetFilter(epFilter);
det->RegisterPrimitive(primitive);
G4SDManager::GetSDMpointer()->AddNewDetector(det);
if(j==0)
{ layerLogical[i]->SetSensitiveDetector(det); }
else
{ gapLogical[i]->SetSensitiveDetector(det); }
}
}
}
Each G4THitsMap object can be accessed from
G4HCofThisEvent with a unique collection ID number. This ID
number can be obtained from G4SDManager::GetCollectionID()
with a name of G4MultiFunctionalDetector and
G4VPrimitiveScorer connected with a slush ("/").
G4THitsMap has a [] operator taking the key value as an
argument and returning the pointer of the value.
Please note that the [] operator returns
the pointer of the value. If
you get zero from the [] operator, it does not mean the
value is zero, but that the provided key does not exist. The value
itself is accessible with an astarisk ("*"). It is advised to check
the validity of the returned pointer before accessing the value.
G4THitsMap also has a += operator in order to accumulate
event data into run data. shows the use of
G4THitsMap.
An example of accessing to G4THitsMap objects.
#include "ExN07Run.hh"
#include "G4Event.hh"
#include "G4HCofThisEvent.hh"
#include "G4SDManager.hh"
ExN07Run::ExN07Run()
{
G4String detName[6] = {"Calor-A_abs","Calor-A_gap","Calor-B_abs","Calor-B_gap",
"Calor-C_abs","Calor-C_gap"};
G4String primNameSum[6] = {"eDep","nGamma","nElectron","nPositron","trackLength","nStep"};
G4String primNameMin[3] = {"minEkinGamma","minEkinElectron","minEkinPositron"};
G4SDManager* SDMan = G4SDManager::GetSDMpointer();
G4String fullName;
for(size_t i=0;i<6;i++)
{
for(size_t j=0;j<6;j++)
{
fullName = detName[i]+"/"+primNameSum[j];
colIDSum[i][j] = SDMan->GetCollectionID(fullName);
}
for(size_t k=0;k<3;k++)
{
fullName = detName[i]+"/"+primNameMin[k];
colIDMin[i][k] = SDMan->GetCollectionID(fullName);
}
}
}
void ExN07Run::RecordEvent(const G4Event* evt)
{
G4HCofThisEvent* HCE = evt->GetHCofThisEvent();
if(!HCE) return;
numberOfEvent++;
for(size_t i=0;i<6;i++)
{
for(size_t j=0;j<6;j++)
{
G4THitsMap<G4double>* evtMap = (G4THitsMap<G4double>*)(HCE->GetHC(colIDSum[i][j]));
mapSum[i][j] += *evtMap;
}
for(size_t k=0;k<3;k++)
{
G4THitsMap<G4double>* evtMap = (G4THitsMap<G4double>*)(HCE->GetHC(colIDMin[i][k]));
std::map<G4int,G4double*>::iterator itr = evtMap->GetMap()->begin();
for(; itr != evtMap->GetMap()->end(); itr++)
{
G4int key = (itr->first);
G4double val = *(itr->second);
G4double* mapP = mapMin[i][k][key];
if( mapP && (val>*mapP) ) continue;
mapMin[i][k].set(key,val);
}
}
}
}
Concrete classes of G4VPrimitiveScorer
With Geant4 version 8.0, several concrete primitive scorer classes
are provided, all of which are derived from the
G4VPrimitiveScorer abstract base class and which are to be
registered to G4MultiFunctionalDetector. Each of them
contains one G4THitsMap object and scores a simple double
value for each key.
Track length scorers
G4PSTrackLength
The track length is defined as the sum of step lengths of the
particles inside the cell. Bt default, the track weight is not
taken into account, but could be used as a multiplier of each step
length if the Weighted() method of this class object is
invoked.
G4PSPassageTrackLength
The passage track length is the same as the track length in
G4PSTrackLength, except that only tracks which pass
through the volume are taken into account. It means newly-generated or
stopped tracks inside the cell are excluded from the calculation.
By default, the track weight is not taken into account, but could
be used as a multiplier of each step length if the
Weighted() method of this class object is invoked.
Deposited energy scorers
G4PSEnergyDeposit
This scorer stores a sum of particles' energy deposits at each
step in the cell. The particle weight is multiplied at each
step.
G4PSDoseDeposit
In some cases, dose is a more convenient way to evaluate the
effect of energy deposit in a cell than simple deposited energy.
The dose deposit is defined by the sum of energy deposits at each
step in a cell divided by the mass of the cell. The mass is
calculated from the density and volume of the cell taken from the
methods of G4VSolid and
G4LogicalVolume. The particle
weight is multiplied at each step.
Current and flux scorers
There are two different definitions of a particle's flow for a
given geometry. One is a current and the other is a flux. In our
scorers, the current is simply defined as the number of particles
(with the particle's weight) at a certain surface or volume, while
the flux takes the particle's injection angle to the geometry into
account. The current and flux are usually defined at a surface, but
volume current and volume flux are also provided.
G4PSFlatSurfaceCurrent
Flat surface current is a surface based scorer. The present
implementation is limited to scoring only at the -Z surface of a
G4Box solid. The quantity is defined by the number
of tracks that reach the surface. The user must choose a direction of the
particle to be scored. The choices are fCurrent_In, fCurrent_Out,
or fCurrent_InOut, one of which must be entered as the second
argument of the constructor. Here, fCurrent_In scores incoming
particles to the cell, while fCurrent_Out scores only outgoing
particles from the cell. fCurrent_InOut scores both directions. The
current is multiplied by particle weight and is normalized for a
unit area.
G4PSSphereSurfaceCurrent
Sphere surface current is a surface based scorer, and similar
to the G4PSFlatSurfaceCurrent. The only difference is that the
surface is defined at the inner surface
of a G4Sphere solid.
G4PSPassageCurrent
Passage current is a volume-based scorer. The current is
defined by the number of tracks that pass through the volume. A
particle weight is applied at the exit point. A passage current is
defined for a volume.
G4PSFlatSurfaceFlux
Flat surface flux is a surface based flux scorer. The surface
flux is defined by the number of tracks that reach the surface. The
expression of surface flux is given by the sum of W/cos(t)/A, where
W, t and A represent particle weight, injection angle of particle
with respect to the surface normal, and area of the surface. The
user must enter one of the particle directions, fFlux_In,
fFlux_Out, or fFlux_InOut in the constructor. Here, fFlux_In scores
incoming particles to the cell, while fFlux_Out scores outgoing
particles from the cell. fFlux_InOut scores both directions.
G4PSCellFlux
Cell flux is a volume based flux scorer. The cell flux is
defined by a track length (L) of the particle inside a volume
divided by the volume (V) of this cell. The track length is
calculated by a sum of the step lengths in the cell. The expression
for cell flux is given by the sum of (W*L)/V, where W is a particle
weight, and is multiplied by the track length at each step.
G4PSPassageCellFlux
Passage cell flux is a volume based scorer similar to
G4PSCellFlux. The only difference is that tracks
which pass through a cell are taken into account. It means generated or
stopped tracks inside the volume are excluded from the
calculation.
Other scorers
G4PSMinKinEAtGeneration
This scorer records the minimum kinetic energy of secondary
particles at their production point in the volume in an event. This
primitive scorer does not integrate the quantity, but records the
minimum quantity.
G4PSNofSecondary
This class scores the number of secondary particles generated
in the volume. The weight of the secondary track is taken into
account.
G4PSNofStep
This class scores the number of steps in the cell. A particle
weight is not applied.
G4PSCellCharge
This class scored the total charge of particles which has stoped
in the volume.
G4VSDFilter and its derived classes
G4VSDFilter is an abstract class that represents a track
filter to be associated with G4VSensitiveDetector or
G4VPrimitiveScorer. It defines a virtual method
G4bool Accept(const G4Step*)
that should return true if this particular step should be
scored by the G4VSensitiveDetector or
G4VPrimitiveScorer.
While the user can implement his/her own filter class, Geant4
version 8.0 provides the following concrete filter classes:
G4SDChargedFilter
All charged particles are accepted.
G4SDNeutralFilter
All neutral particles are accepted.
G4SDParticleFilter
Particle species which are registered to this filter object by
Add("particle_name") are accepted. More than one
species can be registered.
G4SDKineticEnergyFilter
A track with kinetic energy greater than or equal to EKmin and
smaller than EKmin is accepted. EKmin and EKmax should be defined
as arguments of the constructor. The default values of EKmin and
EKmax are zero and DBL_MAX.
G4SDParticleWithEnergyFilter
Combination of G4SDParticleFilter and
G4SDParticleWithEnergyFilter.
The use of the G4SDParticleFilter class is demonstrated
in , where filters which accept gamma,
electron, positron and electron/positron are defined.
Scoring for Event Biasing
Scoring for Event Biasing (described in ) is a
very specific use case whereby particle weights and fluxes through importance
cells are required. The goals of the scoring technique are to:
appraise particle quantities related to special regions or
surfaces,
be applicable to all "cells" (physical volumes or replicas) of
a given geometry,
be customizable.
Standard scoring must be provided for quantities such as tracks
entering a cell, average weight of entering tracks, energy of
entering tracks, and collisions inside the cell.
A number of scorers have been created for this specific appliction:
G4PSNofCollision
This scorer records the number of collisions that occur within a scored volume/cell.
There is the additional possibility to take into account the track weight
whilst scoring the number of collisions, via the following command:
G4PSNofCollision* scorer1 = new G4PSNofCollision(psName="CollWeight");
scorer1->Weighted(true);
G4PSPopulation
This scores the number of tracks within in a given cell per event.
G4PSTrackLength
The track lengths within a cell are measured and if, additionally, the result is desired
to be weighted then the following code has to be implemented:
G4PSTrackLength* scorer5 = new G4PSTrackLength(psName="SLW");
scorer5->Weighted(true);
Further if the energy track flux is required then the following should be
implemented:
G4PSTrackLength* scorer6 = new G4PSTrackLength(psName="SLWE");
scorer6->Weighted(true);
scorer6->MultiplyKineticEnergy(true);
MFDet->RegisterPrimitive(scorer6);
Alternatively to measure the flux per unit velocity then:
G4PSTrackLength* scorer7 = new G4PSTrackLength(psName="SLW_V");
scorer7->Weighted(true);
scorer7->DivideByVelocity(true);
MFDet->RegisterPrimitive(scorer7);
Finally to measure the flux energy per unit velocity then:
G4PSTrackLength* scorer8 = new G4PSTrackLength(psName="SLWE_V");
scorer8->Weighted(true);
scorer8->MultiplyKineticEnergy(true);
scorer8->DivideByVelocity(true);
MFDet->RegisterPrimitive(scorer8);