# Recommended LoKi::Hybrid Functors

This lists the filters recommended for use in the HLT and the selections. See DaVinciTutorial4 for a hands-on tutorial. A longer, but not necessarily up-to-date, list can be found at LoKiParticleFunctions. It also contains examples on how to use these functors in C++ code.

# Particle Functors

## `ALL`: All

Takes all particles. This is required if one wants to apply no cut.
`CombineParticles.FILTER0.Code = "ALL" ;`

## `ABSID`: Absolute value of PID.

Returns the absolute value of the PID. The following lines are equivalent:
```CombineParticles.FILTER0.Code = "ABSID==211" ;
CombineParticles.FILTER0.Code = "ABSID=='pi+' " ;
CombineParticles.FILTER0.Code = "ABSID=='pi-' " ;```
Note the last line! The comparison `(ABSID=='pi-')` takes the absolute value on both sides. This avoid having to remember that the has a positive pid (211) while the has a negative pid (-13).

The pid can also be used without the absolute value. See `ID`.

## `ADMASS`: The absolute mass difference to the reference value

Calculates the absolute difference between the measured mass and the PDG reference value. It takes the pid of the reference particle as argument.
`HltSharedKsLL.FILTER1.Code = "ADMASS('KS0')<50"`

The mass difference can also be used without the absolute value. See `DMASS`.

TODO : A version without argument will be provided where the ID of the particle is used to get the reference mass.

## `BPVDIRA`: Direction angle

Computes the cosine of the angle between the momentum of the particle and the direction fo flight from the best PV to the decay vertex.
`CombineParticles.FILTER2.Code = "(BPVDIRA>0.9999)" ;`

## `BPVIPCHI2()`: IP on related PV

Computes the -IP on the related PV.
`CombineParticles.FILTER2.Code = "BPVIPCHI2()<25" ;`
TODO : So far it needs the ().

## `BPVVDCHI2`: -separation from related PV

Computes the -distance from the related PV.
`CombineParticles.FILTER2.Code = "BPVVDCHI2>100" ;`

## `BPVVDZ`: -distance from the end vertex of the particle and the related primary vertex.

The functor computes the -distance from the end vertex of the particle and the related primary vertex.
```CombineParticles.FILTER2.Code = "0<BPVVDZ" ;
```
The concept and the name come from Sean Brisbane. The functor is available starting from Phys/LoKiPhys version >= v7r2.

## `BPVVDR`: -distance from the end vertex of the particle and the related primary vertex.

The functor computes the -distance(cylindrical) from the end vertex of the particle and the related primary vertex.
```CombineParticles.FILTER2.Code = "0.1<BPVVDR" ;
```
The concept and the name come from Sean Brisbane. The functor is available starting from Phys/LoKiPhys version >= v7r2.

## `BPVVDRHO`: -distance from the end vertex of the particle and the related primary vertex.

The functor computes the -distance(cylindrical) from the end vertex of the particle and the related primary vertex.
```CombineParticles.FILTER2.Code = "0.1<BPVVDRHO" ;
```
The concept and the name come from Sean Brisbane. The functor is available starting from Phys/LoKiPhys version >= v7r2.

## `CHILDCUT`: Applies a cut to a given child

`FilterDesktop.Filter.Code = "CHILDCUT ( MIPCHI2DV ( PRIMARY ) > 1 , 2 )" ;`
In this example one applies an IP cut on the first daughter of the input particle. This requires to know which is the first, second, etc daughter. Can be useful when `(N)INTREE` won't work. Like here for the slow pion in a where searching for a pion in the tree would also return the daughters of the . Use the safer `INTREE` and `NINTREE` instead.

TODO : Is there a way of applying a cut to the daughters only, without navigating the whole tree? From next version `NINGENERATION` and `INGENERATION` will do this.

## `DMASS`: The mass difference to the reference value

Calculates the difference between the measured mass and the PDG reference value. It takes the pid of the reference particle as argument. In most reasonable cases one will use the absolute mass difference (see `DMASS`) or the mass itself (see `MM`).

## `ID`: Particle ID

Like `ABSID` but without the absolute value.

## `INGENERATION`: "in generation"

The predicate which checks the existence of the particle satisfying the requirements in the decay tree at the given depth
```FilterDesktop.Filter.Code = "INGENERATION ( ( 'mu+'==ABSID)  & ( PT > 2 * GeV ) , 2 ) " ;
```
Requires the presence of at least one granddaughter , which the transverse momentum . The generations are defined as: 0 - the particle itself, 1 - the direct children, 2 - grandchildren , etc. The concept and the name come from Patrick Koppenburg. The functor is available starting from Phys/LoKiPhys version >= v7r2.

