-
Notifications
You must be signed in to change notification settings - Fork 96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Output object registered from generator class is not saved to ntuple. #1183
Comments
I have just added a dummy struct to the FairRoot's FairBoxGenerator, and the corresponding branch is saved in the output tree no problem. Can you share the code? |
Sure. I understand it's a bit convoluted, so please let me know if you want me to and I can try to simplify the problem a bit, if the problem is not immediately obvious. We have a main generator class that combines different generators for the beam track and interaction vertices, that's the one inheriting from FairGenerator. It's initialization method is defined here: https://gitlab.cern.ch/mgoncerz/fairmuone/-/blob/nlo_implementation_test/MUonE/MUonEGenerators/MUonEGenerator.cxx#L195, where by the end m_vertexGenerator->Init() is called and is a method defined by me in a base class for interaction vertex generators. This method is defined for the interface of a Mesmer generator here: https://gitlab.cern.ch/mgoncerz/fairmuone/-/blob/nlo_implementation_test/MUonE/MUonEGenerators/VertexGenerators/Mesmer/MUonEVertexGeneratorMesmer.cxx#L37, I'm sure this is run, because the steering card file defined there is being created. The object I'm trying to save (https://gitlab.cern.ch/mgoncerz/fairmuone/-/blob/nlo_implementation_test/MUonE/MUonEGenerators/VertexGenerators/Mesmer/MUonEVertexGeneratorMesmer.h#L43) is of type defined by external Fortran/c++ interface here https://gitlab.cern.ch/muesli/nlo-mc/mue/-/blob/master/code/MuEtree.h#L156 class Event {
public:
Int_t RunNr;
Long_t EventNr;
Double_t wgt_full, wgt_norun, wgt_lep, wgt_LO, wgt_NLO;
static const uint NC = 11;
std::array<Double_t, NC> coef;
Particle muin;
std::vector<Particle> fspart;
Event():
RunNr(0),EventNr(0),wgt_full(0),wgt_norun(0),wgt_lep(0),wgt_LO(0),wgt_NLO(0)
{};
bool Read(std::ifstream &, bool read_coef=true, bool debug=false);
void Print() const;
int GenerateEvent_mesmer(double* pmu);
virtual ~Event(){};
ClassDef(Event,7)
}; The linking and everything works fine, as other classes from the same interface work correctly, but just in case - the package is set up to be cloned and compiled during the compilation of our software in this cmake file -- https://gitlab.cern.ch/mgoncerz/fairmuone/-/blob/nlo_implementation_test/MUonE/MUonEGenerators/VertexGenerators/Mesmer/CMakeLists.txt The macro we're using for production is defined here -- https://gitlab.cern.ch/mgoncerz/fairmuone/-/blob/nlo_implementation_test/MUonE/macros/runProductionJob.C. Most of the code is just configuration of different steps and checks, the important part is from line 26 to 32, 65-75 and 86. I'm doing something exactly the same for our digitization task here - https://gitlab.cern.ch/mgoncerz/fairmuone/-/blob/nlo_implementation_test/MUonE/MUonEDigitization/Calorimeter/MUonECalorimeterDigitization.cxx#L128 and it works flawlessly. The content of our output file looks like this (as you can see, no MesmerEvent is not saved (unless it's hidden somewhere, but I can't find it): |
I've tried to narrow the problem down and added a simple struct in our main generator class (MUonEGenerator). Just a: class test {
public:
test(){};
Int_t testint = 5;
ClassDef(test,2)
}; It should be equivalent to your test. I've included it in the generator class as a pointer: registered in Init() with and also added line It still doesn't show in the ntuple, which makes me think the problem may lie in how we use the generator class in the macro maybe? |
Hi Mateusz, can you try to declare the object t as the member of the generator class? |
I had a closer look at your classes, and it looks that it should be working. Are you sure, that the MUonEVertexGeneratorMesmer::Init() is really called? The git diff to my dummy example shows diff --git a/generators/FairBoxGenerator.cxx b/generators/FairBoxGenerator.cxx
index 25d4f6b45..b3a8a11ae 100644
--- a/generators/FairBoxGenerator.cxx
+++ b/generators/FairBoxGenerator.cxx
@@ -30,6 +30,7 @@
#include "FairLogger.h"
#include "FairPrimaryGenerator.h"
+#include "FairRootManager.h"
#include <TDatabasePDG.h>
#include <TMath.h>
@@ -62,6 +63,7 @@ FairBoxGenerator::FairBoxGenerator()
, fPtRangeIsSet(0)
, fPRangeIsSet(0)
, fEkinRangeIsSet(0)
+ , fEle(new ele{0,1})
{
// Default constructor
}
@@ -89,6 +91,7 @@ FairBoxGenerator::FairBoxGenerator(Int_t pdgid, Int_t mult)
, fPtRangeIsSet(0)
, fPRangeIsSet(0)
, fEkinRangeIsSet(0)
+ , fEle(new ele{0,1})
{
// Constructor. Set default kinematics limits
SetPDGType(pdgid);
@@ -124,6 +127,8 @@ Bool_t FairBoxGenerator::Init()
LOG(fatal) << "FairBoxGenerator: PDG " << GetPDGType() << " not defined";
}
+ FairRootManager::Instance()->RegisterAny("elee", fEle, kTRUE);
+
if (fPhiMax - fPhiMin > 360) {
LOG(fatal) << "FairBoxGenerator:Init(): phi range is too wide: " << fPhiMin << "<phi<" << fPhiMax;
}
@@ -161,6 +166,8 @@ Bool_t FairBoxGenerator::ReadEvent(FairPrimaryGenerator* primGen)
Double32_t pabs = 0, phi, pt = 0, theta = 0, eta, y, mt, px, py, pz = 0;
GenerateEventParameters();
+ fEle->a = gRandom->Integer(100);
+ fEle->b = GetMultiplicity();
// Generate particles
for (Int_t k = 0; k < GetMultiplicity(); k++) {
phi = gRandom->Uniform(fPhiMin, fPhiMax) * TMath::DegToRad();
diff --git a/generators/FairBoxGenerator.h b/generators/FairBoxGenerator.h
index 90b97c591..a3e733f27 100644
--- a/generators/FairBoxGenerator.h
+++ b/generators/FairBoxGenerator.h
@@ -41,6 +41,11 @@
class FairPrimaryGenerator;
+struct ele{
+ int a;
+ int b;
+};
+
class FairBoxGenerator : public FairBaseMCGenerator
{
public:
@@ -134,6 +139,7 @@ class FairBoxGenerator : public FairBaseMCGenerator
FairBoxGenerator& operator=(const FairBoxGenerator&) = default;
private:
+ ele* fEle;
Double32_t fPtMin, fPtMax; // Transverse momentum range [GeV]
Double32_t fPhiMin, fPhiMax; // Azimuth angle range [degree]
Double32_t fEtaMin, fEtaMax; // Pseudorapidity range in lab system
diff --git a/generators/GenLinkDef.h b/generators/GenLinkDef.h
index 5fa5f680f..fb9d6bdbd 100644
--- a/generators/GenLinkDef.h
+++ b/generators/GenLinkDef.h
@@ -23,4 +23,6 @@
#pragma link C++ class FairYPtGenerator+;
#pragma link C++ class FairBaseMCGenerator+;
+#pragma link C++ class ele;
+
#endif And the output file has the correct branch
|
Just wondering (I am just learning FairRoot): I think LOG(info) << "CREATING BRANCH " << iter.first;
…
LOG(info) << "Creating branch for " << iter.first.c_str() << " with address " << obj; ( https://github.com/FairRootGroup/FairRoot/blob/master/base/sink/FairRootFileSink.cxx#L283-L303 ) |
You are totally right, Christian. Here's the message from my trivia example:
|
Thank you both for suggestions!
That's what I did. Sorry for not stating it more clearly. Just to make sure, I did
in the beginning of the Init method and both lines appear in the log file. I couldn't find any mention of neither Event or the test branch being created though, that is:
Full log here: |
It kind of seems like the generator is initialized too late for the I/O class to catch the registered branch. Could it be somehow related to the ordering in the production macro? As you've seen I've made it significantly more complex to account for all possible job configurations. Maybe the problem lies there? |
It might be a problem. Your generator initializes after the initialization of the sink. Since the branches are created during the Sink::Init() stage (CREATING BRANCH), the generators inform the FairRootManager about new branches too late (REGISTERING MESMER OUTPUT):
|
I found out the problem. There is difference in behavior between Geant3 and Geant4. |
Thanks! Just to confirm though, I set the sink after the generator is added. |
@karabowi If this is a real regression ("bug"), could you please create a very simple test case somehow? |
I don't know if it helps, but I may add that registering output in the MCStack works perfectly fine under Geant4, because I've used it previously to save signal tracks from the generator. |
IMHO the problem lies inside the VMC. It wouldn't be the first case that the different VMC engines behave differently, you are just the first person to register output branch in the generator initialization. I will communicate with the VMC expert to confirm my conclusion and see if there's any solution to the problem. @mgoncerz : meanwhile, can you create a workaround function in your generator with I am sitting in the meeting and coding currently is tough. |
@fuhlig1 thanks for tip! I have simply moved the RegisterAny to the constructor of the generator and it works like dandy also in Geant4. |
I can also confirm that moving registration to the constructor works flawlessly. Must be an issue of where the Init is called within the VMC.
No worries! :) |
Works as intended. I would like to add the topic to our discussion list on Monday.
|
Cool. You might consider merging it? At least as a quick warning to the user, that things might go wrong?
Just added it to the list. (You could have done that as well.) |
I have contacted Ivana and the difference between G3 and G4 is part of the design. Let me quote:
So closing the issue, as there will be no developments in the near future. |
Introduced new function `FairMCApplication::InitFinalizer()` which initializes event generator, tasks, and triggers `FairRootManager::WriteFolder()` function. This new function is called from the latter of `InitGeometry()` and `AddIons()`. Previously the funcionality of `InitFinalizer` was split between `InitGeometry()` and `AddIons()`, which caused problems because TGeant3 calls `AddIons()` first, `InitGeometry()` second, TGeant4 calls `InitGeometry()` first, `AddIons()` second. Current implementation assures that initialization of event generators and tasks come before `WriteFolder`. Fixes issues FairRootGroup#1183 and FairRootGroup#1567.
Introduced new function `FairMCApplication::InitFinalizer()` which initializes event generator, tasks, and triggers `FairRootManager::WriteFolder()` function. This new function is called from the latter of `InitGeometry()` and `AddIons()`. Previously the funcionality of `InitFinalizer` was split between `InitGeometry()` and `AddIons()`, which caused problems because TGeant3 calls `AddIons()` first, `InitGeometry()` second, TGeant4 calls `InitGeometry()` first, `AddIons()` second. Current implementation assures that initialization of event generators and tasks come before `WriteFolder`. Fixes issues FairRootGroup#1183 and FairRootGroup#1567.
Introduced new function `FairMCApplication::InitFinalizer()` which initializes event generator, tasks, and triggers `FairRootManager::WriteFolder()` function. This new function is called from `InitMC()` and from `InitOnWorker()` for TGeant4 MT mode. Previously the funcionality of `InitFinalizer` was split between `InitGeometry()` and `AddIons()`, which caused problems because TGeant3 calls `AddIons()` first, `InitGeometry()` second, TGeant4 calls `InitGeometry()` first, `AddIons()` second. Current implementation assures that initialization of event generators and tasks come before `WriteFolder`. Fixes issues FairRootGroup#1183 and FairRootGroup#1567.
Introduced new function `FairMCApplication::InitFinalizer()` which initializes event generator, tasks, and triggers `FairRootManager::WriteFolder()` function. This new function is called from `InitMC()` and from `InitOnWorker()` for TGeant4 MT mode. Previously the funcionality of `InitFinalizer` was split between `InitGeometry()` and `AddIons()`, which caused problems because TGeant3 calls `AddIons()` first, `InitGeometry()` second, TGeant4 calls `InitGeometry()` first, `AddIons()` second. Current implementation assures that initialization of event generators and tasks come before `WriteFolder`. Fixes issues FairRootGroup#1183 and FairRootGroup#1567.
Introduced new function `FairMCApplication::InitFinalizer()` which initializes event generator, tasks, and triggers `FairRootManager::WriteFolder()` function. This new function is called from `InitMC()` and from `InitOnWorker()` for TGeant4 MT mode. Previously the funcionality of `InitFinalizer` was split between `InitGeometry()` and `AddIons()`, which caused problems because TGeant3 calls `AddIons()` first, `InitGeometry()` second, TGeant4 calls `InitGeometry()` first, `AddIons()` second. Current implementation assures that initialization of event generators and tasks come before `WriteFolder`. Fixes issues FairRootGroup#1183 and FairRootGroup#1567.
Introduced new function `FairMCApplication::InitFinalizer()` which initializes event generator, tasks, and triggers `FairRootManager::WriteFolder()` function. This new function is called from `InitMC()` and from `InitOnWorker()` for TGeant4 MT mode. Previously the funcionality of `InitFinalizer` was split between `InitGeometry()` and `AddIons()`, which caused problems because TGeant3 calls `AddIons()` first, `InitGeometry()` second, TGeant4 calls `InitGeometry()` first, `AddIons()` second. Current implementation assures that initialization of event generators and tasks come before `WriteFolder`. Fixes issues FairRootGroup#1183 and FairRootGroup#1567.
Introduced new function `FairMCApplication::InitFinalizer()` which initializes event generator, tasks, and triggers `FairRootManager::WriteFolder()` function. This new function is called from `InitMC()` and from `InitOnWorker()` for TGeant4 MT mode. Previously the funcionality of `InitFinalizer` was split between `InitGeometry()` and `AddIons()`, which caused problems because TGeant3 calls `AddIons()` first, `InitGeometry()` second, TGeant4 calls `InitGeometry()` first, `AddIons()` second. Current implementation assures that initialization of event generators and tasks come before `WriteFolder`. Fixes issues FairRootGroup#1183 and FairRootGroup#1567.
Introduced new function `FairMCApplication::InitFinalizer()` which initializes event generator, tasks, and triggers `FairRootManager::WriteFolder()` function. This new function is called from `InitMC()` and from `InitOnWorker()` for TGeant4 MT mode. Previously the funcionality of `InitFinalizer` was split between `InitGeometry()` and `AddIons()`, which caused problems because TGeant3 calls `AddIons()` first, `InitGeometry()` second, TGeant4 calls `InitGeometry()` first, `AddIons()` second. Current implementation assures that initialization of event generators and tasks come before `WriteFolder`. Fixes issues #1183 and #1567.
I'm trying to register, using FairRootManager::Instance()->RegisterAny("event", m_event, kTRUE), a simple object containing event weights from a Monte Carlo generator, but the output is not saved to the final ntuple.
I'm doing it inside an Init method of a custom generator class, deriving from FairGenerator (which I'm sure is actually ran, because it sets other things as well). The generator is added in a production macro like this:
FairPrimaryGenerator* primGen = new FairPrimaryGenerator();
primGen->AddGenerator(generator);
run->SetGenerator(primGen);
Where run is FairRunSim. The same method works fine for me within FairTasks, running both under FairRunSim and FairRunAna.
The text was updated successfully, but these errors were encountered: