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 "AliRsnEvent.h"
37 #include "AliRsnAnalysis.h"
39 ClassImp(AliRsnAnalysis)
41 //--------------------------------------------------------------------------------------------------------
42 AliRsnAnalysis::AliRsnAnalysis()
46 // Initializes all pointers and collections to NULL.
56 for (i = 0; i < AliPID::kSPECIES; i++) fCuts[i] = 0;
58 //--------------------------------------------------------------------------------------------------------
59 void AliRsnAnalysis::AddCutPair(AliRsnDaughterCut *cut)
62 // Add a cut on pairs.
63 // This cut is global for all pairs.
65 if (!cut->IsPairCut()) {
66 Warning("AddCutPair", "This is a single cut, cannot be added");
70 if (!fPairCuts) fPairCuts = new TObjArray(0);
72 fPairCuts->AddLast(cut);
74 //--------------------------------------------------------------------------------------------------------
75 void AliRsnAnalysis::AddCutSingle(AliPID::EParticleType type, AliRsnDaughterCut *cut)
78 // Add a cut on single particles.
79 // This cut must be specified for each particle type.
81 if (cut->IsPairCut()) {
82 Warning("AddCutSingle", "This is a pair cut, cannot be added");
86 if (type >= AliPID::kElectron && type <= AliPID::kProton) {
87 if (!fCuts[type]) fCuts[type] = new TObjArray(0);
88 fCuts[type]->AddLast(cut);
91 //--------------------------------------------------------------------------------------------------------
92 void AliRsnAnalysis::AddMixPairDef
93 (AliPID::EParticleType p1, Char_t sign1, AliPID::EParticleType p2, Char_t sign2)
96 // Adds a new pair definition to create a new histogram,
97 // for the event mixing step.
98 // If the pair defs array is NULL, it is initialized here.
100 if (!fMixPairDefs) fMixPairDefs = new TObjArray(0);
101 fMixPairDefs->AddLast( new AliPairDef(p1, sign1, p2, sign2, 0, kFALSE) );
103 //--------------------------------------------------------------------------------------------------------
104 void AliRsnAnalysis::AddPairDef
105 (AliPID::EParticleType p1, Char_t sign1, AliPID::EParticleType p2, Char_t sign2, Bool_t onlyTrue)
108 // Adds a new pair definition to create a new histogram,
109 // for the signal evaluation (same event) step.
110 // If the pair defs array is NULL, it is initialized here.
112 if (!fPairDefs) fPairDefs = new TObjArray(0);
113 fPairDefs->AddLast( new AliPairDef(p1, sign1, p2, sign2, fTrueMotherPDG, onlyTrue) );
115 //--------------------------------------------------------------------------------------------------------
116 void AliRsnAnalysis::Clear(Option_t* /* option */)
121 fHistograms->Clear("C");
122 fPairDefs->Clear("C");
124 fMixHistograms->Clear("C");
125 fMixPairDefs->Clear("C");
128 for (i = 0; i < AliPID::kSPECIES; i++) fCuts[i]->Clear("C");
129 fPairCuts->Clear("C");
131 //--------------------------------------------------------------------------------------------------------
132 Stat_t AliRsnAnalysis::EventMix(Int_t nmix, Int_t multDiffMax, Double_t vzDiffMax, Bool_t compareTotMult)
135 // Performs event mixing.
136 // It takes the array of fMixPairDefs and stores results in fMixHistograms.
137 // First parameter defines how many events must be mixed with each one.
138 // Events to be mixed are chosen using the other parameters:
140 // - multDiffMax defines the maximum allowed difference in particle multiplicity,
141 // a) when last argument is kFALSE (default) the multiplicity comparison is made with respect
142 // to the particles of 'type 2' in the pair
143 // b) when last argument is kTRUE, the multiplicity comparison is made with respect of total
144 // particle multiplicity in the events
146 // - vzDiffMax defines maximum allowed difference in Z coordinate of prim. vertex.
148 // If one wants to exchange the particle types, one has to add both combinations of particles
149 // as different pair defs.
152 // analysis->AddMixPairDef(AliRsnEvent::kPion, '+', AliRsnEvent::kKaon, '-');
153 // analysis->AddMixPairDef(AliRsnEvent::kKaon, '-', AliRsnEvent::kPion, '+');
155 // allocate the histograms array
156 Int_t i, npairdefs = (Int_t)fMixPairDefs->GetEntries();
157 fMixHistograms = new TObjArray(npairdefs);
158 TObjArray &histos = *fMixHistograms;
160 for (i = 0; i < npairdefs; i++) {
161 pd = (AliPairDef*)fMixPairDefs->At(i);
162 histos[i] = new TH1D(Form("hmix_%s", pd->GetName()), pd->GetTitle(), fNBins, fHistoMin, fHistoMax);
165 // Link events branch
166 AliRsnEvent *event2 = new AliRsnEvent;
167 fEventsTree->SetBranchAddress("events", &event2);
169 // define variables to store data about particles
171 Int_t iev, ievmix, nEvents = (Int_t)fEventsTree->GetEntries();
174 Int_t nmixed, mult1, mult2, diffMult;
175 Double_t vz1, vz2, diffVz;
176 for (iev = 0; iev < nEvents; iev++) {
179 event2->Clear("DELETE");
180 fEventsTree->GetEntry(iev);
182 // copy this event into 'event 1'
183 AliRsnEvent *event1 = new AliRsnEvent(*event2);
185 // get Z position of primary vertex
186 vz1 = event1->GetPrimaryVertexZ();
188 // if total multiplicities must be used
189 // it is computed here
190 if (compareTotMult) {
191 mult1 = event1->GetMultiplicity();
198 if (iev % 10 == 0) cout << "\rMixing event " << iev << flush;
200 // loop on pair definitions
201 for (i = 0; i < npairdefs; i++) {
203 // get pair definition
204 pd = (AliPairDef*)fMixPairDefs->At(i);
206 // get histogram reference
207 TH1D *histogram = (TH1D*)histos[i];
209 // get multiplicity of particle type '2' in event '1'
211 mult1 = (Int_t)event1->GetTracks(pd->GetSign2(), pd->GetParticle2())->GetEntries();
214 // loop on events for mixing
217 while (nmixed < nmix) {
219 // get other event (it starts from iev + 1, and
220 // loops again to 0 if reachs end of tree)
222 if (ievmix >= nEvents) ievmix -= nEvents;
224 // if event-2-mix is equal to 'iev', then
225 // a complete loop has been done, and no more
226 // mixing can be done, even if they are too few
227 // then the loop breaks anyway
228 if (ievmix == iev) break;
231 event2->Clear("DELETE");
232 fEventsTree->GetEntry(ievmix);
234 // get event stats related to event 2
235 vz2 = event2->GetPrimaryVertexZ();
236 if (compareTotMult) {
237 mult2 = event2->GetMultiplicity();
240 mult2 = event2->GetTracks(pd->GetSign2(), pd->GetParticle2())->GetEntries();
243 // fill histogram if checks are passed
244 diffMult = TMath::Abs(mult1 - mult2);
245 diffVz = TMath::Abs(vz1 - vz2);
246 if (diffVz <= vzDiffMax && diffMult <= multDiffMax) {
247 //cout << ievmix << " " << flush;
248 nPairs += Compute(pd, histogram, event1, event2);
254 event1->Clear("DELETE");
258 } // end loop on events
263 //--------------------------------------------------------------------------------------------------------
264 Stat_t AliRsnAnalysis::Process()
267 // Reads the list 'fPairDefs', and builds an inv-mass histogram for each definition.
268 // For each event, particle of 'type 1' are combined with particles of 'type 2' as
269 // defined in each pair definition specified in the list, taking the list of both types
270 // from the same event.
271 // This method is supposed to evaluate the 'signal' of the resonance, containing the peak.
272 // It can also be used when one wants to evaluate the 'background' with the 'wrong sign'
275 // allocate the histograms array in order to contain
276 // as many objects as the number of pair definitionss
277 Int_t i, npairdefs = (Int_t)fPairDefs->GetEntries();
278 fHistograms = new TObjArray(npairdefs);
279 TObjArray &histos = *fHistograms;
281 // loop over pair defs in order to retrieve the particle species chosen
282 // which are used to set an unique name for the output histogram
283 // There will be a direct correspondence between the inder of pairdef in its array
284 // and the corresponding histogram in the 'fHistograms' list.
286 for (i = 0; i < npairdefs; i++) {
287 pd = (AliPairDef*)fPairDefs->At(i);
288 histos[i] = new TH1D(Form("h_%s", pd->GetName()), pd->GetTitle(), fNBins, fHistoMin, fHistoMax);
291 // Link events branch
292 AliRsnEvent *event = new AliRsnEvent;
293 fEventsTree->SetBranchAddress("events", &event);
295 // define variables to store data about particles
297 Int_t iev, nEvents = (Int_t)fEventsTree->GetEntries();
300 for (iev = 0; iev < nEvents; iev++) {
303 event->Clear("DELETE");
304 fEventsTree->GetEntry(iev);
305 if (iev % 1000 == 0) cout << "\rProcessing event " << iev << flush;
307 // loop over the collection of pair defs
308 for (i = 0; i < npairdefs; i++) {
309 pd = (AliPairDef*)fPairDefs->At(i);
310 TH1D *histogram = (TH1D*)histos[i];
311 // invoke AliPairDef method to fill histogram
312 nPairs += Compute(pd, histogram, event, event);
315 } // end loop on events
320 //--------------------------------------------------------------------------------------------------------
321 void AliRsnAnalysis::WriteHistograms() const
324 // Writes histograms in current directory
327 TObjArrayIter iter(fHistograms);
328 while ( (histogram = (TH1D*)iter.Next()) ) {
332 if (fMixHistograms) {
333 TObjArrayIter iterMix(fMixHistograms);
334 while ( (histogram = (TH1D*)iterMix.Next()) ) {
339 //--------------------------------------------------------------------------------------------------------
340 Stat_t AliRsnAnalysis::Compute
341 (AliPairDef *pd, TH1D* &histogram, AliRsnEvent *event1, AliRsnEvent *event2)
344 // Adds to the specified histogram the invariant mass spectrum calculated taking
345 // particles of type 1 from event 1, and particles of type 2 from event 2.
346 // Events can be equal (signal) or different (background with event mixing).
348 // define two 'cursor' objects
349 AliRsnDaughter *track1 = 0, *track2 = 0;
351 // define iterators for the two collections
352 if (!event1 || !event1->GetTracks(pd->GetSign1(), pd->GetParticle1())) {
353 Error("Compute", "Null pointer for particle 1 collection");
356 if (!event2 || !event2->GetTracks(pd->GetSign2(), pd->GetParticle2())) {
357 Error("Compute", "Null pointer for particle 2 collection");
360 TObjArrayIter iter1(event1->GetTracks(pd->GetSign1(), pd->GetParticle1()));
361 TObjArrayIter iter2(event2->GetTracks(pd->GetSign2(), pd->GetParticle2()));
363 // define temporary variables for better code readability
366 // loop on particle of type 1 (in event 1)
367 while ( (track1 = (AliRsnDaughter*)iter1.Next()) ) {
369 if (fRejectFakes && (track1->GetLabel() < 0)) continue;
370 if (!SingleCutCheck(pd->GetParticle1(), track1)) continue;
374 // loop on particles of type 2 (in event 2)
375 while ( (track2 = (AliRsnDaughter*)iter2.Next()) ) {
377 if (fRejectFakes && (track2->GetLabel() < 0)) continue;
378 if (event1 == event2 && track1->GetIndex() == track2->GetIndex()) continue;
379 if (!SingleCutCheck(pd->GetParticle2(), track2)) continue;
380 if (!PairCutCheck(track1, track2)) continue;
384 Char_t sign1 = (track1->GetSign() > 0) ? '+' : '-';
385 Char_t sign2 = (track2->GetSign() > 0) ? '+' : '-';
386 Info("Compute", "Particle 1: PDG = %d, sign = %c --- Particle 2: PDG = %d, sign = %c", track1->GetTruePDG(), sign1, track2->GetTruePDG(), sign2);
390 track1->SetMass(pd->GetMass1());
391 track2->SetMass(pd->GetMass2());
392 AliRsnDaughter sum = AliRsnDaughter::Sum(*track1, *track2);
394 // if the choice to get ONLY true pairs is selected, a check is made on the mothers
395 if (pd->GetOnlyTrue()) {
396 // the 'sum' AliRsnDaughter object is initialized with
397 // the PDG code of the common mother (if it is the case)
398 if (TMath::Abs(sum.GetMotherPDG()) == TMath::Abs(fTrueMotherPDG)) {
399 histogram->Fill(sum.GetMass());
404 histogram->Fill(sum.GetMass());
414 //--------------------------------------------------------------------------------------------------------
415 Bool_t AliRsnAnalysis::SingleCutCheck(Int_t itype, AliRsnDaughter *track) const
418 // Checks a track against single particle cuts (if defined)
420 if (!fCuts[itype]) return kTRUE;
422 TObjArrayIter iter(fCuts[itype]);
423 AliRsnDaughterCut *cut = 0;
424 while ( (cut = (AliRsnDaughterCut*)iter.Next()) ) {
425 if (!cut->Pass(track)) return kFALSE;
430 //--------------------------------------------------------------------------------------------------------
431 Bool_t AliRsnAnalysis::PairCutCheck(AliRsnDaughter *track1, AliRsnDaughter *track2) const
434 // Checks a pair against pair cuts (if defined)
436 if (!fPairCuts) return kTRUE;
438 TObjArrayIter iter(fPairCuts);
439 AliRsnDaughterCut *cut = 0;
440 while ( (cut = (AliRsnDaughterCut*)iter.Next()) ) {
441 if (!cut->Pass(track1, track2)) return kFALSE;
446 //--------------------------------------------------------------------------------------------------------
447 AliRsnAnalysis::AliPairDef::AliPairDef
448 (AliPID::EParticleType p1, Char_t sign1,
449 AliPID::EParticleType p2, Char_t sign2, Int_t pdgMother, Bool_t onlyTrue)
452 // Constructor for nested class
454 fOnlyTrue = onlyTrue;
456 if (fOnlyTrue) fTrueMotherPDG = pdgMother;
464 // instance a PDG database to recovery true masses of particles
465 TDatabasePDG *db = TDatabasePDG::Instance();
466 Int_t pdg1 = AliPID::ParticleCode((Int_t)p1);
467 Int_t pdg2 = AliPID::ParticleCode((Int_t)p2);
468 fMass1 = db->GetParticle(pdg1)->Mass();
469 fMass2 = db->GetParticle(pdg2)->Mass();
471 // set name according to the chosen particles
472 fName.Append(Form("%s(%c)_%s(%c)", ParticleName(p1), sign1, ParticleName(p2), sign2));
473 fTitle.Append(Form("Inv. mass for %s(%c) and %s(%c)", ParticleName(p1), sign1, ParticleName(p2), sign2));
475 fName.Append("_true");
476 fTitle.Append(" (true pairs)");
479 //--------------------------------------------------------------------------------------------------------
480 Text_t* AliRsnAnalysis::AliPairDef::ParticleName(AliPID::EParticleType part) const
484 // Returns the name of the particle in text format
486 if (part == AliPID::kElectron) return ("E");
487 else if (part == AliPID::kMuon) return ("Mu");
488 else if (part == AliPID::kPion) return ("Pi");
489 else if (part == AliPID::kKaon) return ("K");
490 else if (part == AliPID::kProton) return ("P");
492 Warning("ParticleName", "Unrecognized value of EParticle argument");
496 //--------------------------------------------------------------------------------------------------------