Skip to content

Commit

Permalink
Add partial documentation on intended usage and design
Browse files Browse the repository at this point in the history
  • Loading branch information
tmadlener committed Jul 5, 2024
1 parent fa0e994 commit 98fa6b1
Showing 1 changed file with 178 additions and 0 deletions.
178 changes: 178 additions & 0 deletions doc/VertexRecoParticleRecos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# The relations and associations between `Vertex` and `ReconstructedParticle`

The `Vertex` and the `ReconstructedParticle` have relations that can in
principle form a loop:
- The `Vertex` has a `OneToManyRelation` to `particles`
- The `ReconstructedParticle` has a `OneToOneRelation` to a `startVertex`
- The `RecoParticleVertexAssociation` is an association that links both

Since this has the potential for some confusion this document gives a brief
overview of the main design principles for EDM4hep and also shows the intended
way of using all of these. Additionally, this is one of the places where EDM4hep
is conceptually different than LCIO. Hence, we will also show how the two
concepts map to each other.

## Design principles

The major design principle was *make it possible to create each collection in
separate steps **without having to mutate collections once they have been
created***. The latter part is the most important one, as it is imposed by
EDM4hep's mutability concept. As a consequence, filling the relation information
should follow these main guidelines
- the decay particles that form a `Vertex` should be added to the `particles`.
Hence, a `Vertex` can always be queried for those
- a `ReconstructedParticle` that decayed at a given `Vertex` should point to
this `Vertex` via the `decayVertex`. It is then always possible to get the
decay produces via `getDecayVertex().getParticles()`.
- in order to allow navigation from a decay particle to the vertex it originated
from a `RecoParticleVertexAssociation` should be created. If no such
navigation is necessary, creating these associations can also be omitted.

## Using `Vertex` and (high level) `ReconstructeParticle` objects

The following examples show a few use cases and how to achieve them. We assume
that the following variables are defined externally somehow
- `particle` is a `edm4hep::ReconstructeParticle`. This denotes a decaying particle
- `startVtxAssocs` is a `edm4hep::RecoParticleVertexAssociationCollection`
- `reco` is a `edm4hep::ReconstructedParticle`. This denotes a decay particle,
i.e. it was used as an input to vertexing.

### Getting all decay particles from a `ReconstructedParticle`

```cpp
const auto vtx = particle.getDecayVertex()
const auto decayParticles = vtx.getParticles();
```

### Getting the start vertex for a decay particle

This is a small helper function that encapsulates the main functionality

```cpp
std::optional<edm4hep::Vertex> getStartVertex(edm4hep::ReconstructedParticle p,
const edm4hep::RecoParticleVertexAssociationCollection& assocs) {
for (const auto assoc : assocs) {
if (assoc.getRec() == rec) {
return assoc.getVertex();
}
}
return std::nullopt;
}
```
## Creating `Vertex` and (high level) `ReconstructedParticle` objects
In the following examples we will assume, that we have a list of
`ReconstructedParticle`s that we want to use in vertexing. We will produce the
following outputs
- a `Vertex` collection, containing all the vertices that we could find.
- a `ReconstructedParticle` collection, that represent the particles that
decayed at these vertices. Each of them will have exactly one `decayVertex`
attached to them.
- a `RecoParticleVertexAssociation` collection that links each of the input
`ReconstructedParticle`s back to the `Vertex` from which they emerged.
All of the steps will use function stubs whereever necessary and will mainly
focus on setting the relations / associations.
### 1. Creating vertices
The main point here is to attach the decay particles to the `particles` field of
each `Vertex`. In this example we will assume that that is not already done by
the `magicVertexing` function; mainly to make this part very explicit.
```cpp
// This is a possible signature that works in the example below
std::vector<std::pair<edm4hep::Vertex, std::vector<edm4hep::ReconstructedParticle>>
magicVertexing(const edm4hep::ReconstructedParticleCollection&);
edm4hep::VertexCollection createVertices(const edm4hep::ReconstructedParticleCollection& particles) {
auto vertices = edm4hep::VertexCollection{};
// magicVertexing returns
for (const auto& [vtx, decayParticles] : magicVertexing(particles)) {
for (const auto p : decayParticles) {
vtx.addToParticles(p);
}
vertices.push_back(vtx);
}
return vertices;
}
```

### 2. Creating high level reconstruction particles

This is the most simplest implementation possible. It simply sums up all four
vectors of the decay particles and sets that into the newly created particles.
Again, this is mainly done for illustration purposes, as the important part is
the relation setting.

```cpp
// This is a possible signature for that works in the example below
edm4hep::LorentzVectorM sumFourMomenta(const podio::RelationRange<edm4hep::ReconstructedParticle>&);

edm4hep::ReconstructedParticleCollection createVertexRecos(const edm4hep::VertexCollection& vertices) {
auto recos = edm4hep::ReconstructedParticleCollection{};
for (const auto vtx : vertices) {
auto reco = recos.create();
reco.setDecayVertex(vtx);

auto fourMom = sumFourMomenta(vtx.getParticles());
reco.setMass(fourMom.M());
reco.setMomentum(fourMom.X(), fourMom.Y(), fourMom.Z());
}

return recos;
}
```
### 3. Creating start vertex associations
This is a potentially optional step, depending on whether it is necessary to
allow for easier navigation from the particles back to their start vertices.
```cpp
edm4hep::RecoParticleVertexAssociationCollection(const edm4hep::VertexCollection& vertices) {
auto startVtxAssocs = edm4hep::RecoParticleVertexAssociationCollection{};
for (const auto vtx : vertices) {
for (const auto particle : vtx.getParticles()) {
auto assoc = startVtxAssocs.create();
assoc.setVertex(vtx);
assoc.setRec(particle);
}
}
return startVtxAssocs;
}
```


## EDM4hep vs LCIO

### The concept in LCIO

In LCIO the `Vertex` and `ReconstructedParticle` have similar but slightly
different relations (we will express them in podio/EDM4hep terminology here):
- a `Vertex` has a `OneToOneRelation` to an `associatedParticle`
- a `ReconstructeParticle` has a `OneToOneRelation` to a `startVertex`
- there is a similar association (`LCRelation`) between `Vertex` and
`ReconstructedParticle` as in EDM4hep

The intended way to fill these in LCIO is
- a `Vertex` points back to the particle that decayed via the
`associatedParticle`
- the `associateParticle` has the decay products in its `particles` relation
- each of the decay particles points back to the `Vertex` via the `startVertex`
relation.

The main issue with this format is, that it's impossible to fill this
information in the EDM4hep mutability model without either
- doing the reconstruction of all particles, the vertexing and the high level
reconstruction in one step
- or cloning collections of objects several times in order to be able to fill
all the information consistently

### In LCIO I do this, how do I do it in EDM4hep?

- [ ] TODO

0 comments on commit 98fa6b1

Please sign in to comment.