Output filename from macro

Hello,
I am quite new to Geant4 and using the last version Geant4 v11.0.3
Right now I am trying to update a bit a code that was written about 10 years ago, and my goal is to set the ROOT output file name directly from a macro file.
In the code already written, there is a file called PrimaryMessenger.cc, containing the following code:

fileCmd = new G4UIcmdWithAString(“/mydet/filename”,this);
fileCmd->SetGuidance(“Select ROOT file name”);
fileCmd->SetParameterName(“filename”,true);
fileCmd->SetDefaultValue(“output.root”);

So by using /mydet/filename whatever_name.root I should be able to output a ROOT file.
But I am also creating a ROOT output file from the RunAction.cc file, and giving it a name there:

auto analysisManager = G4AnalysisManager::Instance();
G4String fileName = “whatever_name.root”;
analysisManager->OpenFile(fileName);

So basically it works well when I change the filename from the RunAction.cc file but I’d like to use the fileCmd variable defined in the other file and all my tries were not successful.
My guess is that I’m overwriting the macro call with my hard coded RunAction.cc output file creation.
Would you have an idea on how to solve that? (I already searched for that on geant4 forum but nothing clearly helped me)
Thanks in advance.

I believe you need to implement the void RunActionMessenger::SetNewValue(G4UIcommand* command, G4String newValue) in your PrimaryMessenger.cc:

void RunActionMessenger::SetNewValue(G4UIcommand* command, G4String newValue) {
    if( command == fileCmd) {
        fRunAction->setFilename(newValue);
    }
}

, where you make the call to set the value for your filename in the runAction:

void RunAction::setFilename(G4String fileName) {
    fFileName = G4String(fileName);
}

The hardcoded fileName in your RunAction.cc needs to be replaced with the respective class data member:

auto analysisManager = G4AnalysisManager::Instance();
if(fFileName.size()) // or whatever check is necessesary :)
  analysisManager->OpenFile(fFileName);
else
  analysisManager->OpenFile("defaultFilename.root");
1 Like

Hello weller, thank you for your time.
After checking, I noticed I already have in my code the following lines, in the PrimaryMessenger.cc :

void PrimaryMessenger::SetNewValue(G4UIcommand* command, G4String newValue)
{
   if (command == fileCmd) { myAction->SetFilename(newValue); }
}

And the SetFilename() method is defined in the PrimaryGeneratorAction.hh as follows:

inline void SetFilename(G4String filename) { Filename = filename; }

When you said to make the call to set the value for the filename in RunAction.cc, it means that the SetFilename() method should be instantiated in the RunAction.hh file, or am I mistaking?

I might be overcomplicating things here, but I think I also lack C++ knowledge.

Thanks for your precious help once again, it is much appreciated!

thats good news for you, then you just have to get rid of the hardcoding of the filename (comment out the line G4String fileName = "whatever_name.root";, and use Filename in the next line instead of fileName

making that SetFilename method inline is smart :slight_smile:

Okay so the G4String Filename variable is a public variable instanciated in the PrimaryGeneratorAction class. When I try to call it from the RunAction.cc file, it says that the variable was not declared in this scope.
I included the PrimaryGeneratorAction.hh in the RunAction.hh.
My understanding is that to access private variables of a class I need to use Getters, but as Filename is a public one, I’m not sure what is needed here.
Sorry for this question, this is not really geant4 related but more C++ related, I think.
Thank you again, weller.

hm, in that case you could copy all the stuff that is related to the filename setting from PrimaryGeneratorAction to RunAction. I guess the filename in the PrimaryGeneratorAction refers to some sort of input file to configure the source?

I would say you need to create the RunActionMessenger-class, the RunAction needs a setter (the same as your inline function that you posted before), and you need to register the messenger in the constructor of the RunAction, to have access to “this” runAction object to call the myAction->SetFilename(…) method in the SetNewValue(…) method of the messenger. That should pretty much be it…

1 Like

I will try what you told me and make sure to come back here and post the solution if I succeed.
Thank you for your precious help and good evening.

1 Like

Hey,
As I said, if I find how to make it work I’ll come back and make sure I give the answer.
So I’ve found a workaround to my problem, using the syntax given in B5 basic example.
Instead of defining my own setFilename command, I’m using the analysisManager available macro command analysis/setFileName your_filename and I replaced my RunAction.cc implementation with the one of B5 RunAction.cc

Thanks again for your time @weller, I’m grateful for that (and happy new year!)

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