KaliVeda  1.13/01
Heavy-Ion Analysis Toolkit
MCSampler.cpp
Go to the documentation of this file.
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 
15 namespace 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 
87  fPartitions = t->GetEntries();
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 
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++) {
182  Double_t w = ((StatWeight*)(*fWeightList)[i])->GetWeight();
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 
219  void MCSampler::SetUpTreeBranches(KVEvent*& event, TTree* theTree, const TString& bname)
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 
272  SetDecayChannel();
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();
386  TGraph* g[fPartitions];
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) {
527  KVEvent* pt = GetPartition(wt->GetIndex());
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 
KVTemplateEvent< KVNucleus >::EventIterator EventIterator
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
#define SafeDelete(p)
#define b(i)
char Char_t
const Bool_t kFALSE
bool Bool_t
double Double_t
const Bool_t kTRUE
const char Option_t
#define BIT(n)
R__EXTERN TRandom * gRandom
char * Form(const char *fmt,...)
#define gPad
Base class for KaliVeda framework.
Definition: KVBase.h:141
Abstract base class container for multi-particle events.
Definition: KVEvent.h:66
virtual Double_t GetChannelQValue() const =0
Monte-Carlo sampling of events with statistical weights .
Definition: MCSampler.h:21
virtual ~MCSampler()
Destructor.
Definition: MCSampler.cpp:71
Bool_t fModifyMasses
the partition index
Definition: MCSampler.h:42
KVEvent * fPartition
branch containing events
Definition: MCSampler.h:33
void PlotProbabilities(double emin=0., double emax=100., double estep=1., Option_t *opt="")
Definition: MCSampler.cpp:372
Double_t fLegendProbaMin
weight of channel picked by call to PickRandomChannel()
Definition: MCSampler.h:25
Bool_t SetDecayChannel()
Definition: MCSampler.cpp:312
void PlotMultiplicities(double emin=0., double emax=100., double estep=1., Option_t *opt="")
Definition: MCSampler.cpp:469
void SetBranch(TTree *theTree, const TString &name, void *variable, const TString &vartype)
automatically generated legend for PlotProbabilities
Definition: MCSampler.cpp:198
Double_t ESTAR
variables for TTree branches
Definition: MCSampler.h:38
TLegend * fTheLegend
minimum probability for which channels are included in automatically generated TLegend when PlotProba...
Definition: MCSampler.h:26
void initialiseWeightList()
if nuclear masses are modified
Definition: MCSampler.cpp:36
StatWeight * GetWeight(Int_t i) const
Definition: MCSampler.h:72
void SetUpTreeBranches(KVEvent *&event, TTree *theTree, const TString &bname)
Definition: MCSampler.cpp:219
Double_t EDISP
the excitation energy (Exx)
Definition: MCSampler.h:39
Long64_t IPART
the available kinetic energy
Definition: MCSampler.h:40
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:24
TClonesArray * fWeightList
statistical weight class
Definition: MCSampler.h:35
void GenerateEvents(TTree *, KVEvent *event, Double_t, Long64_t npartitions, Long64_t nev_part=10)
Definition: MCSampler.cpp:252
Bool_t SetExcitationEnergy(Double_t Exx)
Definition: MCSampler.cpp:294
Double_t fSumWeights
list of weights for all events
Definition: MCSampler.h:36
Long64_t PickRandomChannel()
Definition: MCSampler.cpp:169
void CalculateWeights(Double_t excitation_energy)
Definition: MCSampler.cpp:133
KVEvent * GetPartition(Long64_t i)
Definition: MCSampler.h:54
void init()
default initialisations
Definition: MCSampler.cpp:21
void SetStatWeight(const TString &)
Definition: MCSampler.cpp:102
Long64_t fPartitions
Definition: MCSampler.h:31
void GenerateEvent(TTree *theTree, KVEvent *event)
Definition: MCSampler.cpp:341
TBranch * fBranch
number of partitions in TTree/TChain
Definition: MCSampler.h:32
TClass * fWeight
event read from fPartitionList tree
Definition: MCSampler.h:34
Double_t GetSumWeights() const
Definition: MCSampler.h:76
Abstract base class for calculating statistical weights for events .
Definition: StatWeight.h:20
void SetIndex(Long64_t i)
Definition: StatWeight.h:52
virtual void SetWeight(KVEvent *e, Double_t E)=0
void GenerateEvent(KVEvent *partition, KVEvent *event)
Definition: StatWeight.cpp:79
virtual void initGenerateEvent(KVEvent *partition)=0
Double_t GetAvailableEnergy() const
Definition: StatWeight.h:47
virtual void resetGenerateEvent()=0
Double_t GetWeight() const
Definition: StatWeight.h:43
Long64_t GetIndex() const
Definition: StatWeight.h:56
virtual void SetAddress(void *add)
static TClass * GetClass(Bool_t load=kTRUE, Bool_t silent=kFALSE)
TObject * ConstructedAt(Int_t idx)
virtual void Sort(Int_t upto=kMaxInt)
virtual void SetHeader(const char *header="", Option_t *option="")
TLegendEntry * AddEntry(const char *name, const char *label="", Option_t *option="lpf")
virtual const char * GetName() const
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
const long double mg
Definition: KVUnits.h:74
const long double g
masses
Definition: KVUnits.h:72
constexpr Double_t E()
#define mark(osub)