Redirecting G4cout/G4cerr to a file using UI commands

Dear experts,

I am trying to redirect G4cout and G4cerr to files using the UI commands, but I can’t get it to work. I tested this with some of the example applications provided with the source code, but it doesn’t seem to work there either.

The simplest test I did was with the basic/B1 example. At the very beginning of the run1.mac file (as distributed), I added:

/control/cout/useBuffer 1
/control/cout/setCoutFile my_output.out
/control/cout/setCerrFile my_error.err

However, no output is written to the files.

I even considered that maybe the internal buffer was not being flushed, so I added a call to G4cout.flush() inside the class G4SteppingVerbose (and also in G4SteppingVerboseWithUnits). But the output from /tracking/verbose 1 (or 2) was still not redirected to the file as expected.

I would really appreciate any guidance or suggestions.

Best regards,
Alvaro
PS: I am using Geant4 version 11.3 on AlmaLinux 9 with GCC 11.5.

Hi,

I’m not quite sure what are you trying to get, but the last part of your question “output from /tracking/verbose 1 (or 2)” can be done simply dumping the terminal output to a file.

For example, in your command line (I’m supposing, you have /tracking/verbose _ and other commands you need in run1.mac)

./b1example -m run1.mac > myoutput.out

The system will create your file automatically. Naturally, the file will contain ALL the normal printout you could see normally on screen. ALL!!

Hi, @ayerbe , see the first part of what Alvaro wrote:

The point of his question is that apparently, when you try to redirect the G4cout and G4cerr actions to not go to the terminal, the output just disappears. Of course you can redirect everything at the command line, we know that works, and use it all the time. But Geant4 provides a different mechanism in addition, and it is that different mechanism which is apparently not working.

hi,

In case anyone needs a simple workaround, the following redirects G4cout and G4cerr to a file. Be careful about where you use it in MT mode


    std::ofstream dumpFile("g4out.txt");
    //save buffer to restore it later
    auto cout_buf = G4cout.rdbuf();
    auto cerr_buf = G4cerr.rdbuf();
    // redirect G4cout
    G4cout.rdbuf(dumpFile.rdbuf());
    G4cerr.rdbuf(dumpFile.rdbuf());

    // use G4cout/G4cerr normally

    dumpFile.flush();
    G4cout.rdbuf(cout_buf);
    G4cerr.rdbuf(cerr_buf);

It can also be wrapped in a small RAII helper:

class G4StreamRedirect {
public:
explicit G4StreamRedirect(const std::string& filename)
: file_(filename)
{
   if (!file_) {
      throw std::runtime_error(
         "Cannot open file: " + filename);
    }

    oldCout_ = G4cout.rdbuf(file_.rdbuf());
    oldCerr_ = G4cerr.rdbuf(file_.rdbuf());
}

    ~G4StreamRedirect()
    {
        if (oldCout_) G4cout.rdbuf(oldCout_);
        if (oldCerr_) G4cerr.rdbuf(oldCerr_);
    }

    // no copy allowed
    G4StreamRedirect(const G4StreamRedirect&) = delete;
    G4StreamRedirect& operator=(const G4StreamRedirect&) = delete;

private:
   std::ofstream file_;
   std::streambuf* oldCout_;
   std::streambuf* oldCerr_;
};

Best,
Alvaro

Is not ./myApp > out.txt 2> err.txt the simplest and most robust solution?

See what I wrote above:

In addition to that simple statement, the Geant4 mechanism is supposed to allow more finegrained control, such as selecting particular threads for redirection, etc. So the question is about the G4 functionality, not about “how do I redirect?”.

Agreed. But the workaround proposed above looks a bit heavyweight :wink:

For a standalone Geant4 application, redirecting the output from the shell may be sufficient.

In my case, the code is intended to run within the CMSSW framework, where shell-level redirection does not work as expected because Geant4 output is captured and suppressed by the framework. Implementing the redirection in C++ also provides explicit control over the logging behavior and makes it independent of the shell or execution environment.

For these reasons, I opted for the solution shown in the code snippet.

I opened a bugzilla ticket with the details,

I don’t think this is correct. If I remember correctly, output in CMSSW can be managed through MessageLogger, including redirection to files.