KaliVeda
Toolkit for HIC analysis
Loading...
Searching...
No Matches
MCSampler.cpp
1//Created by KVClassFactory on Thu May 7 14:35:05 2015
2//Author: John Frankland,,,
3
4#include "MCSampler.h"
5#include "TRandom.h"
6
7#include <TGraph.h>
8#include <TMultiGraph.h>
9#include "TPad.h"
10#include "TH1.h"
11
13
14
15namespace MicroStat {
16
17
20
21 void MCSampler::init()
22 {
23 // default initialisations
24 fWeightList = 0;
25 fLastPicked = 0;
26 fTheLegend = 0;
27 fLegendProbaMin = 0;
28 fModifyMasses = kFALSE;
29 }
30
31
32
35
36 void MCSampler::initialiseWeightList()
37 {
38 // set up the TClonesArray
39
40 fWeightList = new TClonesArray(fWeight);
41 }
42
43
44
47
48 MCSampler::MCSampler()
49 {
50 // Default constructor
51 init();
52 }
53
54
55
56
59
60 MCSampler::MCSampler(const Char_t* name, const Char_t* title) : KVBase(name, title)
61 {
62 // Write your code here
63 init();
64 }
65
66
67
70
72 {
73 // Destructor
74
76 }
77
78
79
82
83 void MCSampler::SetEventList(TTree* t, const TString& branchname)
84 {
85 // Define the TTree or TChain containing all possible events (partitions).
86
88 fBranch = t->GetBranch(branchname);
89 if (!fBranch) {
90 Error("SetEventList", "cannot find branch %s", branchname.Data());
91 }
92 fPartition = 0;
94 }
95
96
97
101
103 {
104 // Set the kind of statistical weight to be used
105 // This is the name of a class derived from MicroStat::StatWeight
106
107 fWeight = TClass::GetClass(w);
108 if (!fWeight) {
109 Error("SetStatWeight", "class %s not found", w.Data());
110 }
111 }
112
113
114
118
120 {
121 // if nuclear masses are modified, we have to update those in the
122 // partition read from file
123 for (auto& n : EventIterator(fPartition)) n.SetA(n.GetA());
124 }
125
126
127
132
133 void MCSampler::CalculateWeights(Double_t excitation_energy)
134 {
135 // calculate weights of all partitions for the given excitation energy
136 // (in MeV) of the initial compound nucleus
137
138 //Info("CalculateWeights","Calculating channel weights for E*=%f",excitation_energy);
139
141
142 fSumWeights = 0;
143
144 for (int i = 0; i < fPartitions; i++) {
146 GetPartition(i);
148 w->SetWeight(fPartition, excitation_energy + fPartition->GetChannelQValue());
149 w->SetIndex(i);
150 fSumWeights += w->GetWeight();
151
152 //std::cout << i << " Q=" << fPartition->GetChannelQValue() << " weight=" << w->GetWeight() << endl;
153 }
154
155 // sort weights in decreasing order
156 fWeightList->Sort();
157 }
158
159
160
168
170 {
171 // Return the TTree index of a random channel according to the
172 // previously calculated weights
173 // The corresponding weight for the chosen channel can be retrieved
174 // by calling GetRandomChannelWeight()
175 // If no channel is open (i.e. all weights = 0, E* < Q value of first channel),
176 // we return -1.
177
179
180 int i;
181 for (i = 0; i < fPartitions; i++) {
183 if (x < w) break;
184 x -= w;
185 }
186 if (i == fPartitions) {
187 fLastPicked = nullptr;
188 return -1;
189 }
191 return fLastPicked->GetIndex();
192 }
193
194
195
197
198 void MCSampler::SetBranch(TTree* theTree, const TString& bname, void* variable, const TString& vartype)
199 {
200 TString leaflist = bname + "/";
201 leaflist += vartype;
202 TBranch* b = theTree->GetBranch(bname);
203 if (!b) theTree->Branch(bname, variable, leaflist);
204 else b->SetAddress(variable);
205 }
206
207
208
218
220 {
221 // If branch 'bname' does not exist in 'theTree', it will be created and linked to
222 // 'event' which must contain the address of a valid KVEvent object.
223 // If branch already exists, we link it to 'event'.
224 //
225 // Branches will also be created/filled with the following information:
226 // ESTAR/D the excitation energy (Exx)
227 // EDISP/D the available kinetic energy
228 // IPART/I the partition index
229 TBranch* b = theTree->GetBranch(bname);
230 if (!b) {
231 theTree->Branch(bname, "KVEvent", event, 10000000, 0)->SetAutoDelete(kFALSE);
232 }
233 else {
234 b->SetAddress(event);
235 }
236 SetBranch(theTree, "ESTAR", &ESTAR, "D");
237 SetBranch(theTree, "EDISP", &EDISP, "D");
238 SetBranch(theTree, "IPART", &IPART, "L");
239 }
240
241
242
251
252 void MCSampler::GenerateEvents(TTree* theTree, KVEvent* event, Double_t Exx, Long64_t npartitions, Long64_t nev_part)
253 {
254 // Generate (npartitions*nev_part) events for a given value of excitation energy 'Exx' [MeV].
255 // For efficiency, for each chosen partition we generate nev_part events.
256 // This means :
257 // - calculating the statistical weight of all available decay channels/partitions
258 // - picking a channel at random
259 // - generating momenta of all nuclei in chosen channel
260 // - filling the TTree with the new event
261
262 Info("GenerateEvents", "Generating events for E*=%f", Exx);
263
264 if (!SetExcitationEnergy(Exx)) {
265 Error("GenerateEvents", "Excitation energy is too low, no channels are open");
266 return;
267 }
268
269 // generate events
270 while (npartitions--) {
271
273
274
275 for (Long64_t iev = 0; iev < nev_part; iev++) {
276
277 // generate nev_part events for chosen partition
278
279 GenerateEvent(theTree, event);
280
281 }
282
283 }
284
285 }
286
287
288
293
295 {
296 // Define excitation energy for random event generation
297 // This will calculate the channel weights for all partitions
298 // If sumOfWeights = 0 i.e. no channels are open, return kFALSE
299
300 ESTAR = Exx;
301 CalculateWeights(Exx);
302 if (fSumWeights == 0) return kFALSE;
303 return kTRUE;
304 }
305
306
311
313 {
314 // Pick a random decay channel with excitation energy given to
315 // previous call to SetExcitationEnergy method.
316 // Returns kFALSE if no channel is open.
317
319 if (IPART < 0) return kFALSE;
320
322
325
326 return kTRUE;
327
328 }
329
330
340
342 {
343 // Generate 1 kinematical event for the partition previously
344 // picked at random after calling:
345 // SetExcitationEnergy(E*);
346 // SetDecayChannel();
347 // theTree->Fill() is automatically called.
348 // This method can be called many times before either
349 // 1) picking a new decay channel
350 // 2) changing the energy
351
353
354 theTree->Fill();
355
357
358 }
359
360
361
371
372 void MCSampler::PlotProbabilities(double emin, double emax, double estep, Option_t* opt)
373 {
374 // Plot probability of each channel as a function of E* (default)
375 // or E*/A (opt="E*/A")
376 //
377 // If SetLegendProbaMin has previously been called with a >0 value
378 // for the minimum probability, we generate a TLegend which contains
379 // only the channels whose probability reaches at least this minimum
380 // value in the given energy range. Call ShowLegend immediately
381 // after this method in order to display in current pad.
382
383 Bool_t makeLegend = (fLegendProbaMin > 0.0);
384
385 TMultiGraph* mg = new TMultiGraph();
387 Long64_t i = 0;
388 int mark = 20;
389 Double_t fac = 1.;
390
391 for (; i < fPartitions; i++) {
392 KVEvent* pt = GetPartition(i);
393 if (!i && !strcmp(opt, "E*/A")) fac = pt->GetSum("GetA");
394 g[i] = new TGraph();
395 g[i]->SetName(pt->GetPartitionName());
396 g[i]->SetMarkerStyle(mark);
397 g[i]->SetMarkerColor((i % 9) + 1);
398 g[i]->SetLineColor((i % 9) + 1);
399 g[i]->SetFillColor(0);
400 g[i]->ResetBit(BIT(20));
401 mg->Add(g[i], "pl");
402
403 if (!(i % 9)) {
404 mark++;
405 if (mark > 30) mark = 20;
406 }
407
408 }
409 // build TGraph
410 for (double E = emin; E <= emax; E += estep) {
411
412 CalculateWeights(E * fac);
413 for (i = 0; i < fPartitions; i++) {
414
415 if (GetSumWeights() > 0.0) {
416 StatWeight* wt = GetWeight(i);
417
418 Double_t proba = wt->GetWeight() / GetSumWeights();
419 Long64_t voie = wt->GetIndex();
420
421 g[voie]->SetPoint(g[voie]->GetN(), E, proba * 100.);
422 // if we are building a TLegend, we 'mark' each TGraph which
423 // contains probabilities higher than the required minimum
424 // by setting a bit in the TObject status bitfield
425 if (makeLegend && proba > fLegendProbaMin) g[voie]->SetBit(BIT(20));
426 }
427 }
428 }
429 if (gPad) gPad->Clear();
430 mg->Draw("apl");
431 if (!strcmp(opt, "E*/A")) {
432 mg->GetHistogram()->SetXTitle("E*/A (MeV)");
433 }
434
435
437
438 else {
439 mg->GetHistogram()->SetXTitle("E* (MeV)");
440 }
441
442
444
445 mg->GetHistogram()->SetYTitle("Probability");
446 if (makeLegend) {
447 mg->GetHistogram()->SetAxisRange(fLegendProbaMin * 100, 100., "Y");
448 // now add all sufficiently probable decay channels to the TLegend
449 fTheLegend = new TLegend(.7, 0.12, .88, .88);
450 fTheLegend->SetHeader(Form("Channels with P>%4.1f%%", fLegendProbaMin * 100));
451 for (i = 0; i < mg->GetListOfGraphs()->GetSize(); i++) {
452 if (g[i]->TestBit(BIT(20))) {
453 fTheLegend->AddEntry(g[i], g[i]->GetName(), "pl");
454 }
455 }
456 }
457
458 gPad->Modified();
459 gPad->Update();
460
461 }
462
463
468
469 void MCSampler::PlotMultiplicities(double emin, double emax, double estep, Option_t* opt)
470 {
471 // Plot multiplicities of n,p,d,t,3He,4He,... as a function of E* (default)
472 // or E*/A (opt="E*/A")
473 //
474
475 TMultiGraph* mg = new TMultiGraph();
476 const int nparticles = 7;
477 TGraph* g[nparticles];
478
479 TString particles[] = {"1n", "1H", "2H", "3H", "3He", "4He", "Z>2"};
480
481 int mark = 20;
482 Double_t fac = 1.;
483
484 if (!strcmp(opt, "E*/A")) {
485 KVEvent* pt = GetPartition(0);
486 fac = pt->GetSum("GetA");
487 }
488
489
490
492
493 for (int i = 0; i < nparticles; i++) {
494 g[i] = new TGraph();
495 g[i]->SetName(particles[i]);
496 g[i]->SetMarkerStyle(mark);
497 g[i]->SetMarkerColor((i % 9) + 1);
498 g[i]->SetLineColor((i % 9) + 1);
499 g[i]->SetFillColor(0);
500 g[i]->ResetBit(BIT(20));
501 mg->Add(g[i], "pl");
502
503 if (!(i % 9)) {
504 mark++;
505 if (mark > 30) mark = 20;
506 }
507
508 }
509
510 // build TGraph
511
513
514 for (double E = emin; E <= emax; E += estep) {
515
516 CalculateWeights(E * fac);
517 Double_t multiplicities[nparticles];
518 memset(multiplicities, 0, sizeof(double)*nparticles);
519
520 for (Long64_t i = 0; i < fPartitions; i++) {
521
522 if (GetSumWeights() > 0.0) {
523 StatWeight* wt = GetWeight(i);
524
525 Double_t proba = wt->GetWeight() / GetSumWeights();
526 if (proba > 1.e-06) {
528 for (auto& n : EventIterator(pt)) {
529 for (int j = 0; j < nparticles - 1; j++) {
530 if (!strcmp(n.GetSymbol(), particles[j].Data())) multiplicities[j] += proba;
531 }
532 if (n.GetZ() > 2) multiplicities[nparticles - 1] += proba;
533 }
534 }
535
536 }
537 }
538 for (int i = 0; i < nparticles; i++) {
539 g[i]->SetPoint(g[i]->GetN(), E, multiplicities[i]);
540 }
541 }
542
543
545
546 if (gPad) gPad->Clear();
547 mg->Draw("apl");
548 if (!strcmp(opt, "E*/A")) {
549 mg->GetHistogram()->SetXTitle("E*/A (MeV)");
550 }
551 else {
552 mg->GetHistogram()->SetXTitle("E* (MeV)");
553 }
554
555 mg->GetHistogram()->SetYTitle("Multiplicity");
556 gPad->Modified();
557 gPad->Update();
558
559 }
560
561}
562
563
#define SafeDelete(p)
bool Bool_t
char Char_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
const char Option_t
#define BIT(n)
winID w
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t b
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t g
char name[80]
R__EXTERN TRandom * gRandom
char * Form(const char *fmt,...)
#define gPad
Class for iterating over nuclei in events accessed through base pointer/reference.
Base class for KaliVeda framework.
Definition KVBase.h:142
Abstract base class container for multi-particle events.
Definition KVEvent.h:67
virtual Double_t GetChannelQValue() const =0
Monte-Carlo sampling of events with statistical weights .
Definition MCSampler.h:22
virtual ~MCSampler()
Destructor.
Definition MCSampler.cpp:71
Bool_t fModifyMasses
the partition index
Definition MCSampler.h:43
KVEvent * fPartition
branch containing events
Definition MCSampler.h:34
void PlotProbabilities(double emin=0., double emax=100., double estep=1., Option_t *opt="")
Double_t fLegendProbaMin
weight of channel picked by call to PickRandomChannel()
Definition MCSampler.h:26
void PlotMultiplicities(double emin=0., double emax=100., double estep=1., Option_t *opt="")
void SetBranch(TTree *theTree, const TString &name, void *variable, const TString &vartype)
automatically generated legend for PlotProbabilities
Double_t ESTAR
variables for TTree branches
Definition MCSampler.h:39
TLegend * fTheLegend
minimum probability for which channels are included in automatically generated TLegend when PlotProba...
Definition MCSampler.h:27
void initialiseWeightList()
if nuclear masses are modified
Definition MCSampler.cpp:36
void SetUpTreeBranches(KVEvent *&event, TTree *theTree, const TString &bname)
Double_t EDISP
the excitation energy (Exx)
Definition MCSampler.h:40
Long64_t IPART
the available kinetic energy
Definition MCSampler.h:41
void SetEventList(TTree *t, const TString &branchname)
Define the TTree or TChain containing all possible events (partitions).
Definition MCSampler.cpp:83
StatWeight * fLastPicked
Definition MCSampler.h:25
TClonesArray * fWeightList
statistical weight class
Definition MCSampler.h:36
void GenerateEvents(TTree *, KVEvent *event, Double_t, Long64_t npartitions, Long64_t nev_part=10)
Bool_t SetExcitationEnergy(Double_t Exx)
Double_t fSumWeights
list of weights for all events
Definition MCSampler.h:37
Long64_t PickRandomChannel()
void CalculateWeights(Double_t excitation_energy)
void init()
default initialisations
Definition MCSampler.cpp:21
void SetStatWeight(const TString &)
KVEvent * GetPartition(Long64_t i)
Definition MCSampler.h:55
void GenerateEvent(TTree *theTree, KVEvent *event)
TBranch * fBranch
number of partitions in TTree/TChain
Definition MCSampler.h:33
TClass * fWeight
event read from fPartitionList tree
Definition MCSampler.h:35
Double_t GetSumWeights() const
Definition MCSampler.h:77
StatWeight * GetWeight(Int_t i) const
Definition MCSampler.h:73
Abstract base class for calculating statistical weights for events .
Definition StatWeight.h:21
void GenerateEvent(KVEvent *partition, KVEvent *event)
virtual void initGenerateEvent(KVEvent *partition)=0
Double_t GetAvailableEnergy() const
Definition StatWeight.h:48
virtual void resetGenerateEvent()=0
Double_t GetWeight() const
Definition StatWeight.h:44
Long64_t GetIndex() const
Definition StatWeight.h:57
virtual void SetAddress(void *add)
void Sort(Int_t upto=kMaxInt) override
TObject * ConstructedAt(Int_t idx)
virtual void SetHeader(const char *header="", Option_t *option="")
TLegendEntry * AddEntry(const char *name, const char *label="", Option_t *option="lpf")
const char * GetName() const override
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
virtual void Error(const char *method, const char *msgfmt,...) const
virtual void Info(const char *method, const char *msgfmt,...) const
virtual Double_t Uniform(Double_t x1, Double_t x2)
const char * Data() const
virtual Int_t Fill()
virtual TBranch * GetBranch(const char *name)
virtual Long64_t GetEntries() const
virtual Int_t Branch(const char *folder, Int_t bufsize=32000, Int_t splitlevel=99)
long long Long64_t
TPaveText * pt
Double_t x[n]
const Int_t n
void init()
constexpr Double_t E()
ClassImp(TPyArg)
#define mark(osub)