KaliVeda
Toolkit for HIC analysis
KVTemplateParticleCondition.h
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 
66 template<typename ParticleType>
68  static KVHashList fgOptimized;// list of optimized particle conditions
69  mutable Int_t fNUsing;
70  using LambdaFunc = std::function<bool(const ParticleType*)>;
72  LambdaFunc fSavedLambda1, fSavedLambda2;// used by || and &&
73  enum class LogOp { AND, OR } fOpType;
74 
76  {
78  if (IsLambda() && !IsSet()) {
79  switch (fOpType) {
80  case LogOp::AND:
81  fLambdaCondition = [this](const ParticleType * nuc) {
82  return (fSavedLambda1(nuc) && fSavedLambda2(nuc));
83  };
84  break;
85  case LogOp::OR:
86  fLambdaCondition = [this](const ParticleType * nuc) {
87  return (fSavedLambda1(nuc) || fSavedLambda2(nuc));
88  };
89  break;
90  }
91  }
92  }
93 
94 protected:
95 
96  KVString fCondition;//string containing selection criteria with ";" at end
97  KVString fCondition_raw;//'raw' condition, i.e. no ';'
98  KVString fCondition_brackets;//condition with '(' and ')' around it
99 
102  mutable KVClassFactory* cf;
104  mutable Bool_t fOptOK;
105 
106  void Optimize() const
107  {
120 
122  if (fOptimal) { /* check that the same condition has not already been optimized */
124  fOptimal->fNUsing++;
125  fOptOK = kTRUE;
126  return;
127  }
128  Info("Optimize", "Optimization of KVParticleCondition : %s", fCondition.Data());
129 
131  KVString created_class_name = cf->GetClassName();
133  cf->AddMethod("optimized_test", "Bool_t", "public", false, true);
134  cf->AddMethodArgument("optimized_test", "const KVNucleus*", "nuc");
135  cf->AddHeaderIncludeFile("KVNucleus.h");
136 
138  KVString body(" //Optimized Test method for particle condition\n");
139  KVString pointer = "nuc";
140  if (fClassName != "") {
141  pointer.Form("((%s*)nuc)", fClassName.Data());
144  }
145  KVString tmp;
146  tmp = fCondition;
147  tmp.ReplaceAll("_NUC_", pointer.Data());
148  body += " return ";
149  body += tmp;
150 
151  cf->AddMethodBody("optimized_test", body);
152 
154  cf->GenerateCode();
155 
157  gROOT->GetPluginManager()->AddHandler("KVParticleCondition", cf->GetClassName(), cf->GetClassName(),
158  Form("%s+", cf->GetImpFileName()), Form("%s()", cf->GetClassName()));
160  TPluginHandler* ph;
161  if (!(ph = LoadPlugin("KVParticleCondition", cf->GetClassName()))) {
162  Error("Optimize", " *** Optimization failed for KVParticleCondition : %s", fCondition.Data());
163  Error("Optimize", " *** Use method AddExtraInclude(const Char_t*) to give the names of all necessary header files for compilation of your condition.");
164  Fatal("Optimize", " *** THIS CONDITION WILL BE EVALUATED AS kFALSE FOR ALL PARTICLES!!!");
165  delete cf;
166  cf = 0;
169  fOptimal = this;
170  fOptOK = kFALSE;
171  return;
172  }
173  fOptOK = kTRUE;
174  delete cf;
175  cf = 0;
178 
179  Info("Optimize", "fOptimal = %p", fOptimal);
180  if (!fOptimal) {
181  Error("Optimize", " *** Optimization failed for KVParticleCondition : %s", fCondition.Data());
182  Error("Optimize", " *** Use method AddExtraInclude(const Char_t*) to give the names of all necessary header files for compilation of your condition.");
183  Fatal("Optimize", " *** THIS CONDITION WILL BE EVALUATED AS kFALSE FOR ALL PARTICLES!!!");
186  fOptimal = this;
187  fOptOK = kFALSE;
188  }
191  const_cast<KVTemplateParticleCondition*>(fOptimal)->fOptimizedClassName = created_class_name;
193  fOptimal->fNUsing++;
194  Info("Optimize", "Success");
195  }
196 
197  virtual bool optimized_test(const ParticleType*) const
198  {
199  return kFALSE;
200  }
201  void CreateClassFactory() const
202  {
204 
205  if (cf) return;
206 
208  TUUID unique;
209  KVString new_class = unique.AsString();
211  new_class.Remove(8);
212  new_class.Prepend("KVParticleCondition_");
213 
215  cf = new KVClassFactory(new_class.Data(), "Particle condition to test", "KVParticleCondition");
216  cf->SetInheritAllConstructors(kFALSE); // avoid generating ctor with LambdaFunc argument!!!
217  }
218 
220  {
224  CF->Copy(*cf);
225  }
226 
227 public:
229  : KVBase("KVParticleCondition", "Particle selection criteria")
230  {
232  fOptimal = nullptr;
233  cf = nullptr;
234  fOptOK = kFALSE;
235  fNUsing = 0;
236  }
237 
239  : KVBase(cond, "KVParticleCondition")
240  {
260  fOptimal = nullptr;
261  Set(cond);
262  cf = nullptr;
263  fOptOK = kFALSE;
264  fNUsing = 0;
265  }
266 
268  : KVBase(cond, "KVParticleCondition")
269  {
289  fOptimal = nullptr;
290  Set(cond);
291  cf = nullptr;
292  fOptOK = kFALSE;
293  fNUsing = 0;
294  }
295 
297  : KVBase("KVParticleCondition", "Particle selection criteria")
298  {
300  fOptimal = nullptr;
301  cf = nullptr;
302  fOptOK = kFALSE;
303  fNUsing = 0;
304  obj.Copy(*this);
305  }
306 
308  : KVBase(name, "KVParticleCondition"), fLambdaCondition(F)
309  {
333  fOptimal = nullptr;
334  cf = nullptr;
335  fOptOK = kFALSE;
336  fNUsing = 0;
337  }
338  bool IsLambda() const
339  {
341  return (bool)fLambdaCondition || ((bool)fSavedLambda1 && (bool)fSavedLambda2);
342  }
343 
345  {
347  if (fOptimal) {
349  --(fOptimal->fNUsing);
350  if (!(fOptimal->fNUsing)) {
352  delete fOptimal;
353  fOptimal = nullptr;
354  }
355  }
356  SafeDelete(cf);
357  }
358 
359  void Set(const KVString& name, const LambdaFunc& F)
360  {
372  SetName(name);
373  }
374 
375  void Set(const KVString& cond)
376  {
386 
388 
389  fCondition = cond;
390  Ssiz_t ind = fCondition.Index(";");
391  if (ind < 0) {
393  fCondition += ";"; //we add a ";" if there isn't already
394  }
395  else {
397  }
398  fCondition_brackets = "(" + fCondition_raw + ")";
399  }
400 
401  Bool_t Test(const ParticleType* nuc) const
402  {
410 
412  if (!IsSet()) return kTRUE;
413  if (IsLambda()) return fLambdaCondition(nuc);
414  if (!fOptimal) Optimize();
415 
416  return (fOptOK ? fOptimal->optimized_test(nuc) : kFALSE);
417  }
418 
419  Bool_t Test(const ParticleType& nuc) const
420  {
428 
429  return Test(&nuc);
430  }
431 
432  void SetParticleClassName(const Char_t* cl)
433  {
434  fClassName = cl;
435  }
436  void AddExtraInclude(const Char_t* inc_file)
437  {
466 
468  cf->AddImplIncludeFile(inc_file);
469  }
470 
471  void Copy(TObject& obj) const
472  {
474  KVBase::Copy(obj);
475  ((KVTemplateParticleCondition&) obj).fCondition = fCondition;
476  ((KVTemplateParticleCondition&) obj).fCondition_raw = fCondition_raw;
477  ((KVTemplateParticleCondition&) obj).fCondition_brackets = fCondition_brackets;
478  ((KVTemplateParticleCondition&) obj).fLambdaCondition = fLambdaCondition;
479  ((KVTemplateParticleCondition&) obj).fSavedLambda1 = fSavedLambda1;
480  ((KVTemplateParticleCondition&) obj).fSavedLambda2 = fSavedLambda2;
481  ((KVTemplateParticleCondition&) obj).fOpType = fOpType;
482  ((KVTemplateParticleCondition&) obj).fOptOK = fOptOK;
485  ((KVTemplateParticleCondition&) obj).fOptimal = nullptr;
486  if (fClassName != "")((KVTemplateParticleCondition&) obj).SetParticleClassName(fClassName.Data());
487  if (cf) {
488  ((KVTemplateParticleCondition&) obj).SetClassFactory(cf);
489  }
490  }
491 
493  {
495  if (&obj != this) obj.Copy(*this);
496  return (*this);
497  }
498 
500  {
517  Set(sel);
518  return (*this);
519  }
520 
522  {
525  return (*this);
526  }
527 
529  {
539 
542 
543  if (!(A.IsSet() && B.IsSet())) {
545  if (!(A.IsSet() || B.IsSet())) {
548  }
549  else if (A.IsSet()) return KVTemplateParticleCondition(A);
550  else return KVTemplateParticleCondition(B);
551  }
553  if (A.IsLambda() || B.IsLambda()) {
554  if (A.IsLambda() && B.IsLambda()) {
559  tmp.SetName(Form("(%s) && (%s)", A.GetName(), B.GetName()));
560  return tmp;
561  }
562  else {
563  ::Error("KVTemplateParticleCondition::operator&&", "Both KVParticleCondition objects must use lambda captures in order to do this");
565  }
566  }
568  tmp.Set(A.fCondition_brackets + " && " + B.fCondition_brackets);
569  if (A.fClassName != "") tmp.SetParticleClassName(A.fClassName);
570  else if (B.fClassName != "") tmp.SetParticleClassName(B.fClassName);
571  return tmp;
572  }
573 
575  {
585 
588 
589  if (!(A.IsSet() && B.IsSet())) {
591  if (!(A.IsSet() || B.IsSet())) {
594  }
595  else if (A.IsSet()) return KVTemplateParticleCondition(A);
596  else return KVTemplateParticleCondition(B);
597  }
599  if (A.IsLambda() || B.IsLambda()) {
600  if (A.IsLambda() && B.IsLambda()) {
605  tmp.SetName(Form("(%s) || (%s)", A.GetName(), B.GetName()));
606  return tmp;
607  }
608  else {
609  ::Error("operator&&", "Both KVParticleCondition objects must use lambda captures in order to do this");
611  }
612  }
614  tmp.Set(A.fCondition_brackets + " || " + B.fCondition_brackets);
615  if (A.fClassName != "") tmp.SetParticleClassName(A.fClassName);
616  else if (B.fClassName != "") tmp.SetParticleClassName(B.fClassName);
617  return tmp;
618  }
619 
621  {
626 
627  KVTemplateParticleCondition tmp = *this || other;
628  tmp.Copy(*this);
629  return *this;
630  }
631 
633  {
638 
639  KVTemplateParticleCondition tmp = *this && other;
640  tmp.Copy(*this);
641  return *this;
642  }
643  void Print(Option_t* opt = "") const
644  {
646  if (fCondition != "") {
647  Info("Print", "object name = %s, address = %p", GetName(), this);
648  std::cout << " * condition = " << fCondition.Data() << std::endl;
649  std::cout << " * classname = " << fClassName.Data() << std::endl;
650  std::cout << " * fOptimal = " << fOptimal << std::endl;
651  std::cout << " * fNUsing = " << fNUsing << std::endl;
652  if (cf) {
653  std::cout << " * classfactory :" << std::endl;
654  cf->Print();
655  }
656  }
657  else {
658  std::cout << GetName() << std::endl;
659  }
660  }
661 
662  static void PrintOptimizedList()
663  {
664  fgOptimized.Print();
665  }
666  Bool_t IsSet() const
667  {
671 
672  return (fLambdaCondition || fCondition != "");
673  }
674 
675  ClassDef(KVTemplateParticleCondition, 1) //Implements parser of particle selection criteria
676 };
677 
678 template<typename ParticleClass>
680 #endif
int Int_t
#define SafeDelete(p)
#define f(i)
bool Bool_t
int Ssiz_t
char Char_t
constexpr Bool_t kFALSE
constexpr Bool_t kTRUE
const char Option_t
#define ClassDef(name, id)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t sel
char name[80]
#define gROOT
char * Form(const char *fmt,...)
Base class for KaliVeda framework.
Definition: KVBase.h:142
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:29
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:73
An object for handling particle selection.
friend KVTemplateParticleCondition operator||(const KVTemplateParticleCondition &A, const KVTemplateParticleCondition &B)
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
const char * GetName() const override
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)
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)