]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWG/muon/AliMuonEventCuts.cxx
Add pileup rejection in AliMuonEventCuts (Diego)
[u/mrichter/AliRoot.git] / PWG / muon / AliMuonEventCuts.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
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  **************************************************************************/
15
16 #include "AliMuonEventCuts.h"
17
18 #include "TMath.h"
19 #include "TFormula.h"
20 #include "THashList.h"
21 #include "TObjArray.h"
22 #include "TObjString.h"
23 #include "TFile.h"
24 #include "TParameter.h"
25 #include "TKey.h"
26 #include "TSystem.h"
27 #include "TAxis.h"
28 #include "TArrayI.h"
29 #include "TRegexp.h"
30 #include "TPRegexp.h"
31
32 #include "AliLog.h"
33 #include "AliInputEventHandler.h"
34 #include "AliVEvent.h"
35 #include "AliESDEvent.h"
36 #include "AliAODEvent.h"
37 #include "AliVVertex.h"
38 #include "AliCentrality.h"
39 #include "AliAnalysisUtils.h"
40
41 #include "AliAnalysisMuonUtility.h"
42
43 /// \cond CLASSIMP
44 ClassImp(AliMuonEventCuts) // Class implementation in ROOT context
45 /// \endcond
46
47
48 //________________________________________________________________________
49 AliMuonEventCuts::AliMuonEventCuts() :
50   AliAnalysisCuts(),
51   fPhysicsSelectionMask(0),
52   fVertexMinNContributors(0),
53   fVertexVzMin(0.),
54   fVertexVzMax(0.),
55   fCheckMask(0),
56   fDefaultTrigClassPatterns(""),
57   fSelectedTrigPattern(0x0),
58   fRejectedTrigPattern(0x0),
59   fSelectedTrigLevel(0x0),
60   fSelectedTrigCombination(0x0),
61   fTrigInputsMap(0x0),
62   fAllSelectedTrigClasses(0x0),
63   fCentralityClasses(0x0),
64   fAnalysisUtils(0x0),
65   fEventTriggerMask(0),
66   fSelectedTrigClassesInEvent(0x0)
67 {
68   /// Default ctor.
69 }
70
71 //________________________________________________________________________
72 AliMuonEventCuts::AliMuonEventCuts(const char* name, const char* title ) :
73 AliAnalysisCuts(name, title),
74   fPhysicsSelectionMask(0),
75   fVertexMinNContributors(0),
76   fVertexVzMin(0.),
77   fVertexVzMax(0.),
78   fCheckMask(0xFFFF),
79   fDefaultTrigClassPatterns(""),
80   fSelectedTrigPattern(new TObjArray()),
81   fRejectedTrigPattern(new TObjArray()),
82   fSelectedTrigLevel(new TObjArray()),
83   fSelectedTrigCombination(new TObjArray()),
84   fTrigInputsMap(new THashList()),
85   fAllSelectedTrigClasses(new THashList()),
86   fCentralityClasses(0x0),
87   fAnalysisUtils(0x0),
88   fEventTriggerMask(0),
89   fSelectedTrigClassesInEvent(new TObjArray())
90 {
91   /// Constructor
92   SetDefaultParameters();
93   SetDefaultFilterMask();
94   SetDefaultTrigClassPatterns();
95   SetTrigClassLevels();
96   SetDefaultTrigInputsMap();
97   SetCentralityClasses();
98   fAnalysisUtils = new AliAnalysisUtils();
99   fAllSelectedTrigClasses->SetOwner();
100   fSelectedTrigClassesInEvent->SetOwner();
101 }
102
103 //________________________________________________________________________
104 AliMuonEventCuts::AliMuonEventCuts(const AliMuonEventCuts& obj) :
105   AliAnalysisCuts(obj),
106   fPhysicsSelectionMask(obj.fPhysicsSelectionMask),
107   fVertexMinNContributors(obj.fVertexMinNContributors),
108   fVertexVzMin(obj.fVertexVzMin),
109   fVertexVzMax(obj.fVertexVzMax),
110   fCheckMask(obj.fCheckMask),
111   fDefaultTrigClassPatterns(obj.fDefaultTrigClassPatterns),
112   fSelectedTrigPattern(obj.fSelectedTrigPattern),
113   fRejectedTrigPattern(obj.fRejectedTrigPattern),
114   fSelectedTrigLevel(obj.fSelectedTrigLevel),
115   fSelectedTrigCombination(obj.fSelectedTrigCombination),
116   fTrigInputsMap(obj.fTrigInputsMap),
117   fAllSelectedTrigClasses(obj.fAllSelectedTrigClasses),
118   fCentralityClasses(obj.fCentralityClasses),
119   fAnalysisUtils(obj.fAnalysisUtils),
120   fEventTriggerMask(obj.fEventTriggerMask),
121   fSelectedTrigClassesInEvent(obj.fSelectedTrigClassesInEvent)
122 {
123   /// Copy constructor
124 }
125
126
127 //________________________________________________________________________
128 AliMuonEventCuts& AliMuonEventCuts::operator=(const AliMuonEventCuts& obj)
129 {
130   /// Assignment operator
131   if ( this != &obj ) { 
132     AliAnalysisCuts::operator=(obj);
133     fPhysicsSelectionMask = obj.fPhysicsSelectionMask;
134     fVertexMinNContributors = obj.fVertexMinNContributors,
135     fVertexVzMin = obj.fVertexVzMin;
136     fVertexVzMax = obj.fVertexVzMax;
137     fCheckMask = obj.fCheckMask;
138     fDefaultTrigClassPatterns = obj.fDefaultTrigClassPatterns;
139     fSelectedTrigPattern = obj.fSelectedTrigPattern;
140     fRejectedTrigPattern = obj.fRejectedTrigPattern;
141     fSelectedTrigLevel = obj.fSelectedTrigLevel;
142     fSelectedTrigCombination = obj.fSelectedTrigCombination;
143     fTrigInputsMap = obj.fTrigInputsMap;
144     fAllSelectedTrigClasses = obj.fAllSelectedTrigClasses;
145     fCentralityClasses = obj.fCentralityClasses;
146     fAnalysisUtils = obj.fAnalysisUtils;
147     fEventTriggerMask = obj.fEventTriggerMask;
148     fSelectedTrigClassesInEvent = obj.fSelectedTrigClassesInEvent;
149   }
150   return *this;
151 }
152
153
154 //________________________________________________________________________
155 AliMuonEventCuts::~AliMuonEventCuts()
156 {
157   /// Destructor
158   delete fSelectedTrigPattern;
159   delete fRejectedTrigPattern;
160   delete fSelectedTrigLevel;
161   delete fSelectedTrigCombination;
162   delete fTrigInputsMap;
163   delete fAllSelectedTrigClasses;
164   delete fSelectedTrigClassesInEvent;
165   delete fCentralityClasses;
166   delete fAnalysisUtils;
167 }
168
169 //________________________________________________________________________
170 Bool_t AliMuonEventCuts::IsSelected( TObject* obj )
171 {
172   /// Track is selected
173   UInt_t filterMask = GetFilterMask();
174   UInt_t selectionMask = GetSelectionMask(obj);
175   
176   AliDebug(1, Form("Is event selected %i  mask 0x%x", ( selectionMask & filterMask ) == filterMask, selectionMask ));
177   
178   return ( ( selectionMask & filterMask ) == filterMask );
179 }
180
181
182 //________________________________________________________________________
183 UInt_t AliMuonEventCuts::GetSelectionMask( const TObject* obj )
184 {
185   /// Get selection mask
186   
187   UInt_t selectionMask = 0;
188   
189   UInt_t checkMask = fCheckMask | GetFilterMask();
190   
191   const AliInputEventHandler* inputHandler = static_cast<const AliInputEventHandler*> ( obj );
192   
193   if ( checkMask & kPhysicsSelected ) {
194     if ( const_cast<AliInputEventHandler*>(inputHandler)->IsEventSelected() & fPhysicsSelectionMask ) selectionMask |= kPhysicsSelected;
195   }
196   
197   const AliVEvent* event = inputHandler->GetEvent();
198   
199   Double_t centrality = GetCentrality(event);
200   if ( centrality >= fCentralityClasses->GetXmin() && centrality <= fCentralityClasses->GetXmax() ) selectionMask |= kSelectedCentrality;
201   
202   UpdateEvent(event);
203   
204   if ( fSelectedTrigClassesInEvent->GetEntries() > 0 ) selectionMask |= kSelectedTrig;
205   
206   if ( checkMask & kGoodVertex ) {
207     AliVVertex* vertex = AliAnalysisMuonUtility::GetVertexSPD(event);
208     if ( vertex->GetNContributors() >= GetVertexMinNContributors() &&
209       vertex->GetZ() >= GetVertexVzMin() && vertex->GetZ() <= GetVertexVzMax() ) selectionMask |= kGoodVertex;
210   }
211   
212   if ( checkMask & kNoPileup ) {
213     if ( ! fAnalysisUtils->IsPileUpEvent(const_cast<AliVEvent*>(event)) ) selectionMask |= kNoPileup;
214     //  // Uncomment to use settings for pPb
215     //  if ( fRejectPileup ) {
216     //    Int_t nTracklets = ( event.IsA() == AliESDEvent::Class() ) ? static_cast<AliESDEvent*>(event)->GetMultiplicity()->GetNumberOfTracklets() : static_cast<AliAODEvent*>(event)->GetTracklets()->GetNumberOfTracklets();
217     //    Int_t nContrib = ( nTracklets < 40 ) ? 3 : 5;
218     //    Double_t dist = 0.8;
219     //    Bool_t isPielup = ( event.IsA() == AliESDEvent::Class() ) ? static_cast<AliESDEvent*>(event)->IsPileupFromSPD(nContrib,dist) : static_cast<AliAODEvent*>(event)->IsPileupFromSPD(nContrib,dist);
220     //    if ( isPielup ) return;
221     //  }
222   }
223
224   AliDebug(1, Form("Selection mask 0x%x\n", selectionMask));
225   return selectionMask;
226 }
227
228
229 //________________________________________________________________________
230 Bool_t AliMuonEventCuts::IsSelected( TList* /* list */)
231 {
232   /// Not implemented
233   AliError("Function not implemented: Use IsSelected(TObject*)");
234   return kFALSE;
235 }
236
237 //________________________________________________________________________
238 Bool_t AliMuonEventCuts::UpdateEvent ( const AliVEvent* event )
239 {
240   /// Update the transient data member per event
241   
242   if ( fSelectedTrigClassesInEvent && ( fEventTriggerMask == event->GetTriggerMask() ) ) return kFALSE;
243   
244   BuildTriggerClasses(AliAnalysisMuonUtility::GetFiredTriggerClasses(event), AliAnalysisMuonUtility::GetL0TriggerInputs(event), AliAnalysisMuonUtility::GetL1TriggerInputs(event), AliAnalysisMuonUtility::GetL2TriggerInputs(event));
245   
246   fEventTriggerMask = event->GetTriggerMask();
247   
248   return kTRUE;
249 }
250
251 //________________________________________________________________________
252 void AliMuonEventCuts::SetDefaultTrigClassPatterns ()
253 {
254   /// Set the default patterns
255   /// (done in such a way to get all muon triggers)
256   fDefaultTrigClassPatterns = "CM*,C0M*,CINT*,CPBI*,CCENT*,CV*,!*ABCE*,!*-ACE-*,!*-AC-*,!*-E-*,!*WU*,!*EGA*,!*EJE*,!*PHS*";
257   SetTrigClassPatterns(fDefaultTrigClassPatterns);
258 }
259
260
261 //________________________________________________________________________
262 void AliMuonEventCuts::SetTrigClassPatterns ( const TString trigPattern )
263 {
264   /// Set trigger classes
265   ///
266   /// 1) specify trigger class pattern and reject pattern (wildcard * accepted)
267   /// Classes will be filled dynamycally according to the pattern
268   /// - if name contains ! (without spaces): reject it
269   /// - otherwise keep it
270   /// e.g. CMBAC*,!*ALLNOTRD*
271   /// keeps classes beginning with CMBAC, and not containing ALLNOTRD.
272   ///
273   /// CAVEATs:
274   ///   a ) if a wildcard is not specified, exact match is required
275   ///   b ) if you use an fCFContainer and you want an axis to contain the trigger classes,
276   ///       please be sure that each pattern matches only 1 trigger class, or triggers will be mixed up
277   ///       when merging different chuncks.
278   ///
279   ///
280   /// 2) specify a combination of triggers
281   /// combined through a logical AND "&" or a logical OR "|" (wildcard * NOT accepted)
282   /// It is also possible to ask for a trigger class containing a specific trigger input:
283   /// e.g. CMSL7-B-NOPF-MUON&0MSH,CMSL7-B-NOPF-MUON,CMSL7-B-NOPF-MUON|CMSL8-B-NOPF-MUON
284   /// will give the events with:
285   /// - the single low trigger class fired and containing a single high trigger input
286   /// - the single low trigger class fired
287   /// - the single low trigger class 7 or 8 fired
288   /// By default, when specific trigger combinations are provided, the most general case
289   /// based on trigger pattern is disabled...but it can be activated with the disableTrigPattern flag
290   ///
291   /// example:
292   /// SetTrigClassPatterns("CINT7*,!*-ACE-*,CMSL7-B-NOPF-MUON,CMSL7-B-NOPF-MUON&0MSH")
293   
294   
295   fSelectedTrigCombination->SetOwner();
296   if ( fSelectedTrigCombination->GetEntries() > 0 ) fSelectedTrigCombination->Delete();
297   fSelectedTrigPattern->SetOwner();
298   if ( fSelectedTrigPattern->GetEntries() > 0 ) fSelectedTrigPattern->Delete();
299   fRejectedTrigPattern->SetOwner();
300   if ( fRejectedTrigPattern->GetEntries() > 0 ) fRejectedTrigPattern->Delete();
301   
302   TString badSyntax = "", duplicated = "";
303   TString listName[4] = {"L0","L1","L2","trigClass"};
304   
305   TString pattern(trigPattern);
306   pattern.ReplaceAll(" ","");
307   TObjArray* fullList = pattern.Tokenize(",");
308   TIter next(fullList);
309   TObjString* objString = 0x0;
310   
311   TObjArray combinationList;
312   // First search for patterns
313   while ( ( objString = static_cast<TObjString*>(next()) ) ) {
314     TString currPattern = objString->String();
315     Bool_t isCombination = ( currPattern.Contains("&") || currPattern.Contains("|") );
316     Bool_t isSingleTrigger = ( ! isCombination && ! currPattern.BeginsWith("0") && ! currPattern.BeginsWith("1") && ! currPattern.BeginsWith("2") );
317     Bool_t isMatchPattern = ( currPattern.Contains("*") || isSingleTrigger );
318     Bool_t isRejectPattern = kFALSE;
319     if ( currPattern.Contains("!") ) {
320       currPattern.ReplaceAll("!","");
321       isRejectPattern = kTRUE;
322     }
323     if ( isCombination && ( isMatchPattern || isRejectPattern ) ) {
324       badSyntax += Form(" %s;", currPattern.Data());
325       continue;
326     }
327     if ( isRejectPattern ) {
328       fRejectedTrigPattern->AddLast(new TObjString(currPattern));
329       AliDebug(1,Form("Adding %s to reject pattern",currPattern.Data()));
330     }
331     else if ( isMatchPattern ) {
332       fSelectedTrigPattern->AddLast(new TObjString(currPattern));
333       AliDebug(1,Form("Adding %s to match pattern",currPattern.Data()));
334     }
335     else combinationList.Add(objString);
336   }
337   
338   // Then check for combinations
339   TIter nextCombo(&combinationList);
340   while ( ( objString = static_cast<TObjString*>(nextCombo()) ) ) {
341     TString currPattern = objString->String();
342     
343     TString tn (currPattern);
344     Bool_t hasAND = kFALSE, hasOR = kFALSE;
345     if ( tn.Contains("&") ) {
346       tn.ReplaceAll("&",":");
347       hasAND = kTRUE;
348     }
349     if ( tn.Contains("|") ) {
350       tn.ReplaceAll("|",":");
351       hasOR = kTRUE;
352     }
353     if ( tn.Contains("(") || tn.Contains(")") ) {
354       tn.ReplaceAll("(","");
355       tn.ReplaceAll(")","");
356     }
357     
358     if ( ! hasAND && ! hasOR ) {
359       if ( CheckTriggerClassPattern(currPattern) ) {
360         duplicated += Form("%s ", currPattern.Data());
361         continue;
362       }
363     }
364     
365     TObjArray* trigCombo = new TObjArray();
366     trigCombo->SetOwner();
367     trigCombo->SetName(currPattern.Data());
368     
369     UInt_t uniqueID = kComboSimple;
370     if ( hasAND && hasOR ) uniqueID = kComboFormula;
371     else if ( hasAND ) uniqueID = kComboAND;
372     else if ( hasOR ) uniqueID = kComboOR;
373     
374     trigCombo->SetUniqueID(uniqueID);
375     
376     TObjArray* arr = tn.Tokenize(":");
377     
378     TIter nextA(arr);
379     TObjString* an = 0x0;
380     while ( ( an = static_cast<TObjString*>(nextA()) ) )
381     {
382       Int_t listIdx = 3;
383       if ( an->String().BeginsWith("0") ) listIdx = 0;
384       else if ( an->String().BeginsWith("1") ) listIdx = 1;
385       else if ( an->String().BeginsWith("2") ) listIdx = 2;
386       
387       TObjArray* currList = static_cast<TObjArray*>(trigCombo->FindObject(listName[listIdx].Data()));
388       if ( ! currList ) {
389         currList = new TObjArray();
390         currList->SetOwner();
391         currList->SetName(listName[listIdx].Data());
392         currList->SetUniqueID(listIdx);
393         trigCombo->AddAt(currList,listIdx);
394       }
395       TObjString* currStr = new TObjString(an->String());
396       
397       if ( listIdx < 3 ) {
398         // that's an input
399         TObject* trigInput = fTrigInputsMap->FindObject(an->String().Data());
400         if ( trigInput ) currStr->SetUniqueID(trigInput->GetUniqueID());
401         else {
402           AliError(Form("Uknown input %s in formula %s", an->String().Data(), currPattern.Data()));
403           delete trigCombo;
404           trigCombo = 0x0;
405           break;
406         }
407       }
408       currList->AddLast(currStr);
409     }
410     delete arr;
411     if ( trigCombo) {
412       fSelectedTrigCombination->AddLast(trigCombo);
413       AliDebug(1,Form("Adding %s to trigger combination (type %u)",currPattern.Data(),trigCombo->GetUniqueID()));
414     }
415   }
416   delete fullList;
417   
418   if ( ! duplicated.IsNull() )
419     AliWarning(Form("Triggers %s already accounted in patterns",duplicated.Data()));
420   if ( ! badSyntax.IsNull() )
421     AliWarning(Form("%s : illegal expressions. Must be in the form:\n   pattern* => keep class if it contains pattern\n   !pattern* => reject class if it contains pattern\n   class&input = keep class if it satisfies the expression (exact matching required)",badSyntax.Data()));
422 }
423
424
425 //________________________________________________________________________
426 void AliMuonEventCuts::SetTrigClassLevels ( TString pattern )
427 {
428   /// Set trigger cut level associated to the trigger class
429   ///
430   /// example:
431   /// SetTrigClassLevels("MSL:Lpt,MSH:Hpt,MUL:LptLpt")
432   ///
433   /// For the trigger classes defined in SetTrigClassPatterns
434   /// it check if they contains the keywords MSL or MSH
435   /// Hence, in the analysis, the function
436   /// TrackPtCutMatchTrigClass(track, "CPBIMSL") returns true if track match Lpt
437   /// TrackPtCutMatchTrigClass(track, "CPBIMSH") returns true if track match Hpt
438   /// TrackPtCutMatchTrigClass(track, "CMBAC") always returns true
439   
440   fSelectedTrigLevel->SetOwner();
441   if ( fSelectedTrigLevel->GetEntries() > 0 ) fSelectedTrigLevel->Delete();
442   
443   pattern.ReplaceAll(" ","");
444   
445   TObjArray* fullList = pattern.Tokenize(",");
446   UInt_t offset = 2;
447   for ( Int_t ipat=0; ipat<fullList->GetEntries(); ++ipat ) {
448     TString currPattern = fullList->At(ipat)->GetName();
449     TObjArray* arr = currPattern.Tokenize(":");
450     TObjString* trigClassPattern = new TObjString(arr->At(0)->GetName());
451     TString selTrigLevel = arr->At(1)->GetName();
452     selTrigLevel.ToUpper();
453     UInt_t trigLevel = 0;
454     if ( selTrigLevel.Contains("LPT") ) {
455       trigLevel = 2;
456       if ( selTrigLevel.Contains("LPTLPT") ) trigLevel += 2<<offset;
457     }
458     else if ( selTrigLevel.Contains("HPT") ) {
459       trigLevel = 3;
460       if ( selTrigLevel.Contains("HPTHPT") ) trigLevel += 3<<offset;
461     }
462     trigClassPattern->SetUniqueID(trigLevel);
463     fSelectedTrigLevel->AddLast(trigClassPattern);
464     delete arr;
465   }
466   
467   delete fullList;
468 }
469
470 //________________________________________________________________________
471 UInt_t AliMuonEventCuts::GetTriggerInputBitMaskFromInputName(const char* inputName) const
472 {
473   // Get trigger input bit from its name
474   
475   if (!fTrigInputsMap)
476   {
477     AliError("No Inputs Map available");
478     return TMath::Limits<UInt_t>::Max();
479   }
480   
481   TObjString* s = static_cast<TObjString*>(fTrigInputsMap->FindObject(inputName));
482   if (!s)
483   {
484     AliError(Form("Did not find input %s",inputName));
485     return TMath::Limits<UInt_t>::Max();    
486   }
487   return s->GetUniqueID();
488 }
489
490 //________________________________________________________________________
491 TArrayI AliMuonEventCuts::GetTrigClassPtCutLevel ( const TString trigClassName ) const
492 {
493   /// Get trigger class pt cut level for tracking/trigger matching
494   ///
495   /// CAVEAT: this functionality fully works with trigger class names,
496   ///   but it can have a problem to extract the correct information in
497   ///   combinations of trigger classes/inputs. In this case it provides:
498   ///   - the highest pt level among classes/inputs combined through a logical AND "&"
499   ///   - the lowest pt level among classes/inputs combined through a logical OR "|"
500   ///   The first should be fine, but the second could not be the proper matching.
501   TObject* obj = fAllSelectedTrigClasses->FindObject(trigClassName.Data());
502   if ( ! obj ) {
503     AliWarning(Form("Class %s not in the list!", trigClassName.Data()));
504     return -1;
505   }
506   
507   TArrayI ptCutLevel(2);
508   ptCutLevel.Reset();
509   ptCutLevel[0] = obj->GetUniqueID() & 0x3;
510   ptCutLevel[1] = ( obj->GetUniqueID() >> 2 ) & 0x3;
511   
512   AliDebug(3,Form("Class %s ptCutLevel %i %i",trigClassName.Data(),ptCutLevel[0],ptCutLevel[1]));
513   
514   return ptCutLevel;
515 }
516
517
518 //________________________________________________________________________
519 void AliMuonEventCuts::SetTrigInputsMap ( TString trigInputsMap )
520 {
521   /// Set trigger input mask
522   /// The inputs must be in the form:
523   /// input1:ID1,input2:ID2,...
524   /// CAVEAT: the input ID is ID_aliceLogbook - 1
525   /// since this is the ID in the OCDB
526   
527   fTrigInputsMap->SetOwner();
528   if ( fTrigInputsMap->GetEntries() > 0 ) fTrigInputsMap->Delete();
529   
530   trigInputsMap.ReplaceAll(" ","");
531   
532   TObjArray* fullList = trigInputsMap.Tokenize(",");
533   for ( Int_t ipat=0; ipat<fullList->GetEntries(); ++ipat ) {
534     TString currPattern = fullList->At(ipat)->GetName();
535     TObjArray* arr = currPattern.Tokenize(":");
536     TObjString* trigInput = new TObjString(arr->At(0)->GetName());
537     UInt_t trigID = (UInt_t)static_cast<TObjString*>(arr->At(1))->GetString().Atoi();
538     trigInput->SetUniqueID(1<<trigID);
539     fTrigInputsMap->Add(trigInput);
540     delete arr;
541   }
542   delete fullList;
543 }
544
545 //________________________________________________________________________
546 void AliMuonEventCuts::SetDefaultTrigInputsMap ()
547 {
548   /// Set default trigger input mask
549   
550   TString trigInputsMap = "0VBA:0,";
551   trigInputsMap += "0VBC:1,";
552   trigInputsMap += "0SMB:2,";
553   trigInputsMap += "0TVX:3,";
554   trigInputsMap += "0VGC:4,";
555   trigInputsMap += "0VGA:5,";
556   trigInputsMap += "0SH1:6,";
557   trigInputsMap += "0SH2:7,";
558   trigInputsMap += "0HPT:8,";
559   trigInputsMap += "0AMU:9,";
560   trigInputsMap += "0OB0:10,";
561   trigInputsMap += "0ASL:11,";
562   trigInputsMap += "0MSL:12,";
563   trigInputsMap += "0MSH:13,";
564   trigInputsMap += "0MUL:14,";
565   trigInputsMap += "0MLL:15,";
566   trigInputsMap += "0EMC:16,";
567   trigInputsMap += "0PH0:17,";
568   trigInputsMap += "0HWU:18,";
569   trigInputsMap += "0LSR:19,";
570   trigInputsMap += "0T0A:20,";
571   trigInputsMap += "0BPA:21,";
572   trigInputsMap += "0BPC:22,";
573   trigInputsMap += "0T0C:23,";
574   
575   trigInputsMap += "1EJE:0,";
576   trigInputsMap += "1EGA:1,";
577   trigInputsMap += "1EJ2:2,";
578   trigInputsMap += "1EG2:3,";
579   trigInputsMap += "1PHL:4,";
580   trigInputsMap += "1PHM:5,";
581   trigInputsMap += "1PHH:6,";
582   trigInputsMap += "1HCO:8,";
583   trigInputsMap += "1HJT:9,";
584   trigInputsMap += "1HSE:10,";
585   trigInputsMap += "1DUM:11,";
586   trigInputsMap += "1HQU:12,";
587   trigInputsMap += "1H14:13,";
588   trigInputsMap += "1ZMD:14,";
589   trigInputsMap += "1ZMB:16,";
590   trigInputsMap += "1ZED:17,";
591   trigInputsMap += "1ZAC:18,";
592   trigInputsMap += "1EJE:19";
593   
594   SetTrigInputsMap(trigInputsMap);
595 }
596
597 //________________________________________________________________________
598 const TObjArray*
599 AliMuonEventCuts::GetSelectedTrigClassesInEvent(const TString& firedTriggerClasses,
600                                                 UInt_t l0Inputs, UInt_t l1Inputs,
601                                                 UInt_t l2Inputs)
602 {
603   /// Return the selected trigger classes in the fired trigger classes
604   /// give also the L0,L1,L2 input bit masks
605   
606   BuildTriggerClasses(firedTriggerClasses,l0Inputs,l1Inputs,l2Inputs);
607
608   return fSelectedTrigClassesInEvent;
609 }
610
611 //________________________________________________________________________
612 const TObjArray* AliMuonEventCuts::GetSelectedTrigClassesInEvent( const AliVEvent* event )
613 {
614   /// Return the selected trigger classes in the current event
615   UpdateEvent(event);
616   return fSelectedTrigClassesInEvent;
617 }
618
619
620 //________________________________________________________________________
621 void AliMuonEventCuts::BuildTriggerClasses ( const TString firedTrigClasses,
622                                              UInt_t l0Inputs, UInt_t l1Inputs, UInt_t l2Inputs )
623 {
624   //
625   /// Return the list of trigger classes to be considered
626   /// for current event. Update the global list if necessary
627   //
628   
629   AliDebug(2,Form("Fired classes: %s  Inputs 0x%x 0x%x 0x%x",firedTrigClasses.Data(),l0Inputs,l1Inputs,l2Inputs));
630   
631   if ( fSelectedTrigClassesInEvent) fSelectedTrigClassesInEvent->Delete();
632   else {
633     fSelectedTrigClassesInEvent = new TObjArray(0);
634     fSelectedTrigClassesInEvent->SetOwner();
635   }
636   
637
638   TString firedTrigClassesAny = "ANY " + firedTrigClasses;
639   
640   if ( fSelectedTrigPattern->GetEntries() > 0 ) {
641     TObjArray* firedTrigClassesList = firedTrigClassesAny.Tokenize(" ");
642   
643     for ( Int_t itrig=0; itrig<firedTrigClassesList->GetEntries(); ++itrig ) {
644       TString trigName = ((TObjString*)firedTrigClassesList->At(itrig))->GetString();
645
646       TObjString* foundTrig = static_cast<TObjString*>(fAllSelectedTrigClasses->FindObject(trigName.Data()));
647       if ( ! foundTrig ) {
648         if ( ! CheckTriggerClassPattern(trigName) ) continue;
649       }
650       
651       AddToEventSelectedClass ( trigName, foundTrig );
652     } // loop on trigger classes
653   
654     delete firedTrigClassesList;
655   }
656   
657   for ( Int_t icomb=0; icomb<fSelectedTrigCombination->GetEntries(); icomb++ ) {
658     TObjArray* currComb = static_cast<TObjArray*>(fSelectedTrigCombination->At(icomb));
659     if ( CheckTriggerClassCombination(currComb, firedTrigClassesAny, l0Inputs, l1Inputs, l2Inputs) ) {
660       TObjString* foundTrig = static_cast<TObjString*>(fAllSelectedTrigClasses->FindObject(currComb->GetName()));
661       AddToEventSelectedClass ( currComb->GetName(), foundTrig, currComb->GetUniqueID() );
662     }
663   }
664 }
665
666 //_____________________________________________________________________________
667 Bool_t
668 AliMuonEventCuts::CheckTriggerClassPattern ( const TString& toCheck ) const
669 {
670   // Check if the "toCheck" class matches the user pattern
671   
672   for ( Int_t ipat=0; ipat<fRejectedTrigPattern->GetEntries(); ++ipat ) {
673     if ( toCheck.Contains(TRegexp(fRejectedTrigPattern->At(ipat)->GetName(),kTRUE) ) ) return kFALSE;
674   } // loop on reject pattern
675
676   for ( Int_t ipat=0; ipat<fSelectedTrigPattern->GetEntries(); ++ipat ) {
677     if ( toCheck.Contains(TRegexp(fSelectedTrigPattern->At(ipat)->GetName(),kTRUE) ) ) return kTRUE;
678   } // loop on keep pattern
679   
680   return kFALSE;
681 }
682
683
684 //_____________________________________________________________________________
685 Bool_t
686 AliMuonEventCuts::CheckTriggerClassCombination ( const TObjArray* combo,
687                                                  const TString& firedTriggerClasses,
688                                                  UInt_t l0Inputs, UInt_t l1Inputs, UInt_t l2Inputs ) const
689 {
690   // Check if the "toCheck" class (or logical combination of classes and L0 inputs)
691   // are within the "firedTriggerClasses"
692   
693   Bool_t ok(kFALSE);
694   
695   TString comp(combo->GetName());
696   UInt_t trigInputs[3] = {l0Inputs, l1Inputs, l2Inputs};
697   
698   Bool_t exitLoop = kFALSE;
699   
700   TIter nextObj(combo);
701   TObjArray* currList = 0x0;
702   while ( ( currList = static_cast<TObjArray*>(nextObj()) ) ) {
703     Int_t listIdx = currList->GetUniqueID();
704     TIter nextA(currList);
705     TObjString* an = 0x0;
706     while ( ( an = static_cast<TObjString*>(nextA()) ) )
707     {
708       if ( listIdx < 3 ) {
709         UInt_t bit = an->GetUniqueID();
710         ok = ( (trigInputs[listIdx] & bit) == bit );
711       }
712       else {
713         TPRegexp re(Form("(^|[ ])%s([ ]|$)",an->String().Data()));
714         ok = firedTriggerClasses.Contains(re);
715       }
716       if ( combo->GetUniqueID() == kComboFormula ) comp.ReplaceAll(an->String().Data(),Form("%d",ok));
717       else if ( ( combo->GetUniqueID() == kComboAND && ! ok ) || ( combo->GetUniqueID() == kComboOR && ok ) ) {
718         exitLoop = kTRUE;
719         break;
720       }
721     }
722     if ( exitLoop ) break;
723   }
724   
725   if ( combo->GetUniqueID() == kComboFormula ) {
726     TFormula formula("TriggerClassFormulaCheck", comp.Data());
727     if ( formula.Compile() > 0 ) {
728       AliError(Form("Could not evaluate formula %s",comp.Data()));
729       ok = kFALSE;
730     }
731     else ok = formula.Eval(0);
732   }
733   
734   AliDebug(2,Form("tname %s => %d comp=%s  inputs 0x%x 0x%x 0x%x",combo->GetName(),ok,comp.Data(),l0Inputs, l1Inputs, l2Inputs));
735   
736   return ok;
737 }
738
739 //_____________________________________________________________________________
740 void
741 AliMuonEventCuts::AddToEventSelectedClass ( const TString& toCheck, const TObjString* foundTrig, const UInt_t comboType )
742 {
743   /// Add current trigger to the selected class for the event
744   
745   // Compute the trigger pt cut level of the current class
746   UInt_t trigLevel = 0;
747   if ( foundTrig ) trigLevel = foundTrig->GetUniqueID();
748   else {
749     // The assigned trigger pt cut level is:
750     // - the correct one if "toCheck" is a single trigger class
751     // - the highest pt cut among the matching ones in case "toCheck" is a trigger class/input
752     //   combined through (at least one) logical AND "&"
753     // - the lowest pt cut among the macthing ones in case "toCheck" is a trigger class/input
754     //   combined through (only) logical OR "|"
755     // This may lead to errors in case of complex combinations of trigger/inputs
756     Bool_t isFirst = kTRUE;
757     for ( Int_t ipat=0; ipat<fSelectedTrigLevel->GetEntries(); ++ipat ) {
758       if ( toCheck.Contains(fSelectedTrigLevel->At(ipat)->GetName() ) ) {
759         UInt_t currLevel = fSelectedTrigLevel->At(ipat)->GetUniqueID();
760         if ( comboType == kComboAND ) trigLevel = TMath::Max(trigLevel, currLevel);
761         else if ( comboType == kComboOR || comboType == kComboFormula ) {
762           if ( isFirst ) {
763             trigLevel = currLevel;
764             isFirst = kFALSE;
765           }
766           else trigLevel = TMath::Min(trigLevel, currLevel);
767         }
768         else {
769           trigLevel = currLevel;
770           break;
771         }
772       }
773     } // loop on trig level patterns
774   }
775   
776   TObjString* currTrig = new TObjString(toCheck);
777   currTrig->SetUniqueID(trigLevel);
778   fSelectedTrigClassesInEvent->AddLast(currTrig);
779   
780   if ( foundTrig ) return;
781   TObjString* addTrig = new TObjString(toCheck);
782   addTrig->SetUniqueID(trigLevel);
783   fAllSelectedTrigClasses->Add(addTrig);
784   TString trigLevelInfo = Form("trig level %i ", trigLevel & 0x3);
785   trigLevelInfo += ( trigLevel > 3 ) ? "di-muon" : "single-muon";
786   AliInfo(Form("Adding %s (%s) to considered trigger classes",toCheck.Data(),trigLevelInfo.Data()));
787 }
788
789 //________________________________________________________________________
790 void AliMuonEventCuts::SetCentralityClasses(Int_t nCentralityBins, Double_t* centralityBins)
791 {
792   //
793   /// Set centrality classes
794   //
795   Double_t* bins = centralityBins;
796   Int_t nbins = nCentralityBins;
797   
798   Double_t defaultCentralityBins[] = {-5., 0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., 105.};
799   if ( ! centralityBins ) {
800     bins = defaultCentralityBins;
801     nbins = sizeof(defaultCentralityBins)/sizeof(defaultCentralityBins[0])-1;
802   }
803   
804   TString centralityEstimator = "V0M";
805   if ( fCentralityClasses ) {
806     centralityEstimator = GetCentralityEstimator();
807     delete fCentralityClasses;
808   }
809   fCentralityClasses = new TAxis(nbins, bins);
810   TString currClass = "";
811   for ( Int_t ibin=1; ibin<=fCentralityClasses->GetNbins(); ++ibin ){
812     currClass = Form("%.0f_%.0f",fCentralityClasses->GetBinLowEdge(ibin),fCentralityClasses->GetBinUpEdge(ibin));
813     fCentralityClasses->SetBinLabel(ibin, currClass.Data());
814   }
815   
816   SetCentralityEstimator(centralityEstimator);
817 }
818
819 //________________________________________________________________________
820 void AliMuonEventCuts::SetCentralityEstimator ( const TString centralityEstimator )
821 {
822   /// Set centrality estimator
823   fCentralityClasses->SetName(centralityEstimator.Data());
824 }
825
826
827 //________________________________________________________________________
828 TString AliMuonEventCuts::GetCentralityEstimator () const
829 {
830   /// Get centrality estimator
831   return fCentralityClasses->GetName();
832 }
833
834 //________________________________________________________________________
835 Double_t AliMuonEventCuts::GetCentrality ( const AliVEvent* event ) const
836 {
837   /// Get centrality
838   AliVEvent* evt = const_cast<AliVEvent*>(event);
839   return evt->GetCentrality()->GetCentralityPercentile(GetCentralityEstimator());
840 }
841
842 //________________________________________________________________________
843 void AliMuonEventCuts::SetDefaultParameters ()
844 {
845   /// Standard parameters for muon event
846   SetPhysicsSelectionMask(AliVEvent::kAny);
847   SetVertexMinNContributors(1);
848   SetVertexVzLimits();
849 }
850
851
852 //________________________________________________________________________
853 void AliMuonEventCuts::SetDefaultFilterMask ()
854 {
855   /// Standard cuts for muon event
856   SetFilterMask ( kPhysicsSelected | kSelectedTrig | kGoodVertex );
857 }
858
859 //________________________________________________________________________
860 void AliMuonEventCuts::Print(Option_t* option) const
861 {
862   //
863   /// Print info
864   //
865   TString sopt(option);
866   sopt.ToLower();
867   if ( sopt.IsNull() || sopt.Contains("*") || sopt.Contains("all") ) sopt = "mask param";
868   UInt_t filterMask = GetFilterMask();
869   if ( sopt.Contains("mask") ) {
870     printf(" *** Muon event filter mask: *** \n");
871     printf("  0x%x\n", filterMask);
872     if ( filterMask & kPhysicsSelected ) printf("  Pass physics selection 0x%x\n", fPhysicsSelectionMask);
873     if ( filterMask & kSelectedCentrality ) printf(  "%g < centrality (%s) < %g\n", fCentralityClasses->GetXmin(), GetCentralityEstimator().Data(), fCentralityClasses->GetXmax() );
874     if ( filterMask & kSelectedTrig ) printf("  Has selected trigger classes\n");
875     if ( filterMask & kGoodVertex ) printf("  SPD vertex with %i contributors && %g < Vz < %g\n", GetVertexMinNContributors(), GetVertexVzMin(), GetVertexVzMax());
876     if ( filterMask & kNoPileup ) printf("  Reject pileup with SPD\n");
877     printf(" ******************** \n");
878   }
879   if ( sopt.Contains("param") ) {
880     printf(" *** Muon event parameters: *** \n");
881     printf("  Centrality estimator: %s\n", GetCentralityEstimator().Data());
882     printf(" ******************** \n");
883   }
884 }