1 #include "AliAnalysisMuMuCutElement.h"
4 * \ingroup pwg-muon-mumu
6 * \class AliAnalysisMuMuCutElement
8 * An AliAnalysisMuMuCutElement is an interface/proxy to another method (see ctor)
10 * A cut has a type (event cut, track cut, etc..., see ECutType and the IsXXX methods),
11 * a name, and offers a Pass method. A cut can be of one type only.
12 * Generally a real cut is made of several cut elements,
13 * see \ref AliAnalysisMuMuCutCombination
15 * \author L. Aphecetche (Subatech)
18 #include "TMethodCall.h"
20 #include "Riostream.h"
21 #include "AliVParticle.h"
23 ClassImp(AliAnalysisMuMuCutElement)
24 ClassImp(AliAnalysisMuMuCutElementBar)
26 //_____________________________________________________________________________
27 AliAnalysisMuMuCutElement::AliAnalysisMuMuCutElement()
28 : TObject(), fName(""), fIsEventCutter(kFALSE), fIsEventHandlerCutter(kFALSE),
29 fIsTrackCutter(kFALSE), fIsTrackPairCutter(kFALSE), fIsTriggerClassCutter(kFALSE),
30 fCutObject(0x0), fCutMethodName(""), fCutMethodPrototype(""),
31 fDefaultParameters(""), fNofParams(0), fCutMethod(0x0), fCallParams(), fDoubleParams()
33 /// Default ctor, leading to an invalid cut object
36 //_____________________________________________________________________________
37 AliAnalysisMuMuCutElement::AliAnalysisMuMuCutElement(ECutType expectedType,
39 const char* cutMethodName,
40 const char* cutMethodPrototype,
41 const char* defaultParameters)
42 : TObject(), fName(""), fIsEventCutter(kFALSE), fIsEventHandlerCutter(kFALSE),
43 fIsTrackCutter(kFALSE), fIsTrackPairCutter(kFALSE), fIsTriggerClassCutter(kFALSE),
44 fCutObject(&cutObject), fCutMethodName(cutMethodName),
45 fCutMethodPrototype(cutMethodPrototype),fDefaultParameters(defaultParameters),
46 fNofParams(0), fCutMethod(0x0), fCallParams(), fDoubleParams()
49 * Construct a cut, which is a proxy to another method of (most probably) another object
51 * \param expectedType the type of cut which is expected (this cut will be invalidated if
52 * the actual method does not comply with this type)
53 * \param cutObject the object which has the cut method
54 * \param cutMethodName the name of the method of cutObject that should do the cut work
55 * \param cutMethodPrototype the prototype (i.e. list of arguments) of cutMethod
56 * \param defaultParameters values of the default parameters (if any) of the cutMethod
58 * See the \ref Init method for details.
64 //_____________________________________________________________________________
65 AliAnalysisMuMuCutElement::~AliAnalysisMuMuCutElement()
71 //_____________________________________________________________________________
72 Bool_t AliAnalysisMuMuCutElement::CallCutMethod(Long_t p) const
74 /// Call the cut method with one parameter
78 if (!fCutMethod) return kFALSE;
83 fCutMethod->SetParamPtrs(&fCallParams[0]);
85 fCutMethod->Execute(fCutObject,result);
90 //_____________________________________________________________________________
91 Bool_t AliAnalysisMuMuCutElement::CallCutMethod(Long_t p1, Long_t p2) const
93 /// Call the cut method with two parameters
98 if (!fCutMethod) return kFALSE;
104 fCutMethod->SetParamPtrs(&fCallParams[0]);
106 fCutMethod->Execute(fCutObject,result);
111 //_____________________________________________________________________________
112 Int_t AliAnalysisMuMuCutElement::CountOccurences(const TString& prototype, const char* search) const
114 /// Count the number of times "search" is found in prototype
116 TObjArray* a = prototype.Tokenize(",");
122 while ( ( str = static_cast<TObjString*>(next()) ) )
124 if ( str->String().Contains(search) )
133 //_____________________________________________________________________________
134 const char* AliAnalysisMuMuCutElement::CutTypeName(ECutType type)
136 /// Convert the enum into a string
138 if ( type == kEvent )
142 if ( type == kTrack )
146 if ( type == kTrackPair )
150 if ( type == kTriggerClass )
152 return "TriggerClass";
157 //_____________________________________________________________________________
158 const char* AliAnalysisMuMuCutElement::GetCallMethodName() const
160 /// Return the cut method name
161 return ( fCutMethod ? fCutMethod->GetMethodName() : "");
164 //_____________________________________________________________________________
165 const char* AliAnalysisMuMuCutElement::GetCallMethodProto() const
167 /// Return the cut method prototype
168 return ( fCutMethod ? fCutMethod->GetProto() : "");
171 //_____________________________________________________________________________
172 void AliAnalysisMuMuCutElement::Init(ECutType expectedType) const
174 /** Build the non-persistent members (TMethodCalls)
176 * Each cut method XXXX must have
177 * a companion method, called NameOfXXXX(TString& nameOfCut) which fills the nameOfCut
178 * string with the name of cut (using the default parameter values if need be to distinguish
179 * different cuts using the same method).
180 * The cut method we're proxy-ing can not be of any kind. We basically only recognize the
181 * following prototypes (more or less based on the Pass() method prototypes). The checks
182 * performed below to ensure that are far from being bullet-proof though... You've been
185 * For event cutters (3 or them instead of just one because of the, imo,
186 * improper event/eventhandler interfaces we currently have in AliRoot)
188 * Bool_t XXXX(const AliVEvent&, ...)
189 * Bool_t XXXX(const AliVEventHandler&, ...)
190 * Bool_t XXXX(const AliInputEventHandler&, ...)
192 * For track cutters :
194 * Bool_t XXXX(const AliVParticle&, ...)
196 * For track pairs cutters :
198 * Bool_t XXXX(const AliVParticle&, const AliVParticle&, ...)
200 * For trigger class cutters :
202 * Bool_t XXXX(const TString& firedTriggerClasses, TString& acceptedTriggerClasses)
204 * where ... stands for optional arguments (different from VEvent VParticle, etc...),
205 * which can have default values
207 * Note that Root reflexion does not allow (yet?) to check for constness of the arguments,
208 * so AliVEvent& and const AliVEvent& will be the same.
213 TString scutMethodPrototype(fCutMethodPrototype);
215 // some basic checks first
217 TObjArray* tmp = fCutMethodPrototype.Tokenize(",");
218 fNofParams = tmp->GetEntries();
221 Int_t nVEvent = CountOccurences(fCutMethodPrototype,"AliVEvent");
222 Int_t nVEventHandler = CountOccurences(fCutMethodPrototype,"AliVEventHandler") + CountOccurences(fCutMethodPrototype,"AliInputEventHandler");
223 Int_t nparticles = CountOccurences(fCutMethodPrototype,"AliVParticle");
224 Int_t nstrings = CountOccurences(fCutMethodPrototype,"TString");
226 if ( expectedType == kEvent && ( nVEvent == 0 && nVEventHandler == 0 ) )
228 AliError(Form("Cut not of the expected %s type : did not find required prototype arguments AliVEvent, AliVEventHandler or AliInputEventHandler",CutTypeName(kEvent)));
232 if ( expectedType == kTrack && ( nparticles != 1 ) )
234 AliError(Form("Cut not of the expected %s type : did not find the required prototype argument AliVParticle (one and only one required)",CutTypeName(kTrack)));
238 if ( expectedType == kTrackPair && ( nparticles != 2 ) )
240 AliError(Form("Cut not of the expected %s type : did not find the required prototype arguments AliVParticle (2 of them required)",CutTypeName(kTrackPair)));
244 if ( expectedType == kTriggerClass && ( nstrings != 2 ) )
246 AliError(Form("Cut not of the expected %stype : did not find the required prototype arguments TString& (2 of them required)",CutTypeName(kTriggerClass)));
250 // OK, at least the prototype seems to match what we require. Let's continue...
252 scutMethodPrototype.ReplaceAll(" ","");
254 fCutMethod = new TMethodCall;
256 fCutMethod->InitWithPrototype(fCutObject->IsA(),fCutMethodName.Data(),scutMethodPrototype.Data());
258 if (!fCutMethod->IsValid())
260 AliError(Form("Could not find method %s(%s) in class %s",fCutMethodName.Data(),
261 scutMethodPrototype.Data(),fCutObject->ClassName()));
267 TMethodCall nameOfMethod;
269 TString prototype("TString&");
273 if ( scutMethodPrototype.Contains("AliVEvent") )
275 fIsEventCutter=kTRUE;
278 if ( scutMethodPrototype.Contains("AliInputEventHandler") || scutMethodPrototype.Contains("AliVEventHandler") )
280 fIsEventHandlerCutter=kTRUE;
286 AliError(Form("Got an invalid prototype %s (more than one main parameter)",scutMethodPrototype.Data()));
292 if ( nparticles == 1 )
294 fIsTrackCutter=kTRUE;
296 else if ( nparticles == 2 )
298 fIsTrackPairCutter=kTRUE;
300 else if ( nstrings == 2 )
302 fIsTriggerClassCutter = kTRUE;
305 nMainPar += nparticles;
306 nMainPar += nstrings;
310 AliError(Form("Got an invalid prototype %s (more than two main parameters)",scutMethodPrototype.Data()));
318 AliError(Form("Got an invalid prototype %s (no main parameter found)",scutMethodPrototype.Data()));
324 if ( !fIsTriggerClassCutter )
326 scutMethodPrototype.ReplaceAll("const AliVEvent&","");
327 scutMethodPrototype.ReplaceAll("const AliVParticle&","");
328 scutMethodPrototype.ReplaceAll("const AliInputEventHandler&","");
329 scutMethodPrototype.ReplaceAll("const AliVEventHandler&","");
331 prototype += scutMethodPrototype;
333 nameOfMethod.InitWithPrototype(fCutObject->IsA(),Form("NameOf%s",fCutMethodName.Data()),prototype);
335 if (!nameOfMethod.IsValid())
337 AliError(Form("Could not find method NameOf%s(%s) in class %s",fCutMethodName.Data(),
338 prototype.Data(),fCutObject->ClassName()));
344 // Now check if we have some default parameters for the NameOf method
345 // Note that the only supported types for those default parameters
346 // are Int_t and Double_t (which must be then of the form const Double_t&,
347 // note the reference).
349 prototype.ReplaceAll("TString&","");
351 TObjArray* paramTypes = prototype.Tokenize(",");
352 TObjArray* paramValues = fDefaultParameters.Tokenize(",");
354 fDoubleParams.resize(paramValues->GetEntries());
356 Int_t nparams = paramValues->GetEntries();
358 // first parameter is always the TString&, i.e. the "output" of the NameOf
361 fCallParams.resize(nparams+nMainPar);
366 fCallParams[1] = reinterpret_cast<Long_t>(&fName);
370 fCallParams[0] = reinterpret_cast<Long_t>(&fName);
373 for ( Int_t i = 0; i < nparams; ++i )
375 TString pValue = static_cast<TObjString*>(paramValues->At(i))->String();
376 TString pType = static_cast<TObjString*>(paramTypes->At(i))->String();
378 if ( pType.Contains("Double_t"))
380 fDoubleParams[i] = pValue.Atof();
381 fCallParams[i+nMainPar] = reinterpret_cast<Long_t>(&fDoubleParams[i]);
383 else if ( pType.Contains("Int_t") )
385 fCallParams[i+nMainPar] = pValue.Atoi();
389 AliError(Form("Got a parameter of type %s which I don't exactly know how to deal with. Expect something bad to happen...",pType.Data()));
390 fCallParams[i+nMainPar] = reinterpret_cast<Long_t>(&pValue);
394 nameOfMethod.SetParamPtrs(&fCallParams[0+nMainPar-1]);
396 nameOfMethod.Execute(fCutObject);
403 // check whether we have the input bit masks as well
404 Int_t nuint = CountOccurences(scutMethodPrototype,"UInt_t");
407 ( nuint == 3 && nstrings == 2 && ( nuint + nstrings ) == fNofParams ) ||
408 ( nuint == 0 && nstrings == 2 && nstrings == fNofParams );
412 AliError("Incorrect prototype for a trigger class cutter");
419 // Final consistency ross-check
421 if ( expectedType == kEvent && ! (fIsEventCutter || fIsEventHandlerCutter) )
423 AliError("No, it's not an event cutter. Invalidate");
428 if ( expectedType == kTrack && !fIsTrackCutter )
430 AliError("No, it's not a track cutter. Invalidate");
435 if ( expectedType == kTrackPair && !fIsTrackPairCutter )
437 AliError("No, it's not a track pair cutter. Invalidate");
442 if ( expectedType == kTriggerClass && !fIsTriggerClassCutter )
444 AliError("No, it's not a trigger class cutter. Invalidate");
450 //_____________________________________________________________________________
451 Bool_t AliAnalysisMuMuCutElement::IsEqual(const TObject* obj) const
453 /// Whether we're the same cut as obj
455 if ( obj->IsA() != IsA() ) return kFALSE;
457 const AliAnalysisMuMuCutElement* cut = static_cast<const AliAnalysisMuMuCutElement*>(obj);
459 return ( fName == cut->fName &&
460 fIsEventCutter == cut->fIsEventCutter &&
461 fIsEventHandlerCutter == cut->fIsEventHandlerCutter &&
462 fIsTrackCutter == cut->fIsTrackCutter &&
463 fIsTrackPairCutter == cut->fIsTrackPairCutter &&
464 fIsTriggerClassCutter == cut->fIsTriggerClassCutter &&
465 fCutMethodName == cut->fCutMethodName &&
466 fCutMethodPrototype == cut->fCutMethodPrototype &&
467 fDefaultParameters == cut->fDefaultParameters &&
468 fCutObject == cut->fCutObject /* CHECK: should we really impose object equality or class equality would be enough ? */
472 //_____________________________________________________________________________
473 Bool_t AliAnalysisMuMuCutElement::Pass(const AliVEvent& event) const
475 /// Whether the event pass this cut
476 return CallCutMethod(reinterpret_cast<Long_t>(&event));
479 //_____________________________________________________________________________
480 Bool_t AliAnalysisMuMuCutElement::Pass(const AliInputEventHandler& eventHandler) const
482 /// Whether the eventHandler pass this cut
483 return CallCutMethod(reinterpret_cast<Long_t>(&eventHandler));
486 //_____________________________________________________________________________
487 Bool_t AliAnalysisMuMuCutElement::Pass(const AliVParticle& part) const
489 /// Whether the particle pass this cut
490 return CallCutMethod(reinterpret_cast<Long_t>(&part));
493 //_____________________________________________________________________________
494 Bool_t AliAnalysisMuMuCutElement::Pass(const AliVParticle& p1, const AliVParticle& p2) const
496 /// Whether the particle pair pass this cut
497 return CallCutMethod(reinterpret_cast<Long_t>(&p1),reinterpret_cast<Long_t>(&p2));
500 //_____________________________________________________________________________
501 Bool_t AliAnalysisMuMuCutElement::Pass(const TString& firedTriggerClasses,
502 TString& acceptedTriggerClasses,
503 UInt_t L0, UInt_t L1, UInt_t L2) const
505 /** Whether the firedTriggerClasses pass the cut.
506 * \param firedTriggerClasses (input) list of fired trigger classes (separated by space)
507 * \param acceptedTriggerClasses (output) list of accepted classes
508 * \param L0 (input, optional) level 0 trigger mask
509 * \param L1 (input, optional) level 1 trigger mask
510 * \param L2 (input, optional) level 2 trigger mask
516 if (!fCutMethod) return kFALSE;
519 acceptedTriggerClasses = "";
522 Long_t params[] = { reinterpret_cast<Long_t>(&firedTriggerClasses),
523 reinterpret_cast<Long_t>(&acceptedTriggerClasses),
526 fCutMethod->SetParamPtrs(params);
527 fCutMethod->Execute(fCutObject,result);
531 //_____________________________________________________________________________
532 void AliAnalysisMuMuCutElement::Print(Option_t* /*opt*/) const
534 /// Printout of the cut information
540 std::cout << Form("Cut %s(%p) %s(%p)::%s(%s) [",
542 fCutObject->ClassName(),
545 GetCallMethodProto());
547 if ( IsEventCutter() ) std::cout << " E";
548 if ( IsEventHandlerCutter() ) std::cout << " EH";
549 if ( IsTrackCutter() ) std::cout << " T";
550 if ( IsTrackPairCutter() ) std::cout << " TP";
551 if ( IsTriggerClassCutter() ) std::cout << " TC";
553 std::cout << " ]" << std::endl;
556 //_____________________________________________________________________________
557 //_____________________________________________________________________________
558 //_____________________________________________________________________________
561 * \ingroup pwg-muon-mumu
563 * \class AliAnalysisMuMuCutElementBar
565 * \brief The negation of an AliAnalysisMuMuCutElement
567 * \author L. Aphecetche (Subatech)
570 //_____________________________________________________________________________
571 AliAnalysisMuMuCutElementBar::AliAnalysisMuMuCutElementBar() : AliAnalysisMuMuCutElement(),
577 //_____________________________________________________________________________
578 AliAnalysisMuMuCutElementBar::AliAnalysisMuMuCutElementBar(const AliAnalysisMuMuCutElement& ce)
579 : AliAnalysisMuMuCutElement(), fCutElement(&ce)
582 fIsEventCutter = ce.IsEventCutter();
583 fIsEventHandlerCutter = ce.IsEventHandlerCutter();
584 fIsTrackCutter = ce.IsTrackCutter();
585 fIsTrackPairCutter = ce.IsTrackPairCutter();
586 fName = TString::Format("NOT%s",ce.GetName());
589 //_____________________________________________________________________________
590 AliAnalysisMuMuCutElementBar::~AliAnalysisMuMuCutElementBar()
592 /// dtor (nop as we're not the owner of fCutElement)
595 //_____________________________________________________________________________
596 void AliAnalysisMuMuCutElementBar::Print(Option_t* /*opt*/) const
598 /// Printout of the cut information
599 std::cout << Form("Cut %s(%p) : negation of %s(%p)",GetName(),this,fCutElement->GetName(),fCutElement)