Cuts
Most of this information is scattered around the manual, so if a description is too brief here, you might find more information there. This page is intended to gather everything needed to write cuts without having to study the manual for a day.
Definition
One of the harder parts of using Whizard is the setup of cuts. The general definition of the cuts object is
cuts = log_class log_expr [unary_or_binary_particle_list_arg]
The log_class
can be all
, any
or no
and the log_expr
something like E <= 100 GeV
or PDG == 15
.
Note that you can combine multiple log_expr
s as well as cut expressions with
and
or or
.
Basic example
Let's start off with "e+", "e-" => "e+", "e-"
. The only possible divergences
are collinearities with the beam due to t-channel diagrams. So we can just avoid
them with
cuts = all Theta > 10 degree [incoming "e+":"e-", "e+":"e-"]
Here, we have used the incoming
constructor that only selects incoming
particles. You might wonder why this doesn't give always false, for the
combination of incoming beam 1 with incoming beam 1, e.g.. The square bracket with two
entries actually evaluates to the list of all possible pairs which do not
overlap, so this case is excluded. The concept of overlapping will be used
heavily later on.
Note that the expression above is the same as
cuts = all Theta > 10 degree [incoming "e+":"e-", "e-"] and all Theta > 10 degree [incoming "e+":"e-", "e+"]
telling us that concatenations of particle species with :
are expanded.
This syntax should be enough to get basic examples working but for more complicated cases, we first have to understand subevents.
What the hell are subevents?
Subevents are sets of particles that are extracted from an event. A subevent can be created by just putting square brackets around a particle species or alias
["e+"] [u:d:s] [charged]
These subevents evaluate to the set of all positrons, light quarks and charged particles in an event, respectively. In our above example, we can also construct subevents explicitely and have the same effect
cuts = all Theta > 10 degree [[incoming "e+":"e-"], ["e+":"e-"]]
Especially to keep more complicated examples readable, it's quite useful to
declare subevent variables. We can do this with the let
construct
cuts = let subevt @leptons = ["e+":"e-"] in let subevt @inc = [incoming "e+":"e-"] in all Theta > 10 degree [@inc, @leptons]
The @
prefix is hereby mandatory. Now, we are only lacking more powerful
commands to build subevents.
Building subevents
- collect and count
-
collect [particles]
collect
collects all the (composite) particles in the subevent or alias
particles
into a single four-momentum. You can think of this as a contraction
of the set you put in. We can check this by adding to our cut expression
and count [collect [@inc]] == 2
and we will get a zero cross section while demanding == 1
results in the same
result as before. Both count
and collect
can also take a condition
count if logical_expr [particles] collect if logical_expr [particles]
The result for these if
s is always the same as applying the select
filter
beforehand, see below.
- combine
-
combine [particles1, particles2] [particles1 + particles2]
This allows us to make a new subevent of composite particles. The composites
are generated by combining all particles from subevent particles1
with all
particles from subevent particles2
in all possible combinations while
overlapping combinations are excluded. In particular, if a composite particle in
the first argument has a constituent in common with a composite particle in the
second argument, the combination is dropped. So combine [incoming lepton, lepton]
constructs all mutual pairings of an incoming lepton with an outgoing
lepton, in case lepton
is an appropriate alias.
Thinking of subevents and the functions that act on them as streams, combine
fans
out the two given subevents opposed to the contraction of collect
. Note that
if particles1
and particles2
are one-entry subevents, combine
and
collect
actually give the same result, which can be confusing in the
beginning, but for larger subevents, the result is obviously different.
combine
also has an shorthand operator +
that can be used multiple times, e.g. [u + d + s]
.
Finally, this can also take a condition
combine if condition [particles1, particles2]
- cluster
-
cluster [particles] cluster if condition [particles]
cluster
clusters the given subevent or alias particles
to a new subevent
using the external FastJet
library. Variables that influence it are
jet_algorithm
, jet_r
, jet_p
and jet_ycut
.
- select
-
select if condition [particles] select if condition [particles, ref_particles]
select
can be used as a simple filter mechanism. The second argument is only
relevant for binary observables. Select particles if the condition is satisfied
for all reference particles.
- extract
-
extract [particles] extract index n [particles]
Return a one-entry subevent with either the first particle or the n
th
particle. This makes only sense on sort
ed subevents.
- sort
-
sort by observable [particles] sort by observable [particles, ref_particle]
sort
surprisingly sorts the subevent by increasing value of the observable. So if you want the highest values first, add a minus sign in front of your observable
.
- join
-
join [particles, new_particles]
Append the particles of new_particles
to particles
, i.e. join the two sets.
No overlapping entries will be produced.
join
has also a shorthand operator &
with the same syntax as +
.
Of course, you can chain all of these functions. So to get, e.g. a four jet cross section, you can write
cuts = count [cluster if E > 0 GeV [j]] > 3
Things to cut on
For convenience, we put here a table of observables that can also be found in the manual. All observables are either unary, i.e. take one argument, or binary, two arguments.
Observables | |
---|---|
M2 | unary: invariant mass squared of the (composite) particle |
binary: invariant mass squared of the sum of the two momenta | |
M | Signed square root of M2 : positive if M2 > 0, negative if M2 < 0
|
E | unary: energy of the particle |
binary: energy of the sum of the two momenta | |
Px , Py , Pz | like E but returns spatial components
|
P | like E but returns absolut value of spatial vector
|
Pt , Pl | like E but returns transversal and longitudinal momentum
|
Theta | unary: absolute polar angle in lab frame |
binary: angular distance of two particles in lab frame | |
Theta_star | binary: angular distance of two particles in rest frame of momentum sum |
Phi | unary: absolute azimuthal angle in lab frame |
binary: Azimuthal distance of two particles in lab frame | |
Rap , Eta | unary: Rapidity / Pseudorapidity |
binary: Rapidity / Pseudorapidity difference | |
Dist | binary: sqrt(DeltaEta^2 + DeltaPhi^2)
|
kT | binary: 2 * min(E_i^2,E_j^2)*(1-cos(Theta_{ij})
|
PDG | unary: PDG of particle (0 for composite particles) |
You will note that some binary versions are only convenience variants that avoid
to collect
or combine
momenta beforehand. So there are even more
possiblities to say the same thing, which can be confusing in the beginning.
Related topics
The pleasant thing about cuts
is that once you get the hang of it, you can
easily create histograms with analysis
or set scale
s as it uses a similar
syntax. For this, you need to chain in an eval
eval expr [particles] eval expr [particles1, particles2]
So the syntax is similar to the cuts
but this time expr
is usually a
real/floating expression instead of a logical/boolean one. With this you can,
e.g., build the following histograms
analysis = record pt_distribution (eval Pt [photon]) and record mval (eval M [lepton, lepton])
Analogously, you can set the scale
for alphas
to the hardest pt
with
scale = eval Pt [sort by -Pt [colored]]
Finally, there is also the possibility to apply an overall selection
before
events are analyzed or written to file. This does not affect the cuts
that are
used before matrix elements are even evaluated but applies to the complete
event, i.e. potentially with parton showers and hadronization:
selection = all Hel == 0 ["W+":"W-"]