Photodiode Light Collection from Scintillator

Hi there,

I am trying to simulate light collection from plastic scintillator using a small silicon photodiode. Here is a screenshot of my geometry: the main detector volume is a series of polystyrene plastic scintillator sheets and you can see a small photodiode attached to the side of each sheet. I’ve used G4PVReplica to implement this repeated geometry.

The scintillator material has defined its fast and slow constant scintillator components, emission spectrum with photon energy (both fast and slow), absorption length and refractive index. So far I’ve just implemented the photodiodes as solid silicon using the built-in material definition.

So far, I’ve been successful in counting the number of photons produced in each scintillator sheet, by implementing the sheets as a sensitive detector. Naively, I’ve implemented the photodiodes as a sensitive detector as well to try and count the photons in the same way, but of course, no photons actually are able to pass into the photodiode.

Looking at the LXe optical example, it seems that I’ll need to do some boundary process checks in order to simulate photons being collected in the photodiodes. Admittedly, I’m struggling to decipher which parts from this example I’ll need for my simple use case and how to apply it to just the photodiode-scintillator boundary. Would someone be able to offer some advice for how to go about this?

Here is the hit processing for the sensitive detector, currently set up to count the total number of photons produced in the sensitive volume:

G4bool SensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory*) {

// energy deposit
G4double edep = step->GetTotalEnergyDeposit();

if (edep==0.) return false;

// Get calorimeter cell id
const G4VTouchable* touchable = step->GetPreStepPoint()->GetTouchable();
G4int layerNumber = touchable->GetReplicaNumber(1);

// Get hit accounting data for this cell
auto hit = (*fHitsCollection)[layerNumber];
if ( ! hit ) {
    G4ExceptionDescription msg;
    msg << "Cannot access hit " << layerNumber;
    G4Exception("SensitiveDetector::ProcessHits()","MyCode0004", FatalException, msg);

G4double zmax = 128*3;
G4StepPoint* prePoint  = step->GetPreStepPoint();
G4StepPoint* postPoint = step->GetPostStepPoint();
G4double z1 = prePoint->GetPosition().z() + zmax*0.5;
G4double z2 = postPoint->GetPosition().z() + zmax*0.5;
if (z1 >= 0.0 && z2 <= zmax) {
    G4double z = z1 + G4UniformRand()*(z2-z1);
    G4Track* track = step->GetTrack();
    const G4DynamicParticle* theParticle = track->GetDynamicParticle();
    const G4ParticleDefinition* particleDef = theParticle->GetParticleDefinition();
    static G4ParticleDefinition* opticalphoton = G4OpticalPhoton::OpticalPhotonDefinition();
    if (particleDef != opticalphoton) {
        // loop over secondaries, create statistics
        const std::vector<const G4Track*>* secondaries = step->GetSecondaryInCurrentStep();
        for (auto sec : *secondaries) {
            if (sec->GetDynamicParticle()->GetParticleDefinition() == opticalphoton) {
                G4String creator_process = sec->GetCreatorProcess()->GetProcessName();
                if ("Scintillation") == 0) {
return true;

Please let me know if you’d need further information to answer this question!

When you visualize, do you see photons leave the scintillator? Photons will not travel into a material without a defined index of refraction

1 Like

Hi @loydms, thanks for your response.

Yes, I am able to see photons leave the scintillator. I have defined an energy-dependent refractive index for the polystyrene scintillator and in the visualisation, I can see photons (green) leave the detector into the world (G4_AIR) and some go through the photodiodes, which I now have changed to be the same material as the scintillator for testing purposes (i.e. to give it a refractive index).

With this material for the photodiodes, I can get a vanishingly small number of photons. For a simulation with a million protons, I get the following light-distribution from counting the number of photons in each sheet and photodiode, scaling the latter to peak at the same height as the former. From real experiments, I would expect these two curves to be roughly the same, with the photodiode one being more noisy (due to fewer events).

Test.pdf (55.1 KB)

I also did a brute force check to see if photons reach the edge of the scintillator by adding lines to see if the x and y coordinates of either the pre- or post- step of the above are at or beyond the coordinates covered by the photodiodes, and am able to see somewhat better results. The second plot in the file above shows the results for the same number of particles as above and scaled the same way. Note, this ONLY uses the scintillator sensitive detector volume.

I also wonder if the light collection method needs to be different for counting within sheets vs. in photodiodes, as the former is set up in such a way to avoid double counting by checking photons at the point of creation, whereas I will need to check both photons being created at the photodiodes and those that manage to propagate to the diodes from further within the scintillator.

Some context of the simulation: I am measuring the energy deposition and light production of protons in plastic scintillator, and comparing the latter with the total number of photons produced (i.e. perfect detection) vs. with a small photodiode on the edge of the scintillator.

Based on your results I would say you don’t have enough counts in the PD’s to see a trend, either due to not counting hits in the PD or simply not enough photons hitting them. Based on your image, they only cover a small amount of surface area of each sheet, maybe < 5%. If you add in reflection probabilities, and some quantum efficiency probabilities of absorption, I would expect to see very few hits on each PD unless there were many many photons produced. Is the image you attached with millions of protons? There are maybe <10 photons hitting PD’s in that image.

I’ll be honest, I don’t know the best way to do hit counting on the PD’s. I believe a sensitive detector is the correct way, but the way I have done it is to set the absorption distance of the PD high count/kill the particle if the post step PV is in the PD.