Skip to content
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,9 @@ To apply formatting to a file:
```
clang-format -i -style=file /path/to/file.cpp
```
Note that this will reformat the entire file.
If you are preparing a PR, you can instead use
```
git clang-format --style=file $(git merge-base upstream/master HEAD)
```
to only format the lines you changed (otherwise you will reformat the entire file).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for figuring this out :)

Maybe (otherwise you will reformat the entire file) is a bit redundant, as the same information is a few lines above.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In any case, at some point we need to run formatter across the whole repository.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the description

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, maybe MR -> PR?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed (caught a long-term gitlab user :) )

55 changes: 44 additions & 11 deletions analyzers/dataframe/FCCAnalyses/MCParticle.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#define MCPARTICLE_ANALYZERS_H

#include <cmath>
#include <functional>
#include <vector>

#include "ROOT/RVec.hxx"
Expand Down Expand Up @@ -30,26 +31,49 @@ namespace MCParticle{
bool operator() (ROOT::VecOps::RVec<edm4hep::MCParticleData> in);
};

/// @brief Helper struct to select entries matching a certain predicate.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also provide an example of usage?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, sure - would you prefer this in the doxygen doc or on the PR?
The replacements for the selectors below this definition can serve as "inline" examples to refer to.

The general pattern is

struct mySelection: selByPredicate{
    mySelection(): selByPredicate(some_selection_function){}
};

Where some_selection_function is a function returning a "keep" decision for a given input object. Using lambda captures, the function can be configured with constructor arguments - for example, a configurable cut threshold.

This object can then be used to obtain a copy-vector of passed objects from an input object list, or a set of passing indices, or a set of passing element for each of a list of input index vectors.

The main motivation is that we save a lot of common boilerplate code when implementing selection functions (loop over containers, output allocation, copy operations, ...). The pattern also ensures that deep-copies are avoided where possible. We also gain the ability to apply the same selection functor transparently on index-based or copy-based selection logic, avoiding a need to duplicate logic if both are to be supported.

It would actually be more elegant to generalise this to a template consuming an arbitrary input object type, rather than being restricted to the MCParticleData class.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice explanation, I think having it in Doxygen would be the best. Would you also add an example how to use this when working with the dataframe in Python? I mean a snipped a user might write.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added explanation for doxygen, including snippets. Also moved the selByPredicate to Utils, making it available more generally than before.

/// Supports two signatures - either a list of candidates is passed and a list
/// of accepted candidates returned, Or a list of indices in a vector of
/// candidates is passed and a list of accepted indices returned. The latter
/// is more compatible with index-based selection logic.
struct selByPredicate {
selByPredicate(
std::function<bool(const edm4hep::MCParticleData &)> thePredicate)
: m_predicate(thePredicate) {}
std::function<bool(const edm4hep::MCParticleData &)> m_predicate;
ROOT::VecOps::RVec<edm4hep::MCParticleData>
operator()(const ROOT::VecOps::RVec<edm4hep::MCParticleData> &in);
ROOT::VecOps::RVec<int>
operator()(const ROOT::VecOps::RVec<int> &indices,
const ROOT::VecOps::RVec<edm4hep::MCParticleData> &in);
ROOT::VecOps::RVec<ROOT::VecOps::RVec<int>>
operator()(const ROOT::VecOps::RVec<ROOT::VecOps::RVec<int>> &indices,
const ROOT::VecOps::RVec<edm4hep::MCParticleData> &in);
};

