Skip to content

Commit

Permalink
Add support for fastjet library
Browse files Browse the repository at this point in the history
  • Loading branch information
gagnonlg committed Sep 17, 2024
1 parent 5a420db commit 6e0a214
Show file tree
Hide file tree
Showing 10 changed files with 335 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ option(ACTS_BUILD_PLUGIN_DD4HEP "Build DD4hep plugin" OFF)
option(ACTS_BUILD_PLUGIN_PODIO "Build Podio plugin" OFF)
option(ACTS_BUILD_PLUGIN_EDM4HEP "Build EDM4hep plugin" OFF)
option(ACTS_BUILD_PLUGIN_FPEMON "Build FPE monitoring plugin" OFF)
option(ACTS_BUILD_PLUGIN_FASTJET "Build FastJet plugin" OFF)
option(ACTS_BUILD_PLUGIN_GEOMODEL "Build GeoModel plugin" OFF)
option(ACTS_BUILD_PLUGIN_TRACCC "Build Traccc plugin" OFF)
option(ACTS_BUILD_PLUGIN_GEANT4 "Build Geant4 plugin" OFF)
Expand Down Expand Up @@ -369,6 +370,9 @@ if(ACTS_BUILD_PLUGIN_JSON)
add_subdirectory(thirdparty/nlohmann_json)
endif()
endif()
if(ACTS_BUILD_PLUGIN_FASTJET)
find_package(FastJet REQUIRED)
endif()
if(ACTS_BUILD_PLUGIN_GEOMODEL)
find_package(GeoModelCore ${_acts_geomodel_version} REQUIRED CONFIG)
find_package(GeoModelIO ${_acts_geomodel_version} REQUIRED CONFIG)
Expand Down
1 change: 1 addition & 0 deletions Plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# independent plugins
add_component_if(ActSVG PluginActSVG ACTS_BUILD_PLUGIN_ACTSVG)
add_component_if(Cuda PluginCuda ACTS_BUILD_PLUGIN_CUDA)
add_component_if(FastJet PluginFastJet ACTS_BUILD_PLUGIN_FASTJET)
add_component_if(FpeMonitoring PluginFpeMonitoring ACTS_BUILD_PLUGIN_FPEMON)
add_component_if(Geant4 PluginGeant4 ACTS_BUILD_PLUGIN_GEANT4)
add_component_if(GeoModel PluginGeoModel ACTS_BUILD_PLUGIN_GEOMODEL)
Expand Down
16 changes: 16 additions & 0 deletions Plugins/FastJet/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
add_library(ActsPluginFastJet INTERFACE)

