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