Retrieving ROS production - Geant4-DNA

Geant4 Version: 11.4.0
Operating System: Ubuntu 24.04.3 LTS
Compiler/Version: gcc 13.3.0
CMake Version: 3.28.3


Dear Geant4 users,

I am very new to Geant4 and I wish to understand how to use Geant4-DNA.

I have tried to code a very simple model : a sphere full of water with at its center a source of photo-electrons. I wish to record the ROS production. I think I succeed in retrieving all interactions, but I can’t manage to record the ROS. However, I checked some interactions have a deposited dose greater than 10-15 eV thus I think I should see some ROS. Here is an excerpt of the output obtained after simulation :

I’m not a physicist at all and I’m not very comfortable with Geant4 at the moment. Here is my code, if someone has an idea what the problem can be!

Thank you very much for the help,

Regards,

Sarah

DetectorConstruction.cc :

#include "DetectorConstruction.hh"

// --- Geant4 materials
#include "G4NistManager.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "Materials.hh"

// --- Geant4 geometry
#include "G4Box.hh"
#include "G4Sphere.hh"
#include "G4LogicalVolume.hh"
#include "G4PVPlacement.hh"

// --- Visualization
#include "G4VisAttributes.hh"
#include "G4Colour.hh"

// --- Units
#include "G4SystemOfUnits.hh"

using namespace CLHEP;

DetectorConstruction::DetectorConstruction()
: G4VUserDetectorConstruction()
{}

DetectorConstruction::~DetectorConstruction()
{}

G4VPhysicalVolume* DetectorConstruction::Construct()
{
  // =========================================================
  // 1. MATERIALS
  // =========================================================
  // NIST manager gives access to predefined materials
  G4NistManager* nist = G4NistManager::Instance();

  G4Material* water = nist->FindOrBuildMaterial("G4_WATER");
  G4Material* air = nist->FindOrBuildMaterial("G4_AIR");
  G4Material* AGuIX = Materials::CreateAGuIX();
  

  // =========================================================
  // 2. WORLD VOLUME
  // =========================================================

  G4double worldSize = 20*um;

  G4Box* solidWorld =
    new G4Box("World",
              worldSize/2,
              worldSize/2,
              worldSize/2);

  G4LogicalVolume* logicWorld =
    new G4LogicalVolume(solidWorld,
                        air,
                        "World");

  G4VPhysicalVolume* physWorld =
    new G4PVPlacement(nullptr,
                      G4ThreeVector(),
                      logicWorld,
                      "World",
                      nullptr,
                      false,
                      0,
                      true);

  // =========================================================
  // 3. WATER SPHERE
  // =========================================================

  G4Sphere* solidSphere_inner_vesicle =
    new G4Sphere("WaterSphere",
                 0.0,          
                 5*um,      
                 0.0*deg,     
                 360.0*deg,   
                 0.0*deg,      
                 180.0*deg);   

  G4LogicalVolume* logicSphere_inner_vesicle =
    new G4LogicalVolume(solidSphere_inner_vesicle,
                        water,
                        "WaterSphere");

  new G4PVPlacement(nullptr,
                    G4ThreeVector(),
                    logicSphere_inner_vesicle,
                    "WaterSphere",
                    logicWorld,
                    false,
                    0,
                    true);
                    
  // =========================================================
  // 3. NANOPARTICLE
  // =========================================================

  G4Sphere* solidSphere_NP =
    new G4Sphere("Nanoparticle",
                 0.0,         
                 1*um,       
                 0.0*deg,    
                 360.0*deg,   
                 0.0*deg,      
                 180.0*deg);  
                 
  G4LogicalVolume* logicSphere_NP =
    new G4LogicalVolume(solidSphere_NP,
                        water,
                        "Nanoparticle");

  new G4PVPlacement(nullptr,
                    G4ThreeVector(),
                    logicSphere_NP,
                    "Nanoparticle",
                    logicSphere_inner_vesicle,
                    false,
                    0,
                    true);


  // =========================================================
  // 4. VISUALIZATION ATTRIBUTES
  // =========================================================

 
  auto worldVisAtt = new G4VisAttributes();
  worldVisAtt->SetVisibility(false);
  logicWorld->SetVisAttributes(worldVisAtt);

  auto sphereVisAtt = new G4VisAttributes(G4Colour(0.0, 0.0, 1.0, 0.2)); 
  sphereVisAtt->SetForceSolid(true); // force l'affichage en volume
  logicSphere_inner_vesicle->SetVisAttributes(sphereVisAtt);

  auto np_VisAtt = new G4VisAttributes(G4Colour(1.0, 0.0, 0.0)); 
  np_VisAtt->SetForceSolid(true);
  logicSphere_NP->SetVisAttributes(np_VisAtt);

  return physWorld;
}

PrimaryGeneratorAction.cc :

#include "PrimaryGeneratorAction.hh"

#include "G4ParticleTable.hh"
#include "G4ParticleDefinition.hh"
#include "G4SystemOfUnits.hh"
#include "G4ThreeVector.hh"
#include "Randomize.hh"

PrimaryGeneratorAction::PrimaryGeneratorAction()
{
    fParticleGun = new G4ParticleGun(1);

    // Photo-électron = électron
    auto particleDefinition =
        G4ParticleTable::GetParticleTable()->FindParticle("e-");

    fParticleGun->SetParticleDefinition(particleDefinition);

    fParticleGun->SetParticleEnergy(10*keV);

    fParticleGun->SetParticleMomentumDirection(G4ThreeVector(1,0,0));
}

