Creating a spherical-shell detector

I am working on a dose kernel simulation. We want to use a spherical-shell to capture the dose at various angles (theta, phi). Because I want to score dose or energy deposit at each position, a volume must be specified at each location. How would you suggest going about this?

To create the scoring volume, I was thinking of using a nested parameterized volume (“Parent shell” -> “Theta Parameterization” ->“Phi Parameterization”). But I honestly wouldn’t know the right way to get the correct dimensions of the sphere. (Let me know if there is a better way)

For scoring, I would like to use the primitive dose scorers to score the dose. What would be the correct way to do this independently for each spherical-shell segment? Do I need to create a separate scorer for each internal volume? Does the SensitiveDetector Framework automate this in any way?

Hi @donahuw2,

Are you still working on this? I have previously created a spherical-shell detector using G4PVParameterised. A single sensitive detector is all that was needed with a scorer that makes specific reference to the replica number of each volume element in the spherical shell. I can look back in the code and share more if you are still in need of this information.



And example of that would be great. I was going to brute force it with many small segments creating individual objects and then creating a scorer for each, but your method is definitely more efficient. If you are willing to share the code snippet for those sections, I would greatly appreciate it.


Forgive me if I don’t understand perfectly, however I was wondering what is the advantage of this approach vs a sensitive detector for a single volume that simply records interaction site coordinates per event ID along with the other parameters of interest in an ntuple?

Hi William,

Let me know if these code snippets are too limited, I can provide more. I had implemented a class SphericalParameterisation which is derived from G4VPVParameterisation. Here is the header File:

class SphericalParameterisation : public G4VPVParameterisation {
// Constructor
SphericalParameterisation(const G4double startRadius, const G4double incRadius, const G4double stepRad, const G4double thetaSpread);
// Destructor
virtual ~SphericalParameterisation();
// Methods
virtual void ComputeDimensions(G4Sphere& sphere, const G4int copyNo, const G4VPhysicalVolume*) const;
void ComputeTransformation(const G4int, G4VPhysicalVolume*) const {};
//Private variables of your choice below

Actual implementation (the only non trivial bit is the ComputeDimensions). Which takes CopyNo that iterates through zero to a number of your choosing and then uniquely determines the radius, theta, and phi. The various undefined variables you see below are internal to the class and passed in through the constructor:

void SphericalParameterisation::ComputeDimensions(G4Sphere& sphere, const G4int copyNo, const G4VPhysicalVolume*) const
radno = (G4int)(copyNo/steptheta);
thetano = (G4int)(copyNo-radno * steptheta);

sphere.SetInnerRadius((radno) * incradius+startradius);
sphere.SetOuterRadius(((radno+1) * incradius+startradius-0.01 * mm));
sphere.SetDeltaPhiAngle(360 * deg);
sphere.SetStartThetaAngle(thetano * thetaspread);
sphere.SetDeltaThetaAngle((thetaspread * 0.90));

Then in a Parallel or Physical world you will define a logical volume sphere and pass it to G4PVParameterised.

SphericalParameterisation* param = new SphericalParameterisation(input arguments here…);

G4PVParameterised* sphericalscoring_shell = new G4PVParameterised(“sphericalscoring_shell”, SphericalScoring_log, worldLogicalS, kZAxis, numberofvoxels, param);

After this you create a sensitive detector using standard methods and associate the logical volume with the scoring sphere:


Lastly you need to implement your own scorer. The scorer can get the copy number by finding the “RepilicaNumber” of your sphere. You can then add the dose to an array of your choice, and you will know which part of the sphere the energy was deposited in based on the copy number.

G4int index = ((G4TouchableHistory*)(aStep->GetPreStepPoint()->GetTouchable()))->GetReplicaNumber(0);

I know what I’ve described here is fairly long and involved, and you also expressed a desire not to create your own scorer. Still I hope this is helpful.


I think the advantage here is output file size and simplicity. Exporting interaction site coordinates, energy deposition, and event ID will take up a large amount of space compared to simply exporting a single number (dose per primary particle) in each region of the sphere. Also the approach you described will require additional analysis afterwards to accumulate the energy depositions outside of the Geant simulation, where this approach exports the dose in each region directly.

Hi @JDecunha ,
actually this topic seems similar to my problem.
i also want to create something like that.
so can you please share the Geometry that is coming from this code if possible for you. it will be very helpful.

I want to create a geometry in which one sphere of some radius and then another sphere of different diameter by covering the first one and then one more sphere by covering the second one and i want to fill all these three spheres with different-different materials so i can see the dose after this shielding on sphere with two different materials.

can you please guide me on this. this will be a grate help for me.
Thanks in advance!

@JDecunha I want to use G4PVParamaterised like this case but to simulate an absorber medium ( spherical shell 1), inside it 2 spherical shell with different thickness
The first 1 is placed at 70 µm of depth and the second is placed at 10 mm of depth