Conversation
ChristianTackeGSI
left a comment
There was a problem hiding this comment.
First round of comments.
Could we please get a test for this tooling somehow?
Maybe we could integrate it in some other test by running the simulation with two seeds and then compare the results? (which should hopefully be quite the same?)
|
The test will be the next step. First I want to get the macro and the script in which are the prerequisites for the test. |
examples/scripts/checkfiles.sh
Outdated
| simulation/Tutorial1/macros/tutorial1_TGeant4_pions.mc_p2.000_t0_n1.root | ||
| simulation/Tutorial1/macros/tutorial1_TGeant4_pions.mc_p2.000_t0_n10.root | ||
| simulation/Tutorial1/macros/tutorial1_pythia8_TGeant4_pions.mc_p2.000_t0_n10.root | ||
| simulation/Tutorial1/macros/tutorial1_pythia6_TGeant4_pions.mc_p2.000_t0_n10.root | ||
| simulation/Tutorial1/macros/tutorial1_urqmd_TGeant4.mc.root | ||
|
|
||
| simulation/Tutorial2/macros/tutorial2_pions.mc_p2.000_t0_n10.root | ||
| simulation/Tutorial2/macros/tutorial2_pions.mc_p2.000_t0_n10.sg1.root | ||
| simulation/Tutorial2/macros/tutorial2_pions.mc_p2.000_t0_n20.sg2.root | ||
| simulation/Tutorial2/macros/tutorial2_pions.mc_p2.000_t0_n130.bg.root | ||
| #simulation/Tutorial2/macros/digis.mc.root | ||
| #simulation/Tutorial2/macros/digis.mix.mc.root | ||
|
|
||
| simulation/Tutorial4/macros/data/testrun_align_TGeant4.root | ||
| simulation/Tutorial4/macros/data/testreco_align_TGeant4.root | ||
| #simulation/Tutorial4/macros/data/test.ana.root | ||
|
|
||
| simulation/rutherford/macros/data/test_TGeant4.mc.root | ||
| simulation/rutherford/macros/data/test1_TGeant4.mc.root | ||
|
|
||
| advanced/propagator/macros/prop.mc.root | ||
| #advanced/propagator/macros/prop.rk.cal.root | ||
|
|
||
| advanced/Tutorial3/macro/data/testrun_TGeant4.root | ||
| advanced/Tutorial3/macro/data/testdigi_TGeant4.root | ||
| advanced/Tutorial3/macro/data/testreco_TGeant4.root | ||
| advanced/Tutorial3/macro/data/testDiRePr_TGeant4.root | ||
| #advanced/Tutorial3/macro/data/testrecotimebased_TGeant4.root | ||
|
|
||
| #MQ/serialization/data_io/testinput1.root | ||
| #MQ/serialization/data_io/outputEx1Test.root | ||
| #MQ/serialization/data_io/testinput2.root | ||
| #MQ/serialization/data_io/outputEx2Test.root | ||
| #MQ/pixelDetector/macros/pixel_TGeant4.mc.root | ||
| #MQ/pixelDetector/macros/pixel_TGeant4.digi.root | ||
| #MQ/pixelDetector/macros/pixel_TGeant4.digiToBin.root | ||
| #MQ/pixelDetector/macros/MQ.pixel_TGeant4.hits.root | ||
| #MQ/pixelSimSplit/run/MQ.simulation_TGeant4.data.root |
There was a problem hiding this comment.
We should generate this list somehow, having it hardcoded like this will be a nightmare to maintain.
There was a problem hiding this comment.
I agree but I am not sure if this will be so easy. For the time being it would be good if we could keep the hard coded list.
There was a problem hiding this comment.
An idea would be to glob for ${dir1}/**/*.root and then iterate this list of files, if such a root file also exists in $dir2. We may have to add then another sanity check to the TreeCompareAuto.C macro that it will skip non-FairRoot root files, if there were any.
There was a problem hiding this comment.
The problem is that not all ROOT files should be tested. Not all off them contain the tree. That means that we have to filter the list afterwards to get only the list of files we want. In my opinion this isn't better than having a fixed list.
One solution would be to provide some benchmark files you want to compare and loop over these files and compare them with the newly produced ones. The downside of this is that we have to provide the benchmark files somehow.
There was a problem hiding this comment.
Another approach would be:
- Add a CMake list variable
FAIRROOT_SIMTREE_FILES_FOR_INTEGRITY_TESTING - Append file names to it in each of the local
CMakeLists.txtfiles from each example/test the file belongs to - Then
configure_file()thischeckfiles.shscript in a way that the contents of the CMake variable is added
Then the "authority" of naming relevant root files stays local to the individual example/test/lib. What do you think?
The macro compares the cbmsim trees of two ROOT files whose names are passed as arguments. If any difference is found the script fails. The script simply calls the macro for all relevant ROOT files which are produced when running the test suite. This allows to compare results before and after a change.
|
@ChristianTackeGSI, @dennisklein, thanks for all the suggestions. I hope I addressed them now all. |
4d8743c to
86a3f4b
Compare
examples/scripts/TreeCompareAuto.C
Outdated
| return 0; | ||
| } | ||
|
|
||
| TCanvas c1; |
There was a problem hiding this comment.
| TCanvas c1; |
and see following comment further down
There was a problem hiding this comment.
This is needed to suppress a warning/info from ROOT. I add a comment and renamed the variable.
| TString command1 = leafName + ">>htemp"; | ||
| tree1->Draw(command1); | ||
| int entries{0}; | ||
| float low{0.}; | ||
| float high{0.}; | ||
| int nBins{0}; | ||
| auto htemp = static_cast<TH1F*>(gPad->GetPrimitive("htemp")); | ||
| if (htemp) { | ||
| entries = htemp->GetEntries(); | ||
| nBins = htemp->GetNbinsX(); | ||
| low = htemp->GetXaxis()->GetXmin(); | ||
| high = htemp->GetXaxis()->GetXmax(); | ||
| } |
There was a problem hiding this comment.
| TString command1 = leafName + ">>htemp"; | |
| tree1->Draw(command1); | |
| int entries{0}; | |
| float low{0.}; | |
| float high{0.}; | |
| int nBins{0}; | |
| auto htemp = static_cast<TH1F*>(gPad->GetPrimitive("htemp")); | |
| if (htemp) { | |
| entries = htemp->GetEntries(); | |
| nBins = htemp->GetNbinsX(); | |
| low = htemp->GetXaxis()->GetXmin(); | |
| high = htemp->GetXaxis()->GetXmax(); | |
| } | |
| TH1F htemp; | |
| long long entries = tree1->GetEntries(); | |
| float value = 0; | |
| tree1->SetBranchAddress(leafName, &value); | |
| for (long long i = 0; i < entries; ++i) { | |
| tree1->GetEntry(i); | |
| htemp->Fill(value); | |
| } | |
| float low = htemp.GetXaxis()->GetXmin(); | |
| float high = htemp.GetXaxis()->GetXmax(); | |
| int nBins = htemp.GetNbinsX(); |
Why not something simple like this (have not tested the above code, but there should be some code similar to the above)?
What is the benefit to go through all this Draw() logic and global referencing via gPad?
We could also get rid of the htemp->Clear(); etc?
There was a problem hiding this comment.
For the hist case a bit further down, one could use a TFormula, but since it is just a subtraction, not even needed?
There was a problem hiding this comment.
I think this will not work since the value can be anything and must not be a float.
There was a problem hiding this comment.
Then why do you cast it to a TH1F* where the F stands for float? (Also, how are low and high then supposed to work if it is not a float?)
There was a problem hiding this comment.
(Also, how are low and high then supposed to work if it is not a float?)
Btw, TAxis::GetXmax() returns a double?!
There was a problem hiding this comment.
In our case, it should rather depend on the data in the root file, should it not?
There was a problem hiding this comment.
You can pass any number to TH1F::Fill() which will find the proper bin to increase. The type of the histogram only defines the maximum value which can be stored per bin. TH1C can only store values less than 128 per bin. TH1F stores the bin content in a float value.
These are the values you have to pass to the constructor which is the same for all types of one dimensional histograms
[in] | name | name of histogram (avoid blanks) | const char*
[in] | title | histogram title. | const char*
[in] | nbins | number of bins | int
[in] | xlow | low edge of first bin | double
[in] | xup | upper edge of last bin (not included in last bin) | double
TAxis::GetMax returns the value value of the upper edge of the last bin which is a double.
There was a problem hiding this comment.
Ok, thx, this I misunderstood. But then the common type to fill the histogram with is just double? So, read the tree content into doubles (instead of float as I did in my suggestion)?
There was a problem hiding this comment.
Or as a question: Which H1F API is used by TTree::Draw to add its stored values to the histogram?
There was a problem hiding this comment.
And whatever the code looks like, my points are:
- Why do we need to involve a
TCanvasobject, aTPadobject and a function calledDraw- all clearly graphics related entities - in a script that does not want to produce any graphics? Especially, if we have to create a randomTCanvasobject in the middle which is not used and just for some side effect? Don't you agree that this is a terrible program to write, read and maintain (source code readability AND computational complexity)? - Can we produce the histogram object without the indirection through the global object
gPad?
Rewrite function GetLeafNames
Use solution proposed by @dennisklein in FairRootGroup#1419
Fix variable names.
Remove C-style casts.
Use uniqe_ptr where possible.
Remove fixed tree name.
Use standard types instaed of ROOT types.
Use references instead of pointers where possible.
Remove unneeded functions.
General code improvements.
86a3f4b to
070d938
Compare
ChristianTackeGSI
left a comment
There was a problem hiding this comment.
I didn't follow all the discussions. So please excuse, if I duplicate anything! (In that case, just write a short "dupe" and press the resolve button!)
| TString command = leafName + "-" + leafName1 + ">>hist(20, -10.,10.)"; | ||
| tree1->Draw(command); | ||
| auto hist = static_cast<TH1F*>(gPad->GetPrimitive("hist")); |
There was a problem hiding this comment.
Can we please call this histogram hdifferences or something like that?
| TKey* key; | ||
| TIter keyIterator(keylist); | ||
| TString treeName; | ||
| int numTreeInFile{0}; | ||
| while ((key = static_cast<TKey*>(keyIterator()))) { |
There was a problem hiding this comment.
Can this be replaced by a TRangeDynCast?
Something like this maybe?
for (auto key : TRangeDynCast<TKey const>(keylist)) {
if (!key) {
continue;
}
…
}|
|
||
| bool operator==(TH1 const&, TH1 const&); | ||
|
|
||
| int TreeCompareAuto(TString fileName1 = "", TString fileName2 = "") |
There was a problem hiding this comment.
| int TreeCompareAuto(TString fileName1 = "", TString fileName2 = "") | |
| int TreeCompareAuto(TString fileName1, TString fileName2) |
We anyways expect non-empty arguments.
ChristianTackeGSI
left a comment
There was a problem hiding this comment.
As I recently learned, ReadObj returns an owning pointer.
| if (key->ReadObj()->InheritsFrom("TTree")) { | ||
| treeName = key->GetName(); | ||
| std::cout << "Found TTree with name " << treeName << std::endl; | ||
| numTreeInFile++; | ||
| } |
There was a problem hiding this comment.
TKey::ReadObj returns an owning pointer (see #1461).
Maybe move this in front of the loop?
std::unique_ptr<TTree> tree1;And then:
| if (key->ReadObj()->InheritsFrom("TTree")) { | |
| treeName = key->GetName(); | |
| std::cout << "Found TTree with name " << treeName << std::endl; | |
| numTreeInFile++; | |
| } | |
| tree1.reset(key->ReadObject<TTree>()); | |
| if (tree1) { | |
| treeName = key->GetName(); | |
| std::cout << "Found TTree with name " << treeName << std::endl; | |
| numTreeInFile++; | |
| } |
|
This PR has been automatically marked as stale because it has not had recent activity. It will not be closed. |
Add a macro which allows to compare the cbmsim tree of two different ROOT macros. The added script does this comparison for all relevant ROOT files produced by the test suite. This allows to easily compare the results before and after a change of FairRoot to see if there are unexpected changes.
Checklist: