Store information in a dynamic vector during a Run with user hooks

Dear all,

I’m a beginner and I started recently to use Geant4. I’m writing to ask help about the adoption of the user hooks (G4UserTrackingAction, G4UserSteppingAction, …). In particular, I want to print information of the particle through UserSteppingAction into an output file.

What I did at the beginning in UserSteppingAction(const G4Step * theStep) is the printing in the output of the information in the following way:

void NewSteppingAction::UserSteppingAction(const G4Step * theStep) { ... G4StepPoint* pointIn=theStep->GetPreStepPoint(); G4StepPoint* pointOut=theStep->GetPostStepPoint(); ... G4ThreeVector posIn=pointIn->GetPosition(); G4ThreeVector posOut=pointOut->GetPosition(); extFile << posIn/cm<< " " << posOut/cm << G4endl; ... }

where the extFile has been opened at the beginning of the file file:

std::ofstream extFile(“ext_file.txt”);

The problem is that,in this way, the simulation keeps opening the file at each Step with an unuseful lose of the simulation time.
For this reason, I tried to save all the data in an array, declared at the beginning of the Run, and store the information in the output file only at the end of the run.

Indeed, UserSteppingAction allows to access to the information of G4Step and I thought to do the same by including NewG4Run, a new class inherited from G4Run with the definition of the dynamic vector std::vector<G4ThreeVector> vector; in the class. So, I implemented NewSteppingAction with the variable theRun declared with NewG4Run:

void NewSteppingAction::UserSteppingAction(const G4Step * theStep, NewG4Run* theRun)

I tried to do the same with NewG4RunAction (inherited from G4RunAction), without success: in both cases (with NewG4RunAction and NewG4Run), the simulation is not able to print any tipe of information (empty file).
Any suggestion, please? Also an explanation regarding how Geant4 works in order to pass the variables between Run, Step, Event and Track would be really appreciated!
Thank you in advance for your time!


Hi Christian

If you just want to write out some information from a single function, for example, your stepping action, you can adopt a very simple strategy - see code below. Notice the use of static to open the file just once (this fixes your “opening the file at each Step” problem). Also note the use of a mutex to prevent the stepping actions in different threads trying to write at the same time.

If you want to be more professional, or if you need to communicate between functions and classes, you have to be a little more sophisticated. You would have to open the file in your BeginOfRunAction, or even in your main program, and communicate it to other functions using extern or, even more professionally, by passing to the other functions, for example, through a constructor or access function. B1 does a bit of this in order to accumulate the energy deposition for an event.


#include "G4Threading.hh"
#include "G4AutoLock.hh"
#include "G4SystemOfUnits.hh"

void SteppingAction::UserSteppingAction(const G4Step* step)

  G4double edepStep = step->GetTotalEnergyDeposit();

  static G4Mutex stuffMutex = G4MUTEX_INITIALIZER;
  G4AutoLock al(&stuffMutex);
  static std::ofstream stuff("stuff.csv");
  static bool first = true;
  if (first) {
    first = false;
    stuff << "#,eDep/keV,..." << std::endl;
  stuff << ',' << edepStep/keV /* ... */ << std::endl;
1 Like

P.S. You can get a lot of information simply by /tracking/verbose 2, for example.

1 Like

Hello Christian,

I would advise against writing to a file during either UserEventAction or UserSteppingAction. In multi-threaded mode this will cause problems.

The data flow scheme that is complimentary to Geant4’s multi-threaded mode is: SensitiveDetector::ProcessHits → SensitiveDetector::HitCollection → Run::Merge → RunAction::EndOfRunAction.

You can implement your scoring using the Geant4’s HitCollection, or you can write your own storage, as you did.

1 Like

This presentation contains some basic info about hit processing and run/event/stack/track/step entities.

1 Like

Thank you very much for your help and the information provided!
I created my sensitive detector with my hit collections. The data flow I used is: SensitiveDetector::ProcessHits → SensitiveDetector::HitCollection → Run::RecordEvent->Run::Merge → RunAction::EndOfRunAction.
In this way, I recorded the information at the end of each event and merge the information from multi threading.


This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.