target_include_directories(
ActsPluginFastJet
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_link_libraries(ActsPluginFastJet INTERFACE FastJet)

install(
TARGETS ActsPluginFastJet
EXPORT ActsPluginFastJetTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(DIRECTORY include/Acts DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
71 changes: 71 additions & 0 deletions Plugins/FastJet/include/Acts/Plugins/FastJet/TrackJets.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// This file is part of the Acts project.
//
// Copyright (C) 2024 CERN for the benefit of the Acts project
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#pragma once

#include <Acts/Definitions/Units.hpp>

#include <optional>
#include <vector>

#include <fastjet/JetDefinition.hh>
#include <fastjet/PseudoJet.hh>

namespace Acts::FastJet {

template <typename TrackContainer>
class TrackJetSequence {
public:
/// Get all the track jets passing the pT & eta cuts
///
/// @param ptMin the minimum jet pT in GeV
/// @param etaMax the maximum jet absolute eta
///
/// @return a vector of fastjet::PseudoJet objects
std::vector<fastjet::PseudoJet> jets(float ptMin = 20 *
Acts::UnitConstants::GeV,
float etaMax = 2.5);

/// Get the tracks making up a track-jet
///
/// @param jet the jet from which to get the constituent tracks
/// @param coreR optional radius inside which to get the tracks
///
/// @return a vector of TrackProxy
std::vector<typename TrackContainer::TrackProxy> tracksInJet(
const fastjet::PseudoJet& jet, std::optional<float> coreR = {});

/// Main constructor, but using the "makeTrackJets" function is recommended
///
/// @param clusterSeq the fastjet::ClusterSequence object
/// @param inputTracks the input tracks that make up the sequence
TrackJetSequence(fastjet::ClusterSequence clusterSeq,
TrackContainer& inputTracks)
: m_clusterSeq{std::move(clusterSeq)}, m_inputTracks{inputTracks} {}

private:
fastjet::ClusterSequence m_clusterSeq;
TrackContainer& m_inputTracks;
};

/// Default jet definition: Anti-kt with a radius of 0.4
const fastjet::JetDefinition DefaultJetDefinition =
fastjet::JetDefinition(fastjet::antikt_algorithm, 0.4);

/// Create a sequence of track jets
///
/// @param tracks the input tracks
/// @jetDef the jet definition to use, defaults to "DefaultJetDefinition"
template <typename TrackContainer>
TrackJetSequence<TrackContainer> makeTrackJets(
TrackContainer& tracks,
fastjet::JetDefinition jetDef = DefaultJetDefinition);

} // namespace Acts::FastJet

#include "TrackJets.ipp"
60 changes: 60 additions & 0 deletions Plugins/FastJet/include/Acts/Plugins/FastJet/TrackJets.ipp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// This file is part of the Acts project.
//
// Copyright (C) 2024 CERN for the benefit of the Acts project
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <Acts/Definitions/Algebra.hpp>
#include <Acts/Definitions/Common.hpp>

template <typename TrackContainer>
Acts::FastJet::TrackJetSequence<TrackContainer> Acts::FastJet::makeTrackJets(
TrackContainer& tracks, fastjet::JetDefinition jetDef) {
std::vector<fastjet::PseudoJet> inputs;

for (std::size_t i = 0; i < tracks.size(); i++) {
typename TrackContainer::ConstTrackProxy track = tracks.getTrack(i);
Acts::Vector3 p = track.momentum();
float m = track.particleHypothesis().mass();

float px = p[Acts::eMom0];
float py = p[Acts::eMom1];
float pz = p[Acts::eMom2];
float e = std::sqrt(m * m + px * px + py * py + pz * pz);

inputs.emplace_back(px, py, pz, e);
inputs.back().set_user_index(i);
}

fastjet::ClusterSequence cs(inputs, jetDef);

return TrackJetSequence(std::move(cs), tracks);
}

template <typename TrackContainer>
std::vector<fastjet::PseudoJet>
Acts::FastJet::TrackJetSequence<TrackContainer>::jets(float ptMin,
float etaMax) {
fastjet::Selector sel_eta = fastjet::SelectorAbsEtaMax(etaMax);
return sel_eta(m_clusterSeq.inclusive_jets(ptMin));
}

template <typename TrackContainer>
std::vector<typename TrackContainer::TrackProxy>
Acts::FastJet::TrackJetSequence<TrackContainer>::tracksInJet(
const fastjet::PseudoJet& jet, std::optional<float> coreR) {
fastjet::Selector sel = fastjet::SelectorIdentity();
if (coreR.has_value()) {
sel = fastjet::SelectorCircle(coreR.value());
sel.set_reference(jet);
}

std::vector<typename TrackContainer::TrackProxy> tracks;
for (fastjet::PseudoJet& cst : sel(jet.constituents())) {
tracks.push_back(m_inputTracks.getTrack(cst.user_index()));
}

return tracks;
}
1 change: 1 addition & 0 deletions Tests/UnitTests/Plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_subdirectory_if(Cuda ACTS_BUILD_PLUGIN_CUDA)
add_subdirectory_if(Detray ACTS_BUILD_PLUGIN_TRACCC)
add_subdirectory_if(DD4hep ACTS_BUILD_PLUGIN_DD4HEP)
add_subdirectory_if(ExaTrkX ACTS_BUILD_PLUGIN_EXATRKX)
add_subdirectory_if(FastJet ACTS_BUILD_PLUGIN_FASTJET)
add_subdirectory_if(Geant4 ACTS_BUILD_PLUGIN_GEANT4)
add_subdirectory_if(GeoModel ACTS_BUILD_PLUGIN_GEOMODEL)
add_subdirectory_if(Json ACTS_BUILD_PLUGIN_JSON)
Expand Down
2 changes: 2 additions & 0 deletions Tests/UnitTests/Plugins/FastJet/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
set(unittest_extra_libraries ActsPluginFastJet)
add_unittest(TrackJetsTests TrackJetsTests.cpp)
139 changes: 139 additions & 0 deletions Tests/UnitTests/Plugins/FastJet/TrackJetsTests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// This file is part of the Acts project.
//
// Copyright (C) 2024 CERN for the benefit of the Acts project
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <boost/test/unit_test.hpp>

#include <Acts/Plugins/FastJet/TrackJets.hpp>

class ParticleHypothesis {
public:
float mass() { return 139.57061 * Acts::UnitConstants::MeV; }
};

class Track {
public:
Track(float pt, float eta, float phi) {
m_momentum[0] = pt * std::cos(phi);
m_momentum[1] = pt * std::sin(phi);
m_momentum[1] = pt * std::sinh(eta);
}
Acts::Vector3 momentum() const { return m_momentum; }
ParticleHypothesis particleHypothesis() const { return ParticleHypothesis(); }

private:
Acts::Vector3 m_momentum;
};

bool operator==(Track const& lhs, Track const& rhs) {
return lhs.momentum() == rhs.momentum();
}

class TrackContainer {
public:
using TrackProxy = Track;

TrackContainer() {}
void insert(Track track) { m_vec.push_back(std::move(track)); }
std::size_t size() { return m_vec.size(); }

using ConstTrackProxy = const Track&;
ConstTrackProxy getTrack(std::size_t i) {
if (i < size()) {
return m_vec[i];
}
throw std::runtime_error("Too few tracks");
}

private:
std::vector<Track> m_vec;
};

BOOST_AUTO_TEST_CASE(SingleTrack) {
TrackContainer tracks;
tracks.insert(Track(100, 0, 0));

Acts::FastJet::TrackJetSequence jetSeq = Acts::FastJet::makeTrackJets(tracks);
std::vector<fastjet::PseudoJet> jets = jetSeq.jets();

BOOST_CHECK_EQUAL(jets.size(), 1);
BOOST_CHECK_EQUAL(jets[0].constituents().size(), 1);
BOOST_CHECK_EQUAL(jets[0].constituents()[0].user_index(), 0);
BOOST_CHECK_CLOSE(jets[0].pt(), 100, 1e-3);
BOOST_CHECK_CLOSE(jets[0].eta(), 0, 1e-3);
BOOST_CHECK_CLOSE(jets[0].phi(), 0, 1e-3);
BOOST_CHECK_CLOSE(jets[0].m(), ParticleHypothesis().mass(), 1);
}

BOOST_AUTO_TEST_CASE(TwoTracksTwoJets) {
TrackContainer tracks;
tracks.insert(Track(100, 0, 0.0));
tracks.insert(Track(100, 0, M_PI));

Acts::FastJet::TrackJetSequence jetSeq = Acts::FastJet::makeTrackJets(tracks);
std::vector<fastjet::PseudoJet> jets = jetSeq.jets();

BOOST_CHECK_EQUAL(jets.size(), 2);

std::vector<Track> trks_0 = jetSeq.tracksInJet(jets[0]);
BOOST_CHECK_EQUAL(trks_0.size(), 1);
BOOST_CHECK(trks_0[0] == tracks.getTrack(0) ||
trks_0[0] == tracks.getTrack(1));

std::vector<Track> trks_1 = jetSeq.tracksInJet(jets[1]);
BOOST_CHECK_EQUAL(trks_1.size(), 1);
BOOST_CHECK(trks_1[0] == tracks.getTrack(0) ||
trks_1[0] == tracks.getTrack(1));
BOOST_CHECK(trks_0[0] != trks_1[0]);
}

BOOST_AUTO_TEST_CASE(TwoTracksOneJet) {
TrackContainer tracks;
tracks.insert(Track(100, 0, 0.0));
tracks.insert(Track(100, 0, 0.2));

Acts::FastJet::TrackJetSequence jetSeq = Acts::FastJet::makeTrackJets(tracks);
std::vector<fastjet::PseudoJet> jets = jetSeq.jets();

BOOST_CHECK_EQUAL(jets.size(), 1);

std::vector<Track> trks_0 = jetSeq.tracksInJet(jets[0]);
BOOST_CHECK_EQUAL(trks_0.size(), 2);
BOOST_CHECK(trks_0[0] == tracks.getTrack(0) ||
trks_0[0] == tracks.getTrack(1));
BOOST_CHECK(trks_0[1] == tracks.getTrack(0) ||
trks_0[1] == tracks.getTrack(1));
BOOST_CHECK(trks_0[0] != trks_0[1]);
}

BOOST_AUTO_TEST_CASE(TracksInJetCore) {
TrackContainer tracks;
tracks.insert(Track(100, 0, 0));
tracks.insert(Track(10, 0.05, 0));
tracks.insert(Track(10, -0.05, 0));
tracks.insert(Track(10, 0.2, 0));
tracks.insert(Track(10, -0.2, 0));

Acts::FastJet::TrackJetSequence jetSeq = Acts::FastJet::makeTrackJets(tracks);
std::vector<fastjet::PseudoJet> jets = jetSeq.jets();

BOOST_REQUIRE_EQUAL(jets.size(), 1);

std::vector<Track> trks = jetSeq.tracksInJet(jets[0], 0.1);
BOOST_CHECK_EQUAL(trks.size(), 3);

BOOST_CHECK(std::find(trks.begin(), trks.end(), tracks.getTrack(0)) !=
trks.end());
BOOST_CHECK(std::find(trks.begin(), trks.end(), tracks.getTrack(1)) !=
trks.end());
BOOST_CHECK(std::find(trks.begin(), trks.end(), tracks.getTrack(2)) !=
trks.end());
BOOST_CHECK(std::find(trks.begin(), trks.end(), tracks.getTrack(3)) ==
trks.end());
BOOST_CHECK(std::find(trks.begin(), trks.end(), tracks.getTrack(4)) ==
trks.end());
}
40 changes: 40 additions & 0 deletions cmake/FindFastJet.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Find the FastJet includes and libraries.

find_library(FastJet_LIBRARY NAMES FastJet fastjet DOC "The FastJet library")

find_path(
FastJet_INCLUDE_DIR
fastjet/version.hh
DOC "The FastJet include directory"
)

file(READ "${FastJet_INCLUDE_DIR}/fastjet/config_auto.h" FastJet_VERSION_FILE)
string(
REGEX MATCH
"#define FASTJET_PACKAGE_VERSION \"([0-9]+\.[0-9]+\.[0-9]+)\""
_
${FastJet_VERSION_FILE}
)

set(FastJet_VERSION ${CMAKE_MATCH_1})

find_package_handle_standard_args(
FastJet
REQUIRED_VARS FastJet_LIBRARY FastJet_INCLUDE_DIR
VERSION_VAR FastJet_VERSION
)

add_library(FastJet SHARED IMPORTED)
set_property(TARGET FastJet PROPERTY IMPORTED_LOCATION ${FastJet_LIBRARY})
set_property(
TARGET FastJet
PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${FastJet_INCLUDE_DIR}
)

mark_as_advanced(FastJet_FOUND FastJet_INCLUDE_DIR FastJet_LIBRARY)

if(FastJet_FOUND)
message(STATUS "Found FastJet ${FastJet_VERSION} at ${FastJet_LIBRARY}")
else()
message(FATAL_ERROR "FastJet not found")
endif()
1 change: 1 addition & 0 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ components.
| ACTS_BUILD_PLUGIN_PODIO | Build Podio plugin<br> type: `bool`, default: `OFF` |
| ACTS_BUILD_PLUGIN_EDM4HEP | Build EDM4hep plugin<br> type: `bool`, default: `OFF` |
| ACTS_BUILD_PLUGIN_FPEMON | Build FPE monitoring plugin<br> type: `bool`, default: `OFF` |
| ACTS_BUILD_PLUGIN_FASTJET | Build FastJet plugin<br> type: `bool`, default: `OFF` |
| ACTS_BUILD_PLUGIN_GEOMODEL | Build GeoModel plugin<br> type: `bool`, default: `OFF` |
| ACTS_BUILD_PLUGIN_TRACCC | Build Traccc plugin<br> type: `bool`, default: `OFF` |
| ACTS_BUILD_PLUGIN_GEANT4 | Build Geant4 plugin<br> type: `bool`, default: `OFF` |
Expand Down

0 comments on commit 6e0a214

Please sign in to comment.