Rivet tutorials

Projections

Projections are arguably the most important objects in Rivet - they’re certainly the part that does most of the work. A projection is an object which calculates a property or properties from an Event. Such properties can be a single number (e.g. multiplicity in a certain phase space), a single complex object (e.g. sphericity tensor) or a list of such objects (e.g. a set of boosted jets or charged particles).

In case you’re confused by the name, “projection” was chosen since their task is to project out quantities of interest from the complexities of whole events - they don’t strictly obey the definition of an algebraic projection operator!

A few details about projections

All Rivet projections inherit from the abstract Projection class, which defines the interface elements supported by all projections. You don’t need to worry about this too much - it basically forces you to supply project() and compare() methods which can be used polymorphically by Rivet’s internal mechanisms.

The projections are used by Analysis objects. Internally, projections are compared via the Projection::compare(...) method which allows duplicate instantiations of the same projection to be avoided - as a result, the second (and so on) time a given projection is called for a particular event, it will simply return its cached value rather than repeating the computation.

Specific projections

Here are some examples of projections available in the current release of Rivet:

How to use projections

For this example we’ll use the FinalState projection in an analysis. The analysis file (or its header, if you’re using one) must include the interface of FinalState, with a #include "Rivet/Projections/FinalState.hh" directive.

Create and initialize projections in the analysis init method:

void init() {
  FinalState fs(Cuts::abseta < 1.0, Cuts::pT > 0.5*GeV);
  declare(fs, "FS");
  declare(Multiplicity(fs), "Mult");
  declare(Thrust(fs), "Thrust");
}

Then, when using the projection, you’ll probably want to have something like this in the analyze(...) method:

void MyAnalysis::analyze(const Event& e) {
  ...
  // Project into final state
  const FinalState& fs = apply<FinalState>(e, "FS");
  ...
}

Note that it’s good practice to make the returned projection a const reference – this guarantees that the cached result will remain unchanged between repeated calls, perhaps in distinct analyses.

If using a projection inside another projection, the same applies for initialising it in the constructor of the “client” class, and the use of the projection on each event should be in the body of the MyProjection::project(...) method.

Writing a projection

The best documentation when writing a projection is to look at some existing ones and use them as templates - pick a short one like ChargedFinalState or Beam since their structure is easier to see. Issues to be particularly aware of include: