R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
R3BNeulandNeutronReconstructionStatistics.cxx
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) 2019 GSI Helmholtzzentrum für Schwerionenforschung GmbH *
3 * Copyright (C) 2019-2025 Members of R3B Collaboration *
4 * *
5 * This software is distributed under the terms of the *
6 * GNU General Public Licence (GPL) version 3, *
7 * copied verbatim in the file "LICENSE". *
8 * *
9 * In applying this license GSI does not waive the privileges and immunities *
10 * granted to it by virtue of its status as an Intergovernmental Organization *
11 * or submit itself to any jurisdiction. *
12 ******************************************************************************/
13
15#include "FairLogger.h"
16#include <FairRootManager.h>
17#include <TFile.h>
18#include <iostream>
19#include <numeric>
20
21template <class T>
22typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type almost_equal(T x, T y, int ulp)
23{
24 // the machine epsilon has to be scaled to the magnitude of the values used
25 // and multiplied by the desired precision in ULPs (units in the last place)
26 return std::abs(x - y) <= std::numeric_limits<T>::epsilon() * std::abs(x + y) * ulp
27 // unless the result is subnormal
28 || std::abs(x - y) < std::numeric_limits<T>::min();
29}
30
32 TString secondary,
33 TString predicted,
34 std::ostream& out)
35 : fPrimaryClusters(primary)
36 , fSecondaryClusters(secondary)
37 , fPredictedNeutrons(predicted)
38 , fPredictedName(predicted)
39 , fhTP(nullptr)
40 , fhFP(nullptr)
41 , fhFN(nullptr)
42 , fhTN(nullptr)
43 , fTP(0)
44 , fFP(0)
45 , fFN(0)
46 , fTN(0)
47 , fOut(out)
48 , fMult(100)
49{
50}
51
53{
54 try
55 {
56 fPrimaryClusters.Init();
57 fSecondaryClusters.Init();
58 fPredictedNeutrons.Init();
59 }
60 catch (const std::exception& e)
61 {
62 LOG(fatal) << "R3BNeulandNeutronReconstruction" << e.what();
63 }
64
65 TH1::AddDirectory(kFALSE);
66 fhTP = new TH1D("fhTP", "True Positive", 10, 0., 10.);
67 fhFN = new TH1D("fhFN", "False Negative", 10, 0., 10.);
68 fhFP = new TH1D("fhFP", "False Positive", 10, 0., 10.);
69 fhTN = new TH1D("fhTN", "True Negative", 30, 0., 30.);
70 fhF1 = new TH1D("fhF1", "F1 Value", 11, 0., 1.1);
71
72 return kSUCCESS;
73}
74
76{
77 const auto actualPositive = fPrimaryClusters.Retrieve();
78 const auto actualNegative = fSecondaryClusters.Retrieve();
79 const auto predictedPositive = fPredictedNeutrons.Retrieve();
80
81 auto comp = [](const R3BNeulandNeutron* n, const R3BNeulandCluster* c)
82 {
83 return almost_equal(c->GetT(), n->GetT(), 2) && almost_equal(c->GetPosition().X(), n->GetPosition().X(), 2) &&
84 almost_equal(c->GetPosition().Y(), n->GetPosition().Y(), 2) &&
85 almost_equal(c->GetPosition().Z(), n->GetPosition().Z(), 2);
86 };
87
88 fMult[predictedPositive.size()]++;
89
90 double truePositives = 0.;
91 for (const auto& c : actualPositive)
92 {
93 for (const auto& n : predictedPositive)
94 {
95 if (comp(n, c))
96 {
97 truePositives++;
98 break;
99 }
100 }
101 }
102 const double falseNegatives = (double)actualPositive.size() - truePositives;
103 fTP += truePositives;
104 fhTP->Fill(truePositives);
105 fFN += falseNegatives;
106 fhFN->Fill(falseNegatives);
107
108 double falsePositives = 0.;
109 for (const auto& c : actualNegative)
110 {
111 for (const auto& n : predictedPositive)
112 {
113 if (comp(n, c))
114 {
115 falsePositives++;
116 break;
117 }
118 }
119 }
120 const double trueNegatives = (double)actualNegative.size() - falsePositives;
121 fFP += falsePositives;
122 fhFP->Fill(falsePositives);
123 fTN += trueNegatives;
124 fhTN->Fill(trueNegatives);
125
126 const double precision = truePositives / (truePositives + falsePositives);
127 const double recall = truePositives / (truePositives + falseNegatives);
128
129 auto Fbeta = [&](double beta)
130 {
131 if (precision == 0. && recall == 0.)
132 return 0.;
133 return (1. + beta * beta) * (precision * recall) / ((beta * beta * precision) + recall);
134 };
135 fhF1->Fill(Fbeta(1.));
136}
137
139{
140 TDirectory* tmp = gDirectory;
141 FairRootManager::Instance()->GetOutFile()->cd();
142
143 gDirectory->mkdir(fPredictedName + "Statistics");
144 gDirectory->cd(fPredictedName + "Statistics");
145
146 fhTP->Write();
147 fhFN->Write();
148 fhFP->Write();
149 fhTN->Write();
150 fhF1->Write();
151
152 gDirectory = tmp;
153
154 const double precision = (double)fTP / ((double)fTP + (double)fFP);
155 const double recall = (double)fTP / ((double)fTP + (double)fFN);
156 auto Fbeta = [&](double beta)
157 { return (1. + beta * beta) * (precision * recall) / ((beta * beta * precision) + recall); };
158 const double accuracy = (double)(fTP + fTN) / (double)(fTP + fTN + fFP + fFN);
159
160 fOut << "PREC DATA\n";
161 fOut << fPredictedName << "\tTruePositive \t" << fTP << "\t" << (double)fTP / ((double)fTP + (double)fFN) << "\n"
162 << fPredictedName << "\tFalsePositive\t" << fFP << "\t" << (double)fFP / ((double)fTN + (double)fFP) << "\n"
163 << fPredictedName << "\tFalseNegative\t" << fFN << "\t" << (double)fFN / ((double)fTP + (double)fFN) << "\n"
164 << fPredictedName << "\tTrueNegative \t" << fTN << "\t" << (double)fTN / ((double)fTN + (double)fFP) << "\n"
165 << fPredictedName << "\tAccuracy\t" << accuracy << "\n"
166 << fPredictedName << "\tPrecision\t" << precision << "\n"
167 << fPredictedName << "\tSensitivity\t" << recall << "\n"
168 << fPredictedName << "\tF1\t" << Fbeta(1.) << "\n"
169 << "\n";
170
171 fOut << "MULT DATA\n";
172 const int sum = std::accumulate(fMult.begin(), fMult.end(), 0);
173 for (unsigned int i = 0; i < fMult.size(); i++)
174 {
175 fOut << i << "\t" << fMult[i] << "\t" << (double)fMult[i] / (double)sum << "\n";
176 }
177 fOut << "END" << std::endl;
178}
static const Double_t c
std::enable_if<!std::numeric_limits< T >::is_integer, bool >::type almost_equal(T x, T y, int ulp)
TVector3 GetPosition() const
Double_t GetT() const
R3BNeulandNeutronReconstructionStatistics(TString primary="NeulandNeutronClusters", TString secondary="NeulandPrimaryClusters", TString predicted="NeulandSecondaryClusters", std::ostream &out=std::cout)