R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
R3BNeulandMultiplicityCalorimetricTrain.cxx
Go to the documentation of this file.
2#include "FairLogger.h"
3#include "FairRootManager.h"
4#include "FairRuntimeDb.h"
5#include "Math/Factory.h"
6#include "Math/Functor.h"
7#include "Math/Minimizer.h"
8#include "TDirectory.h"
9#include <TH2.h>
10#include <iostream>
11#include <numeric>
12
13/*
14 * ^
15 * |
16 * n |
17 * c 3
18 * l X X
19 * u X X
20 * s X X
21 * t X X
22 * e 0 X
23 * r | X X
24 * |---1 X X X X 2----->
25 * edep
26 */
27
29 std::string_view tracks,
30 std::string_view phits)
31 : FairTask("R3BNeulandMultiplicityCalorimetricTrain")
32 , fClusters(clusters)
33 , fTracks(tracks)
34 , fPHits(std::move(phits))
35 , fPar(nullptr)
36 , fUseHits(false)
37 , fEdepOpt({ 200, 25, 50, 1500 })
38 , fEdepOffOpt({ 5, 1, 0, 250 })
39 , fNclusterOpt({ 10, 5, 5, 50 })
40 , fNclusterOffOpt({ 2, 1, 0, 10 })
41 , fWeight(0)
42{
43}
44
46{
47 for (auto& nc : fCuts)
48 {
49 delete nc.second;
50 }
51}
52
54{
55 // Input
56 fClusters.init();
57 fTracks.init();
58 fPHits.init(true);
59
60 // Output Parameter Container
61 auto* ioman = FairRootManager::Instance();
62 if (ioman == nullptr)
63 {
64 LOG(fatal) << "R3BNeulandMultiplicityCalorimetricTrain:Init: No FairRootManager";
65 return kFATAL;
66 }
67
68 auto* rtdb = FairRuntimeDb::instance();
69 if (rtdb == nullptr)
70 {
71 LOG(fatal) << "R3BNeulandMultiplicityCalorimetricTrain::Init: No FairRuntimeDb!";
72 return kFATAL;
73 }
74 fPar = dynamic_cast<R3BNeulandMultiplicityCalorimetricPar*>(
75 rtdb->getContainer("R3BNeulandMultiplicityCalorimetricPar"));
76 if (fPar == nullptr)
77 {
78 LOG(fatal) << "R3BNeulandMultiplicityCalorimetricTrain::Init: No R3BNeulandMultiplicityCalorimetricPar!";
79 return kFATAL;
80 }
81 // FIXME: FairRuntimeDB needs to be forced to load the Data from the second file with Run Id 1
82 // rtdb->initContainers(rtdb->getCurrentRun()->getRunId(), 1);
83
84 return kSUCCESS;
85}
86
88{
89 const int nPN = fUseHits ? fPHits.get().size() : fTracks.get().size();
90
91 const auto& clusters = fClusters.get();
92 const auto nClusters = clusters.size();
93
94 if (nClusters == 0)
95 {
96 return;
97 }
98
99 const auto Edep =
100 std::accumulate(clusters.cbegin(),
101 clusters.cend(),
102 double{},
103 [](double sum, const R3BNeulandCluster& cluster) { return sum + cluster.GetE(); });
104
105 GetOrBuildHist(nPN)->Fill(static_cast<int>(std::ceil(Edep)), static_cast<double>(nClusters));
106}
107
109{
110 Optimize();
111
112 if (FairLogger::GetLogger()->IsLogNeeded(fair::Severity::debug))
113 {
114 Print();
115 }
116
117 auto* rtdb = FairRuntimeDb::instance();
118 rtdb->addRun(1);
119 fPar->SetNeutronCuts(fCuts);
120 fPar->setChanged();
121 rtdb->writeContainer(fPar, rtdb->getRun(1), nullptr);
122
123 TDirectory* tmp = gDirectory;
124 FairRootManager::Instance()->GetOutFile()->cd();
125
126 gDirectory->mkdir("NeulandMultiplicityCalorimetricTrain");
127 gDirectory->cd("NeulandMultiplicityCalorimetricTrain");
128
129 for (auto& nh : fHists)
130 {
131 nh.second->Write();
132 }
133
134 gDirectory = tmp;
135}
136
137void R3BNeulandMultiplicityCalorimetricTrain::Optimize()
138{
139 ROOT::Math::Minimizer* min = ROOT::Math::Factory::CreateMinimizer("Genetic");
140
141 ROOT::Math::Functor minimizor_functor([&](const double* cut) { return WastedEfficiency(cut); }, 4);
142 min->SetFunction(minimizor_functor);
143
144 min->SetLimitedVariable(0, "edep", fEdepOpt.at(0), fEdepOpt.at(1), fEdepOpt.at(2), fEdepOpt.at(3));
145 min->SetLimitedVariable(1, "edepoff", fEdepOffOpt.at(0), fEdepOffOpt.at(1), fEdepOffOpt.at(2), fEdepOffOpt.at(3));
146 min->SetLimitedVariable(
147 2, "ncluster", fNclusterOpt.at(0), fNclusterOpt.at(1), fNclusterOpt.at(2), fNclusterOpt.at(3));
148 min->SetLimitedVariable(
149 3, "nclusteroff", fNclusterOffOpt.at(0), fNclusterOffOpt.at(1), fNclusterOffOpt.at(2), fNclusterOffOpt.at(3));
150
151 min->Minimize();
152
153 LOG(info) << "R3BNeulandMultiplicityCalorimetricTrain::Optimize done!";
154}
155
156TCutG* R3BNeulandMultiplicityCalorimetricTrain::GetCut(const unsigned int nNeutrons,
157 const double edep,
158 const double edepoff,
159 const double ncluster,
160 const double nclusteroff)
161{
162 if (!fCuts[nNeutrons])
163 {
164 fCuts[nNeutrons] = new TCutG(TString(std::to_string(nNeutrons)), 4);
165 fCuts.at(nNeutrons)->SetVarX("Total Energy [MeV]");
166 fCuts.at(nNeutrons)->SetVarY("Number of Clusters");
167 }
168 auto cut = fCuts[nNeutrons];
169
170 // nmin: p0 = p1 = (-1,-1)
171 if (nNeutrons == fHists.begin()->first)
172 {
173 cut->SetPoint(0, -1, -1);
174 cut->SetPoint(1, -1, -1);
175 }
176 else
177 {
178 cut->SetPoint(0, -1, ncluster * (nNeutrons - 1) + nclusteroff);
179 cut->SetPoint(1, edep * (nNeutrons - 1) + edepoff, -1);
180 }
181
182 // nmax: p2 (inf, -1) p3 (-1, inf)
183 if (nNeutrons == fHists.rbegin()->first)
184 {
185 cut->SetPoint(2, 100000, -1);
186 cut->SetPoint(3, -1, 100000);
187 }
188 else
189 {
190 cut->SetPoint(2, edep * nNeutrons + edepoff, -1);
191 cut->SetPoint(3, -1, ncluster * nNeutrons + nclusteroff);
192 }
193
194 return cut;
195}
196
197double R3BNeulandMultiplicityCalorimetricTrain::WastedEfficiency(const double* d)
198{
199 double edep = d[0];
200 double edepoff = d[1];
201 double ncluster = d[2];
202 double nclusteroff = d[3];
203
204 double wasted_efficiency = 0;
205 for (auto& nh : fHists)
206 {
207 const unsigned int nNeutrons = nh.first;
208 const double efficiency =
209 ((double)GetCut(nNeutrons, edep, edepoff, ncluster, nclusteroff)->IntegralHist(nh.second) /
210 (double)nh.second->GetEntries());
211 wasted_efficiency += (1. - efficiency) * (1. + fWeight * nNeutrons);
212 }
213 return wasted_efficiency;
214}
215
217{
218 std::cout << "\t";
219 for (const auto& nh : fHists)
220 {
221 std::cout << nh.first << "n\t";
222 }
223 std::cout << std::endl;
224
225 for (const auto& nc : fCuts)
226 {
227 const unsigned int nOut = nc.first;
228 const TCutG* cut = nc.second;
229
230 std::cout << nOut << "n:\t";
231 for (const auto& nh : fHists)
232 {
233 std::cout << ((double)cut->IntegralHist(nh.second) / (double)nh.second->GetEntries()) << "\t";
234 }
235 std::cout << std::endl;
236 }
237 std::cout << std::endl;
238}
239
240TH2D* R3BNeulandMultiplicityCalorimetricTrain::GetOrBuildHist(const unsigned int i)
241{
242 if (fHists.find(i) == fHists.end())
243 {
244 const TString name = "hnPN" + std::to_string(i);
245 fHists[i] = new TH2D(name, name, 150, 0, 5000, 50, 0, 100);
246 fHists.at(i)->GetXaxis()->SetTitle("Total Energy [MeV]");
247 fHists.at(i)->GetYaxis()->SetTitle("Number of Clusters");
248 }
249 return fHists.at(i);
250}
NeuLAND number of clusters / energy - neutron multiplicity parameter storage.
R3BNeulandMultiplicityCalorimetricTrain(std::string_view clusters="NeulandClusters", std::string_view tracks="NeulandPrimaryTracks", std::string_view phits="NeulandPrimaryHits")