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