Learn how to associate information from distinct tables through index columns and index tables
Executable: o2-analysistutorial-associated-derived
Index columns and index tables
Related information can be contained in different tables. And in order to associate this informations index columns and index tables are used.
ProduceEtaPhi, ProduceColExtra, and ConsumeEtaPhi
The tutorial example starts with the declaration and production of three tables, EtaPhi and CollisionsExtra, which are normal tables, and HMPIDTracksIndex, an index table.
The index table HMPIDTracksIndex contains for each row of table Tracks the row number of table HMPIDs with the related HMPID information.
DECLARE_SOA_INDEX_TABLE_USER(HMPIDTracksIndex, Tracks, "HMPIDTRKIDX", indices::TrackId, indices::HMPIDId);
ConsumeColExtra
In task ConsumeColExtra the basic usage of indices is demonstrated. Tracks are associated to collisions via the index column o2::aod::track::CollisionId (see the declaration of the Tracks table). Access to the collsion associated with a given track track0 is achieved with track0.collision_as<T>(), where T is a table including the Collisions table (see also tutorial [Creating Tables] (creatingTables.md#declaration-of-columns)). In the example case T is a Join of Collisions and CollisionsExtra.
struct ConsumeColExtra {
// use collisions with > 10 tracks only
using myCol = soa::Join<aod::Collisions, aod::CollisionsExtra>;
expressions::Filter multfilter = aod::collision::mult > 10;
// group tracks according to collision
void process(soa::Filtered<myCol>::iterator const& col, aod::Tracks const& tracks)
{
// get collision index and track multiplicity from the collisions ...
LOGF(INFO, "[direct] ID: %d; %d == %d", col.globalIndex(), col.mult(), tracks.size());
if (tracks.size() > 0) {
// ... or through an associated track.
auto track0 = tracks.begin();
LOGF(INFO, "[index ] ID: %d; %d == %d", track0.collision_as<myCol>().globalIndex(), track0.collision_as<myCol>().mult(), tracks.size());
}
}
};
PartitionColExtra
Index columns allow to easily select e.g. all tracks belonging to a given collision using the sliceBy()
method (see also DECLARE_SOA_TABLE). groupedTracks contains only tracks which belong to Collision col.
The slicing needs to be pre-declared using Preslice
(or PresliceUnsorted
if the index is not sorted) so that the framework can prepare and add it to the internal cache.
struct Task {
Preslice<aod::Tracks> perCol = aod::track::collisionId;
void proces(aod::Collisions const & cols, aod::Tracks const& tracks) {
for (auto& col : cols) {
auto groupedTracks = tracks.sliceBy(perCol, col.globalIndex());
}
}
}
BuildHmpidIndex and ConsumeHmpidIndex
Builds<T> is used to prepare an index column of type T. This has to be performed before the index table can be used. Note the declaration of the init() function without any content. This is needed to make the task complete (see minimum requirements for a task).
struct BuildHmpidIndex {
// build the index table HMPIDTracksIndex
Builds<aod::HMPIDTracksIndex> idx;
void init(InitContext const&){};
};
In the following loop the index table is used to relate the information from the Tracks table with the related rows of the HMPID table. To check if a given track has related HMPID information the has_hmpid() method is applied. This returns true in case the HMPID information exists and the method hmpid() can be used to retrieve the associated row of the HMPIDs table.
for (auto& track : tracks) {
// check weather given track has associated HMPID information
if (track.has_hmpid()) {
// access the HMIPD information associated with the actual track
LOGF(INFO, "Track %d has HMPID info: %.2f", track.globalIndex(), track.hmpid().hmpidSignal());
}
}