/// select MCParticles with transverse momentum greater than a minimum value [GeV]
struct sel_pt {
struct sel_pt : selByPredicate {
sel_pt(float arg_min_pt);
float m_min_pt = 20; //> transverse momentum threshold [GeV]
ROOT::VecOps::RVec<edm4hep::MCParticleData> operator() (ROOT::VecOps::RVec<edm4hep::MCParticleData> in);
};

/// select MCParticles with absolute pseudorapidity less than a max value
struct sel_eta : selByPredicate {
sel_eta(float arg_max_eta);
};

/// select MCParticles with their status
struct sel_genStatus {
struct sel_genStatus : selByPredicate {
sel_genStatus(int arg_status);
int m_status = 1; //> Generator status
ROOT::VecOps::RVec<edm4hep::MCParticleData> operator() (ROOT::VecOps::RVec<edm4hep::MCParticleData> in);
};

/// select MCParticles with their PDG id
struct sel_pdgID {
struct sel_pdgID : selByPredicate {
sel_pdgID(int arg_pdg, bool arg_chargeconjugate);
int m_pdg = 13;
bool m_chargeconjugate = true;
ROOT::VecOps::RVec<edm4hep::MCParticleData> operator() (ROOT::VecOps::RVec<edm4hep::MCParticleData> in);
};

/// select MCParticles with a non-zero charge
struct sel_charged : selByPredicate {
sel_charged();
};

/// get MC history tree for a given MCParticle index
Expand Down Expand Up @@ -116,7 +140,6 @@ namespace MCParticle{
ROOT::VecOps::RVec<edm4hep::MCParticleData> in ,
ROOT::VecOps::RVec<int> ind);


/// return the parent index of a given list of MC particles
ROOT::VecOps::RVec<int> get_parentid(ROOT::VecOps::RVec<int> mcind, ROOT::VecOps::RVec<edm4hep::MCParticleData> mc, ROOT::VecOps::RVec<int> parents);

Expand Down Expand Up @@ -210,6 +233,16 @@ namespace MCParticle{
/// return the list of stable particles from the decay of a mother particle, looking at the full decay chain recursively. i is the mother index in the Particle block
std::vector<int> get_list_of_stable_particles_from_decay( int i, ROOT::VecOps::RVec<edm4hep::MCParticleData> in, ROOT::VecOps::RVec<int> ind) ;

/// return the list of stable particles from the decays of a mother particle,
/// looking at the full decay chain recursively. i is the list of mother
/// indices to process in the Particle block. Will return a vector of vectors
/// - each vector is the set of children for one of the mothers in the input
/// vector
ROOT::VecOps::RVec<ROOT::VecOps::RVec<int>>
get_lists_of_stable_particles_from_decays(
ROOT::VecOps::RVec<int> i, ROOT::VecOps::RVec<edm4hep::MCParticleData> in,
ROOT::VecOps::RVec<int> ind);

/// return the list of particles from the decay of a mother particle. i is the mother index in the Particle block.
std::vector<int> get_list_of_particles_from_decay( int i,
ROOT::VecOps::RVec<edm4hep::MCParticleData> in,
Expand Down
44 changes: 38 additions & 6 deletions analyzers/dataframe/FCCAnalyses/ReconstructedParticle2MC.h
Comment thread
kjvbrt marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,44 @@ namespace ReconstructedParticle2MC{
ROOT::VecOps::RVec<edm4hep::ReconstructedParticleData> reco,
ROOT::VecOps::RVec<edm4hep::MCParticleData> mc) ;

/// select ReconstructedParticles matched to the (stable) MC particles whose indices are passed in a list
ROOT::VecOps::RVec<edm4hep::ReconstructedParticleData> selRP_matched_to_list( ROOT::VecOps::RVec<int> mcParticles_indices,
ROOT::VecOps::RVec<int> recind,
ROOT::VecOps::RVec<int> mcind,
ROOT::VecOps::RVec<edm4hep::ReconstructedParticleData> reco,
ROOT::VecOps::RVec<edm4hep::MCParticleData> mc) ;
/// select ReconstructedParticles matched to the MC particles whose indices
/// are passed in a list
/// @param mcParticles_indices indices of the MC particles to look up
/// @param recind: reco index component of the MCRecoAssociations
/// @param mcind: mc index component of the MCRecoAssociations
/// @param reco: full reco particle list (ReconstructedParticles)
/// @param mc: full mc particle list (Particles)
/// @param require_stable: if set to true, will only match stable particles.
/// @return List of ReconstructedParticle candidates with length corresponding
/// to the number of *stable* MC particles in the mcParticles_indices vector.
/// In presence of unstable particles, no 1:1 correspondence. For
/// non-reconstructed stable MC particles, a dummy particle will be inserted.
/// If 1:1 length correspondence is required, set require_stable to false.
ROOT::VecOps::RVec<edm4hep::ReconstructedParticleData> selRP_matched_to_list(
const ROOT::VecOps::RVec<int> &mcParticles_indices,
const ROOT::VecOps::RVec<int> &recind,
const ROOT::VecOps::RVec<int> &mcind,
const ROOT::VecOps::RVec<edm4hep::ReconstructedParticleData> &reco,
const ROOT::VecOps::RVec<edm4hep::MCParticleData> &mc,
bool require_stable = true);
/// select indices of ReconstructedParticles matched to the MC particles whose
/// indices are passed in a list
/// @param mcParticles_indices indices of the MC particles to look up
/// @param recind: reco index component of the MCRecoAssociations
/// @param mcind: mc index component of the MCRecoAssociations
/// @param mc: full mc particle list (Particles)
/// @param require_stable: if set to true, will only match stable particles.
/// @return List of ReconstructedParticle candidates with length corresponding
/// to the number of *stable* MC particles in the mcParticles_indices vector.
/// In presence of unstable particles, no 1:1 correspondence. For
/// non-reconstructed stable MC particles, a "-1" entry will be inserted. If
/// 1:1 length correspondence is required, set require_stable to false.
ROOT::VecOps::RVec<int> selRP_indices_matched_to_list(
const ROOT::VecOps::RVec<int> &mcParticles_indices,
const ROOT::VecOps::RVec<int> &recind,
const ROOT::VecOps::RVec<int> &mcind,
const ROOT::VecOps::RVec<edm4hep::MCParticleData> &mc,
bool require_stable = true);

/// return the index of the MC particle that is associated to a given track (via the track-reco association)
int getTrack2MC_index ( int track_index,
Expand Down
Loading