1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 //-------------------------------------------------------------------------
17 // Class AliRsnAnalysis
18 // Reconstruction and analysis of a binary resonance
19 // ........................................
20 // ........................................
21 // ........................................
22 // ........................................
23 // ........................................
25 // author: A. Pulvirenti (email: alberto.pulvirenti@ct.infn.it)
26 //-------------------------------------------------------------------------
28 #include <Riostream.h>
32 #include <TDatabasePDG.h>
34 #include "AliRsnDaughter.h"
35 #include "AliRsnDaughterCut.h"
36 #include "AliRsnDaughterCutPair.h"
37 #include "AliRsnEvent.h"
38 #include "AliRsnAnalysis.h"
40 ClassImp(AliRsnAnalysis)
42 //--------------------------------------------------------------------------------------------------------
43 AliRsnAnalysis::AliRsnAnalysis() :
59 // Initializes all pointers and collections to NULL.
62 for (i = 0; i < AliPID::kSPECIES; i++) fCuts[i] = 0;
64 //--------------------------------------------------------------------------------------------------------
65 AliRsnAnalysis::AliRsnAnalysis(const AliRsnAnalysis ©) :
67 fRejectFakes(copy.fRejectFakes),
69 fHistoMin(copy.fHistoMin),
70 fHistoMax(copy.fHistoMax),
71 fTrueMotherPDG(copy.fTrueMotherPDG),
81 // Initializes all pointers and collections to NULL anyway,
82 // but copies some settings from the argument.
85 for (i = 0; i < AliPID::kSPECIES; i++) fCuts[i] = 0;
87 //--------------------------------------------------------------------------------------------------------
88 void AliRsnAnalysis::AddCutPair(AliRsnDaughterCutPair *cut)
91 // Add a cut on pairs.
92 // This cut is global for all pairs.
94 if (!fPairCuts) fPairCuts = new TObjArray(0);
95 fPairCuts->AddLast(cut);
97 //--------------------------------------------------------------------------------------------------------
98 void AliRsnAnalysis::AddCutSingle(AliPID::EParticleType type, AliRsnDaughterCut *cut)
101 // Add a cut on single particles.
102 // This cut must be specified for each particle type.
104 if (type >= AliPID::kElectron && type <= AliPID::kProton) {
105 if (!fCuts[type]) fCuts[type] = new TObjArray(0);
106 fCuts[type]->AddLast(cut);
109 //--------------------------------------------------------------------------------------------------------
110 void AliRsnAnalysis::AddMixPairDef
111 (AliPID::EParticleType p1, Char_t sign1, AliPID::EParticleType p2, Char_t sign2)
114 // Adds a new pair definition to create a new histogram,
115 // for the event mixing step.
116 // If the pair defs array is NULL, it is initialized here.
118 if (!fMixPairDefs) fMixPairDefs = new TObjArray(0);
119 fMixPairDefs->AddLast( new AliPairDef(p1, sign1, p2, sign2, 0, kFALSE) );
121 //--------------------------------------------------------------------------------------------------------
122 void AliRsnAnalysis::AddPairDef
123 (AliPID::EParticleType p1, Char_t sign1, AliPID::EParticleType p2, Char_t sign2, Bool_t onlyTrue)
126 // Adds a new pair definition to create a new histogram,
127 // for the signal evaluation (same event) step.
128 // If the pair defs array is NULL, it is initialized here.
130 if (!fPairDefs) fPairDefs = new TObjArray(0);
131 fPairDefs->AddLast( new AliPairDef(p1, sign1, p2, sign2, fTrueMotherPDG, onlyTrue) );
133 //--------------------------------------------------------------------------------------------------------
134 void AliRsnAnalysis::Clear(Option_t* /* option */)
139 fHistograms->Clear("C");
140 fPairDefs->Clear("C");
142 fMixHistograms->Clear("C");
143 fMixPairDefs->Clear("C");
146 for (i = 0; i < AliPID::kSPECIES; i++) fCuts[i]->Clear("C");
147 fPairCuts->Clear("C");
149 //--------------------------------------------------------------------------------------------------------
150 Stat_t AliRsnAnalysis::EventMix(Int_t nmix, Int_t multDiffMax, Double_t vzDiffMax, Bool_t compareTotMult)
153 // Performs event mixing.
154 // It takes the array of fMixPairDefs and stores results in fMixHistograms.
155 // First parameter defines how many events must be mixed with each one.
156 // Events to be mixed are chosen using the other parameters:
158 // - multDiffMax defines the maximum allowed difference in particle multiplicity,
159 // a) when last argument is kFALSE (default) the multiplicity comparison is made with respect
160 // to the particles of 'type 2' in the pair
161 // b) when last argument is kTRUE, the multiplicity comparison is made with respect of total
162 // particle multiplicity in the events
164 // - vzDiffMax defines maximum allowed difference in Z coordinate of prim. vertex.
166 // If one wants to exchange the particle types, one has to add both combinations of particles
167 // as different pair defs.
170 // analysis->AddMixPairDef(AliRsnEvent::kPion, '+', AliRsnEvent::kKaon, '-');
171 // analysis->AddMixPairDef(AliRsnEvent::kKaon, '-', AliRsnEvent::kPion, '+');
173 // allocate the histograms array
174 Int_t i, npairdefs = (Int_t)fMixPairDefs->GetEntries();
175 fMixHistograms = new TObjArray(npairdefs);
176 TObjArray &histos = *fMixHistograms;
178 for (i = 0; i < npairdefs; i++) {
179 pd = (AliPairDef*)fMixPairDefs->At(i);
180 histos[i] = new TH1D(Form("hmix_%s", pd->GetName()), pd->GetTitle(), fNBins, fHistoMin, fHistoMax);
183 // Link events branch
184 AliRsnEvent *event2 = new AliRsnEvent;
185 fEventsTree->SetBranchAddress("events", &event2);
187 // define variables to store data about particles
189 Int_t iev, ievmix, nEvents = (Int_t)fEventsTree->GetEntries();
192 Int_t nmixed, mult1, mult2, diffMult;
193 Double_t vz1, vz2, diffVz;
194 for (iev = 0; iev < nEvents; iev++) {
197 event2->Clear("DELETE");
198 fEventsTree->GetEntry(iev);
200 // copy this event into 'event 1'
201 AliRsnEvent *event1 = new AliRsnEvent(*event2);
203 // get Z position of primary vertex
204 vz1 = event1->GetPrimaryVertexZ();
206 // if total multiplicities must be used
207 // it is computed here
208 if (compareTotMult) {
209 mult1 = event1->GetMultiplicity();
216 if (iev % 10 == 0) cout << "\rMixing event " << iev << flush;
218 // loop on pair definitions
219 for (i = 0; i < npairdefs; i++) {
221 // get pair definition
222 pd = (AliPairDef*)fMixPairDefs->At(i);
224 // get histogram reference
225 TH1D *histogram = (TH1D*)histos[i];
227 // get multiplicity of particle type '2' in event '1'
229 mult1 = (Int_t)event1->GetTracks(pd->GetSign2(), pd->GetParticle2())->GetEntries();
232 // loop on events for mixing
235 while (nmixed < nmix) {
237 // get other event (it starts from iev + 1, and
238 // loops again to 0 if reachs end of tree)
240 if (ievmix >= nEvents) ievmix -= nEvents;
242 // if event-2-mix is equal to 'iev', then
243 // a complete loop has been done, and no more
244 // mixing can be done, even if they are too few
245 // then the loop breaks anyway
246 if (ievmix == iev) break;
249 event2->Clear("DELETE");
250 fEventsTree->GetEntry(ievmix);
252 // get event stats related to event 2
253 vz2 = event2->GetPrimaryVertexZ();
254 if (compareTotMult) {
255 mult2 = event2->GetMultiplicity();
258 mult2 = event2->GetTracks(pd->GetSign2(), pd->GetParticle2())->GetEntries();
261 // fill histogram if checks are passed
262 diffMult = TMath::Abs(mult1 - mult2);
263 diffVz = TMath::Abs(vz1 - vz2);
264 if (diffVz <= vzDiffMax && diffMult <= multDiffMax) {
265 //cout << ievmix << " " << flush;
266 nPairs += Compute(pd, histogram, event1, event2);
272 event1->Clear("DELETE");
276 } // end loop on events
281 //--------------------------------------------------------------------------------------------------------
282 Stat_t AliRsnAnalysis::Process()
285 // Reads the list 'fPairDefs', and builds an inv-mass histogram for each definition.
286 // For each event, particle of 'type 1' are combined with particles of 'type 2' as
287 // defined in each pair definition specified in the list, taking the list of both types
288 // from the same event.
289 // This method is supposed to evaluate the 'signal' of the resonance, containing the peak.
290 // It can also be used when one wants to evaluate the 'background' with the 'wrong sign'
293 // allocate the histograms array in order to contain
294 // as many objects as the number of pair definitionss
295 Int_t i, npairdefs = (Int_t)fPairDefs->GetEntries();
296 fHistograms = new TObjArray(npairdefs);
297 TObjArray &histos = *fHistograms;
299 // loop over pair defs in order to retrieve the particle species chosen
300 // which are used to set an unique name for the output histogram
301 // There will be a direct correspondence between the inder of pairdef in its array
302 // and the corresponding histogram in the 'fHistograms' list.
304 for (i = 0; i < npairdefs; i++) {
305 pd = (AliPairDef*)fPairDefs->At(i);
306 histos[i] = new TH1D(Form("h_%s", pd->GetName()), pd->GetTitle(), fNBins, fHistoMin, fHistoMax);
309 // Link events branch
310 AliRsnEvent *event = new AliRsnEvent;
311 fEventsTree->SetBranchAddress("events", &event);
313 // define variables to store data about particles
315 Int_t iev, nEvents = (Int_t)fEventsTree->GetEntries();
318 for (iev = 0; iev < nEvents; iev++) {
321 event->Clear("DELETE");
322 fEventsTree->GetEntry(iev);
323 if (iev % 1000 == 0) cout << "\rProcessing event " << iev << flush;
325 // loop over the collection of pair defs
326 for (i = 0; i < npairdefs; i++) {
327 pd = (AliPairDef*)fPairDefs->At(i);
328 TH1D *histogram = (TH1D*)histos[i];
329 // invoke AliPairDef method to fill histogram
330 nPairs += Compute(pd, histogram, event, event);
333 } // end loop on events
338 //--------------------------------------------------------------------------------------------------------
339 void AliRsnAnalysis::WriteHistograms() const
342 // Writes histograms in current directory
345 TObjArrayIter iter(fHistograms);
346 while ( (histogram = (TH1D*)iter.Next()) ) {
350 if (fMixHistograms) {
351 TObjArrayIter iterMix(fMixHistograms);
352 while ( (histogram = (TH1D*)iterMix.Next()) ) {
357 //--------------------------------------------------------------------------------------------------------
358 Stat_t AliRsnAnalysis::Compute
359 (AliPairDef *pd, TH1D* &histogram, AliRsnEvent *event1, AliRsnEvent *event2)
362 // Adds to the specified histogram the invariant mass spectrum calculated taking
363 // particles of type 1 from event 1, and particles of type 2 from event 2.
364 // Events can be equal (signal) or different (background with event mixing).
366 // define two 'cursor' objects
367 AliRsnDaughter *track1 = 0, *track2 = 0;
369 // define iterators for the two collections
370 if (!event1 || !event1->GetTracks(pd->GetSign1(), pd->GetParticle1())) {
371 Error("Compute", "Null pointer for particle 1 collection");
374 if (!event2 || !event2->GetTracks(pd->GetSign2(), pd->GetParticle2())) {
375 Error("Compute", "Null pointer for particle 2 collection");
378 TObjArrayIter iter1(event1->GetTracks(pd->GetSign1(), pd->GetParticle1()));
379 TObjArrayIter iter2(event2->GetTracks(pd->GetSign2(), pd->GetParticle2()));
381 // define temporary variables for better code readability
384 // loop on particle of type 1 (in event 1)
385 while ( (track1 = (AliRsnDaughter*)iter1.Next()) ) {
387 if (fRejectFakes && (track1->GetLabel() < 0)) continue;
388 if (!SingleCutCheck(pd->GetParticle1(), track1)) continue;
392 // loop on particles of type 2 (in event 2)
393 while ( (track2 = (AliRsnDaughter*)iter2.Next()) ) {
395 if (fRejectFakes && (track2->GetLabel() < 0)) continue;
396 if (event1 == event2 && track1->GetIndex() == track2->GetIndex()) continue;
397 if (!SingleCutCheck(pd->GetParticle2(), track2)) continue;
398 if (!PairCutCheck(track1, track2)) continue;
402 Char_t sign1 = (track1->GetSign() > 0) ? '+' : '-';
403 Char_t sign2 = (track2->GetSign() > 0) ? '+' : '-';
404 Info("Compute", "Particle 1: PDG = %d, sign = %c --- Particle 2: PDG = %d, sign = %c", track1->GetTruePDG(), sign1, track2->GetTruePDG(), sign2);
408 track1->SetMass(pd->GetMass1());
409 track2->SetMass(pd->GetMass2());
410 AliRsnDaughter sum = AliRsnDaughter::Sum(*track1, *track2);
412 // if the choice to get ONLY true pairs is selected, a check is made on the mothers
413 if (pd->GetOnlyTrue()) {
414 // the 'sum' AliRsnDaughter object is initialized with
415 // the PDG code of the common mother (if it is the case)
416 if (TMath::Abs(sum.GetMotherPDG()) == TMath::Abs(fTrueMotherPDG)) {
417 histogram->Fill(sum.GetMass());
422 histogram->Fill(sum.GetMass());
432 //--------------------------------------------------------------------------------------------------------
433 Bool_t AliRsnAnalysis::SingleCutCheck(Int_t itype, AliRsnDaughter *track) const
436 // Checks a track against single particle cuts (if defined)
438 if (!fCuts[itype]) return kTRUE;
440 TObjArrayIter iter(fCuts[itype]);
441 AliRsnDaughterCut *cut = 0;
442 while ( (cut = (AliRsnDaughterCut*)iter.Next()) ) {
443 if (!cut->Pass(track)) return kFALSE;
448 //--------------------------------------------------------------------------------------------------------
449 Bool_t AliRsnAnalysis::PairCutCheck(AliRsnDaughter *track1, AliRsnDaughter *track2) const
452 // Checks a pair against pair cuts (if defined)
454 if (!fPairCuts) return kTRUE;
456 TObjArrayIter iter(fPairCuts);
457 AliRsnDaughterCutPair *cut = 0;
458 while ( (cut = (AliRsnDaughterCutPair*)iter.Next()) ) {
459 if (!cut->Pass(track1, track2)) return kFALSE;
464 //--------------------------------------------------------------------------------------------------------
465 AliRsnAnalysis::AliPairDef::AliPairDef
466 (AliPID::EParticleType p1, Char_t sign1, AliPID::EParticleType p2, Char_t sign2, Int_t pdgMother, Bool_t onlyTrue) :
469 fTrueMotherPDG(pdgMother),
478 // Constructor for nested class
480 if (!fOnlyTrue) fTrueMotherPDG = 0;
482 // instance a PDG database to recovery true masses of particles
483 TDatabasePDG *db = TDatabasePDG::Instance();
484 Int_t pdg1 = AliPID::ParticleCode((Int_t)p1);
485 Int_t pdg2 = AliPID::ParticleCode((Int_t)p2);
486 fMass1 = db->GetParticle(pdg1)->Mass();
487 fMass2 = db->GetParticle(pdg2)->Mass();
489 // set name according to the chosen particles
490 fName.Append(Form("%s(%c)_%s(%c)", ParticleName(p1), sign1, ParticleName(p2), sign2));
491 fTitle.Append(Form("Inv. mass for %s(%c) and %s(%c)", ParticleName(p1), sign1, ParticleName(p2), sign2));
493 fName.Append("_true");
494 fTitle.Append(" (true pairs)");
497 //--------------------------------------------------------------------------------------------------------
498 Text_t* AliRsnAnalysis::AliPairDef::ParticleName(AliPID::EParticleType part) const
502 // Returns the name of the particle in text format
504 if (part == AliPID::kElectron) return ("E");
505 else if (part == AliPID::kMuon) return ("Mu");
506 else if (part == AliPID::kPion) return ("Pi");
507 else if (part == AliPID::kKaon) return ("K");
508 else if (part == AliPID::kProton) return ("P");
510 Warning("ParticleName", "Unrecognized value of EParticle argument");
514 //--------------------------------------------------------------------------------------------------------