Commit 59b8d0dd authored by Adam Edward Barton's avatar Adam Edward Barton
Browse files

Merge branch 'IntroducingACTSSeedingIntoAthena' into 'master'

ATLIDTRKCP-354: Introducing ACTS seeding into Athena

See merge request atlas/athena!47319
parents e76fb355 4d7e5a8b
/*
Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
*/
#ifndef ACTSINTERFACES_IACTSSEEDINGTOOL_U
#define ACTSINTERFACES_IACTSSEEDINGTOOL_U 1
// Athena
#include "GaudiKernel/IAlgTool.h"
#include "GaudiKernel/EventContext.h"
#include "BeamSpotConditionsData/BeamSpotData.h"
#include "Acts/MagneticField/MagneticFieldContext.hpp"
// ACTS EDM
#include "ActsEDM/ActsSpacePoint.h"
#include "ActsEDM/ActsSeed.h"
namespace ActsTrk {
class IActsSeedingTool
: virtual public IAlgTool {
public:
DeclareInterfaceID(IActsSeedingTool, 1, 0);
virtual
StatusCode
createSeeds(const EventContext& ctx,
const ActsTrk::SpacePointContainer& spContainer,
const InDet::BeamSpotData& beamSpotData,
const Acts::MagneticFieldContext& magFieldContext,
ActsTrk::SeedContainer& seedContainer ) const = 0;
};
} // namespace
#endif
# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
# Declare the package name:
atlas_subdir( ActsTrkFinding )
# External dependencies:
find_package( Acts COMPONENTS Core )
atlas_add_library( ActsTrkFindingLib
PUBLIC_HEADERS ActsTrkFinding
LINK_LIBRARIES
GaudiKernel
BeamSpotConditionsData
ActsCore
ActsEDM
)
atlas_add_component( ActsTrkFinding
src/*.h
src/*.cxx
src/components/*.cxx
LINK_LIBRARIES ActsTrkFindingLib ActsInteropLib MagFieldConditions)
# Install files from the package:
atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} )
# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
from AthenaConfiguration.ComponentFactory import CompFactory
from ActsTrkFinding.ActsSeedingToolConfig import ActsSeedingToolCfg
def ActsSeedingAlgorithmCfg(ConfigFlags,
name: str = 'ActsSeedingAlgorithm',
inputCollection: str = '',
outputCollection: str = '',
**options):
assert isinstance(inputCollection, str)
assert isinstance(outputCollection, str)
acc = ComponentAccumulator()
# tools
# check if options have already the seed tool defined
# and make sure it is not a None
seedTool = None
if options.get("SeedTool", None) is None:
seedingToolOptions = options.get('seedingToolOptions', {})
seedTool = acc.popToolsAndMerge(ActsSeedingToolCfg(ConfigFlags,
name = 'ActsSeedingTool',
inputCollection = inputCollection,
**seedingToolOptions))
# Remove keys not required by the Algorithm
options.pop('seedingToolOptions', None)
options['name'] = f"{name}_{inputCollection}"
options.setdefault('SeedTool', seedTool)
options.setdefault('BeamSpotKey', 'BeamSpotData')
options.setdefault('AtlasFieldCacheCondObj', 'fieldCondObj')
options.setdefault('InputSpacePoints', inputCollection)
options.setdefault('OutputSeeds', outputCollection)
ActsTrk__ActsSeedingAlgorithm = CompFactory.getComp(f"ActsTrk::{name}")
acc.addEventAlgo(ActsTrk__ActsSeedingAlgorithm(**options))
return acc
# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
from AthenaConfiguration.ComponentFactory import CompFactory
from ActsInterop import UnitConstants
def ActsSeedingToolCfg(ConfigFlags,
name: str = 'ActsSeedingTool',
inputCollection: str = "",
**options):
assert isinstance(inputCollection, str)
acc = ComponentAccumulator()
options['name'] = f"{name}_{inputCollection}"
options.setdefault('rMax', 200. * UnitConstants.mm)
options.setdefault('deltaRMin', 5. * UnitConstants.mm)
options.setdefault('deltaRMax', 60. * UnitConstants.mm)
options.setdefault('collisionRegionMin', -250. * UnitConstants.mm)
options.setdefault('collisionRegionMax', 250. * UnitConstants.mm)
options.setdefault('zMin', -2000 * UnitConstants.mm)
options.setdefault('zMax', 2000 * UnitConstants.mm)
options.setdefault('maxSeedsPerSpM', 1)
options.setdefault('cotThetaMax', 7.40627)
options.setdefault('sigmaScattering', 5)
options.setdefault('radLengthPerSeed', 0.5)
options.setdefault('minPt', 500. * UnitConstants.MeV)
options.setdefault('impactMax', 3 * UnitConstants.mm)
ActsTrk__ActsSeedingTool = CompFactory.getComp(f"ActsTrk::{name}")
acc.setPrivateTools(ActsTrk__ActsSeedingTool(**options))
return acc
# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
from AthenaCommon.Configurable import ConfigurableRun3Behavior
from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
from AthenaConfiguration.ComponentAccumulator import CAtoGlobalWrapper
from ActsTrkFinding.ActsSeedingAlgorithmConfig import ActsSeedingAlgorithmCfg
def ActsTrackingSequenceCfg(ConfigFlags,
inputCollections: list = []):
# prepare entire sequence
with ConfigurableRun3Behavior():
acc = ComponentAccumulator()
for i_collection in inputCollections:
o_collection = f"ActsSeeds_{i_collection}"
acc.merge(ActsSeedingAlgorithmCfg(ConfigFlags,
name = 'ActsSeedingAlgorithm',
inputCollection = i_collection,
outputCollection = o_collection))
# Set OutputLevel can be set with the following piece of code
# This will set the Outputl Level of all the algorithms and Tools to
# a defined value
#
# from AthenaCommon.Constants import DEBUG
# for el in acc._allSequences:
# for member in el.Members:
# member.OutputLevel = DEBUG
# the following is needed to reliably determine whether we're really being steered from an old-style job option
# assume we're running CPython
import inspect
stack = inspect.stack()
if len(stack) >= 2 and stack[1].function == 'CAtoGlobalWrapper':
for el in acc._allSequences:
el.name = "TopAlg"
return acc
def ActsTrackingSequenceToAthena(ConfigFlags,
inputCollections: list = []):
options = {}
options['inputCollections'] = inputCollections
with ConfigurableRun3Behavior():
CAtoGlobalWrapper(ActsTrackingSequenceCfg, ConfigFlags, **options)
/*
Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
*/
#include "src/ActsSeedingAlgorithm.h"
// ACTS
#include "Acts/Definitions/Units.hpp"
#include "Acts/MagneticField/MagneticFieldContext.hpp"
#include "ActsGeometry/ATLASMagneticFieldWrapper.h"
#include "Acts/Seeding/BinFinder.hpp"
#include "Acts/Seeding/BinnedSPGroup.hpp"
#include "Acts/Seeding/SeedFilter.hpp"
#include "Acts/Seeding/Seedfinder.hpp"
#include "TrkSpacePoint/SpacePointCollection.h"
namespace ActsTrk {
ActsSeedingAlgorithm::ActsSeedingAlgorithm( const std::string &name,
ISvcLocator *pSvcLocator )
: AthReentrantAlgorithm( name,pSvcLocator )
{}
StatusCode ActsSeedingAlgorithm::initialize() {
ATH_MSG_INFO( "Initializing " << name() << " ... " );
// Retrieve seed tool
ATH_CHECK( m_seedsTool.retrieve() );
// Cond
ATH_CHECK( m_beamSpotKey.initialize() );
ATH_CHECK( m_fieldCondObjInputKey.initialize() );
// Read nd Write handles
ATH_CHECK( m_spacePointKey.initialize() );
ATH_CHECK( m_seedKey.initialize() );
return StatusCode::SUCCESS;
}
StatusCode ActsSeedingAlgorithm::execute(const EventContext& ctx) const {
ATH_MSG_DEBUG( "Executing " << name() <<" ... " );
// ================================================== //
// ===================== CONDS ====================== //
// ================================================== //
// Read the Beam Spot information
SG::ReadCondHandle<InDet::BeamSpotData> beamSpotHandle { m_beamSpotKey, ctx };
ATH_CHECK( beamSpotHandle.isValid() );
if (beamSpotHandle.cptr() == nullptr) {
ATH_MSG_ERROR("Retrieved Beam Spot Handle contains a nullptr");
return StatusCode::FAILURE;
}
auto beamSpotData = beamSpotHandle.cptr();
// Read the b-field information
SG::ReadCondHandle<AtlasFieldCacheCondObj> readHandle { m_fieldCondObjInputKey, ctx };
ATH_CHECK( readHandle.isValid() );
const AtlasFieldCacheCondObj* fieldCondObj{ *readHandle };
if (fieldCondObj == nullptr) {
ATH_MSG_ERROR("Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCondObjInputKey.key());
return StatusCode::FAILURE;
}
// Get the magnetic field
// Using ACTS classes in order to be sure we are consistent
Acts::MagneticFieldContext magFieldContext(fieldCondObj);
// ================================================== //
// ===================== INPUTS ===================== //
// ================================================== //
ATH_MSG_DEBUG( "Retrieving Input Collection '" << m_spacePointKey.key() << "' ..." );
SG::ReadHandle< ActsTrk::SpacePointContainer > handle = SG::makeHandle( m_spacePointKey, ctx );
ATH_CHECK( handle.isValid() );
const ActsTrk::SpacePointContainer *spContainer = handle.get();
ATH_MSG_DEBUG( " \\__ " << spContainer->size() << " elements from input collection!" );
// ================================================== //
// ===================== OUTPUTS ==================== //
// ================================================== //
SG::WriteHandle< ActsTrk::SeedContainer > seedHandle = SG::makeHandle( m_seedKey, ctx );
ATH_MSG_DEBUG( " \\__ Seed Container `" << m_seedKey.key() << "` created ..." );
std::unique_ptr< ActsTrk::SeedContainer > seedPtrs = std::make_unique< ActsTrk::SeedContainer >();
// ================================================== //
// ===================== COMPUTATION ================ //
// ================================================== //
ATH_MSG_DEBUG("Running Seed Finding ...");
ATH_CHECK( m_seedsTool->createSeeds( ctx,
*spContainer,
*beamSpotData,
magFieldContext,
*seedPtrs.get() ) );
ATH_MSG_DEBUG(" \\__ Created " << seedPtrs->size() << " seeds");
// ================================================== //
// ===================== STORE OUTPUT =============== //
// ================================================== //
ATH_MSG_DEBUG("Storing Seed Collection");
ATH_CHECK( seedHandle.record( std::move( seedPtrs ) ) );
return StatusCode::SUCCESS;
}
} // namespace
/*
Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
*/
#ifndef ACTSTRACKFINDING_ACTSSEEDINGALGORITHM_H
#define ACTSTRACKFINDING_ACTSSEEDINGALGORITHM_H 1
// Base Class
#include "AthenaBaseComps/AthReentrantAlgorithm.h"
// Gaudi includes
#include "GaudiKernel/ToolHandle.h"
// Tools
#include "ActsTrkFinding/IActsSeedingTool.h"
// Athena
#include "BeamSpotConditionsData/BeamSpotData.h"
#include "MagFieldConditions/AtlasFieldCacheCondObj.h"
#include "MagFieldElements/AtlasFieldCache.h"
// Handle Keys
#include "StoreGate/ReadCondHandleKey.h"
#include "StoreGate/ReadHandleKey.h"
#include "StoreGate/WriteHandleKey.h"
namespace ActsTrk {
class ActsSeedingAlgorithm :
public AthReentrantAlgorithm {
public:
ActsSeedingAlgorithm(const std::string &name,
ISvcLocator *pSvcLocator);
virtual ~ActsSeedingAlgorithm() = default;
virtual StatusCode initialize() override;
virtual StatusCode execute(const EventContext& ctx) const override;
private:
// Tool Handles
ToolHandle< ActsTrk::IActsSeedingTool > m_seedsTool {this, "SeedTool", "","Seed Tool"};
// Handle Keys
SG::ReadCondHandleKey< InDet::BeamSpotData > m_beamSpotKey{this, "BeamSpotKey", "BeamSpotData", "SG key for beam spot"};
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCondObjInputKey {this, "AtlasFieldCacheCondObj", "fieldCondObj",
"Name of the Magnetic Field conditions object key"};
SG::ReadHandleKey< ActsTrk::SpacePointContainer > m_spacePointKey {this,"InputSpacePoints","","Input Acts Space Points"};
SG::WriteHandleKey< ActsTrk::SeedContainer > m_seedKey {this,"OutputSeeds","","Output Seeds"};
};
} // namespace
#endif
/*
Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
*/
#include "src/ActsSeedingTool.h"
// ACTS
#include "Acts/Seeding/SeedFilterConfig.hpp"
#include "Acts/Seeding/BinFinder.hpp"
#include "Acts/Seeding/BinnedSPGroup.hpp"
#include "Acts/Seeding/SeedFilter.hpp"
#include "Acts/Seeding/Seedfinder.hpp"
#include "Acts/Definitions/Units.hpp"
namespace ActsTrk {
ActsSeedingTool::ActsSeedingTool(const std::string& type,
const std::string& name,
const IInterface* parent)
: base_class(type, name, parent)
{
declareInterface<IActsSeedingTool>(this);
}
StatusCode ActsSeedingTool::initialize() {
ATH_MSG_INFO( "Initializing " << name() << "..." );
ATH_MSG_INFO( "Properties Summary:" );
ATH_MSG_INFO( " " << m_rMax );
ATH_MSG_INFO( " " << m_deltaRMin );
ATH_MSG_INFO( " " << m_deltaRMax );
ATH_MSG_INFO( " " << m_collisionRegionMin );
ATH_MSG_INFO( " " << m_collisionRegionMax );
ATH_MSG_INFO( " " << m_zMin );
ATH_MSG_INFO( " " << m_zMax );
ATH_MSG_INFO( " " << m_maxSeedsPerSpM );
ATH_MSG_INFO( " " << m_cotThetaMax );
ATH_MSG_INFO( " " << m_sigmaScattering );
ATH_MSG_INFO( " " << m_radLengthPerSeed );
ATH_MSG_INFO( " " << m_minPt );
ATH_MSG_INFO( " " << m_impactMax );
return StatusCode::SUCCESS;
}
StatusCode
ActsSeedingTool::createSeeds(const EventContext& /*ctx*/,
const ActsTrk::SpacePointContainer& spContainer,
const InDet::BeamSpotData& beamSpotData,
const Acts::MagneticFieldContext& magFieldContext,
ActsTrk::SeedContainer& seedContainer ) const
{
// Create Seeds
auto groupSeeds =
createSeeds( spContainer.begin(),
spContainer.end(),
beamSpotData,
magFieldContext );
// Store seeds
seedContainer.reserve(groupSeeds.size());
for (unsigned int i(0);i<groupSeeds.size();i++) {
std::unique_ptr< ActsTrk::Seed > to_add =
std::make_unique<ActsTrk::Seed>(std::forward<ActsTrk::Seed>(groupSeeds.at(i)));
seedContainer.push_back( std::move(to_add) );
}
return StatusCode::SUCCESS;
}
template<
typename spacepoint_iterator_t,
typename external_spacepoint_t
>
std::vector< Acts::Seed< external_spacepoint_t > >
ActsSeedingTool::createSeeds( spacepoint_iterator_t spBegin,
spacepoint_iterator_t spEnd,
const InDet::BeamSpotData& beamSpotData,
const Acts::MagneticFieldContext& magFieldContext ) const {
using seed_t = Acts::Seed< external_spacepoint_t >;
static thread_local std::vector< seed_t > seeds;
seeds.clear();
if ( spBegin == spEnd )
return seeds;
// Beam Spot Position
Acts::Vector2 beamPos( beamSpotData.beamPos()[ Amg::x ] * Acts::UnitConstants::mm,
beamSpotData.beamPos()[ Amg::y ] * Acts::UnitConstants::mm );
// Magnetic Field
ATLASMagneticFieldWrapper magneticField;
Acts::MagneticFieldProvider::Cache magFieldCache = magneticField.makeCache( magFieldContext );
Acts::Vector3 bField = *magneticField.getField( Acts::Vector3(beamPos.x(), beamPos.y(), 0),
magFieldCache );
auto Configs = prepareConfiguration< external_spacepoint_t >( beamPos,bField );
auto gridCfg = Configs.first;
auto finderCfg = Configs.second;
auto extractCovariance = [=](const external_spacepoint_t& sp, float, float,
float) -> std::pair<Acts::Vector3, Acts::Vector2> {
Acts::Vector3 position(sp.x(), sp.y(), sp.z());
Acts::Vector2 covariance(sp.varianceR(), sp.varianceZ());
return std::make_pair(position, covariance);
};
std::shared_ptr< Acts::BinFinder< external_spacepoint_t > > bottomBinFinder =
std::make_shared< Acts::BinFinder< external_spacepoint_t > >();
std::shared_ptr< Acts::BinFinder< external_spacepoint_t > > topBinFinder =
std::make_shared< Acts::BinFinder< external_spacepoint_t > >();
std::unique_ptr< Acts::SpacePointGrid< external_spacepoint_t > > grid =
Acts::SpacePointGridCreator::createGrid< external_spacepoint_t >(gridCfg);
Acts::BinnedSPGroup< external_spacepoint_t > spacePointsGrouping(spBegin, spEnd, extractCovariance,
bottomBinFinder, topBinFinder, std::move(grid), finderCfg);
Acts::Seedfinder< external_spacepoint_t > finder(finderCfg);
static thread_local typename decltype(finder)::State state;
auto group = spacePointsGrouping.begin();
auto groupEnd = spacePointsGrouping.end();
for (; group != groupEnd; ++group) {
finder.createSeedsForGroup(state, std::back_inserter(seeds), group.bottom(),
group.middle(), group.top());
}
return seeds;
}
template< typename external_spacepoint_t >
const std::pair< Acts::SpacePointGridConfig,Acts::SeedfinderConfig< external_spacepoint_t > >
ActsSeedingTool::prepareConfiguration( const Acts::Vector2& beamPos,
const Acts::Vector3& bField ) const {
// Configuration for Acts::SpacePointGrid
// These values will not be changed during execution
// B Field will be updated for each event (gridCfg.bFieldInZ)
Acts::SpacePointGridConfig gridCfg;
gridCfg.minPt = m_minPt;
gridCfg.rMax = m_rMax;
gridCfg.zMax = m_zMax;
gridCfg.zMin = m_zMin;
gridCfg.deltaRMax = m_deltaRMax;
gridCfg.cotThetaMax = m_cotThetaMax;
gridCfg.bFieldInZ = bField[2];
// Configuration for Acts::Seedfinder
// These values will not be changed during execution
// B Field and Beam Spot position will be updated for each event (finderCfg.bFieldInZ and finderCfg.beamPos)
Acts::SeedFilterConfig filterCfg;
filterCfg.deltaRMin = m_deltaRMin;
filterCfg.maxSeedsPerSpM = m_maxSeedsPerSpM;
Acts::SeedfinderConfig< external_spacepoint_t > finderCfg;
finderCfg.seedFilter = std::make_unique<Acts::SeedFilter< external_spacepoint_t > >(Acts::SeedFilter< external_spacepoint_t >(filterCfg));
finderCfg.rMax = m_rMax;
finderCfg.deltaRMin = m_deltaRMin;
finderCfg.deltaRMax = m_deltaRMax;
finderCfg.collisionRegionMin = m_collisionRegionMin;
finderCfg.collisionRegionMax = m_collisionRegionMax;
finderCfg.zMin = m_zMin;
finderCfg.zMax = m_zMax;
finderCfg.maxSeedsPerSpM = m_maxSeedsPerSpM;
finderCfg.cotThetaMax = m_cotThetaMax;
finderCfg.sigmaScattering = m_sigmaScattering;
finderCfg.radLengthPerSeed = m_radLengthPerSeed;
finderCfg.minPt = m_minPt;
finderCfg.impactMax = m_impactMax;
finderCfg.beamPos = beamPos;
finderCfg.bFieldInZ = bField[2];
return std::make_pair( gridCfg,finderCfg );
}
} // namespace ActsTrk
/*
Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
*/
#ifndef ACTSTRACKFINDING_ACTSSEEDINGTOOL_H
#define ACTSTRACKFINDING_ACTSSEEDINGTOOL_H 1
// ATHENA
#include "ActsTrkFinding/IActsSeedingTool.h"
#include "AthenaBaseComps/AthAlgTool.h"
#include "BeamSpotConditionsData/BeamSpotData.h"
#include "MagFieldConditions/AtlasFieldCacheCondObj.h"
#include "MagFieldElements/AtlasFieldCache.h"
#include "StoreGate/ReadCondHandleKey.h"
#include "ActsGeometry/ATLASMagneticFieldWrapper.h"
// ACTS CORE
#include "Acts/Definitions/Units.hpp"
#include "Acts/Definitions/Common.hpp"
#include "Acts/Definitions/Algebra.hpp"
#include "Acts/MagneticField/MagneticFieldContext.hpp"
#include "Acts/Seeding/SpacePointGrid.hpp"
#include "Acts/Seeding/BinFinder.hpp"
#include "Acts/Seeding/BinnedSPGroup.hpp"
#include "Acts/Seeding/SeedfinderConfig.hpp"
#include "Acts/Seeding/SeedFilterConfig.hpp"
#include "Acts/Seeding/SeedFilter.hpp"
#include "Acts/Seeding/Seedfinder.hpp"
#include "Acts/Seeding/Seed.hpp"
namespace ActsTrk {
class ActsSeedingTool :
public extends<AthAlgTool, ActsTrk::IActsSeedingTool> {
public:
ActsSeedingTool(const std::string& type, const std::string& name,
const IInterface* parent);
virtual ~ActsSeedingTool() = default;
virtual StatusCode initialize() override;
// Interface
virtual StatusCode
createSeeds(const EventContext& ctx,