20#include "ResultEvent.hh"
21#include "ResultEventTree.hh"
22#include "ResultHistogram.hh"
23#include "ResultHistogram2D.hh"
24#include "ResultSampler.hh"
25#include "ResultTree.hh"
27#include "analysis/Event.hh"
28#include "analysis/Model.hh"
29#include "analysis/Options.hh"
32#include "BDSOutputROOTEventOptions.hh"
33#include "BDSOutputROOTEventSampler.hh"
34#include "BDSVersionData.hh"
46#include "TDirectory.h"
54 std::vector<Result*> results;
62 std::vector<Result*>& results)
65 TDirectory* originalDirectory = TDirectory::CurrentDirectory();
70 TList* d1k = d1->GetListOfKeys();
71 for (
int i = 0; i < d1k->GetEntries(); ++i)
73 TObject* keyObject = d1k->At(i);
74 TObject* d1o = d1->Get(keyObject->GetName());
76 std::string objectName = std::string(keyObject->GetName());
77 std::string className = std::string(d1o->ClassName());
80 if (objectName ==
"Options" && className ==
"TTree")
82 std::vector<const char*> names;
83 TTree* options = (TTree*) d1->Get(objectName.c_str());
91 if (className ==
"TDirectory" || className ==
"TDirectoryFile")
93 TDirectory* subD1 = (TDirectory*)d1->Get(objectName.c_str());
94 TDirectory* subD2 = (TDirectory*)d2->Get(objectName.c_str());
102 else if(className ==
"TH1D")
104 TH1* d1h = (TH1*)d1->Get(objectName.c_str());
105 TH1* d2h = (TH1*)d2->Get(objectName.c_str());
113 else if(className ==
"TTree")
115 TTree* d1t = (TTree*)d1->Get(objectName.c_str());
116 TTree* d2t = (TTree*)d2->Get(objectName.c_str());
126 std::cout <<
"No comparison written for object named " << objectName
127 <<
" of type " << className << std::endl;
130 originalDirectory->cd();
137 c->
name = h1->GetName();
138 c->tolerance = Compare::Chi2Tolerance;
140 c->h1Entries = h1->GetEntries();
141 c->h2Entries = h2->GetEntries();
142 c->h1NXBins = h1->GetNbinsX();
143 c->h2NXBins = h2->GetNbinsX();
144 c->h1XMean = h1->GetMean();
145 c->h2XMean = h2->GetMean();
146 c->h1XRms = h1->GetRMS();
147 c->h2XRms = h2->GetRMS();
148 c->h1Integral= h1->Integral();
149 c->h2Integral= h2->Integral();
152 if (c->h1NXBins != c->h2NXBins)
155 results.push_back(c);
161 for (
int i=0;i < h1->GetNbinsX(); i++)
164 if (h1->GetBinError(i) > 0)
166 c->chi2 += std::pow(h1->GetBinContent(i)-h2->GetBinContent(i),2)/(std::pow(h1->GetBinError(i),2)+std::pow(h2->GetBinError(i),2));
171 if (!std::isnormal(ndof))
176 if(c->chi2 > Compare::Chi2Tolerance)
179 results.push_back(c);
184 std::vector<std::string> treesToIgnore = {
"Header",
"Model",
"Options",
"Run",
"Beam",
"ParticleData"};
187 std::string treeName = t1->GetName();
188 if (std::find(treesToIgnore.begin(), treesToIgnore.end(), treeName) != treesToIgnore.end())
190 else if (!strcmp(treeName.c_str(),
"Optics"))
195 else if (!strcmp(treeName.c_str(),
"Event"))
199 TDirectory* dir = t1->GetDirectory();
201 std::vector<std::string> samplerNames;
202 std::vector<std::string> samplerCNames;
203 std::vector<std::string> samplerSNames;
205 TTree* modTree =
dynamic_cast<TTree*
>(dir->Get(
"Model"));
209 else if (modTree->GetEntries() == 0)
215 modTree->GetEntry(0);
217 samplerCNames = mod->SamplerCNames();
218 samplerSNames = mod->SamplerSNames();
222 {std::cout <<
"Model not stored so can't compare sampler branches." << std::endl;}
223 Compare::EventTree(t1, t2, results, samplerNames, samplerCNames, samplerSNames);
230 c->t1NEntries = (int)t1->GetEntries();
231 c->t2NEntries = (int)t2->GetEntries();
233 TObjArray* oa1 = t1->GetListOfBranches();
234 TObjArray* oa2 = t2->GetListOfBranches();
236 for(
int j = 0; j<oa1->GetSize(); ++j)
238 bool branchFailed =
false;
239 TBranch* b1 = (TBranch*)((*oa1)[j]);
240 TBranch* b2 = (TBranch*)((*oa2)[j]);
243 b1->SetAddress(&t1v);
244 b2->SetAddress(&t2v);
245 for(
int i = 0; i<t1->GetEntries(); ++i)
250 if(std::abs((t1v - t2v )/t1v) > Compare::TreeTolerance)
259 {c->offendingBranches.emplace_back(std::string(b2->GetName()));}
261 results.push_back(c);
267 c->
name = t1->GetName();
270 c->t1NEntries = (int)t1->GetEntries();
271 c->t2NEntries = (int)t2->GetEntries();
274 std::map<std::string, bool> positiveValues = {
298 std::vector<std::string> errorBranches = {
299 "Sigma_Emitt_x",
"Sigma_Emitt_y",
300 "Sigma_Alpha_x",
"Sigma_Alpha_y",
301 "Sigma_Beta_x",
"Sigma_Beta_y",
302 "Sigma_Gamma_x",
"Sigma_Gamma_y",
303 "Sigma_Disp_x",
"Sigma_Disp_y",
304 "Sigma_Disp_xp",
"Sigma_Disp_yp",
305 "Sigma_Mean_x",
"Sigma_Mean_y",
306 "Sigma_Sigma_x",
"Sigma_Sigma_y",
307 "Sigma_Sigma_xp",
"Sigma_Sigma_yp",
308 "Sigma_Mean_E",
"Sigma_Sigma_E",
309 "Sigma_Mean_t",
"Sigma_Sigma_t"
312 TObjArray *oa1 = t1->GetListOfBranches();
316 for (
int j = 0; j< oa1->GetSize(); ++j)
318 TBranch* b1 = (TBranch*)(*oa1)[j];
319 std::string branchName = std::string(b1->GetName());
321 bool branchFailed =
false;
322 bool shouldBeGTEZero =
false;
329 if (Compare::IsInVector(branchName, errorBranches))
332 b1->SetAddress(&t1v);
333 for(
int i = 0; i<t1->GetEntries(); ++i)
337 if (LTZero(t1v) || NanOrInf(t1v))
347 shouldBeGTEZero = positiveValues[branchName];
349 std::string errBranchName =
"Sigma_" + branchName;
351 TBranch* b1err = t1->GetBranch(errBranchName.c_str());
352 TBranch* b2err = t2->GetBranch(errBranchName.c_str());
353 if (!b1err || !b2err)
356 TBranch* b2 = t2->GetBranch(branchName.c_str());
363 b1->SetAddress(&t1v);
364 b1err->SetAddress(&t1e);
365 b2->SetAddress(&t2v);
366 b2err->SetAddress(&t2e);
369 for(
int i = 0; i<t1->GetEntries(); ++i)
374 if (!std::isnormal(t1e) || !std::isnormal(t2e))
379 bool valueIsGood =
true;
382 if (!GTEZero(t1v) || !GTEZero(t2v))
383 {valueIsGood =
false;}
385 if (NanOrInf(t1v) || NanOrInf(t2v) || !valueIsGood)
388 std::cout <<
"Invalid value found for branch \"" << branchName <<
"\"" << G4endl;
389 std::cout << t1v <<
" " << t2v <<
" " << t1e <<
" " << t2e <<
" " << std::endl;
394 double chi2 = std::pow(t1v - t2v, 2) / (std::pow(t1e,2) + std::pow(t2e,2));
396 branchFailed = chi2 > Compare::OpticsSimgaTolerance;
400 std::cout << t1v <<
" " << t2v <<
" " << t1e <<
" "
401 << t2e <<
" " << chi2 << std::endl;
410 std::cout <<
"Branch was " << branchName << std::endl << std::endl;
411 c->offendingBranches.push_back(branchName);
415 results.push_back(c);
418void Compare::EventTree(TTree* t1, TTree* t2, std::vector<Result*>& results,
419 const std::vector<std::string>& samplerNames,
420 const std::vector<std::string>& samplerCNames,
421 const std::vector<std::string>& samplerSNames)
424 ret->
name = t1->GetName();
427 ret->t1NEntries = (int)t1->GetEntries();
428 ret->t2NEntries = (int)t2->GetEntries();
432 if (ret->t1NEntries != ret->t2NEntries)
435 results.push_back(ret);
440 G4bool processSamplers = !samplerNames.empty();
441 Event* evtLocal1 =
new Event(
false, processSamplers, BDSIM_DATA_VERSION);
442 Event* evtLocal2 =
new Event(
false, processSamplers, BDSIM_DATA_VERSION);
443 evtLocal1->
SetBranchAddress(t1, &samplerNames,
false,
nullptr,
nullptr, &samplerCNames, &samplerSNames);
444 evtLocal2->
SetBranchAddress(t2, &samplerNames,
false,
nullptr,
nullptr, &samplerCNames, &samplerSNames);
446 for (
long int i = 0; i < (
long int)t1->GetEntries(); i++)
449 re.
name = std::to_string(i);
451 re.
objtype =
"Event of Event Tree";
454 Int_t bytesLoaded1 = t1->GetEntry(i);
455 Int_t bytesLoaded2 = t2->GetEntry(i);
456 std::cout <<
"Bytes loaded (1) " << bytesLoaded1 << std::endl;
457 std::cout <<
"Bytes loaded (2) " << bytesLoaded2 << std::endl;
460 std::cout << evtLocal1 <<
" " << evtLocal2 << std::endl;
469 for (
auto j = 0; j < (int)evtLocal1->
Samplers.size(); j++)
474 ret->eventResults.push_back(re);
481 results.push_back(ret);
497 std::string samplerName = e1->samplerName;
498 if (samplerName ==
"sampler")
499 {samplerName = e2->samplerName;}
503 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"n");}
507 if (
Diff(e1->z, e2->z))
508 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"z");}
509 if (
Diff(e1->S, e2->S))
510 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"S");}
512 for (
int i = 0; i < e1->n; i++)
514 if (
Diff(e1->energy, e2->energy, i))
515 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"energy");}
516 if (
Diff(e1->x, e2->x, i))
517 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"x");}
518 if (
Diff(e1->y, e2->y, i))
519 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"y");}
520 if (
Diff(e1->xp, e2->xp, i))
521 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"xp");}
522 if (
Diff(e1->yp, e2->yp, i))
523 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"yp");}
524 if (
Diff(e1->zp, e2->zp, i))
525 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"zp");}
526 if (
Diff(e1->p, e2->p, i))
527 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"p");}
528 if (
Diff(e1->T, e2->T, i))
529 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"T");}
530 if (
Diff(e1->partID, e2->partID, i))
531 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"partID");}
533 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"charge");}
535 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"isIon");}
537 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"ionA");}
539 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"ionZ");}
541 {rs.passed =
false; rs.offendingLeaves.emplace_back(
"nElectrons");}
547 {re->
passed =
false; re->offendingBranches.push_back(samplerName);}
548 re->samplerResults.push_back(rs);
553 bool allPassed =
true;
554 const int titleWidth = 20;
555 const int fullWidth = titleWidth + 22;
556 std::cout << std::endl;
557 std::cout <<
"N results: " << results.size() << std::endl;
558 std::cout <<
"Comparison: " << std::setw(titleWidth) <<
"Object Name" <<
" "
559 <<
"Result" << std::endl;
560 std::cout << std::setfill(
'-') << std::setw(fullWidth) <<
" " << std::endl;
561 std::cout << std::setfill(
' ');
562 for (
const auto& result : results)
564 if (!(result->passed))
567 std::cout << *result << std::endl;
570 {std::cout <<
"Comparison: " << std::setw(20) << result->name <<
" : Passed" << std::endl;}
577 std::cout <<
"Comparison file has no " << className <<
" called " << objectName <<
". Skipping" << std::endl;
584 if (aString.compare(0, prefix.length(), prefix) == 0)
589 catch(
const std::out_of_range&)
594bool Compare::IsInVector(std::string key,
const std::vector<std::string>& vec)
596 return std::find(vec.begin(), vec.end(), key) != vec.end();
Information stored per sampler per event.
std::vector< bool > isIon
These are not filled by default.
std::vector< int > nElectrons
These are not filled by default.
std::vector< int > ionA
These are not filled by default.
std::vector< int > charge
These are not filled by default.
std::vector< int > ionZ
These are not filled by default.
BDSOutputROOTEventSampler< double > * GetPrimaries()
Accessor.
std::vector< BDSOutputROOTEventSampler< double > * > Samplers
Local variable ROOT data is mapped to.
void SetBranchAddress(TTree *t, const RBDS::VectorString *samplerNames=nullptr, bool allBranchesOn=false, const RBDS::VectorString *branchesToTurnOn=nullptr, const RBDS::VectorString *collimatorNamesIn=nullptr, const RBDS::VectorString *samplerCNamesIn=nullptr, const RBDS::VectorString *samplerSNamesIn=nullptr)
void SetBranchAddress(TTree *t, bool allBranchesOn=true, const RBDS::VectorString *branchesToTurnOn=nullptr)
Set the branch addresses to address the contents of the file.
std::vector< std::string > SamplerNames() const
Access all the unique sampler names from the model.
void SetBranchAddress(TTree *t, bool allBranchesOn=true, const RBDS::VectorString *branchesToTurnOn=nullptr)
Set the branch addresses to address the contents of the file.
BDSOutputROOTEventOptions * options
Member that ROOT can map file data to locally.
Result of comparison of all entries in an Event tree in BDSIM output.
Result of comparison of single entry of an Event tree in BDSIM output.
Result of comparing 2 histograms.
Result of comparison of a sampler branch.
Result of comparing 2 TTrees.
std::string name
Name of object being compared in files.
bool passed
Whether it passed or not.
std::string objtype
Name of class of object being compared in files.
std::vector< Result * > Files(TFile *f1, TFile *f2)
Compare two files.
void Trees(TTree *t1, TTree *t2, std::vector< Result * > &results)
Compare two TTrees.
bool Summarise(const std::vector< Result * > &results)
Loop over results and print any failed ones. Returns true if all passed.
bool Diff(const std::vector< T > &v1, std::vector< T > &v2, int i)
Return true if they're different.
bool hasPrimaries
Bool for checking if primaries were written to file.
void PrintNoMatching(std::string className, std::string objectName)
void Histograms(TH1 *h1, TH1 *h2, std::vector< Result * > &results)
Compare two histogams.
void Directories(TDirectory *d1, TDirectory *d2, std::vector< Result * > &results)
void Optics(TTree *t1, TTree *t2, std::vector< Result * > &results)
bool StringStartsWith(std::string aString, std::string prefix)
Check whether a string is prefixed with another string.