]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWG/muon/AliAnalysisMuMuCutElement.cxx
AliAODEvent::GetHeader now return AliVHeader
[u/mrichter/AliRoot.git] / PWG / muon / AliAnalysisMuMuCutElement.cxx
CommitLineData
5376e016
CP
1#include "AliAnalysisMuMuCutElement.h"
2
3/**
4 * \ingroup pwg-muon-mumu
5 *
6 * \class AliAnalysisMuMuCutElement
7 *
8 * An AliAnalysisMuMuCutElement is an interface/proxy to another method (see ctor)
9 *
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
14 *
15 * \author L. Aphecetche (Subatech)
16 */
17
18#include "TMethodCall.h"
19#include "AliLog.h"
20#include "Riostream.h"
21#include "AliVParticle.h"
22
23ClassImp(AliAnalysisMuMuCutElement)
24ClassImp(AliAnalysisMuMuCutElementBar)
25
26//_____________________________________________________________________________
27AliAnalysisMuMuCutElement::AliAnalysisMuMuCutElement()
28: TObject(), fName(""), fIsEventCutter(kFALSE), fIsEventHandlerCutter(kFALSE),
29fIsTrackCutter(kFALSE), fIsTrackPairCutter(kFALSE), fIsTriggerClassCutter(kFALSE),
30fCutObject(0x0), fCutMethodName(""), fCutMethodPrototype(""),
0804b4cc 31fDefaultParameters(""), fNofParams(0), fCutMethod(0x0), fCallParams(), fDoubleParams()
5376e016
CP
32{
33 /// Default ctor, leading to an invalid cut object
34}
35
36//_____________________________________________________________________________
37AliAnalysisMuMuCutElement::AliAnalysisMuMuCutElement(ECutType expectedType,
38 TObject& cutObject,
39 const char* cutMethodName,
40 const char* cutMethodPrototype,
41 const char* defaultParameters)
42: TObject(), fName(""), fIsEventCutter(kFALSE), fIsEventHandlerCutter(kFALSE),
43fIsTrackCutter(kFALSE), fIsTrackPairCutter(kFALSE), fIsTriggerClassCutter(kFALSE),
44fCutObject(&cutObject), fCutMethodName(cutMethodName),
45fCutMethodPrototype(cutMethodPrototype),fDefaultParameters(defaultParameters),
0804b4cc 46fNofParams(0), fCutMethod(0x0), fCallParams(), fDoubleParams()
5376e016
CP
47{
48 /**
49 * Construct a cut, which is a proxy to another method of (most probably) another object
50 *
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
57 *
58 * See the \ref Init method for details.
59 */
60
61 Init(expectedType);
62}
63
64//_____________________________________________________________________________
65AliAnalysisMuMuCutElement::~AliAnalysisMuMuCutElement()
66{
67 /// Dtor
68 delete fCutMethod;
69}
70
71//_____________________________________________________________________________
72Bool_t AliAnalysisMuMuCutElement::CallCutMethod(Long_t p) const
73{
74 /// Call the cut method with one parameter
75 if (!fCutMethod)
76 {
77 Init();
78 if (!fCutMethod) return kFALSE;
79 }
80
81 fCallParams[0] = p;
82
83 fCutMethod->SetParamPtrs(&fCallParams[0]);
84 Long_t result;
85 fCutMethod->Execute(fCutObject,result);
86
87 return (result!=0);
88}
89
90//_____________________________________________________________________________
91Bool_t AliAnalysisMuMuCutElement::CallCutMethod(Long_t p1, Long_t p2) const
92{
93 /// Call the cut method with two parameters
94
95 if (!fCutMethod)
96 {
97 Init();
98 if (!fCutMethod) return kFALSE;
99 }
100
101 fCallParams[0] = p1;
102 fCallParams[1] = p2;
103
104 fCutMethod->SetParamPtrs(&fCallParams[0]);
105 Long_t result;
106 fCutMethod->Execute(fCutObject,result);
107
108 return (result!=0);
109}
110
111//_____________________________________________________________________________
112Int_t AliAnalysisMuMuCutElement::CountOccurences(const TString& prototype, const char* search) const
113{
114 /// Count the number of times "search" is found in prototype
115
116 TObjArray* a = prototype.Tokenize(",");
117 TObjString* str;
118 TIter next(a);
119
120 Int_t n(0);
121
122 while ( ( str = static_cast<TObjString*>(next()) ) )
123 {
124 if ( str->String().Contains(search) )
125 {
126 ++n;
127 }
128 }
129 delete a;
130 return n;
131}
132
133//_____________________________________________________________________________
134const char* AliAnalysisMuMuCutElement::CutTypeName(ECutType type)
135{
136 /// Convert the enum into a string
137
138 if ( type == kEvent )
139 {
140 return "Event";
141 }
142 if ( type == kTrack )
143 {
144 return "Track";
145 }
146 if ( type == kTrackPair )
147 {
148 return "TrackPair";
149 }
150 if ( type == kTriggerClass )
151 {
152 return "TriggerClass";
153 }
154 return "Any";
155}
156
157//_____________________________________________________________________________
158const char* AliAnalysisMuMuCutElement::GetCallMethodName() const
159{
160 /// Return the cut method name
161 return ( fCutMethod ? fCutMethod->GetMethodName() : "");
162}
163
164//_____________________________________________________________________________
165const char* AliAnalysisMuMuCutElement::GetCallMethodProto() const
166{
167 /// Return the cut method prototype
168 return ( fCutMethod ? fCutMethod->GetProto() : "");
169}
170
171//_____________________________________________________________________________
172void AliAnalysisMuMuCutElement::Init(ECutType expectedType) const
173{
174 /** Build the non-persistent members (TMethodCalls)
175 *
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
183 * warned !
184 *
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)
187 *
188 * Bool_t XXXX(const AliVEvent&, ...)
189 * Bool_t XXXX(const AliVEventHandler&, ...)
190 * Bool_t XXXX(const AliInputEventHandler&, ...)
191 *
192 * For track cutters :
193 *
194 * Bool_t XXXX(const AliVParticle&, ...)
195 *
196 * For track pairs cutters :
197 *
198 * Bool_t XXXX(const AliVParticle&, const AliVParticle&, ...)
199 *
200 * For trigger class cutters :
201 *
202 * Bool_t XXXX(const TString& firedTriggerClasses, TString& acceptedTriggerClasses)
203 *
204 * where ... stands for optional arguments (different from VEvent VParticle, etc...),
205 * which can have default values
206 *
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.
209 *
210 *
211 */
212
213 TString scutMethodPrototype(fCutMethodPrototype);
214
215 // some basic checks first
216
217 TObjArray* tmp = fCutMethodPrototype.Tokenize(",");
218 fNofParams = tmp->GetEntries();
219 delete tmp;
220
221 Int_t nVEvent = CountOccurences(fCutMethodPrototype,"AliVEvent");
222 Int_t nVEventHandler = CountOccurences(fCutMethodPrototype,"AliVEventHandler");
223 Int_t nInputHandler = CountOccurences(fCutMethodPrototype,"AliInputEventHandler");
224 Int_t nparticles = CountOccurences(fCutMethodPrototype,"AliVParticle");
225 Int_t nstrings = CountOccurences(fCutMethodPrototype,"TString");
226
227 if ( expectedType == kEvent && ( nVEvent == 0 && nVEventHandler == 0 && nInputHandler == 0 ) )
228 {
229 AliError(Form("Cut not of the expected %s type : did not find required prototype arguments AliVEvent, AliVEventHandler or AliInputEventHandler",CutTypeName(kEvent)));
230 return;
231 }
232
233 if ( expectedType == kTrack && ( nparticles != 1 ) )
234 {
235 AliError(Form("Cut not of the expected %s type : did not find the required prototype argument AliVParticle (one and only one required)",CutTypeName(kTrack)));
236 return;
237 }
238
239 if ( expectedType == kTrackPair && ( nparticles != 2 ) )
240 {
241 AliError(Form("Cut not of the expected %s type : did not find the required prototype arguments AliVParticle (2 of them required)",CutTypeName(kTrackPair)));
242 return;
243 }
244
245 if ( expectedType == kTriggerClass && ( nstrings != 2 ) )
246 {
247 AliError(Form("Cut not of the expected %stype : did not find the required prototype arguments TString& (2 of them required)",CutTypeName(kTriggerClass)));
248 return;
249 }
250
251 // OK, at least the prototype seems to match what we require. Let's continue...
252
253 scutMethodPrototype.ReplaceAll(" ","");
254
255 fCutMethod = new TMethodCall;
256
257 fCutMethod->InitWithPrototype(fCutObject->IsA(),fCutMethodName.Data(),scutMethodPrototype.Data());
258
259 if (!fCutMethod->IsValid())
260 {
261 AliError(Form("Could not find method %s(%s) in class %s",fCutMethodName.Data(),
262 scutMethodPrototype.Data(),fCutObject->ClassName()));
263 delete fCutMethod;
264 fCutMethod=0x0;
265 return;
266 }
267
268 TMethodCall nameOfMethod;
269
270 TString prototype("TString&");
271
272 Int_t nMainPar = 0;
273
274 if ( scutMethodPrototype.Contains("AliVEvent") )
275 {
276 fIsEventCutter=kTRUE;
277 ++nMainPar;
278 }
279 if ( scutMethodPrototype.Contains("AliInputEventHandler") )
280 {
281 fIsEventHandlerCutter=kTRUE;
282 ++nMainPar;
283 }
284
285 if ( nMainPar > 1 )
286 {
287 AliError(Form("Got an invalid prototype %s (more than one main parameter)",scutMethodPrototype.Data()));
288 delete fCutMethod;
289 fCutMethod=0x0;
290 return;
291 }
292
293 if ( nparticles == 1 )
294 {
295 fIsTrackCutter=kTRUE;
296 }
297 else if ( nparticles == 2 )
298 {
299 fIsTrackPairCutter=kTRUE;
300 }
301 else if ( nstrings == 2 )
302 {
303 fIsTriggerClassCutter = kTRUE;
304 }
305
306 nMainPar += nparticles;
307 nMainPar += nstrings;
308
309 if ( nMainPar > 2 )
310 {
311 AliError(Form("Got an invalid prototype %s (more than two main parameters)",scutMethodPrototype.Data()));
312 delete fCutMethod;
313 fCutMethod=0x0;
314 return;
315 }
316
317 if ( nMainPar == 0 )
318 {
319 AliError(Form("Got an invalid prototype %s (no main parameter found)",scutMethodPrototype.Data()));
320 delete fCutMethod;
321 fCutMethod=0x0;
322 return;
323 }
324
325 if ( !fIsTriggerClassCutter )
326 {
327 scutMethodPrototype.ReplaceAll("const AliVEvent&","");
328 scutMethodPrototype.ReplaceAll("const AliVParticle&","");
329 scutMethodPrototype.ReplaceAll("const AliInputEventHandler&","");
330
331 prototype += scutMethodPrototype;
332
333 nameOfMethod.InitWithPrototype(fCutObject->IsA(),Form("NameOf%s",fCutMethodName.Data()),prototype);
334
335 if (!nameOfMethod.IsValid())
336 {
337 AliError(Form("Could not find method NameOf%s(%s) in class %s",fCutMethodName.Data(),
338 prototype.Data(),fCutObject->ClassName()));
339 delete fCutMethod;
340 fCutMethod=0x0;
341 return;
342 }
343
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).
348
349 prototype.ReplaceAll("TString&","");
350
351 TObjArray* paramTypes = prototype.Tokenize(",");
352 TObjArray* paramValues = fDefaultParameters.Tokenize(",");
353
354 fDoubleParams.resize(paramValues->GetEntries());
355
356 Int_t nparams = paramValues->GetEntries();
357
358 // first parameter is always the TString&, i.e. the "output" of the NameOf
359 // method
360
361 fCallParams.resize(nparams+nMainPar);
362
363 if ( nMainPar == 2 )
364 {
365 fCallParams[0] = 0;
366 fCallParams[1] = reinterpret_cast<Long_t>(&fName);
367 }
368 else
369 {
370 fCallParams[0] = reinterpret_cast<Long_t>(&fName);
371 }
372
373 for ( Int_t i = 0; i < nparams; ++i )
374 {
375 TString pValue = static_cast<TObjString*>(paramValues->At(i))->String();
376 TString pType = static_cast<TObjString*>(paramTypes->At(i))->String();
377
378 if ( pType.Contains("Double_t"))
379 {
380 fDoubleParams[i] = pValue.Atof();
381 fCallParams[i+nMainPar] = reinterpret_cast<Long_t>(&fDoubleParams[i]);
382 }
383 else if ( pType.Contains("Int_t") )
384 {
385 fCallParams[i+nMainPar] = pValue.Atoi();
386 }
387 else
388 {
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);
391 }
392 }
393
394 nameOfMethod.SetParamPtrs(&fCallParams[0+nMainPar-1]);
395
396 nameOfMethod.Execute(fCutObject);
397
398 delete paramTypes;
399 delete paramValues;
400 }
401 else
402 {
403 // check whether we have the input bit masks as well
404 Int_t nuint = CountOccurences(scutMethodPrototype,"UInt_t");
405
406 Bool_t ok =
407 ( nuint == 3 && nstrings == 2 && ( nuint + nstrings ) == fNofParams ) ||
408 ( nuint == 0 && nstrings == 2 && nstrings == fNofParams );
409
410 if (!ok)
411 {
412 AliError("Incorrect prototype for a trigger class cutter");
413 delete fCutMethod;
414 fCutMethod=0x0;
415 return;
416 }
417 }
418
419 // Final consistency ross-check
420
421 if ( expectedType == kEvent && ! (fIsEventCutter || fIsEventHandlerCutter) )
422 {
423 AliError("No, it's not an event cutter. Invalidate");
424 delete fCutMethod;
425 fCutMethod=0x0;
426 }
427
428 if ( expectedType == kTrack && !fIsTrackCutter )
429 {
430 AliError("No, it's not a track cutter. Invalidate");
431 delete fCutMethod;
432 fCutMethod=0x0;
433 }
434
435 if ( expectedType == kTrackPair && !fIsTrackPairCutter )
436 {
437 AliError("No, it's not a track pair cutter. Invalidate");
438 delete fCutMethod;
439 fCutMethod=0x0;
440 }
441
442 if ( expectedType == kTriggerClass && !fIsTriggerClassCutter )
443 {
444 AliError("No, it's not a trigger class cutter. Invalidate");
445 delete fCutMethod;
446 fCutMethod=0x0;
447 }
448}
449
450//_____________________________________________________________________________
451Bool_t AliAnalysisMuMuCutElement::IsEqual(const TObject* obj) const
452{
453 /// Whether we're the same cut as obj
454
455 if ( obj->IsA() != IsA() ) return kFALSE;
456
457 const AliAnalysisMuMuCutElement* cut = static_cast<const AliAnalysisMuMuCutElement*>(obj);
458
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 ? */
469 );
470}
471
472//_____________________________________________________________________________
473Bool_t AliAnalysisMuMuCutElement::Pass(const AliVEvent& event) const
474{
475 /// Whether the event pass this cut
476 return CallCutMethod(reinterpret_cast<Long_t>(&event));
477}
478
479//_____________________________________________________________________________
480Bool_t AliAnalysisMuMuCutElement::Pass(const AliInputEventHandler& eventHandler) const
481{
482 /// Whether the eventHandler pass this cut
483 return CallCutMethod(reinterpret_cast<Long_t>(&eventHandler));
484}
485
486//_____________________________________________________________________________
487Bool_t AliAnalysisMuMuCutElement::Pass(const AliVParticle& part) const
488{
489 /// Whether the particle pass this cut
490 return CallCutMethod(reinterpret_cast<Long_t>(&part));
491}
492
493//_____________________________________________________________________________
494Bool_t AliAnalysisMuMuCutElement::Pass(const AliVParticle& p1, const AliVParticle& p2) const
495{
496 /// Whether the particle pair pass this cut
497 return CallCutMethod(reinterpret_cast<Long_t>(&p1),reinterpret_cast<Long_t>(&p2));
498}
499
500//_____________________________________________________________________________
501Bool_t AliAnalysisMuMuCutElement::Pass(const TString& firedTriggerClasses,
502 TString& acceptedTriggerClasses,
503 UInt_t L0, UInt_t L1, UInt_t L2) const
504{
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
511 */
512
513 if (!fCutMethod)
514 {
515 Init();
516 if (!fCutMethod) return kFALSE;
517 }
518
519 acceptedTriggerClasses = "";
520
521 Long_t result;
522 Long_t params[] = { reinterpret_cast<Long_t>(&firedTriggerClasses),
523 reinterpret_cast<Long_t>(&acceptedTriggerClasses),
524 L0,L1,L2 };
525
526 fCutMethod->SetParamPtrs(params);
527 fCutMethod->Execute(fCutObject,result);
528 return (result!=0);
529}
530
531//_____________________________________________________________________________
532void AliAnalysisMuMuCutElement::Print(Option_t* /*opt*/) const
533{
534 /// Printout of the cut information
535 if ( !fCutMethod )
536 {
537 Init();
538 }
539
540 std::cout << Form("Cut %s(%p) %s(%p)::%s(%s) [",
541 fName.Data(),this,
542 fCutObject->ClassName(),
543 fCutObject,
544 GetCallMethodName(),
545 GetCallMethodProto());
546
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";
552
553 std::cout << " ]" << std::endl;
554}
555
556//_____________________________________________________________________________
557//_____________________________________________________________________________
558//_____________________________________________________________________________
559
560/**
561 * \ingroup pwg-muon-mumu
562 *
563 * \class AliAnalysisMuMuCutElementBar
564 *
565 * \brief The negation of an AliAnalysisMuMuCutElement
566 *
567 * \author L. Aphecetche (Subatech)
568 */
569
570//_____________________________________________________________________________
571AliAnalysisMuMuCutElementBar::AliAnalysisMuMuCutElementBar() : AliAnalysisMuMuCutElement(),
572fCutElement(0x0)
573{
574 /// default ctor
575}
576
577//_____________________________________________________________________________
578AliAnalysisMuMuCutElementBar::AliAnalysisMuMuCutElementBar(const AliAnalysisMuMuCutElement& ce)
579: AliAnalysisMuMuCutElement(), fCutElement(&ce)
580{
581 /// ctor
582 fIsEventCutter = ce.IsEventCutter();
583 fIsEventHandlerCutter = ce.IsEventHandlerCutter();
584 fIsTrackCutter = ce.IsTrackCutter();
585 fIsTrackPairCutter = ce.IsTrackPairCutter();
586 fName = TString::Format("NOT%s",ce.GetName());
587}
588
589//_____________________________________________________________________________
590AliAnalysisMuMuCutElementBar::~AliAnalysisMuMuCutElementBar()
591{
592 /// dtor (nop as we're not the owner of fCutElement)
593}
594
595//_____________________________________________________________________________
596void AliAnalysisMuMuCutElementBar::Print(Option_t* /*opt*/) const
597{
598 /// Printout of the cut information
599 std::cout << Form("Cut %s(%p) : negation of %s(%p)",GetName(),this,fCutElement->GetName(),fCutElement)
600 << std::endl;
601}
602