## `INTREE`: In tree

Requires there is a particle in the decay tree satisfying the requirements.
`FilterDesktop.Filter.Code = "(INTREE( (ID=='J/psi(1S)') & (BPVVDCHI2>25) ) )" ;`
Requires there is a in the tree more than away from the best vertex.

## `MAXTREE`: Maximum value in the decay tree

Returns the maximum value of some functor in the decay tree. Useful to apply cuts on all particles, or to extract some value from the tree.
`CombineParticles.FILTER2.Code = "(M-MAXTREE('D0'==ABSID,M)<165.5)" ;`
This example looks for all in the decay, returns the largest mass (which is the mass of the as there's only one) and computes the mass difference with the mother.

## `MINTREE`: Minimal value in the decay tree

Takes a functor as agrument and returns its minimal value searching through the decay tree.
`CombineParticles.FILTER0.Code = "(MINTREE(ABSID=='K+',PT)>1400)" ;`
This would look for all particles kaons in the decay tree and find their and return the minimum. The cut then requires that all kaon descendents have a .

## `MINVDDV`: minimum distance between the particle's end-vertex and any other vertex

The functor evaluates the minimal 3D-distance between the particle's end-vertex and the vertices form "list". The list of vertices is extracted from the desktop:
```CombineParticles.FILTER2.Code = "MINVDDV(PRIMARY)>1" ;
```
Requires that the particle's end-vertex has at least one millimeter separation with respect to any primary vertex.

## `MINVDSOURCE`: minimum distance between the particle's end-vertex and any other vertex

The functor evaluates the minimal 3D-distance between the particle's end-vertex and the vertices form "list". The list of vertices is extracted from the "source":
```CombineParticles.FILTER2.Code = "MINVDSOURCE( VSOURCEDV ( PRIMARY ) )>1" ;
```
Requires that the particle's end-vertex has at least one millimeter separation with respect to any primary vertex.

## `MINVDTES`: minimum distance between the particle's end-vertex and any other vertex

The functor evaluates the minimal 3D-distance between the particle's end-vertex and the vertices form "list". The list of vertices is extracted from the TES:
```CombineParticles.FILTER2.Code = "MINVDTES('SomeLocationInTES',PRIMARY)>1" ;
```
Requires that the particle's end-vertex has at least one millimeter separation with respect to any primary vertex.

## `MIPCHI2DV`: Minimum IP-

Returns the minimum distance of a particles's trajectory to any set of vertices. Most useful in conjunction with the `PRIMARY` argument that looks at PVs.
`CombineParticles.FILTER0.Code = "(MIPCHI2DV(PRIMARY)>9)" ;`
This requires that the particle is away from any PV.

## `MIPDV`: Minimum IP

Returns the minimum distance of a particles's trajectory to any set of vertices. Most useful in conjunction with the `PRIMARY` argument that looks at PVs.
`CombineParticles.FILTER0.Code = "(MIPDV(PRIMARY)>0.15)" ;`
This requires that the particle is 0.15 mm away from any PV.

## `M`: Mass

Returns . Uses the function `LHCb::Particle::momentum().M()`. For many cases it should be practically the same as `MM`.

## `MM`: Measured Mass

Returns the measured mass of the particle. The function `LHCb::Particle::measuredMass()` is used for evaluation.
`HltSharedDiMuon.FILTER1.Code = "(MM<11000)"`
This selects dimuons up to a mass of 11 GeV.

## `NINGENERATION`: "Number of particles in generation"

The function which counts the particles satisfying the requirements in the decay tree at the given depth:
```FilterDesktop.Filter.Code = " 2 == NINGENERATION ( ( 'mu+'==ABSID)  & ( PT > 2 * GeV ) , 2 ) " ;
```
Requires the presence of exactly two granddaughter with the transverse momentum . The generations are defined as: 0 - the particle itself, 1 - the direct children, 2 - grandchildren , etc. The concept and the name come from Patrick Koppenburg. The functor is available starting from Phys/LoKiPhys version >= v7r2.

## `NINTREE`: Number of particles in tree

Returns the number of particles in a tree satisfying some selection criteria.
`CombineParticles.FILTER0.Code = "( 2 == NINTREE( (ABSID=='e-') & (PT>1000)))" ;`
Requires that there are two electrons in the tree with .

## `P`: Momentum

Gets the momentum of the particle.
`HltSharedKsLL.FILTER0.Code = "(P>2000)";`
Gets particles with .

## `PIDe`, `PIDmu`, `PIDK`, `PIDp`, `PIDpi` : PID DLL

Gets the combined delta-log-likelihood for the given hypothesis (wrt the pion)
`CombineParticles.FILTER0.Code = "(PIDe-PIDpi>6)" ;`

## `PT`: Transverse momentum

Gets the transverse momentum of the particle. Note that this is evaluated at the first measurement of the particle, which might not be where you want it for pions in decays.
`HltSharedKsLL.FILTER0.Code = "(PT>1000)";`
Gets particles with .

## `TRCHI2DOF`: per degree of freedom of the track fit

Gets the per degree of freedom of the track fit.
`CombineParticles.FILTER0.Code = "(TRCHI2DOF<20)" ;`

## `VDMIN`: Distance of two vertices

TODO : Not yet supported.

## `VFASPF`: Vertex Function as Particle Function.

Allows to apply vertex functors to the particle's `endVertex()`.
`CombineParticles.FILTER2.Code = "(VFASPF(VCHI2/VDOF)<10)" ;`
Applies a cut to the vertex of the particle.

# Vertex functors

Vertex functors are accessed using `VFASPF`.

## `VCHI2` : Vertex

`CombineParticles.FILTER2.Code = "(VFASPF(VCHI2/VDOF)<10)" ;`

## `VDOF` : Vertex fit number of degrees of freedom

`CombineParticles.FILTER2.Code = "(VFASPF(VCHI2/VDOF)<10)" ;`

## `VMINVDDV`: minimum distance between the vertex and any other vertex

The functor evaluates the minimal 3D-distance between the vertex and the vertices from "list". The list of vertices is extracted from the desktop:
```CombineParticles.FILTER2.Code = "VFASFP(VMINVDDV(PRIMARY))>1" ;
```
Requires that the particle's end-vertex has at least one millimeter separation with respect to any primary vertex.

## `VMINVDSOURCE`: minimum distance between the vertex and any other vertex

The functor evaluates the minimal 3D-distance between the vertex and the vertices form "list". The list of vertices is extracted from the "source":
```CombineParticles.FILTER2.Code = "VFASPF( VMINVDSOURCE( VSOURCEDV ( PRIMARY ) ) ) >1" ;
```
Requires that the particle's end-vertex has at least one millimeter separation with respect to any primary vertex.

## `VMINVDTES`: minimum distance between the vertex and any other vertex

The functor evaluates the minimal 3D-distance between the vertex and the vertices form "list". The list of vertices is extracted from the TES:
```CombineParticles.FILTER2.Code = "VFASPF( VMINVDTES ( 'SomeLocationInTES' , PRIMARY ) ) >1" ;
```
Requires that the particle's end-vertex has at least one millimeter separation with respect to any primary vertex.

## `VPCHI2`: -probability

The functor evaluates the -probability of the vertex, taking into account the number of degrees of freedom. The GSL routine `gsl_cdf_chisq_Q` functon is used for evaluation.
```CombineParticles.FILTER2.Code = "VFASPF(VPCHI2)>1*perCent" ;
```
The functor is available starting from Phys/LoKiPhys version >= v7r2

# Units

Presently units are not supported easily. This will change in the next release. To avoid confusion between `M` (mass) and `m` (meter) for instance a limited set will be defined. Vanya suggests:

• MeV, GeV
• mm, millimeter, cm , centimeter, meter
• perCent
• ns, fs, nanosecond, femtosecond, ps, picoseconds
These units are available starting from Phys/LoKiPhys version >= v7r2

# Syntax

Cut are combined using the bit-wide `&` and `|` operators, not boolean operators. This also requires that cuts are well protected using parentheses. Example:
```HltSharedD02KsPiPi.FILTER0.Code = "( ((ABSID=='pi+') & (PT>400)) |
((ABSID=='KS0') & (PT>1000)))"```
Cuts can be split over several lines.

# Use of `CombineParticles`.

`CombineParticles` is a `DVAlgorithm` that combines the input particles according to the decay descriptor. There are three cuts applied :
1. `FILTER0` : On the incoming daughter particles.
2. `FILTER1` : Once a combination has been made according to the decay descriptor but before the vertex fit.
3. `FILTER2` : After the vertex fit.
All the cuts that require the position of the vertex must be applied in `FILTER2`, while the others can be applied earlier (saving CPU). Note that for long lived particles like Ks it pays off to apply a loose mass cut in `FILTER1` and a harder in `FILTER2`. The reason is that the vertex fit does a propagation of the momenta through the detector. You thus get the momentum at the Ks vertex, while in `FILTER1` it's just the sum of the momenta of the daughters at their first measurement.

A simple example:

```HltShared.Members += { "CombineParticles/HltSharedPhi2KK" } ;
HltSharedPhi2KK.PhysDesktop.InputLocations = { "Phys/HltNoPIDsKaons" };
HltSharedPhi2KK.DecayDescriptor = "phi(1020) -> K+ K-";
HltSharedPhi2KK.FILTER0.Code = "(MIPCHI2DV(PRIMARY)>4)";    // (IP > 2 sigma)^2
HltSharedPhi2KK.FILTER1.Code = "(ADMASS('phi(1020)')<50)";  // mass window +/- 300 MeV
HltSharedPhi2KK.FILTER2.Code = "(VFASPF(VCHI2/VDOF)<25)" ;       ```

The decay descriptor can be overwritten by `DecayDescriptors` which allows to reconstruct several decays in one go.

```HltShared.Members += { "CombineParticles/HltSharedDstarWithD02KPi" } ;
HltSharedDstarWithD02KPi.PhysDesktop.InputLocations = { "Phys/HltSharedD02KPi", "Phys/HltSharedSlowPions" };
HltSharedDstarWithD02KPi.DecayDescriptors = {"[D*(2010)+ -> pi+ D0]cc", "[D*(2010)+ -> pi+ D~0]cc" }; // also wrong-sign ones
HltSharedDstarWithD02KPi.FILTER0.Code = "(ALL)";    // IP already applied in shared slow pion
HltSharedDstarWithD02KPi.FILTER1.Code = "(ADMASS('D*(2010)+')<50) & (PT>1250)";  // mass window +/- 50 MeV, PT> 1.25 GeV
HltSharedDstarWithD02KPi.FILTER2.Code = "(VFASPF(VCHI2/VDOF)<25) & (M-MAXTREE('D0'==ABSID,M)<165.5)" ;       // Chi2 < 25 . D*-D0 = 145.5 MeV, +2
```

# Use of `FilterDesktop`.

`FilterDesktop` is a `DVAlgorithm` that applies a cut and clones the selected particles. It has one filter (`Filter`) but the default is not the `LoKi::Hybrid::FilterCriterion` which needs to be set by hand using the `FilterCriterion` property.
```HltExclusive.Members += { "FilterDesktop/HltSelSingleMuon" } ;
HltSelSingleMuon.PhysDesktop.InputLocations  = {"Phys/HltMuons"} ;
HltSelSingleMuon.FilterCriterion = "LoKi::Hybrid::FilterCriterion" ;
/**
* Pt > 3 GeV & IP/err > 5 & IP > 0.15 mm
*/
HltSelSingleMuon.Filter.Code = "((PT>3000) & (MIPCHI2DV(PRIMARY)>25) & (MIPDV(PRIMARY)>0.15))" ; ```

## Help

Please do not send mails directly to the authors, but send the questions and requests through the following mailing lists:

`lhcb-davinci@cern.ch`, `lhcb-loki@cern.ch`, `lhcb-bender@cern.ch`

In this case more colleagues can profit from solutions to the problems and it will allow a bit more wide distribution of useful information, tricks, recipes, experience and the solutions. Also it will simplify the monitoring of the progress with the implementation of the missing functionality.

### Examples

Many working examples can be found in the `Hlt/HltSelections` package from version `v6r0` released with `DaVinci v19r11`.

## Feature requests

Feature requests should be sent to the same mailing lists as above. For every new feature a suggested name should be provided. This drastically simplifies the life of developers and results in a much higher priority.

### Change of names

Although it is very simple to define aliases for these functors (and many of them are actually available) their use is not encouraged. This is because we would like to define a minimum vocabulary everyone would have to be able to understand. Since this is rather new, suggestions for changes of names are accepted but should be agreed by the community. Please send requests to the mailing lists above. It is suggested to freeze this in the next version.

Suggestions for the names of the filters in `CombineParticles` are also welcome.