PrimaryGeneratorAction::~PrimaryGeneratorAction()
{
    delete fParticleGun;
}

void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event)
{
    G4ThreeVector position(0,0,0);
    fParticleGun->SetParticlePosition(position);

    fParticleGun->GeneratePrimaryVertex(event);
}

SteppingAction.cc :

#include "SteppingAction.hh"
#include "G4Track.hh"
#include "G4ParticleDefinition.hh"
#include "G4StepPoint.hh"
#include "G4SystemOfUnits.hh"
#include "G4ThreeVector.hh"
#include "G4VProcess.hh"
#include "G4PhysicalVolumeStore.hh"

SteppingAction::SteppingAction() {

    stepCounter = 0;

    outAll.open("steps_all.csv");
    outAll << "Step#,X_um,Y_um,Z_um,KinE_MeV,dE_MeV,StepLength_mm,TrackLength_mm,Volume,Process\n";


    outROS.open("ROS.csv");
    outROS << "Name,X_um,Y_um,Z_um,Time_ns\n";
}

SteppingAction::~SteppingAction() {
    if (outAll.is_open()) outAll.close();
    if (outROS.is_open()) outROS.close();
}

void SteppingAction::UserSteppingAction(const G4Step* step)
{
    stepCounter++;

    auto track = step->GetTrack();
    auto particle = track->GetDefinition();
    auto name = particle->GetParticleName();

    // Position
    G4ThreeVector pos = step->GetPostStepPoint()->GetPosition();

    // Energie cinétique
    G4double kinE = step->GetPostStepPoint()->GetKineticEnergy();

    // Energie déposée
    G4double dE = step->GetTotalEnergyDeposit();

    // Longueurs
    G4double stepLength = step->GetStepLength();
    G4double trackLength = track->GetTrackLength();

    // Volume
    auto vol = step->GetPreStepPoint()->GetTouchableHandle()
                   ->GetVolume()->GetName();

    // Processus
    auto proc = step->GetPostStepPoint()->GetProcessDefinedStep();
    G4String procName = proc ? proc->GetProcessName() : "init";

    // Filtre spatial si tu veux
    if (pos.mag() > 5.005*um) return;

    // === ECRITURE CSV ===
    outAll << stepCounter << ","
           << pos.x()/um << ","
           << pos.y()/um << ","
           << pos.z()/um << ","
           << kinE/MeV << ","
           << dE/MeV << ","
           << stepLength/mm << ","
           << trackLength/mm << ","
           << vol << ","
           << procName << "\n";
}

PhysicsList.cc :

#include "PhysicsList.hh"

#include "G4EmDNAPhysics.hh"
#include "G4EmDNAChemistry.hh"
#include "G4DecayPhysics.hh"
#include "G4UnitsTable.hh"
#include "G4SystemOfUnits.hh"

PhysicsList::PhysicsList()
{
    SetVerboseLevel(1);

    // === PHYSIQUE Geant4-DNA (e-, protons, ions, basse énergie)
    RegisterPhysics(new G4EmDNAPhysics());

    // === CHIMIE (diffusion + réactions ROS)
    RegisterPhysics(new G4EmDNAChemistry());

    // === Désintégration standard
    RegisterPhysics(new G4DecayPhysics());
}

PhysicsList::~PhysicsList() {}

void PhysicsList::SetCuts()
{
    // DNA ne dépend pas des cuts classiques
    SetCutsWithDefault();
}

main.cc :

#include "G4RunManager.hh"
#include "G4UImanager.hh"

#include "G4VisExecutive.hh"
#include "G4UIExecutive.hh"

#include "DetectorConstruction.hh"
#include "PhysicsList.hh"
#include "PrimaryGeneratorAction.hh"
#include "SteppingAction.hh"
#include "G4Scheduler.hh"
#include "G4DNAChemistryManager.hh"


int main(int argc, char** argv)
{
    // 1. Run manager
    auto runManager = new G4RunManager;

    // 2. Geometry
    runManager->SetUserInitialization(new DetectorConstruction());

    // 3. Physics (DNA + chimie)
    runManager->SetUserInitialization(new PhysicsList());

    // 4. Primary generator
    runManager->SetUserAction(new PrimaryGeneratorAction());
    
    runManager->SetUserAction(new SteppingAction());

    runManager->Initialize();
    
    // === ACTIVER LA CHIMIE ===
    G4DNAChemistryManager::Instance()->Initialize();
    G4Scheduler::Instance()->SetVerbose(1);

    // 5. Visualization
    auto visManager = new G4VisExecutive;
    visManager->Initialize();

    // 6. UI
    G4UIExecutive* ui = nullptr;
    if (argc == 1) {
        ui = new G4UIExecutive(argc, argv);
    }

    auto UImanager = G4UImanager::GetUIpointer();
    if (ui) {
        UImanager->ApplyCommand("/control/execute vis.mac");
        ui->SessionStart();
        delete ui;
    }

    // ---- WARNING : ne pas delete visManager/runManager ----
    // delete visManager;
    // delete runManager;

    return 0;
}

There are 2 examples that show how to record chemical yields, which is probably what you’re after, called “chem4” and “chem5”.

The path in your installation is:
examples/extended/medical/dna/chem4

Or you can just take them from the code repo:

You can try also chem6 and Physics Processes — Book For Application Developers 11.4 documentation