Falaise  3.3.0
SuperNEMO Software Toolkit
FLReconstruct Pipeline Output

Table of Contents

Introduction

The current official reconstruction pipeline consists in several steps, each responsible of the elaboration of additional informations stored in dedicated banks in the event record. We saw in the tutorial on FLSimulate output that the Monte-Carlo program creates a new data bank in the event record (a datatools::things object) which is keyed SD (S imulated D ata).

Once the FLSimulate output file is generated, it can be used as the input of the FLReconstruct program. We describe here the contents of the reconstruction data banks added by the reconstruction pipeline.

+----------------------------------+
| Event record (datatools::things) |
+----------------------------------+
|
+----------------+------+-------+-------+- - - - ?
| | | | |
+----+ : +----+ +-----+ +-----+ +-----+
| SD | : | CD | | TCD | | TTD | | PTD |
+----+ : +----+ +-----+ +-----+ +-----+
/ : \ \ / /
/ : \ \ / /
+------+------+ : +--+----+--+-----+-+
| Monte-Carlo | : | Reconstruction |
| output | : | outputs |
+-------------+ : +------------------+

The shared handle concept

Before to describe the SuperNEMO reconstruction banks, we explain the shared handle concept, a special kind of reference to an arbitrary object. A shared handle is implemented through the datatools::handle<T> template class, where T is an arbitrary class. It is based on the template boost::shared_ptr<T> smart pointer class from the Boost library (note: this concept is also available in C++11, however we don't use this implementation in the SuperNEMO software yet).

The shared handle is a special kind of pointer which is responsible of the memory management of the object it handles. More, it is able to share the handle to this object with as many as other shared handles of the same type. As long as at least one shared handle points to the object, the object is still managed in memory and thus accessible. When, and only when, the last shared handle on a given object is destroyed, the object itself is finally discarded from the memory. This mechanism is implemented using some hidden reference counter.

Below we represent a shared handle [h] that originaly points to an object which has been dynamically allocated in memory (typically through the new C++ operator):

+-------[1]
[h]------>| Object |
+--------+

As it is the only shared handle refering to this object (see the [1] counter on the top right corner of the box), when the [h] handle is destroyed (we use here the [~h] symbol), this automatically discards the object (using the ~Object to represent the deletion process):

+------[1=>0]
[~h]~ ~ ~ | ~Object | ======> {nothing is left in memory}
+---------+

Now suppose we have a second shared handle [h'] that now enters the game and points to the same object than [h] :

+-------[2]
[h]------>| Object |<------[h']
+--------+

If we destroy [h], the object will be not destroyed because there is still one shared handle that refers to it, namely [h'], which now becomes the responsible of the memory management of the object:

+-----[2=>1] +-------[1]
[~h]~ ~ ~ | Object |<------[h'] ======> | Object |<------[h']
+--------+ +--------+

Many SuperNEMO data models make use of this technique to manipulate data structures of interest: hits, clusters of hits, tracks... whatever data banks refer to these objects. This enables the sharing of such objects from within various data banks. We don't have to care about who or what is responsible of the memory management.

The illustration below illustrates a typical case where a CD and a TCD banks refer to the same pool of Geiger hits (the [h?] represent shared handle objects):

+----------------------------------+
| Event record (datatools::things) |
+----------------------------------+
|
+-------------------------+
| |
+----+ +-----+
| CD | | TCD |
+----+ +-----+
| |
| +---------------[h0]-------------[h1]
| | | |
| | v v
| +-------------+ +------------+ +------------+
| | Unclustered | | Cluster #0 | | Cluster #1 |
| +-------------+ +------------+ +------------+
| | | |
| +----------[2] | | |
[ha]--->| GG Hit #0 |<----[hA] | |
| +-----------+ | |
| +----------[2] | |
[hb]--->| GG Hit #1 |<---------------------[hB] |
| +-----------+ | |
| +----------[2] | |
[hc]--->| GG Hit #2 |<---------------------[hC] |
| +-----------+ | |
| +----------[3] | |
[hd]--->| GG Hit #3 |<---------------------[hD] /--------[hE]
| +-----------+<----------------------------/ |
| +----------[2] |
[he]--->| GG Hit #4 |<--------------------------------------[hF]
| +-----------+ |
| +----------[2] |
[hf]--->| GG Hit #5 |<--------------------------------------[hG]
+-----------+

If we destroy the CD bank from the event record, this will destroy the shared handles ha, hb, hc, hd, he and hf. However, as Geiger hits objects from #0 to #5 are also refered by other shared handles from the TCD bank, they are not deleted :

+----------------------------------+
| Event record (datatools::things) |
+----------------------------------+
|
+-----+
| TCD |
+-----+
|
+---------------[h0]-------------[h1]
| | |
| v v
+-------------+ +------------+ +------------+
| Unclustered | | Cluster #0 | | Cluster #1 |
+-------------+ +------------+ +------------+
| | |
+----------[1] | | |
| GG Hit #0 |<----[hA] | |
+-----------+ | |
+----------[1] | |
| GG Hit #1 |<---------------------[hB] |
+-----------+ | |
+----------[1] | |
| GG Hit #2 |<---------------------[hC] |
+-----------+ | |
+----------[2] | |
| GG Hit #3 |<---------------------[hD] /--------[hE]
+-----------+<----------------------------/ |
+----------[1] |
| GG Hit #4 |<--------------------------------------[hF]
+-----------+ |
+----------[1] |
| GG Hit #5 |<--------------------------------------[hG]
+-----------+

If we now remove the cluster #0 from the TCD bank, the Geiger hits #1 and #2 are destroyed but the other ones are preserved, protected by their shared handles:

+----------------------------------+
| Event record (datatools::things) |
+----------------------------------+
|
+-----+
| TCD |
+-----+
|
+---------------[h1]
| |
| v
+-------------+ +------------+
| Unclustered | | Cluster #1 |
+-------------+ +------------+
| |
+----------[1] | |
| GG Hit #0 |<----[hA] |
+-----------+ |
+----------[1] |
| GG Hit #3 |<---------------------[hE]
+-----------+ |
+----------[1] |
| GG Hit #4 |<---------------------[hF]
+-----------+ |
+----------[1] |
| GG Hit #5 |<---------------------[hG]
+-----------+

That means that even if we completely remove some banks from the event record, as long as some shared handles will point to a given object from other data banks, the object will be preserved from deletion and will remain usable at any processing stage of the pipeline. This technique is non only safe with respect to memory management, it is also fully supported by the Boost/Serialization library which is the base of the Falaise I/O system.

Mock digitization and calibration

Both mock digitization and calibration modules snemo::processing::mock_tracker_s2c_module and snemo::processing::mock_calorimeter_s2c_module create and fill the CD bank (C alibrated D ata). The CD bank contains a snemo::datamodel::calibrated_data object.

Each snemo::datamodel::calibrated_data object contains:

Tracker clustering

Whatever tracker clustering module is used (snemo::reconstruction::mock_tracker_clustering_module, snemo::reconstruction::cat_tracker_clustering_module or snemo::reconstruction::sultan_tracker_clustering_module), it create and fill the TCD bank (T racker C lustering D ata). The TCD bank contains a snemo::datamodel::tracker_clustering_data object.

Each snemo::datamodel::tracker_clustering_data object contains:

Each snemo::datamodel::tracker_clustering_solution object contains:

Each snemo::datamodel::tracker_cluster object contains:

Track fitting

A track fitting algorithm tries to fit a line or an helix to a given cluster provided from the TCD bank. It creates and fills the TTD bank (T racker T rajectory D ata). The TTD bank contains a snemo::datamodel::tracker_trajectory_data object.

Each snemo::datamodel::tracker_trajectory_data object contains:

Each snemo::datamodel::tracker_trajectory_solution object contains:

Each snemo::datamodel::tracker_trajectory object contains:

Two types of trajectory patterns are supported:

Both classes inherit the snemo::datamodel::base_trajectory_pattern classes.

A snemo::datamodel::line_trajectory_pattern contains:

A snemo::datamodel::helix_trajectory_pattern contains:

Charged particle measurements

A module dedicated to measurements of charged particles tries to compute some useful informations associated to a given trajectory. The ChargedParticleTracking plugin provides such a module: snemo::reconstruction::charged_particle_tracking_module. This module is able to perform several measurements of interest on the trajectories that have been fitted during the previous track fitting process:

It used the CD and TTD banks as its input and creates and fills the PTD bank (P article T rack D ata). The PTD bank contains a snemo::datamodel::particle_track_data object.

TODO: