R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
R3BNeulandMCMon.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
14#include "R3BNeulandMCMon.h"
15#include "FairRootManager.h"
16#include "FairRun.h"
17#include "R3BMCTrack.h"
18#include "R3BNeulandCommon.h"
19#include "TDirectory.h"
20#include "TFile.h"
21#include <FairTask.h>
22#include <Math/Vector4Dfwd.h>
23#include <Rtypes.h>
24#include <RtypesCore.h>
25#include <TH2.h>
26#include <TH3.h>
27#include <TString.h>
28#include <array>
29#include <cmath>
30#include <cstddef>
31#include <fairlogger/Logger.h>
32#include <fstream>
33#include <iostream>
34#include <map>
35#include <numeric>
36#include <string>
37#include <vector>
38
39inline Bool_t IsPrimaryNeutron(const R3BMCTrack* mcTrack)
40{
41 return (mcTrack->GetPdgCode() == 2112 && mcTrack->GetMotherId() == -1);
42}
43
44inline Bool_t IsMotherPrimaryNeutron(const R3BMCTrack* mcTrack, const std::vector<R3BMCTrack*>& tracks)
45{
46 if (mcTrack->GetMotherId() < 0 || size_t(mcTrack->GetMotherId()) >= tracks.size())
47 {
48 return false;
49 }
50 return IsPrimaryNeutron(tracks.at(mcTrack->GetMotherId()));
51}
52
53inline Double_t GetKineticEnergy(const R3BMCTrack* mcTrack)
54{
55 return (mcTrack->GetEnergy() - mcTrack->GetMass()) * 1000.;
56}
57
58inline Double_t GetTheta(const R3BMCTrack* mcTrack) { return std::acos(mcTrack->GetPz() / mcTrack->GetP()); }
59
60static std::map<int, std::string> lookup_table = {
61 { -211, "pion" }, { 22, "gamma" }, { 111, "pion" }, { 211, "pion" }, { 2112, "n" },
62 { 2212, "p" }, { 1000010020, "d, t" }, { 1000010030, "d, t" }, { 1000020030, "alpha" }, { 1000020040, "alpha" },
63};
64
65std::string lookup(int pid)
66{
67 const auto l = lookup_table.find(pid);
68 if (l == lookup_table.end())
69 {
70 return std::string("heavy");
71 }
72 else
73 {
74 return l->second;
75 }
76}
77
78template <typename T>
79void writeout(std::map<T, TH1D*>& map, const std::string& what, const int nEvents = 0)
80{
81 if (!map.empty())
82 {
83 std::ostream* out = &std::cout;
84 std::ofstream of;
85 if (FairRun::Instance() != nullptr)
86 {
87 const std::string f =
88 std::string{ FairRun::Instance()->GetUserOutputFileName().Data() } + std::string(".") + what + ".dat";
89 std::cout << "Writing to file " << f << std::endl;
90 of.open(f);
91 out = &of;
92 }
93 gDirectory->mkdir(what.c_str());
94 gDirectory->cd(what.c_str());
95 for (const auto& kv : map)
96 {
97 auto h = kv.second;
98 const auto c = h->GetEntries();
99 if (nEvents > 0 && nEvents > c)
100 {
101 h->Fill(0., nEvents - c);
102 }
103 *out << kv.first << "\t" << c << "\t" << h->GetMean() << "\t" << h->GetMeanError() << std::endl;
104 kv.second->Write();
105 }
106 gDirectory->cd("..");
107 }
108}
109
110R3BNeulandMCMon::R3BNeulandMCMon(const Option_t* option)
111 : FairTask("R3B NeuLAND Neuland Monte Carlo Monitor")
112 , fIs3DTrackEnabled(false)
113 , fIsFullSimAnaEnabled(false)
114 , fPrimaryNeutronInteractionPoints("NeulandPrimaryPoints")
115 , fMCTracks("MCTrack")
116 , fNeulandPoints("NeulandPoints")
117 , nEvents(0)
118{
119 LOG(info) << "Using R3B NeuLAND Neuland Monte Carlo Monitor";
120
121 TString opt = option;
122 opt.ToUpper();
123 if (opt.Contains("3DTRACK"))
124 {
125 fIs3DTrackEnabled = true;
126 LOG(info) << "... with 3D track visualization";
127 }
128 if (opt.Contains("FULLSIMANA"))
129 {
131 LOG(info) << "... with full simulation neutron reaction product analysis";
132 }
133}
134
136{
138 fMCTracks.Init();
139 fNeulandPoints.init();
140
141 fhNPNIPsEToFVSTime = new TH2D("NPNIPEToFVSTime", "NPNIP E_{ToF} vs. NPNIP Time", 100, 0, 1000, 500, 0, 500);
142 fhNPNIPsEToFVSTime->GetXaxis()->SetTitle("NPNIP E_{ToF} [MeV]");
143 fhNPNIPsEToFVSTime->GetYaxis()->SetTitle("NPNIP t [ns]");
144
145 fhPDG = new TH1D("hPDG",
146 "Number of particles by PDG code created by primary neutron interaction resulting in a point",
147 8000,
148 -4000,
149 4000);
150 fhEPrimarys = new TH1D("hE_primarys", "Energy of primary particles", 10000, 0, 10000);
151 fhEPrimarys2 = new TH1D("hE_primarys2", "Tot. Energy of primary particles", 100000, 0, 100000);
152 fhEPrimaryNeutrons = new TH1D("hE_primary_neutrons", "Energy of primary Neutrons", 10000, 0, 10000);
153 fhErelMC = new TH1D("hErelMC", "Erel", 5000, 0, 5000);
154 fhEtotPrim = new TH1D("hE_tot_prim",
155 "Total Light Yield of non-neutron LandPoints created by primary neutron interaction(s)",
156 6000,
157 0,
158 6000);
159 fhEtot = new TH1D("hE_tot", "Total Light Yield of non-neutron LandPoints", 6000, 0, 6000);
160 fhESecondaryNeutrons = new TH1D(
161 "hE_secondary_neutrons", "Energy of neutron tracks created by primary neutron interaction", 6000, 0, 6000);
162 fhMotherIDs = new TH1D("hmotherIDs", "MotherIDs", 6010, -10, 6000);
163 fhPrimaryDaughterIDs = new TH1D("hprimary_daughter_IDs", "IDs of tracks with a primary mother", 6001, -1, 6000);
164 fhMCToF = new TH1D("fhMCToF", "Energy of primary Neutron - ToF Energy from PNIPS", 2001, -1000, 1000);
165
166 fhNPNIPSrvsz = new TH2D("fhNPNIPSrvsz", "NPNIPS R = #sqrt(x**2+y**2) vs z", 600, 1000, 4000, 40, 0, 200);
167 fhNPNIPSrvsz->GetXaxis()->SetTitle("NPNIP Z [cm]");
168 fhNPNIPSrvsz->GetYaxis()->SetTitle("NPNIP R [cm]");
169
170 fhNPNIPSxy = new TH2D("fhNPNIPSxy", "NPNIPS xy", 101, -200, 200, 101, -200, 200);
171 fhNPNIPSxy->GetXaxis()->SetTitle("NPNIP X [cm]");
172 fhNPNIPSxy->GetYaxis()->SetTitle("NPNIP Y [cm]");
173
174 fhnNPNIPs = new TH1D("fhnNPNIPs", "Number of NPNIPs per event", 10, -0.5, 9.5);
175
176 fhnProducts = new TH1D("nProducts", "Number of products created by primary neutron interaction", 20, -0.5, 19.5);
178 new TH1D("nProductsCharged",
179 "Number of products created by primary neutron interaction w/o gammas, neutrons, pion0",
180 20,
181 -0.5,
182 19.5);
183 fhSumProductEnergy = new TH1D("SumProductEnergy", "Sum product energy", 1000, 0, 1000);
184 fhnSecondaryNeutrons = new TH1D("NumberSecondaryNeutrons", "Number of Secondary Neutrons", 10, -0.5, 9.5);
185 fhnSecondaryProtons = new TH1D("NumberSecondaryProtons", "Number of Secondary Protons", 10, -0.5, 9.5);
186
187 // bins = 10**numpy.arange(-2,2.42,0.03)
188 std::array<double, 148> bins = {
189 1.00000000e-02, 1.07151931e-02, 1.14815362e-02, 1.23026877e-02, 1.31825674e-02, 1.41253754e-02, 1.51356125e-02,
190 1.62181010e-02, 1.73780083e-02, 1.86208714e-02, 1.99526231e-02, 2.13796209e-02, 2.29086765e-02, 2.45470892e-02,
191 2.63026799e-02, 2.81838293e-02, 3.01995172e-02, 3.23593657e-02, 3.46736850e-02, 3.71535229e-02, 3.98107171e-02,
192 4.26579519e-02, 4.57088190e-02, 4.89778819e-02, 5.24807460e-02, 5.62341325e-02, 6.02559586e-02, 6.45654229e-02,
193 6.91830971e-02, 7.41310241e-02, 7.94328235e-02, 8.51138038e-02, 9.12010839e-02, 9.77237221e-02, 1.04712855e-01,
194 1.12201845e-01, 1.20226443e-01, 1.28824955e-01, 1.38038426e-01, 1.47910839e-01, 1.58489319e-01, 1.69824365e-01,
195 1.81970086e-01, 1.94984460e-01, 2.08929613e-01, 2.23872114e-01, 2.39883292e-01, 2.57039578e-01, 2.75422870e-01,
196 2.95120923e-01, 3.16227766e-01, 3.38844156e-01, 3.63078055e-01, 3.89045145e-01, 4.16869383e-01, 4.46683592e-01,
197 4.78630092e-01, 5.12861384e-01, 5.49540874e-01, 5.88843655e-01, 6.30957344e-01, 6.76082975e-01, 7.24435960e-01,
198 7.76247117e-01, 8.31763771e-01, 8.91250938e-01, 9.54992586e-01, 1.02329299e+00, 1.09647820e+00, 1.17489755e+00,
199 1.25892541e+00, 1.34896288e+00, 1.44543977e+00, 1.54881662e+00, 1.65958691e+00, 1.77827941e+00, 1.90546072e+00,
200 2.04173794e+00, 2.18776162e+00, 2.34422882e+00, 2.51188643e+00, 2.69153480e+00, 2.88403150e+00, 3.09029543e+00,
201 3.31131121e+00, 3.54813389e+00, 3.80189396e+00, 4.07380278e+00, 4.36515832e+00, 4.67735141e+00, 5.01187234e+00,
202 5.37031796e+00, 5.75439937e+00, 6.16595002e+00, 6.60693448e+00, 7.07945784e+00, 7.58577575e+00, 8.12830516e+00,
203 8.70963590e+00, 9.33254301e+00, 1.00000000e+01, 1.07151931e+01, 1.14815362e+01, 1.23026877e+01, 1.31825674e+01,
204 1.41253754e+01, 1.51356125e+01, 1.62181010e+01, 1.73780083e+01, 1.86208714e+01, 1.99526231e+01, 2.13796209e+01,
205 2.29086765e+01, 2.45470892e+01, 2.63026799e+01, 2.81838293e+01, 3.01995172e+01, 3.23593657e+01, 3.46736850e+01,
206 3.71535229e+01, 3.98107171e+01, 4.26579519e+01, 4.57088190e+01, 4.89778819e+01, 5.24807460e+01, 5.62341325e+01,
207 6.02559586e+01, 6.45654229e+01, 6.91830971e+01, 7.41310241e+01, 7.94328235e+01, 8.51138038e+01, 9.12010839e+01,
208 9.77237221e+01, 1.04712855e+02, 1.12201845e+02, 1.20226443e+02, 1.28824955e+02, 1.38038426e+02, 1.47910839e+02,
209 1.58489319e+02, 1.69824365e+02, 1.81970086e+02, 1.94984460e+02, 2.08929613e+02, 2.23872114e+02, 2.39883292e+02,
210 2.57039578e+02,
211 };
212
213 fhElossVSLight = new TH2D("fhElossVSLight",
214 "Deposited Energy vs Generated Light",
215 bins.size() - 1,
216 bins.data(),
217 bins.size() - 1,
218 bins.data());
219 fhElossVSLightLog = new TH2D("fhElossVSLightLog", "Deposited Energy vs Generated Light", 600, -3, 3, 600, -3, 3);
220
221 fhThetaLight = new TH2D("fhThetaLight", "fhThetaLight", 200, -100, 100, 400, 0, 400);
222
224 {
225 // XYZ -> ZXY (side view)
226
227 fh3 = new TH3D("hMCTracks", "hMCTracks", 60, 1400, 1700, 50, -125, 125, 50, -125, 125);
228 fh3->SetTitle("NeuLAND MCTracks");
229 fh3->GetXaxis()->SetTitle("Z");
230 fh3->GetYaxis()->SetTitle("X");
231 fh3->GetZaxis()->SetTitle("Y");
232 FairRootManager::Instance()->Register("NeulandMCMon", "MC Tracks in NeuLAND", fh3, kTRUE);
233
234 fh3PNIP = new TH3D("h3DNPNIPS", "h3DNPNIPS", 60, 1400, 1700, 50, -125, 125, 50, -125, 125);
235 fh3PNIP->SetTitle("NeuLAND 3D NPNIPS");
236 fh3PNIP->GetXaxis()->SetTitle("Z");
237 fh3PNIP->GetYaxis()->SetTitle("X");
238 fh3PNIP->GetZaxis()->SetTitle("Y");
239 FairRootManager::Instance()->Register("Neuland3DPNIP", "First interactions in NeuLAND", fh3PNIP, kTRUE);
240 }
241
242 return kSUCCESS;
243}
244
245void R3BNeulandMCMon::Exec(Option_t*) // NOLINT: restructure later
246{
247 nEvents++;
248
249 const auto& npnips = fPrimaryNeutronInteractionPoints.get();
250 const auto& mcTracks = fMCTracks.Retrieve();
251 const auto& points = fNeulandPoints.get();
252
253 for (const auto& mcTrack : mcTracks)
254 {
255 // Distribution of MC Track mother id's
256 fhMotherIDs->Fill(mcTrack->GetMotherId());
257
258 // Energy of primary Particles
259 if (mcTrack->GetMotherId() == -1)
260 {
261 fhEPrimarys->Fill(GetKineticEnergy(mcTrack));
262 fhEPrimarys2->Fill(mcTrack->GetEnergy() * 1000.);
263 }
264
265 // Energy of primary Neutrons
266 if (IsPrimaryNeutron(mcTrack))
267 {
268 fhEPrimaryNeutrons->Fill(GetKineticEnergy(mcTrack));
269 }
270
271 // Remaining energy of neutrons after first interaction
272 if (IsMotherPrimaryNeutron(mcTrack, mcTracks) && mcTrack->GetPdgCode() == 2112)
273 {
275 }
276 }
277
278 fhnNPNIPs->Fill(npnips.size());
279 for (const auto& npnip : npnips)
280 {
281 // WIP: ToF Calculation -> Should respect other origin than 0,0,0,0.
282 const Double_t point_mag2 =
283 std::pow(npnip.GetX(), 2) + std::pow(npnip.GetY(), 2) + std::pow(npnip.GetZ(), 2); // cm²
284 const Double_t velocity_sq = point_mag2 / std::pow(npnip.GetTime(), 2); // ns²
285
286 const Double_t massNeutron = 939.565379; // MeV/c²
287 const Double_t ETimeOfFlight = massNeutron * ((1. / std::sqrt(1 - (velocity_sq / R3B::Neuland::CLight2))) - 1);
288
289 auto* mcTrack = mcTracks.at(npnip.GetTrackID());
290 fhNPNIPsEToFVSTime->Fill(ETimeOfFlight, npnip.GetTime());
291 fhMCToF->Fill(GetKineticEnergy(mcTrack) - ETimeOfFlight);
292 fhNPNIPSrvsz->Fill(npnip.GetZ(), std::sqrt(std::pow(npnip.GetX(), 2) + std::pow(npnip.GetY(), 2)));
293 fhNPNIPSxy->Fill(npnip.GetX(), npnip.GetY());
294 }
295
296 {
297 std::map<Int_t, Double_t> EtotPDG;
298 Double_t Etot = 0.;
299 Double_t EtotPrim = 0.;
300
301 for (const auto& point : points)
302 {
303 const R3BMCTrack* mcTrack = mcTracks.at(point.GetTrackID());
304
305 Etot += point.GetLightYield() * 1000.;
306
307 // Select tracks with a primary neutron mother
308 if (IsMotherPrimaryNeutron(mcTrack, mcTracks))
309 {
310
311 // Total energy of non-neutron secondary particles where mother is a primary neutron
312 if (mcTrack->GetPdgCode() != 2112)
313 {
314 EtotPrim += point.GetLightYield() * 1000.;
315 }
316
317 // Distribution of secondary particles
318 fhPDG->Fill(mcTrack->GetPdgCode());
319 fhPrimaryDaughterIDs->Fill(point.GetTrackID());
320
321 // Buld Histograms for each particle PDG if it doesn't exist
322 if (!fhmEPdg[mcTrack->GetPdgCode()])
323 {
324 TString name = TString("Light Yield of PID ") + TString::Itoa(mcTrack->GetPdgCode(), 10) +
325 TString(" with a primary neutron mother");
326 fhmEPdg[mcTrack->GetPdgCode()] =
327 new TH1D("hE_PDG_" + TString::Itoa(mcTrack->GetPdgCode(), 10), name, 3000, 0, 3000);
328 }
329 // Get Energy py particle where the mother is a primary neutron
330 fhmEPdg[mcTrack->GetPdgCode()]->Fill(point.GetLightYield() * 1000.); // point.GetEnergyLoss()*1000.);
331 } // end primary neutron mother
332
333 // Sum energy per particle type per event
334 if (!EtotPDG[mcTrack->GetPdgCode()])
335 {
336 EtotPDG[mcTrack->GetPdgCode()] = 0.;
337 }
338 EtotPDG[mcTrack->GetPdgCode()] += point.GetLightYield() * 1000.; // point.GetEnergyLoss()*1000.;
339
340 fhElossVSLight->Fill(point.GetEnergyLoss() * 1000., point.GetLightYield() * 1000.);
341 fhElossVSLightLog->Fill(std::log10(point.GetEnergyLoss() * 1000.),
342 std::log10(point.GetLightYield() * 1000.));
343
344 if (!fhmElossVSLightLogPdg[mcTrack->GetPdgCode()])
345 {
347 new TH2D("fhElossVSLightLog_" + TString::Itoa(mcTrack->GetPdgCode(), 10),
348 "Deposited Energy vs Generated Light",
349 600,
350 -3,
351 3,
352 600,
353 -3,
354 3);
355 }
356 fhmElossVSLightLogPdg[mcTrack->GetPdgCode()]->Fill(std::log10(point.GetEnergyLoss() * 1000.),
357 std::log10(point.GetLightYield() * 1000.));
358
359 fhThetaLight->Fill(GetTheta(mcTrack), point.GetLightYield() * 1000.);
360 }
361
362 fhEtot->Fill(Etot);
363 fhEtotPrim->Fill(EtotPrim);
364
365 for (const auto& kv : EtotPDG)
366 {
367 if (!fhmEtotPdg[kv.first])
368 {
369 TString name = TString("Sum Light Yield of PID ") + TString::Itoa(kv.first, 10);
370 fhmEtotPdg[kv.first] = new TH1D("fhEtotPDG_" + TString::Itoa(kv.first, 10), name, 3000, 0, 3000);
371 }
372 fhmEtotPdg[kv.first]->Fill(kv.second);
373
374 if (!fhmEtotPdgRel[kv.first])
375 {
376 TString name = TString("Percent Light Yield of PID ") + TString::Itoa(kv.first, 10) +
377 TString(" to total Light Yield.");
378 fhmEtotPdgRel[kv.first] = new TH1D("fhEtotPDGRel_" + TString::Itoa(kv.first, 10), name, 110, 0, 110);
379 }
380 if (Etot == 0)
381 {
382 fhmEtotPdgRel[kv.first]->Fill(0);
383 }
384 else
385 {
386 fhmEtotPdgRel[kv.first]->Fill(kv.second / Etot * 100.);
387 }
388 }
389 }
390
391 {
392 std::vector<int> primaryNeutronIDs;
393 std::map<int, std::vector<R3BMCTrack*>> tracksByPrimaryNeutronID;
394
395 const Int_t nTracks = mcTracks.size();
396 for (Int_t j = 0; j < nTracks; j++)
397 {
398 R3BMCTrack* track = mcTracks.at(j);
399 if (track->GetMotherId() == -1 && track->GetPdgCode() == 2112)
400 {
401 primaryNeutronIDs.push_back(j);
402 }
403 }
404
405 for (Int_t j = 0; j < nTracks; j++)
406 {
407 R3BMCTrack* track = mcTracks.at(j);
408 for (const Int_t primaryNeutronID : primaryNeutronIDs)
409 {
410 if (track->GetMotherId() == primaryNeutronID)
411 {
412 tracksByPrimaryNeutronID[primaryNeutronID].push_back(track);
413 }
414 }
415 }
416
417 for (const Int_t primaryNeutronID : primaryNeutronIDs)
418 {
419 auto& tracks = tracksByPrimaryNeutronID[primaryNeutronID];
420 fhnProducts->Fill(tracks.size());
421
422 fhnProductsCharged->Fill(std::accumulate(tracks.begin(),
423 tracks.end(),
424 0,
425 [](const int a, const R3BMCTrack* b)
426 {
427 if (b->GetPdgCode() == 2112 || b->GetPdgCode() == 22 ||
428 b->GetPdgCode() == 111)
429 {
430 return a;
431 }
432 else
433 {
434 return a + 1;
435 }
436 }));
437
438 fhnSecondaryNeutrons->Fill(std::accumulate(tracks.begin(),
439 tracks.end(),
440 0,
441 [](const int c, const R3BMCTrack* t)
442 {
443 if (t->GetPdgCode() == 2112)
444 {
445 return c + 1;
446 }
447 return c;
448 }));
449
450 fhnSecondaryProtons->Fill(std::accumulate(tracks.begin(),
451 tracks.end(),
452 0,
453 [](const int c, const R3BMCTrack* t)
454 {
455 if (t->GetPdgCode() == 2212)
456 {
457 return c + 1;
458 }
459 return c;
460 }));
461
462 const Double_t sumProductEnergy = std::accumulate(tracks.begin(),
463 tracks.end(),
464 0.,
465 [](const Double_t a, const R3BMCTrack* b)
466 { return a + 1000. * (b->GetEnergy() - b->GetMass()); });
467
468 fhSumProductEnergy->Fill(sumProductEnergy);
469
470 if (fIsFullSimAnaEnabled)
471 {
472 std::map<int, int> mCountByProductPdg;
473
474 for (const auto& track : tracks)
475 {
476 if (mCountByProductPdg.find(track->GetPdgCode()) == mCountByProductPdg.end())
477 {
478 mCountByProductPdg[track->GetPdgCode()] = 1;
479 }
480 else
481 {
482 mCountByProductPdg[track->GetPdgCode()]++;
483 }
484
485 auto& hEnergy = fhmEnergyByProductPdg[track->GetPdgCode()];
486 if (hEnergy == nullptr)
487 {
488 hEnergy = new TH1D(TString::Itoa(track->GetPdgCode(), 10),
489 TString::Itoa(track->GetPdgCode(), 10),
490 1000,
491 0,
492 1000);
493 }
494 hEnergy->Fill(1000. * (track->GetEnergy() - track->GetMass()));
495
496 const auto l = lookup(track->GetPdgCode());
497 auto& hEnergyRed = fhmEnergyByProductPdgReduced[l];
498 if (hEnergyRed == nullptr)
499 {
500 hEnergyRed = new TH1D(l.c_str(), l.c_str(), 1000, 0, 1000);
501 }
502 hEnergyRed->Fill(1000. * (track->GetEnergy() - track->GetMass()));
503 }
504
505 for (const auto& kv : mCountByProductPdg)
506 {
507 const int pdg = kv.first;
508 auto& hCount = fhmCountByProductPdg[pdg];
509 if (hCount == nullptr)
510 {
511 hCount = new TH1D(TString::Itoa(pdg, 10), TString::Itoa(pdg, 10), 10, 0, 10);
512 }
513 hCount->Fill(kv.second);
514
515 const auto l = lookup(kv.first);
516 auto& hCountRed = fhmCountByProductPdgReduced[l];
517 if (hCountRed == nullptr)
518 {
519 hCountRed = new TH1D(l.c_str(), l.c_str(), 10, 0, 10);
520 }
521 hCountRed->Fill(kv.second);
522 }
523
524 std::sort(tracks.begin(),
525 tracks.end(),
526 [](const R3BMCTrack* a, const R3BMCTrack* b) { return a->GetPdgCode() < b->GetPdgCode(); });
527
528 // std::vector<int> filteredPdgCodes{ 22, -211, 211, 111 };
529 std::vector<int> filteredPdgCodes{ 22, 111 };
530 const TString reaction = std::accumulate(
531 tracks.begin(),
532 tracks.end(),
533 TString(),
534 [&](TString s, const R3BMCTrack* b) -> TString
535 {
536 if (std::find(filteredPdgCodes.begin(), filteredPdgCodes.end(), b->GetPdgCode()) !=
537 filteredPdgCodes.end())
538 {
539 return s;
540 }
541 return s += "_" + TString::Itoa(b->GetPdgCode(), 10);
542 });
543
544 if (fhmEnergyByReaction[reaction] == nullptr)
545 {
546 fhmEnergyByReaction[reaction] = new TH1D(reaction, reaction, 1000, 0, 1000);
547 }
548 fhmEnergyByReaction[reaction]->Fill(sumProductEnergy);
549
550 for (const auto& track : tracks)
551 {
552 auto& hEnergy = fhmmEnergyByReactionByProductPdg[reaction][track->GetPdgCode()];
553 if (hEnergy == nullptr)
554 {
555 hEnergy = new TH1D(TString::Itoa(track->GetPdgCode(), 10) + reaction,
556 TString::Itoa(track->GetPdgCode(), 10) + reaction,
557 1000,
558 0,
559 1000);
560 }
561 hEnergy->Fill(1000. * (track->GetEnergy() - track->GetMass()));
562 }
563 }
564 }
565 }
566
567 {
568 ROOT::Math::PxPyPzEVector p4;
569 double m0 = 0;
570 for (const auto track : mcTracks)
571 {
572 if (track->GetMotherId() != -1)
573 {
574 break;
575 }
576 p4 += track->GetFourMomentum();
577 m0 += track->GetMass();
578 }
579 fhErelMC->Fill((p4.M() - m0) * 1e6);
580 }
581
582 if (fIs3DTrackEnabled)
583 {
584 fh3->Reset("ICES");
585 for (const auto& point : points)
586 {
587 if (point.GetLightYield() > 0)
588 {
589 const auto pos = point.GetPosition();
590 fh3->Fill(pos.Z(), pos.X(), pos.Y(), point.GetEnergyLoss() * 1000.);
591 }
592 }
593
594 fh3PNIP->Reset("ICES");
595 for (const auto& npnip : npnips)
596 {
597 fh3PNIP->Fill(npnip.GetZ(), npnip.GetX(), npnip.GetY(), npnip.GetTime());
598 }
599 }
600}
601
603{
604 TDirectory* tmp = gDirectory;
605 FairRootManager::Instance()->GetOutFile()->cd();
606
607 gDirectory->mkdir("NeulandMCMon");
608 gDirectory->cd("NeulandMCMon");
609
610 fhPDG->Write();
611 fhEPrimarys->Write();
612 fhEPrimarys2->Write();
613 fhEPrimaryNeutrons->Write();
614 fhErelMC->Write();
615 fhEtot->Write();
616 fhEtotPrim->Write();
617 fhESecondaryNeutrons->Write();
618 fhMotherIDs->Write();
619 fhPrimaryDaughterIDs->Write();
620 fhMCToF->Write();
621 fhNPNIPsEToFVSTime->Write();
622 fhNPNIPSrvsz->Write();
623 fhNPNIPSxy->Write();
624 fhnNPNIPs->Write();
625 fhThetaLight->Write();
626 fhElossVSLight->Write();
627 fhElossVSLightLog->Write();
628
629 gDirectory = tmp;
630 gDirectory->cd("NeulandMCMon");
631 gDirectory->mkdir("LightYield");
632 gDirectory->cd("LightYield");
633
634 gDirectory->mkdir("LightYieldByProductPdg");
635 gDirectory->cd("LightYieldByProductPdg");
636 for (const auto& kv : fhmEPdg)
637 {
638 kv.second->Write();
639 }
640 for (const auto& kv : fhmElossVSLightLogPdg)
641 {
642 kv.second->Write();
643 }
644 gDirectory->cd("..");
645
646 gDirectory->mkdir("SumLightYieldByProductPdg");
647 gDirectory->cd("SumLightYieldByProductPdg");
648 for (const auto& kv : fhmEtotPdg)
649 {
650 kv.second->Write();
651 }
652 gDirectory->cd("..");
653
654 gDirectory->mkdir("RelSumLightYieldByProductPdg");
655 gDirectory->cd("RelSumLightYieldByProductPdg");
656 for (const auto& kv : fhmEtotPdgRel)
657 {
658 kv.second->Write();
659 }
660 gDirectory->cd("..");
661
662 gDirectory = tmp;
663 gDirectory->cd("NeulandMCMon");
664 gDirectory->mkdir("Products");
665 gDirectory->cd("Products");
666
667 fhnProducts->Write();
668 fhnProductsCharged->Write();
669 fhSumProductEnergy->Write();
670 fhnSecondaryProtons->Write();
671 fhnSecondaryNeutrons->Write();
672
673 writeout(fhmEnergyByProductPdg, "EnergyByProduct");
674 writeout(fhmEnergyByProductPdgReduced, "EnergyByProductReduced");
675 writeout(fhmCountByProductPdg, "CountByProduct", nEvents);
676 writeout(fhmCountByProductPdgReduced, "CountByProductReduced", nEvents);
677 writeout(fhmEnergyByReaction, "EnergyByReaction");
678
680 {
681 gDirectory->mkdir("EnergyByReactionByProductPdg");
682 gDirectory->cd("EnergyByReactionByProductPdg");
683 for (const auto& kv : fhmmEnergyByReactionByProductPdg)
684 {
685 gDirectory->mkdir(kv.first);
686 gDirectory->cd(kv.first);
687 for (const auto& kv2 : kv.second)
688 {
689 kv2.second->Write();
690 }
691 gDirectory->cd("..");
692 }
693 gDirectory->cd("..");
694 }
695
696 gDirectory = tmp;
697}
698
ClassImp(R3B::Neuland::Cal2HitPar)
void writeout(std::map< T, TH1D * > &map, const std::string &what, const int nEvents=0)
Bool_t IsMotherPrimaryNeutron(const R3BMCTrack *mcTrack, const std::vector< R3BMCTrack * > &tracks)
Double_t GetKineticEnergy(const R3BMCTrack *mcTrack)
Double_t GetTheta(const R3BMCTrack *mcTrack)
Bool_t IsPrimaryNeutron(const R3BMCTrack *mcTrack)
std::string lookup(int pid)
static std::map< int, std::string > lookup_table
static const Double_t c
static const Double_t massNeutron
int GetPdgCode() const
Accessors.
Definition R3BMCTrack.h:48
double GetEnergy() const
Definition R3BMCTrack.h:63
double GetPz() const
Definition R3BMCTrack.h:59
double GetP() const
Definition R3BMCTrack.h:65
double GetMass() const
Definition R3BMCTrack.h:60
int GetMotherId() const
Definition R3BMCTrack.h:49
R3B::InputVectorConnector< R3BNeulandPoint > fPrimaryNeutronInteractionPoints
std::map< Int_t, TH1D * > fhmCountByProductPdg
R3B::InputVectorConnector< R3BNeulandPoint > fNeulandPoints
std::map< std::string, TH1D * > fhmCountByProductPdgReduced
std::map< TString, std::map< Int_t, TH1D * > > fhmmEnergyByReactionByProductPdg
std::map< Int_t, TH1D * > fhmEtotPdg
std::map< std::string, TH1D * > fhmEnergyByProductPdgReduced
R3BNeulandMCMon(const Option_t *option="")
std::map< Int_t, TH1D * > fhmEtotPdgRel
TH1D * fhPrimaryDaughterIDs
void Finish() override
TCAInputConnector< R3BMCTrack > fMCTracks
std::map< TString, TH1D * > fhmEnergyByReaction
std::map< Int_t, TH2D * > fhmElossVSLightLogPdg
void Exec(Option_t *) override
InitStatus Init() override
std::map< Int_t, TH1D * > fhmEnergyByProductPdg
Bool_t fIsFullSimAnaEnabled
TH1D * fhESecondaryNeutrons
std::map< Int_t, TH1D * > fhmEPdg
STL class.
constexpr auto CLight2
constexpr UInt_t nEvents