]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWG/muon/AliAnalysisMuMuCutElement.cxx
Fix Coverity 24835
[u/mrichter/AliRoot.git] / PWG / muon / AliAnalysisMuMuCutElement.cxx
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
23 ClassImp(AliAnalysisMuMuCutElement)
24 ClassImp(AliAnalysisMuMuCutElementBar)
25
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()
32 {
33   /// Default ctor, leading to an invalid cut object
34 }
35
36 //_____________________________________________________________________________
37 AliAnalysisMuMuCutElement::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),
43 fIsTrackCutter(kFALSE), fIsTrackPairCutter(kFALSE), fIsTriggerClassCutter(kFALSE),
44 fCutObject(&cutObject), fCutMethodName(cutMethodName),
45 fCutMethodPrototype(cutMethodPrototype),fDefaultParameters(defaultParameters),
46 fNofParams(0), fCutMethod(0x0), fCallParams(), fDoubleParams()
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 //_____________________________________________________________________________
65 AliAnalysisMuMuCutElement::~AliAnalysisMuMuCutElement()
66 {
67   /// Dtor
68   delete fCutMethod;
69 }
70
71 //_____________________________________________________________________________
72 Bool_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 //_____________________________________________________________________________
91 Bool_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 //_____________________________________________________________________________
112 Int_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 //_____________________________________________________________________________
134 const 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 //_____________________________________________________________________________
158 const char* AliAnalysisMuMuCutElement::GetCallMethodName() const
159 {
160   /// Return the cut method name
161   return ( fCutMethod ? fCutMethod->GetMethodName() : "");
162 }
163
164 //_____________________________________________________________________________
165 const char* AliAnalysisMuMuCutElement::GetCallMethodProto() const
166 {
167   /// Return the cut method prototype
168   return ( fCutMethod ? fCutMethod->GetProto() : "");
169 }
170
171 //_____________________________________________________________________________
172 void 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") + CountOccurences(fCutMethodPrototype,"AliInputEventHandler");
223   Int_t nparticles = CountOccurences(fCutMethodPrototype,"AliVParticle");
224   Int_t nstrings = CountOccurences(fCutMethodPrototype,"TString");
225   
226   if ( expectedType == kEvent && ( nVEvent == 0 && nVEventHandler == 0 ) )
227   {
228     AliError(Form("Cut not of the expected %s type : did not find required prototype arguments AliVEvent, AliVEventHandler or AliInputEventHandler",CutTypeName(kEvent)));
229     return;
230   }
231   
232   if ( expectedType == kTrack && ( nparticles != 1 ) )
233   {
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)));
235     return;
236   }
237
238   if ( expectedType == kTrackPair && ( nparticles != 2 ) )
239   {
240     AliError(Form("Cut not of the expected %s type : did not find the required prototype arguments AliVParticle (2 of them required)",CutTypeName(kTrackPair)));
241     return;
242   }
243
244   if ( expectedType == kTriggerClass && ( nstrings != 2 ) )
245   {
246     AliError(Form("Cut not of the expected %stype : did not find the required prototype arguments TString& (2 of them required)",CutTypeName(kTriggerClass)));
247     return;
248   }
249   
250   // OK, at least the prototype seems to match what we require. Let's continue...
251   
252   scutMethodPrototype.ReplaceAll("  ","");
253   
254   fCutMethod = new TMethodCall;
255   
256   fCutMethod->InitWithPrototype(fCutObject->IsA(),fCutMethodName.Data(),scutMethodPrototype.Data());
257   
258   if (!fCutMethod->IsValid())
259   {
260     AliError(Form("Could not find method %s(%s) in class %s",fCutMethodName.Data(),
261                   scutMethodPrototype.Data(),fCutObject->ClassName()));
262     delete fCutMethod;
263     fCutMethod=0x0;
264     return;
265   }
266   
267   TMethodCall nameOfMethod;
268   
269   TString prototype("TString&");
270   
271   Int_t nMainPar = 0;
272   
273   if ( scutMethodPrototype.Contains("AliVEvent") )
274   {
275     fIsEventCutter=kTRUE;
276     ++nMainPar;
277   }
278   if ( scutMethodPrototype.Contains("AliInputEventHandler") || scutMethodPrototype.Contains("AliVEventHandler") )
279   {
280     fIsEventHandlerCutter=kTRUE;
281     ++nMainPar;
282   }
283
284   if ( nMainPar > 1 )
285   {
286     AliError(Form("Got an invalid prototype %s (more than one main parameter)",scutMethodPrototype.Data()));
287     delete fCutMethod;
288     fCutMethod=0x0;
289     return;
290   }
291   
292   if ( nparticles == 1 )
293   {
294     fIsTrackCutter=kTRUE;
295   }
296   else if ( nparticles == 2 )
297   {
298     fIsTrackPairCutter=kTRUE;
299   }
300   else if ( nstrings == 2 )
301   {
302     fIsTriggerClassCutter = kTRUE;
303   }
304   
305   nMainPar += nparticles;
306   nMainPar += nstrings;
307   
308   if ( nMainPar > 2 )
309   {
310     AliError(Form("Got an invalid prototype %s (more than two main parameters)",scutMethodPrototype.Data()));
311     delete fCutMethod;
312     fCutMethod=0x0;
313     return;
314   }
315   
316   if ( nMainPar == 0 )
317   {
318     AliError(Form("Got an invalid prototype %s (no main parameter found)",scutMethodPrototype.Data()));
319     delete fCutMethod;
320     fCutMethod=0x0;
321     return;
322   }
323   
324   if ( !fIsTriggerClassCutter )
325   {
326     scutMethodPrototype.ReplaceAll("const AliVEvent&","");
327     scutMethodPrototype.ReplaceAll("const AliVParticle&","");
328     scutMethodPrototype.ReplaceAll("const AliInputEventHandler&","");
329     scutMethodPrototype.ReplaceAll("const AliVEventHandler&","");
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 //_____________________________________________________________________________
451 Bool_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 //_____________________________________________________________________________
473 Bool_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 //_____________________________________________________________________________
480 Bool_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 //_____________________________________________________________________________
487 Bool_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 //_____________________________________________________________________________
494 Bool_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 //_____________________________________________________________________________
501 Bool_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 //_____________________________________________________________________________
532 void 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 //_____________________________________________________________________________
571 AliAnalysisMuMuCutElementBar::AliAnalysisMuMuCutElementBar() : AliAnalysisMuMuCutElement(),
572 fCutElement(0x0)
573 {
574   /// default ctor
575 }
576
577 //_____________________________________________________________________________
578 AliAnalysisMuMuCutElementBar::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 //_____________________________________________________________________________
590 AliAnalysisMuMuCutElementBar::~AliAnalysisMuMuCutElementBar()
591 {
592   /// dtor (nop as we're not the owner of fCutElement)
593 }
594
595 //_____________________________________________________________________________
596 void 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