KaliVeda  1.13/01
Heavy-Ion Analysis Toolkit
KVTemplateParticleCondition.h
Go to the documentation of this file.
1 /*
2 $Id: KVParticleCondition.h,v 1.3 2007/03/26 10:14:56 franklan Exp $
3 $Revision: 1.3 $
4 $Date: 2007/03/26 10:14:56 $
5 */
6 
9 
10 #ifndef __KVTEMPLATEPARTICLECONDITION_H
11 #define __KVTEMPLATEPARTICLECONDITION_H
12 
13 #include "KVBase.h"
14 #include "KVString.h"
15 #include "KVHashList.h"
16 #include <vector>
17 #include <functional>
18 #include <KVClassFactory.h>
19 #include "TROOT.h"
20 
21 class KVClassFactory;
22 
65 template<typename ParticleType>
67  static KVHashList fgOptimized;// list of optimized particle conditions
68  mutable Int_t fNUsing;
69  using LambdaFunc = std::function<bool(const ParticleType*)>;
71  LambdaFunc fSavedLambda1, fSavedLambda2;// used by || and &&
72  enum class LogOp { AND, OR } fOpType;
73 
75  {
77  if (IsLambda() && !IsSet()) {
78  switch (fOpType) {
79  case LogOp::AND:
80  fLambdaCondition = [this](const ParticleType * nuc) {
81  return (fSavedLambda1(nuc) && fSavedLambda2(nuc));
82  };
83  break;
84  case LogOp::OR:
85  fLambdaCondition = [this](const ParticleType * nuc) {
86  return (fSavedLambda1(nuc) || fSavedLambda2(nuc));
87  };
88  break;
89  }
90  }
91  }
92 
93 protected:
94 
95  KVString fCondition;//string containing selection criteria with ";" at end
96  KVString fCondition_raw;//'raw' condition, i.e. no ';'
97  KVString fCondition_brackets;//condition with '(' and ')' around it
98 
101  mutable KVClassFactory* cf;
103  mutable Bool_t fOptOK;
104 
105  void Optimize() const
106  {
119 
121  if (fOptimal) { /* check that the same condition has not already been optimized */
123  fOptimal->fNUsing++;
124  fOptOK = kTRUE;
125  return;
126  }
127  Info("Optimize", "Optimization of KVParticleCondition : %s", fCondition.Data());
128 
130  KVString created_class_name = cf->GetClassName();
132  cf->AddMethod("optimized_test", "Bool_t", "public", false, true);
133  cf->AddMethodArgument("optimized_test", "const KVNucleus*", "nuc");
134  cf->AddHeaderIncludeFile("KVNucleus.h");
135 
137  KVString body(" //Optimized Test method for particle condition\n");
138  KVString pointer = "nuc";
139  if (fClassName != "") {
140  pointer.Form("((%s*)nuc)", fClassName.Data());
143  }
144  KVString tmp;
145  tmp = fCondition;
146  tmp.ReplaceAll("_NUC_", pointer.Data());
147  body += " return ";
148  body += tmp;
149 
150  cf->AddMethodBody("optimized_test", body);
151 
153  cf->GenerateCode();
154 
156  gROOT->GetPluginManager()->AddHandler("KVParticleCondition", cf->GetClassName(), cf->GetClassName(),
157  Form("%s+", cf->GetImpFileName()), Form("%s()", cf->GetClassName()));
159  TPluginHandler* ph;
160  if (!(ph = LoadPlugin("KVParticleCondition", cf->GetClassName()))) {
161  Error("Optimize", " *** Optimization failed for KVParticleCondition : %s", fCondition.Data());
162  Error("Optimize", " *** Use method AddExtraInclude(const Char_t*) to give the names of all necessary header files for compilation of your condition.");
163  Fatal("Optimize", " *** THIS CONDITION WILL BE EVALUATED AS kFALSE FOR ALL PARTICLES!!!");
164  delete cf;
165  cf = 0;
168  fOptimal = this;
169  fOptOK = kFALSE;
170  return;
171  }
172  fOptOK = kTRUE;
173  delete cf;
174  cf = 0;
177 
178  Info("Optimize", "fOptimal = %p", fOptimal);
179  if (!fOptimal) {
180  Error("Optimize", " *** Optimization failed for KVParticleCondition : %s", fCondition.Data());
181  Error("Optimize", " *** Use method AddExtraInclude(const Char_t*) to give the names of all necessary header files for compilation of your condition.");
182  Fatal("Optimize", " *** THIS CONDITION WILL BE EVALUATED AS kFALSE FOR ALL PARTICLES!!!");
185  fOptimal = this;
186  fOptOK = kFALSE;
187  }
190  const_cast<KVTemplateParticleCondition*>(fOptimal)->fOptimizedClassName = created_class_name;
192  fOptimal->fNUsing++;
193  Info("Optimize", "Success");
194  }
195 
196  virtual bool optimized_test(const ParticleType*) const
197  {
198  return kFALSE;
199  }
200  void CreateClassFactory() const
201  {
203 
204  if (cf) return;
205 
207  TUUID unique;
208  KVString new_class = unique.AsString();
210  new_class.Remove(8);
211  new_class.Prepend("KVParticleCondition_");
212 
214  cf = new KVClassFactory(new_class.Data(), "Particle condition to test", "KVParticleCondition");
215  cf->SetInheritAllConstructors(kFALSE); // avoid generating ctor with LambdaFunc argument!!!
216  }
217 
219  {
223  CF->Copy(*cf);
224  }
225 
226 public:
228  : KVBase("KVParticleCondition", "Particle selection criteria")
229  {
231  fOptimal = nullptr;
232  cf = nullptr;
233  fOptOK = kFALSE;
234  fNUsing = 0;
235  }
236 
238  : KVBase(cond, "KVParticleCondition")
239  {
259  fOptimal = nullptr;
260  Set(cond);
261  cf = nullptr;
262  fOptOK = kFALSE;
263  fNUsing = 0;
264  }
265 
267  : KVBase(cond, "KVParticleCondition")
268  {
288  fOptimal = nullptr;
289  Set(cond);
290  cf = nullptr;
291  fOptOK = kFALSE;
292  fNUsing = 0;
293  }
294 
296  : KVBase("KVParticleCondition", "Particle selection criteria")
297  {
299  fOptimal = nullptr;
300  cf = nullptr;
301  fOptOK = kFALSE;
302  fNUsing = 0;
303  obj.Copy(*this);
304  }
305 
307  : KVBase(name, "KVParticleCondition"), fLambdaCondition(F)
308  {
332  fOptimal = nullptr;
333  cf = nullptr;
334  fOptOK = kFALSE;
335  fNUsing = 0;
336  }
337  bool IsLambda() const
338  {
340  return (bool)fLambdaCondition || ((bool)fSavedLambda1 && (bool)fSavedLambda2);
341  }
342 
344  {
346  if (fOptimal) {
348  --(fOptimal->fNUsing);
349  if (!(fOptimal->fNUsing)) {
351  delete fOptimal;
352  fOptimal = nullptr;
353  }
354  }
355  SafeDelete(cf);
356  }
357 
358  void Set(const KVString& name, const LambdaFunc& F)
359  {
371  SetName(name);
372  }
373 
374  void Set(const KVString& cond)
375  {
385 
387 
388  fCondition = cond;
389  Ssiz_t ind = fCondition.Index(";");
390  if (ind < 0) {
392  fCondition += ";"; //we add a ";" if there isn't already
393  }
394  else {
396  }
397  fCondition_brackets = "(" + fCondition_raw + ")";
398  }
399 
400  Bool_t Test(const ParticleType* nuc) const
401  {
409 
411  if (!IsSet()) return kTRUE;
412  if (IsLambda()) return fLambdaCondition(nuc);
413  if (!fOptimal) Optimize();
414 
415  return (fOptOK ? fOptimal->optimized_test(nuc) : kFALSE);
416  }
417 
418  Bool_t Test(const ParticleType& nuc) const
419  {
427 
428  return Test(&nuc);
429  }
430 
432  {
433  fClassName = cl;
434  }
435  void AddExtraInclude(const Char_t* inc_file)
436  {
465 
467  cf->AddImplIncludeFile(inc_file);
468  }
469 
470  void Copy(TObject& obj) const
471  {
473  KVBase::Copy(obj);
474  ((KVTemplateParticleCondition&) obj).fCondition = fCondition;
475  ((KVTemplateParticleCondition&) obj).fCondition_raw = fCondition_raw;
476  ((KVTemplateParticleCondition&) obj).fCondition_brackets = fCondition_brackets;
477  ((KVTemplateParticleCondition&) obj).fLambdaCondition = fLambdaCondition;
478  ((KVTemplateParticleCondition&) obj).fSavedLambda1 = fSavedLambda1;
479  ((KVTemplateParticleCondition&) obj).fSavedLambda2 = fSavedLambda2;
480  ((KVTemplateParticleCondition&) obj).fOpType = fOpType;
481  ((KVTemplateParticleCondition&) obj).fOptOK = fOptOK;
484  ((KVTemplateParticleCondition&) obj).fOptimal = nullptr;
485  if (fClassName != "")((KVTemplateParticleCondition&) obj).SetParticleClassName(fClassName.Data());
486  if (cf) {
487  ((KVTemplateParticleCondition&) obj).SetClassFactory(cf);
488  }
489  }
490 
492  {
494  if (&obj != this) obj.Copy(*this);
495  return (*this);
496  }
497 
499  {
516  Set(sel);
517  return (*this);
518  }
519 
521  {
524  return (*this);
525  }
526 
528  {
538 
541 
542  if (!(A.IsSet() && B.IsSet())) {
544  if (!(A.IsSet() || B.IsSet())) {
547  }
548  else if (A.IsSet()) return KVTemplateParticleCondition(A);
549  else return KVTemplateParticleCondition(B);
550  }
552  if (A.IsLambda() || B.IsLambda()) {
553  if (A.IsLambda() && B.IsLambda()) {
558  tmp.SetName(Form("(%s) && (%s)", A.GetName(), B.GetName()));
559  return tmp;
560  }
561  else {
562  ::Error("KVTemplateParticleCondition::operator&&", "Both KVParticleCondition objects must use lambda captures in order to do this");
564  }
565  }
567  tmp.Set(A.fCondition_brackets + " && " + B.fCondition_brackets);
568  if (A.fClassName != "") tmp.SetParticleClassName(A.fClassName);
569  else if (B.fClassName != "") tmp.SetParticleClassName(B.fClassName);
570  return tmp;
571  }
572 
574  {
584 
587 
588  if (!(A.IsSet() && B.IsSet())) {
590  if (!(A.IsSet() || B.IsSet())) {
593  }
594  else if (A.IsSet()) return KVTemplateParticleCondition(A);
595  else return KVTemplateParticleCondition(B);
596  }
598  if (A.IsLambda() || B.IsLambda()) {
599  if (A.IsLambda() && B.IsLambda()) {
604  tmp.SetName(Form("(%s) || (%s)", A.GetName(), B.GetName()));
605  return tmp;
606  }
607  else {
608  ::Error("operator&&", "Both KVParticleCondition objects must use lambda captures in order to do this");
610  }
611  }
613  tmp.Set(A.fCondition_brackets + " || " + B.fCondition_brackets);
614  if (A.fClassName != "") tmp.SetParticleClassName(A.fClassName);
615  else if (B.fClassName != "") tmp.SetParticleClassName(B.fClassName);
616  return tmp;
617  }
618 
620  {
625 
626  KVTemplateParticleCondition tmp = *this || other;
627  tmp.Copy(*this);
628  return *this;
629  }
630 
632  {
637 
638  KVTemplateParticleCondition tmp = *this && other;
639  tmp.Copy(*this);
640  return *this;
641  }
642  void Print(Option_t* opt = "") const
643  {
645  if (fCondition != "") {
646  Info("Print", "object name = %s, address = %p", GetName(), this);
647  std::cout << " * condition = " << fCondition.Data() << std::endl;
648  std::cout << " * classname = " << fClassName.Data() << std::endl;
649  std::cout << " * fOptimal = " << fOptimal << std::endl;
650  std::cout << " * fNUsing = " << fNUsing << std::endl;
651  if (cf) {
652  std::cout << " * classfactory :" << std::endl;
653  cf->Print();
654  }
655  }
656  else {
657  std::cout << GetName() << std::endl;
658  }
659  }
660 
661  static void PrintOptimizedList()
662  {
663  fgOptimized.Print();
664  }
665  Bool_t IsSet() const
666  {
670 
671  return (fLambdaCondition || fCondition != "");
672  }
673 
674  ClassDef(KVTemplateParticleCondition, 1) //Implements parser of particle selection criteria
675 };
676 
677 template<typename ParticleClass>
679 #endif
int Int_t
#define SafeDelete(p)
#define f(i)
int Ssiz_t
char Char_t
const Bool_t kFALSE
bool Bool_t
const Bool_t kTRUE
const char Option_t
#define ClassDef(name, id)
#define gROOT
char * Form(const char *fmt,...)
Base class for KaliVeda framework.
Definition: KVBase.h:141
virtual void Copy(TObject &) const
Make a copy of this object.
Definition: KVBase.cpp:394
static TPluginHandler * LoadPlugin(const Char_t *base, const Char_t *uri="0")
Definition: KVBase.cpp:793
Factory class for generating skeleton files for new classes.
void Print(Option_t *opt="") const
Print infos on object.
void GenerateCode()
Generate header and implementation file for currently-defined class.
void SetInheritAllConstructors(Bool_t yes=kTRUE)
const Char_t * GetImpFileName() const
void AddHeaderIncludeFile(const Char_t *filename)
void Copy(TObject &obj) const
Copy the state of this KVClassFactory to the one referenced by 'obj'.
void AddImplIncludeFile(const Char_t *filename)
const Char_t * GetClassName() const
void AddMethodBody(const Char_t *method_name, const KVString &body)
void AddMethodArgument(const Char_t *method_name, const Char_t *argument_type, const Char_t *argument_name="", const Char_t *default_value="")
KVClassMethod * AddMethod(const Char_t *name, const Char_t *return_type, const Char_t *access="public", Bool_t isVirtual=kFALSE, Bool_t isConst=kFALSE)
Extended version of ROOT THashList.
Definition: KVHashList.h:28
virtual void Add(TObject *obj)
virtual TObject * Remove(TObject *obj)
Remove object from list.
virtual TObject * FindObject(const char *name) const
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:72
An object for handling particle selection.
friend KVTemplateParticleCondition operator||(const KVTemplateParticleCondition &A, const KVTemplateParticleCondition &B)
void Copy(TObject &obj) const
Make a copy of this object.
KVTemplateParticleCondition & operator&=(const KVTemplateParticleCondition &other)
void SetClassFactory(KVClassFactory *CF)
friend KVTemplateParticleCondition operator&&(const KVTemplateParticleCondition &A, const KVTemplateParticleCondition &B)
Bool_t Test(const ParticleType *nuc) const
KVTemplateParticleCondition(const KVTemplateParticleCondition &obj)
Bool_t Test(const ParticleType &nuc) const
void Set(const KVString &name, const LambdaFunc &F)
virtual bool optimized_test(const ParticleType *) const
void AddExtraInclude(const Char_t *inc_file)
KVTemplateParticleCondition & operator=(const KVTemplateParticleCondition &obj)
KVTemplateParticleCondition(const KVString &cond)
void SetParticleClassName(const Char_t *cl)
const KVTemplateParticleCondition * fOptimal
void Optimize() const
false if optimisation failed (can't load generated code)
KVString fOptimizedClassName
used to generate code for optimisation
Bool_t fOptOK
name of generated class used for optimisation
KVTemplateParticleCondition & operator=(const KVString &sel)
std::function< bool(const ParticleType *)> LambdaFunc
number of classes using this as an optimized condition
KVTemplateParticleCondition(const KVString &name, const LambdaFunc &F)
KVTemplateParticleCondition & operator=(const LambdaFunc &f)
void Print(Option_t *opt="") const
enum KVTemplateParticleCondition::LogOp fOpType
KVTemplateParticleCondition & operator|=(const KVTemplateParticleCondition &other)
virtual void Print(Option_t *option, const char *wildcard, Int_t recurse=1) const
virtual const char * GetName() const
virtual void SetName(const char *name)
virtual void Error(const char *method, const char *msgfmt,...) const
virtual void Fatal(const char *method, const char *msgfmt,...) const
virtual void Info(const char *method, const char *msgfmt,...) const
Longptr_t ExecPlugin(int nargs, const T &... params)
TSubString Strip(EStripType s=kTrailing, char c=' ') const
const char * Data() const
TString & Prepend(char c, Ssiz_t rep=1)
void Form(const char *fmt,...)
TString & Remove(EStripType s, char c)
TString & ReplaceAll(const char *s1, const char *s2)
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
const char * AsString() const
#define F(x, y, z)
const long double cl
Definition: KVUnits.h:85