]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGLF/RESONANCES/AliRsnCutV0.cxx
Added cut on fiducial volume + fix cosine pointing angle for AODv0
[u/mrichter/AliRoot.git] / PWGLF / RESONANCES / AliRsnCutV0.cxx
1 //
2 // Class AliRsnCutV0
3 //
4 // General implementation of a single cut strategy, which can be:
5 // - a value contained in a given interval  [--> IsBetween()   ]
6 // - a value equal to a given reference     [--> MatchesValue()]
7 //
8 // In all cases, the reference value(s) is (are) given as data members
9 // and each kind of cut requires a given value type (Int, UInt, Double),
10 // but the cut check procedure is then automatized and chosen thanks to
11 // an enumeration of the implemented cut types.
12 // At the end, the user (or any other point which uses this object) has
13 // to use the method IsSelected() to check if this cut has been passed.
14 //
15 // authors: Massimo Venaruzzo (massimo.venaruzzo@ts.infn.it)
16 // modified: Enrico Fragiacomo (enrico.fragiacomo@ts.infn.it)
17 //
18
19 #include <Riostream.h>
20 #include <TFormula.h>
21 #include <TBits.h>
22
23 #include "AliLog.h"
24 #include "AliESDtrackCuts.h"
25
26 #include "AliRsnEvent.h"
27 #include "AliRsnDaughter.h"
28 #include "AliRsnCutV0.h"
29
30 ClassImp(AliRsnCutV0)
31
32 //_________________________________________________________________________________________________
33 AliRsnCutV0::AliRsnCutV0(const char *name, Int_t hypothesis, AliPID::EParticleType pid, AliPID::EParticleType pid2) :
34    AliRsnCut(name, AliRsnTarget::kDaughter),
35    fHypothesis(0),
36    fMass(0.0),
37    fTolerance(0.01),
38    fMaxDCAVertex(0.3),
39    fMinCosPointAngle(0.95),
40    fMaxDaughtersDCA(0.5),
41    fMinTPCcluster(70),
42    fMaxRapidity(0.8),
43    fPID(pid),
44    fPID2(pid2),
45    fPIDCutProton(0),
46    fPIDCutPion(0),
47    fESDtrackCuts(0x0),
48    fCutQuality(Form("%sDaughtersQuality", name)),
49    fAODTestFilterBit(5)
50 {
51 //
52 // Default constructor.
53 // Initializes all cuts in such a way that all of them are disabled.
54 //
55
56    SetHypothesis(hypothesis);
57 }
58
59 //_________________________________________________________________________________________________
60 AliRsnCutV0::AliRsnCutV0(const AliRsnCutV0 &copy) :
61    AliRsnCut(copy),
62    fHypothesis(copy.fHypothesis),
63    fMass(copy.fMass),
64    fTolerance(copy.fTolerance),
65    fMaxDCAVertex(copy.fMaxDCAVertex),
66    fMinCosPointAngle(copy.fMinCosPointAngle),
67    fMaxDaughtersDCA(copy.fMaxDaughtersDCA),
68    fMinTPCcluster(copy.fMinTPCcluster),
69    fMaxRapidity(copy.fMaxRapidity),
70    fPID(copy.fPID),
71    fPID2(copy.fPID2),
72    fPIDCutProton(copy.fPIDCutProton),
73    fPIDCutPion(copy.fPIDCutPion),
74    fESDtrackCuts(copy.fESDtrackCuts),
75    fCutQuality(copy.fCutQuality),
76    fAODTestFilterBit(copy.fAODTestFilterBit)
77 {
78 //
79 // Copy constructor.
80 // Just copy all data member values.:IsSelected: Object is not a V0 (RESONANCES/AliRsnCutV0.cxx:149)
81
82 //
83    fCutQuality.SetPtRange(0.15, 1E+20);
84    fCutQuality.SetEtaRange(-0.8, 0.8);
85    fCutQuality.SetSPDminNClusters(1);
86    fCutQuality.SetITSminNClusters(0);
87    fCutQuality.SetITSmaxChi2(1E+20);
88    fCutQuality.SetTPCminNClusters(fMinTPCcluster);
89    fCutQuality.SetTPCmaxChi2(4.0);
90    fCutQuality.SetRejectKinkDaughters();
91    fCutQuality.SetAODTestFilterBit(5);
92
93 }
94
95 //_________________________________________________________________________________________________
96 AliRsnCutV0 &AliRsnCutV0::operator=(const AliRsnCutV0 &copy)
97 {
98 //
99 // Assignment operator.
100 // Just copy all data member values.
101 //
102    if (this == &copy)
103      return *this;
104    fHypothesis = copy.fHypothesis;
105    fMass = copy.fMass;
106    fTolerance = copy.fTolerance;
107    fMaxDCAVertex = copy.fMaxDCAVertex;
108    fMinCosPointAngle = copy.fMinCosPointAngle;
109    fMaxDaughtersDCA = copy.fMaxDaughtersDCA;
110    fMinTPCcluster = copy.fMinTPCcluster;
111    fMaxRapidity = copy.fMaxRapidity;
112    fCutQuality = copy.fCutQuality;
113    fPID = copy.fPID;
114    fPID2 = copy.fPID2;
115    fPIDCutProton = copy.fPIDCutProton;
116    fPIDCutPion = copy.fPIDCutPion;
117    fESDtrackCuts = copy.fESDtrackCuts;
118    fCutQuality = copy.fCutQuality;
119    fAODTestFilterBit = copy.fAODTestFilterBit;
120
121    return (*this);
122 }
123
124 //_________________________________________________________________________________________________
125 Bool_t AliRsnCutV0::IsSelected(TObject *object)
126 {
127 //:IsSelected: Object is not a V0 (RESONANCES/AliRsnCutV0.cxx:149)
128
129 // Cut checker.
130 // Checks the type of object being evaluated
131 // and then calls the appropriate sub-function (for ESD or AOD)
132 //
133
134    // coherence check
135    if (!TargetOK(object)) return kFALSE;
136
137    // check cast
138    AliESDv0 *v0esd = fDaughter->Ref2ESDv0();
139    AliAODv0 *v0aod = fDaughter->Ref2AODv0();
140    //cout << fDaughter->GetRef()->ClassName() << ' ' << v0esd << ' ' << v0aod << endl;
141
142    // operate depending on cast:IsSelected: Object is not a V0 (RESONANCES/AliRsnCutV0.cxx:149)
143
144    if (v0esd) {
145       return CheckESD(v0esd);
146    } else if (v0aod) {
147       return CheckAOD(v0aod);
148    } else {
149       AliDebugClass(1, "Object is not a V0");
150       return kFALSE;
151    }
152 }
153
154 //_________________________________________________________________________________________________
155 Bool_t AliRsnCutV0::CheckESD(AliESDv0 *v0)
156 {
157 //
158 // Check an ESD V0.
159 // This is done using the default track checker for ESD.
160 // It is declared static, not to recreate it every time.
161 //
162
163    AliDebugClass(1, "Check ESD");
164    if (v0->GetOnFlyStatus()) {
165       AliDebugClass(1, "Rejecting V0 in 'on fly' status");
166       return kFALSE; // if kTRUE, then this V0 is recontructed
167    }
168
169    // retrieve pointer to owner event
170    AliESDEvent *lESDEvent = fEvent->GetRefESD();
171    Double_t xPrimaryVertex = lESDEvent->GetPrimaryVertex()->GetX();
172    Double_t yPrimaryVertex = lESDEvent->GetPrimaryVertex()->GetY();
173    Double_t zPrimaryVertex = lESDEvent->GetPrimaryVertex()->GetZ();
174    AliDebugClass(2, Form("Primary vertex: %f %f %f", xPrimaryVertex, yPrimaryVertex, zPrimaryVertex));
175
176    // retrieve the V0 daughters
177    UInt_t lIdxPos      = (UInt_t) TMath::Abs(v0->GetPindex());
178    UInt_t lIdxNeg      = (UInt_t) TMath::Abs(v0->GetNindex());
179    AliESDtrack *pTrack = lESDEvent->GetTrack(lIdxPos);
180    AliESDtrack *nTrack = lESDEvent->GetTrack(lIdxNeg);
181
182    // check quality cuts
183    if (fESDtrackCuts) {
184       AliDebugClass(2, "Checking quality cuts");
185       if (!fESDtrackCuts->IsSelected(pTrack)) {
186          AliDebugClass(2, "Positive daughter failed quality cuts");
187          return kFALSE;
188       }
189       if (!fESDtrackCuts->IsSelected(nTrack)) {
190          AliDebugClass(2, "Negative daughter failed quality cuts");
191          return kFALSE;
192       }
193    }
194
195    // filter like-sign V0
196    if ( TMath::Abs( ((pTrack->GetSign()) - (nTrack->GetSign())) ) < 0.1) {
197       AliDebugClass(2, "Failed like-sign V0 check");
198       return kFALSE;
199    }
200
201
202    // check compatibility with expected species hypothesis
203    v0->ChangeMassHypothesis(fHypothesis);
204    if ((TMath::Abs(v0->GetEffMass() - fMass)) > fTolerance) {
205       AliDebugClass(2, "V0 is not in the expected inv mass range");
206       return kFALSE;
207    }
208
209    // topological checks
210    if (TMath::Abs(v0->GetD(xPrimaryVertex, yPrimaryVertex, zPrimaryVertex)) > fMaxDCAVertex) {
211       AliDebugClass(2, "Failed check on DCA to primary vertes");
212       return kFALSE;
213    }
214       if (TMath::Abs(v0->GetV0CosineOfPointingAngle()) < fMinCosPointAngle) {
215       AliDebugClass(2, "Failed check on cosine of pointing angle");
216       return kFALSE;
217    }
218    if (TMath::Abs(v0->GetDcaV0Daughters()) > fMaxDaughtersDCA) {
219       AliDebugClass(2, "Failed check on DCA between daughters");
220       return kFALSE;
221    }
222    if (TMath::Abs(v0->Y(fHypothesis)) > fMaxRapidity) {
223       AliDebugClass(2, "Failed check on V0 rapidity");
224       return kFALSE;
225    }
226
227    Double_t v0Position[3]; // from $ALICE_ROOT/ANALYSIS/AliESDV0Cuts.cxx
228   v0->GetXYZ(v0Position[0],v0Position[1],v0Position[2]);
229   Double_t radius = TMath::Sqrt(TMath::Power(v0Position[0],2) + TMath::Power(v0Position[1],2));
230   if ( ( radius < 0.8 ) || ( radius > 100 ) ) {
231     AliDebugClass(2, "Failed fiducial volume");
232     return kFALSE;   
233   }
234     
235    // check PID on proton or antiproton from V0
236
237    // check initialization of PID object
238    AliPIDResponse *pid = fEvent->GetPIDResponse();
239    if (!pid) {
240       AliFatal("NULL PID response");
241       return kFALSE;
242    }
243
244    // check if TOF is matched
245    // and computes all values used in the PID cut
246    //Bool_t   isTOFpos  = MatchTOF(ptrack);
247    //Bool_t   isTOFneg  = MatchTOF(ntrack);
248    //Double_t pospTPC   = pTrack->GetTPCmomentum();
249    //Double_t negpTPC   = nTrack->GetTPCmomentum();
250    //Double_t posp      = pTrack->P();
251    //Double_t negp      = nTrack->P();
252    Double_t posnsTPC   = TMath::Abs(pid->NumberOfSigmasTPC(pTrack, fPID));
253    Double_t posnsTPC2  = TMath::Abs(pid->NumberOfSigmasTPC(pTrack, fPID2));
254    //Double_t posnsTOF  = TMath::Abs(pid->NumberOfSigmasTOF(ptrack, fPID));
255    Double_t negnsTPC   = TMath::Abs(pid->NumberOfSigmasTPC(nTrack, fPID));
256    Double_t negnsTPC2  = TMath::Abs(pid->NumberOfSigmasTPC(nTrack, fPID2));
257    //Double_t negnsTOF  = TMath::Abs(pid->NumberOfSigmasTOF(ntrack, fPID));
258    Double_t maxTPC = 1E20;
259    Double_t maxTPC2 = 1E20;
260    //Double_t maxTOF = 1E20;
261
262    // applies the cut differently depending on the PID and the momentum
263
264    if(fHypothesis==kLambda0) {
265       //if (isTOFpos) {
266       // TPC: 5sigma cut for all
267       //if (posnsTPC > 5.0) return kFALSE;
268       // TOF: 3sigma
269       // maxTOF = 3.0;
270       //return (posnsTOF <= maxTOF);
271       //} else {
272       // TPC:
273
274       maxTPC = fPIDCutProton;
275       maxTPC2 = fPIDCutPion;
276
277       if (! ((posnsTPC <= maxTPC) && (negnsTPC2 <= maxTPC2)) ) {
278          AliDebugClass(2, "Failed check on V0 PID");
279          return kFALSE;
280       }
281    }
282
283    //}
284
285    if(fHypothesis==kLambda0Bar) {
286       //if (isTOFneg) {
287       // TPC: 5sigma cut for all
288       //if (negnsTPC > 5.0) return kFALSE;
289       // TOF: 3sigma
290       // maxTOF = 3.0;
291       //return (negnsTOF <= maxTOF);
292       //} else {
293       // TPC:
294
295      
296          maxTPC = fPIDCutProton;
297          maxTPC2 = fPIDCutPion;
298
299       if(! ((negnsTPC <= maxTPC) && (posnsTPC2 <= maxTPC2)) ) {
300          AliDebugClass(2, "Failed check on V0 PID");
301          return kFALSE;
302       }
303    }
304    //}
305
306
307    // if we reach this point, all checks were successful
308    AliDebugClass(2, "Good V0");
309    return kTRUE;
310 }
311
312 //_________________________________________________________________________________________________
313 Bool_t AliRsnCutV0::CheckAOD(AliAODv0 *v0)
314 {
315 //
316 // Check an AOD V0.
317 // This is done doing directly all checks, since there is not
318 // an equivalend checker for AOD tracks
319 //
320
321    AliDebugClass(2, "Check AOD");
322    if (v0->GetOnFlyStatus()) {
323       AliDebugClass(2, "Rejecting V0 in 'on fly' status");
324       return kFALSE; // if kTRUE, then this V0 is recontructed
325    }
326
327    // retrieve pointer to owner event
328    AliAODEvent *lAODEvent = fEvent->GetRefAOD();
329    Double_t xPrimaryVertex = lAODEvent->GetPrimaryVertex()->GetX();
330    Double_t yPrimaryVertex = lAODEvent->GetPrimaryVertex()->GetY();
331    Double_t zPrimaryVertex = lAODEvent->GetPrimaryVertex()->GetZ();
332    AliDebugClass(2, Form("Primary vertex: %f %f %f", xPrimaryVertex, yPrimaryVertex, zPrimaryVertex));
333
334    // retrieve the V0 daughters
335    AliAODTrack *pTrack = (AliAODTrack *) (v0->GetSecondaryVtx()->GetDaughter(0));
336    AliAODTrack *nTrack = (AliAODTrack *) (v0->GetSecondaryVtx()->GetDaughter(1));
337
338    // check quality cuts
339    UInt_t  filtermapP = 9999;
340    UInt_t  filtermapN = 9999;
341    filtermapP = pTrack->GetFilterMap();
342    filtermapN = nTrack->GetFilterMap();
343
344    //-----
345    // next lines commented out by EF - 17/01/2014 
346    // NOTE that the filter bit test on V0 daughters removes a huge amount of V0 candidates, including good ones.
347    //      Likely wrong -> requires a DCA max!
348    //      Removing the test, there's a little gain in efficiency in the
349    //      final search for Sigma* candidates
350    // NOTE that further constrains (e.g. DCA of daughters greater than xxx), 
351    //      necessary to remove background, are already in V0s. (see also below)
352    /*
353    if ( !pTrack->TestFilterBit(fAODTestFilterBit)   ) {
354       AliDebugClass(2, Form("Positive daughter failed quality cuts filtermapP=%d",filtermapP));
355       return kFALSE;
356    }
357    if ( !nTrack->TestFilterBit(fAODTestFilterBit)   ) {
358       AliDebugClass(2, Form("Negative daughter failed quality cuts filtermapN=%d",filtermapN));
359       return kFALSE;
360    }
361    */
362
363    //----
364    // next lines are not necessary. Just left there (commented-out) to remind that the requirement on the DCA of V0 daughters
365    //      is already in the V0, so requiring dca>0.050 (with 0.050 cm the default value from the Lambda analysis)
366    //      does not remove V0s candidates
367    /*
368    Double_t dca = v0->DcaPosToPrimVertex() ;
369      AliDebugClass(2, Form("DCA of Lambda positive daughter %f",dca));
370    if(dca<0.050) {
371      AliDebugClass(2, Form("DCA of Lambda positive daughter (%f) less than 0.05",dca));
372       return kFALSE;
373    }
374    dca = v0->DcaNegToPrimVertex();
375    if(dca<0.050) {
376      AliDebugClass(2, Form("DCA of Lambda negative daughter (%f) less than 0.05",dca));
377       return kFALSE;
378    }
379    */
380
381    // EF - 17/01/2014 - next check apparently not effective!? Already in V0s?
382    // filter like-sign V0
383    if ( TMath::Abs( ((pTrack->Charge()) - (nTrack->Charge())) ) < 0.1) {
384       AliDebugClass(2, "Failed like-sign V0 check");
385       return kFALSE;
386    }
387
388    // check compatibility with expected species hypothesis
389    Double_t mass = 0.0;
390    if(fHypothesis==kLambda0) {
391       mass = v0->MassLambda();
392    }
393    else if (fHypothesis==kLambda0Bar) {
394       mass = v0->MassAntiLambda();
395    }
396    if ((TMath::Abs(mass - fMass)) > fTolerance) {
397       AliDebugClass(2, Form("V0 is not in the expected inv mass range  Mass: %d %f %f", fHypothesis, fMass, mass));
398       return kFALSE;
399    }
400    AliDebugClass(2, Form("Mass: %d %f %f", fHypothesis, fMass, mass));
401
402
403    // topological checks
404    if (TMath::Abs(v0->DcaV0ToPrimVertex()) > fMaxDCAVertex) {
405       AliDebugClass(2, Form("Failed check on DCA to primary vertes dca=%f maxdca=%f",TMath::Abs(v0->DcaV0ToPrimVertex()),fMaxDCAVertex));
406       return kFALSE;
407    }
408
409    // next cut is effective (should it be in AODV0?)     
410    AliAODVertex *vertex = lAODEvent->GetPrimaryVertex();
411    Double_t cospointangle = v0->CosPointingAngle(vertex);
412    if (TMath::Abs( cospointangle )  < fMinCosPointAngle) {
413      AliDebugClass(2, "Failed check on cosine of pointing angle");
414      return kFALSE;
415    }
416  
417   // next cut is effective (should it be in AODV0?)
418    if (TMath::Abs(v0->DcaV0Daughters()) > fMaxDaughtersDCA) {
419       AliDebugClass(2, "Failed check on DCA between daughters");
420       return kFALSE;
421    }
422
423    if (TMath::Abs(v0->RapLambda()) > fMaxRapidity) {
424       AliDebugClass(2, "Failed check on V0 rapidity");
425       return kFALSE;
426    }
427
428    Double_t radius = v0->RadiusV0();
429    if ( ( radius < 0.8 ) || ( radius > 100 ) ) {
430      AliDebugClass(2, "Failed fiducial volume");
431      return kFALSE;   
432    }
433
434    //-----------------------------------------------------------
435    // check initialization of PID object
436    AliPIDResponse *pid = fEvent->GetPIDResponse();
437    if (!pid) {
438       AliFatal("NULL PID response");
439       return kFALSE;
440    }
441
442    Double_t posnsTPC   = TMath::Abs(pid->NumberOfSigmasTPC(pTrack, fPID));
443    Double_t posnsTPC2  = TMath::Abs(pid->NumberOfSigmasTPC(pTrack, fPID2));
444    Double_t negnsTPC   = TMath::Abs(pid->NumberOfSigmasTPC(nTrack, fPID));
445    Double_t negnsTPC2  = TMath::Abs(pid->NumberOfSigmasTPC(nTrack, fPID2));
446    Double_t maxTPC = 1E20;
447    Double_t maxTPC2 = 1E20;
448
449    // applies the cut differently depending on the PID and the momentum
450    if(fHypothesis==kLambda0) {
451      maxTPC = fPIDCutProton; 
452      maxTPC2 = fPIDCutPion;      
453      if (! ((posnsTPC <= maxTPC) && (negnsTPC2 <= maxTPC2)) ) {
454        AliDebugClass(2, "Failed check on V0 PID");
455        return kFALSE;
456      }
457    }
458    
459    if(fHypothesis==kLambda0Bar) {
460      maxTPC = fPIDCutProton;
461      maxTPC2 = fPIDCutPion;
462      if(! ((negnsTPC <= maxTPC) && (posnsTPC2 <= maxTPC2)) ) {
463        AliDebugClass(2, "Failed check on V0 PID");
464        return kFALSE;
465      }
466    }
467    
468    //---------------------------------------------------------------
469    // if we reach this point, all checks were successful
470    AliDebugClass(1, "Good AOD V0");
471    AliDebugClass(1, Form("Mass: %d %f %f %d %d", fHypothesis, fMass, mass, filtermapP, filtermapN));
472    return kTRUE;
473
474 }
475
476 //_________________________________________________________________________________________________
477 void AliRsnCutV0::Print(const Option_t *) const
478 {
479 //
480 // Print information on this cut
481 //
482 }