I am trying to combine many TCut objects into a single TCut in a python script using
the logical ‘and’ operator but I am having problems. In python I get:
[code]>>> from ROOT import TCut
cut1 = TCut(“x>5”)
cut2 = TCut(“x<2”)
cut3 = cut1 and cut2
cut3.Print()
OBJ: TCut CUT x<2[/code]
whereas in a root interactive session I get:
root [0] TCut cut1("x>5")
root [1] TCut cut2("x<2")
root [2] TCut cut3 = cut1 && cut2
root [3] cut3.Print()
OBJ: TCut CUT (x>5)&&(x<2)
Is there a problem with the logical ‘and’ operator overloading or am I missing something?
the “and” in python can not be overloaded (the bit-wise & can, but so can that operator in C++, so there is a short-coming). In addition, there is currently no support in PyROOT for friend global functions (it’s on my wishlist). The easiest way to work with TCuts, then, is like so:
[code]>>> cut1 = TCut(“x>5”)
cut2 = TCut(“x<2”)
cut3 = TCut(cut1)
cut3 += cut2
cut3.Print()
OBJ: TCut CUT (x>5)&&(x<2)
[/code]
In the code above, cut1 is first copied into cut3, to prevent cut1 from being changed, then cut2 is added to cut3. The two lines execute “cut3 = TCut(cut1).iadd( cut2 )”.
the “and” in python can not be overloaded (the bit-wise & can, but so can that operator in C++, so there is a short-coming). In addition, there is currently no support in PyROOT for friend global functions (it’s on my wishlist). The easiest way to work with TCuts, then, is like so:
[code]>>> cut1 = TCut(“x>5”)
cut2 = TCut(“x<2”)
cut3 = TCut(cut1)
cut3 += cut2
cut3.Print()
OBJ: TCut CUT (x>5)&&(x<2)
[/code]
In the code above, cut1 is first copied into cut3, to prevent cut1 from being changed, then cut2 is added to cut3. The two lines execute “cut3 = TCut(cut1).iadd( cut2 )”.
same problem with ‘or’ as with ‘and’ I’m afraid (it’s funny though that the TCut header explicitly has to disable a gcc warning b/c of the choice to overload operator|| and operator&& ).
Best I can think of is some string manipulation:[code]>>> cut1 = TCut(“x>5”)
cut2 = TCut(“x<2”)
cut3 = TCut( cut1.GetTitle() + ’ || !’ + cut2.GetTitle() )
cut3.Print()
OBJ: TCut CUT x>5 || !x<2[/code]
Note that this string manipulation (modulo some error handling and brackets etc.) is what the implementation of the C++ operator|| is actually doing.
same problem with ‘or’ as with ‘and’ I’m afraid (it’s funny though that the TCut header explicitly has to disable a gcc warning b/c of the choice to overload operator|| and operator&& ).
Best I can think of is some string manipulation:[code]>>> cut1 = TCut(“x>5”)
cut2 = TCut(“x<2”)
cut3 = TCut( cut1.GetTitle() + ’ || !’ + cut2.GetTitle() )
cut3.Print()
OBJ: TCut CUT x>5 || !x<2[/code]
Note that this string manipulation (modulo some error handling and brackets etc.) is what the implementation of the C++ operator|| is actually doing.
same problem with ‘or’ as with ‘and’ I’m afraid (it’s funny though that the TCut header explicitly has to disable a gcc warning b/c of the choice to overload operator|| and operator&& ).
Best I can think of is some string manipulation:[code]>>> cut1 = TCut(“x>5”)
cut2 = TCut(“x<2”)
cut3 = TCut( cut1.GetTitle() + ’ || !’ + cut2.GetTitle() )
cut3.Print()
OBJ: TCut CUT x>5 || !x<2[/code]
Note that this string manipulation (modulo some error handling and brackets etc.) is what the implementation of the C++ operator|| is actually doing.
>>> from rootpy.tree import Cut
>>> a = Cut("a > 2")
>>> b = Cut("b < 5")
>>> a | b
(a>2)||(b<5)
>>> a & b
(a>2)&&(b<5)
>>>
>>> c = Cut("3 < c < 10")
>>> c
3<c&&c<10
>>>
Similar to your suggestion of using the add-in-place operator += to “and” cuts together, couldn’t you make the multiply-in-place operator *= implement “or”?
a.class.bases
(<class ‘ROOT.TCut’>,)
a
a<10
b
b>2
-a
!(a<10)
a * -1
(a<10)(-1)
-1 * a
(a<10)(-1)
a-b
(a<10)-(b>2)
-a-b
(!(a<10))-(b>2)
a | -a & b + a
(a<10)||((!(a<10))&&((b>2)+(a<10)))
a += b
a
(a<10)+(b>2)
a &= b
a
((a<10)+(b>2))&&(b>2)
a |= b
a
(((a<10)+(b>2))&&(b>2))||(b>2)
a = b
a
((((a<10)+(b>2))&&(b>2))||(b>2))(b>2)
-a
!(((((a<10)+(b>2))&&(b>2))||(b>2))*(b>2))
[/code]