diff --git a/Tracking/Acts/FaserActsGeometry/src/CuboidVolumeBuilder.cxx b/Tracking/Acts/FaserActsGeometry/src/CuboidVolumeBuilder.cxx index 76416ff7b7a917a9e47a18a87ac125686b6d386a..a8a8bd2dec4016916236128d6c78e815b8015bf2 100644 --- a/Tracking/Acts/FaserActsGeometry/src/CuboidVolumeBuilder.cxx +++ b/Tracking/Acts/FaserActsGeometry/src/CuboidVolumeBuilder.cxx @@ -75,12 +75,12 @@ std::shared_ptr<const Acts::Layer> CuboidVolumeBuilder::buildLayer( if ( !cfg.surfaces.empty() ) { return layerCreator.planeLayer(gctx, cfg.surfaces, cfg.binsX, cfg.binsY, - Acts::BinningValue::binZ, std::nullopt, trafo, - std::move(ap)); + Acts::BinningValue::binZ, std::nullopt, trafo); +// std::move(ap)); } else { return layerCreator.planeLayer(gctx, {cfg.surface}, cfg.binsX, cfg.binsY, - Acts::BinningValue::binZ, std::nullopt, trafo, - std::move(ap)); + Acts::BinningValue::binZ, std::nullopt, trafo); +// std::move(ap)); } } diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsExtrapolationTool.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsExtrapolationTool.cxx index e84a69c6a3fe54ee30ecb046a0606a1e264da5e5..c5351bfaaea0780c843fb1aa3a6ec6fd31cdb3ce 100644 --- a/Tracking/Acts/FaserActsGeometry/src/FaserActsExtrapolationTool.cxx +++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsExtrapolationTool.cxx @@ -71,7 +71,8 @@ FaserActsExtrapolationTool::initialize() ATH_MSG_INFO("Initializing ACTS extrapolation"); - m_logger = makeActsAthenaLogger(this, "Prop", "FaserActsExtrapTool"); + m_logger = Acts::getDefaultLogger("ExtrapolationTool", Acts::Logging::INFO); +// m_logger = makeActsAthenaLogger(this, "Prop", "FaserActsExtrapTool"); ATH_CHECK( m_trackingGeometryTool.retrieve() ); std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry @@ -318,8 +319,8 @@ FaserActsExtrapolationTool::propagate(const EventContext& ctx, ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin"); Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx); - const FaserActsGeometryContext& gctx - = m_trackingGeometryTool->getGeometryContext(ctx); + const FaserActsGeometryContext& gctx = m_trackingGeometryTool->getNominalGeometryContext(); +// const FaserActsGeometryContext& gctx = m_trackingGeometryTool->getGeometryContext(ctx); auto anygctx = gctx.context(); diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsTrackingGeometrySvc.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsTrackingGeometrySvc.cxx index f32a02990835e96bc0d56bfe887604bf3667a4eb..94c852743ebd4dec46d3ee734a7f800dd4384a3e 100644 --- a/Tracking/Acts/FaserActsGeometry/src/FaserActsTrackingGeometrySvc.cxx +++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsTrackingGeometrySvc.cxx @@ -25,6 +25,8 @@ #include "FaserActsGeometry/CuboidVolumeBuilder.h" #include "Acts/ActsVersion.hpp" #include "Acts/Definitions/Units.hpp" +#include <Acts/Plugins/Json/JsonMaterialDecorator.hpp> +#include <Acts/Plugins/Json/MaterialMapJsonConverter.hpp> // PACKAGE #include "FaserActsGeometry/FaserActsLayerBuilder.h" @@ -73,6 +75,21 @@ FaserActsTrackingGeometrySvc::initialize() cvhConfig, makeActsAthenaLogger(this, "CylVolHlpr", "ActsTGSvc")); Acts::TrackingGeometryBuilder::Config tgbConfig; + + if (m_useMaterialMap) { + std::shared_ptr<const Acts::IMaterialDecorator> matDeco = nullptr; + std::string matFile = m_materialMapInputFile; + ATH_MSG_INFO("Configured to use material input: " << matFile); + if (matFile.find(".json") != std::string::npos) { + // Set up the converter first + Acts::MaterialMapJsonConverter::Config jsonGeoConvConfig; + // Set up the json-based decorator + matDeco = std::make_shared<const Acts::JsonMaterialDecorator>( + jsonGeoConvConfig, m_materialMapInputFile, Acts::Logging::INFO); + } + tgbConfig.materialDecorator = matDeco; + } + try { // SCT tgbConfig.trackingVolumeBuilders.push_back([&]( diff --git a/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt b/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt index 21e5ed799d3caeaf33d4fc85102b9be48e18e599..34d9584f9f6b30b1683c962d6baa59037bc8d6f3 100755 --- a/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt +++ b/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt @@ -23,22 +23,64 @@ atlas_add_library( FaserActsKalmanFilterLib atlas_add_component(FaserActsKalmanFilter FaserActsKalmanFilter/CombinatorialKalmanFilterAlg.h + FaserActsKalmanFilter/EffPlotTool.h + FaserActsKalmanFilter/FASERSourceLink.h FaserActsKalmanFilter/FaserActsGeometryContainers.h + FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h + FaserActsKalmanFilter/IdentifierLink.h FaserActsKalmanFilter/IndexSourceLink.h + FaserActsKalmanFilter/ITrackFinderTool.h + FaserActsKalmanFilter/ITrackSeedTool.h +# FaserActsKalmanFilter/ClusterTrackSeedTool.h +# FaserActsKalmanFilter/TruthTrackFinderTool.h FaserActsKalmanFilter/Measurement.h +# FaserActsKalmanFilter/MultiTrackFinderTool.h + FaserActsKalmanFilter/MyAmbiguitySolver.h + FaserActsKalmanFilter/PerformanceWriterTool.h + FaserActsKalmanFilter/PlotHelpers.h + FaserActsKalmanFilter/ResPlotTool.h + FaserActsKalmanFilter/RootTrajectoryStatesWriterTool.h + FaserActsKalmanFilter/RootTrajectorySummaryWriterTool.h +# FaserActsKalmanFilter/SegmentFitClusterTrackFinderTool.h +# FaserActsKalmanFilter/SegmentFitTrackFinderTool.h FaserActsKalmanFilter/SimWriterTool.h FaserActsKalmanFilter/SPSeedBasedInitialParameterTool.h FaserActsKalmanFilter/SPSimpleInitialParameterTool.h + FaserActsKalmanFilter/SummaryPlotTool.h + FaserActsKalmanFilter/TrackClassification.h + FaserActsKalmanFilter/TrackSelection.h FaserActsKalmanFilter/TrajectoryWriterTool.h +# FaserActsKalmanFilter/ProtoTrackWriterTool.h FaserActsKalmanFilter/TruthBasedInitialParameterTool.h - src/CombinatorialKalmbanFilterAlg.cxx +# FaserActsKalmanFilter/TruthSeededTrackFinderTool.h + FaserActsKalmanFilter/ThreeStationTrackSeedTool.h +# src/ClusterTrackSeedTool.cxx + src/CombinatorialKalmanFilterAlg.cxx + src/EffPlotTool.cxx + src/FaserActsKalmanFilterAlg.cxx +# src/MultiTrackFinderTool.cxx + src/PerformanceWriterTool.cxx + src/PlotHelpers.cxx + src/ResPlotTool.cxx + src/RootTrajectoryStatesWriterTool.cxx + src/RootTrajectorySummaryWriterTool.cxx +# src/SegmentFitClusterTrackFinderTool.cxx +# src/SegmentFitTrackFinderTool.cxx src/SimWriterTool.cxx src/SPSeedBasedInitialParameterTool.cxx src/SPSimpleInitialParameterTool.cxx +# src/ProtoTrackWriterTool.cxx src/TrackFindingAlgorithmFunction.cxx + src/TrackFittingFunction.cxx src/TrajectoryWriterTool.cxx src/TruthBasedInitialParameterTool.cxx + src/SummaryPlotTool.cxx + src/TrackClassification.cxx + src/TrackSelection.cxx +# src/TruthTrackFinderTool.cxx +# src/TruthSeededTrackFinderTool.cxx + src/ThreeStationTrackSeedTool.cxx src/components/FaserActsKalmanFilter_entries.cxx PUBLIC_HEADERS FaserActsKalmanFilter INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${BOOST_INCLUDE_DIRS} @@ -63,6 +105,7 @@ atlas_add_component(FaserActsKalmanFilter TrackerIdentifier TrackerReadoutGeometry Identifier + TrackerSimEvent TrackerSimData TrackerSeedFinderLib ) diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ClusterTrackSeedTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ClusterTrackSeedTool.h new file mode 100644 index 0000000000000000000000000000000000000000..fa869dc1bd7242f5096a16d879b73ab86a9e2173 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ClusterTrackSeedTool.h @@ -0,0 +1,100 @@ +#ifndef FASERACTSKALMANFILTER_CLUSTERTRACKFINDERTOOL_H +#define FASERACTSKALMANFILTER_CLUSTERTRACKFINDERTOOL_H + +#include "TrackerPrepRawData/FaserSCT_ClusterContainer.h" +#include "AthenaBaseComps/AthAlgTool.h" +#include "Gaudi/Property.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/StatusCode.h" + +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" +#include "FaserActsKalmanFilter/ITrackSeedTool.h" +#include "TrkTrack/TrackCollection.h" +#include <memory> +#include <string> +#include <vector> + +class FaserSCT_ID; +namespace TrackerDD { class SCT_DetectorManager; } + +class ClusterTrackSeedTool : public extends<AthAlgTool, ITrackSeedTool> { +public: + ClusterTrackSeedTool(const std::string& type, const std::string& name, const IInterface* parent); + virtual ~ClusterTrackSeedTool() = default; + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + virtual StatusCode run() override; + + const std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> initialTrackParameters() const override; + const std::shared_ptr<const Acts::Surface> initialSurface() const override; + const std::shared_ptr<std::vector<IndexSourceLink>> sourceLinks() const override; + const std::shared_ptr<IdentifierLink> idLinks() const override; + const std::shared_ptr<std::vector<Measurement>> measurements() const override; + const std::shared_ptr<std::vector<const Tracker::FaserSCT_Cluster*>> clusters() const override; + +private: + std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> m_initialTrackParameters; + std::shared_ptr<const Acts::Surface> m_initialSurface; + std::shared_ptr<std::vector<IndexSourceLink>> m_sourceLinks {}; + std::shared_ptr<IdentifierLink> m_idLinks {}; + std::shared_ptr<std::vector<Measurement>> m_measurements {}; + std::shared_ptr<std::vector<const Tracker::FaserSCT_Cluster*>> m_clusters {}; + + const FaserSCT_ID* m_idHelper {nullptr}; + const TrackerDD::SCT_DetectorManager* m_detManager {nullptr}; + + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool { + this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; + SG::ReadHandleKey<TrackCollection> m_trackCollection { + this, "TrackCollection", "SegmentFit", "Input track collection name" }; + SG::ReadHandleKey<Tracker::FaserSCT_ClusterContainer> m_clusterContainerKey { + this, "ClusterContainer", "SCT_ClusterContainer"}; + + // position resolution of a cluster + Gaudi::Property<double> m_std_cluster {this, "std_cluster", 0.04}; + + // covariance of the initial parameters + Gaudi::Property<double> m_covLoc0 {this, "covLoc0", 1}; + Gaudi::Property<double> m_covLoc1 {this, "covLoc1", 1}; + Gaudi::Property<double> m_covPhi {this, "covPhi", 1}; + Gaudi::Property<double> m_covTheta {this, "covTheta", 1}; + Gaudi::Property<double> m_covQOverP {this, "covQOverP", 1}; + Gaudi::Property<double> m_covTime {this, "covTime", 1}; + + Gaudi::Property<double> m_origin {this, "origin", 0, "z position of the reference surface"}; + + static Acts::CurvilinearTrackParameters get_params(const Amg::Vector3D& position_st1, const Amg::Vector3D& position_st2, const Acts::BoundSymMatrix& cov, double origin); +}; + +inline const std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> +ClusterTrackSeedTool::initialTrackParameters() const { + return m_initialTrackParameters; +} + +inline const std::shared_ptr<const Acts::Surface> +ClusterTrackSeedTool::initialSurface() const { + return m_initialSurface; +} + +inline const std::shared_ptr<std::vector<IndexSourceLink>> +ClusterTrackSeedTool::sourceLinks() const { + return m_sourceLinks; +} + +inline const std::shared_ptr<IdentifierLink> +ClusterTrackSeedTool::idLinks() const { + return m_idLinks; +} + +inline const std::shared_ptr<std::vector<Measurement>> +ClusterTrackSeedTool::measurements() const { + return m_measurements; +} + +inline const std::shared_ptr<std::vector<const Tracker::FaserSCT_Cluster*>> +ClusterTrackSeedTool::clusters() const { + return m_clusters; +} + + +#endif // FASERACTSKALMANFILTER_CLUSTERTRACKFINDERTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CombinatorialKalmanFilterAlg.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CombinatorialKalmanFilterAlg.h index 4b750614a3f496a9cabef0352c223d9b9e5a9658..50453e26cf7b4ce21ca8b3b4a6b4c70bceb19d40 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CombinatorialKalmanFilterAlg.h +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CombinatorialKalmanFilterAlg.h @@ -2,82 +2,97 @@ #define COMBINATORIALKALMANFILTERALG_H #include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "AthenaBaseComps/AthAlgorithm.h" #include "TrackerSpacePoint/FaserSCT_SpacePointContainer.h" #include "TrackerPrepRawData/FaserSCT_ClusterContainer.h" #include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" #include "FaserActsKalmanFilter/TruthBasedInitialParameterTool.h" -#include "FaserActsKalmanFilter/SPSimpleInitialParameterTool.h" -#include "FaserActsKalmanFilter/SPSeedBasedInitialParameterTool.h" +//#include "FaserActsKalmanFilter/SPSimpleInitialParameterTool.h" +//#include "FaserActsKalmanFilter/SPSeedBasedInitialParameterTool.h" #include "Acts/TrackFinding/CombinatorialKalmanFilter.hpp" #include "Acts/TrackFinding/MeasurementSelector.hpp" #include "FaserActsKalmanFilter/Measurement.h" #include "MagFieldConditions/FaserFieldCacheCondObj.h" #include "FaserActsKalmanFilter/TrajectoryWriterTool.h" #include "TrkTrack/TrackCollection.h" +#include "FaserActsKalmanFilter/ITrackSeedTool.h" +#include "FaserActsKalmanFilter/RootTrajectoryStatesWriterTool.h" +#include "FaserActsKalmanFilter/RootTrajectorySummaryWriterTool.h" +#include "FaserActsKalmanFilter/PerformanceWriterTool.h" + class FaserSCT_ID; -namespace Trk -{ +namespace Trk { class TrackStateOnSurface; } namespace TrackerDD { - class SCT_DetectorManager; +class SCT_DetectorManager; } -class CombinatorialKalmanFilterAlg : public AthReentrantAlgorithm { - public: +class CombinatorialKalmanFilterAlg : public AthAlgorithm { +public: CombinatorialKalmanFilterAlg(const std::string& name, ISvcLocator* pSvcLocator); virtual ~CombinatorialKalmanFilterAlg() = default; StatusCode initialize() override; - StatusCode execute(const EventContext& ctx) const override; + StatusCode execute() override; StatusCode finalize() override; using TrackFinderOptions = - Acts::CombinatorialKalmanFilterOptions<IndexSourceLinkAccessor, MeasurementCalibrator, Acts::MeasurementSelector>; - using FitterResult = Acts::Result<Acts::CombinatorialKalmanFilterResult<IndexSourceLink>>; - using TrackFinderResult = std::vector<FitterResult>; -// using TrackFinderResult = std::vector< -// Acts::Result<Acts::CombinatorialKalmanFilterResult<IndexSourceLink>>>; - using TrackFinderFunction = std::function<TrackFinderResult( - const IndexSourceLinkContainer&, const std::vector<Acts::CurvilinearTrackParameters>&, - const TrackFinderOptions&)>; - - static TrackFinderFunction makeTrackFinderFunction( - std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry); + Acts::CombinatorialKalmanFilterOptions<IndexSourceLinkAccessor, + MeasurementCalibrator, + Acts::MeasurementSelector>; + using TrackFitterResult = + Acts::Result<Acts::CombinatorialKalmanFilterResult<IndexSourceLink>>; + using TrackFinderResult = std::vector<TrackFitterResult>; + using TrackParameters = Acts::CurvilinearTrackParameters; + using TrackParametersContainer = std::vector<TrackParameters>; - Acts::MagneticFieldContext getMagneticFieldContext(const EventContext& ctx) const; + class TrackFinderFunction { + public: + virtual ~TrackFinderFunction() = default; + virtual TrackFinderResult operator()(const IndexSourceLinkContainer&, + const TrackParametersContainer&, + const TrackFinderOptions&) const = 0; + }; + static std::shared_ptr<TrackFinderFunction> makeTrackFinderFunction( + std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry, + bool resolvePassive, bool resolveMaterial, bool resolveSensitive); + virtual Acts::MagneticFieldContext getMagneticFieldContext(const EventContext& ctx) const; private: - const FaserSCT_ID* m_idHelper{nullptr}; - const TrackerDD::SCT_DetectorManager* m_detManager{nullptr}; - -// std::unique_ptr<Trk::Track> makeTrack(Acts::GeometryContext& tgContext, FitterResult& fitResult, std::vector<Tracker::FaserSCT_Cluster> seed_spcollection) const; - std::unique_ptr<Trk::Track> makeTrack(Acts::GeometryContext& tgContext, FitterResult& fitResult, std::vector<Tracker::FaserSCT_SpacePoint> seed_spcollection) const; - const Trk::TrackParameters* ConvertActsTrackParameterToATLAS(const Acts::BoundTrackParameters &actsParameter, const Acts::GeometryContext& gctx) const; + void computeSharedHits(std::vector<IndexSourceLink>* sourceLinks, TrackFinderResult& results) const; + std::shared_ptr<TrackFinderFunction> m_fit; + std::unique_ptr<const Acts::Logger> m_logger; + const FaserSCT_ID* m_idHelper {nullptr}; + const TrackerDD::SCT_DetectorManager* m_detManager {nullptr}; - SG::WriteHandleKey<TrackCollection> m_trackCollection { this, "FaserActsCKFTrackCollection", "FaserActsCKFTrackCollection", "Output trackcollectionname" }; - - ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool{this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; -// ToolHandle<SPSeedBasedInitialParameterTool> m_initialParameterTool{this, "InitialParameterTool", "SPSeedBasedInitialParameterTool"}; -// ToolHandle<SPSimpleInitialParameterTool> m_initialParameterTool{this, "InitialParameterTool", "SPSimpleInitialParameterTool"}; - ToolHandle<TruthBasedInitialParameterTool> m_initialParameterTool{this, "InitialParameterTool", "TruthBasedInitialParameterTool"}; - ToolHandle<TrajectoryWriterTool> m_trajectoryWriterTool{this, "OutputTool", "TrajectoryWriterTool"}; + Gaudi::Property<std::string> m_actsLogging {this, "ActsLogging", "VERBOSE"}; + Gaudi::Property<int> m_minNumberMeasurements {this, "MinNumberMeasurements", 12}; + Gaudi::Property<bool> m_backwardPropagation {this, "BackwardPropagation", false}; + Gaudi::Property<bool> m_performanceWriter {this, "PerformanceWriter", true}; + Gaudi::Property<bool> m_summaryWriter {this, "SummaryWriter", true}; + Gaudi::Property<bool> m_statesWriter {this, "StatesWriter", false}; + Gaudi::Property<bool> m_resolvePassive {this, "resolvePassive", false}; + Gaudi::Property<bool> m_resolveMaterial {this, "resolveMaterial", true}; + Gaudi::Property<bool> m_resolveSensitive {this, "resolveSensitive", true}; + Gaudi::Property<double> m_maxSteps {this, "maxSteps", 10000}; + Gaudi::Property<double> m_chi2Max {this, "chi2Max", 15}; + Gaudi::Property<unsigned long> m_nMax {this, "nMax", 10}; + Gaudi::Property<size_t> m_nTrajectories {this, "nTrajectories", 2}; SG::ReadCondHandleKey<FaserFieldCacheCondObj> m_fieldCondObjInputKey {this, "FaserFieldCacheCondObj", "fieldCondObj", "Name of the Magnetic Field conditions object key"}; - SG::ReadHandleKey<FaserSCT_SpacePointContainer> m_SpacePointContainerKey{this, "SpacePointsSCTName", "SCT_SpacePointContainer", "SCT space point container"}; - SG::ReadHandleKey<Tracker::FaserSCT_ClusterContainer> m_Sct_clcontainerKey{this, "SCT_ClusterContainer", "SCT_ClusterContainer"}; - mutable int m_nevents; - mutable int m_ntracks; - mutable int m_nseeds; - mutable int m_nsp1; - mutable int m_nsp2; - mutable int m_nsp3; - mutable int m_nsp10; - mutable int m_nsp11; - mutable int m_ncom; + ToolHandle<ITrackSeedTool> m_trackSeedTool {this, "TrackSeed", "ClusterTrackSeedTool"}; + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool {this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; + ToolHandle<PerformanceWriterTool> m_performanceWriterTool {this, "PerformanceWriterTool", "PerformanceWriterTool"}; + ToolHandle<RootTrajectoryStatesWriterTool> m_trajectoryStatesWriterTool {this, "RootTrajectoryStatesWriterTool", "RootTrajectoryStatesWriterTool"}; + ToolHandle<RootTrajectorySummaryWriterTool> m_trajectorySummaryWriterTool {this, "RootTrajectorySummaryWriterTool", "RootTrajectorySummaryWriterTool"}; + + std::unique_ptr<Trk::Track> makeTrack(Acts::GeometryContext& tgContext, TrackFitterResult& fitResult) const; + const Trk::TrackParameters* ConvertActsTrackParameterToATLAS(const Acts::BoundTrackParameters &actsParameter, const Acts::GeometryContext& gctx) const; + SG::WriteHandleKey<TrackCollection> m_trackCollection { this, "CKFTrackCollection", "CKFTrackCollection" }; }; #endif // COMBINATORIALKALMANFILTERALG_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/EffPlotTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/EffPlotTool.h new file mode 100644 index 0000000000000000000000000000000000000000..e5af125d6021d5ab19b71f73eebc63a99604aea5 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/EffPlotTool.h @@ -0,0 +1,57 @@ +#ifndef FASERACTSKALMANFILTER_EFFPLOTTOOL_H +#define FASERACTSKALMANFILTER_EFFPLOTTOOL_H + +#include "FaserActsKalmanFilter/PlotHelpers.h" +#include "Acts/EventData/TrackParameters.hpp" +#include "HepMC/GenParticle.h" +#include "TEfficiency.h" +#include "TProfile.h" +#include <map> +#include <string> + +class EffPlotTool { +public: + std::map<std::string, PlotHelpers::Binning> m_varBinning = { + {"Eta", PlotHelpers::Binning("#eta", 40, 4, 12)}, + {"Phi", PlotHelpers::Binning("#phi", 100, -3.15, 3.15)}, + {"Pt", PlotHelpers::Binning("pT [GeV/c]", 40, 0, 20)} + }; + + /// @brief Nested Cache struct + struct EffPlotCache { + TEfficiency* trackEff_vs_pT; ///< Tracking efficiency vs pT + TEfficiency* trackEff_vs_eta; ///< Tracking efficiency vs eta + TEfficiency* trackEff_vs_phi; ///< Tracking efficiency vs phi + }; + + /// Constructor + /// + EffPlotTool() = default; + + /// @brief book the efficiency plots + /// + /// @param effPlotCache the cache for efficiency plots + void book(EffPlotCache& effPlotCache) const; + + /// @brief fill efficiency plots + /// + /// @param effPlotCache cache object for efficiency plots + /// @param truthParticle the truth Particle + /// @param status the reconstruction status + void fill(EffPlotCache& effPlotCache, const HepMC::GenParticle* truthParticle, bool status) const; + + /// @brief write the efficiency plots to file + /// + /// @param effPlotCache cache object for efficiency plots + void write(const EffPlotCache& effPlotCache) const; + + /// @brief delete the efficiency plots + /// + /// @param effPlotCache cache object for efficiency plots + void clear(EffPlotCache& effPlotCache) const; + +private: + const double m_MeV2GeV = 0.001; +}; + +#endif // FASERACTSKALMANFILTER_EFFPLOTTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FASERSourceLink.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FASERSourceLink.h new file mode 100644 index 0000000000000000000000000000000000000000..6ec1c46b9ad12ff6822c070a4ea320d6079dd387 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FASERSourceLink.h @@ -0,0 +1,57 @@ +#pragma once + +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include <cassert> +#include <boost/container/flat_map.hpp> +#include "FaserActsKalmanFilter/FaserActsGeometryContainers.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" + +using Index = uint32_t; + +class FASERSourceLink final { +public: + /// Construct from geometry identifier and index. + constexpr FASERSourceLink(Acts::GeometryIdentifier gid, Index idx, Tracker::FaserSCT_Cluster hit) + : m_geometryId(gid), m_index(idx), m_hit(hit) {} + + // Construct an invalid source link. Must be default constructible to + /// satisfy SourceLinkConcept. + FASERSourceLink() = default; + FASERSourceLink(const FASERSourceLink&) = default; + FASERSourceLink(FASERSourceLink&&) = default; + FASERSourceLink& operator=(const FASERSourceLink&) = default; + FASERSourceLink& operator=(FASERSourceLink&&) = default; + + /// Access the geometry identifier. + constexpr Acts::GeometryIdentifier geometryId() const { return m_geometryId; } + /// Access the index. + constexpr Index index() const { return m_index; } + /// Access the Tracker::FaserSCT_Cluster hit + constexpr Tracker::FaserSCT_Cluster hit() const { return m_hit; } + +private: + Acts::GeometryIdentifier m_geometryId; + Index m_index; + Tracker::FaserSCT_Cluster m_hit; + + friend constexpr bool operator==(const FASERSourceLink& lhs, + const FASERSourceLink& rhs) { + return (lhs.m_geometryId == rhs.m_geometryId) and + (lhs.m_index == rhs.m_index); + } + friend constexpr bool operator!=(const FASERSourceLink& lhs, + const FASERSourceLink& rhs) { + return not(lhs == rhs); + } +}; + +/// Container of index source links. +/// +/// Since the source links provide a `.geometryId()` accessor, they can be +/// stored in an ordered geometry container. +using FASERSourceLinkContainer = GeometryIdMultiset<FASERSourceLink>; +/// Accessor for the above source link container +/// +/// It wraps up a few lookup methods to be used in the Combinatorial Kalman +/// Filter +using FASERSourceLinkAccessor = GeometryIdMultisetAccessor<FASERSourceLink>; diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h index 8e90ed858c09efc3d46985a7edb354ea2de6c280..34dd7c63e7ef5842ac1416dc30d895bef3ecf997 100755 --- a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h @@ -6,8 +6,8 @@ #define FASERACTSKALMANFILTER_FASERACTSKALMANFILTERALG_H // ATHENA -#include "AthenaBaseComps/AthAlgorithm.h" #include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "AthenaBaseComps/AthAlgorithm.h" #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ITHistSvc.h" #include "Gaudi/Property.h" /*no forward decl: typedef*/ @@ -24,6 +24,7 @@ #include "GeneratorObjects/McEventCollection.h" #include "TrackerSimData/TrackerSimDataCollection.h" #include "TrkTrack/TrackCollection.h" +#include "FaserActsKalmanFilter/TrajectoryWriterTool.h" // ACTS #include "Acts/MagneticField/ConstantBField.hpp" @@ -47,6 +48,9 @@ #include "FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h" #include "FaserActsKalmanFilter/IndexSourceLink.h" #include "FaserActsKalmanFilter/Measurement.h" +#include "FaserActsKalmanFilter/ITrackFinderTool.h" +//#include "FaserActsKalmanFilter/ProtoTrackWriterTool.h" +#include "FaserActsKalmanFilter/RootTrajectoryStatesWriterTool.h" // STL #include <memory> @@ -73,216 +77,59 @@ using BField_t = FASERMagneticFieldWrapper; //class FaserActsKalmanFilterAlg : public AthReentrantAlgorithm { class FaserActsKalmanFilterAlg : public AthAlgorithm { public: - FaserActsKalmanFilterAlg (const std::string& name, ISvcLocator* pSvcLocator); + FaserActsKalmanFilterAlg(const std::string& name, ISvcLocator* pSvcLocator); + virtual ~FaserActsKalmanFilterAlg() = default; + StatusCode initialize() override; - //StatusCode execute(const EventContext& ctx) const override; +// StatusCode execute(const EventContext& ctx) const override; StatusCode execute() override; StatusCode finalize() override; - using FitterResult = Acts::Result<Acts::KalmanFitterResult<IndexSourceLink>>; - // Fit function that takes input measurements, initial trackstate and fitter - // options and returns some fit-specific result. - using FitterFunction = std::function<FitterResult( - const std::vector<IndexSourceLink>&, - const Acts::CurvilinearTrackParameters&, - const Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder>&, - const std::vector<const Acts::Surface*>&)>; + using IndexedParams = std::unordered_map<size_t, Acts::BoundTrackParameters>; + using TrackFitterOptions = + Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder, + Acts::VoidReverseFilteringLogic>; + using TrackFitterResult = + Acts::Result<Acts::KalmanFitterResult<IndexSourceLink>>; - using BoundVector = Acts::ActsVector<6>; + using TrackParameters = Acts::CurvilinearTrackParameters; - // Create the fitter function implementation. - static FitterFunction - makeFitterFunction( - ActsExtrapolationDetail::VariantPropagator* varProp); + class TrackFitterFunction { + public: + virtual ~TrackFitterFunction() = default; + virtual TrackFitterResult operator()(const std::vector<IndexSourceLink>&, + const TrackParameters&, + const TrackFitterOptions&) const = 0; + }; - virtual - Acts::MagneticFieldContext - //getMagneticFieldContext(const EventContext& ctx) const; - getMagneticFieldContext() const; + static std::shared_ptr<TrackFitterFunction> makeTrackFitterFunction( + std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry); - void initializeTree(); + virtual Acts::MagneticFieldContext getMagneticFieldContext(const EventContext& ctx) const; - void fillFitResult(const Acts::GeometryContext& geoctx, const TrajectoryContainer& trajectories, const Acts::BoundTrackParameters& truthParam); +private: + const FaserSCT_ID* m_idHelper {nullptr}; + std::shared_ptr<TrackFitterFunction> m_fit; + std::unique_ptr<const Acts::Logger> m_logger; - // Create a track from the fitter result - std::unique_ptr<Trk::Track> makeTrack(Acts::GeometryContext& tgContext, FitterResult& fitResult,const SpacePointForSeedCollection* seed_spcollection ) const; + Gaudi::Property<std::string> m_actsLogging {this, "ActsLogging", "VERBOSE"}; + std::unique_ptr<Trk::Track> makeTrack(Acts::GeometryContext& tgContext, TrackFitterResult& fitResult, std::vector<const Tracker::FaserSCT_Cluster*> clusters) const; const Trk::TrackParameters* ConvertActsTrackParameterToATLAS(const Acts::BoundTrackParameters &actsParameter, const Acts::GeometryContext& gctx) const; - void clearTrackVariables(); - -private: - const FaserSCT_ID* m_idHelper{nullptr}; - // Read handle for conditions object to get the field cache SG::ReadCondHandleKey<FaserFieldCacheCondObj> m_fieldCondObjInputKey {this, "FaserFieldCacheCondObj", "fieldCondObj", "Name of the Magnetic Field conditions object key"}; - ToolHandle<IFaserActsExtrapolationTool> m_extrapolationTool{this, "ExtrapolationTool", "FaserActsExtrapolationTool"}; - - Gaudi::Property<std::string> m_fieldMode{this, "FieldMode", "FASER"}; - Gaudi::Property<std::vector<double>> m_constantFieldVector{this, "ConstantFieldVector", {0, 0, 0}}; + ToolHandle<ITrackFinderTool> m_trackFinderTool {this, "TrackFinderTool", "TruthTrackFinderTool"}; + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool {this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; + ToolHandle<TrajectoryWriterTool> m_trajectoryWriterTool {this, "OutputTool", "TrajectoryWriterTool"}; + ToolHandle<RootTrajectoryStatesWriterTool> m_trajectoryStatesWriterTool {this, "RootTrajectoryStatesWriterTool", "RootTrajectoryStatesWriterTool"}; +// ToolHandle<ProtoTrackWriterTool> m_protoTrackWriterTool {this, "ProtoTrackWriterTool", "ProtoTrackWriterTool"}; - SG::ReadHandleKey<SpacePointForSeedCollection> m_seed_spcollectionKey{this, "FaserSpacePointsSeedsName", "SpacePointForSeedCollection", "SpacePointForSeedCollection"}; - - SG::ReadHandleKey<McEventCollection> m_mcEventKey { this, "McEventCollection", "BeamTruthEvent" }; + SG::ReadHandleKey<McEventCollection> m_mcEventKey { this, "McEventCollection", "BeamTruthEvent" }; SG::ReadHandleKey<TrackerSimDataCollection> m_sctMap {this, "TrackerSimDataCollection", "SCT_SDO_Map"}; const TrackerDD::SCT_DetectorManager* m_detManager{nullptr}; - SG::WriteHandleKey<TrackCollection> m_trackCollection { this, "FaserActsCKFTrackCollection", "FaserActsCKFTrackCollection", "Output trackcollection name" }; - - ServiceHandle<ITHistSvc> m_thistSvc; - - TTree *m_trackTree{nullptr}; - - Acts::GeometryIdentifier getGeometryIdentifier(const Identifier id); - int getGeometryIdentifierVolume(int station); - int getGeometryIdentifierLayer(int layer); - int getGeometryIdentifierSensitive(int row, int column); - - /// Acts tree values - int m_eventNr{0}; - int m_trajNr{0}; - int m_trackNr{0}; - - unsigned long m_t_barcode{0}; /// Truth particle barcode - int m_t_charge{0}; /// Truth particle charge - float m_t_eT{0}; /// Truth particle time on the first layer - float m_t_eLOC0{-99.}; /// Truth local x on the first layer - float m_t_eLOC1{-99.}; /// Truth local y on the first layer - float m_t_eTHETA{-99.}; /// Truth particle momentum theta on the first layer - float m_t_ePHI{-99.}; /// Truth particle momentum phi on the first layer - float m_t_eQOP{-99.}; /// Truth particle momentum qop on the first layer - float m_t_x{-99.}; /// Truth particle position x on the first layer - float m_t_y{-99.}; /// Truth particle position y on the first layer - float m_t_z{-99.}; /// Truth particle position z on the first layer - float m_t_px{-99.}; /// Truth particle momentum px on the first layer - float m_t_py{-99.}; /// Truth particle momentum py on the first layer - float m_t_pz{-99.}; /// Truth particle momentum pz on the first layer - - int m_nHoles{0}; /// number of holes in the track fit - int m_nOutliers{0}; /// number of outliers in the track fit - int m_nStates{0}; /// number of all states - int m_nMeasurements{0}; /// number of states with measurements - std::vector<int> m_volumeID; /// volume identifier - std::vector<int> m_layerID; /// layer identifier - std::vector<int> m_moduleID; /// surface identifier - std::vector<float> m_lx_hit; /// uncalibrated measurement local x - std::vector<float> m_ly_hit; /// uncalibrated measurement local y - std::vector<float> m_x_hit; /// uncalibrated measurement global x - std::vector<float> m_y_hit; /// uncalibrated measurement global y - std::vector<float> m_z_hit; /// uncalibrated measurement global z - std::vector<float> m_res_x_hit; /// hit residual x - std::vector<float> m_res_y_hit; /// hit residual y - std::vector<float> m_err_x_hit; /// hit err x - std::vector<float> m_err_y_hit; /// hit err y - std::vector<float> m_pull_x_hit; /// hit pull x - std::vector<float> m_pull_y_hit; /// hit pull y - std::vector<int> m_dim_hit; /// dimension of measurement - - bool m_hasFittedParams{false}; /// if the track has fitted parameter - float m_eLOC0_fit{-99.}; /// fitted parameter eLOC_0 - float m_eLOC1_fit{-99.}; /// fitted parameter eLOC_1 - float m_ePHI_fit{-99.}; /// fitted parameter ePHI - float m_eTHETA_fit{-99.}; /// fitted parameter eTHETA - float m_eQOP_fit{-99.}; /// fitted parameter eQOP - float m_eT_fit{-99.}; /// fitted parameter eT - float m_err_eLOC0_fit{-99.}; /// fitted parameter eLOC_-99.err - float m_err_eLOC1_fit{-99.}; /// fitted parameter eLOC_1 err - float m_err_ePHI_fit{-99.}; /// fitted parameter ePHI err - float m_err_eTHETA_fit{-99.}; /// fitted parameter eTHETA err - float m_err_eQOP_fit{-99.}; /// fitted parameter eQOP err - float m_err_eT_fit{-99.}; /// fitted parameter eT err - float m_px_fit{-99.}; /// fitted parameter global px - float m_py_fit{-99.}; /// fitted parameter global py - float m_pz_fit{-99.}; /// fitted parameter global pz - float m_x_fit{-99.}; /// fitted parameter global PCA x - float m_y_fit{-99.}; /// fitted parameter global PCA y - float m_z_fit{-99.}; /// fitted parameter global PCA z - float m_chi2_fit{-99.}; /// fitted parameter chi2 - float m_ndf_fit{-99.}; /// fitted parameter ndf - int m_charge_fit{-99}; /// fitted parameter charge - - int m_nPredicted{0}; /// number of states with predicted parameter - std::vector<bool> m_prt; /// predicted status - std::vector<float> m_eLOC0_prt; /// predicted parameter eLOC0 - std::vector<float> m_eLOC1_prt; /// predicted parameter eLOC1 - std::vector<float> m_ePHI_prt; /// predicted parameter ePHI - std::vector<float> m_eTHETA_prt; /// predicted parameter eTHETA - std::vector<float> m_eQOP_prt; /// predicted parameter eQOP - std::vector<float> m_eT_prt; /// predicted parameter eT - std::vector<float> m_res_eLOC0_prt; /// predicted parameter eLOC0 residual - std::vector<float> m_res_eLOC1_prt; /// predicted parameter eLOC1 residual - std::vector<float> m_err_eLOC0_prt; /// predicted parameter eLOC0 error - std::vector<float> m_err_eLOC1_prt; /// predicted parameter eLOC1 error - std::vector<float> m_err_ePHI_prt; /// predicted parameter ePHI error - std::vector<float> m_err_eTHETA_prt; /// predicted parameter eTHETA error - std::vector<float> m_err_eQOP_prt; /// predicted parameter eQOP error - std::vector<float> m_err_eT_prt; /// predicted parameter eT error - std::vector<float> m_pull_eLOC0_prt; /// predicted parameter eLOC0 pull - std::vector<float> m_pull_eLOC1_prt; /// predicted parameter eLOC1 pull - std::vector<float> m_x_prt; /// predicted global x - std::vector<float> m_y_prt; /// predicted global y - std::vector<float> m_z_prt; /// predicted global z - std::vector<float> m_px_prt; /// predicted momentum px - std::vector<float> m_py_prt; /// predicted momentum py - std::vector<float> m_pz_prt; /// predicted momentum pz - std::vector<float> m_eta_prt; /// predicted momentum eta - std::vector<float> m_pT_prt; /// predicted momentum pT - - int m_nFiltered{0}; /// number of states with filtered parameter - std::vector<bool> m_flt; /// filtered status - std::vector<float> m_eLOC0_flt; /// filtered parameter eLOC0 - std::vector<float> m_eLOC1_flt; /// filtered parameter eLOC1 - std::vector<float> m_ePHI_flt; /// filtered parameter ePHI - std::vector<float> m_eTHETA_flt; /// filtered parameter eTHETA - std::vector<float> m_eQOP_flt; /// filtered parameter eQOP - std::vector<float> m_eT_flt; /// filtered parameter eT - std::vector<float> m_res_eLOC0_flt; /// filtered parameter eLOC0 residual - std::vector<float> m_res_eLOC1_flt; /// filtered parameter eLOC1 residual - std::vector<float> m_err_eLOC0_flt; /// filtered parameter eLOC0 error - std::vector<float> m_err_eLOC1_flt; /// filtered parameter eLOC1 error - std::vector<float> m_err_ePHI_flt; /// filtered parameter ePHI error - std::vector<float> m_err_eTHETA_flt; /// filtered parameter eTHETA error - std::vector<float> m_err_eQOP_flt; /// filtered parameter eQOP error - std::vector<float> m_err_eT_flt; /// filtered parameter eT error - std::vector<float> m_pull_eLOC0_flt; /// filtered parameter eLOC0 pull - std::vector<float> m_pull_eLOC1_flt; /// filtered parameter eLOC1 pull - std::vector<float> m_x_flt; /// filtered global x - std::vector<float> m_y_flt; /// filtered global y - std::vector<float> m_z_flt; /// filtered global z - std::vector<float> m_px_flt; /// filtered momentum px - std::vector<float> m_py_flt; /// filtered momentum py - std::vector<float> m_pz_flt; /// filtered momentum pz - std::vector<float> m_eta_flt; /// filtered momentum eta - std::vector<float> m_pT_flt; /// filtered momentum pT - std::vector<float> m_chi2; /// chisq from filtering - - int m_nSmoothed{0}; /// number of states with smoothed parameter - std::vector<bool> m_smt; /// smoothed status - std::vector<float> m_eLOC0_smt; /// smoothed parameter eLOC0 - std::vector<float> m_eLOC1_smt; /// smoothed parameter eLOC1 - std::vector<float> m_ePHI_smt; /// smoothed parameter ePHI - std::vector<float> m_eTHETA_smt; /// smoothed parameter eTHETA - std::vector<float> m_eQOP_smt; /// smoothed parameter eQOP - std::vector<float> m_eT_smt; /// smoothed parameter eT - std::vector<float> m_res_eLOC0_smt; /// smoothed parameter eLOC0 residual - std::vector<float> m_res_eLOC1_smt; /// smoothed parameter eLOC1 residual - std::vector<float> m_err_eLOC0_smt; /// smoothed parameter eLOC0 error - std::vector<float> m_err_eLOC1_smt; /// smoothed parameter eLOC1 error - std::vector<float> m_err_ePHI_smt; /// smoothed parameter ePHI error - std::vector<float> m_err_eTHETA_smt; /// smoothed parameter eTHETA error - std::vector<float> m_err_eQOP_smt; /// smoothed parameter eQOP error - std::vector<float> m_err_eT_smt; /// smoothed parameter eT error - std::vector<float> m_pull_eLOC0_smt; /// smoothed parameter eLOC0 pull - std::vector<float> m_pull_eLOC1_smt; /// smoothed parameter eLOC1 pull - std::vector<float> m_x_smt; /// smoothed global x - std::vector<float> m_y_smt; /// smoothed global y - std::vector<float> m_z_smt; /// smoothed global z - std::vector<float> m_px_smt; /// smoothed momentum px - std::vector<float> m_py_smt; /// smoothed momentum py - std::vector<float> m_pz_smt; /// smoothed momentum pz - std::vector<float> m_eta_smt; /// smoothed momentum eta - std::vector<float> m_pT_smt; /// smoothed momentum pT - + SG::WriteHandleKey<TrackCollection> m_trackCollection { this, "FaserActsKFTrackCollection", "FaserActsKFTrackCollection", "Output track collection" }; }; #endif diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h index 35baa239600d5f273dd91c2145eecfd8e1c8b52a..06924bed8e4adbe304697a4f71019d9134be72f8 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h @@ -6,82 +6,88 @@ #pragma once -#include <unordered_map> -#include <utility> - -// ACTS #include "Acts/EventData/MultiTrajectory.hpp" #include "Acts/EventData/TrackParameters.hpp" - -// PACKAGE #include "FaserActsKalmanFilter/IndexSourceLink.h" +#include <unordered_map> +#include <utility> -using IndexedParams = std::unordered_map<size_t, Acts::BoundTrackParameters>; - -struct FaserActsRecMultiTrajectory -{ +/// Store reconstructed trajectories from track finding/fitting. +/// +/// It contains a MultiTrajectory with a vector of entry indices for +/// individual trajectories, and a map of fitted parameters indexed by the +/// entry index. In case of track fitting, there is at most one trajectory +/// in the MultiTrajectory; In case of track finding, there could be +/// multiple trajectories in the MultiTrajectory. +struct FaserActsRecMultiTrajectory { public: - FaserActsRecMultiTrajectory() = default; + /// (Reconstructed) trajectory with multiple states. + using MultiTrajectory = ::Acts::MultiTrajectory<IndexSourceLink>; + /// Fitted parameters identified by indices in the multi trajectory. + using IndexedParams = std::unordered_map<size_t, Acts::BoundTrackParameters>; - FaserActsRecMultiTrajectory(const Acts::MultiTrajectory<IndexSourceLink>& multiTraj, - const std::vector<size_t>& tTips, - const IndexedParams& parameters) + /// Default construct an empty object. Required for container compatibility + /// and to signal an error. + FaserActsRecMultiTrajectory() = default; + /// Construct from fitted multi trajectory and parameters. + /// + /// @param multiTraj The multi trajectory + /// @param tTips Tip indices that identify valid trajectories + /// @param parameters Fitted track parameters indexed by trajectory index + FaserActsRecMultiTrajectory(const MultiTrajectory& multiTraj, + const std::vector<size_t>& tTips, + const IndexedParams& parameters) : m_multiTrajectory(multiTraj), m_trackTips(tTips), m_trackParameters(parameters) {} - FaserActsRecMultiTrajectory(const FaserActsRecMultiTrajectory& rhs) - : m_multiTrajectory(rhs.m_multiTrajectory), - m_trackTips(rhs.m_trackTips), - m_trackParameters(rhs.m_trackParameters) {} - - FaserActsRecMultiTrajectory(FaserActsRecMultiTrajectory&& rhs) - : m_multiTrajectory(std::move(rhs.m_multiTrajectory)), - m_trackTips(std::move(rhs.m_trackTips)), - m_trackParameters(std::move(rhs.m_trackParameters)) {} - - ~FaserActsRecMultiTrajectory() = default; - - FaserActsRecMultiTrajectory& operator=(const FaserActsRecMultiTrajectory& rhs) { - m_multiTrajectory = rhs.m_multiTrajectory; - m_trackTips = rhs.m_trackTips; - m_trackParameters = rhs.m_trackParameters; - return *this; - } + /// Return true if there exists no valid trajectory. + bool empty() const { return m_trackTips.empty(); } - FaserActsRecMultiTrajectory& operator=(FaserActsRecMultiTrajectory&& rhs) { - m_multiTrajectory = std::move(rhs.m_multiTrajectory); - m_trackTips = std::move(rhs.m_trackTips); - m_trackParameters = std::move(rhs.m_trackParameters); - return *this; - } + /// Access the underlying multi trajectory. + const MultiTrajectory& multiTrajectory() const { return m_multiTrajectory; } - bool hasTrajectory(const size_t& entryIndex) const { - return std::count(m_trackTips.begin(), m_trackTips.end(), entryIndex) > 0; - } + /// Access the tip indices that identify valid trajectories. + const std::vector<size_t>& tips() const { return m_trackTips; } - bool hasTrackParameters(const size_t& entryIndex) const { - return m_trackParameters.count(entryIndex) > 0; + /// Check if a trajectory exists for the given index. + /// + /// @param entryIndex The trajectory entry index + /// @return Whether there is trajectory with provided entry index + bool hasTrajectory(size_t entryIndex) const { + return (0 < std::count(m_trackTips.begin(), m_trackTips.end(), entryIndex)); } - std::pair<std::vector<size_t>, Acts::MultiTrajectory<IndexSourceLink>> - trajectory() const { - return std::make_pair(m_trackTips, m_multiTrajectory); + /// Check if fitted track parameters exists for the given index. + /// + /// @param entryIndex The trajectory entry index + /// @return Whether having fitted track parameters or not + bool hasTrackParameters(size_t entryIndex) const { + return (0 < m_trackParameters.count(entryIndex)); } - const Acts::BoundTrackParameters& trackParameters(const size_t& entryIndex) const { + /// Access the fitted track parameters for the given index. + /// + /// @param entryIndex The trajectory entry index + /// @return The fitted track parameters of the trajectory + const Acts::BoundTrackParameters& trackParameters(size_t entryIndex) const { auto it = m_trackParameters.find(entryIndex); - if (it != m_trackParameters.end()) { - return it->second; - } else { + if (it == m_trackParameters.end()) { throw std::runtime_error( "No fitted track parameters for trajectory with entry index = " + std::to_string(entryIndex)); } + return it->second; } - private: - Acts::MultiTrajectory<IndexSourceLink> m_multiTrajectory; +private: + // The multiTrajectory + MultiTrajectory m_multiTrajectory; + // The entry indices of trajectories stored in multiTrajectory std::vector<size_t> m_trackTips = {}; + // The fitted parameters at the provided surface for individual trajectories IndexedParams m_trackParameters = {}; }; + +/// Container for multiple trajectories. +using TrajectoriesContainer = std::vector<FaserActsRecMultiTrajectory>; diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ITrackFinderTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ITrackFinderTool.h new file mode 100644 index 0000000000000000000000000000000000000000..6fbc80c422cb3d83122a7c9ec9524da527221d15 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ITrackFinderTool.h @@ -0,0 +1,27 @@ +#ifndef FASERACTSKALMANFILTER_ITRACKFINDERTOOL_H +#define FASERACTSKALMANFILTER_ITRACKFINDERTOOL_H + +#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/IAlgTool.h" +#include "FaserActsKalmanFilter/IndexSourceLink.h" +#include "FaserActsKalmanFilter/IdentifierLink.h" +#include "FaserActsKalmanFilter/Measurement.h" +#include "Acts/EventData/TrackParameters.hpp" + +class ITrackFinderTool : virtual public IAlgTool { +public: + DeclareInterfaceID(ITrackFinderTool, 1, 0); + + // TODO use Acts::BoundTrackParameters instead? + virtual StatusCode run() = 0; + virtual const std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> initialTrackParameters() const = 0; + virtual const std::shared_ptr<const Acts::Surface> initialSurface() const = 0; + virtual const std::shared_ptr<std::vector<std::vector<IndexSourceLink>>> sourceLinks() const = 0; + virtual const std::shared_ptr<std::vector<IdentifierLink>> idLinks() const = 0; + virtual const std::shared_ptr<std::vector<std::vector<Measurement>>> measurements() const = 0; + virtual const std::shared_ptr<std::vector<std::vector<Tracker::FaserSCT_SpacePoint>>> spacePoints() const = 0; + virtual const std::shared_ptr<std::vector<std::vector<const Tracker::FaserSCT_Cluster*>>> clusters() const = 0; +}; + +#endif // FASERACTSKALMANFILTER_ITRACKFINDERTOOL_H \ No newline at end of file diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ITrackSeedTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ITrackSeedTool.h new file mode 100644 index 0000000000000000000000000000000000000000..34b5c23c2516ec620a73ab74d192e7f76ae278fc --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ITrackSeedTool.h @@ -0,0 +1,25 @@ +#ifndef FASERACTSKALMANFILTER_ITRACKSEEDTOOL_H +#define FASERACTSKALMANFILTER_ITRACKSEEDTOOL_H + +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/IAlgTool.h" +#include "FaserActsKalmanFilter/IndexSourceLink.h" +#include "FaserActsKalmanFilter/IdentifierLink.h" +#include "FaserActsKalmanFilter/Measurement.h" +#include "Acts/EventData/TrackParameters.hpp" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" + +class ITrackSeedTool : virtual public IAlgTool { +public: + DeclareInterfaceID(ITrackSeedTool, 1, 0); + + virtual StatusCode run() = 0; + virtual const std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> initialTrackParameters() const = 0; + virtual const std::shared_ptr<const Acts::Surface> initialSurface() const = 0; + virtual const std::shared_ptr<std::vector<IndexSourceLink>> sourceLinks() const = 0; + virtual const std::shared_ptr<IdentifierLink> idLinks() const = 0; + virtual const std::shared_ptr<std::vector<Measurement>> measurements() const = 0; + virtual const std::shared_ptr<std::vector<const Tracker::FaserSCT_Cluster*>> clusters() const = 0; +}; + +#endif // FASERACTSKALMANFILTER_ITRACKSEEDTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IdentifierLink.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IdentifierLink.h new file mode 100644 index 0000000000000000000000000000000000000000..5d236afec358b683ee5812889656d353a62d4924 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IdentifierLink.h @@ -0,0 +1,10 @@ +#ifndef FASERACTSKALMANFILTER_IDENTIFIERLINK_H +#define FASERACTSKALMANFILTER_IDENTIFIERLINK_H + +#include "Identifier/Identifier.h" + +using Index = uint32_t; + +using IdentifierLink = std::map<Index, Identifier>; + +#endif // FASERACTSKALMANFILTER_IDENTIFIERLINK_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IndexSourceLink.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IndexSourceLink.h index 99d101519030fca1d4fd7904bc7549b22a39a6c2..79973020943627dc32655fecb3a24437bb0c1284 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IndexSourceLink.h +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IndexSourceLink.h @@ -15,6 +15,7 @@ #include <boost/container/flat_map.hpp> #include "FaserActsKalmanFilter/FaserActsGeometryContainers.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" /// Index type to reference elements in a container. /// @@ -34,10 +35,10 @@ using Index = uint32_t; class IndexSourceLink final { public: /// Construct from geometry identifier and index. - constexpr IndexSourceLink(Acts::GeometryIdentifier gid, Index idx) - : m_geometryId(gid), m_index(idx) {} + IndexSourceLink(Acts::GeometryIdentifier gid, Index idx, const Tracker::FaserSCT_Cluster* hit) + : m_geometryId(gid), m_index(idx), m_hit(hit) {} - // Construct an invalid source link. Must be default constructible to + // Construct an invalid source link. Must be default constructible to /// satisfy SourceLinkConcept. IndexSourceLink() = default; IndexSourceLink(const IndexSourceLink&) = default; @@ -49,10 +50,13 @@ public: constexpr Acts::GeometryIdentifier geometryId() const { return m_geometryId; } /// Access the index. constexpr Index index() const { return m_index; } + /// Access the Tracker::FaserSCT_Cluster hit + constexpr const Tracker::FaserSCT_Cluster* hit() const { return m_hit; } private: Acts::GeometryIdentifier m_geometryId; Index m_index; + const Tracker::FaserSCT_Cluster* m_hit; friend constexpr bool operator==(const IndexSourceLink& lhs, const IndexSourceLink& rhs) { diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/MultiTrackFinderTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/MultiTrackFinderTool.h new file mode 100644 index 0000000000000000000000000000000000000000..56e5db2666157c330e91258776b3a6b34af44278 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/MultiTrackFinderTool.h @@ -0,0 +1,232 @@ +#ifndef FASERACTSKALMANFILTER_MULTITRACKFINDERTOOL_H +#define FASERACTSKALMANFILTER_MULTITRACKFINDERTOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "Gaudi/Property.h" +#include "GaudiKernel/EventContext.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/StatusCode.h" +#include "StoreGate/ReadHandleKey.h" +#include <string> +#include <vector> + +#include "TrackerSpacePoint/FaserSCT_SpacePointContainer.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" +#include "FaserActsKalmanFilter/ITrackFinderTool.h" +#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "TrkTrack/TrackCollection.h" + +class FaserSCT_ID; +namespace TrackerDD { +class SCT_DetectorManager; +} + + +class MultiTrackFinderTool : public extends<AthAlgTool, ITrackFinderTool> { +public: + MultiTrackFinderTool(const std::string& type, const std::string& name, const IInterface* parent); + virtual ~MultiTrackFinderTool() = default; + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + virtual StatusCode run() override; + + virtual const std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> initialTrackParameters() const override; + virtual const std::shared_ptr<const Acts::Surface> initialSurface() const override; + virtual const std::shared_ptr<std::vector<std::vector<IndexSourceLink>>> sourceLinks() const override; + virtual const std::shared_ptr<std::vector<IdentifierLink>> idLinks() const override; + virtual const std::shared_ptr<std::vector<std::vector<Measurement>>> measurements() const override; + virtual const std::shared_ptr<std::vector<std::vector<Tracker::FaserSCT_SpacePoint>>> spacePoints() const override; + virtual const std::shared_ptr<std::vector<std::vector<const Tracker::FaserSCT_Cluster*>>> clusters() const override; + + struct Tracklet { + public: + Tracklet(const std::vector<Identifier>& ids, + const std::vector<Acts::GeometryIdentifier>& geoIds, + const std::vector<double>& positions, + const Amg::Vector3D& fitPosition, + const std::vector<const Tracker::FaserSCT_Cluster*>& clusters) + : m_ids(ids), m_geoIds(geoIds), m_positions(positions), m_fitPosition(fitPosition), m_clusters(clusters) {}; + + std::vector<Identifier> ids() const { return m_ids; }; + std::vector<Acts::GeometryIdentifier> geoIds() const { return m_geoIds; } + std::vector<double> clusterPositions() const { return m_positions; } + const std::vector<const Tracker::FaserSCT_Cluster*>& clusters() const { return m_clusters; } + Amg::Vector3D position() const { return m_fitPosition; } + + private: + std::vector<Identifier> m_ids; + std::vector<Acts::GeometryIdentifier> m_geoIds; + std::vector<double> m_positions; + Amg::Vector3D m_fitPosition; + std::vector<const Tracker::FaserSCT_Cluster*> m_clusters; + }; + + struct ProtoTrack { + public: + ProtoTrack(const MultiTrackFinderTool::Tracklet& t1, + const MultiTrackFinderTool::Tracklet& t2, + const MultiTrackFinderTool::Tracklet& t3) + : m_t1(t1), m_t2(t2), m_t3(t3) {} + + Acts::CurvilinearTrackParameters initialTrackParameters( + double covLoc0, double covLoc1, double covPhi, double covTheta, double covQOverP, double covTime) const { + Acts::Vector3 dir = m_t2.position() - m_t1.position(); + Acts::Vector3 pos = m_t1.position() - m_t1.position().z()/dir.z() * dir; + Acts::Vector4 pos4 {pos.x(), pos.y(), pos.z(), 0}; + auto [abs_momentum, charge] = momentum({{1, m_t1.position()}, {2, m_t2.position()}, {3, m_t3.position()}}); + + Acts::BoundSymMatrix cov = Acts::BoundSymMatrix::Zero(); + cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = covLoc0; + cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = covLoc1; + cov(Acts::eBoundPhi, Acts::eBoundPhi) = covPhi; + cov(Acts::eBoundTheta, Acts::eBoundTheta) = covTheta; + cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = covQOverP; + cov(Acts::eBoundTime, Acts::eBoundTime) = covTime; + + Acts::CurvilinearTrackParameters params = + Acts::CurvilinearTrackParameters(pos4, dir, abs_momentum, charge, cov); + return params; + } + + std::tuple<std::vector<Measurement>, std::vector<IndexSourceLink>, std::map<Index, Identifier>, std::vector<const Tracker::FaserSCT_Cluster*>> run() const { + const int kSize = 1; + using ThisMeasurement = Acts::Measurement<IndexSourceLink, Acts::BoundIndices, kSize>; + std::array<Acts::BoundIndices, kSize> Indices = {Acts::eBoundLoc0}; + std::vector<IndexSourceLink> sourceLinks; + std::map<Index, Identifier> idLinks; + std::vector<Measurement> measurements; + std::vector<const Tracker::FaserSCT_Cluster*> clusters; + clusters.reserve(m_t1.clusters().size() + m_t2.clusters().size() + m_t3.clusters().size()); + clusters.insert(clusters.end(), m_t1.clusters().begin(), m_t1.clusters().end()); + clusters.insert(clusters.end(), m_t2.clusters().begin(), m_t2.clusters().end()); + clusters.insert(clusters.end(), m_t3.clusters().begin(), m_t3.clusters().end()); + + for (const MultiTrackFinderTool::Tracklet& tracklet : {m_t1, m_t2, m_t3}) { + // FIXME check that ids, geoIds and positions have the same size + auto ids = tracklet.ids(); + auto geoIds = tracklet.geoIds(); + auto positions = tracklet.clusterPositions(); + for (size_t i = 0; i < tracklet.ids().size(); ++i) { + idLinks[measurements.size()] = ids[i]; + IndexSourceLink sourceLink(geoIds[i], measurements.size()); + Eigen::Matrix<double, 1, 1> clusterPos {positions[i]}; + Eigen::Matrix<double, 1, 1> clusterCov {0.04 * 0.04,}; + ThisMeasurement meas(sourceLink, Indices, clusterPos, clusterCov); + sourceLinks.push_back(sourceLink); + measurements.emplace_back(std::move(meas)); + } + } + return std::make_tuple(measurements, sourceLinks, idLinks, clusters); + } + + double chi2() const { + return calc_chi2({m_t1.position(), m_t2.position(), m_t3.position()}); + } + + private: + Tracklet m_t1, m_t2, m_t3; + + static std::pair<double, double> momentum(const std::map<int, Amg::Vector3D>& pos, double B=0.57) { + Acts::Vector3 vec_l = pos.at(3) - pos.at(1); + double abs_l = std::sqrt(vec_l.y() * vec_l.y() + vec_l.z() * vec_l.z()); + double t = (pos.at(2).z() - pos.at(1).z()) / (pos.at(3).z() - pos.at(1).z()); + Acts::Vector3 vec_m = pos.at(1) + t * vec_l; + Acts::Vector3 vec_s = pos.at(2) - vec_m; + double abs_s = std::sqrt(vec_s.y() * vec_s.y() + vec_s.z() * vec_s.z()); + double p_yz = 0.3 * abs_l * abs_l * B / (8 * abs_s * 1000); + double charge = vec_s.y() < 0 ? 1 : -1; + return std::make_pair(p_yz, charge); + } + + static std::pair<Acts::Vector3, Acts::Vector3> linear_fit(const std::vector<Acts::Vector3>& hits) { + size_t n_hits = hits.size(); + Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> centers(n_hits, 3); + for (size_t i = 0; i < n_hits; ++i) centers.row(i) = hits[i]; + Acts::Vector3 origin = centers.colwise().mean(); + Eigen::MatrixXd centered = centers.rowwise() - origin.transpose(); + Eigen::MatrixXd cov = centered.adjoint() * centered; + Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eig(cov); + Acts::Vector3 axis = eig.eigenvectors().col(2).normalized(); + return std::make_pair(origin, axis); + } + + double calc_chi2(const std::vector<Acts::Vector3>& hits) const { + auto [origin, axis] = linear_fit(hits); + double chi2 = 0; + for (const Acts::Vector3& hit : hits) { + Acts::Vector3 exp = origin + (hit.z() - origin.z()) * axis/axis.z(); + chi2 += (exp.x() - hit.x()) * (exp.x() - hit.x()) + (exp.y() - hit.y()) * (exp.y() - hit.y()); + } + return chi2; + } + }; + + struct sort_chi2 { + inline bool operator() (const ProtoTrack& track1, const ProtoTrack& track2) { + return (track1.chi2() < track2.chi2()); + } + }; + +private: + std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> m_initialTrackParameters; + std::shared_ptr<const Acts::Surface> m_initialSurface; + std::shared_ptr<std::vector<std::vector<IndexSourceLink>>> m_sourceLinks {}; + std::shared_ptr<std::vector<IdentifierLink>> m_idLinks {}; + std::shared_ptr<std::vector<std::vector<Measurement>>> m_measurements {}; + std::shared_ptr<std::vector<std::vector<Tracker::FaserSCT_SpacePoint>>> m_spacePoints {}; + std::shared_ptr<std::vector<std::vector<const Tracker::FaserSCT_Cluster*>>> m_clusters {}; + + const FaserSCT_ID* m_idHelper {nullptr}; + const TrackerDD::SCT_DetectorManager* m_detManager {nullptr}; + + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool { + this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; + SG::ReadHandleKey<TrackCollection> m_trackCollection { + this, "TrackCollection", "SegmentFit", "Input track collection name" }; + + // covariance of the initial parameters + Gaudi::Property<double> m_covLoc0 {this, "covLoc0", 1}; + Gaudi::Property<double> m_covLoc1 {this, "covLoc1", 1}; + Gaudi::Property<double> m_covPhi {this, "covPhi", 1}; + Gaudi::Property<double> m_covTheta {this, "covTheta", 1}; + Gaudi::Property<double> m_covQOverP {this, "covQOverP", 1}; + Gaudi::Property<double> m_covTime {this, "covTime", 1}; +}; + +inline const std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> +MultiTrackFinderTool::initialTrackParameters() const { + return m_initialTrackParameters; +} + +inline const std::shared_ptr<const Acts::Surface> +MultiTrackFinderTool::initialSurface() const { + return m_initialSurface; +} + +inline const std::shared_ptr<std::vector<std::vector<IndexSourceLink>>> +MultiTrackFinderTool::sourceLinks() const { + return m_sourceLinks; +} + +inline const std::shared_ptr<std::vector<IdentifierLink>> +MultiTrackFinderTool::idLinks() const { + return m_idLinks; +} + +inline const std::shared_ptr<std::vector<std::vector<Measurement>>> +MultiTrackFinderTool::measurements() const { + return m_measurements; +} + +inline const std::shared_ptr<std::vector<std::vector<Tracker::FaserSCT_SpacePoint>>> +MultiTrackFinderTool::spacePoints() const { + return m_spacePoints; +} + +inline const std::shared_ptr<std::vector<std::vector<const Tracker::FaserSCT_Cluster*>>> +MultiTrackFinderTool::clusters() const { + return m_clusters; +} + +#endif // FASERACTSKALMANFILTER_MULTITRACKFINDERTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/MyAmbiguitySolver.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/MyAmbiguitySolver.h new file mode 100644 index 0000000000000000000000000000000000000000..47257befa2fcbd70da95d1ee88bd41d0fdabeb2a --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/MyAmbiguitySolver.h @@ -0,0 +1,80 @@ +#ifndef FASERACTSKALMANFILTER_AMBIGUITYSOLVER_H +#define FASERACTSKALMANFILTER_AMBIGUITYSOLVER_H + +#include "Acts/TrackFinding/CombinatorialKalmanFilter.hpp" +#include "FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h" + +using CombinatorialKalmanFilterResult = Acts::CombinatorialKalmanFilterResult<IndexSourceLink>; +using TrackFitterResult = Acts::Result<CombinatorialKalmanFilterResult>; +using TrackFinderResult = std::vector<TrackFitterResult>; + + +size_t numberMeasurements(const CombinatorialKalmanFilterResult& ckfResult) { + auto traj = FaserActsRecMultiTrajectory(ckfResult.fittedStates, ckfResult.lastMeasurementIndices, ckfResult.fittedParameters); + const auto& mj = traj.multiTrajectory(); + const auto& trackTips = traj.tips(); + size_t maxMeasurements = 0; + for (const auto& trackTip : trackTips) { + auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); + size_t nMeasurements = trajState.nMeasurements; + if (nMeasurements > maxMeasurements) { + maxMeasurements = nMeasurements; + } + std::cout << "# measurements: " << trajState.nMeasurements << std::endl; + } + return maxMeasurements; +} + +int countSharedHits(const CombinatorialKalmanFilterResult& result1, const CombinatorialKalmanFilterResult& result2) { + int count = 0; + std::vector<size_t> hitIndices {}; + + for (auto measIndex : result1.lastMeasurementIndices) { + result1.fittedStates.visitBackwards(measIndex, [&](const auto& state) { + if (not state.typeFlags().test(Acts::TrackStateFlag::MeasurementFlag)) + return; + size_t hitIndex = state.uncalibrated().index(); + hitIndices.emplace_back(hitIndex); + }); + } + + for (auto measIndex : result2.lastMeasurementIndices) { + result2.fittedStates.visitBackwards(measIndex, [&](const auto& state) { + if (not state.typeFlags().test(Acts::TrackStateFlag::MeasurementFlag)) + return; + size_t hitIndex = state.uncalibrated().index(); + if (std::find(hitIndices.begin(), hitIndices.end(), hitIndex) != hitIndices.end()) { + count += 1; + } + }); + } + return count; +} + + +std::pair<int, int> solveAmbiguity(TrackFinderResult& results, size_t minMeasurements = 13) { + std::map<std::pair<size_t, size_t>, size_t> trackPairs {}; + for (size_t i = 0; i < results.size(); ++i) { + // if (not results.at(i).ok()) continue; + // if (numberMeasurements(results.at(i).value()) < minMeasurements) continue; + for (size_t j = i+1; j < results.size(); ++j) { + // if (not results.at(j).ok()) continue; + // if (numberMeasurements(results.at(j).value()) < minMeasurements) continue; + int n = countSharedHits(results.at(i).value(), results.at(j).value()); + trackPairs[std::make_pair(i, j)] = n; + } + } + + std::pair<size_t, size_t> bestTrackPair; + size_t minSharedHits = std::numeric_limits<size_t>::max(); + for (const auto& trackPair : trackPairs) { + if (trackPair.second < minSharedHits) { + minSharedHits = trackPair.second; + bestTrackPair = trackPair.first; + } + } + + return bestTrackPair; +} + +#endif //FASERACTSKALMANFILTER_AMBIGUITYSOLVER_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/PerformanceWriterTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/PerformanceWriterTool.h new file mode 100644 index 0000000000000000000000000000000000000000..037a7da407d4c09d2e4cd20cba31731af455f52d --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/PerformanceWriterTool.h @@ -0,0 +1,50 @@ +#ifndef FASERACTSKALMANFILTER_PERFORMANCEWRITER_H +#define FASERACTSKALMANFILTER_PERFORMANCEWRITER_H + +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "AthenaBaseComps/AthAlgTool.h" +#include "FaserActsKalmanFilter/ResPlotTool.h" +#include "FaserActsKalmanFilter/EffPlotTool.h" +#include "FaserActsKalmanFilter/SummaryPlotTool.h" +#include "FaserActsGeometryInterfaces/IFaserActsExtrapolationTool.h" +#include "TrackerSimData/TrackerSimDataCollection.h" +#include "GeneratorObjects/McEventCollection.h" +#include "Acts/Geometry/GeometryContext.hpp" +class TFile; +struct FaserActsRecMultiTrajectory; +using TrajectoriesContainer = std::vector<FaserActsRecMultiTrajectory>; + +class PerformanceWriterTool : public AthAlgTool { +public: + PerformanceWriterTool(const std::string& type, const std::string& name, const IInterface* parent); + ~PerformanceWriterTool() override = default; + + StatusCode initialize() override; + StatusCode finalize() override; + + StatusCode write(const Acts::GeometryContext& geoContext, const TrajectoriesContainer& trajectories); + +private: + std::unique_ptr<const Acts::BoundTrackParameters> extrapolateToReferenceSurface( + const EventContext& ctx, const HepMC::GenParticle* particle) const; + SG::ReadHandleKey<TrackerSimDataCollection> m_simDataCollectionKey { + this, "TrackerSimDataCollection", "SCT_SDO_Map"}; + SG::ReadHandleKey<McEventCollection> m_mcEventCollectionKey { + this, "McEventCollection", "BeamTruthEvent"}; + ToolHandle<IFaserActsExtrapolationTool> m_extrapolationTool { + this, "ExtrapolationTool", "FaserActsExtrapolationTool"}; + Gaudi::Property<std::string> m_filePath{this, "FilePath", "performance_ckf.root"}; + TFile* m_outputFile{nullptr}; + + /// Plot tool for residuals and pulls. + ResPlotTool m_resPlotTool; + ResPlotTool::ResPlotCache m_resPlotCache; + /// Plot tool for efficiency + EffPlotTool m_effPlotTool; + EffPlotTool::EffPlotCache m_effPlotCache; + /// Plot tool for track hit info + SummaryPlotTool m_summaryPlotTool; + SummaryPlotTool::SummaryPlotCache m_summaryPlotCache; +}; + +#endif // FASERACTSKALMANFILTER_PERFORMANCEWRITER_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/PlotHelpers.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/PlotHelpers.h new file mode 100644 index 0000000000000000000000000000000000000000..c3e8a1caf22d1debbea709c8fbbfe3c8a1b695c2 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/PlotHelpers.h @@ -0,0 +1,113 @@ +#ifndef FASERACTSKALMANFILTER_PLOTHELPERS_H +#define FASERACTSKALMANFILTER_PLOTHELPERS_H + +#include "TEfficiency.h" +#include "TFitResult.h" +#include "TFitResultPtr.h" +#include "TH1F.h" +#include "TH2F.h" +#include "TProfile.h" +#include <string> + +namespace PlotHelpers { + +struct Binning { + Binning() = default; + + Binning(std::string bTitle, int bins, float bMin, float bMax) + : title(bTitle), nBins(bins), min(bMin), max(bMax) {}; + + std::string title; ///< title to be displayed + int nBins; ///< number of bins + float min; ///< minimum value + float max; ///< maximum value +}; + + +/// @brief book a 1D histogram +/// @param histName the name of histogram +/// @param histTitle the title of histogram +/// @param varBinning the binning info of variable +/// @return histogram pointer +TH1F *bookHisto(const char *histName, const char *histTitle, + const Binning &varBinning); + +/// @brief book a 2D histogram +/// @param histName the name of histogram +/// @param histTitle the title of histogram +/// @param varXBinning the binning info of variable at x axis +/// @param varYBinning the binning info of variable at y axis +/// @return histogram pointer +TH2F* bookHisto(const char* histName, const char* histTitle, + const Binning& varXBinning, const Binning& varYBinning); + +/// @brief fill a 1D histogram +/// @param hist histogram to fill +/// @param value value to fill +/// @param weight weight to fill +void fillHisto(TH1F* hist, float value, float weight = 1.0); + +/// @brief fill a 2D histogram +/// @param hist histogram to fill +/// @param xValue x value to fill +/// @param yValue y value to fill +/// @param weight weight to fill +void fillHisto(TH2F* hist, float xValue, float yValue, float weight = 1.0); + +/// @brief extract details, i.e. mean and width of a 1D histogram and fill +/// them into histograms +/// @param inputHist histogram to investigate +/// @param j which bin number of meanHist and widthHist to fill +/// @param meanHist histogram to fill the mean value of inputHist +/// @param widthHist histogram to fill the width value of inputHist +/// +void anaHisto(TH1D* inputHist, int j, TH1F* meanHist, TH1F* widthHist); + +/// @brief book a 1D efficiency plot +/// @param effName the name of plot +/// @param effTitle the title of plot +/// @param varBinning the binning info of variable +/// @return TEfficiency pointer +TEfficiency* bookEff(const char* effName, const char* effTitle, const Binning& varBinning); + +/// @brief book a 2D efficiency plot +/// @param effName the name of plot +/// @param effTitle the title of plot +/// @param varXBinning the binning info of variable at x axis +/// @param varYBinning the binning info of variable at y axis +/// @return TEfficiency pointer +TEfficiency* bookEff(const char* effName, const char* effTitle, + const Binning& varXBinning, const Binning& varYBinning); + +/// @brief fill a 1D efficiency plot +/// @param efficiency plot to fill +/// @param value value to fill +/// @param status bool to denote passed or not +void fillEff(TEfficiency* efficiency, float value, bool status); + +/// @brief fill a 2D efficiency plot +/// @param efficiency plot to fill +/// @param xValue x value to fill +/// @param yValue y value to fill +/// @param status bool to denote passed or not +void fillEff(TEfficiency* efficiency, float xValue, float yValue, bool status); + +/// @brief book a TProfile plot +/// @param profName the name of plot +/// @param profTitle the title of plot +/// @param varXBinning the binning info of variable at x axis +/// @param varYBinning the binning info of variable at y axis +/// @return TProfile pointer +TProfile* bookProf(const char* profName, const char* profTitle, + const Binning& varXBinning, const Binning& varYBinning); + +/// @brief fill a TProfile plot +/// @param profile plot to fill +/// @param xValue xvalue to fill +/// @param yValue yvalue to fill +/// @param weight weight to fill +void fillProf(TProfile* profile, float xValue, float yValue, float weight = 1.0); + +} // namespace PlotHelpers + +#endif // FASERACTSKALMANFILTER_PLOTHELPERS_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ProtoTrackWriterTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ProtoTrackWriterTool.h new file mode 100644 index 0000000000000000000000000000000000000000..a71ddb56ab7b70af4930fc5cd1369010a5e7446b --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ProtoTrackWriterTool.h @@ -0,0 +1,61 @@ +#ifndef FASERACTSKALMANFILTER_PROTOTRACKWRITERTOOL_H +#define FASERACTSKALMANFILTER_PROTOTRACKWRITERTOOL_H + +#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" +#include "AthenaBaseComps/AthAlgTool.h" +#include "Gaudi/Property.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/StatusCode.h" +#include "GaudiKernel/ToolHandle.h" +#include <memory> +#include <string> +#include <vector> + +#include "Acts/EventData/TrackParameters.hpp" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" +#include "FaserActsKalmanFilter/ITrackFinderTool.h" +#include "FaserActsKalmanFilter/Measurement.h" + +class FaserSCT_ID; +class TFile; +class TTree; + +class ProtoTrackWriterTool : public AthAlgTool { +public: + ProtoTrackWriterTool(const std::string& type, const std::string& name, + const IInterface* parent); + virtual ~ProtoTrackWriterTool() = default; + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + StatusCode write(std::shared_ptr<const Acts::CurvilinearTrackParameters> protoTrackParameters, + std::shared_ptr<std::vector<Measurement>> measurements, + const Acts::GeometryContext& ctx) const; + +private: + const FaserSCT_ID* m_idHelper{nullptr}; + + ToolHandle<ITrackFinderTool> m_trackFinderTool {this, "TrackFinderTool", "TruthTrackFinderTool"}; + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool {this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; + Gaudi::Property<std::string> m_filePath {this, "File", "ProtoTracks.root", "Root file"}; + TFile* m_file; + TTree* m_params; + TTree* m_meas; + + mutable int m_run_number; + mutable int m_event_number; + mutable double m_x; + mutable double m_y; + mutable double m_z; + mutable double m_px; + mutable double m_py; + mutable double m_pz; + mutable int m_station; + mutable int m_layer; + mutable int m_phi; + mutable int m_eta; + mutable int m_side; + mutable double m_meas_eLOC0; + mutable double m_meas_eLOC1; +}; + +#endif // FASERACTSKALMANFILTER_PROTOTRACKWRITERTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ResPlotTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ResPlotTool.h new file mode 100644 index 0000000000000000000000000000000000000000..0b65984bed7e7de4c7975fdf9cc67248c253dab7 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ResPlotTool.h @@ -0,0 +1,87 @@ +#ifndef FASERACTSKALMANFILTER_RESPLOTTOOL_H +#define FASERACTSKALMANFILTER_RESPLOTTOOL_H + +#include "FaserActsKalmanFilter/PlotHelpers.h" +#include "Acts/EventData/TrackParameters.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "HepMC/GenParticle.h" +#include "TH1F.h" +#include "TH2F.h" +#include <map> +#include <string> +#include <vector> + +class ResPlotTool { +public: + std::vector<std::string> m_paramNames = {"x0", "y0", "phi", "theta", "qop", "t"}; + std::map<std::string, PlotHelpers::Binning> m_varBinning { + {"Eta", PlotHelpers::Binning("#eta", 40, 4, 12)}, + {"Pt", PlotHelpers::Binning("pT [GeV/c]", 40, 0, 20)}, + {"Pull", PlotHelpers::Binning("pull", 100, -5, 5)}, + {"Residual_x0", PlotHelpers::Binning("r_{x0} [mm]", 100, -0.1, 0.1)}, + {"Residual_y0", PlotHelpers::Binning("r_{y0} [mm]", 100, -4, 4)}, + {"Residual_phi", PlotHelpers::Binning("r_{#phi} [rad]", 100, -0.3, 0.3)}, + {"Residual_theta", PlotHelpers::Binning("r_{#theta} [rad]", 100, -0.002, 0.002)}, + {"Residual_qop", PlotHelpers::Binning("r_{q/p} [c/GeV]", 100, -0.002, 0.002)}, + {"Residual_t", PlotHelpers::Binning("r_{t} [s]", 100, -1000, 1000)}, + }; + + /// @brief Nested Cache struct + struct ResPlotCache { + std::map<std::string, TH1F*> res; ///< Residual distribution + std::map<std::string, TH2F*> res_vs_eta; ///< Residual vs eta scatter plot + std::map<std::string, TH1F*> resMean_vs_eta; ///< Residual mean vs eta distribution + std::map<std::string, TH1F*> resWidth_vs_eta; ///< Residual width vs eta distribution + std::map<std::string, TH2F*> res_vs_pT; ///< Residual vs pT scatter plot + std::map<std::string, TH1F*> resMean_vs_pT; ///< Residual mean vs pT distribution + std::map<std::string, TH1F*> resWidth_vs_pT; ///< Residual width vs pT distribution + + std::map<std::string, TH1F*> pull; ///< Pull distribution + std::map<std::string, TH2F*> pull_vs_eta; ///< Pull vs eta scatter plot + std::map<std::string, TH1F*> pullMean_vs_eta; ///< Pull mean vs eta distribution + std::map<std::string, TH1F*> pullWidth_vs_eta; ///< Pull width vs eta distribution + std::map<std::string, TH2F*> pull_vs_pT; ///< Pull vs pT scatter plot + std::map<std::string, TH1F*> pullMean_vs_pT; ///< Pull mean vs pT distribution + std::map<std::string, TH1F*> pullWidth_vs_pT; ///< Pull width vs pT distribution + }; + + /// Constructor + /// + ResPlotTool() = default; + + /// @brief book the histograms + /// + /// @param resPlotCache the cache for residual/pull histograms + void book(ResPlotCache& resPlotCache) const; + + /// @brief fill the histograms + /// + /// @param resPlotCache the cache for residual/pull histograms + /// @param gctx the geometry context + /// @param truthParticle the truth particle + /// @param fittedParamters the fitted parameters at perigee surface + void fill(ResPlotCache& resPlotCache, const Acts::GeometryContext& gctx, + std::unique_ptr<const Acts::BoundTrackParameters> truthParameters, + const Acts::BoundTrackParameters& fittedParameters) const; + + /// @brief extract the details of the residual/pull plots and fill details + /// + /// into separate histograms + /// @param resPlotCache the cache object for residual/pull histograms + void refinement(ResPlotCache& resPlotCache) const; + + /// @brief write the histograms to output file + /// + /// @param resPlotCache the cache object for residual/pull histograms + void write(const ResPlotCache& resPlotCache) const; + + /// @brief delele the histograms + /// + /// @param resPlotCache the cache object for residual/pull histograms + void clear(ResPlotCache& resPlotCache) const; + +private: + const double m_MeV2GeV = 0.001; +}; + +#endif // FASERACTSKALMANFILTER_RESPLOTTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/RootTrajectoryStatesWriterTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/RootTrajectoryStatesWriterTool.h new file mode 100644 index 0000000000000000000000000000000000000000..280762a89a23fdf0555615aa0a7e82c23d3ccfa5 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/RootTrajectoryStatesWriterTool.h @@ -0,0 +1,129 @@ +#ifndef FASERACTSKALMANFILTER_ROOTTRAJECTORYSTATESWRITERTOOL_H +#define FASERACTSKALMANFILTER_ROOTTRAJECTORYSTATESWRITERTOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "Acts/EventData/TrackParameters.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "TrackerSimEvent/FaserSiHitCollection.h" +#include "TrackerSimData/TrackerSimDataCollection.h" +#include "GeneratorObjects/McEventCollection.h" +#include <array> +#include <string> +#include <vector> + + +class FaserSCT_ID; +namespace TrackerDD { +class SCT_DetectorManager; +} +class TFile; +class TTree; +struct FaserActsRecMultiTrajectory; +using TrajectoriesContainer = std::vector<FaserActsRecMultiTrajectory>; + +class RootTrajectoryStatesWriterTool : public AthAlgTool { +public: + RootTrajectoryStatesWriterTool(const std::string& type, const std::string& name, const IInterface* parent); + ~RootTrajectoryStatesWriterTool() override = default; + + StatusCode initialize() override; + StatusCode finalize() override; + + StatusCode write(const Acts::GeometryContext& gctx, const TrajectoriesContainer& trajectories) const; + +private: + SG::ReadHandleKey<McEventCollection> m_mcEventCollectionKey {this, "McEventCollection", "TruthEvent"}; + SG::ReadHandleKey<TrackerSimDataCollection> m_simDataCollectionKey {this, "TrackerSimDataCollection", "SCT_SDO_Map"}; + SG::ReadHandleKey <FaserSiHitCollection> m_faserSiHitKey {this, "FaserSiHitCollection", "SCT_Hits"}; + + const double m_MeV2GeV = 0.001; + + const FaserSCT_ID* m_idHelper{nullptr}; + const TrackerDD::SCT_DetectorManager* m_detMgr {nullptr}; + Gaudi::Property<std::string> m_filePath {this, "FilePath", "track_states_ckf.root", "Output root file"}; + Gaudi::Property<std::string> m_treeName {this, "TreeName", "tree", "Tree name"}; + Gaudi::Property<bool> m_mc {this, "MC", false}; + TFile* m_outputFile; + TTree* m_outputTree; + + mutable uint32_t m_eventNr{0}; ///< the event number + mutable uint32_t m_multiTrajNr{0}; ///< the multi-trajectory number + mutable unsigned int m_subTrajNr{0}; ///< the multi-trajectory sub-trajectory number + + mutable std::vector<float> m_t_x; ///< Global truth hit position x + mutable std::vector<float> m_t_y; ///< Global truth hit position y + mutable std::vector<float> m_t_z; ///< Global truth hit position z + mutable std::vector<float> m_t_dx; ///< Truth particle direction x at global hit position + mutable std::vector<float> m_t_dy; ///< Truth particle direction y at global hit position + mutable std::vector<float> m_t_dz; ///< Truth particle direction z at global hit position + + mutable std::vector<float> m_t_eLOC0; ///< truth parameter eBoundLoc0 + mutable std::vector<float> m_t_eLOC1; ///< truth parameter eBoundLoc1 + mutable std::vector<float> m_t_ePHI; ///< truth parameter ePHI + mutable std::vector<float> m_t_eTHETA; ///< truth parameter eTHETA + mutable std::vector<float> m_t_eQOP; ///< truth parameter eQOP + mutable std::vector<float> m_t_eT; ///< truth parameter eT + + mutable unsigned int m_nStates{0}; ///< number of all states + mutable unsigned int m_nMeasurements{0}; ///< number of states with measurements + mutable std::vector<int> m_volumeID; ///< volume identifier + mutable std::vector<int> m_layerID; ///< layer identifier + mutable std::vector<int> m_moduleID; ///< surface identifier + mutable std::vector<int> m_station; ///< station + mutable std::vector<int> m_layer; ///< layer + mutable std::vector<int> m_phi_module; ///< phi module (rows) + mutable std::vector<int> m_eta_module; ///< eta module (columns) + mutable std::vector<int> m_side; ///< module side + mutable std::vector<float> m_pathLength; ///< path length + mutable std::vector<float> m_lx_hit; ///< uncalibrated measurement local x + mutable std::vector<float> m_ly_hit; ///< uncalibrated measurement local y + mutable std::vector<float> m_x_hit; ///< uncalibrated measurement global x + mutable std::vector<float> m_y_hit; ///< uncalibrated measurement global y + mutable std::vector<float> m_z_hit; ///< uncalibrated measurement global z + mutable std::vector<float> m_res_x_hit; ///< hit residual x + mutable std::vector<float> m_res_y_hit; ///< hit residual y + mutable std::vector<float> m_err_x_hit; ///< hit err x + mutable std::vector<float> m_err_y_hit; ///< hit err y + mutable std::vector<float> m_pull_x_hit; ///< hit pull x + mutable std::vector<float> m_pull_y_hit; ///< hit pull y + mutable std::vector<int> m_dim_hit; ///< dimension of measurement + + mutable std::array<int, 3> m_nParams; ///< number of states which have filtered/predicted/smoothed parameters + mutable std::array<std::vector<bool>, 3> m_hasParams; ///< status of the filtered/predicted/smoothed parameters + mutable std::array<std::vector<float>, 3> m_eLOC0; ///< predicted/filtered/smoothed parameter eLOC0 + mutable std::array<std::vector<float>, 3> m_eLOC1; ///< predicted/filtered/smoothed parameter eLOC1 + mutable std::array<std::vector<float>, 3> m_ePHI; ///< predicted/filtered/smoothed parameter ePHI + mutable std::array<std::vector<float>, 3> m_eTHETA; ///< predicted/filtered/smoothed parameter eTHETA + mutable std::array<std::vector<float>, 3> m_eQOP; ///< predicted/filtered/smoothed parameter eQOP + mutable std::array<std::vector<float>, 3> m_eT; ///< predicted/filtered/smoothed parameter eT + mutable std::array<std::vector<float>, 3> m_res_eLOC0; ///< predicted/filtered/smoothed parameter eLOC0 residual + mutable std::array<std::vector<float>, 3> m_res_eLOC1; ///< predicted/filtered/smoothed parameter eLOC1 residual + mutable std::array<std::vector<float>, 3> m_res_ePHI; ///< predicted/filtered/smoothed parameter ePHI residual + mutable std::array<std::vector<float>, 3> m_res_eTHETA; ///< predicted/filtered/smoothed parameter eTHETA residual + mutable std::array<std::vector<float>, 3> m_res_eQOP; ///< predicted/filtered/smoothed parameter eQOP residual + mutable std::array<std::vector<float>, 3> m_res_eT; ///< predicted/filtered/smoothed parameter eT residual + mutable std::array<std::vector<float>, 3> m_err_eLOC0; ///< predicted/filtered/smoothed parameter eLOC0 error + mutable std::array<std::vector<float>, 3> m_err_eLOC1; ///< predicted/filtered/smoothed parameter eLOC1 error + mutable std::array<std::vector<float>, 3> m_err_ePHI; ///< predicted/filtered/smoothed parameter ePHI error + mutable std::array<std::vector<float>, 3> m_err_eTHETA; ///< predicted/filtered/smoothed parameter eTHETA error + mutable std::array<std::vector<float>, 3> m_err_eQOP; ///< predicted/filtered/smoothed parameter eQOP error + mutable std::array<std::vector<float>, 3> m_err_eT; ///< predicted/filtered/smoothed parameter eT error + mutable std::array<std::vector<float>, 3> m_pull_eLOC0; ///< predicted/filtered/smoothed parameter eLOC0 pull + mutable std::array<std::vector<float>, 3> m_pull_eLOC1; ///< predicted/filtered/smoothed parameter eLOC1 pull + mutable std::array<std::vector<float>, 3> m_pull_ePHI; ///< predicted/filtered/smoothed parameter ePHI pull + mutable std::array<std::vector<float>, 3> m_pull_eTHETA; ///< predicted/filtered/smoothed parameter eTHETA pull + mutable std::array<std::vector<float>, 3> m_pull_eQOP; ///< predicted/filtered/smoothed parameter eQOP pull + mutable std::array<std::vector<float>, 3> m_pull_eT; ///< predicted/filtered/smoothed parameter eT pull + mutable std::array<std::vector<float>, 3> m_x; ///< predicted/filtered/smoothed parameter global x + mutable std::array<std::vector<float>, 3> m_y; ///< predicted/filtered/smoothed parameter global y + mutable std::array<std::vector<float>, 3> m_z; ///< predicted/filtered/smoothed parameter global z + mutable std::array<std::vector<float>, 3> m_px; ///< predicted/filtered/smoothed parameter px + mutable std::array<std::vector<float>, 3> m_py; ///< predicted/filtered/smoothed parameter py + mutable std::array<std::vector<float>, 3> m_pz; ///< predicted/filtered/smoothed parameter pz + mutable std::array<std::vector<float>, 3> m_eta; ///< predicted/filtered/smoothed parameter eta + mutable std::array<std::vector<float>, 3> m_pT; ///< predicted/filtered/smoothed parameter pT + + mutable std::vector<float> m_chi2; ///< chisq from filtering +}; + +#endif // FASERACTSKALMANFILTER_ROOTTRAJECTORYSTATESWRITERTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/RootTrajectorySummaryWriterTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/RootTrajectorySummaryWriterTool.h new file mode 100644 index 0000000000000000000000000000000000000000..2ce72c2429164d9ff8af8e77cf95aaac36d8df26 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/RootTrajectorySummaryWriterTool.h @@ -0,0 +1,117 @@ +#ifndef FASERACTSKALMANFILTER_ROOTTRAJECTORYSUMMARYWRITERTOOL_H +#define FASERACTSKALMANFILTER_ROOTTRAJECTORYSUMMARYWRITERTOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "Acts/EventData/TrackParameters.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "FaserActsKalmanFilter/IdentifierLink.h" +#include "TrackerSimData/TrackerSimDataCollection.h" +#include "GeneratorObjects/McEventCollection.h" +#include "FaserActsGeometryInterfaces/IFaserActsExtrapolationTool.h" +#include <array> +#include <string> +#include <vector> + +class FaserSCT_ID; +namespace TrackerDD { +class SCT_DetectorManager; +} +class TFile; +class TTree; +struct FaserActsRecMultiTrajectory; +using TrajectoriesContainer = std::vector<FaserActsRecMultiTrajectory>; + +class RootTrajectorySummaryWriterTool : public AthAlgTool { +public: + RootTrajectorySummaryWriterTool(const std::string& type, const std::string& name, const IInterface* parent); + ~RootTrajectorySummaryWriterTool() override = default; + StatusCode write(const Acts::GeometryContext& geoContext, const TrajectoriesContainer& trajectories) const; + StatusCode initialize() override; + StatusCode finalize() override; + +private: + std::unique_ptr<const Acts::BoundTrackParameters> extrapolateToReferenceSurface( + const EventContext& ctx, const HepMC::GenParticle* particle) const; + const FaserSCT_ID* m_idHelper {nullptr}; + SG::ReadHandleKey<TrackerSimDataCollection> m_simDataCollectionKey { + this, "TrackerSimDataCollection", "SCT_SDO_Map"}; + SG::ReadHandleKey<McEventCollection> m_mcEventCollectionKey { + this, "McEventCollection", "TruthEvent"}; + ToolHandle<IFaserActsExtrapolationTool> m_extrapolationTool { + this, "ExtrapolationTool", "FaserActsExtrapolationTool"}; + + Gaudi::Property<std::string> m_filePath{this, "FilePath", "track_summary_ckf.root", "Output root file"}; + Gaudi::Property<std::string> m_treeName{this, "TreeName", "tree", "Tree name"}; + + const double m_MeV2GeV = 0.001; + + TFile* m_outputFile; + TTree* m_outputTree; + mutable uint32_t m_eventNr{0}; ///< The event number + mutable std::vector<uint32_t> m_multiTrajNr; ///< The multi-trajectory numbers in event + mutable std::vector<unsigned int> m_subTrajNr; ///< The multi-trajectory sub-trajectory number in event + + mutable std::vector<unsigned int> m_nStates; ///< The number of states + mutable std::vector<unsigned int> m_nMeasurements; ///< The number of measurements + mutable std::vector<unsigned int> m_nOutliers; ///< The number of outliers + mutable std::vector<unsigned int> m_nHoles; ///< The number of holes + mutable std::vector<unsigned int> m_nSharedHits; ///< The number of shared hits + mutable std::vector<float> m_chi2Sum; ///< The total chi2 + mutable std::vector<unsigned int> m_NDF; ///< The number of ndf of the measurements+outliers + mutable std::vector<std::vector<double>> m_measurementChi2; ///< The chi2 on all measurement states + mutable std::vector<std::vector<double>> m_outlierChi2; ///< The chi2 on all outlier states + // FIXME replace volume, layer, ... with station, layer, ... + mutable std::vector<std::vector<double>> m_measurementVolume; ///< The volume id of the measurements + mutable std::vector<std::vector<double>> m_measurementLayer; ///< The layer id of the measurements + mutable std::vector<std::vector<double>> m_outlierVolume; ///< The volume id of the outliers + mutable std::vector<std::vector<double>> m_outlierLayer; ///< The layer id of the outliers + + // The majority truth particle info + mutable std::vector<unsigned int> m_nMajorityHits; ///< The number of hits from majority particle + mutable std::vector<uint64_t> m_majorityParticleId; ///< The particle Id of the majority particle + mutable std::vector<int> m_t_charge; ///< Charge of majority particle + mutable std::vector<float> m_t_time; ///< Time of majority particle + mutable std::vector<float> m_t_vx; ///< Vertex x positions of majority particle + mutable std::vector<float> m_t_vy; ///< Vertex y positions of majority particle + mutable std::vector<float> m_t_vz; ///< Vertex z positions of majority particle + mutable std::vector<float> m_t_px; ///< Initial momenta px of majority particle + mutable std::vector<float> m_t_py; ///< Initial momenta py of majority particle + mutable std::vector<float> m_t_pz; ///< Initial momenta pz of majority particle + mutable std::vector<float> m_t_theta; ///< In * m_MeV2GeVitial momenta theta of majority particle + mutable std::vector<float> m_t_phi; ///< Initial momenta phi of majority particle + mutable std::vector<float> m_t_p; ///< Initial abs momenta of majority particle + mutable std::vector<float> m_t_pT; ///< Initial momenta pT of majority particle + mutable std::vector<float> m_t_eta; ///< Initial momenta eta of majority particle + + mutable std::vector<bool> m_hasFittedParams; ///< If the track has fitted parameter + // The fitted parameters + mutable std::vector<float> m_eLOC0_fit; ///< Fitted parameters eBoundLoc0 of track + mutable std::vector<float> m_eLOC1_fit; ///< Fitted parameters eBoundLoc1 of track + mutable std::vector<float> m_ePHI_fit; ///< Fitted parameters ePHI of track + mutable std::vector<float> m_eTHETA_fit; ///< Fitted parameters eTHETA of track + mutable std::vector<float> m_eQOP_fit; ///< Fitted parameters eQOP of track + mutable std::vector<float> m_eT_fit; ///< Fitted parameters eT of track + // The error of fitted parameters + mutable std::vector<float> m_err_eLOC0_fit; ///< Fitted parameters eLOC err of track + mutable std::vector<float> m_err_eLOC1_fit; ///< Fitted parameters eBoundLoc1 err of track + mutable std::vector<float> m_err_ePHI_fit; ///< Fitted parameters ePHI err of track + mutable std::vector<float> m_err_eTHETA_fit; ///< Fitted parameters eTHETA err of track + mutable std::vector<float> m_err_eQOP_fit; ///< Fitted parameters eQOP err of track + mutable std::vector<float> m_err_eT_fit; ///< Fitted parameters eT err of track + // The residual of fitted parameters + mutable std::vector<float> m_res_eLOC0_fit; ///< Fitted parameters eLOC res of track + mutable std::vector<float> m_res_eLOC1_fit; ///< Fitted parameters eBoundLoc1 res of track + mutable std::vector<float> m_res_ePHI_fit; ///< Fitted parameters ePHI res of track + mutable std::vector<float> m_res_eTHETA_fit; ///< Fitted parameters eTHETA res of track + mutable std::vector<float> m_res_eQOP_fit; ///< Fitted parameters eQOP res of track + mutable std::vector<float> m_res_eT_fit; ///< Fitted parameters eT res of track + // The pull of fitted parameters + mutable std::vector<float> m_pull_eLOC0_fit; ///< Fitted parameters eLOC pull of track + mutable std::vector<float> m_pull_eLOC1_fit; ///< Fitted parameters eBoundLoc1 pull of track + mutable std::vector<float> m_pull_ePHI_fit; ///< Fitted parameters ePHI pull of track + mutable std::vector<float> m_pull_eTHETA_fit; ///< Fitted parameters eTHETA pull of track + mutable std::vector<float> m_pull_eQOP_fit; ///< Fitted parameters eQOP pull of track + mutable std::vector<float> m_pull_eT_fit; ///< Fitted parameters eT pull of track +}; + +#endif // FASERACTSKALMANFILTER_ROOTTRAJECTORYSUMMARYWRITERTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/SegmentFitClusterTrackFinderTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/SegmentFitClusterTrackFinderTool.h new file mode 100644 index 0000000000000000000000000000000000000000..6bf7ba6984300ae218a39015786d99d034922e64 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/SegmentFitClusterTrackFinderTool.h @@ -0,0 +1,106 @@ +#ifndef FASERACTSKALMANFILTER_SEGMENTFITCLUSTERTRACKFINDERTOOL_H +#define FASERACTSKALMANFILTER_SEGMENTFITCLUSTERTRACKFINDERTOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "Gaudi/Property.h" +#include "GaudiKernel/EventContext.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/StatusCode.h" +#include "StoreGate/ReadHandleKey.h" +#include <string> +#include <vector> + +#include "TrackerSpacePoint/FaserSCT_SpacePointContainer.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" +#include "FaserActsKalmanFilter/ITrackFinderTool.h" +#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "TrkTrack/TrackCollection.h" + +class FaserSCT_ID; +namespace TrackerDD { +class SCT_DetectorManager; +} + + +class SegmentFitClusterTrackFinderTool : public extends<AthAlgTool, ITrackFinderTool> { +public: + SegmentFitClusterTrackFinderTool(const std::string& type, const std::string& name, const IInterface* parent); + virtual ~SegmentFitClusterTrackFinderTool() = default; + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + virtual StatusCode run() override; + + virtual const std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> initialTrackParameters() const override; + virtual const std::shared_ptr<const Acts::Surface> initialSurface() const override; + virtual const std::shared_ptr<std::vector<std::vector<IndexSourceLink>>> sourceLinks() const override; + virtual const std::shared_ptr<std::vector<IdentifierLink>> idLinks() const override; + virtual const std::shared_ptr<std::vector<std::vector<Measurement>>> measurements() const override; + virtual const std::shared_ptr<std::vector<std::vector<Tracker::FaserSCT_SpacePoint>>> spacePoints() const override; + virtual const std::shared_ptr<std::vector<std::vector<const Tracker::FaserSCT_Cluster*>>> clusters() const override; + +private: + std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> m_initialTrackParameters; + std::shared_ptr<const Acts::Surface> m_initialSurface; + std::shared_ptr<std::vector<std::vector<IndexSourceLink>>> m_sourceLinks {}; + std::shared_ptr<std::vector<IdentifierLink>> m_idLinks {}; + std::shared_ptr<std::vector<std::vector<Measurement>>> m_measurements {}; + std::shared_ptr<std::vector<std::vector<Tracker::FaserSCT_SpacePoint>>> m_spacePoints {}; + std::shared_ptr<std::vector<std::vector<const Tracker::FaserSCT_Cluster*>>> m_clusters {}; + + const FaserSCT_ID* m_idHelper {nullptr}; + const TrackerDD::SCT_DetectorManager* m_detManager {nullptr}; + static std::pair<double, double> momentum(const std::map<int, Amg::Vector3D>& pos, double B=0.57); + + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool { + this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; + SG::ReadHandleKey<TrackCollection> m_trackCollection { + this, "TrackCollection", "SegmentFit", "Input track collection name" }; + + // covariance of the initial parameters + Gaudi::Property<double> m_sigmaCluster {this, "sigmaCluster", 0.04}; + Gaudi::Property<double> m_covLoc0 {this, "covLoc0", 1}; + Gaudi::Property<double> m_covLoc1 {this, "covLoc1", 1}; + Gaudi::Property<double> m_covPhi {this, "covPhi", 1}; + Gaudi::Property<double> m_covTheta {this, "covTheta", 1}; + Gaudi::Property<double> m_covQOverP {this, "covQOverP", 1}; + Gaudi::Property<double> m_covTime {this, "covTime", 1}; +}; + + +inline const std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> +SegmentFitClusterTrackFinderTool::initialTrackParameters() const { + return m_initialTrackParameters; +} + +inline const std::shared_ptr<const Acts::Surface> +SegmentFitClusterTrackFinderTool::initialSurface() const { + return m_initialSurface; +} + +inline const std::shared_ptr<std::vector<std::vector<IndexSourceLink>>> +SegmentFitClusterTrackFinderTool::sourceLinks() const { + return m_sourceLinks; +} + +inline const std::shared_ptr<std::vector<IdentifierLink>> +SegmentFitClusterTrackFinderTool::idLinks() const { + return m_idLinks; +} + +inline const std::shared_ptr<std::vector<std::vector<Measurement>>> +SegmentFitClusterTrackFinderTool::measurements() const { + return m_measurements; +} + +inline const std::shared_ptr<std::vector<std::vector<Tracker::FaserSCT_SpacePoint>>> +SegmentFitClusterTrackFinderTool::spacePoints() const { + return m_spacePoints; +} + +inline const std::shared_ptr<std::vector<std::vector<const Tracker::FaserSCT_Cluster*>>> +SegmentFitClusterTrackFinderTool::clusters() const { + return m_clusters; +} + +#endif // FASERACTSKALMANFILTER_SEGMENTFITCLUSTERTRACKFINDERTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/SegmentFitTrackFinderTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/SegmentFitTrackFinderTool.h new file mode 100644 index 0000000000000000000000000000000000000000..3f555be285fc792c42db3b8903f9e208e4fa7902 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/SegmentFitTrackFinderTool.h @@ -0,0 +1,98 @@ +#ifndef FASERACTSKALMANFILTER_SEGMENTFITTRACKFINDERTOOL_H +#define FASERACTSKALMANFILTER_SEGMENTFITTRACKFINDERTOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "Gaudi/Property.h" +#include "GaudiKernel/EventContext.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/StatusCode.h" +#include "StoreGate/ReadHandleKey.h" +#include <string> +#include <vector> + +#include "TrackerSpacePoint/FaserSCT_SpacePointContainer.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" +#include "FaserActsKalmanFilter/ITrackFinderTool.h" +#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" +#include "TrkTrack/TrackCollection.h" + +class FaserSCT_ID; +namespace TrackerDD { +class SCT_DetectorManager; +} + + +class SegmentFitTrackFinderTool : public extends<AthAlgTool, ITrackFinderTool> { +public: + SegmentFitTrackFinderTool(const std::string& type, const std::string& name, const IInterface* parent); + virtual ~SegmentFitTrackFinderTool() = default; + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + virtual StatusCode run() override; + + virtual const std::shared_ptr<const Acts::CurvilinearTrackParameters> initialTrackParameters() const override; + virtual const std::shared_ptr<const Acts::Surface> initialSurface() const override; + virtual const std::shared_ptr<std::vector<IndexSourceLink>> sourceLinks() const override; + virtual const std::shared_ptr<IdentifierLink> idLinks() const override; + virtual const std::shared_ptr<std::vector<Measurement>> measurements() const override; + virtual const std::shared_ptr<std::vector<Tracker::FaserSCT_SpacePoint>> spacePoints() const override; + +private: + std::shared_ptr<const Acts::CurvilinearTrackParameters> m_initialTrackParameters; + std::shared_ptr<const Acts::Surface> m_initialSurface; + std::shared_ptr<std::vector<IndexSourceLink>> m_sourceLinks {}; + std::shared_ptr<IdentifierLink> m_idLinks {}; + std::shared_ptr<std::vector<Measurement>> m_measurements {}; + std::shared_ptr<std::vector<Tracker::FaserSCT_SpacePoint>> m_spacePoints {}; + + const FaserSCT_ID* m_idHelper {nullptr}; + const TrackerDD::SCT_DetectorManager* m_detManager {nullptr}; + static double momentum(const std::map<int, Amg::Vector3D>& pos, double B=0.57) ; + + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool { + this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; + SG::ReadHandleKey<TrackCollection> m_trackCollection { + this, "TrackCollection", "SegmentFit", "Input track collection name" }; + SG::ReadHandleKey<FaserSCT_SpacePointContainer> m_spacePointContainerKey { + this, "SpacePoints", "SCT_SpacePointContainer", "Space point container"}; + + // covariance of the initial parameters + Gaudi::Property<double> m_covLoc0 {this, "covLoc0", 1}; + Gaudi::Property<double> m_covLoc1 {this, "covLoc1", 1}; + Gaudi::Property<double> m_covPhi {this, "covPhi", 1}; + Gaudi::Property<double> m_covTheta {this, "covTheta", 1}; + Gaudi::Property<double> m_covQOverP {this, "covQOverP", 1}; + Gaudi::Property<double> m_covTime {this, "covTime", 1}; +}; + + +inline const std::shared_ptr<const Acts::CurvilinearTrackParameters> + SegmentFitTrackFinderTool::initialTrackParameters() const { + return m_initialTrackParameters; +} + +inline const std::shared_ptr<const Acts::Surface> + SegmentFitTrackFinderTool::initialSurface() const { +return m_initialSurface; +} + +inline const std::shared_ptr<std::vector<IndexSourceLink>> + SegmentFitTrackFinderTool::sourceLinks() const { + return m_sourceLinks; +} + +inline const std::shared_ptr<IdentifierLink> +SegmentFitTrackFinderTool::idLinks() const { + return m_idLinks; +} + +inline const std::shared_ptr<std::vector<Measurement>> + SegmentFitTrackFinderTool::measurements() const { + return m_measurements; +} + +inline const std::shared_ptr<std::vector<Tracker::FaserSCT_SpacePoint>> + SegmentFitTrackFinderTool::spacePoints() const { + return m_spacePoints; +} +#endif // FASERACTSKALMANFILTER_SEGMENTFITTRACKFINDERTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/SummaryPlotTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/SummaryPlotTool.h new file mode 100644 index 0000000000000000000000000000000000000000..ea54ffc0f424409ce16887c8824ce271f9a342c2 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/SummaryPlotTool.h @@ -0,0 +1,67 @@ +#ifndef FASERACTSKALMANFILTER_SUMMARYPLOTTOOL_H +#define FASERACTSKALMANFILTER_SUMMARYPLOTTOOL_H + +#include "FaserActsKalmanFilter/PlotHelpers.h" +#include "Acts/EventData/TrackParameters.hpp" +#include "TProfile.h" +#include <map> +#include <string> + +class SummaryPlotTool { +public: + std::map<std::string, PlotHelpers::Binning> m_varBinning { + {"Eta", PlotHelpers::Binning("#eta", 40, 4, 12)}, + {"Phi", PlotHelpers::Binning("#phi", 100, -3.15, 3.15)}, + {"Pt", PlotHelpers::Binning("pT [GeV/c]", 40, 0, 20)}, + {"Num", PlotHelpers::Binning("N", 30, -0.5, 29.5)} + }; + + /// @brief Nested Cache struct + struct SummaryPlotCache { + TProfile* nStates_vs_eta; ///< Number of total states vs eta + TProfile* nMeasurements_vs_eta; ///< Number of non-outlier measurements vs eta + TProfile* nHoles_vs_eta; ///< Number of holes vs eta + TProfile* nOutliers_vs_eta; ///< Number of outliers vs eta + TProfile* nSharedHits_vs_eta; ///< Number of Shared Hits vs eta + TProfile* nStates_vs_pt; ///< Number of total states vs pt + TProfile* nMeasurements_vs_pt; ///< Number of non-outlier measurements vs pt + TProfile* nHoles_vs_pt; ///< Number of holes vs pt + TProfile* nOutliers_vs_pt; ///< Number of outliers vs pt + TProfile* nSharedHits_vs_pt; ///< Number of Shared Hits vs pt + }; + + /// Constructor + /// + SummaryPlotTool() = default; + + /// @brief book the track info plots + /// + /// @param trackSummaryPlotCache the cache for track info plots + void book(SummaryPlotCache& trackSummaryPlotCache) const; + + /// @brief fill reco track info w.r.t. fitted track parameters + /// + /// @param trackSummaryPlotCache cache object for track info plots + /// @param fittedParameters fitted track parameters of this track + /// @param nStates number of track states + /// @param nMeasurements number of measurements + /// @param nOutliers number of outliers + /// @param nHoles number of holes + /// @param nSharedHits number of shared hits + void fill(SummaryPlotCache& trackSummaryPlotCache, + const Acts::BoundTrackParameters& fittedParameters, size_t nStates, + size_t nMeasurements, size_t nOutliers, size_t nHoles, + size_t nSharedHits) const; + + /// @brief write the track info plots to file + /// + /// @param trackSummaryPlotCache cache object for track info plots + void write(const SummaryPlotCache& trackSummaryPlotCache) const; + + /// @brief delete the track info plots + /// + /// @param trackSummaryPlotCache cache object for track info plots + void clear(SummaryPlotCache& trackSummaryPlotCache) const; +}; + +#endif // FASERACTSKALMANFILTER_SUMMARYPLOTTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ThreeStationTrackSeedTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ThreeStationTrackSeedTool.h new file mode 100644 index 0000000000000000000000000000000000000000..a37f1dbf1061e636402e1069c49ac22a479c610b --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ThreeStationTrackSeedTool.h @@ -0,0 +1,102 @@ +#ifndef FASERACTSKALMANFILTER_THREESTATIONTRACKSEEDTOOL_H +#define FASERACTSKALMANFILTER_THREESTATIONTRACKSEEDTOOL_H + +#include "TrackerPrepRawData/FaserSCT_ClusterContainer.h" +#include "AthenaBaseComps/AthAlgTool.h" +#include "Gaudi/Property.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/StatusCode.h" + +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" +#include "FaserActsKalmanFilter/ITrackSeedTool.h" +#include "TrkTrack/TrackCollection.h" +#include <memory> +#include <string> +#include <vector> + +class FaserSCT_ID; +namespace TrackerDD { class SCT_DetectorManager; } + +class ThreeStationTrackSeedTool : public extends<AthAlgTool, ITrackSeedTool> { +public: + ThreeStationTrackSeedTool(const std::string& type, const std::string& name, const IInterface* parent); + virtual ~ThreeStationTrackSeedTool() = default; + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + virtual StatusCode run() override; + + const std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> initialTrackParameters() const override; + const std::shared_ptr<const Acts::Surface> initialSurface() const override; + const std::shared_ptr<std::vector<IndexSourceLink>> sourceLinks() const override; + const std::shared_ptr<IdentifierLink> idLinks() const override; + const std::shared_ptr<std::vector<Measurement>> measurements() const override; + const std::shared_ptr<std::vector<const Tracker::FaserSCT_Cluster*>> clusters() const override; + +private: + std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> m_initialTrackParameters; + std::shared_ptr<const Acts::Surface> m_initialSurface; + std::shared_ptr<std::vector<IndexSourceLink>> m_sourceLinks {}; + std::shared_ptr<IdentifierLink> m_idLinks {}; + std::shared_ptr<std::vector<Measurement>> m_measurements {}; + std::shared_ptr<std::vector<const Tracker::FaserSCT_Cluster*>> m_clusters {}; + + const FaserSCT_ID* m_idHelper {nullptr}; + const TrackerDD::SCT_DetectorManager* m_detManager {nullptr}; + + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool { + this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; + SG::ReadHandleKey<TrackCollection> m_trackCollection { + this, "TrackCollection", "SegmentFit", "Input track collection name" }; + SG::ReadHandleKey<Tracker::FaserSCT_ClusterContainer> m_clusterContainerKey { + this, "ClusterContainer", "SCT_ClusterContainer"}; + + // position resolution of a cluster + Gaudi::Property<double> m_std_cluster {this, "std_cluster", 0.04}; + + // covariance of the initial parameters + Gaudi::Property<double> m_covLoc0 {this, "covLoc0", 1}; + Gaudi::Property<double> m_covLoc1 {this, "covLoc1", 1}; + Gaudi::Property<double> m_covPhi {this, "covPhi", 1}; + Gaudi::Property<double> m_covTheta {this, "covTheta", 1}; + Gaudi::Property<double> m_covQOverP {this, "covQOverP", 1}; + Gaudi::Property<double> m_covTime {this, "covTime", 1}; + + Gaudi::Property<double> m_origin {this, "origin", 0, "z position of the reference surface"}; + + static Acts::CurvilinearTrackParameters get_params( + const Amg::Vector3D& position_st1, const Amg::Vector3D& position_st2, const Amg::Vector3D& position_st3, const Acts::BoundSymMatrix& cov, double origin); + static std::pair<double, double> momentum(const std::map<int, Amg::Vector3D>& pos, double B=0.57); +}; + +inline const std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> +ThreeStationTrackSeedTool::initialTrackParameters() const { + return m_initialTrackParameters; +} + +inline const std::shared_ptr<const Acts::Surface> +ThreeStationTrackSeedTool::initialSurface() const { + return m_initialSurface; +} + +inline const std::shared_ptr<std::vector<IndexSourceLink>> +ThreeStationTrackSeedTool::sourceLinks() const { + return m_sourceLinks; +} + +inline const std::shared_ptr<IdentifierLink> +ThreeStationTrackSeedTool::idLinks() const { + return m_idLinks; +} + +inline const std::shared_ptr<std::vector<Measurement>> +ThreeStationTrackSeedTool::measurements() const { + return m_measurements; +} + +inline const std::shared_ptr<std::vector<const Tracker::FaserSCT_Cluster*>> +ThreeStationTrackSeedTool::clusters() const { + return m_clusters; +} + + +#endif // FASERACTSKALMANFILTER_THREESTATIONTRACKSEEDTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TrackClassification.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TrackClassification.h new file mode 100644 index 0000000000000000000000000000000000000000..790cdb8f95643d270fe12e6e7a38ba0b6739382e --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TrackClassification.h @@ -0,0 +1,18 @@ +#ifndef FASERACTSKALMANFILTER_TRACKCLASSIFICATION_H +#define FASERACTSKALMANFILTER_TRACKCLASSIFICATION_H + +#include "FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h" +#include "TrackerSimData/TrackerSimDataCollection.h" + +struct ParticleHitCount { + int particleId; + size_t hitCount; +}; + +/// Identify all particles that contribute to a trajectory. +void identifyContributingParticles( + const TrackerSimDataCollection& simDataCollection, + const FaserActsRecMultiTrajectory& trajectories, size_t tip, + std::vector<ParticleHitCount>& particleHitCounts); + +#endif // FASERACTSKALMANFILTER_TRACKCLASSIFICATION_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TrackSelection.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TrackSelection.h new file mode 100644 index 0000000000000000000000000000000000000000..858bb15c82b1e1d58ce8d92698e17aacac0b9baf --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TrackSelection.h @@ -0,0 +1,20 @@ +#ifndef FASERACTSKALMANFILTER_TRACKSELECTION_H +#define FASERACTSKALMANFILTER_TRACKSELECTION_H + +#include "FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h" +#include "TrackerSimData/TrackerSimDataCollection.h" +#include "Acts/TrackFinding/CombinatorialKalmanFilter.hpp" + +using TrackFitterResult = +Acts::Result<Acts::CombinatorialKalmanFilterResult<IndexSourceLink>>; +using TrackFinderResult = std::vector<TrackFitterResult>; + +struct TrackQuality { + Acts::CombinatorialKalmanFilterResult<IndexSourceLink> track; + size_t nMeasurements; + double chi2; +}; + +void selectTracks(TrackFinderResult& results, std::vector<TrackQuality>& trackQuality); + +#endif // FASERACTSKALMANFILTER_TRACKSELECTION_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TrajectoryWriterTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TrajectoryWriterTool.h index 659cea7fa08321bb43a38fcc598a7054b119262c..0643ad9ce973f65453e72063701befaa3b2789ec 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TrajectoryWriterTool.h +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TrajectoryWriterTool.h @@ -7,7 +7,7 @@ class TFile; class TTree; -class FaserActsRecMultiTrajectory; +struct FaserActsRecMultiTrajectory; using TrajectoriesContainer = std::vector<FaserActsRecMultiTrajectory>; class TrajectoryWriterTool : public AthAlgTool { @@ -21,7 +21,7 @@ class TrajectoryWriterTool : public AthAlgTool { virtual StatusCode finalize() override; void writeout(TrajectoriesContainer trajectories, - Acts::GeometryContext geoContext,std::vector<Acts::CurvilinearTrackParameters> traj ) const; + Acts::GeometryContext geoContext, std::vector<Acts::CurvilinearTrackParameters> traj ) const; void clearVariables() const; @@ -60,6 +60,10 @@ class TrajectoryWriterTool : public AthAlgTool { mutable std::vector<float> m_x_hit; mutable std::vector<float> m_y_hit; mutable std::vector<float> m_z_hit; + mutable std::vector<float> m_meas_eLOC0; + mutable std::vector<float> m_meas_eLOC1; + mutable std::vector<float> m_meas_cov_eLOC0; + mutable std::vector<float> m_meas_cov_eLOC1; mutable std::vector<float> m_res_x_hit; mutable std::vector<float> m_res_y_hit; mutable std::vector<float> m_err_x_hit; diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TruthSeededTrackFinderTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TruthSeededTrackFinderTool.h new file mode 100644 index 0000000000000000000000000000000000000000..79425aa17c64a68e4c517170587a6fc84ac973c3 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TruthSeededTrackFinderTool.h @@ -0,0 +1,113 @@ +#ifndef FASERACTSKALMANFILTER_TRUTHSEEDEDTRACKFINDERTOOL_H +#define FASERACTSKALMANFILTER_TRUTHSEEDEDTRACKFINDERTOOL_H + +#include "Acts/Definitions/Units.hpp" +#include "AthenaBaseComps/AthAlgTool.h" +#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" +#include "FaserActsKalmanFilter/ITrackFinderTool.h" +#include "Gaudi/Property.h" +#include "GaudiKernel/EventContext.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/StatusCode.h" +#include "GeneratorObjects/McEventCollection.h" +#include "StoreGate/ReadHandleKey.h" +#include "TrackerSpacePoint/SpacePointForSeedCollection.h" +#include <string> +#include <vector> + +class FaserSCT_ID; +namespace TrackerDD { +class SCT_DetectorManager; +} + +using namespace Acts::UnitLiterals; + +class TruthSeededTrackFinderTool : public extends<AthAlgTool, ITrackFinderTool> { +public: + TruthSeededTrackFinderTool(const std::string& type, const std::string& name, const IInterface* parent); + virtual ~TruthSeededTrackFinderTool() = default; + + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + virtual StatusCode run() override; + + virtual const std::shared_ptr<const Acts::CurvilinearTrackParameters> initialTrackParameters() const override { + return m_initialTrackParameters; + } + + virtual const std::shared_ptr<const Acts::Surface> initialSurface() const override { + return m_initialSurface; + } + + virtual const std::shared_ptr<std::vector<IndexSourceLink>> sourceLinks() const override { + return m_sourceLinks; + } + + virtual const std::shared_ptr<IdentifierLink> idLinks() const override; + + virtual const std::shared_ptr<std::vector<Measurement>> measurements() const override { + return m_measurements; + } + + virtual const std::shared_ptr<std::vector<Tracker::FaserSCT_SpacePoint>> spacePoints() const override; + +private: + std::shared_ptr<const Acts::CurvilinearTrackParameters> m_initialTrackParameters; + std::shared_ptr<const Acts::Surface> m_initialSurface; + std::shared_ptr<std::vector<IndexSourceLink>> m_sourceLinks {}; + std::shared_ptr<IdentifierLink> m_idLinks {}; + std::shared_ptr<std::vector<Measurement>> m_measurements {}; + std::shared_ptr<std::vector<Tracker::FaserSCT_SpacePoint>> m_spacePoints {}; + + const FaserSCT_ID* m_idHelper{nullptr}; + const TrackerDD::SCT_DetectorManager* m_detManager{nullptr}; + + static std::vector<Acts::Vector3> map2vector(const std::map<int, Acts::Vector3>& positions, int station); + static Acts::Vector3 average(const std::vector<Acts::Vector3>& spacePoints); + static std::pair<Acts::Vector3, Acts::Vector3> linear_fit(const std::vector<Acts::Vector3>& position); + static std::pair<double, double> momentum2(const std::map<int, Acts::Vector3>& hits, double B=0.57) ; + + SG::ReadHandleKey<SpacePointForSeedCollection> m_spacePointCollectionKey { + this, "FaserSpacePointsSeedsName", "Seeds_SpacePointContainer"}; + SG::ReadHandleKey<McEventCollection> m_mcEventCollectionKey {this, "McEventCollection", "BeamTruthEvent"}; + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool { + this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; + + Gaudi::Property<bool> m_useTrueInitialParameters {this, "useTrueInitialParameters", true}; + + // covariance matrix of measurement + Gaudi::Property<double> m_covMeas00 {this, "covMeas00", 0.0004}; + Gaudi::Property<double> m_covMeas01 {this, "covMeas01", 0.01}; + Gaudi::Property<double> m_covMeas10 {this, "covMeas10", 0.01}; + Gaudi::Property<double> m_covMeas11 {this, "covMeas11", 0.64}; + + // smearing of initial parameters + Gaudi::Property<double> m_sigmaLoc0 {this, "sigmaLoc0", 0}; + Gaudi::Property<double> m_sigmaLoc1 {this, "sigmaLoc1", 0}; + Gaudi::Property<double> m_sigmaPhi {this, "sigmaPhi", 0}; + Gaudi::Property<double> m_sigmaTheta {this, "sigmaTheta", 0}; + Gaudi::Property<double> m_sigmaP {this, "sigmaP", 0}; + Gaudi::Property<double> m_sigmaTime {this, "sigmaTime", 0}; + + // covariance parameters + Gaudi::Property<double> m_covLoc0 {this, "covLoc0", 1}; + Gaudi::Property<double> m_covLoc1 {this, "covLoc1", 1}; + Gaudi::Property<double> m_covPhi {this, "covPhi", 1}; + Gaudi::Property<double> m_covTheta {this, "covTheta", 1}; + Gaudi::Property<double> m_covQOverP {this, "covQOverP", 1}; + Gaudi::Property<double> m_covTime {this, "covTime", 1}; +}; + +inline const std::shared_ptr<std::vector<Tracker::FaserSCT_SpacePoint>> +TruthSeededTrackFinderTool::spacePoints() const { + return m_spacePoints; +} + +inline const std::shared_ptr<IdentifierLink> +TruthSeededTrackFinderTool::idLinks() const { + return m_idLinks; +} + + +#endif // FASERACTSKALMANFILTER_TRUTHSEEDEDTRACKFINDERTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TruthTrackFinderTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TruthTrackFinderTool.h new file mode 100644 index 0000000000000000000000000000000000000000..3bfe35b68013a3ef323a43c245e046b7248be094 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TruthTrackFinderTool.h @@ -0,0 +1,109 @@ +#ifndef FASERACTSKALMANFILTER_TRUTHTRACKFINDERTOOL_H +#define FASERACTSKALMANFILTER_TRUTHTRACKFINDERTOOL_H + +#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" +#include "AthenaBaseComps/AthAlgTool.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" +#include "FaserActsKalmanFilter/ITrackFinderTool.h" +#include "Gaudi/Property.h" +#include "GaudiKernel/EventContext.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/StatusCode.h" +#include "StoreGate/ReadHandleKey.h" +#include "TrackerSimEvent/FaserSiHitCollection.h" +#include <string> +#include <vector> + +class FaserSCT_ID; +namespace TrackerDD { +class SCT_DetectorManager; +} + + +class TruthTrackFinderTool : public extends<AthAlgTool, ITrackFinderTool> { +public: + TruthTrackFinderTool(const std::string& type, const std::string& name, const IInterface* parent); + virtual ~TruthTrackFinderTool() = default; + + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + virtual StatusCode run() override; + + virtual const std::shared_ptr<const Acts::CurvilinearTrackParameters> initialTrackParameters() const override { + return m_initialTrackParameters; + } + + virtual const std::shared_ptr<const Acts::Surface> initialSurface() const override { + return m_initialSurface; + } + + virtual const std::shared_ptr<std::vector<IndexSourceLink>> sourceLinks() const override { + return m_sourceLinks; + } + + virtual const std::shared_ptr<IdentifierLink> idLinks() const override; + + virtual const std::shared_ptr<std::vector<Measurement>> measurements() const override { + return m_measurements; + } + + virtual const std::shared_ptr<std::vector<Tracker::FaserSCT_SpacePoint>> spacePoints() const override; + +private: + std::shared_ptr<const Acts::CurvilinearTrackParameters> m_initialTrackParameters; + std::shared_ptr<const Acts::Surface> m_initialSurface; + std::shared_ptr<std::vector<IndexSourceLink>> m_sourceLinks {}; + std::shared_ptr<IdentifierLink> m_idLinks {}; + std::shared_ptr<std::vector<Measurement>> m_measurements {}; + std::shared_ptr<std::vector<Tracker::FaserSCT_SpacePoint>> m_spacePoints {}; + + const FaserSCT_ID* m_idHelper{nullptr}; + const TrackerDD::SCT_DetectorManager* m_detManager{nullptr}; + + SG::ReadHandleKey<FaserSiHitCollection> m_siHitCollectionKey { + this, "FaserSiHitCollection", "SCT_Hits"}; + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool { + this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; + + // smearing of measurements + Gaudi::Property<double> m_sigma0 {this, "sigmaMeasLoc0", 0}; + Gaudi::Property<double> m_sigma1 {this, "sigmaMeasLoc1", 0}; + + // covariance of the measurements + Gaudi::Property<double> m_covMeasLoc0 {this, "covMeasLoc0", 0.01}; + Gaudi::Property<double> m_covMeasLoc1 {this, "covMeasLoc1", 0.01}; + + // smearing of initial parameters + Gaudi::Property<double> m_sigmaLoc0 {this, "sigmaLoc0", 0}; + Gaudi::Property<double> m_sigmaLoc1 {this, "sigmaLoc1", 0}; + Gaudi::Property<double> m_sigmaPhi {this, "sigmaPhi", 0}; + Gaudi::Property<double> m_sigmaTheta {this, "sigmaTheta", 0}; + Gaudi::Property<double> m_sigmaP {this, "sigmaP", 0}; + Gaudi::Property<double> m_sigmaTime {this, "sigmaTime", 0}; + + // covariance of the initial parameters + Gaudi::Property<double> m_covLoc0 {this, "covLoc0", 1}; + Gaudi::Property<double> m_covLoc1 {this, "covLoc1", 1}; + Gaudi::Property<double> m_covPhi {this, "covPhi", 1}; + Gaudi::Property<double> m_covTheta {this, "covTheta", 1}; + Gaudi::Property<double> m_covQOverP {this, "covQOverP", 1}; + Gaudi::Property<double> m_covTime {this, "covTime", 1}; + + // TODO get parameters of first layer from tracker geometry + Gaudi::Property<int> m_first_station {this, "first_station", 1, "first station for which the initial track parameters are calculated"}; + Gaudi::Property<int> m_first_layer {this, "first_layer", 0, "first layer for which the initial track parameters are calculated"}; + Gaudi::Property<int> m_first_side {this, "first_side", 1, "first side for which the initial track parameters are calculated"}; +}; + +inline const std::shared_ptr<std::vector<Tracker::FaserSCT_SpacePoint>> + TruthTrackFinderTool::spacePoints() const { + return m_spacePoints; +} + +inline const std::shared_ptr<IdentifierLink> +TruthTrackFinderTool::idLinks() const { + return m_idLinks; +} + + +#endif // FASERACTSKALMANFILTER_TRUTHTRACKFINDERTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/python/CombinatorialKalmanFilterConfig.py b/Tracking/Acts/FaserActsKalmanFilter/python/CombinatorialKalmanFilterConfig.py index 46c01fd06268dddf34867f76d358e4ab10f961e3..8021e9319d7dcf7d7205a0c1547f9bbffd4d5625 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/python/CombinatorialKalmanFilterConfig.py +++ b/Tracking/Acts/FaserActsKalmanFilter/python/CombinatorialKalmanFilterConfig.py @@ -1,43 +1,78 @@ # Copyright (C) 2002-2021 CERN for the benefit of the ATLAS and FASER collaborations +from FaserSCT_GeoModel.FaserSCT_GeoModelConfig import FaserSCT_GeometryCfg from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg +from MagFieldServices.MagFieldServicesConfig import MagneticFieldSvcCfg +from FaserActsGeometry.ActsGeometryConfig import ActsTrackingGeometrySvcCfg -def CombinatorialKalmanFilter_OutputCfg(flags): +def FaserActsAlignmentCondAlgCfg(flags, **kwargs): acc = ComponentAccumulator() - acc.merge(OutputStreamCfg(flags, "ESD")) - ostream = acc.getEventAlgo("OutputStreamESD") - ostream.TakeItemsFromInput = True + acc.addCondAlgo(CompFactory.FaserActsAlignmentCondAlg(name="FaserActsAlignmentCondAlg", **kwargs)) return acc -def CombinatorialKalmanFilter_OutputAODCfg(flags): + +def CombinatorialKalmanFilter_OutputCfg(flags): acc = ComponentAccumulator() itemList = ["xAOD::EventInfo#*", "xAOD::EventAuxInfo#*", - "FaserSCT_RDO_Container#*", - "xAOD::FaserTriggerData#*", - "xAOD::FaserTriggerDataAux#*", - "ScintWaveformContainer#*", "TrackCollection#*", - "xAOD::WaveformHitContainer#*", - "xAOD::WaveformHitAuxContainer#*", - "xAOD::WaveformClock#*", - "xAOD::WaveformClockAuxInfo#*" ] - acc.merge(OutputStreamCfg(flags, "AOD",itemList)) - ostream = acc.getEventAlgo("OutputStreamAOD") + acc.merge(OutputStreamCfg(flags, "ESD", itemList)) + ostream = acc.getEventAlgo("OutputStreamESD") ostream.TakeItemsFromInput = True return acc - def CombinatorialKalmanFilterCfg(flags, **kwargs): - acc = ComponentAccumulator() - kwargs.setdefault("SpacePointsSCTName", "SCT_SpacePointContainer") - combinatorialKalmanFilterAlg = CompFactory.CombinatorialKalmanFilterAlg(**kwargs) - acc.addEventAlgo(combinatorialKalmanFilterAlg) + # acc = ComponentAccumulator() + acc = FaserSCT_GeometryCfg(flags) + acc.merge(MagneticFieldSvcCfg(flags)) + # acc.merge(FaserActsAlignmentCondAlgCfg(flags)) + acts_tracking_geometry_svc = ActsTrackingGeometrySvcCfg(flags) + acc.merge(acts_tracking_geometry_svc ) + +# track_seed_tool = CompFactory.ClusterTrackSeedTool() + track_seed_tool = CompFactory.ThreeStationTrackSeedTool() + sigma_loc0 = 1.9e-2 + sigma_loc1 = 9e-1 + sigma_phi = 3.3e-2 + sigma_theta = 2.9e-4 + p = 1000 + sigma_p = 0.1 * p + sigma_qop = sigma_p / (p * p) + initial_variance_inflation = [100, 100, 100, 100, 100] + track_seed_tool.covLoc0 = initial_variance_inflation[0] * sigma_loc1 * sigma_loc1 + track_seed_tool.covLoc1 = initial_variance_inflation[1] * sigma_loc0 * sigma_loc0 + track_seed_tool.covPhi = initial_variance_inflation[2] * sigma_phi * sigma_phi + track_seed_tool.covTheta = initial_variance_inflation[3] * sigma_theta * sigma_theta + track_seed_tool.covQOverP = initial_variance_inflation[4] * sigma_qop * sigma_qop + track_seed_tool.std_cluster = 0.023 + track_seed_tool.origin = 0 + + trajectory_states_writer_tool = CompFactory.RootTrajectoryStatesWriterTool() + trajectory_states_writer_tool.MC = True + + trajectory_summary_writer_tool = CompFactory.RootTrajectorySummaryWriterTool() + + actsExtrapolationTool = CompFactory.FaserActsExtrapolationTool("FaserActsExtrapolationTool") + actsExtrapolationTool.MaxSteps = 1000 + actsExtrapolationTool.TrackingGeometryTool = CompFactory.FaserActsTrackingGeometryTool("TrackingGeometryTool") + performance_writer_tool = CompFactory.PerformanceWriterTool("PerformanceWriterTool") + performance_writer_tool.ExtrapolationTool = actsExtrapolationTool + + ckf = CompFactory.CombinatorialKalmanFilterAlg(**kwargs) + ckf.TrackSeed = track_seed_tool + ckf.ActsLogging = "INFO" + ckf.RootTrajectoryStatesWriterTool = trajectory_states_writer_tool + ckf.RootTrajectorySummaryWriterTool = trajectory_summary_writer_tool + ckf.PerformanceWriterTool = performance_writer_tool + ckf.nTrajectories = 2 + + ckf.nMax = 1 + ckf.chi2Max = 15 + acc.addEventAlgo(ckf) acc.merge(CombinatorialKalmanFilter_OutputCfg(flags)) - acc.merge(CombinatorialKalmanFilter_OutputAODCfg(flags)) return acc diff --git a/Tracking/Acts/FaserActsKalmanFilter/python/FaserActsKalmanFilterConfig.py b/Tracking/Acts/FaserActsKalmanFilter/python/FaserActsKalmanFilterConfig.py index 6d6167c051b868d6032355e5bfd58d2a0f8296bd..cc44658845f4202f7295faf93de273cee776c552 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/python/FaserActsKalmanFilterConfig.py +++ b/Tracking/Acts/FaserActsKalmanFilter/python/FaserActsKalmanFilterConfig.py @@ -1,50 +1,161 @@ # Copyright (C) 2002-2021 CERN for the benefit of the ATLAS and FASER collaborations +from math import pi from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg from MagFieldServices.MagFieldServicesConfig import MagneticFieldSvcCfg -FaserActsKalmanFilterAlg,FaserActsTrackingGeometrySvc, FaserActsTrackingGeometryTool, FaserActsExtrapolationTool,FaserActsAlignmentCondAlg, THistSvc = CompFactory.getComps("FaserActsKalmanFilterAlg","FaserActsTrackingGeometrySvc", "FaserActsTrackingGeometryTool", "FaserActsExtrapolationTool","FaserActsAlignmentCondAlg", "THistSvc") +# FaserActsKalmanFilterAlg,FaserActsTrackingGeometrySvc, FaserActsTrackingGeometryTool, FaserActsExtrapolationTool,FaserActsAlignmentCondAlg, THistSvc = CompFactory.getComps("FaserActsKalmanFilterAlg","FaserActsTrackingGeometrySvc", "FaserActsTrackingGeometryTool", "FaserActsExtrapolationTool","FaserActsAlignmentCondAlg", "THistSvc") +# +# def FaserActsTrackingGeometrySvcCfg(flags, **kwargs): +# acc = ComponentAccumulator() +# acc.addService(FaserActsTrackingGeometrySvc(name = "FaserActsTrackingGeometrySvc", **kwargs)) +# return acc +# +# def FaserActsAlignmentCondAlgCfg(flags, **kwargs): +# acc = ComponentAccumulator() +# acc.addCondAlgo(CompFactory.FaserActsAlignmentCondAlg(name = "FaserActsAlignmentCondAlg", **kwargs)) +# #acc.addCondAlgo(CompFactory.NominalAlignmentCondAlg(name = "NominalAlignmentCondAlg", **kwargs)) +# return acc +# +# def FaserActsKalmanFilterCfg(flags, **kwargs): +# acc = ComponentAccumulator() +# # Initialize field service +# acc.merge(MagneticFieldSvcCfg(flags)) +# +# acc.merge(FaserActsTrackingGeometrySvcCfg(flags, **kwargs)) +# acc.merge(FaserActsAlignmentCondAlgCfg(flags, **kwargs)) +# +# kwargs.setdefault("FaserSpacePointsSeedsName", "Seeds_SpacePointContainer") +# actsKalmanFilterAlg = FaserActsKalmanFilterAlg(**kwargs) +# #actsKalmanFilterAlg.TrackingGeometryTool = FaserActsTrackingGeometryTool("TrackingGeometryTool") +# actsExtrapolationTool=FaserActsExtrapolationTool("FaserActsExtrapolationTool") +# actsExtrapolationTool.FieldMode="FASER" +# #actsExtrapolationTool.FieldMode="Constant" +# actsExtrapolationTool.TrackingGeometryTool=FaserActsTrackingGeometryTool("TrackingGeometryTool") +# actsKalmanFilterAlg.ExtrapolationTool=actsExtrapolationTool +# acc.addEventAlgo(actsKalmanFilterAlg) +# histSvc= THistSvc() +# histSvc.Output += [ "KalmanTracks DATAFILE='KalmanTracks.root' OPT='RECREATE'" ] +# acc.addService(histSvc) +# acc.merge(FaserActsKalmanFilter_OutputCfg(flags)) +# return acc +# +# def FaserActsKalmanFilter_OutputCfg(flags): +# """Return ComponentAccumulator with Output for SCT. Not standalone.""" +# acc = ComponentAccumulator() +# acc.merge(OutputStreamCfg(flags, "ESD")) +# ostream = acc.getEventAlgo("OutputStreamESD") +# ostream.TakeItemsFromInput = True +# return acc -def FaserActsTrackingGeometrySvcCfg(flags, **kwargs): +def FaserActsKalmanFilter_OutputCfg(flags): acc = ComponentAccumulator() - acc.addService(FaserActsTrackingGeometrySvc(name = "FaserActsTrackingGeometrySvc", **kwargs)) - return acc + itemList = ["xAOD::EventInfo#*", + "xAOD::EventAuxInfo#*", + "TrackCollection#*", + ] + acc.merge(OutputStreamCfg(flags, "ESD", itemList)) + ostream = acc.getEventAlgo("OutputStreamESD") + ostream.TakeItemsFromInput = True + return acc -def FaserActsAlignmentCondAlgCfg(flags, **kwargs): +def FaserActsKalmanFilter_OutputAODCfg(flags): acc = ComponentAccumulator() - acc.addCondAlgo(CompFactory.FaserActsAlignmentCondAlg(name = "FaserActsAlignmentCondAlg", **kwargs)) - #acc.addCondAlgo(CompFactory.NominalAlignmentCondAlg(name = "NominalAlignmentCondAlg", **kwargs)) + itemList = ["xAOD::EventInfo#*", + "xAOD::EventAuxInfo#*", + "FaserSCT_RDO_Container#*", + "xAOD::FaserTriggerData#*", + "xAOD::FaserTriggerDataAux#*", + "ScintWaveformContainer#*", + "TrackCollection#*", + "xAOD::WaveformHitContainer#*", + "xAOD::WaveformHitAuxContainer#*", + "xAOD::WaveformClock#*", + "xAOD::WaveformClockAuxInfo#*" + ] + acc.merge(OutputStreamCfg(flags, "AOD",itemList)) + ostream = acc.getEventAlgo("OutputStreamAOD") + ostream.TakeItemsFromInput = True return acc + def FaserActsKalmanFilterCfg(flags, **kwargs): acc = ComponentAccumulator() - # Initialize field service - acc.merge(MagneticFieldSvcCfg(flags)) - - acc.merge(FaserActsTrackingGeometrySvcCfg(flags, **kwargs)) - acc.merge(FaserActsAlignmentCondAlgCfg(flags, **kwargs)) - - kwargs.setdefault("FaserSpacePointsSeedsName", "Seeds_SpacePointContainer") - actsKalmanFilterAlg = FaserActsKalmanFilterAlg(**kwargs) - #actsKalmanFilterAlg.TrackingGeometryTool = FaserActsTrackingGeometryTool("TrackingGeometryTool") - actsExtrapolationTool=FaserActsExtrapolationTool("FaserActsExtrapolationTool") - actsExtrapolationTool.FieldMode="FASER" - #actsExtrapolationTool.FieldMode="Constant" - actsExtrapolationTool.TrackingGeometryTool=FaserActsTrackingGeometryTool("TrackingGeometryTool") - actsKalmanFilterAlg.ExtrapolationTool=actsExtrapolationTool - acc.addEventAlgo(actsKalmanFilterAlg) - histSvc= THistSvc() - histSvc.Output += [ "KalmanTracks DATAFILE='KalmanTracks.root' OPT='RECREATE'" ] - acc.addService(histSvc) - acc.merge(FaserActsKalmanFilter_OutputCfg(flags)) - return acc + track_finder_tool = CompFactory.MultiTrackFinderTool() + # track_finder_tool = CompFactory.SegmentFitClusterTrackFinderTool() + # track_finder_tool = CompFactory.SegmentFitTrackFinderTool() + sigma_loc0 = 1.9e-2 + sigma_loc1 = 9e-1 + sigma_phi = 3.3e-2 + sigma_theta = 2.9e-4 + sigma_p_rel = 0.1 + p = 1 + sigma_qop = 0.1 * p / (p * p) + initial_variance_inflation = [100, 100, 1000, 1000, 1000] + track_finder_tool.covLoc0 = initial_variance_inflation[0] * sigma_loc1 * sigma_loc1 + track_finder_tool.covLoc1 = initial_variance_inflation[1] * sigma_loc0 * sigma_loc0 + track_finder_tool.covPhi = initial_variance_inflation[2] * sigma_phi * sigma_phi + track_finder_tool.covTheta = initial_variance_inflation[3] * sigma_theta * sigma_theta + track_finder_tool.covQOverP = initial_variance_inflation[4] * sigma_qop * sigma_qop + # track_finder_tool.sigmaCluster = 0.04 + # track_finder_tool.covLoc0 = 1e-1 + # track_finder_tool.covLoc1 = 1e-1 + # track_finder_tool.covPhi = 1e-1 + # track_finder_tool.covTheta = 1e-1 + # track_finder_tool.covQOverP = 1e-1 -def FaserActsKalmanFilter_OutputCfg(flags): - """Return ComponentAccumulator with Output for SCT. Not standalone.""" - acc = ComponentAccumulator() - acc.merge(OutputStreamCfg(flags, "ESD")) - ostream = acc.getEventAlgo("OutputStreamESD") - ostream.TakeItemsFromInput = True + # track_finder_tool = CompFactory.TruthSeededTrackFinderTool() + # track_finder_tool.useTrueInitialParameters = False + # track_finder_tool.covMeas00 = 0.0004 + # track_finder_tool.covMeas01 = 0.01 + # track_finder_tool.covMeas10 = 0.01 + # track_finder_tool.covMeas11 = 0.64 + # track_finder_tool.covLoc0 = 1e-4 + # track_finder_tool.covLoc1 = 1e-4 + # track_finder_tool.covPhi = 1e-4 + # track_finder_tool.covTheta = 1e-4 + # track_finder_tool.covQOverP = 1e-4 + + # track_finder_tool.covLoc0 = 1e-1 + # track_finder_tool.covLoc1 = 1e-1 + # track_finder_tool.covPhi = 1e-1 + # track_finder_tool.covTheta = 1e-1 + # track_finder_tool.covQOverP = 1e-1 + + # track_finder_tool.sigmaLoc0 = 0.02 + # track_finder_tool.sigmaLoc1 = 0.8 + # track_finder_tool.sigmaPhi = 2 * pi/180 + # track_finder_tool.sigmaTheta = 2 * pi/180 + # track_finder_tool.sigmaP = 0.1 + + # track_finder_tool = CompFactory.TruthTrackFinderTool() + # track_finder_tool.first_side = 1 + # track_finder_tool.sigmaMeasLoc0 = 0.02 + # track_finder_tool.sigmaMeasLoc1 = 0.8 + # track_finder_tool.covMeasLoc0 = 0.02 * 0.02 * 10 + # track_finder_tool.covMeasLoc1 = 0.8 * 0.8 * 10 + # track_finder_tool.sigmaLoc0 = 0 + # track_finder_tool.sigmaLoc1 = 0 + # track_finder_tool.sigmaPhi = 0 + # track_finder_tool.sigmaTheta = 0 + # track_finder_tool.sigmaP = 0 + # track_finder_tool.covLoc0 = 1e-3 + # track_finder_tool.covLoc1 = 1e-3 + # track_finder_tool.covPhi = 1e-3 + # track_finder_tool.covTheta = 1e-3 + # track_finder_tool.covQOverP = 1e-3 + trajectory_writer_tool = CompFactory.TrajectoryWriterTool() + trajectory_writer_tool.FilePath = "KalmanFilterTrajectories.root" + # trajectory_states_writer_tool = CompFactory.RootTrajectoryStatesWriterTool() + # trajectory_states_writer_tool.FilePath = "TrajectoryStates.root" + kalman_filter = CompFactory.FaserActsKalmanFilterAlg(**kwargs) + # kalman_filter.RootTrajectoryStatesWriterTool = trajectory_states_writer_tool + kalman_filter.OutputTool = trajectory_writer_tool + kalman_filter.TrackFinderTool = track_finder_tool + kalman_filter.ActsLogging = "VERBOSE" + acc.addEventAlgo(kalman_filter) + acc.merge(FaserActsKalmanFilter_OutputCfg(flags)) + # acc.merge(FaserActsKalmanFilter_OutputAODCfg(flags)) return acc diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/ClusterTrackSeedTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/ClusterTrackSeedTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..8d78c9f0eaa1088675806b0a9aee1472ce3396ff --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/ClusterTrackSeedTool.cxx @@ -0,0 +1,129 @@ +#include "FaserActsKalmanFilter/ClusterTrackSeedTool.h" +#include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "TrackerPrepRawData/FaserSCT_ClusterCollection.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "Identifier/Identifier.h" +#include "Acts/Geometry/GeometryIdentifier.hpp" + + +// FIXME make this a method of ClusterTrackSeedTool +std::pair<double, double> momentum(const std::map<int, Amg::Vector3D>& pos, double B=0.57) { + Acts::Vector3 vec_l = pos.at(3) - pos.at(1); + double abs_l = std::sqrt(vec_l.y() * vec_l.y() + vec_l.z() * vec_l.z()); + double t = (pos.at(2).z() - pos.at(1).z()) / (pos.at(3).z() - pos.at(1).z()); + Acts::Vector3 vec_m = pos.at(1) + t * vec_l; + Acts::Vector3 vec_s = pos.at(2) - vec_m; + double abs_s = std::sqrt(vec_s.y() * vec_s.y() + vec_s.z() * vec_s.z()); + double p_yz = 0.3 * abs_l * abs_l * B / (8 * abs_s * 1000); + double charge = vec_s.y() < 0 ? 1 : -1; + return std::make_pair(p_yz, charge); +} + + +ClusterTrackSeedTool::ClusterTrackSeedTool( + const std::string& type, const std::string& name, const IInterface* parent) + : base_class(type, name, parent) {} + + +StatusCode ClusterTrackSeedTool::initialize() { + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + ATH_CHECK(detStore()->retrieve(m_detManager, "SCT")); + ATH_CHECK(m_trackingGeometryTool.retrieve()); + ATH_CHECK(m_trackCollection.initialize()); + ATH_CHECK(m_clusterContainerKey.initialize()); + return StatusCode::SUCCESS; +} + + +StatusCode ClusterTrackSeedTool::run() { + // create track seeds for multiple tracks + SG::ReadHandle<TrackCollection> trackCollection {m_trackCollection}; + ATH_CHECK(trackCollection.isValid()); + + SG::ReadHandle<Tracker::FaserSCT_ClusterContainer> clusterContainer {m_clusterContainerKey}; + ATH_CHECK(clusterContainer.isValid()); + + using IdentifierMap = std::map<Identifier, Acts::GeometryIdentifier>; + std::shared_ptr<IdentifierMap> identifierMap = m_trackingGeometryTool->getIdentifierMap(); + + const int kSize = 1; + using ThisMeasurement = Acts::Measurement<IndexSourceLink, Acts::BoundIndices, kSize>; + std::array<Acts::BoundIndices, kSize> Indices = {Acts::eBoundLoc0}; + std::vector<IndexSourceLink> sourceLinks; + std::vector<Measurement> measurements; + std::map<Index, Identifier> identifierLinkMap; + std::vector<const Tracker::FaserSCT_Cluster*> clusters {}; + for (const Tracker::FaserSCT_ClusterCollection* clusterCollection : *clusterContainer) { + for (const Tracker::FaserSCT_Cluster* cluster : *clusterCollection) { + Identifier id = cluster->detectorElement()->identify(); + identifierLinkMap[measurements.size()] = id; + Acts::GeometryIdentifier geoId = identifierMap->at(id); + IndexSourceLink sourceLink(geoId, measurements.size()); + // create measurement + const auto& par = cluster->localPosition(); + Eigen::Matrix<double, 1, 1> pos {par.x(),}; + Eigen::Matrix<double, 1, 1> cov {m_std_cluster * m_std_cluster,}; + ThisMeasurement meas(sourceLink, Indices, pos, cov); + sourceLinks.push_back(sourceLink); + measurements.emplace_back(std::move(meas)); + clusters.push_back(cluster); + } + } + + + std::map<int, std::vector<Amg::Vector3D>> station_position_map; + for (const Trk::Track* track : *trackCollection) { + for (const Trk::TrackStateOnSurface* trackState : *(track->trackStateOnSurfaces())) { + auto clusterOnTrack = dynamic_cast<const Tracker::FaserSCT_ClusterOnTrack*> (trackState->measurementOnTrack()); + if (clusterOnTrack) { + Identifier id = clusterOnTrack->identify(); + int station = m_idHelper->station(id); + auto fitParameters = track->trackParameters()->front(); + Amg::Vector3D fitPosition = fitParameters->position(); + station_position_map[station].push_back(fitPosition); + break; + } + } + } + + Acts::BoundSymMatrix cov = Acts::BoundSymMatrix::Zero(); + cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = m_covLoc0; + cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = m_covLoc1; + cov(Acts::eBoundPhi, Acts::eBoundPhi) = m_covPhi; + cov(Acts::eBoundTheta, Acts::eBoundTheta) = m_covTheta; + cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = m_covQOverP; + cov(Acts::eBoundTime, Acts::eBoundTime) = m_covTime; + + std::vector<Acts::CurvilinearTrackParameters> initParams {}; + for (const Amg::Vector3D& pos1 : station_position_map[1]) { + for (const Amg::Vector3D& pos2 : station_position_map[2]) { + initParams.push_back(get_params(pos1, pos2, cov, m_origin)); + } + } + + m_initialTrackParameters = std::make_shared<std::vector<Acts::CurvilinearTrackParameters>>(initParams); + m_sourceLinks = std::make_shared<std::vector<IndexSourceLink>>(sourceLinks); + m_idLinks = std::make_shared<IdentifierLink>(identifierLinkMap); + m_measurements = std::make_shared<std::vector<Measurement>>(measurements); + m_initialSurface = Acts::Surface::makeShared<Acts::PlaneSurface>( + Acts::Vector3 {0, 0, m_origin}, Acts::Vector3{0, 0, 1}); + m_clusters = std::make_shared<std::vector<const Tracker::FaserSCT_Cluster*>>(clusters); + + return StatusCode::SUCCESS; +} + + +StatusCode ClusterTrackSeedTool::finalize() { + return StatusCode::SUCCESS; +} + + +Acts::CurvilinearTrackParameters ClusterTrackSeedTool::get_params( + const Amg::Vector3D& position_st1, const Amg::Vector3D& position_st2, const Acts::BoundSymMatrix& cov, double origin) { + Acts::Vector3 dir = position_st2 - position_st1; + Acts::Vector3 pos = position_st1 - (position_st1.z() - origin)/dir.z() * dir; + Acts::Vector4 pos4 {pos.x(), pos.y(), pos.z(), 0}; + return Acts::CurvilinearTrackParameters(pos4, dir, 100000000, 1, cov); +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/CombinatorialKalmanFilterAlg.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/CombinatorialKalmanFilterAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ebc292de212566ae8e79cc793eabcdc6e679c9fa --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/CombinatorialKalmanFilterAlg.cxx @@ -0,0 +1,388 @@ +#include "FaserActsKalmanFilter/CombinatorialKalmanFilterAlg.h" + +#include "StoreGate/ReadHandle.h" +#include "StoreGate/ReadCondHandleKey.h" +#include "TrackerSpacePoint/FaserSCT_SpacePointCollection.h" +#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrkPrepRawData/PrepRawData.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" +#include "TrkRIO_OnTrack/RIO_OnTrack.h" +#include "TrkSurfaces/Surface.h" +#include "Identifier/Identifier.h" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/EventData/TrackParameters.hpp" +#include "FaserActsKalmanFilter/IndexSourceLink.h" +#include "FaserActsKalmanFilter/Measurement.h" +#include "FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h" +#include "Acts/Surfaces/PerigeeSurface.hpp" +#include "Acts/MagneticField/MagneticFieldContext.hpp" +#include "FaserActsKalmanFilter/TrackSelection.h" +#include "FaserActsKalmanFilter/MyAmbiguitySolver.h" +#include <algorithm> + +using TrajectoriesContainer = std::vector<FaserActsRecMultiTrajectory>; +std::array<Acts::BoundIndices, 2> indices = {Acts::eBoundLoc0, Acts::eBoundLoc1}; + + +CombinatorialKalmanFilterAlg::CombinatorialKalmanFilterAlg( + const std::string& name, ISvcLocator* pSvcLocator) + : AthAlgorithm(name, pSvcLocator) {} + + +StatusCode CombinatorialKalmanFilterAlg::initialize() { + ATH_CHECK(m_fieldCondObjInputKey.initialize()); + ATH_CHECK(m_trackingGeometryTool.retrieve()); + ATH_CHECK(m_trackSeedTool.retrieve()); + // ATH_CHECK(m_trackCollection.initialize()); + if (m_performanceWriter) { + ATH_CHECK(m_performanceWriterTool.retrieve()); + } + if (m_statesWriter) { + ATH_CHECK(m_trajectoryStatesWriterTool.retrieve()); + } + if (m_summaryWriter) { + ATH_CHECK(m_trajectorySummaryWriterTool.retrieve()); + } + ATH_CHECK(detStore()->retrieve(m_idHelper,"FaserSCT_ID")); + m_fit = makeTrackFinderFunction(m_trackingGeometryTool->trackingGeometry(), + m_resolvePassive, m_resolveMaterial, m_resolveSensitive); + // FIXME fix Acts logging level + if (m_actsLogging == "VERBOSE") { + m_logger = Acts::getDefaultLogger("KalmanFitter", Acts::Logging::VERBOSE); + } else if (m_actsLogging == "DEBUG") { + m_logger = Acts::getDefaultLogger("KalmanFitter", Acts::Logging::DEBUG); + } else { + m_logger = Acts::getDefaultLogger("KalmanFitter", Acts::Logging::INFO); + } + return StatusCode::SUCCESS; +} + + +StatusCode CombinatorialKalmanFilterAlg::execute() { + + const EventContext& ctx = Gaudi::Hive::currentContext(); + + ATH_CHECK(m_trackCollection.initialize()); + SG::WriteHandle<TrackCollection> trackContainer{m_trackCollection,ctx}; + std::unique_ptr<TrackCollection> outputTracks = std::make_unique<TrackCollection>(); + + std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry + = m_trackingGeometryTool->trackingGeometry(); + + const FaserActsGeometryContext& gctx = m_trackingGeometryTool->getNominalGeometryContext(); + auto geoctx = gctx.context(); + Acts::MagneticFieldContext magctx = getMagneticFieldContext(ctx); + Acts::CalibrationContext calctx; + + CHECK(m_trackSeedTool->run()); + std::shared_ptr<const Acts::Surface> initialSurface = + m_trackSeedTool->initialSurface(); + std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> initialParameters = + m_trackSeedTool->initialTrackParameters(); + std::shared_ptr<std::vector<IndexSourceLink>> sourceLinks = + m_trackSeedTool->sourceLinks(); + std::shared_ptr<IdentifierLink> idLinks = m_trackSeedTool->idLinks(); + std::shared_ptr<std::vector<Measurement>> measurements = m_trackSeedTool->measurements(); + std::shared_ptr<std::vector<const Tracker::FaserSCT_Cluster*>> clusters = m_trackSeedTool->clusters(); + + TrajectoriesContainer trajectories; + trajectories.reserve(initialParameters->size()); + + Acts::PropagatorPlainOptions pOptions; + pOptions.maxSteps = m_maxSteps; + + Acts::GeometryContext geoContext = m_trackingGeometryTool->getNominalGeometryContext().context(); + Acts::MagneticFieldContext magFieldContext = getMagneticFieldContext(ctx); + Acts::CalibrationContext calibContext; + Acts::MeasurementSelector::Config measurementSelectorCfg = { + {Acts::GeometryIdentifier(), {m_chi2Max, m_nMax}}, + }; + + // Set the CombinatorialKalmanFilter options + CombinatorialKalmanFilterAlg::TrackFinderOptions options( + geoContext, magFieldContext, calibContext, + IndexSourceLinkAccessor(), MeasurementCalibrator(*measurements), + Acts::MeasurementSelector(measurementSelectorCfg), + Acts::LoggerWrapper{*m_logger}, pOptions, &(*initialSurface)); + + // Perform the track finding for all initial parameters + ATH_MSG_DEBUG("Invoke track finding with " << initialParameters->size() << " seeds."); + IndexSourceLinkContainer tmp; + for (const auto& sl : *sourceLinks) { + tmp.emplace_hint(tmp.end(), sl); + } + auto results = (*m_fit)(tmp, *initialParameters, options); + + std::vector<TrackQuality> trackQuality; + selectTracks(results, trackQuality); + for (const auto& track : trackQuality) { + ATH_MSG_VERBOSE("?? " << track.nMeasurements << ", " << track.chi2); + } + + TrackFinderResult selectedResults; + for (size_t i = 0; i < std::min(trackQuality.size(), (size_t)m_nTrajectories); ++i) { + selectedResults.push_back(Acts::Result<Acts::CombinatorialKalmanFilterResult<IndexSourceLink>>(trackQuality[i].track)); + } + /* + TrackFinderResult minTrackRequirements {}; + for (auto& result : results) { + if (not result.ok()) { + continue; + } + auto& ckfResult = result.value(); + auto traj = FaserActsRecMultiTrajectory(ckfResult.fittedStates, ckfResult.lastMeasurementIndices, ckfResult.fittedParameters); + const auto& mj = traj.multiTrajectory(); + const auto& trackTips = traj.tips(); + size_t maxMeasurements = 0; + for (const auto& trackTip : trackTips) { + auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); + size_t nMeasurements = trajState.nMeasurements; + if (nMeasurements > maxMeasurements) { + maxMeasurements = nMeasurements; + } + } + if (maxMeasurements >= m_minNumberMeasurements) { + minTrackRequirements.push_back(Acts::Result<Acts::CombinatorialKalmanFilterResult<IndexSourceLink>>(ckfResult)); + } + } + + TrackFinderResult selectedResults {}; + if (minTrackRequirements.size() > 2) { + std::pair<std::size_t, std::size_t> trackIndices = solveAmbiguity(results); + selectedResults.push_back( + Acts::Result<Acts::CombinatorialKalmanFilterResult<IndexSourceLink>>(results.at(trackIndices.first).value())); + selectedResults.push_back( + Acts::Result<Acts::CombinatorialKalmanFilterResult<IndexSourceLink>>(results.at(trackIndices.second).value())); + } else { + for (auto& result : minTrackRequirements) { + selectedResults.push_back( + Acts::Result<Acts::CombinatorialKalmanFilterResult<IndexSourceLink>>(result.value())); + } + } + */ + computeSharedHits(sourceLinks.get(), selectedResults); + + // Loop over the track finding results for all initial parameters + for (std::size_t iseed = 0; iseed < selectedResults.size(); ++iseed) { + // The result for this seed + auto& result = selectedResults[iseed]; + if (result.ok()) { + // Get the track finding output object + const auto& trackFindingOutput = result.value(); + + std::unique_ptr<Trk::Track> track = makeTrack(geoctx, result); + if (track) { + outputTracks->push_back(std::move(track)); + } + + if (!trackFindingOutput.fittedParameters.empty()) { + const std::unordered_map<size_t, Acts::BoundTrackParameters>& params = trackFindingOutput.fittedParameters; + for (const auto& surface_params : params) { + ATH_MSG_VERBOSE("Fitted parameters for track " << iseed << ", surface " << surface_params.first); + ATH_MSG_VERBOSE(" position: " << surface_params.second.position(geoctx).transpose()); + ATH_MSG_VERBOSE(" momentum: " << surface_params.second.momentum().transpose()); +// const auto& [currentTip, tipState] = trackFindingOutput.activeTips.back(); +// ATH_MSG_VERBOSE(" #measurements: " << tipState.nMeasurements); + } + } else { + ATH_MSG_DEBUG("No fitted parameters for track " << iseed); + } + // Create a Trajectories result struct + trajectories.emplace_back(trackFindingOutput.fittedStates, + trackFindingOutput.lastMeasurementIndices, + trackFindingOutput.fittedParameters); + } else { + ATH_MSG_WARNING("Track finding failed for seed " << iseed << " with error" << result.error()); + // Track finding failed. Add an empty result so the output container has + // the same number of entries as the input. + trajectories.push_back(FaserActsRecMultiTrajectory()); + } + } + + if (m_statesWriter) { + ATH_CHECK(m_trajectoryStatesWriterTool->write(geoctx, trajectories)); + } + if (m_summaryWriter) { + ATH_CHECK(m_trajectorySummaryWriterTool->write(geoctx, trajectories)); + } + if (m_performanceWriter) { + ATH_CHECK(m_performanceWriterTool->write(geoctx, trajectories)); + } + ATH_CHECK(trackContainer.record(std::move(outputTracks))); + + return StatusCode::SUCCESS; +} + + +StatusCode CombinatorialKalmanFilterAlg::finalize() { + return StatusCode::SUCCESS; +} + + +Acts::MagneticFieldContext CombinatorialKalmanFilterAlg::getMagneticFieldContext(const EventContext& ctx) const { + SG::ReadCondHandle<FaserFieldCacheCondObj> readHandle{m_fieldCondObjInputKey, ctx}; + if (!readHandle.isValid()) { + std::stringstream msg; + msg << "Failed to retrieve magnetic field condition data " << m_fieldCondObjInputKey.key() << "."; + throw std::runtime_error(msg.str()); + } + const FaserFieldCacheCondObj* fieldCondObj{*readHandle}; + return Acts::MagneticFieldContext(fieldCondObj); +} + +std::unique_ptr<Trk::Track> +CombinatorialKalmanFilterAlg::makeTrack(Acts::GeometryContext& geoCtx, TrackFitterResult& fitResult) const { + using ConstTrackStateProxy = + Acts::detail_lt::TrackStateProxy<IndexSourceLink, 6, true>; + std::unique_ptr<Trk::Track> newtrack = nullptr; + //Get the fit output object + const auto& fitOutput = fitResult.value(); + if (fitOutput.fittedParameters.size() > 0) { + DataVector<const Trk::TrackStateOnSurface>* finalTrajectory = new DataVector<const Trk::TrackStateOnSurface>{}; + std::vector<std::unique_ptr<const Acts::BoundTrackParameters>> actsSmoothedParam; + // Loop over all the output state to create track state + fitOutput.fittedStates.visitBackwards(fitOutput.lastMeasurementIndices.front(), [&](const ConstTrackStateProxy& state) { + auto flag = state.typeFlags(); + if (state.referenceSurface().associatedDetectorElement() != nullptr) { + // We need to determine the type of state + std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern; + const Trk::TrackParameters *parm; + + // State is a hole (no associated measurement), use predicted para meters + if (flag[Acts::TrackStateFlag::HoleFlag] == true) { + const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(), + state.predicted(), + state.predictedCovariance()); + parm = ConvertActsTrackParameterToATLAS(actsParam, geoCtx); + // auto boundaryCheck = m_boundaryCheckTool->boundaryCheck(*p arm); + typePattern.set(Trk::TrackStateOnSurface::Hole); + } + // The state was tagged as an outlier, use filtered parameters + else if (flag[Acts::TrackStateFlag::OutlierFlag] == true) { + const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(), + state.filtered(), state.filteredCovariance()); + parm = ConvertActsTrackParameterToATLAS(actsParam, geoCtx); + typePattern.set(Trk::TrackStateOnSurface::Outlier); + } + // The state is a measurement state, use smoothed parameters + else { + const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(), + state.smoothed(), state.smoothedCovariance()); + actsSmoothedParam.push_back(std::make_unique<const Acts::BoundTrackParameters>(Acts::BoundTrackParameters(actsParam))); + // const auto& psurface=actsParam.referenceSurface(); + Acts::Vector2 local(actsParam.parameters()[Acts::eBoundLoc0], actsParam.parameters()[Acts::eBoundLoc1]); + // const Acts::Vector3 dir = Acts::makeDirectionUnitFromPhiTheta(actsParam.parameters()[Acts::eBoundPhi], actsParam.parameters()[Acts::eBoundTheta]); + // auto pos=actsParam.position(tgContext); + parm = ConvertActsTrackParameterToATLAS(actsParam, geoCtx); + typePattern.set(Trk::TrackStateOnSurface::Measurement); + } + Tracker::FaserSCT_ClusterOnTrack* measState = nullptr; + if (state.hasUncalibrated()) { + const Tracker::FaserSCT_Cluster* fitCluster = state.uncalibrated().hit(); + if (fitCluster->detectorElement() != nullptr) { + measState = new Tracker::FaserSCT_ClusterOnTrack{ + fitCluster, + Trk::LocalParameters{ + Trk::DefinedParameter{fitCluster->localPosition()[0], Trk::loc1}, + Trk::DefinedParameter{fitCluster->localPosition()[1], Trk::loc2} + }, + fitCluster->localCovariance(), + m_idHelper->wafer_hash(fitCluster->detectorElement()->identify()) + }; + } + } + double nDoF = state.calibratedSize(); + const Trk::FitQualityOnSurface *quality = new Trk::FitQualityOnSurface(state.chi2(), nDoF); + const Trk::TrackStateOnSurface *perState = new Trk::TrackStateOnSurface(measState, parm, quality, nullptr, typePattern); + // If a state was succesfully created add it to the trajectory + if (perState) { + finalTrajectory->insert(finalTrajectory->begin(), perState); + } + } + return; + }); + + // Create the track using the states + const Trk::TrackInfo newInfo(Trk::TrackInfo::TrackFitter::KalmanFitter, Trk::ParticleHypothesis::muon); + // Trk::FitQuality* q = nullptr; + // newInfo.setTrackFitter(Trk::TrackInfo::TrackFitter::KalmanFitter ); //Mark the fitter as KalmanFitter + newtrack = std::make_unique<Trk::Track>(newInfo, std::move(*finalTrajectory), nullptr); + } + return newtrack; +} + +const Trk::TrackParameters* +CombinatorialKalmanFilterAlg::ConvertActsTrackParameterToATLAS(const Acts::BoundTrackParameters &actsParameter, const Acts::GeometryContext& gctx) const { + using namespace Acts::UnitLiterals; + std::optional<AmgSymMatrix(5)> cov = std::nullopt; + if (actsParameter.covariance()){ + AmgSymMatrix(5) newcov(actsParameter.covariance()->topLeftCorner(5, 5)); + // Convert the covariance matrix to GeV + for(int i=0; i < newcov.rows(); i++){ + newcov(i, 4) = newcov(i, 4)*1_MeV; + } + for(int i=0; i < newcov.cols(); i++){ + newcov(4, i) = newcov(4, i)*1_MeV; + } + cov = std::optional<AmgSymMatrix(5)>(newcov); + } + const Amg::Vector3D& pos=actsParameter.position(gctx); + double tphi=actsParameter.get<Acts::eBoundPhi>(); + double ttheta=actsParameter.get<Acts::eBoundTheta>(); + double tqOverP=actsParameter.get<Acts::eBoundQOverP>()*1_MeV; + double p = std::abs(1. / tqOverP); + Amg::Vector3D tmom(p * std::cos(tphi) * std::sin(ttheta), p * std::sin(tphi) * std::sin(ttheta), p * std::cos(ttheta)); + const Trk::CurvilinearParameters * curv = new Trk::CurvilinearParameters(pos,tmom,tqOverP>0, cov); + return curv; +} + +void CombinatorialKalmanFilterAlg::computeSharedHits(std::vector<IndexSourceLink>* sourceLinks, TrackFinderResult& results) const { + // Compute shared hits from all the reconstructed tracks + // Compute nSharedhits and Update ckf results + // hit index -> list of multi traj indexes [traj, meas] + static_assert(Acts::SourceLinkConcept<IndexSourceLink>, + "Source link does not fulfill SourceLinkConcept"); + + std::vector<std::size_t> firstTrackOnTheHit( + sourceLinks->size(), std::numeric_limits<std::size_t>::max()); + std::vector<std::size_t> firstStateOnTheHit( + sourceLinks->size(), std::numeric_limits<std::size_t>::max()); + + for (unsigned int iresult = 0; iresult < results.size(); iresult++) { + if (not results.at(iresult).ok()) { + continue; + } + + auto& ckfResult = results.at(iresult).value(); + auto& measIndexes = ckfResult.lastMeasurementIndices; + + for (auto measIndex : measIndexes) { + ckfResult.fittedStates.visitBackwards(measIndex, [&](const auto& state) { + if (not state.typeFlags().test(Acts::TrackStateFlag::MeasurementFlag)) + return; + + std::size_t hitIndex = state.uncalibrated().index(); + + // Check if hit not already used + if (firstTrackOnTheHit.at(hitIndex) == + std::numeric_limits<std::size_t>::max()) { + firstTrackOnTheHit.at(hitIndex) = iresult; + firstStateOnTheHit.at(hitIndex) = state.index(); + return; + } + + // if already used, control if first track state has been marked + // as shared + int indexFirstTrack = firstTrackOnTheHit.at(hitIndex); + int indexFirstState = firstStateOnTheHit.at(hitIndex); + if (not results.at(indexFirstTrack).value().fittedStates.getTrackState(indexFirstState).typeFlags().test(Acts::TrackStateFlag::SharedHitFlag)) + results.at(indexFirstTrack).value().fittedStates.getTrackState(indexFirstState).typeFlags().set(Acts::TrackStateFlag::SharedHitFlag); + + // Decorate this track + results.at(iresult).value().fittedStates.getTrackState(state.index()).typeFlags().set(Acts::TrackStateFlag::SharedHitFlag); + }); + } + } +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/CombinatorialKalmbanFilterAlg.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/CombinatorialKalmbanFilterAlg.cxx deleted file mode 100644 index f5c547e61418ca7d5d0e4eb8b1cbdb9651e9316b..0000000000000000000000000000000000000000 --- a/Tracking/Acts/FaserActsKalmanFilter/src/CombinatorialKalmbanFilterAlg.cxx +++ /dev/null @@ -1,449 +0,0 @@ -#include "FaserActsKalmanFilter/CombinatorialKalmanFilterAlg.h" - -#include "StoreGate/ReadHandle.h" -#include "StoreGate/ReadCondHandleKey.h" -#include "TrackerSpacePoint/FaserSCT_SpacePointCollection.h" -#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" -#include "TrackerIdentifier/FaserSCT_ID.h" -#include "TrkPrepRawData/PrepRawData.h" -#include "TrackerPrepRawData/FaserSCT_Cluster.h" -#include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" -#include "TrkRIO_OnTrack/RIO_OnTrack.h" -#include "TrkSurfaces/Surface.h" -#include "Identifier/Identifier.h" -#include "Acts/Geometry/GeometryIdentifier.hpp" -#include "Acts/EventData/TrackParameters.hpp" -#include "FaserActsKalmanFilter/IndexSourceLink.h" -#include "FaserActsKalmanFilter/Measurement.h" -#include "FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h" -#include "Acts/Surfaces/PerigeeSurface.hpp" -#include "Acts/MagneticField/MagneticFieldContext.hpp" - -using IdentifierMap = std::map<Identifier, Acts::GeometryIdentifier>; -using ThisMeasurement = Acts::Measurement<IndexSourceLink, Acts::BoundIndices, 2>; -using TrajectoriesContainer = std::vector<FaserActsRecMultiTrajectory>; -std::array<Acts::BoundIndices, 2> indices = {Acts::eBoundLoc0, Acts::eBoundLoc1}; - - -CombinatorialKalmanFilterAlg::CombinatorialKalmanFilterAlg( - const std::string& name, ISvcLocator* pSvcLocator) - : AthReentrantAlgorithm(name, pSvcLocator) {} - - -StatusCode CombinatorialKalmanFilterAlg::initialize() { - ATH_MSG_INFO("CombinatorialKalmanFilterAlg::initialize"); - m_nevents=0; - m_ntracks=0; - m_nseeds=0; - m_nsp10=0; - m_nsp11=0; - m_ncom=0; - m_nsp1=0; - m_nsp2=0; - m_nsp3=0; - - ATH_CHECK(m_trackingGeometryTool.retrieve()); - ATH_CHECK(m_initialParameterTool.retrieve()); - ATH_CHECK(m_trajectoryWriterTool.retrieve()); - ATH_CHECK(detStore()->retrieve(m_idHelper,"FaserSCT_ID")); - - ATH_CHECK( m_fieldCondObjInputKey.initialize() ); - - ATH_CHECK(m_trackCollection.initialize()); - - if (m_SpacePointContainerKey.key().empty()) { - ATH_MSG_FATAL("empty space point container key"); - return StatusCode::FAILURE; - } - ATH_CHECK(m_SpacePointContainerKey.initialize()); - ATH_CHECK(m_Sct_clcontainerKey.initialize() ); - - return StatusCode::SUCCESS; -} - - -StatusCode CombinatorialKalmanFilterAlg::execute(const EventContext& ctx) const { - ATH_MSG_DEBUG("CombinatorialKalmanFilterAlg::execute"); - m_nevents++; - - SG::ReadHandle<FaserSCT_SpacePointContainer> spcontainer(m_SpacePointContainerKey, ctx); - if (!spcontainer.isValid()) { - ATH_MSG_FATAL( "Could not find the data object "<< spcontainer.name()); - return StatusCode::FAILURE; - } - SG::ReadHandle<Tracker::FaserSCT_ClusterContainer> sct_clcontainer( m_Sct_clcontainerKey, ctx ); -if (!sct_clcontainer.isValid()){ -msg(MSG:: FATAL) << "Could not find the data object "<< sct_clcontainer.name() << " !" << endmsg; -return StatusCode::RECOVERABLE; -} - - - //make TrackCollection - SG::WriteHandle<TrackCollection> trackContainer{m_trackCollection,ctx}; - std::unique_ptr<TrackCollection> outputTracks = std::make_unique<TrackCollection>(); - - const std::shared_ptr<IdentifierMap> identifierMap - = m_trackingGeometryTool->getIdentifierMap(); - - /* - // Create measurement and source link containers - IndexSourceLinkContainer sourceLinks; - MeasurementContainer measurements; - std::vector<Identifier> sp_ids; - std::vector<Tracker::FaserSCT_Cluster> sps; - - std::vector<Acts::Vector3> pos1; - std::vector<Acts::Vector3> pos2; - std::vector<Acts::Vector3> pos3; - pos1.clear();pos2.clear();pos3.clear(); - Tracker::FaserSCT_ClusterContainer::const_iterator coll_it = sct_clcontainer->begin(); - Tracker::FaserSCT_ClusterContainer::const_iterator coll_itend = sct_clcontainer->end(); - for (; coll_it != coll_itend; ++coll_it) { - const Tracker::FaserSCT_ClusterCollection* spcollection = *coll_it; - Tracker::FaserSCT_ClusterCollection::const_iterator sp_it = spcollection->begin(); - Tracker::FaserSCT_ClusterCollection::const_iterator sp_end = spcollection->end(); - for (; sp_it != sp_end; ++sp_it) { - const Tracker::FaserSCT_Cluster* sp = *sp_it; - Identifier id = sp->detectorElement()->identify(); - //Identifier id = sp->associatedSurface().associatedDetectorElementIdentifier(); - Acts::GeometryIdentifier geoId = identifierMap->at(id); - IndexSourceLink sourceLink(geoId, measurements.size()); - sourceLinks.emplace_hint(sourceLinks.end(), std::move(sourceLink)); - ThisMeasurement meas(sourceLink, indices, sp->localPosition(), sp->localCovariance()); - //ThisMeasurement meas(sourceLink, indices, sp->localParameters(), sp->localCovariance()); - measurements.emplace_back(std::move(meas)); - - if(m_idHelper->station(sp->identify())==1)pos1.push_back(Acts::Vector3(sp->globalPosition().x(),sp->globalPosition().y(),sp->globalPosition().z())); - if(m_idHelper->station(sp->identify())==2)pos2.push_back(Acts::Vector3(sp->globalPosition().x(),sp->globalPosition().y(),sp->globalPosition().z())); - if(m_idHelper->station(sp->identify())==3)pos3.push_back(Acts::Vector3(sp->globalPosition().x(),sp->globalPosition().y(),sp->globalPosition().z())); - sp_ids.push_back(sp->identify()); - sps.push_back(*sp); - } - } -*/ - // Create measurement and source link containers - IndexSourceLinkContainer sourceLinks; - MeasurementContainer measurements; - std::vector<Identifier> sp_ids; - std::vector<Tracker::FaserSCT_SpacePoint> sps; - -// std::vector<Acts::Vector3> pos1; -// std::vector<Acts::Vector3> pos2; -// std::vector<Acts::Vector3> pos3; -// pos1.clear();pos2.clear();pos3.clear(); - std::vector<int> layer1; - layer1.clear(); - FaserSCT_SpacePointContainer::const_iterator coll_it = spcontainer->begin(); - FaserSCT_SpacePointContainer::const_iterator coll_itend = spcontainer->end(); - for (; coll_it != coll_itend; ++coll_it) { - const FaserSCT_SpacePointCollection* spcollection = *coll_it; - FaserSCT_SpacePointCollection::const_iterator sp_it = spcollection->begin(); - FaserSCT_SpacePointCollection::const_iterator sp_end = spcollection->end(); - for (; sp_it != sp_end; ++sp_it) { - const Tracker::FaserSCT_SpacePoint* sp = *sp_it; - Identifier id = sp->associatedSurface().associatedDetectorElementIdentifier(); - Acts::GeometryIdentifier geoId = identifierMap->at(id); - IndexSourceLink sourceLink(geoId, measurements.size()); - sourceLinks.emplace_hint(sourceLinks.end(), std::move(sourceLink)); - ThisMeasurement meas(sourceLink, indices, sp->localParameters(), sp->localCovariance()); - measurements.emplace_back(std::move(meas)); - -// if(m_idHelper->station(sp->clusterList().first->identify())==1) { -// pos1.push_back(Acts::Vector3(sp->globalPosition().x(),sp->globalPosition().y(),sp->globalPosition().z())); -// layer1.push_back(m_idHelper->layer(sp->clusterList().first->identify())); -// } -// if(m_idHelper->station(sp->clusterList().first->identify())==2)pos2.push_back(Acts::Vector3(sp->globalPosition().x(),sp->globalPosition().y(),sp->globalPosition().z())); -// if(m_idHelper->station(sp->clusterList().first->identify())==3)pos3.push_back(Acts::Vector3(sp->globalPosition().x(),sp->globalPosition().y(),sp->globalPosition().z())); - sp_ids.push_back(sp->clusterList().first->identify()); - sps.push_back(*sp); - } - } - - // Get initial parameters - // FIXME: Get initial parameters from clusterFitter or SeedFinder not MC! - std::vector<Acts::CurvilinearTrackParameters> initialParameters; - auto initialParameter = m_initialParameterTool->getInitialParameters(sp_ids); - initialParameters.push_back(initialParameter); -// if(pos1.size()<1||pos2.size()<1||pos3.size()<1) return StatusCode::SUCCESS; -// std::vector<Acts::CurvilinearTrackParameters> initialParameters; -// initialParameters.clear(); -// Acts::Vector3 pos1a(0,0,0); -// Acts::Vector3 pos2a(0,0,0); -// Acts::Vector3 pos3a(0,0,0); -// for(long unsigned int i1=0;i1<pos1.size();i1++)pos1a+=pos1[i1]; -// for(long unsigned int i1=0;i1<pos2.size();i1++)pos2a+=pos2[i1]; -// for(long unsigned int i1=0;i1<pos3.size();i1++)pos3a+=pos3[i1]; -// pos1a/=pos1.size(); -// pos2a/=pos2.size(); -// pos3a/=pos3.size(); -// m_nsp1+=pos1.size(); -// m_nsp2+=pos2.size(); -// m_nsp3+=pos3.size(); -// for(int i1=0;i1<pos1.size();i1++){ -// for(int i2=0;i2<pos2.size();i2++){ -// for(int i3=0;i3<pos3.size();i3++){ -// auto initialParameter=m_initialParameterTool->getInitialParameters(pos1[i1],pos2[i2],pos3[i3]); -// initialParameters.push_back(initialParameter); -// } -// } -// } - /* - if(pos1.size()>0&&pos2.size()>0&&pos3.size()>0) { - auto initialParameter=m_initialParameterTool->getInitialParameters(pos1a,pos2a,pos3a); - if(initialParameter.momentum().z()>0){ - m_nseeds++; - initialParameters.push_back(initialParameter); - */ - // for one stations -// if(pos1.size()>2) { -// std::vector<Acts::Vector3> pos10; -// std::vector<Acts::Vector3> pos11; -// std::vector<Acts::Vector3> pos12; -// pos10.clear();pos11.clear();pos12.clear(); -// for(std::size_t ipos=0;ipos<pos1.size();ipos++){ -// if(layer1[ipos]==0)pos10.push_back(pos1[ipos]); -// if(layer1[ipos]==1)pos11.push_back(pos1[ipos]); -// if(layer1[ipos]==2)pos12.push_back(pos1[ipos]); -// } -// if(pos10.size()>0&&pos11.size()>0&&pos12.size()>0){ -// auto initialParameter=m_initialParameterTool->getInitialParameters_1station(pos10,pos11,pos12); -// initialParameters.insert(initialParameters.end(),initialParameter.begin(),initialParameter.end()); - /* - //for two stations - if(pos1.size()>1&&pos2.size()>0) { - Acts::Vector3 pos10a(0,0,0); - Acts::Vector3 pos11a(0,0,0); - int n10a=0,n11a=0; - for(int ipos=0;ipos<pos1.size();ipos++){ - if(layer1[ipos]==0){pos10a+=pos1[ipos];n10a++;} - if(layer1[ipos]>0){pos11a+=pos1[ipos];n11a++;} - } - m_nsp10+=n10a; - m_nsp11+=n11a; - if(n10a>0&&n11a>0){ - m_ncom++; - pos10a/=n10a; - pos11a/=n11a; - Acts::Vector3 dir1=(pos11a-pos10a).normalized(); - auto initialParameter=m_initialParameterTool->getInitialParameters_2stations(pos1a,pos2a,dir1); - if(initialParameter.momentum().z()>0){ - m_nseeds++; - initialParameters.push_back(initialParameter); - } - */ - - // Prepare the output data with MultiTrajectory - TrajectoriesContainer trajectories; - trajectories.reserve(initialParameters.size()); - - // Construct a perigee surface as the target surface - auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>( - Acts::Vector3{0., 0., 0.}); - - Acts::PropagatorPlainOptions pOptions; - pOptions.maxSteps = 10000; - /* - Acts::DirectNavigator navigator; - std::unique_ptr<ActsExtrapolationDetail::VariantPropagator> varProp; - Acts::Vector3 constantFieldVector = Acts::Vector3(0,0,0.55); - auto bField = std::make_shared<Acts::ConstantBField>(constantFieldVector); - auto stepper = Acts::EigenStepper<>(std::move(bField)); - auto propagator = Acts::Propagator<decltype(stepper), Acts::DirectNavigator>(std::move(stepper), - std::move(navigator)); - varProp = std::make_unique<VariantPropagator>(propagator); - */ - - Acts::GeometryContext geoContext = m_trackingGeometryTool->getNominalGeometryContext().context(); - Acts::MagneticFieldContext magFieldContext = getMagneticFieldContext(ctx); - Acts::CalibrationContext calibContext; - double chi2Max = 15; - size_t nMax = 10; - Acts::MeasurementSelector::Config measurementSelectorCfg = { - {Acts::GeometryIdentifier(), {chi2Max, nMax}}, - }; - std::unique_ptr<const Acts::Logger> logger - = Acts::getDefaultLogger("CombinatorialKalmanFilter", Acts::Logging::INFO); - - // Set the CombinatorialKalmanFilter options - CombinatorialKalmanFilterAlg::TrackFinderOptions options( - geoContext, magFieldContext, calibContext, - IndexSourceLinkAccessor(), MeasurementCalibrator(measurements), - Acts::MeasurementSelector(measurementSelectorCfg), - //Acts::LoggerWrapper{*logger}, varProp, &(*pSurface)); - Acts::LoggerWrapper{*logger}, pOptions, &(*pSurface)); - - std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry - = m_trackingGeometryTool->trackingGeometry(); - - // Get track finder function - auto trackFinderFunction = makeTrackFinderFunction(trackingGeometry); - - // Perform the track finding for all initial parameters - ATH_MSG_DEBUG("Invoke track finding with " << initialParameters.size() - << " seeds."); - auto results = trackFinderFunction(sourceLinks, initialParameters, options); - // Loop over the track finding results for all initial parameters - for (std::size_t iseed = 0; iseed < initialParameters.size(); ++iseed) { - // The result for this seed - auto& result = results[iseed]; - if (result.ok()) { - // Get the track finding output object - const auto& trackFindingOutput = result.value(); - std::unique_ptr<Trk::Track> track = makeTrack(geoContext, result,sps); - m_ntracks++; - if(track!=nullptr) { - outputTracks->push_back(std::move(track)); - } else { - ATH_MSG_DEBUG("No Trk::Track is created" ); - } - // Create a Trajectories result struct - trajectories.emplace_back(std::move(trackFindingOutput.fittedStates), - std::move(trackFindingOutput.lastMeasurementIndices), - std::move(trackFindingOutput.fittedParameters)); - } else { - ATH_MSG_WARNING("Track finding failed for seed " << iseed << " with error" - << result.error()); - // Track finding failed. Add an empty result so the output container has - // the same number of entries as the input. - trajectories.push_back(FaserActsRecMultiTrajectory()); - } - } - - m_trajectoryWriterTool->writeout(trajectories, geoContext,initialParameters); -// } -// } - - if(outputTracks->size()>0) { - ATH_MSG_DEBUG("Found " << outputTracks->size() << " tracks"); - } else { - ATH_MSG_WARNING("No track is found"); - } - - ATH_CHECK(trackContainer.record(std::move(outputTracks))); - return StatusCode::SUCCESS; -} - - -StatusCode CombinatorialKalmanFilterAlg::finalize() { - ATH_MSG_INFO("CombinatorialKalmanFilterAlg::finalize"); - ATH_MSG_INFO("Summary info"); - ATH_MSG_INFO("In total, "<<m_nevents<<" events, and "<<m_nseeds<<" seeds, and "<<m_ntracks<<" tracks"); - ATH_MSG_INFO("In total, "<<m_nsp1<<" , "<<m_nsp2<<" , "<<m_nsp3<<" ,"<<m_nsp10<<" , "<<m_nsp11<<" , "<<m_ncom); - - return StatusCode::SUCCESS; -} - - -Acts::MagneticFieldContext CombinatorialKalmanFilterAlg::getMagneticFieldContext(const EventContext& ctx) const { - SG::ReadCondHandle<FaserFieldCacheCondObj> readHandle{m_fieldCondObjInputKey, ctx}; - if (!readHandle.isValid()) { - std::stringstream msg; - msg << "Failed to retrieve magnetic field condition data " << m_fieldCondObjInputKey.key() << "."; - throw std::runtime_error(msg.str()); - } - const FaserFieldCacheCondObj* fieldCondObj{*readHandle}; - - return Acts::MagneticFieldContext(fieldCondObj); -} - -std::unique_ptr<Trk::Track> -CombinatorialKalmanFilterAlg::makeTrack(Acts::GeometryContext& tgContext, FitterResult& fitResult, std::vector<Tracker::FaserSCT_SpacePoint> sps) const { - std::unique_ptr<Trk::Track> newtrack = nullptr; - //Get the fit output object - const auto& fitOutput = fitResult.value(); - if (fitOutput.fittedParameters.size()>0) { - DataVector<const Trk::TrackStateOnSurface>* finalTrajectory = new DataVector<const Trk::TrackStateOnSurface>{}; - std::vector<std::unique_ptr<const Acts::BoundTrackParameters>> actsSmoothedParam; - ATH_MSG_DEBUG("makeTrack : trackTip "<<fitOutput.lastMeasurementIndices.size()); - // Loop over all the output state to create track state - fitOutput.fittedStates.visitBackwards(fitOutput.lastMeasurementIndices.front(), [&](const auto &state) { - auto flag = state.typeFlags(); - if (state.referenceSurface().associatedDetectorElement() != nullptr) { - // const auto* actsElement = dynamic_cast<const FaserActsDetectorElement*>(state.referenceSurface().associatedDetectorElement()); - // if (actsElement != nullptr ){ - // We need to determine the type of state - std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern; - const Trk::TrackParameters *parm; - - // State is a hole (no associated measurement), use predicted para meters - if (flag[Acts::TrackStateFlag::HoleFlag] == true) { - const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(), - state.predicted(), - state.predictedCovariance()); - parm = ConvertActsTrackParameterToATLAS(actsParam, tgContext); - // auto boundaryCheck = m_boundaryCheckTool->boundaryCheck(*p arm); - typePattern.set(Trk::TrackStateOnSurface::Hole); - } - // The state was tagged as an outlier, use filtered parameters - else if (flag[Acts::TrackStateFlag::OutlierFlag] == true) { - const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(), - state.filtered(), state.filteredCovariance()); - parm = ConvertActsTrackParameterToATLAS(actsParam, tgContext); - typePattern.set(Trk::TrackStateOnSurface::Outlier); - } - // The state is a measurement state, use smoothed parameters - else { - const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(), - state.smoothed(), state.smoothedCovariance()); - actsSmoothedParam.push_back(std::make_unique<const Acts::BoundTrackParameters>(Acts::BoundTrackParameters(actsParam))); - // const auto& psurface=actsParam.referenceSurface(); - Acts::Vector2 local(actsParam.parameters()[Acts::eBoundLoc0], actsParam.parameters()[Acts::eBoundLoc1]); - // const Acts::Vector3 dir = Acts::makeDirectionUnitFromPhiTheta(actsParam.parameters()[Acts::eBoundPhi], actsParam.parameters()[Acts::eBoundTheta]); - // auto pos=actsParam.position(tgContext); - parm = ConvertActsTrackParameterToATLAS(actsParam, tgContext); - typePattern.set(Trk::TrackStateOnSurface::Measurement); - } - Tracker::FaserSCT_ClusterOnTrack* measState = nullptr; - if (state.hasUncalibrated()) { - auto sp= sps.at(state.uncalibrated().index()); - //const Tracker::FaserSCT_Cluster* fitCluster=&sp; - const Tracker::FaserSCT_Cluster* fitCluster=sp.clusterList().first; - if(fitCluster !=nullptr) { - measState = new Tracker::FaserSCT_ClusterOnTrack{ fitCluster, Trk::LocalParameters { Trk::DefinedParameter { fitCluster->localPosition()[0], Trk::loc1 }, Trk::DefinedParameter { fitCluster->localPosition()[1], Trk::loc2 } }, fitCluster->localCovariance(), m_idHelper->wafer_hash(fitCluster->detectorElement()->identify())}; - } - } - double nDoF = state.calibratedSize(); - const Trk::FitQualityOnSurface *quality = new Trk::FitQualityOnSurface(state.chi2(), nDoF); - const Trk::TrackStateOnSurface *perState = new Trk::TrackStateOnSurface(measState, parm, quality, nullptr, typePattern); - // If a state was succesfully created add it to the trajectory - if (perState) { - finalTrajectory->insert(finalTrajectory->begin(), perState); - } - } - return; - }); - - // Create the track using the states - const Trk::TrackInfo newInfo(Trk::TrackInfo::TrackFitter::KalmanFitter, Trk::ParticleHypothesis::muon); - // Trk::FitQuality* q = nullptr; - // newInfo.setTrackFitter(Trk::TrackInfo::TrackFitter::KalmanFitter ); //Mark the fitter as KalmanFitter - newtrack = std::make_unique<Trk::Track>(newInfo, std::move(*finalTrajectory), nullptr); - } - return newtrack; -} - -const Trk::TrackParameters* -CombinatorialKalmanFilterAlg ::ConvertActsTrackParameterToATLAS(const Acts::BoundTrackParameters &actsParameter, const Acts::GeometryContext& gctx) const { - using namespace Acts::UnitLiterals; - std::optional<AmgSymMatrix(5)> cov = std::nullopt; - if (actsParameter.covariance()){ - AmgSymMatrix(5) newcov(actsParameter.covariance()->topLeftCorner(5, 5)); - // Convert the covariance matrix to GeV - for(int i=0; i < newcov.rows(); i++){ - newcov(i, 4) = newcov(i, 4)*1_MeV; - } - for(int i=0; i < newcov.cols(); i++){ - newcov(4, i) = newcov(4, i)*1_MeV; - } - cov = std::optional<AmgSymMatrix(5)>(newcov); - } - const Amg::Vector3D& pos=actsParameter.position(gctx); - double tphi=actsParameter.get<Acts::eBoundPhi>(); - double ttheta=actsParameter.get<Acts::eBoundTheta>(); - double tqOverP=actsParameter.get<Acts::eBoundQOverP>()*1_MeV; - double p = std::abs(1. / tqOverP); - Amg::Vector3D tmom(p * std::cos(tphi) * std::sin(ttheta), p * std::sin(tphi) * std::sin(ttheta), p * std::cos(ttheta)); - const Trk::CurvilinearParameters * curv = new Trk::CurvilinearParameters(pos,tmom,tqOverP>0, cov); - return curv; -} - diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/EffPlotTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/EffPlotTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..514fe5407c1585e1a0884a60f2dc5d039ebe92ae --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/EffPlotTool.cxx @@ -0,0 +1,40 @@ +#include "FaserActsKalmanFilter/EffPlotTool.h" +#include "Acts/Utilities/Helpers.hpp" + +void EffPlotTool::book(EffPlotTool::EffPlotCache &effPlotCache) const { + PlotHelpers::Binning bPhi = m_varBinning.at("Phi"); + PlotHelpers::Binning bEta = m_varBinning.at("Eta"); + PlotHelpers::Binning bPt = m_varBinning.at("Pt"); + // efficiency vs pT + effPlotCache.trackEff_vs_pT = PlotHelpers::bookEff( + "trackeff_vs_pT", "Tracking efficiency;Truth pT [GeV/c];Efficiency", bPt); + // efficiency vs eta + effPlotCache.trackEff_vs_eta = PlotHelpers::bookEff( + "trackeff_vs_eta", "Tracking efficiency;Truth #eta;Efficiency", bEta); + // efficiency vs phi + effPlotCache.trackEff_vs_phi = PlotHelpers::bookEff( + "trackeff_vs_phi", "Tracking efficiency;Truth #phi;Efficiency", bPhi); +} + +void EffPlotTool::fill(EffPlotTool::EffPlotCache &effPlotCache, + const HepMC::GenParticle* truthParticle, bool status) const { + const auto t_phi = truthParticle->momentum().phi(); + const auto t_eta = truthParticle->momentum().eta(); + const auto t_pT = truthParticle->momentum().perp() * m_MeV2GeV; + + PlotHelpers::fillEff(effPlotCache.trackEff_vs_pT, t_pT, status); + PlotHelpers::fillEff(effPlotCache.trackEff_vs_eta, t_eta, status); + PlotHelpers::fillEff(effPlotCache.trackEff_vs_phi, t_phi, status); +} + +void EffPlotTool::write(const EffPlotTool::EffPlotCache &effPlotCache) const { + effPlotCache.trackEff_vs_pT->Write(); + effPlotCache.trackEff_vs_eta->Write(); + effPlotCache.trackEff_vs_phi->Write(); +} + +void EffPlotTool::clear(EffPlotTool::EffPlotCache &effPlotCache) const { + delete effPlotCache.trackEff_vs_pT; + delete effPlotCache.trackEff_vs_eta; + delete effPlotCache.trackEff_vs_phi; +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/FaserActsKalmanFilterAlg.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/FaserActsKalmanFilterAlg.cxx index c9427a0f8f9940f6d181e4f4775bcb9a8e2ae527..673524123467db8461bb25da2157bfa00eb6755a 100755 --- a/Tracking/Acts/FaserActsKalmanFilter/src/FaserActsKalmanFilterAlg.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/FaserActsKalmanFilterAlg.cxx @@ -7,7 +7,7 @@ // ATHENA #include "GaudiKernel/EventContext.h" #include "GaudiKernel/ISvcLocator.h" -#include "GaudiKernel/PhysicalConstants.h" +//#include "GaudiKernel/PhysicalConstants.h" #include "TrackerReadoutGeometry/SCT_DetectorManager.h" #include "TrackerReadoutGeometry/SiDetectorDesign.h" #include "TrackerReadoutGeometry/SiLocalPosition.h" @@ -18,14 +18,8 @@ #include "FaserDetDescr/FaserDetectorID.h" // ACTS -#include "Acts/TrackFitting/GainMatrixSmoother.hpp" -#include "Acts/TrackFitting/GainMatrixUpdater.hpp" #include "Acts/Geometry/GeometryIdentifier.hpp" -#include "Acts/MagneticField/ConstantBField.hpp" -#include "Acts/MagneticField/InterpolatedBFieldMap.hpp" -#include "Acts/MagneticField/SharedBField.hpp" #include "Acts/MagneticField/MagneticFieldContext.hpp" -#include "Acts/Propagator/EigenStepper.hpp" #include "Acts/Propagator/Navigator.hpp" #include "Acts/Propagator/Propagator.hpp" #include "Acts/Surfaces/Surface.hpp" @@ -43,7 +37,6 @@ #include "Acts/EventData/TrackParameters.hpp" #include "Acts/EventData/MultiTrajectoryHelpers.hpp" #include "Acts/EventData/Measurement.hpp" -#include "Acts/Geometry/GeometryIdentifier.hpp" // PACKAGE @@ -52,6 +45,9 @@ #include "FaserActsGeometry/FaserActsGeometryContext.h" #include "FaserActsGeometry/IFaserActsPropStepRootWriterSvc.h" #include "FaserActsGeometry/FaserActsDetectorElement.h" +#include "FaserActsKalmanFilter/IdentifierLink.h" + +#include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" //ROOT #include <TTree.h> @@ -65,7 +61,6 @@ #include <string> #include <fstream> #include <cmath> -#include <random> using TrajectoryContainer = std::vector<FaserActsRecMultiTrajectory>; @@ -75,476 +70,99 @@ using Acts::VectorHelpers::perp; using Acts::VectorHelpers::phi; using Acts::VectorHelpers::theta; using ThisMeasurement = Acts::Measurement<IndexSourceLink, Acts::BoundIndices, 2>; -using Updater = Acts::GainMatrixUpdater; -using Smoother = Acts::GainMatrixSmoother; -using Stepper = Acts::EigenStepper<FASERMagneticFieldWrapper>; -using Propagator = Acts::Propagator<Stepper, Acts::DirectNavigator>; -using Fitter = Acts::KalmanFitter<Propagator, Updater, Smoother>; - -namespace ActsExtrapolationDetail { - using VariantPropagatorBase = boost::variant< - Acts::Propagator<Acts::EigenStepper<>, Acts::DirectNavigator>, - Acts::Propagator<Acts::EigenStepper<>, Acts::DirectNavigator> - >; +using IdentifierMap = std::map<Identifier, Acts::GeometryIdentifier>; - class VariantPropagator : public VariantPropagatorBase - { - public: - using VariantPropagatorBase::VariantPropagatorBase; - }; +FaserActsKalmanFilterAlg::FaserActsKalmanFilterAlg(const std::string& name, ISvcLocator* pSvcLocator) : + AthAlgorithm(name, pSvcLocator) {} -} - -using ActsExtrapolationDetail::VariantPropagator; - -FaserActsKalmanFilterAlg::FaserActsKalmanFilterAlg(const std::string& name, ISvcLocator* pSvcLocator) - : AthAlgorithm(name, pSvcLocator) , m_thistSvc("THistSvc", name) -{ -} - -// FixMe the Identifier to GeometryIdentfier mapping should not be hardcoded. -int FaserActsKalmanFilterAlg::getGeometryIdentifierVolume(int station) -{ - switch(station) - { - case 1: - return 2; - case 2: - return 3; - case 3: - return 4; - default: - ATH_MSG_ERROR("Received unexpected station. Check detector geometry"); - return 0; - } -} - -int FaserActsKalmanFilterAlg::getGeometryIdentifierLayer(int layer) -{ - switch(layer) - { - case 0: - return 2; - case 1: - return 4; - case 2: - return 6; - default: - ATH_MSG_ERROR("Received unexpected layer. Check detector geometry"); - return 0; - } -} - -int FaserActsKalmanFilterAlg::getGeometryIdentifierSensitive(int row, int column) -{ - if (row == 0 && column == -1) - return 2; - else if (row == 0 && column == 1) - return 4; - else if (row == 1 && column == -1) - return 5; - else if (row == 1 && column == 1) - return 7; - else if (row == 2 && column == -1) - return 10; - else if (row == 2 && column == 1) - return 12; - else if (row == 3 && column == -1) - return 13; - else if (row ==3 && column == 1) - return 15; - else - { - ATH_MSG_ERROR("Received unexpected row or column. Check detector geometry"); - return 0; - } -} - -Acts::GeometryIdentifier FaserActsKalmanFilterAlg::getGeometryIdentifier(const Identifier id) -{ - Acts::GeometryIdentifier geoId = Acts::GeometryIdentifier(); - geoId.setVolume(getGeometryIdentifierVolume(m_idHelper->station(id))); - geoId.setLayer(getGeometryIdentifierLayer(m_idHelper->layer(id))); - geoId.setSensitive(getGeometryIdentifierSensitive(m_idHelper->phi_module(id), m_idHelper->eta_module(id))); - return geoId; -} StatusCode FaserActsKalmanFilterAlg::initialize() { - - ATH_MSG_DEBUG(name() << "::" << __FUNCTION__); - - ATH_MSG_INFO("Initializing ACTS kalman filter"); - - ATH_CHECK( m_fieldCondObjInputKey.initialize() ); - - ATH_CHECK( m_extrapolationTool.retrieve() ); - - if ( m_seed_spcollectionKey.key().empty()){ - ATH_MSG_FATAL( "SCTs selected and no name set for SCT clusters"); - return StatusCode::FAILURE; + ATH_CHECK(m_fieldCondObjInputKey.initialize()); + ATH_CHECK(m_trackingGeometryTool.retrieve()); + ATH_CHECK(m_trackFinderTool.retrieve()); + ATH_CHECK(m_trajectoryWriterTool.retrieve()); + ATH_CHECK(m_trajectoryStatesWriterTool.retrieve()); +// ATH_CHECK(m_protoTrackWriterTool.retrieve()); + ATH_CHECK(m_trackCollection.initialize()); + ATH_CHECK(detStore()->retrieve(m_idHelper,"FaserSCT_ID")); + m_fit = makeTrackFitterFunction(m_trackingGeometryTool->trackingGeometry()); + if (m_actsLogging == "VERBOSE") { + m_logger = Acts::getDefaultLogger("KalmanFitter", Acts::Logging::VERBOSE); + } else if (m_actsLogging == "DEBUG") { + m_logger = Acts::getDefaultLogger("KalmanFitter", Acts::Logging::DEBUG); + } else { + m_logger = Acts::getDefaultLogger("KalmanFitter", Acts::Logging::INFO); } - - ATH_CHECK( m_seed_spcollectionKey.initialize() ); - - ATH_CHECK( m_mcEventKey.initialize() ); - - ATH_CHECK( m_sctMap.initialize()); - - ATH_CHECK(detStore()->retrieve(m_idHelper,"FaserSCT_ID")); - - ATH_CHECK(detStore()->retrieve(m_detManager, "SCT")); - - ATH_CHECK(m_thistSvc.retrieve()); - - m_trackTree = new TTree("tracks", ""); - - ATH_CHECK(m_thistSvc->regTree("/KalmanTracks/tracks", m_trackTree)); - - if (m_trackTree) { - initializeTree(); - } - else { - ATH_MSG_ERROR("No tree found!"); - } - - ATH_MSG_INFO("ACTS kalman filter successfully initialized"); return StatusCode::SUCCESS; } -//StatusCode FaserActsKalmanFilterAlg::execute(const EventContext& ctx) const -StatusCode FaserActsKalmanFilterAlg::execute() -{ - ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__); +//StatusCode FaserActsKalmanFilterAlg::execute(const EventContext& ctx) const { +StatusCode FaserActsKalmanFilterAlg::execute() { + const EventContext& ctx = Gaudi::Hive::currentContext(); - m_eventNr++; + //make TrackCollection + ATH_CHECK(m_trackCollection.initialize()); + SG::WriteHandle<TrackCollection> trackContainer{m_trackCollection,ctx}; + std::unique_ptr<TrackCollection> outputTracks = std::make_unique<TrackCollection>(); - //SG::ReadHandle<SpacePointForSeedCollection> seed_spcollection( m_seed_spcollectionKey, ctx ); - SG::ReadHandle<SpacePointForSeedCollection> seed_spcollection( m_seed_spcollectionKey ); - if (!seed_spcollection.isValid()){ - msg(MSG:: FATAL) << "Could not find the data object "<< seed_spcollection.name() << " !" << endmsg; - return StatusCode::RECOVERABLE; - } + std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry + = m_trackingGeometryTool->trackingGeometry(); - const FaserActsGeometryContext& gctx - = m_extrapolationTool->trackingGeometryTool()->getNominalGeometryContext(); + const FaserActsGeometryContext& gctx = m_trackingGeometryTool->getNominalGeometryContext(); auto geoctx = gctx.context(); - Acts::MagneticFieldContext magctx = getMagneticFieldContext(); + Acts::MagneticFieldContext magctx = getMagneticFieldContext(ctx); Acts::CalibrationContext calctx; - std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry - = m_extrapolationTool->trackingGeometryTool()->trackingGeometry(); - - std::shared_ptr<const Acts::Surface> pSurface; - - // Get SiDetectorElements - const TrackerDD::SiDetectorElementCollection* elCollection{m_detManager->getDetectorElementCollection()}; - if (elCollection == nullptr) { - ATH_MSG_FATAL("Null pointer is returned by getDetectorElementCollection()"); - return StatusCode::FAILURE; - } - + CHECK(m_trackFinderTool->run()); + std::shared_ptr<const Acts::Surface> initialSurface = + m_trackFinderTool->initialSurface(); + std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> initialTrackParameters = + m_trackFinderTool->initialTrackParameters(); + std::shared_ptr<std::vector<std::vector<IndexSourceLink>>> sourceLinks = + m_trackFinderTool->sourceLinks(); + std::shared_ptr<std::vector<IdentifierLink>> idLinks = m_trackFinderTool->idLinks(); + std::shared_ptr<std::vector<std::vector<Measurement>>> measurements = + m_trackFinderTool->measurements(); + std::shared_ptr<std::vector<std::vector<Tracker::FaserSCT_SpacePoint>>> spacePoints = + m_trackFinderTool->spacePoints(); + std::shared_ptr<std::vector<std::vector<const Tracker::FaserSCT_Cluster*>>> clusters = + m_trackFinderTool->clusters(); - static const TrackerDD::SCT_DetectorManager *s_sct; - if(detStore()->retrieve(s_sct,"SCT").isFailure()) s_sct = 0; - int N_1_0=0, N_1_1=0, N_1_2=0, N_2_0=0, N_2_1=0, N_2_2=0; - Acts::Vector3 pos1_0(0., 0., 0.); - Acts::Vector3 pos1_1(0., 0., 0.); - Acts::Vector3 pos1_2(0., 0., 0.); - Acts::Vector3 pos2_0(0., 0., 0.); - Acts::Vector3 pos2_1(0., 0., 0.); - Acts::Vector3 pos2_2(0., 0., 0.); - HepMC::FourVector truthmom; - HepMC::FourVector pv; +// ATH_CHECK(m_protoTrackWriterTool->write(initialTrackParameters, measurements, geoctx)); - // create source links and measurements - std::vector<IndexSourceLink> sourceLinks; - std::vector<const Acts::Surface*> surfSequence; - MeasurementContainer measurements; + int n_trackSeeds = initialTrackParameters->size(); - SpacePointForSeedCollection::const_iterator it = seed_spcollection->begin(); - SpacePointForSeedCollection::const_iterator itend = seed_spcollection->end(); - for (; it != itend; ++it){ - const Tracker::FaserSCT_SpacePoint *sp = (&(**it))->SpacePoint(); + TrajectoryContainer trajectories; + trajectories.reserve(1); - const Identifier id = sp->clusterList().first->identify(); - const TrackerDD::SiDetectorElement* siSpElement = m_detManager->getDetectorElement(id); - auto spElement = static_cast<const FaserActsDetectorElement>(siSpElement); - // Acts::GeometryIdentifier geoId = getGeometryIdentifier(id); - Acts::GeometryIdentifier geoId; + for (int i = 0; i < n_trackSeeds; ++i) { - const Acts::TrackingVolume* tVolume = trackingGeometry->highestTrackingVolume(); - if (tVolume->confinedVolumes()) { - for (auto volume : tVolume->confinedVolumes()->arrayObjects()) { - if (volume->confinedLayers()) { - for (const auto& layer : volume->confinedLayers()->arrayObjects()) { - if (layer->layerType() == Acts::navigation) continue; - for (auto surface : layer->surfaceArray()->surfaces()) { - if (surface) { - const Acts::DetectorElementBase *detElement = surface->associatedDetectorElement(); - const auto *faserDetElement = dynamic_cast<const FaserActsDetectorElement*>(detElement); - auto* tmp = const_cast<FaserActsDetectorElement*>(faserDetElement); - if (*tmp == spElement) { - geoId = surface->geometryId(); - } - } - } - } - } - } - } - - const Acts::Surface* surfacePtr = trackingGeometry->findSurface(geoId); - surfSequence.push_back(surfacePtr); - if (not surfacePtr) { - ATH_MSG_ERROR("Could not find surface " << geoId); - return StatusCode::FAILURE; - } - - Index spIdx = measurements.size(); - IndexSourceLink sourceLink(geoId, spIdx); - - - auto par = sp->localParameters(); - auto cov = sp->localCovariance(); - std::array<Acts::BoundIndices, 2> indices = {Acts::eBoundLoc0, Acts::eBoundLoc1}; - ThisMeasurement meas(sourceLink, indices, par, cov); - sourceLinks.push_back(std::move(sourceLink)); - measurements.emplace_back(std::move(meas)); - - - // Get the truth position and momentum - SG::ReadHandle<McEventCollection> h_mcEvents(m_mcEventKey); - SG::ReadHandle<TrackerSimDataCollection> h_collectionMap(m_sctMap); - const auto& simdata = h_collectionMap->find(id)->second; - const auto& deposits = simdata.getdeposits(); - for( const auto& depositPair : deposits) - { - if (depositPair.first->pdg_id() == -13) { - pv = depositPair.first->production_vertex()->position(); - truthmom = depositPair.first->momentum(); - } - } - - // Get the measurements - Amg::Vector3D gloPos=sp->globalPosition(); - int station = m_idHelper->station(id); - int plane = m_idHelper->layer(id); - if (station==1 && plane==0) { - N_1_0++; - pos1_0 = Acts::Vector3(gloPos.x(), gloPos.y(), gloPos.z()); - - // Construct a plane surface as the target surface - const TrackerDD::SiDetectorDesign &design = siSpElement->design(); - double hlX = design.width()/2. * 1_mm; - double hlY = design.length()/2. * 1_mm; - auto rectangleBounds = std::make_shared<const Acts::RectangleBounds>(hlX, hlY); - Amg::Transform3D g2l = siSpElement->getMaterialGeom()->getDefAbsoluteTransform() - * Amg::CLHEPTransformToEigen(siSpElement->recoToHitTransform()); - pSurface = Acts::Surface::makeShared<Acts::PlaneSurface>( g2l, rectangleBounds ); - } - if (station==1 && plane==1) { - N_1_1++; - pos1_1 = Acts::Vector3(gloPos.x(), gloPos.y(), gloPos.z()); - } - if (station==1 && plane==2) { - N_1_2++; - pos1_2 = Acts::Vector3(gloPos.x(), gloPos.y(), gloPos.z()); - } - if (station==2 && plane==0) { - N_2_0++; - pos2_0 = Acts::Vector3(gloPos.x(), gloPos.y(), gloPos.z()); - } - if (station==2 && plane==1) { - N_2_1++; - pos2_1 = Acts::Vector3(gloPos.x(), gloPos.y(), gloPos.z()); - } - if (station==2 && plane==2) { - N_2_2++; - pos2_2 = Acts::Vector3(gloPos.x(), gloPos.y(), gloPos.z()); - } - } - - for (auto sl : sourceLinks) - { - std::cout << "??volume=" << sl.geometryId().volume() << std::endl; - std::cout << "??layer=" << sl.geometryId().layer() << std::endl; - std::cout << "??sensitive=" << sl.geometryId().sensitive() << std::endl; - } - - // Calculate the initial track parameters - if ( (N_1_0==1) && (N_1_1==1) && (N_1_2==1) && (N_2_0==1) && (N_2_1==1) && (N_2_2==1)) { - std::cout<<"!!!!!!!!!!! pos1_0 = ("<<pos1_0.x()<<", "<<pos1_0.y()<<", "<<pos1_0.z()<<") "<<std::endl; - std::cout<<"!!!!!!!!!!! pos1_1 = ("<<pos1_1.x()<<", "<<pos1_1.y()<<", "<<pos1_1.z()<<") "<<std::endl; - std::cout<<"!!!!!!!!!!! pos1_2 = ("<<pos1_2.x()<<", "<<pos1_2.y()<<", "<<pos1_2.z()<<") "<<std::endl; - std::cout<<"!!!!!!!!!!! pos2_0 = ("<<pos2_0.x()<<", "<<pos2_0.y()<<", "<<pos2_0.z()<<") "<<std::endl; - std::cout<<"!!!!!!!!!!! pos2_1 = ("<<pos2_1.x()<<", "<<pos2_1.y()<<", "<<pos2_1.z()<<") "<<std::endl; - std::cout<<"!!!!!!!!!!! pos2_2 = ("<<pos2_2.x()<<", "<<pos2_2.y()<<", "<<pos2_2.z()<<") "<<std::endl; - //@FIXME: change the hard codes in future - double charge = 1; - double B = 0.55; - //const Acts::Vector3 pos = pos1_0; - const Acts::Vector3 pos(pos1_0.x(), pos1_0.y(), pos1_0.z()-1); - Acts::Vector3 d1 = pos1_2 - pos1_0; - Acts::Vector3 d2 = pos2_2 - pos2_0; - // the direction of momentum in the first station - Acts::Vector3 direct1 = d1.normalized(); - // the direction of momentum in the second station - Acts::Vector3 direct2 = d2.normalized(); - // the vector pointing from the center of circle to the particle at layer 2 in Y-Z plane - double R1_z = charge * direct1.y() / std::sqrt(direct1.y()*direct1.y() + direct1.z()*direct1.z()); - // double R1_y = -charge * direct1.z() / std::sqrt(direct1.y()*direct1.y() + direct1.z()*direct1.z()); - // the vector pointing from the center of circle to the particle at layer 3 in Y-Z plane - double R2_z = charge * direct2.y() / std::sqrt(direct2.y()*direct2.y() + direct2.z()*direct2.z()); - // double R2_y = -charge * direct2.z() / std::sqrt(direct2.y()*direct2.y() + direct2.z()*direct2.z()); - // the norm of radius - double R = (pos2_0.z() - pos1_2.z()) / (R2_z - R1_z); - // the norm of momentum in Y-Z plane - double p_yz = 0.3*B*R / 1000.0; // R(mm), p(GeV), B(T) - double p_z = p_yz * direct1.z() / std::sqrt(direct1.y()*direct1.y() + direct1.z()*direct1.z()); - double p_y = p_yz * direct1.y() / std::sqrt(direct1.y()*direct1.y() + direct1.z()*direct1.z()); - double p_x = direct1.x() * p_z / direct1.z(); - // total momentum at the layer 0 - const Acts::Vector3 mom(p_x, p_y, p_z); - double p = mom.norm(); - std::cout<<"!!!!!!!!!!! InitTrack momentum on layer 0: ( "<<mom.x()*1000<<", "<<mom.y()*1000<<", "<<mom.z()*1000<<", "<<p*1000<<") "<<std::endl; - // build the track covariance matrix using the smearing sigmas - double sigmaU = 200_um; - double sigmaV = 200_um; - double sigmaPhi = 1_degree; - double sigmaTheta = 1_degree; - double sigmaQOverP = 0.01*p / (p*p); - double sigmaT0 = 1_ns; - Acts::BoundSymMatrix cov = Acts::BoundSymMatrix::Zero(); - cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = sigmaU * sigmaU; - cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = sigmaV * sigmaV; - cov(Acts::eBoundPhi, Acts::eBoundPhi) = sigmaPhi * sigmaPhi; - cov(Acts::eBoundTheta, Acts::eBoundTheta) = sigmaTheta * sigmaTheta; - cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = sigmaQOverP * sigmaQOverP; - cov(Acts::eBoundTime, Acts::eBoundTime) = sigmaT0 * sigmaT0; - double time =0; - //Acts::CurvilinearTrackParameters InitTrackParam(std::make_optional(std::move(cov)), pos, mom, charge, time); // calculated initial parameters - - // Smearing truth parameters as initial parameters - Acts::Vector3 pPos(pv.x(), pv.y(), pv.z()); - Acts::Vector3 pMom(truthmom.x()/1000., truthmom.y()/1000., truthmom.z()/1000.); - std::random_device rd; - std::default_random_engine rng {rd()}; - std::normal_distribution<> norm; // mu: 0 sigma: 1 - Acts::Vector3 deltaPos(sigmaU*norm(rng), sigmaU*norm(rng), sigmaU*norm(rng)); - auto theta = Acts::VectorHelpers::theta(pMom.normalized()); - auto phi = Acts::VectorHelpers::phi(pMom.normalized()); - auto angles = Acts::detail::normalizePhiTheta(phi + sigmaPhi*norm(rng), theta + sigmaTheta*norm(rng)); - Acts::Vector3 dir(std::sin(angles.second) * std::cos(angles.first), - std::sin(angles.second) * std::sin(angles.first), - std::cos(angles.second)); - const Acts::Vector3 deltaMom = ( pMom.norm()*(1 + 0.01*norm(rng)) ) * dir - pMom; - std::cout << "deltaPos: " << deltaPos << std::endl; - std::cout << "deltaMom: " << deltaMom << std::endl; - const Acts::Vector4 posTime ((pPos+deltaPos).x(), (pPos+deltaPos).y(), (pPos+deltaPos).z(), time); - const Acts::Vector3 momentum = pMom+deltaMom; - const Acts::Vector3 momentum_dir = momentum.normalized(); - double momentum_abs = momentum.norm(); - Acts::CurvilinearTrackParameters InitTrackParam(posTime, momentum_dir, momentum_abs, charge, std::make_optional(std::move(cov))); - - // the surface which the production point is bound to - Acts::Vector3 center(0, 0, pPos.z()); - Acts::Vector3 normal(0, 0, 1); - std::shared_ptr<const Acts::Surface> initSurface = Acts::Surface::makeShared<Acts::PlaneSurface>(center, normal); - // extrapolate the particle from production point to the first layer - const Acts::Vector4 truthPosTime (pPos.x(), pPos.y(), pPos.z(), time); -// const Acts::Vector3 truthMomentum_dir = pMom.normalized(); -// double truthMomentum_abs = pMom.norm(); - - BoundVector params = BoundVector::Zero(); - params[Acts::eBoundLoc0] = pPos.x(); - params[Acts::eBoundLoc1] = pPos.y(); - params[Acts::eBoundPhi] = Acts::VectorHelpers::phi(pMom.normalized()); - params[Acts::eBoundTheta] = Acts::VectorHelpers::theta(pMom.normalized()); - params[Acts::eBoundQOverP] = charge/p; - params[Acts::eBoundTime] = time; - - Acts::BoundTrackParameters startParameters(initSurface, params, charge, std::nullopt); - auto truthParam = m_extrapolationTool->propagate(Gaudi::Hive::currentContext(), startParameters, *pSurface); - std::cout << "truth pos on 1st layer: " << truthParam->position(geoctx) << std::endl; - std::cout << "truth mom on 1st layer: " << truthParam->momentum() << std::endl; - std::cout << "truth parameters on 1st layer: " << truthParam->parameters() << std::endl; - - - // Call the Acts Kalman Filter - // Prepare the output data with MultiTrajectory - TrajectoryContainer trajectories; - trajectories.reserve(1); - - // Construct a perigee surface as the target surface - //auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>( - // Acts::Vector3{0., 0., 0.}); - - // Set the KalmanFitter options - std::unique_ptr<const Acts::Logger> logger = Acts::getDefaultLogger("KalmanFitter", Acts::Logging::VERBOSE); - Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder> kfOptions( + Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder, Acts::VoidReverseFilteringLogic> kfOptions( geoctx, magctx, calctx, - MeasurementCalibrator(measurements), + MeasurementCalibrator(measurements->at(i)), Acts::VoidOutlierFinder(), - Acts::LoggerWrapper{*logger}, + Acts::VoidReverseFilteringLogic(), + Acts::LoggerWrapper{*m_logger}, Acts::PropagatorPlainOptions(), - &(*pSurface), - true, // scattering - true, // energy loss - false // backward filtering + &(*initialSurface) ); + kfOptions.multipleScattering = false; + kfOptions.energyLoss = false; ATH_MSG_DEBUG("Invoke fitter"); - - // Acts::Navigator navigator(trackingGeometry); - Acts::DirectNavigator navigator; - // navigator.resolvePassive = false; - // navigator.resolveMaterial = true; - // navigator.resolveSensitive = true; - - std::unique_ptr<ActsExtrapolationDetail::VariantPropagator> varProp; - - if (m_fieldMode == "FASER") { - ATH_MSG_INFO("Using FASER magnetic field service"); - ATH_CHECK( m_fieldCondObjInputKey.initialize() ); - auto bField = std::make_shared<FASERMagneticFieldWrapper>(); - auto stepper = Acts::EigenStepper<>(std::move(bField)); - auto propagator = Acts::Propagator<decltype(stepper), Acts::DirectNavigator>(std::move(stepper), - std::move(navigator)); - varProp = std::make_unique<VariantPropagator>(propagator); - } - else if (m_fieldMode == "Constant") { - if (m_constantFieldVector.value().size() != 3) - { - ATH_MSG_ERROR("Incorrect field vector size. Using empty field."); - return StatusCode::FAILURE; - } - - Acts::Vector3 constantFieldVector = Acts::Vector3(m_constantFieldVector[0], - m_constantFieldVector[1], - m_constantFieldVector[2]); - - ATH_MSG_INFO("Using constant magnetic field: (Bx, By, Bz) = (" << m_constantFieldVector[0] << ", " - << m_constantFieldVector[1] << ", " - << m_constantFieldVector[2] << ")"); - auto bField = std::make_shared<Acts::ConstantBField>(constantFieldVector); - auto stepper = Acts::EigenStepper<>(std::move(bField)); - auto propagator = Acts::Propagator<decltype(stepper), Acts::DirectNavigator>(std::move(stepper), - std::move(navigator)); - varProp = std::make_unique<VariantPropagator>(propagator); - } - - auto fit = makeFitterFunction(varProp.get()); - auto result = fit(sourceLinks, InitTrackParam, kfOptions, surfSequence); - - ATH_MSG_VERBOSE("Size of sourceLinks: " << sourceLinks.size()); + auto result = (*m_fit)(sourceLinks->at(i), initialTrackParameters->at(i), kfOptions); int itrack = 0; if (result.ok()) { // Get the fit output object const auto& fitOutput = result.value(); + std::unique_ptr<Trk::Track> track = makeTrack(geoctx, result, clusters->at(i)); + if (track) { + outputTracks->push_back(std::move(track)); + } // The track entry indices container. One element here. std::vector<size_t> trackTips; @@ -568,752 +186,142 @@ StatusCode FaserActsKalmanFilterAlg::execute() trajectories.emplace_back(std::move(fitOutput.fittedStates), std::move(trackTips), std::move(indexedParams)); } else { - ATH_MSG_WARNING("Fit failed for track " << itrack << " with error" - << result.error()); + ATH_MSG_WARNING("Fit failed for track " << itrack << " with error" << result.error()); // Fit failed, but still create a empty truth fit track trajectories.push_back(FaserActsRecMultiTrajectory()); } + } - fillFitResult(geoctx, trajectories, *truthParam); +// std::vector<Acts::CurvilinearTrackParameters> initialTrackParametersVector {*initialTrackParameters}; +// m_trajectoryWriterTool->writeout(trajectories, geoctx, initialTrackParametersVector); +// ATH_CHECK(m_trajectoryStatesWriterTool->write(trajectories, geoctx, *idLinks)); - } - return StatusCode::SUCCESS; -} + ATH_CHECK(trackContainer.record(std::move(outputTracks))); -StatusCode FaserActsKalmanFilterAlg::finalize() -{ return StatusCode::SUCCESS; } -namespace { - - template <typename Fitter> - struct FitterFunctionImpl - { - Fitter fitter; - - FitterFunctionImpl(Fitter&& f) : fitter(std::move(f)) {} - - FaserActsKalmanFilterAlg::FitterResult - operator()( - const std::vector<IndexSourceLink>& sourceLinks, - const Acts::CurvilinearTrackParameters& initialParameters, - const Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder>& options, - const std::vector<const Acts::Surface*>& sSequence) const - { - return fitter.fit(sourceLinks, initialParameters, options, sSequence); - }; - }; +StatusCode FaserActsKalmanFilterAlg::finalize() { + return StatusCode::SUCCESS; } -FaserActsKalmanFilterAlg::FitterFunction -FaserActsKalmanFilterAlg::makeFitterFunction( - ActsExtrapolationDetail::VariantPropagator* varProp) -{ - - return boost::apply_visitor([&](const auto& propagator) -> FitterFunction { - using Updater = Acts::GainMatrixUpdater; - using Smoother = Acts::GainMatrixSmoother; - using Fitter = Acts::KalmanFitter<typename std::decay_t<decltype(propagator)>, Updater, Smoother>; - - Fitter fitter(std::move(propagator)); - // build the fitter functions. owns the fitter object. - return FitterFunctionImpl<Fitter>(std::move(fitter)); - }, *varProp); -} - -//Acts::MagneticFieldContext FaserActsKalmanFilterAlg::getMagneticFieldContext(const EventContext& ctx) const { -//SG::ReadCondHandle<FaserFieldCacheCondObj> readHandle{m_fieldCondObjInputKey, ctx}; -Acts::MagneticFieldContext FaserActsKalmanFilterAlg::getMagneticFieldContext() const { - SG::ReadCondHandle<FaserFieldCacheCondObj> readHandle{m_fieldCondObjInputKey}; +Acts::MagneticFieldContext FaserActsKalmanFilterAlg::getMagneticFieldContext(const EventContext& ctx) const { + SG::ReadCondHandle<FaserFieldCacheCondObj> readHandle{m_fieldCondObjInputKey, ctx}; if (!readHandle.isValid()) { std::stringstream msg; msg << "Failed to retrieve magnetic field condition data " << m_fieldCondObjInputKey.key() << "."; throw std::runtime_error(msg.str()); } const FaserFieldCacheCondObj* fieldCondObj{*readHandle}; - return Acts::MagneticFieldContext(fieldCondObj); } -void FaserActsKalmanFilterAlg::initializeTree() -{ - m_trackTree->Branch("event_nr", &m_eventNr); - m_trackTree->Branch("traj_nr", &m_trajNr); - m_trackTree->Branch("track_nr", &m_trackNr); - m_trackTree->Branch("t_barcode", &m_t_barcode, "t_barcode/l"); - m_trackTree->Branch("t_charge", &m_t_charge); - m_trackTree->Branch("t_eT", &m_t_eT); - m_trackTree->Branch("t_eLOC0", &m_t_eLOC0); - m_trackTree->Branch("t_eLOC1", &m_t_eLOC1); - m_trackTree->Branch("t_x", &m_t_x); - m_trackTree->Branch("t_y", &m_t_y); - m_trackTree->Branch("t_z", &m_t_z); - m_trackTree->Branch("t_px", &m_t_px); - m_trackTree->Branch("t_py", &m_t_py); - m_trackTree->Branch("t_pz", &m_t_pz); - m_trackTree->Branch("t_eTHETA", &m_t_eTHETA); - m_trackTree->Branch("t_ePHI", &m_t_ePHI); - m_trackTree->Branch("t_eQOP", &m_t_eQOP); - - m_trackTree->Branch("hasFittedParams", &m_hasFittedParams); - m_trackTree->Branch("chi2_fit", &m_chi2_fit); - m_trackTree->Branch("ndf_fit", &m_ndf_fit); - m_trackTree->Branch("eLOC0_fit", &m_eLOC0_fit); - m_trackTree->Branch("eLOC1_fit", &m_eLOC1_fit); - m_trackTree->Branch("ePHI_fit", &m_ePHI_fit); - m_trackTree->Branch("eTHETA_fit", &m_eTHETA_fit); - m_trackTree->Branch("eQOP_fit", &m_eQOP_fit); - m_trackTree->Branch("eT_fit", &m_eT_fit); - m_trackTree->Branch("charge_fit", &m_charge_fit); - m_trackTree->Branch("err_eLOC0_fit", &m_err_eLOC0_fit); - m_trackTree->Branch("err_eLOC1_fit", &m_err_eLOC1_fit); - m_trackTree->Branch("err_ePHI_fit", &m_err_ePHI_fit); - m_trackTree->Branch("err_eTHETA_fit", &m_err_eTHETA_fit); - m_trackTree->Branch("err_eQOP_fit", &m_err_eQOP_fit); - m_trackTree->Branch("err_eT_fit", &m_err_eT_fit); - m_trackTree->Branch("g_px_fit", &m_px_fit); - m_trackTree->Branch("g_py_fit", &m_py_fit); - m_trackTree->Branch("g_pz_fit", &m_pz_fit); - m_trackTree->Branch("g_x_fit" , &m_x_fit); - m_trackTree->Branch("g_y_fit" , &m_y_fit); - m_trackTree->Branch("g_z_fit" , &m_z_fit); - - m_trackTree->Branch("nHoles", &m_nHoles); - m_trackTree->Branch("nOutliers", &m_nOutliers); - m_trackTree->Branch("nStates", &m_nStates); - m_trackTree->Branch("nMeasurements", &m_nMeasurements); - m_trackTree->Branch("volume_id", &m_volumeID); - m_trackTree->Branch("layer_id", &m_layerID); - m_trackTree->Branch("module_id", &m_moduleID); - m_trackTree->Branch("l_x_hit", &m_lx_hit); - m_trackTree->Branch("l_y_hit", &m_ly_hit); - m_trackTree->Branch("g_x_hit", &m_x_hit); - m_trackTree->Branch("g_y_hit", &m_y_hit); - m_trackTree->Branch("g_z_hit", &m_z_hit); - m_trackTree->Branch("res_x_hit", &m_res_x_hit); - m_trackTree->Branch("res_y_hit", &m_res_y_hit); - m_trackTree->Branch("err_x_hit", &m_err_x_hit); - m_trackTree->Branch("err_y_hit", &m_err_y_hit); - m_trackTree->Branch("pull_x_hit", &m_pull_x_hit); - m_trackTree->Branch("pull_y_hit", &m_pull_y_hit); - m_trackTree->Branch("dim_hit", &m_dim_hit); - m_trackTree->Branch("nPredicted", &m_nPredicted); - m_trackTree->Branch("predicted", &m_prt); - m_trackTree->Branch("eLOC0_prt", &m_eLOC0_prt); - m_trackTree->Branch("eLOC1_prt", &m_eLOC1_prt); - m_trackTree->Branch("ePHI_prt", &m_ePHI_prt); - m_trackTree->Branch("eTHETA_prt", &m_eTHETA_prt); - m_trackTree->Branch("eQOP_prt", &m_eQOP_prt); - m_trackTree->Branch("eT_prt", &m_eT_prt); - m_trackTree->Branch("res_eLOC0_prt", &m_res_eLOC0_prt); - m_trackTree->Branch("res_eLOC1_prt", &m_res_eLOC1_prt); - m_trackTree->Branch("err_eLOC0_prt", &m_err_eLOC0_prt); - m_trackTree->Branch("err_eLOC1_prt", &m_err_eLOC1_prt); - m_trackTree->Branch("err_ePHI_prt", &m_err_ePHI_prt); - m_trackTree->Branch("err_eTHETA_prt", &m_err_eTHETA_prt); - m_trackTree->Branch("err_eQOP_prt", &m_err_eQOP_prt); - m_trackTree->Branch("err_eT_prt", &m_err_eT_prt); - m_trackTree->Branch("pull_eLOC0_prt", &m_pull_eLOC0_prt); - m_trackTree->Branch("pull_eLOC1_prt", &m_pull_eLOC1_prt); - m_trackTree->Branch("g_x_prt", &m_x_prt); - m_trackTree->Branch("g_y_prt", &m_y_prt); - m_trackTree->Branch("g_z_prt", &m_z_prt); - m_trackTree->Branch("px_prt", &m_px_prt); - m_trackTree->Branch("py_prt", &m_py_prt); - m_trackTree->Branch("pz_prt", &m_pz_prt); - m_trackTree->Branch("eta_prt", &m_eta_prt); - m_trackTree->Branch("pT_prt", &m_pT_prt); - - m_trackTree->Branch("nFiltered", &m_nFiltered); - m_trackTree->Branch("filtered", &m_flt); - m_trackTree->Branch("eLOC0_flt", &m_eLOC0_flt); - m_trackTree->Branch("eLOC1_flt", &m_eLOC1_flt); - m_trackTree->Branch("ePHI_flt", &m_ePHI_flt); - m_trackTree->Branch("eTHETA_flt", &m_eTHETA_flt); - m_trackTree->Branch("eQOP_flt", &m_eQOP_flt); - m_trackTree->Branch("eT_flt", &m_eT_flt); - m_trackTree->Branch("res_eLOC0_flt", &m_res_eLOC0_flt); - m_trackTree->Branch("res_eLOC1_flt", &m_res_eLOC1_flt); - m_trackTree->Branch("err_eLOC0_flt", &m_err_eLOC0_flt); - m_trackTree->Branch("err_eLOC1_flt", &m_err_eLOC1_flt); - m_trackTree->Branch("err_ePHI_flt", &m_err_ePHI_flt); - m_trackTree->Branch("err_eTHETA_flt", &m_err_eTHETA_flt); - m_trackTree->Branch("err_eQOP_flt", &m_err_eQOP_flt); - m_trackTree->Branch("err_eT_flt", &m_err_eT_flt); - m_trackTree->Branch("pull_eLOC0_flt", &m_pull_eLOC0_flt); - m_trackTree->Branch("pull_eLOC1_flt", &m_pull_eLOC1_flt); - m_trackTree->Branch("g_x_flt", &m_x_flt); - m_trackTree->Branch("g_y_flt", &m_y_flt); - m_trackTree->Branch("g_z_flt", &m_z_flt); - m_trackTree->Branch("px_flt", &m_px_flt); - m_trackTree->Branch("py_flt", &m_py_flt); - m_trackTree->Branch("pz_flt", &m_pz_flt); - m_trackTree->Branch("eta_flt", &m_eta_flt); - m_trackTree->Branch("pT_flt", &m_pT_flt); - m_trackTree->Branch("chi2", &m_chi2); - - m_trackTree->Branch("nSmoothed", &m_nSmoothed); - m_trackTree->Branch("smoothed", &m_smt); - m_trackTree->Branch("eLOC0_smt", &m_eLOC0_smt); - m_trackTree->Branch("eLOC1_smt", &m_eLOC1_smt); - m_trackTree->Branch("ePHI_smt", &m_ePHI_smt); - m_trackTree->Branch("eTHETA_smt", &m_eTHETA_smt); - m_trackTree->Branch("eQOP_smt", &m_eQOP_smt); - m_trackTree->Branch("eT_smt", &m_eT_smt); - m_trackTree->Branch("res_eLOC0_smt", &m_res_eLOC0_smt); - m_trackTree->Branch("res_eLOC1_smt", &m_res_eLOC1_smt); - m_trackTree->Branch("err_eLOC0_smt", &m_err_eLOC0_smt); - m_trackTree->Branch("err_eLOC1_smt", &m_err_eLOC1_smt); - m_trackTree->Branch("err_ePHI_smt", &m_err_ePHI_smt); - m_trackTree->Branch("err_eTHETA_smt", &m_err_eTHETA_smt); - m_trackTree->Branch("err_eQOP_smt", &m_err_eQOP_smt); - m_trackTree->Branch("err_eT_smt", &m_err_eT_smt); - m_trackTree->Branch("pull_eLOC0_smt", &m_pull_eLOC0_smt); - m_trackTree->Branch("pull_eLOC1_smt", &m_pull_eLOC1_smt); - m_trackTree->Branch("g_x_smt", &m_x_smt); - m_trackTree->Branch("g_y_smt", &m_y_smt); - m_trackTree->Branch("g_z_smt", &m_z_smt); - m_trackTree->Branch("px_smt", &m_px_smt); - m_trackTree->Branch("py_smt", &m_py_smt); - m_trackTree->Branch("pz_smt", &m_pz_smt); - m_trackTree->Branch("eta_smt", &m_eta_smt); - m_trackTree->Branch("pT_smt", &m_pT_smt); +std::unique_ptr<Trk::Track> +FaserActsKalmanFilterAlg::makeTrack(Acts::GeometryContext& geoCtx, TrackFitterResult& fitResult, std::vector<const Tracker::FaserSCT_Cluster*> clusters) const { + using ConstTrackStateProxy = + Acts::detail_lt::TrackStateProxy<IndexSourceLink, 6, true>; + std::unique_ptr<Trk::Track> newtrack = nullptr; + //Get the fit output object + const auto& fitOutput = fitResult.value(); + if (fitOutput.fittedParameters) { + DataVector<const Trk::TrackStateOnSurface>* finalTrajectory = new DataVector<const Trk::TrackStateOnSurface>{}; + std::vector<std::unique_ptr<const Acts::BoundTrackParameters>> actsSmoothedParam; + // Loop over all the output state to create track state + fitOutput.fittedStates.visitBackwards(fitOutput.lastMeasurementIndex, [&](const ConstTrackStateProxy& state) { + auto flag = state.typeFlags(); + if (state.referenceSurface().associatedDetectorElement() != nullptr) { + // We need to determine the type of state + std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern; + const Trk::TrackParameters *parm; + + // State is a hole (no associated measurement), use predicted para meters + if (flag[Acts::TrackStateFlag::HoleFlag] == true) { + const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(), + state.predicted(), + state.predictedCovariance()); + parm = ConvertActsTrackParameterToATLAS(actsParam, geoCtx); + // auto boundaryCheck = m_boundaryCheckTool->boundaryCheck(*p arm); + typePattern.set(Trk::TrackStateOnSurface::Hole); + } + // The state was tagged as an outlier, use filtered parameters + else if (flag[Acts::TrackStateFlag::OutlierFlag] == true) { + const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(), + state.filtered(), state.filteredCovariance()); + parm = ConvertActsTrackParameterToATLAS(actsParam, geoCtx); + typePattern.set(Trk::TrackStateOnSurface::Outlier); + } + // The state is a measurement state, use smoothed parameters + else { + const Acts::BoundTrackParameters actsParam(state.referenceSurface().getSharedPtr(), + state.smoothed(), state.smoothedCovariance()); + actsSmoothedParam.push_back(std::make_unique<const Acts::BoundTrackParameters>(Acts::BoundTrackParameters(actsParam))); + // const auto& psurface=actsParam.referenceSurface(); + Acts::Vector2 local(actsParam.parameters()[Acts::eBoundLoc0], actsParam.parameters()[Acts::eBoundLoc1]); + // const Acts::Vector3 dir = Acts::makeDirectionUnitFromPhiTheta(actsParam.parameters()[Acts::eBoundPhi], actsParam.parameters()[Acts::eBoundTheta]); + // auto pos=actsParam.position(tgContext); + parm = ConvertActsTrackParameterToATLAS(actsParam, geoCtx); + typePattern.set(Trk::TrackStateOnSurface::Measurement); + } + Tracker::FaserSCT_ClusterOnTrack* measState = nullptr; + if (state.hasUncalibrated()) { + const Tracker::FaserSCT_Cluster* fitCluster = clusters.at(state.uncalibrated().index()); + if (fitCluster->detectorElement() != nullptr) { + measState = new Tracker::FaserSCT_ClusterOnTrack{ + fitCluster, + Trk::LocalParameters{ + Trk::DefinedParameter{fitCluster->localPosition()[0], Trk::loc1}, + Trk::DefinedParameter{fitCluster->localPosition()[1], Trk::loc2} + }, + fitCluster->localCovariance(), + m_idHelper->wafer_hash(fitCluster->detectorElement()->identify()) + }; + } + } + double nDoF = state.calibratedSize(); + const Trk::FitQualityOnSurface *quality = new Trk::FitQualityOnSurface(state.chi2(), nDoF); + const Trk::TrackStateOnSurface *perState = new Trk::TrackStateOnSurface(measState, parm, quality, nullptr, typePattern); + // If a state was succesfully created add it to the trajectory + if (perState) { + finalTrajectory->insert(finalTrajectory->begin(), perState); + } + } + return; + }); + + // Create the track using the states + const Trk::TrackInfo newInfo(Trk::TrackInfo::TrackFitter::KalmanFitter, Trk::ParticleHypothesis::muon); + // Trk::FitQuality* q = nullptr; + // newInfo.setTrackFitter(Trk::TrackInfo::TrackFitter::KalmanFitter ); //Mark the fitter as KalmanFitter + newtrack = std::make_unique<Trk::Track>(newInfo, std::move(*finalTrajectory), nullptr); + } + return newtrack; } -void FaserActsKalmanFilterAlg::fillFitResult( - const Acts::GeometryContext& geoctx, - const TrajectoryContainer& trajectories, - const Acts::BoundTrackParameters& truthParam -) -{ - m_t_eLOC0 = truthParam.parameters()[Acts::eBoundLoc0]; - m_t_eLOC1 = truthParam.parameters()[Acts::eBoundLoc1]; - m_t_ePHI = truthParam.parameters()[Acts::eBoundPhi]; - m_t_eTHETA = truthParam.parameters()[Acts::eBoundTheta]; - m_t_eQOP = truthParam.parameters()[Acts::eBoundQOverP]; - m_t_eT = truthParam.parameters()[Acts::eBoundTime]; - m_t_x = truthParam.position(geoctx)(0); - m_t_y = truthParam.position(geoctx)(1); - m_t_z = truthParam.position(geoctx)(2); - m_t_px = truthParam.momentum()(0); - m_t_py = truthParam.momentum()(1); - m_t_pz = truthParam.momentum()(2); - std::cout<<"truth global position on the first layer = "<<m_t_x<<" "<<m_t_y<<" "<<m_t_z<<" "<<std::endl; - std::cout<<"truth momentum on the first layer = "<<m_t_px<<" "<<m_t_py<<" "<<m_t_pz<<" "<<std::endl; - std::cout<<"truth local parameters on the first layer = "<<m_t_eLOC0<<" "<<m_t_eLOC1<<" "<<m_t_ePHI<<" "<<m_t_eTHETA<<" "<<m_t_eQOP<<" "<<std::endl; - - // Loop over the trajectories - int iTraj = 0; - for (const auto& traj : trajectories) { - m_trajNr = iTraj; - - // The trajectory entry indices and the multiTrajectory - const auto& [trackTips, mj] = traj.trajectory(); - if (trackTips.empty()) { - ATH_MSG_WARNING("Empty multiTrajectory."); - continue; +const Trk::TrackParameters* +FaserActsKalmanFilterAlg ::ConvertActsTrackParameterToATLAS(const Acts::BoundTrackParameters &actsParameter, const Acts::GeometryContext& gctx) const { + using namespace Acts::UnitLiterals; + std::optional<AmgSymMatrix(5)> cov = std::nullopt; + if (actsParameter.covariance()){ + AmgSymMatrix(5) newcov(actsParameter.covariance()->topLeftCorner(5, 5)); + // Convert the covariance matrix to GeV + for(int i=0; i < newcov.rows(); i++){ + newcov(i, 4) = newcov(i, 4)*1_MeV; } - - // Get the entry index for the single trajectory - auto& trackTip = trackTips.front(); - std::cout<<"trackTip = "<<trackTip<<std::endl; - - // Collect the trajectory summary info - auto trajState = - Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); - - m_nMeasurements = trajState.nMeasurements; - m_nStates = trajState.nStates; - m_nOutliers = trajState.nOutliers; - m_nHoles = trajState.nHoles; - m_chi2_fit = trajState.chi2Sum; - m_ndf_fit = trajState.NDF; - std::cout << "Track has " << trajState.nMeasurements - << " measurements and " << trajState.nHoles - << " holes and " << trajState.nOutliers - << " outliers and " << trajState.nStates - << " states " << std::endl; - - /// If it has track parameters, fill the values - if (traj.hasTrackParameters(trackTip)) - { - m_hasFittedParams = true; - const auto &boundParam = traj.trackParameters(trackTip); - const auto ¶meter = boundParam.parameters(); - const auto &covariance = *boundParam.covariance(); - m_charge_fit = boundParam.charge(); - m_eLOC0_fit = parameter[Acts::eBoundLoc0]; - m_eLOC1_fit = parameter[Acts::eBoundLoc1]; - m_ePHI_fit = parameter[Acts::eBoundPhi]; - m_eTHETA_fit = parameter[Acts::eBoundTheta]; - m_eQOP_fit = parameter[Acts::eBoundQOverP]; - m_eT_fit = parameter[Acts::eBoundTime]; - m_err_eLOC0_fit = - sqrt(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0)); - m_err_eLOC1_fit = - sqrt(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1)); - m_err_ePHI_fit = sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi)); - m_err_eTHETA_fit = - sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta)); - m_err_eQOP_fit = sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)); - m_err_eT_fit = sqrt(covariance(Acts::eBoundTime, Acts::eBoundTime)); - - m_px_fit = boundParam.momentum()(0); - m_py_fit = boundParam.momentum()(1); - m_pz_fit = boundParam.momentum()(2); - m_x_fit = boundParam.position(geoctx)(0); - m_y_fit = boundParam.position(geoctx)(1); - m_z_fit = boundParam.position(geoctx)(2); + for(int i=0; i < newcov.cols(); i++){ + newcov(4, i) = newcov(4, i)*1_MeV; } - - m_nPredicted = 0; - m_nFiltered = 0; - m_nSmoothed = 0; - - mj.visitBackwards(trackTip, [&](const auto &state) { - /// Only fill the track states with non-outlier measurement - auto typeFlags = state.typeFlags(); - if (not typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) - { - return true; - } - - const auto& surface = state.referenceSurface(); - - /// Get the geometry ID - auto geoID = state.referenceSurface().geometryId(); - m_volumeID.push_back(geoID.volume()); - m_layerID.push_back(geoID.layer()); - m_moduleID.push_back(geoID.sensitive()); - - // expand the local measurements into the full bound space - Acts::BoundVector meas = - state.projector().transpose() * state.calibrated(); - - // extract local and global position - Acts::Vector2 local(meas[Acts::eBoundLoc0], meas[Acts::eBoundLoc1]); - Acts::Vector3 mom(1, 1, 1); - Acts::Vector3 global = - surface.localToGlobal(geoctx, local, mom); - - // fill the measurement info - m_lx_hit.push_back(local[Acts::ePos0]); - m_ly_hit.push_back(local[Acts::ePos1]); - m_x_hit.push_back(global[Acts::ePos0]); - m_y_hit.push_back(global[Acts::ePos1]); - m_z_hit.push_back(global[Acts::ePos2]); - - /// Get the predicted parameter for this state - bool predicted = false; - if (state.hasPredicted()) - { - predicted = true; - m_nPredicted++; - Acts::BoundTrackParameters parameter( - state.referenceSurface().getSharedPtr(), - state.predicted(), - state.predictedCovariance()); - auto covariance = state.predictedCovariance(); - - /// Local hit residual info - auto H = state.effectiveProjector(); - auto resCov = state.effectiveCalibratedCovariance() + - H * covariance * H.transpose(); - auto residual = state.effectiveCalibrated() - H * state.predicted(); - - /// Predicted residual - m_res_eLOC0_prt.push_back(residual(Acts::eBoundLoc0)); - m_res_eLOC1_prt.push_back(residual(Acts::eBoundLoc1)); - - /// Predicted parameter pulls - m_pull_eLOC0_prt.push_back( - residual(Acts::eBoundLoc0) / - sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_pull_eLOC1_prt.push_back( - residual(Acts::eBoundLoc1) / - sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); - - - /// Predicted parameter - m_eLOC0_prt.push_back(parameter.parameters()[Acts::eBoundLoc0]); - m_eLOC1_prt.push_back(parameter.parameters()[Acts::eBoundLoc1]); - m_ePHI_prt.push_back(parameter.parameters()[Acts::eBoundPhi]); - m_eTHETA_prt.push_back(parameter.parameters()[Acts::eBoundTheta]); - m_eQOP_prt.push_back(parameter.parameters()[Acts::eBoundQOverP]); - m_eT_prt.push_back(parameter.parameters()[Acts::eBoundTime]); - - /// Predicted parameter Uncertainties - m_err_eLOC0_prt.push_back( - sqrt(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_err_eLOC1_prt.push_back( - sqrt(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1))); - m_err_ePHI_prt.push_back( - sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi))); - m_err_eTHETA_prt.push_back( - sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta))); - m_err_eQOP_prt.push_back( - sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP))); - m_err_eT_prt.push_back( - sqrt(covariance(Acts::eBoundTime, Acts::eBoundTime))); - - m_x_prt.push_back(parameter.position(geoctx).x()); - m_y_prt.push_back(parameter.position(geoctx).y()); - m_z_prt.push_back(parameter.position(geoctx).z()); - m_px_prt.push_back(parameter.momentum().x()); - m_py_prt.push_back(parameter.momentum().y()); - m_pz_prt.push_back(parameter.momentum().z()); - m_pT_prt.push_back(parameter.transverseMomentum()); - m_eta_prt.push_back(eta(parameter.position(geoctx))); - } - else - { - /// Push bad values if no predicted parameter - m_eLOC0_prt.push_back(-9999); - m_eLOC1_prt.push_back(-9999); - m_ePHI_prt.push_back(-9999); - m_eTHETA_prt.push_back(-9999); - m_eQOP_prt.push_back(-9999); - m_eT_prt.push_back(-9999); - m_res_eLOC0_prt.push_back(-9999); - m_res_eLOC1_prt.push_back(-9999); - m_err_eLOC0_prt.push_back(-9999); - m_err_eLOC1_prt.push_back(-9999); - m_err_ePHI_prt.push_back(-9999); - m_err_eTHETA_prt.push_back(-9999); - m_err_eQOP_prt.push_back(-9999); - m_err_eT_prt.push_back(-9999); - m_pull_eLOC0_prt.push_back(-9999); - m_pull_eLOC1_prt.push_back(-9999); - m_x_prt.push_back(-9999); - m_y_prt.push_back(-9999); - m_z_prt.push_back(-9999); - m_px_prt.push_back(-9999); - m_py_prt.push_back(-9999); - m_pz_prt.push_back(-9999); - m_pT_prt.push_back(-9999); - m_eta_prt.push_back(-9999); - } - - bool filtered = false; - if (state.hasFiltered()) - { - filtered = true; - m_nFiltered++; - Acts::BoundTrackParameters parameter( - state.referenceSurface().getSharedPtr(), - state.filtered(), - state.filteredCovariance()); - auto covariance = state.filteredCovariance(); - - /// Local hit residual info - auto H = state.effectiveProjector(); - auto resCov = state.effectiveCalibratedCovariance() + - H * covariance * H.transpose(); - auto residual = state.effectiveCalibrated() - H * state.filtered(); - - /// Filtered residual - m_res_eLOC0_flt.push_back(residual(Acts::eBoundLoc0)); - m_res_eLOC1_flt.push_back(residual(Acts::eBoundLoc1)); - - /// Filtered parameter pulls - m_pull_eLOC0_flt.push_back( - residual(Acts::eBoundLoc0) / - sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_pull_eLOC1_flt.push_back( - residual(Acts::eBoundLoc1) / - sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); - - /// Filtered parameter - m_eLOC0_flt.push_back(parameter.parameters()[Acts::eBoundLoc0]); - m_eLOC1_flt.push_back(parameter.parameters()[Acts::eBoundLoc1]); - m_ePHI_flt.push_back(parameter.parameters()[Acts::eBoundPhi]); - m_eTHETA_flt.push_back(parameter.parameters()[Acts::eBoundTheta]); - m_eQOP_flt.push_back(parameter.parameters()[Acts::eBoundQOverP]); - m_eT_flt.push_back(parameter.parameters()[Acts::eBoundTime]); - - /// Filtered parameter uncertainties - m_err_eLOC0_flt.push_back( - sqrt(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_err_eLOC1_flt.push_back( - sqrt(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1))); - m_err_ePHI_flt.push_back( - sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi))); - m_err_eTHETA_flt.push_back( - sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta))); - m_err_eQOP_flt.push_back( - sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP))); - m_err_eT_flt.push_back( - sqrt(covariance(Acts::eBoundTime, Acts::eBoundTime))); - - /// Other filtered parameter info - m_x_flt.push_back(parameter.position(geoctx).x()); - m_y_flt.push_back(parameter.position(geoctx).y()); - m_z_flt.push_back(parameter.position(geoctx).z()); - m_px_flt.push_back(parameter.momentum().x()); - m_py_flt.push_back(parameter.momentum().y()); - m_pz_flt.push_back(parameter.momentum().z()); - m_pT_flt.push_back(parameter.transverseMomentum()); - m_eta_flt.push_back(eta(parameter.position(geoctx))); - m_chi2.push_back(state.chi2()); - - } - else - { - /// Push bad values if no filtered parameter - m_eLOC0_flt.push_back(-9999); - m_eLOC1_flt.push_back(-9999); - m_ePHI_flt.push_back(-9999); - m_eTHETA_flt.push_back(-9999); - m_eQOP_flt.push_back(-9999); - m_eT_flt.push_back(-9999); - m_res_eLOC0_flt.push_back(-9999); - m_res_eLOC1_flt.push_back(-9999); - m_err_eLOC0_flt.push_back(-9999); - m_err_eLOC1_flt.push_back(-9999); - m_err_ePHI_flt.push_back(-9999); - m_err_eTHETA_flt.push_back(-9999); - m_err_eQOP_flt.push_back(-9999); - m_err_eT_flt.push_back(-9999); - m_pull_eLOC0_flt.push_back(-9999); - m_pull_eLOC1_flt.push_back(-9999); - m_x_flt.push_back(-9999); - m_y_flt.push_back(-9999); - m_z_flt.push_back(-9999); - m_py_flt.push_back(-9999); - m_pz_flt.push_back(-9999); - m_pT_flt.push_back(-9999); - m_eta_flt.push_back(-9999); - m_chi2.push_back(-9999); - } - - bool smoothed = false; - if (state.hasSmoothed()) - { - smoothed = true; - m_nSmoothed++; - Acts::BoundTrackParameters parameter( - state.referenceSurface().getSharedPtr(), - state.smoothed(), - state.smoothedCovariance()); - auto covariance = state.smoothedCovariance(); - - /// Local hit residual info - auto H = state.effectiveProjector(); - auto resCov = state.effectiveCalibratedCovariance() + - H * covariance * H.transpose(); - auto residual = state.effectiveCalibrated() - H * state.smoothed(); - - m_res_x_hit.push_back(residual(Acts::eBoundLoc0)); - m_res_y_hit.push_back(residual(Acts::eBoundLoc1)); - m_err_x_hit.push_back( - sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_err_y_hit.push_back( - sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); - m_pull_x_hit.push_back( - residual(Acts::eBoundLoc0) / - sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_pull_y_hit.push_back( - residual(Acts::eBoundLoc1) / - sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); - m_dim_hit.push_back(state.calibratedSize()); - - /// Smoothed residual - m_res_eLOC0_smt.push_back(residual(Acts::eBoundLoc0)); - m_res_eLOC1_smt.push_back(residual(Acts::eBoundLoc1)); - - /// Smoothed parameter pulls - m_pull_eLOC0_smt.push_back( - residual(Acts::eBoundLoc0) / - sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_pull_eLOC1_smt.push_back( - residual(Acts::eBoundLoc1) / - sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); - - /// Smoothed parameter - m_eLOC0_smt.push_back(parameter.parameters()[Acts::eBoundLoc0]); - m_eLOC1_smt.push_back(parameter.parameters()[Acts::eBoundLoc1]); - m_ePHI_smt.push_back(parameter.parameters()[Acts::eBoundPhi]); - m_eTHETA_smt.push_back(parameter.parameters()[Acts::eBoundTheta]); - m_eQOP_smt.push_back(parameter.parameters()[Acts::eBoundQOverP]); - m_eT_smt.push_back(parameter.parameters()[Acts::eBoundTime]); - - /// Smoothed parameter uncertainties - m_err_eLOC0_smt.push_back( - sqrt(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_err_eLOC1_smt.push_back( - sqrt(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1))); - m_err_ePHI_smt.push_back( - sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi))); - m_err_eTHETA_smt.push_back( - sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta))); - m_err_eQOP_smt.push_back( - sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP))); - m_err_eT_smt.push_back( - sqrt(covariance(Acts::eBoundTime, Acts::eBoundTime))); - - m_x_smt.push_back(parameter.position(geoctx).x()); - m_y_smt.push_back(parameter.position(geoctx).y()); - m_z_smt.push_back(parameter.position(geoctx).z()); - m_px_smt.push_back(parameter.momentum().x()); - m_py_smt.push_back(parameter.momentum().y()); - m_pz_smt.push_back(parameter.momentum().z()); - m_pT_smt.push_back(parameter.transverseMomentum()); - m_eta_smt.push_back(eta(parameter.position(geoctx))); - } - else - { - /// Push bad values if no smoothed parameter - m_eLOC0_smt.push_back(-9999); - m_eLOC1_smt.push_back(-9999); - m_ePHI_smt.push_back(-9999); - m_eTHETA_smt.push_back(-9999); - m_eQOP_smt.push_back(-9999); - m_eT_smt.push_back(-9999); - m_res_eLOC0_smt.push_back(-9999); - m_res_eLOC1_smt.push_back(-9999); - m_err_eLOC0_smt.push_back(-9999); - m_err_eLOC1_smt.push_back(-9999); - m_err_ePHI_smt.push_back(-9999); - m_err_eTHETA_smt.push_back(-9999); - m_err_eQOP_smt.push_back(-9999); - m_err_eT_smt.push_back(-9999); - m_pull_eLOC0_smt.push_back(-9999); - m_pull_eLOC1_smt.push_back(-9999); - m_x_smt.push_back(-9999); - m_y_smt.push_back(-9999); - m_z_smt.push_back(-9999); - m_px_smt.push_back(-9999); - m_py_smt.push_back(-9999); - m_pz_smt.push_back(-9999); - m_pT_smt.push_back(-9999); - m_eta_smt.push_back(-9999); - m_res_x_hit.push_back(-9999); - m_res_y_hit.push_back(-9999); - m_err_x_hit.push_back(-9999); - m_err_y_hit.push_back(-9999); - m_pull_x_hit.push_back(-9999); - m_pull_y_hit.push_back(-9999); - m_dim_hit.push_back(-9999); - } - - /// Save whether or not states had various KF steps - m_prt.push_back(predicted); - m_flt.push_back(filtered); - m_smt.push_back(smoothed); - - return true; - } /// Finish lambda function - ); /// Finish multi trajectory visitBackwards call - - iTraj++; - - } // all trajectories - - m_trackTree->Fill(); - - clearTrackVariables(); + cov = std::optional<AmgSymMatrix(5)>(newcov); + } + const Amg::Vector3D& pos=actsParameter.position(gctx); + double tphi=actsParameter.get<Acts::eBoundPhi>(); + double ttheta=actsParameter.get<Acts::eBoundTheta>(); + double tqOverP=actsParameter.get<Acts::eBoundQOverP>()*1_MeV; + double p = std::abs(1. / tqOverP); + Amg::Vector3D tmom(p * std::cos(tphi) * std::sin(ttheta), p * std::sin(tphi) * std::sin(ttheta), p * std::cos(ttheta)); + const Trk::CurvilinearParameters * curv = new Trk::CurvilinearParameters(pos,tmom,tqOverP>0, cov); + return curv; } -void FaserActsKalmanFilterAlg::clearTrackVariables() -{ - m_volumeID.clear(); - m_layerID.clear(); - m_moduleID.clear(); - m_lx_hit.clear(); - m_ly_hit.clear(); - m_x_hit.clear(); - m_y_hit.clear(); - m_z_hit.clear(); - m_res_x_hit.clear(); - m_res_y_hit.clear(); - m_err_x_hit.clear(); - m_err_y_hit.clear(); - m_pull_x_hit.clear(); - m_pull_y_hit.clear(); - m_dim_hit.clear(); - - m_prt.clear(); - m_eLOC0_prt.clear(); - m_eLOC1_prt.clear(); - m_ePHI_prt.clear(); - m_eTHETA_prt.clear(); - m_eQOP_prt.clear(); - m_eT_prt.clear(); - m_res_eLOC0_prt.clear(); - m_res_eLOC1_prt.clear(); - m_err_eLOC0_prt.clear(); - m_err_eLOC1_prt.clear(); - m_err_ePHI_prt.clear(); - m_err_eTHETA_prt.clear(); - m_err_eQOP_prt.clear(); - m_err_eT_prt.clear(); - m_pull_eLOC0_prt.clear(); - m_pull_eLOC1_prt.clear(); - m_x_prt.clear(); - m_y_prt.clear(); - m_z_prt.clear(); - m_px_prt.clear(); - m_py_prt.clear(); - m_pz_prt.clear(); - m_eta_prt.clear(); - m_pT_prt.clear(); - - m_flt.clear(); - m_eLOC0_flt.clear(); - m_eLOC1_flt.clear(); - m_ePHI_flt.clear(); - m_eTHETA_flt.clear(); - m_eQOP_flt.clear(); - m_eT_flt.clear(); - m_res_eLOC0_flt.clear(); - m_res_eLOC1_flt.clear(); - m_err_eLOC0_flt.clear(); - m_err_eLOC1_flt.clear(); - m_err_ePHI_flt.clear(); - m_err_eTHETA_flt.clear(); - m_err_eQOP_flt.clear(); - m_err_eT_flt.clear(); - m_pull_eLOC0_flt.clear(); - m_pull_eLOC1_flt.clear(); - m_x_flt.clear(); - m_y_flt.clear(); - m_z_flt.clear(); - m_px_flt.clear(); - m_py_flt.clear(); - m_pz_flt.clear(); - m_eta_flt.clear(); - m_pT_flt.clear(); - m_chi2.clear(); - - m_smt.clear(); - m_eLOC0_smt.clear(); - m_eLOC1_smt.clear(); - m_ePHI_smt.clear(); - m_eTHETA_smt.clear(); - m_eQOP_smt.clear(); - m_eT_smt.clear(); - m_res_eLOC0_smt.clear(); - m_res_eLOC1_smt.clear(); - m_err_eLOC0_smt.clear(); - m_err_eLOC1_smt.clear(); - m_err_ePHI_smt.clear(); - m_err_eTHETA_smt.clear(); - m_err_eQOP_smt.clear(); - m_err_eT_smt.clear(); - m_pull_eLOC0_smt.clear(); - m_pull_eLOC1_smt.clear(); - m_x_smt.clear(); - m_y_smt.clear(); - m_z_smt.clear(); - m_px_smt.clear(); - m_py_smt.clear(); - m_pz_smt.clear(); - m_eta_smt.clear(); - m_pT_smt.clear(); - - return; -} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/MultiTrackFinderTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/MultiTrackFinderTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..f10448452d2a9161dab5207963a514135475efce --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/MultiTrackFinderTool.cxx @@ -0,0 +1,120 @@ +#include "FaserActsKalmanFilter/MultiTrackFinderTool.h" + +#include "Acts/Definitions/TrackParametrization.hpp" +#include "Acts/EventData/Measurement.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Surfaces/Surface.hpp" +#include "FaserActsKalmanFilter/IndexSourceLink.h" +#include "Identifier/Identifier.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "TrkTrack/Track.h" +#include "TrkTrack/TrackStateOnSurface.h" +#include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +//#include "TrackerPrepRawData/FaserSCT_ClusterCollection.h" +#include <algorithm> +#include <vector> + + +MultiTrackFinderTool::MultiTrackFinderTool(const std::string& type, const std::string& name, const IInterface* parent) + : base_class(type, name, parent) {} + + +StatusCode MultiTrackFinderTool::initialize() { + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + ATH_CHECK(detStore()->retrieve(m_detManager, "SCT")); + ATH_CHECK(m_trackingGeometryTool.retrieve()); + ATH_CHECK(m_trackCollection.initialize()); + return StatusCode::SUCCESS; +} + + +StatusCode MultiTrackFinderTool::run() { + SG::ReadHandle<TrackCollection> trackCollection {m_trackCollection}; + ATH_CHECK(trackCollection.isValid()); + + using IdentifierMap = std::map<Identifier, Acts::GeometryIdentifier>; + std::shared_ptr<IdentifierMap> identifierMap = m_trackingGeometryTool->getIdentifierMap(); + + std::map<int, std::vector<Tracklet>> tracklets; + for (const Trk::Track* track : *trackCollection) { + std::vector<Identifier> ids; + std::vector<Acts::GeometryIdentifier> geoIds; + std::vector<double> positions; + std::vector<const Tracker::FaserSCT_Cluster*> clusters {}; + auto fitParameters = track->trackParameters()->front(); + const Amg::Vector3D fitPosition = fitParameters->position(); + const Amg::Vector3D fitMomentum = fitParameters->momentum(); + ATH_MSG_DEBUG(fitPosition.x() << ", " << fitPosition.y() << fitPosition.z()); + for (const Trk::TrackStateOnSurface* state : *(track->trackStateOnSurfaces())) { + auto clusterOnTrack = dynamic_cast<const Tracker::FaserSCT_ClusterOnTrack*> ( state->measurementOnTrack()); + if (clusterOnTrack) { + const Tracker::FaserSCT_Cluster* cluster = clusterOnTrack->prepRawData(); + clusters.push_back(cluster); + Identifier id = cluster->detectorElement()->identify(); + ids.push_back(id); + Acts::GeometryIdentifier geoId = identifierMap->at(id); + geoIds.push_back(geoId); + const auto& par = cluster->localPosition(); + positions.push_back(par.x()); + } + } + auto tracklet = Tracklet(ids, geoIds, positions, fitPosition, clusters); + int station = m_idHelper->station(ids.front()); + tracklets[station].push_back(tracklet); + } + + // create all combinations of tracklets + std::vector<ProtoTrack> protoTracks {}; + for (const Tracklet& t1 : tracklets[1]) { + for (const Tracklet& t2 : tracklets[2]) { + for (const Tracklet& t3 : tracklets[3]) { + protoTracks.push_back(ProtoTrack(t1, t2, t3)); + } + } + } + + // sort proto tracks by their chi2 value and select best two tracks + std::sort(protoTracks.begin(), protoTracks.end(), sort_chi2()); + + std::vector<std::vector<IndexSourceLink>> sourceLinkVector; + std::vector<std::vector<Measurement>> measurementVector; + std::vector<std::map<Index, Identifier>> idLinkVector; + std::vector<Acts::CurvilinearTrackParameters> paramVector; + std::vector<std::vector<const Tracker::FaserSCT_Cluster*>> clusterVector; + int n_protoTracks = std::min((int)protoTracks.size(), 2); + for (int i = 0; i < n_protoTracks; ++i) { + // FIXME check if protoTrack exists + ProtoTrack track = protoTracks[i]; + auto [measurements, sourceLinks, idLinks, clusters] = track.run(); + auto params = track.initialTrackParameters(m_covLoc0, m_covLoc1, m_covPhi, m_covTheta, m_covQOverP, m_covTime); + sourceLinkVector.push_back(sourceLinks); + measurementVector.push_back(measurements); + idLinkVector.push_back(idLinks); + paramVector.push_back(params); + clusterVector.push_back(clusters); + } + + m_sourceLinks = std::make_shared<std::vector<std::vector<IndexSourceLink>>>(sourceLinkVector); + m_measurements = std::make_shared<std::vector<std::vector<Measurement>>>(measurementVector); + m_idLinks = std::make_shared<std::vector<std::map<Index, Identifier>>>(idLinkVector); + m_initialTrackParameters = std::make_shared<std::vector<Acts::CurvilinearTrackParameters>>(paramVector); + m_clusters = std::make_shared<std::vector<std::vector<const Tracker::FaserSCT_Cluster*>>>(clusterVector); + + // create initial surface + m_initialSurface = Acts::Surface::makeShared<Acts::PlaneSurface>( + Acts::Vector3 {0, 0, 0}, Acts::Vector3{0, 0, 1}); + + return StatusCode::SUCCESS; +} + + +StatusCode MultiTrackFinderTool::finalize() { + return StatusCode::SUCCESS; +} + + + diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/MyAmbiguitySolver.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/MyAmbiguitySolver.cxx new file mode 100644 index 0000000000000000000000000000000000000000..998269a83cf6228092dd3b31987696f929820e4e --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/MyAmbiguitySolver.cxx @@ -0,0 +1,3 @@ +#include "FaserActsKalmanFilter/MyAmbiguitySolver.h" + + diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/PerformanceWriterTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/PerformanceWriterTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..3f99bea98466b59a4ccaa12c898c1f9660ca27bc --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/PerformanceWriterTool.cxx @@ -0,0 +1,180 @@ +#include "FaserActsKalmanFilter/PerformanceWriterTool.h" +#include "FaserActsKalmanFilter/TrackClassification.h" +#include "Acts/EventData/MultiTrajectory.hpp" +#include "Acts/EventData/MultiTrajectoryHelpers.hpp" +#include "TFile.h" + + +PerformanceWriterTool::PerformanceWriterTool( + const std::string& type, const std::string& name, const IInterface* parent) + : AthAlgTool(type, name, parent) {} + + +StatusCode PerformanceWriterTool::initialize() { + ATH_CHECK(m_extrapolationTool.retrieve()); + ATH_CHECK(m_mcEventCollectionKey.initialize()); + ATH_CHECK(m_simDataCollectionKey.initialize()); + + std::string filePath = m_filePath; + m_outputFile = TFile::Open(filePath.c_str(), "RECREATE"); + if (m_outputFile == nullptr) { + ATH_MSG_WARNING("Unable to open output file at " << m_filePath); + return StatusCode::RECOVERABLE; + } + + // initialize the residual and efficiency plots tool + m_resPlotTool.book(m_resPlotCache); + m_effPlotTool.book(m_effPlotCache); + m_summaryPlotTool.book(m_summaryPlotCache); + return StatusCode::SUCCESS; +} + + +StatusCode PerformanceWriterTool::finalize() { + // fill residual and pull details into additional hists + m_resPlotTool.refinement(m_resPlotCache); + if (m_outputFile) { + m_outputFile->cd(); + m_resPlotTool.write(m_resPlotCache); + m_effPlotTool.write(m_effPlotCache); + m_summaryPlotTool.write(m_summaryPlotCache); + ATH_MSG_VERBOSE("Wrote performance plots to '" << m_outputFile->GetPath() << "'"); + } + + m_resPlotTool.clear(m_resPlotCache); + m_effPlotTool.clear(m_effPlotCache); + m_summaryPlotTool.clear(m_summaryPlotCache); + if (m_outputFile) { + m_outputFile->Close(); + } + + return StatusCode::SUCCESS; +} + + +StatusCode PerformanceWriterTool::write(const Acts::GeometryContext& geoContext, const TrajectoriesContainer& trajectories) { + const EventContext& ctx = Gaudi::Hive::currentContext(); + + SG::ReadHandle<McEventCollection> mcEvents {m_mcEventCollectionKey, ctx}; + ATH_CHECK(mcEvents.isValid()); + if (mcEvents->size() != 1) { + ATH_MSG_ERROR("There should be exactly one event in the McEventCollection."); + return StatusCode::FAILURE; + } + + std::map<int, const HepMC::GenParticle*> particles {}; + for (const HepMC::GenParticle* particle : mcEvents->front()->particle_range()) { + particles[particle->barcode()] = particle; + } + + SG::ReadHandle<TrackerSimDataCollection> simData {m_simDataCollectionKey, ctx}; + ATH_CHECK(simData.isValid()); + + // Truth particles with corresponding reconstructed tracks + std::vector<int> reconParticleIds; + reconParticleIds.reserve(particles.size()); + // For each particle within a track, how many hits did it contribute + std::vector<ParticleHitCount> particleHitCounts; + + + // Loop over all trajectories + for (size_t itraj = 0; itraj < trajectories.size(); ++itraj) { + const auto& traj = trajectories[itraj]; + + if (traj.empty()) { + ATH_MSG_WARNING("Empty trajectories object " << itraj); + continue; + } + + // The trajectory entry indices and the multiTrajectory + const auto& trackTips = traj.tips(); + const auto& mj = traj.multiTrajectory(); + + // Check the size of the trajectory entry indices. For track fitting, there + // should be at most one trajectory + if (trackTips.size() > 1) { + ATH_MSG_ERROR("Track fitting should not result in multiple trajectories."); + return StatusCode::FAILURE; + } + // Get the entry index for the single trajectory + auto trackTip = trackTips.front(); + + // Select reco track with fitted parameters + if (not traj.hasTrackParameters(trackTip)) { + ATH_MSG_WARNING("No fitted track parameters."); + continue; + } + const auto& fittedParameters = traj.trackParameters(trackTip); + + // Get the majority truth particle for this trajectory + identifyContributingParticles(*simData, traj, trackTip, particleHitCounts); + if (particleHitCounts.empty()) { + ATH_MSG_WARNING("No truth particle associated with this trajectory."); + continue; + } + // Find the truth particle for the majority barcode + const auto ip = particles.find(particleHitCounts.front().particleId); + if (ip == particles.end()) { + ATH_MSG_WARNING("Majority particle not found in the particles collection."); + continue; + } + + // Record this majority particle ID of this trajectory + reconParticleIds.push_back(ip->first); + const HepMC::GenParticle* truthParticle = ip->second; + std::unique_ptr<const Acts::BoundTrackParameters> truthParameters + = extrapolateToReferenceSurface(ctx, truthParticle); + // Fill the residual plots + if (truthParameters) { + m_resPlotTool.fill(m_resPlotCache, geoContext, std::move(truthParameters), fittedParameters); + } else { + ATH_MSG_WARNING("Can not extrapolate truth parameters to reference surface."); + } + // Collect the trajectory summary info + auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); + // Fill the trajectory summary info + m_summaryPlotTool.fill(m_summaryPlotCache, fittedParameters, trajState.nStates, trajState.nMeasurements, + trajState.nOutliers, trajState.nHoles, trajState.nSharedHits); + } + + // Fill the efficiency, defined as the ratio between number of tracks with fitted parameter and total truth tracks + // (assumes one truth partilce has one truth track) + for (const auto& particle : particles) { + bool isReconstructed = false; + // Find if the particle has been reconstructed + auto it = std::find(reconParticleIds.begin(), reconParticleIds.end(), particle.first); + if (it != reconParticleIds.end()) { + isReconstructed = true; + } + m_effPlotTool.fill(m_effPlotCache, particle.second, isReconstructed); + } + + return StatusCode::SUCCESS; +} + +std::unique_ptr<const Acts::BoundTrackParameters> PerformanceWriterTool::extrapolateToReferenceSurface( + const EventContext& ctx, const HepMC::GenParticle* particle) const { + const HepMC::FourVector &vertex = particle->production_vertex()->position(); + const HepMC::FourVector &momentum = particle->momentum(); + + // The coordinate system of the Acts::PlaneSurface is defined as + // T = Z = normal, U = X x T = -Y, V = T x U = x + auto startSurface = Acts::Surface::makeShared<Acts::PlaneSurface>( + Acts::Vector3(0, 0, vertex.z()), Acts::Vector3(0, 0, 1)); + auto targetSurface = Acts::Surface::makeShared<Acts::PlaneSurface>( + Acts::Vector3(0, 0, 0), Acts::Vector3(0, 0, -1)); + Acts::BoundVector params = Acts::BoundVector::Zero(); + params[Acts::eBoundLoc0] = -vertex.y(); + params[Acts::eBoundLoc1] = vertex.x(); + params[Acts::eBoundPhi] = momentum.phi(); + params[Acts::eBoundTheta] = momentum.theta(); + // FIXME get charge of HepMC::GenParticle, the following does not work, e.g. for pions + double charge = particle->pdg_id() > 0 ? -1 : 1; + double MeV2GeV = 1e-3; + params[Acts::eBoundQOverP] = charge / (momentum.rho() * MeV2GeV); + params[Acts::eBoundTime] = vertex.t(); + Acts::BoundTrackParameters startParameters(std::move(startSurface), params, charge); + std::unique_ptr<const Acts::BoundTrackParameters> targetParameters = + m_extrapolationTool->propagate(ctx, startParameters, *targetSurface); + return targetParameters; +} \ No newline at end of file diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/PlotHelpers.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/PlotHelpers.cxx new file mode 100644 index 0000000000000000000000000000000000000000..0d50d843ea075ab3d3799dccdc6e2ba46cd74127 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/PlotHelpers.cxx @@ -0,0 +1,92 @@ +#include "FaserActsKalmanFilter/PlotHelpers.h" +#include <cassert> + +namespace PlotHelpers { + +TH1F* bookHisto(const char* histName, const char* histTitle, + const Binning& varBinning) { + TH1F* hist = new TH1F(histName, histTitle, varBinning.nBins, varBinning.min, + varBinning.max); + hist->GetXaxis()->SetTitle(varBinning.title.c_str()); + hist->GetYaxis()->SetTitle("Entries"); + hist->Sumw2(); + return hist; +} + +TH2F* bookHisto(const char* histName, const char* histTitle, + const Binning& varXBinning, const Binning& varYBinning) { + TH2F* hist = new TH2F(histName, histTitle, varXBinning.nBins, varXBinning.min, + varXBinning.max, varYBinning.nBins, varYBinning.min, + varYBinning.max); + hist->GetXaxis()->SetTitle(varXBinning.title.c_str()); + hist->GetYaxis()->SetTitle(varYBinning.title.c_str()); + hist->Sumw2(); + return hist; +} + +void fillHisto(TH1F* hist, float value, float weight) { + assert(hist != nullptr); + hist->Fill(value, weight); +} + +void fillHisto(TH2F* hist, float xValue, float yValue, float weight) { + assert(hist != nullptr); + hist->Fill(xValue, yValue, weight); +} + +void anaHisto(TH1D* inputHist, int j, TH1F* meanHist, TH1F* widthHist) { + // evaluate mean and width via the Gauss fit + assert(inputHist != nullptr); + if (inputHist->GetEntries() > 0) { + TFitResultPtr r = inputHist->Fit("gaus", "QS0"); + if (r.Get() and ((r->Status() % 1000) == 0)) { + // fill the mean and width into 'j'th bin of the meanHist and widthHist, + // respectively + meanHist->SetBinContent(j, r->Parameter(1)); + meanHist->SetBinError(j, r->ParError(1)); + widthHist->SetBinContent(j, r->Parameter(2)); + widthHist->SetBinError(j, r->ParError(2)); + } + } +} + +TEfficiency* bookEff(const char* effName, const char* effTitle, const Binning& varBinning) { + TEfficiency* efficiency = new TEfficiency(effName, effTitle, varBinning.nBins, + varBinning.min, varBinning.max); + return efficiency; +} + +TEfficiency* bookEff(const char* effName, const char* effTitle, + const Binning& varXBinning, const Binning& varYBinning) { + TEfficiency* efficiency = new TEfficiency( + effName, effTitle, varXBinning.nBins, varXBinning.min, varXBinning.max, + varYBinning.nBins, varYBinning.min, varYBinning.max); + return efficiency; +} + +void fillEff(TEfficiency* efficiency, float value, bool status) { + assert(efficiency != nullptr); + efficiency->Fill(status, value); +} + +void fillEff(TEfficiency* efficiency, float xValue, float yValue, bool status) { + assert(efficiency != nullptr); + efficiency->Fill(status, xValue, yValue); +} + +TProfile* bookProf(const char* profName, const char* profTitle, + const Binning& varXBinning, const Binning& varYBinning) { + TProfile* prof = + new TProfile(profName, profTitle, varXBinning.nBins, varXBinning.min, + varXBinning.max, varYBinning.min, varYBinning.max); + prof->GetXaxis()->SetTitle(varXBinning.title.c_str()); + prof->GetYaxis()->SetTitle(varYBinning.title.c_str()); + return prof; +} + +void fillProf(TProfile* profile, float xValue, float yValue, float weight) { + assert(profile != nullptr); + profile->Fill(xValue, yValue, weight); +} + +} // namespace PlotHelpers diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/ProtoTrackWriterTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/ProtoTrackWriterTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..5ec0dfc1a1d430208b10c14a7c368ac89ac08ff3 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/ProtoTrackWriterTool.cxx @@ -0,0 +1,108 @@ +#include "FaserActsKalmanFilter/ProtoTrackWriterTool.h" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Identifier/Identifier.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include <TFile.h> +#include <TTree.h> + + +ProtoTrackWriterTool::ProtoTrackWriterTool( + const std::string& type, const std::string& name, const IInterface* parent) + : AthAlgTool(type, name, parent) {} + + +StatusCode ProtoTrackWriterTool::initialize() { + + ATH_CHECK(m_trackFinderTool.retrieve()); + ATH_CHECK(m_trackingGeometryTool.retrieve()); + + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + + std::string filePath = m_filePath; + m_file = TFile::Open(filePath.c_str(), "RECREATE"); + if (m_file == nullptr) { + ATH_MSG_ERROR("Unable to open output file at " << m_filePath); + return StatusCode::FAILURE; + } + m_file->cd(); + + m_params = new TTree("parameters", "parameters"); + m_params->Branch("run_number", &m_run_number, "run_number/I"); + m_params->Branch("event_number", &m_event_number, "event_number/I"); + m_params->Branch("x", &m_x, "x/D"); + m_params->Branch("y", &m_y, "y/D"); + m_params->Branch("z", &m_z, "z/D"); + m_params->Branch("px", &m_px, "px/D"); + m_params->Branch("py", &m_py, "py/D"); + m_params->Branch("pz", &m_pz, "pz/D"); + + m_meas = new TTree("measurements", "measurements"); + m_meas->Branch("run_number", &m_run_number, "run_number/I"); + m_meas->Branch("event_number", &m_event_number, "event_number/I"); + m_meas->Branch("station", &m_station, "station/I"); + m_meas->Branch("layer", &m_layer, "layer/I"); + m_meas->Branch("phi", &m_phi, "phi/I"); + m_meas->Branch("eta", &m_eta, "eta/I"); + m_meas->Branch("side", &m_side, "side/I"); + m_meas->Branch("meas_eLOC0", &m_meas_eLOC0, "meas_eLOC0/D"); + m_meas->Branch("meas_eLOC1", &m_meas_eLOC1, "meas_eLOC1/D"); + + return StatusCode::SUCCESS; +} + + +StatusCode ProtoTrackWriterTool::finalize() { + m_file->cd(); + m_params->Write(); + m_meas->Write(); + return StatusCode::SUCCESS; +} + + +StatusCode ProtoTrackWriterTool::write( + std::shared_ptr<const Acts::CurvilinearTrackParameters> protoTrackParameters, + std::shared_ptr<std::vector<Measurement>> measurements, + const Acts::GeometryContext& geoctx) const { + + EventContext ctx = Gaudi::Hive::currentContext(); + m_run_number = ctx.eventID().run_number(); + m_event_number = ctx.eventID().event_number(); + + using IdentifierMap = std::map<Identifier, Acts::GeometryIdentifier>; + std::shared_ptr<IdentifierMap> identifierMap = m_trackingGeometryTool->getIdentifierMap(); + // flip key-value pairs of identifier map + std::map<Acts::GeometryIdentifier, Identifier> geoIdentifierMap; + for (const std::pair<const Identifier, Acts::GeometryIdentifier>& identifierPair : *identifierMap) { + geoIdentifierMap[identifierPair.second] = identifierPair.first; + } + + Acts::Vector3 position = protoTrackParameters->position(geoctx); + Acts::Vector3 direction = protoTrackParameters->momentum(); + m_x = position.x(); + m_y = position.y(); + m_z = position.z(); + m_px = direction.x(); + m_py = direction.y(); + m_pz = direction.z(); + m_params->Fill(); + + for (const Measurement& variantMeasurement : *measurements) { + // auto meas = std::get<Acts::Measurement<IndexSourceLink, Acts::BoundIndices, 2>>(variantMeasurement); + std::visit([&](const auto& meas) { + Acts::GeometryIdentifier geoId = meas.sourceLink().geometryId(); + Identifier id = geoIdentifierMap.at(geoId); + m_station = m_idHelper->station(id); + m_layer = m_idHelper->layer(id); + m_phi = m_idHelper->phi_module(id); + m_eta = m_idHelper->eta_module(id); + m_side = m_idHelper->side(id); + auto params = meas.parameters(); + m_meas_eLOC0 = params[Acts::eBoundLoc0]; + // write out as many variables as there are + // m_meas_eLOC1 = params[Acts::eBoundLoc1]; + m_meas->Fill(); + }, variantMeasurement); + }; + + return StatusCode::SUCCESS; +} \ No newline at end of file diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/ResPlotTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/ResPlotTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..11c1483a7762679e42ce41542d1a5b165aaf4f0c --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/ResPlotTool.cxx @@ -0,0 +1,201 @@ +#include "FaserActsKalmanFilter/ResPlotTool.h" +#include "Acts/Utilities/Helpers.hpp" +#include "HepMC/GenVertex.h" + +void ResPlotTool::book(ResPlotTool::ResPlotCache& resPlotCache) const { + PlotHelpers::Binning bEta = m_varBinning.at("Eta"); + PlotHelpers::Binning bPt = m_varBinning.at("Pt"); + PlotHelpers::Binning bPull = m_varBinning.at("Pull"); + std::cout << "DEBUG: Initialize the histograms for residual and pull plots" << std::endl; + for (unsigned int parID = 0; parID < Acts::eBoundSize; parID++) { + std::string parName = m_paramNames.at(parID); + std::string parResidual = "Residual_" + parName; + // Binning for residual is parameter dependent + PlotHelpers::Binning bResidual = m_varBinning.at(parResidual); + + + // residual distributions + resPlotCache.res[parName] = PlotHelpers::bookHisto( + Form("res_%s", parName.c_str()), + Form("Residual of %s", parName.c_str()), bResidual); + // residual vs eta scatter plots + resPlotCache.res_vs_eta[parName] = PlotHelpers::bookHisto( + Form("res_%s_vs_eta", parName.c_str()), + Form("Residual of %s vs eta", parName.c_str()), bEta, bResidual); + // residual mean in each eta bin + resPlotCache.resMean_vs_eta[parName] = PlotHelpers::bookHisto( + Form("resmean_%s_vs_eta", parName.c_str()), + Form("Residual mean of %s", parName.c_str()), bEta); + // residual width in each eta bin + resPlotCache.resWidth_vs_eta[parName] = PlotHelpers::bookHisto( + Form("reswidth_%s_vs_eta", parName.c_str()), + Form("Residual width of %s", parName.c_str()), bEta); + // residual vs pT scatter plots + resPlotCache.res_vs_pT[parName] = PlotHelpers::bookHisto( + Form("res_%s_vs_pT", parName.c_str()), + Form("Residual of %s vs pT", parName.c_str()), bPt, bResidual); + // residual mean in each pT bin + resPlotCache.resMean_vs_pT[parName] = PlotHelpers::bookHisto( + Form("resmean_%s_vs_pT", parName.c_str()), + Form("Residual mean of %s", parName.c_str()), bPt); + // residual width in each pT bin + resPlotCache.resWidth_vs_pT[parName] = PlotHelpers::bookHisto( + Form("reswidth_%s_vs_pT", parName.c_str()), + Form("Residual width of %s", parName.c_str()), bPt); + + // pull distritutions + resPlotCache.pull[parName] = PlotHelpers::bookHisto( + Form("pull_%s", parName.c_str()), + Form("Pull of %s", parName.c_str()), bPull); + // pull vs eta scatter plots + resPlotCache.pull_vs_eta[parName] = PlotHelpers::bookHisto( + Form("pull_%s_vs_eta", parName.c_str()), + Form("Pull of %s vs eta", parName.c_str()), bEta, bPull); + // pull mean in each eta bin + resPlotCache.pullMean_vs_eta[parName] = PlotHelpers::bookHisto( + Form("pullmean_%s_vs_eta", parName.c_str()), + Form("Pull mean of %s", parName.c_str()), bEta); + // pull width in each eta bin + resPlotCache.pullWidth_vs_eta[parName] = PlotHelpers::bookHisto( + Form("pullwidth_%s_vs_eta", parName.c_str()), + Form("Pull width of %s", parName.c_str()), bEta); + // pull vs pT scatter plots + resPlotCache.pull_vs_pT[parName] = PlotHelpers::bookHisto( + Form("pull_%s_vs_pT", parName.c_str()), + Form("Pull of %s vs pT", parName.c_str()), bPt, bPull); + // pull mean in each pT bin + resPlotCache.pullMean_vs_pT[parName] = PlotHelpers::bookHisto( + Form("pullmean_%s_vs_pT", parName.c_str()), + Form("Pull mean of %s", parName.c_str()), bPt); + // pull width in each pT bin + resPlotCache.pullWidth_vs_pT[parName] = PlotHelpers::bookHisto( + Form("pullwidth_%s_vs_pT", parName.c_str()), + Form("Pull width of %s", parName.c_str()), bPt); + } +} + +void ResPlotTool::write(const ResPlotCache &resPlotCache) const { + for (unsigned int parID = 0; parID < Acts::eBoundSize; parID++) { + std::string parName = m_paramNames.at(parID); + if (resPlotCache.res.count(parName)) { + resPlotCache.res.at(parName)->Write(); + resPlotCache.res_vs_eta.at(parName)->Write(); + resPlotCache.resMean_vs_eta.at(parName)->Write(); + resPlotCache.resWidth_vs_eta.at(parName)->Write(); + resPlotCache.res_vs_pT.at(parName)->Write(); + resPlotCache.resMean_vs_pT.at(parName)->Write(); + resPlotCache.resWidth_vs_pT.at(parName)->Write(); + resPlotCache.pull.at(parName)->Write(); + resPlotCache.pull_vs_eta.at(parName)->Write(); + resPlotCache.pullMean_vs_eta.at(parName)->Write(); + resPlotCache.pullWidth_vs_eta.at(parName)->Write(); + resPlotCache.pull_vs_pT.at(parName)->Write(); + resPlotCache.pullMean_vs_pT.at(parName)->Write(); + resPlotCache.pullWidth_vs_pT.at(parName)->Write(); + } + } +} + +void ResPlotTool::clear(ResPlotCache &resPlotCache) const { + for (unsigned int parID = 0; parID < Acts::eBoundSize; parID++) { + std::string parName = m_paramNames.at(parID); + if (resPlotCache.res.count(parName)) { + delete resPlotCache.res.at(parName); + delete resPlotCache.res_vs_eta.at(parName); + delete resPlotCache.resMean_vs_eta.at(parName); + delete resPlotCache.resWidth_vs_eta.at(parName); + delete resPlotCache.res_vs_pT.at(parName); + delete resPlotCache.resMean_vs_pT.at(parName); + delete resPlotCache.resWidth_vs_pT.at(parName); + delete resPlotCache.pull.at(parName); + delete resPlotCache.pull_vs_eta.at(parName); + delete resPlotCache.pullMean_vs_eta.at(parName); + delete resPlotCache.pullWidth_vs_eta.at(parName); + delete resPlotCache.pull_vs_pT.at(parName); + delete resPlotCache.pullMean_vs_pT.at(parName); + delete resPlotCache.pullWidth_vs_pT.at(parName); + } + } +} + +void ResPlotTool::fill( + ResPlotCache& resPlotCache, const Acts::GeometryContext& gctx, + std::unique_ptr<const Acts::BoundTrackParameters> truthParameters, + const Acts::BoundTrackParameters& fittedParameters) const { + using ParametersVector = Acts::BoundTrackParameters::ParametersVector; + using Acts::VectorHelpers::eta; + using Acts::VectorHelpers::perp; + // using Acts::VectorHelpers::phi; + // using Acts::VectorHelpers::theta; + + // get the fitted parameter (at perigee surface) and its error + auto trackParameter = fittedParameters.parameters(); + + // get the truth position and momentum + ParametersVector truthParameter = truthParameters->parameters(); + + // get the truth eta and pT + const auto truthEta = eta(truthParameters->momentum().normalized()); + const auto truthPt = truthParameters->absoluteMomentum() * perp(truthParameters->momentum().normalized()); + + // fill the histograms for residual and pull + for (unsigned int parID = 0; parID < Acts::eBoundSize; parID++) { + std::string parName = m_paramNames.at(parID); + float residual = trackParameter[parID] - truthParameter[parID]; + PlotHelpers::fillHisto(resPlotCache.res.at(parName), residual); + PlotHelpers::fillHisto(resPlotCache.res_vs_eta.at(parName), truthEta, residual); + PlotHelpers::fillHisto(resPlotCache.res_vs_pT.at(parName), truthPt, residual); + + if (fittedParameters.covariance().has_value()) { + auto covariance = *fittedParameters.covariance(); + if (covariance(parID, parID) > 0) { + float pull = residual / sqrt(covariance(parID, parID)); + PlotHelpers::fillHisto(resPlotCache.pull[parName], pull); + PlotHelpers::fillHisto(resPlotCache.pull_vs_eta.at(parName), truthEta, pull); + PlotHelpers::fillHisto(resPlotCache.pull_vs_pT.at(parName), truthPt, pull); + } else { + std::cout << "WARNING: Fitted track parameter :" << parName << " has negative covariance = " << covariance(parID, parID) << std::endl; + } + } else { + std::cout << "WARNING: Fitted track parameter :" << parName << " has no covariance" << std::endl; + } + } +} + + +// get the mean and width of residual/pull in each eta/pT bin and fill them into histograms +void ResPlotTool::refinement(ResPlotTool::ResPlotCache& resPlotCache) const { + PlotHelpers::Binning bEta = m_varBinning.at("Eta"); + PlotHelpers::Binning bPt = m_varBinning.at("Pt"); + for (unsigned int parID = 0; parID < Acts::eBoundSize; parID++) { + std::string parName = m_paramNames.at(parID); + // refine the plots vs eta + for (int j = 1; j <= bEta.nBins; j++) { + TH1D* temp_res = resPlotCache.res_vs_eta.at(parName)->ProjectionY( + Form("%s_projy_bin%d", "Residual_vs_eta_Histo", j), j, j); + PlotHelpers::anaHisto(temp_res, j, + resPlotCache.resMean_vs_eta.at(parName), + resPlotCache.resWidth_vs_eta.at(parName)); + + TH1D* temp_pull = resPlotCache.pull_vs_eta.at(parName)->ProjectionY( + Form("%s_projy_bin%d", "Pull_vs_eta_Histo", j), j, j); + PlotHelpers::anaHisto(temp_pull, j, + resPlotCache.pullMean_vs_eta.at(parName), + resPlotCache.pullWidth_vs_eta.at(parName)); + } + + // refine the plots vs pT + for (int j = 1; j <= bPt.nBins; j++) { + TH1D* temp_res = resPlotCache.res_vs_pT.at(parName)->ProjectionY( + Form("%s_projy_bin%d", "Residual_vs_pT_Histo", j), j, j); + PlotHelpers::anaHisto(temp_res, j, resPlotCache.resMean_vs_pT.at(parName), + resPlotCache.resWidth_vs_pT.at(parName)); + + TH1D* temp_pull = resPlotCache.pull_vs_pT.at(parName)->ProjectionY( + Form("%s_projy_bin%d", "Pull_vs_pT_Histo", j), j, j); + PlotHelpers::anaHisto(temp_pull, j, + resPlotCache.pullMean_vs_pT.at(parName), + resPlotCache.pullWidth_vs_pT.at(parName)); + } + } +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectoryStatesWriterTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectoryStatesWriterTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e81f46ff6d2d87c96b9d86fba97982bbf01dc4cb --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectoryStatesWriterTool.cxx @@ -0,0 +1,656 @@ +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "FaserActsKalmanFilter/RootTrajectoryStatesWriterTool.h" +#include "Acts/EventData/MultiTrajectory.hpp" +#include "Acts/EventData/MultiTrajectoryHelpers.hpp" +#include "Acts/EventData/detail/TransformationBoundToFree.hpp" +#include "Acts/Utilities/Helpers.hpp" +#include "FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "GeoPrimitives/CLHEPtoEigenConverter.h" +#include "TrackerReadoutGeometry/SiDetectorElement.h" +#include "FaserActsKalmanFilter/TrackClassification.h" +#include <TFile.h> +#include <TTree.h> + +using Acts::VectorHelpers::eta; +using Acts::VectorHelpers::perp; +using Acts::VectorHelpers::phi; +using Acts::VectorHelpers::theta; + +RootTrajectoryStatesWriterTool::RootTrajectoryStatesWriterTool( + const std::string& type, const std::string& name, const IInterface* parent) + : AthAlgTool(type, name, parent) {} + +StatusCode RootTrajectoryStatesWriterTool::initialize() { + ATH_CHECK(m_mcEventCollectionKey.initialize()); + ATH_CHECK(m_simDataCollectionKey.initialize()); + ATH_CHECK(m_faserSiHitKey.initialize()); + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + ATH_CHECK(detStore()->retrieve(m_detMgr, "SCT")); + + std::string filePath = m_filePath; + std::string treeName = m_treeName; + m_outputFile = TFile::Open(filePath.c_str(), "RECREATE"); + if (m_outputFile == nullptr) { + ATH_MSG_ERROR("Unable to open output file at " << m_filePath); + return StatusCode::FAILURE; + } + m_outputFile->cd(); + m_outputTree = new TTree(treeName.c_str(), treeName.c_str()); + if (m_outputTree == nullptr) { + ATH_MSG_ERROR("Unable to create TTree"); + return StatusCode::FAILURE; + } + + m_outputTree = new TTree("tree", "tree"); + + m_outputTree->Branch("event_nr", &m_eventNr); + m_outputTree->Branch("multiTraj_nr", &m_multiTrajNr); + m_outputTree->Branch("subTraj_nr", &m_subTrajNr); + + m_outputTree->Branch("t_x", &m_t_x); + m_outputTree->Branch("t_y", &m_t_y); + m_outputTree->Branch("t_z", &m_t_z); + m_outputTree->Branch("t_dx", &m_t_dx); + m_outputTree->Branch("t_dy", &m_t_dy); + m_outputTree->Branch("t_dz", &m_t_dz); + m_outputTree->Branch("t_eLOC0", &m_t_eLOC0); + m_outputTree->Branch("t_eLOC1", &m_t_eLOC1); + m_outputTree->Branch("t_ePHI", &m_t_ePHI); + m_outputTree->Branch("t_eTHETA", &m_t_eTHETA); + m_outputTree->Branch("t_eQOP", &m_t_eQOP); + m_outputTree->Branch("t_eT", &m_t_eT); + + m_outputTree->Branch("nStates", &m_nStates); + m_outputTree->Branch("nMeasurements", &m_nMeasurements); + m_outputTree->Branch("volume_id", &m_volumeID); + m_outputTree->Branch("layer_id", &m_layerID); + m_outputTree->Branch("module_id", &m_moduleID); + m_outputTree->Branch("station", &m_station); + m_outputTree->Branch("layer", &m_layer); + m_outputTree->Branch("phi_module", &m_phi_module); + m_outputTree->Branch("eta_module", &m_eta_module); + m_outputTree->Branch("side", &m_side); + m_outputTree->Branch("pathLength", &m_pathLength); + m_outputTree->Branch("l_x_hit", &m_lx_hit); + m_outputTree->Branch("l_y_hit", &m_ly_hit); + m_outputTree->Branch("g_x_hit", &m_x_hit); + m_outputTree->Branch("g_y_hit", &m_y_hit); + m_outputTree->Branch("g_z_hit", &m_z_hit); + m_outputTree->Branch("res_x_hit", &m_res_x_hit); + m_outputTree->Branch("res_y_hit", &m_res_y_hit); + m_outputTree->Branch("err_x_hit", &m_err_x_hit); + m_outputTree->Branch("err_y_hit", &m_err_y_hit); + m_outputTree->Branch("pull_x_hit", &m_pull_x_hit); + m_outputTree->Branch("pull_y_hit", &m_pull_y_hit); + m_outputTree->Branch("dim_hit", &m_dim_hit); + + m_outputTree->Branch("nPredicted", &m_nParams[0]); + m_outputTree->Branch("predicted", &m_hasParams[0]); + m_outputTree->Branch("eLOC0_prt", &m_eLOC0[0]); + m_outputTree->Branch("eLOC1_prt", &m_eLOC1[0]); + m_outputTree->Branch("ePHI_prt", &m_ePHI[0]); + m_outputTree->Branch("eTHETA_prt", &m_eTHETA[0]); + m_outputTree->Branch("eQOP_prt", &m_eQOP[0]); + m_outputTree->Branch("eT_prt", &m_eT[0]); + m_outputTree->Branch("res_eLOC0_prt", &m_res_eLOC0[0]); + m_outputTree->Branch("res_eLOC1_prt", &m_res_eLOC1[0]); + m_outputTree->Branch("res_ePHI_prt", &m_res_ePHI[0]); + m_outputTree->Branch("res_eTHETA_prt", &m_res_eTHETA[0]); + m_outputTree->Branch("res_eQOP_prt", &m_res_eQOP[0]); + m_outputTree->Branch("res_eT_prt", &m_res_eT[0]); + m_outputTree->Branch("err_eLOC0_prt", &m_err_eLOC0[0]); + m_outputTree->Branch("err_eLOC1_prt", &m_err_eLOC1[0]); + m_outputTree->Branch("err_ePHI_prt", &m_err_ePHI[0]); + m_outputTree->Branch("err_eTHETA_prt", &m_err_eTHETA[0]); + m_outputTree->Branch("err_eQOP_prt", &m_err_eQOP[0]); + m_outputTree->Branch("err_eT_prt", &m_err_eT[0]); + m_outputTree->Branch("pull_eLOC0_prt", &m_pull_eLOC0[0]); + m_outputTree->Branch("pull_eLOC1_prt", &m_pull_eLOC1[0]); + m_outputTree->Branch("pull_ePHI_prt", &m_pull_ePHI[0]); + m_outputTree->Branch("pull_eTHETA_prt", &m_pull_eTHETA[0]); + m_outputTree->Branch("pull_eQOP_prt", &m_pull_eQOP[0]); + m_outputTree->Branch("pull_eT_prt", &m_pull_eT[0]); + m_outputTree->Branch("g_x_prt", &m_x[0]); + m_outputTree->Branch("g_y_prt", &m_y[0]); + m_outputTree->Branch("g_z_prt", &m_z[0]); + m_outputTree->Branch("px_prt", &m_px[0]); + m_outputTree->Branch("py_prt", &m_py[0]); + m_outputTree->Branch("pz_prt", &m_pz[0]); + m_outputTree->Branch("eta_prt", &m_eta[0]); + m_outputTree->Branch("pT_prt", &m_pT[0]); + + m_outputTree->Branch("nFiltered", &m_nParams[1]); + m_outputTree->Branch("filtered", &m_hasParams[1]); + m_outputTree->Branch("eLOC0_flt", &m_eLOC0[1]); + m_outputTree->Branch("eLOC1_flt", &m_eLOC1[1]); + m_outputTree->Branch("ePHI_flt", &m_ePHI[1]); + m_outputTree->Branch("eTHETA_flt", &m_eTHETA[1]); + m_outputTree->Branch("eQOP_flt", &m_eQOP[1]); + m_outputTree->Branch("eT_flt", &m_eT[1]); + m_outputTree->Branch("res_eLOC0_flt", &m_res_eLOC0[1]); + m_outputTree->Branch("res_eLOC1_flt", &m_res_eLOC1[1]); + m_outputTree->Branch("res_ePHI_flt", &m_res_ePHI[1]); + m_outputTree->Branch("res_eTHETA_flt", &m_res_eTHETA[1]); + m_outputTree->Branch("res_eQOP_flt", &m_res_eQOP[1]); + m_outputTree->Branch("res_eT_flt", &m_res_eT[1]); + m_outputTree->Branch("err_eLOC0_flt", &m_err_eLOC0[1]); + m_outputTree->Branch("err_eLOC1_flt", &m_err_eLOC1[1]); + m_outputTree->Branch("err_ePHI_flt", &m_err_ePHI[1]); + m_outputTree->Branch("err_eTHETA_flt", &m_err_eTHETA[1]); + m_outputTree->Branch("err_eQOP_flt", &m_err_eQOP[1]); + m_outputTree->Branch("err_eT_flt", &m_err_eT[1]); + m_outputTree->Branch("pull_eLOC0_flt", &m_pull_eLOC0[1]); + m_outputTree->Branch("pull_eLOC1_flt", &m_pull_eLOC1[1]); + m_outputTree->Branch("pull_ePHI_flt", &m_pull_ePHI[1]); + m_outputTree->Branch("pull_eTHETA_flt", &m_pull_eTHETA[1]); + m_outputTree->Branch("pull_eQOP_flt", &m_pull_eQOP[1]); + m_outputTree->Branch("pull_eT_flt", &m_pull_eT[1]); + m_outputTree->Branch("g_x_flt", &m_x[1]); + m_outputTree->Branch("g_y_flt", &m_y[1]); + m_outputTree->Branch("g_z_flt", &m_z[1]); + m_outputTree->Branch("px_flt", &m_px[1]); + m_outputTree->Branch("py_flt", &m_py[1]); + m_outputTree->Branch("pz_flt", &m_pz[1]); + m_outputTree->Branch("eta_flt", &m_eta[1]); + m_outputTree->Branch("pT_flt", &m_pT[1]); + + m_outputTree->Branch("nSmoothed", &m_nParams[2]); + m_outputTree->Branch("smoothed", &m_hasParams[2]); + m_outputTree->Branch("eLOC0_smt", &m_eLOC0[2]); + m_outputTree->Branch("eLOC1_smt", &m_eLOC1[2]); + m_outputTree->Branch("ePHI_smt", &m_ePHI[2]); + m_outputTree->Branch("eTHETA_smt", &m_eTHETA[2]); + m_outputTree->Branch("eQOP_smt", &m_eQOP[2]); + m_outputTree->Branch("eT_smt", &m_eT[2]); + m_outputTree->Branch("res_eLOC0_smt", &m_res_eLOC0[2]); + m_outputTree->Branch("res_eLOC1_smt", &m_res_eLOC1[2]); + m_outputTree->Branch("res_ePHI_smt", &m_res_ePHI[2]); + m_outputTree->Branch("res_eTHETA_smt", &m_res_eTHETA[2]); + m_outputTree->Branch("res_eQOP_smt", &m_res_eQOP[2]); + m_outputTree->Branch("res_eT_smt", &m_res_eT[2]); + m_outputTree->Branch("err_eLOC0_smt", &m_err_eLOC0[2]); + m_outputTree->Branch("err_eLOC1_smt", &m_err_eLOC1[2]); + m_outputTree->Branch("err_ePHI_smt", &m_err_ePHI[2]); + m_outputTree->Branch("err_eTHETA_smt", &m_err_eTHETA[2]); + m_outputTree->Branch("err_eQOP_smt", &m_err_eQOP[2]); + m_outputTree->Branch("err_eT_smt", &m_err_eT[2]); + m_outputTree->Branch("pull_eLOC0_smt", &m_pull_eLOC0[2]); + m_outputTree->Branch("pull_eLOC1_smt", &m_pull_eLOC1[2]); + m_outputTree->Branch("pull_ePHI_smt", &m_pull_ePHI[2]); + m_outputTree->Branch("pull_eTHETA_smt", &m_pull_eTHETA[2]); + m_outputTree->Branch("pull_eQOP_smt", &m_pull_eQOP[2]); + m_outputTree->Branch("pull_eT_smt", &m_pull_eT[2]); + m_outputTree->Branch("g_x_smt", &m_x[2]); + m_outputTree->Branch("g_y_smt", &m_y[2]); + m_outputTree->Branch("g_z_smt", &m_z[2]); + m_outputTree->Branch("px_smt", &m_px[2]); + m_outputTree->Branch("py_smt", &m_py[2]); + m_outputTree->Branch("pz_smt", &m_pz[2]); + m_outputTree->Branch("eta_smt", &m_eta[2]); + m_outputTree->Branch("pT_smt", &m_pT[2]); + + m_outputTree->Branch("chi2", &m_chi2); + + return StatusCode::SUCCESS; +} + + +StatusCode RootTrajectoryStatesWriterTool::finalize() { + m_outputFile->cd(); + m_outputTree->Write(); + m_outputFile->Close(); + return StatusCode::SUCCESS; +} + +StatusCode RootTrajectoryStatesWriterTool::write(const Acts::GeometryContext& gctx, const TrajectoriesContainer& trajectories) const { + + if (m_outputFile == nullptr) + return StatusCode::SUCCESS; + + const EventContext& ctx = Gaudi::Hive::currentContext(); + + SG::ReadHandle<McEventCollection> mcEvents {m_mcEventCollectionKey, ctx}; + ATH_CHECK(mcEvents.isValid()); + if (mcEvents->size() != 1) { + ATH_MSG_ERROR("There should be exactly one event in the McEventCollection."); + return StatusCode::FAILURE; + } + ATH_MSG_VERBOSE("Found " << mcEvents->front()->particles_size() << " particles."); + std::map<int, const HepMC::GenParticle*> particles {}; + for (const HepMC::GenParticle* particle : mcEvents->front()->particle_range()) { + particles[particle->barcode()] = particle; + } + + SG::ReadHandle<TrackerSimDataCollection> simData {m_simDataCollectionKey, ctx}; + ATH_CHECK(simData.isValid()); + + SG::ReadHandle<FaserSiHitCollection> siHitCollection {m_faserSiHitKey, ctx}; + ATH_CHECK(siHitCollection.isValid()); + std::map<std::pair<int, Identifier>, const FaserSiHit*> siHitMap; + for (const FaserSiHit& hit : *siHitCollection) { + int barcode = hit.trackNumber(); + Identifier id = m_idHelper->wafer_id(hit.getStation(), hit.getPlane(), hit.getRow(), hit.getModule(), hit.getSensor()); + siHitMap[std::make_pair(barcode, id)] = &hit; + } + + // using HitParticlesMap = IndexMultimap<ActsFatras::Barcode>; + // using HitSimHitsMap = IndexMultimap<Index>; + + // Read additional input collections + // const auto& particles = ctx.eventStore.get<SimParticleContainer>(m_cfg.inputParticles); + // const auto& simHits = ctx.eventStore.get<SimHitContainer>(m_cfg.inputSimHits); + // const auto& hitParticlesMap = ctx.eventStore.get<HitParticlesMap>(m_cfg.inputMeasurementParticlesMap); + // const auto& hitSimHitsMap = ctx.eventStore.get<HitSimHitsMap>(m_cfg.inputMeasurementSimHitsMap); + + // For each particle within a track, how many hits did it contribute + std::vector<ParticleHitCount> particleHitCounts; + + // Get the event number + m_eventNr = ctx.eventID().event_number(); + + // Loop over the trajectories + for (size_t itraj = 0; itraj < trajectories.size(); ++itraj) { + const auto& traj = trajectories[itraj]; + + if (traj.empty()) { + ATH_MSG_WARNING("Empty trajectories object " << itraj); + continue; + } + + // The trajectory index + m_multiTrajNr = itraj; + + // The trajectory entry indices and the multiTrajectory + const auto& mj = traj.multiTrajectory(); + const auto& trackTips = traj.tips(); + + // Loop over the entry indices for the subtrajectories + for (unsigned int isubtraj = 0; isubtraj < trackTips.size(); ++isubtraj) { + // The subtrajectory index + m_subTrajNr = isubtraj; + // The entry index for this subtrajectory + const auto& trackTip = trackTips[isubtraj]; + // Collect the trajectory summary info + auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); + m_nMeasurements = trajState.nMeasurements; + m_nStates = trajState.nStates; + + // Get the majority truth particle to this track + int barcode; + int truthQ = 1.; + float truthMomentum = 1; + identifyContributingParticles(*simData, traj, trackTip, particleHitCounts); + if (not particleHitCounts.empty()) { + // Get the barcode of the majority truth particle + barcode = particleHitCounts.front().particleId; + // Find the truth particle via the barcode + auto ip = particles.find(barcode); + if (ip != particles.end()) { + const auto& particle = ip->second; + ATH_MSG_DEBUG("Find the truth particle with barcode = " << barcode); + // Get the truth particle charge + // FIXME find better way to access charge of simulated particle, this does not work for + // pions which have a positive pdg code (211) and positive charge + truthQ = particle->pdg_id() > 0 ? -1 : 1; + truthMomentum = particle->momentum().rho() * m_MeV2GeV; + } else { + ATH_MSG_WARNING("Truth particle with barcode = " << barcode << " not found!"); + } + } + float truthQOP = truthQ / truthMomentum; + + // Get the trackStates on the trajectory + m_nParams = {0, 0, 0}; + using ConstTrackStateProxy = + Acts::detail_lt::TrackStateProxy<IndexSourceLink, 6, true>; + mj.visitBackwards(trackTip, [&](const ConstTrackStateProxy& state) { + // we only fill the track states with non-outlier measurement + auto typeFlags = state.typeFlags(); + if (not typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) { + return true; + } + + const auto& surface = state.referenceSurface(); + + // get the truth hits corresponding to this trackState + Identifier id = state.uncalibrated().hit()->identify(); + Identifier waferId = m_idHelper->wafer_id(id); + if (siHitMap.count(std::make_pair(barcode, waferId)) == 0) { + ATH_MSG_WARNING("no FaserSiHit for hit with id " << id << " from particle " << barcode); + return true; + } + const FaserSiHit* siHit = siHitMap.find(std::make_pair(barcode, waferId))->second; + HepGeom::Point3D localStartPos = siHit->localStartPosition(); + HepGeom::Point3D localEndPos = siHit->localEndPosition(); + HepGeom::Point3D<double> localPos = 0.5 * (localEndPos + localStartPos); + auto truthLocal = Acts::Vector2(localPos.y(), localPos.z()); + const TrackerDD::SiDetectorElement* element = m_detMgr->getDetectorElement(id); + const HepGeom::Point3D<double> globalStartPosition = + Amg::EigenTransformToCLHEP(element->transformHit()) * localStartPos; + const HepGeom::Point3D<double> globalEndPosition = + Amg::EigenTransformToCLHEP(element->transformHit()) * localEndPos; + auto globalPosition = 0.5 * (globalStartPosition + globalEndPosition); + auto globalDirection = globalEndPosition - globalStartPosition; + auto truthUnitDir = Acts::Vector3(globalDirection.x(), globalDirection.y(), globalDirection.z()).normalized(); + auto truthPos = Acts::Vector3(globalPosition.x() , globalPosition.y(), globalPosition.z()); + // FIXME get truthQOP for each state + + // fill the truth hit info + m_t_x.push_back(truthPos[Acts::ePos0]); + m_t_y.push_back(truthPos[Acts::ePos1]); + m_t_z.push_back(truthPos[Acts::ePos2]); + m_t_dx.push_back(truthUnitDir[Acts::eMom0]); + m_t_dy.push_back(truthUnitDir[Acts::eMom1]); + m_t_dz.push_back(truthUnitDir[Acts::eMom2]); + + // get the truth track parameter at this track State + float truthLOC0 = truthLocal[Acts::ePos0]; + float truthLOC1 = truthLocal[Acts::ePos1]; + float truthTIME = siHit->meanTime(); + float truthPHI = phi(truthUnitDir); + float truthTHETA = theta(truthUnitDir); + + // fill the truth track parameter at this track State + m_t_eLOC0.push_back(truthLOC0); + m_t_eLOC1.push_back(truthLOC1); + m_t_ePHI.push_back(truthPHI); + m_t_eTHETA.push_back(truthTHETA); + m_t_eQOP.push_back(truthQOP); + m_t_eT.push_back(truthTIME); + + // get the geometry ID + auto geoID = surface.geometryId(); + m_volumeID.push_back(geoID.volume()); + m_layerID.push_back(geoID.layer()); + m_moduleID.push_back(geoID.sensitive()); + + // get wafer information + m_station.push_back(m_idHelper->station(id)); + m_layer.push_back(m_idHelper->layer(id)); + m_phi_module.push_back(m_idHelper->phi_module(id)); + m_eta_module.push_back(m_idHelper->eta_module(id)); + m_side.push_back(m_idHelper->side(id)); + + // get the path length + m_pathLength.push_back(state.pathLength()); + + // expand the local measurements into the full bound space + Acts::BoundVector meas = state.projector().transpose() * state.calibrated(); + // extract local and global position + Acts::Vector2 local(meas[Acts::eBoundLoc0], meas[Acts::eBoundLoc1]); + Acts::Vector3 mom(1, 1, 1); + Acts::Vector3 global = surface.localToGlobal(gctx, local, mom); + + // fill the measurement info + m_lx_hit.push_back(local[Acts::ePos0]); + m_ly_hit.push_back(local[Acts::ePos1]); + m_x_hit.push_back(global[Acts::ePos0]); + m_y_hit.push_back(global[Acts::ePos1]); + m_z_hit.push_back(global[Acts::ePos2]); + + // status of the fitted track parameters + std::array<bool, 3> hasParams = {false, false, false}; + // optional fitted track parameters + std::optional<std::pair<Acts::BoundVector, Acts::BoundMatrix>> + trackParamsOpt = std::nullopt; + // lambda to get the fitted track parameters + auto getTrackParams = [&](unsigned int ipar) { + if (ipar == 0 && state.hasPredicted()) { + hasParams[0] = true; + m_nParams[0]++; + trackParamsOpt = + std::make_pair(state.predicted(), state.predictedCovariance()); + } else if (ipar == 1 && state.hasFiltered()) { + hasParams[1] = true; + m_nParams[1]++; + trackParamsOpt = + std::make_pair(state.filtered(), state.filteredCovariance()); + } else if (ipar == 2 && state.hasSmoothed()) { + hasParams[2] = true; + m_nParams[2]++; + trackParamsOpt = + std::make_pair(state.smoothed(), state.smoothedCovariance()); + } + }; + + // fill the fitted track parameters + for (unsigned int ipar = 0; ipar < 3; ++ipar) { + // get the fitted track parameters + getTrackParams(ipar); + if (trackParamsOpt) { + const auto& [parameters, covariance] = *trackParamsOpt; + if (ipar == 0) { + // + // local hit residual info + auto H = state.effectiveProjector(); + auto resCov = state.effectiveCalibratedCovariance() + + H * covariance * H.transpose(); + auto res = state.effectiveCalibrated() - H * parameters; + m_res_x_hit.push_back(res[Acts::eBoundLoc0]); +// m_res_y_hit.push_back(res[Acts::eBoundLoc1]); + m_res_y_hit.push_back(-99.); + m_err_x_hit.push_back( + sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0))); +// m_err_y_hit.push_back( +// sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); + m_err_x_hit.push_back(-99.); + m_res_y_hit.push_back(-99.); + m_pull_x_hit.push_back( + res[Acts::eBoundLoc0] / + sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0))); +// m_pull_y_hit.push_back( +// res[Acts::eBoundLoc1] / +// sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); + m_pull_y_hit.push_back(-99); + m_dim_hit.push_back(state.calibratedSize()); + } + + // track parameters + m_eLOC0[ipar].push_back(parameters[Acts::eBoundLoc0]); + m_eLOC1[ipar].push_back(parameters[Acts::eBoundLoc1]); + m_ePHI[ipar].push_back(parameters[Acts::eBoundPhi]); + m_eTHETA[ipar].push_back(parameters[Acts::eBoundTheta]); + m_eQOP[ipar].push_back(parameters[Acts::eBoundQOverP]); + m_eT[ipar].push_back(parameters[Acts::eBoundTime]); + + // track parameters residual + m_res_eLOC0[ipar].push_back(parameters[Acts::eBoundLoc0] - + truthLOC0); + m_res_eLOC1[ipar].push_back(parameters[Acts::eBoundLoc1] - + truthLOC1); + float resPhi = Acts::detail::difference_periodic<float>( + parameters[Acts::eBoundPhi], truthPHI, + static_cast<float>(2 * M_PI)); + m_res_ePHI[ipar].push_back(resPhi); + m_res_eTHETA[ipar].push_back(parameters[Acts::eBoundTheta] - + truthTHETA); + m_res_eQOP[ipar].push_back(parameters[Acts::eBoundQOverP] - + truthQOP); + m_res_eT[ipar].push_back(parameters[Acts::eBoundTime] - truthTIME); + + // track parameters error + m_err_eLOC0[ipar].push_back( + sqrt(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0))); + m_err_eLOC1[ipar].push_back( + sqrt(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1))); + m_err_ePHI[ipar].push_back( + sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi))); + m_err_eTHETA[ipar].push_back( + sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta))); + m_err_eQOP[ipar].push_back( + sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP))); + m_err_eT[ipar].push_back( + sqrt(covariance(Acts::eBoundTime, Acts::eBoundTime))); + + // track parameters pull + m_pull_eLOC0[ipar].push_back( + (parameters[Acts::eBoundLoc0] - truthLOC0) / + sqrt(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0))); + m_pull_eLOC1[ipar].push_back( + (parameters[Acts::eBoundLoc1] - truthLOC1) / + sqrt(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1))); + m_pull_ePHI[ipar].push_back( + resPhi / sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi))); + m_pull_eTHETA[ipar].push_back( + (parameters[Acts::eBoundTheta] - truthTHETA) / + sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta))); + m_pull_eQOP[ipar].push_back( + (parameters[Acts::eBoundQOverP] - truthQOP) / + sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP))); + m_pull_eT[ipar].push_back( + (parameters[Acts::eBoundTime] - truthTIME) / + sqrt(covariance(Acts::eBoundTime, Acts::eBoundTime))); + + // further track parameter info + Acts::FreeVector freeParams = + Acts::detail::transformBoundToFreeParameters(surface, gctx, + parameters); + m_x[ipar].push_back(freeParams[Acts::eFreePos0]); + m_y[ipar].push_back(freeParams[Acts::eFreePos1]); + m_z[ipar].push_back(freeParams[Acts::eFreePos2]); + auto p = std::abs(1 / freeParams[Acts::eFreeQOverP]); + m_px[ipar].push_back(p * freeParams[Acts::eFreeDir0]); + m_py[ipar].push_back(p * freeParams[Acts::eFreeDir1]); + m_pz[ipar].push_back(p * freeParams[Acts::eFreeDir2]); + m_pT[ipar].push_back(p * std::hypot(freeParams[Acts::eFreeDir0], + freeParams[Acts::eFreeDir1])); + m_eta[ipar].push_back(Acts::VectorHelpers::eta( + freeParams.segment<3>(Acts::eFreeDir0))); + } else { + if (ipar == 0) { + // push default values if no track parameters + m_res_x_hit.push_back(-99.); + m_res_y_hit.push_back(-99.); + m_err_x_hit.push_back(-99.); + m_err_y_hit.push_back(-99.); + m_pull_x_hit.push_back(-99.); + m_pull_y_hit.push_back(-99.); + m_dim_hit.push_back(-99.); + } + // push default values if no track parameters + m_eLOC0[ipar].push_back(-99.); + m_eLOC1[ipar].push_back(-99.); + m_ePHI[ipar].push_back(-99.); + m_eTHETA[ipar].push_back(-99.); + m_eQOP[ipar].push_back(-99.); + m_eT[ipar].push_back(-99.); + m_res_eLOC0[ipar].push_back(-99.); + m_res_eLOC1[ipar].push_back(-99.); + m_res_ePHI[ipar].push_back(-99.); + m_res_eTHETA[ipar].push_back(-99.); + m_res_eQOP[ipar].push_back(-99.); + m_res_eT[ipar].push_back(-99.); + m_err_eLOC0[ipar].push_back(-99); + m_err_eLOC1[ipar].push_back(-99); + m_err_ePHI[ipar].push_back(-99); + m_err_eTHETA[ipar].push_back(-99); + m_err_eQOP[ipar].push_back(-99); + m_err_eT[ipar].push_back(-99); + m_pull_eLOC0[ipar].push_back(-99.); + m_pull_eLOC1[ipar].push_back(-99.); + m_pull_ePHI[ipar].push_back(-99.); + m_pull_eTHETA[ipar].push_back(-99.); + m_pull_eQOP[ipar].push_back(-99.); + m_pull_eT[ipar].push_back(-99.); + m_x[ipar].push_back(-99.); + m_y[ipar].push_back(-99.); + m_z[ipar].push_back(-99.); + m_px[ipar].push_back(-99.); + m_py[ipar].push_back(-99.); + m_pz[ipar].push_back(-99.); + m_pT[ipar].push_back(-99.); + m_eta[ipar].push_back(-99.); + } + // fill the track parameters status + m_hasParams[ipar].push_back(hasParams[ipar]); + } + + // fill the chi2 + m_chi2.push_back(state.chi2()); + + return true; + }); // all states + + // fill the variables for one track to tree + m_outputTree->Fill(); + + // now reset + m_t_x.clear(); + m_t_y.clear(); + m_t_z.clear(); + m_t_dx.clear(); + m_t_dy.clear(); + m_t_dz.clear(); + m_t_eLOC0.clear(); + m_t_eLOC1.clear(); + m_t_ePHI.clear(); + m_t_eTHETA.clear(); + m_t_eQOP.clear(); + m_t_eT.clear(); + + m_volumeID.clear(); + m_layerID.clear(); + m_moduleID.clear(); + m_station.clear(); + m_layer.clear(); + m_phi_module.clear(); + m_eta_module.clear(); + m_side.clear(); + m_pathLength.clear(); + m_lx_hit.clear(); + m_ly_hit.clear(); + m_x_hit.clear(); + m_y_hit.clear(); + m_z_hit.clear(); + m_res_x_hit.clear(); + m_res_y_hit.clear(); + m_err_x_hit.clear(); + m_err_y_hit.clear(); + m_pull_x_hit.clear(); + m_pull_y_hit.clear(); + m_dim_hit.clear(); + + for (unsigned int ipar = 0; ipar < 3; ++ipar) { + m_hasParams[ipar].clear(); + m_eLOC0[ipar].clear(); + m_eLOC1[ipar].clear(); + m_ePHI[ipar].clear(); + m_eTHETA[ipar].clear(); + m_eQOP[ipar].clear(); + m_eT[ipar].clear(); + m_res_eLOC0[ipar].clear(); + m_res_eLOC1[ipar].clear(); + m_res_ePHI[ipar].clear(); + m_res_eTHETA[ipar].clear(); + m_res_eQOP[ipar].clear(); + m_res_eT[ipar].clear(); + m_err_eLOC0[ipar].clear(); + m_err_eLOC1[ipar].clear(); + m_err_ePHI[ipar].clear(); + m_err_eTHETA[ipar].clear(); + m_err_eQOP[ipar].clear(); + m_err_eT[ipar].clear(); + m_pull_eLOC0[ipar].clear(); + m_pull_eLOC1[ipar].clear(); + m_pull_ePHI[ipar].clear(); + m_pull_eTHETA[ipar].clear(); + m_pull_eQOP[ipar].clear(); + m_pull_eT[ipar].clear(); + m_x[ipar].clear(); + m_y[ipar].clear(); + m_z[ipar].clear(); + m_px[ipar].clear(); + m_py[ipar].clear(); + m_pz[ipar].clear(); + m_eta[ipar].clear(); + m_pT[ipar].clear(); + } + + m_chi2.clear(); + } // all subtrajectories + } // all trajectories + + return StatusCode::SUCCESS; +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectorySummaryWriterTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectorySummaryWriterTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e3251a8098f29661776da8350fff4b26585cdc79 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectorySummaryWriterTool.cxx @@ -0,0 +1,456 @@ +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "FaserActsKalmanFilter/RootTrajectorySummaryWriterTool.h" +#include "Acts/EventData/MultiTrajectory.hpp" +#include "Acts/EventData/MultiTrajectoryHelpers.hpp" +#include "Acts/EventData/detail/TransformationBoundToFree.hpp" +#include "Acts/Utilities/Helpers.hpp" +#include "FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "GeoPrimitives/CLHEPtoEigenConverter.h" +#include "TrackerReadoutGeometry/SiDetectorElement.h" +#include "FaserActsKalmanFilter/TrackClassification.h" +#include "HepMC/GenParticle.h" +#include "HepMC/GenVertex.h" +#include <TFile.h> +#include <TTree.h> + +/// NaN values for TTree variables +constexpr double NaNdouble = std::numeric_limits<double>::quiet_NaN(); +constexpr float NaNfloat = std::numeric_limits<float>::quiet_NaN(); +constexpr float NaNint = std::numeric_limits<int>::quiet_NaN(); + +using ConstTrackStateProxy = Acts::detail_lt::TrackStateProxy<IndexSourceLink, 6, true>; + +using Acts::VectorHelpers::eta; +using Acts::VectorHelpers::perp; +using Acts::VectorHelpers::phi; +using Acts::VectorHelpers::theta; + +RootTrajectorySummaryWriterTool::RootTrajectorySummaryWriterTool( + const std::string& type, const std::string& name, const IInterface* parent) + : AthAlgTool(type, name, parent) {} + + +StatusCode RootTrajectorySummaryWriterTool::initialize() { + ATH_CHECK(m_simDataCollectionKey.initialize()); + ATH_CHECK(m_mcEventCollectionKey.initialize()); + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + + std::string filePath = m_filePath; + std::string treeName = m_treeName; + m_outputFile = TFile::Open(filePath.c_str(), "RECREATE"); + if (m_outputFile == nullptr) { + ATH_MSG_WARNING("Unable to open output file at " << m_filePath); + return StatusCode::RECOVERABLE; + } + m_outputFile->cd(); + m_outputTree = new TTree(treeName.c_str(), treeName.c_str()); + if (m_outputTree == nullptr) { + ATH_MSG_ERROR("Unable to create TTree"); + return StatusCode::FAILURE; + } + + m_outputTree = new TTree("tree", "tree"); + + m_outputTree->Branch("event_nr", &m_eventNr); + m_outputTree->Branch("multiTraj_nr", &m_multiTrajNr); + m_outputTree->Branch("subTraj_nr", &m_subTrajNr); + + m_outputTree->Branch("nStates", &m_nStates); + m_outputTree->Branch("nMeasurements", &m_nMeasurements); + m_outputTree->Branch("nOutliers", &m_nOutliers); + m_outputTree->Branch("nHoles", &m_nHoles); + m_outputTree->Branch("nSharedHits", &m_nSharedHits); + m_outputTree->Branch("chi2Sum", &m_chi2Sum); + m_outputTree->Branch("NDF", &m_NDF); + m_outputTree->Branch("measurementChi2", &m_measurementChi2); + m_outputTree->Branch("outlierChi2", &m_outlierChi2); + m_outputTree->Branch("measurementVolume", &m_measurementVolume); + m_outputTree->Branch("measurementLayer", &m_measurementLayer); + m_outputTree->Branch("outlierVolume", &m_outlierVolume); + m_outputTree->Branch("outlierLayer", &m_outlierLayer); + + m_outputTree->Branch("nMajorityHits", &m_nMajorityHits); + m_outputTree->Branch("majorityParticleId", &m_majorityParticleId); + m_outputTree->Branch("t_charge", &m_t_charge); + m_outputTree->Branch("t_time", &m_t_time); + m_outputTree->Branch("t_vx", &m_t_vx); + m_outputTree->Branch("t_vy", &m_t_vy); + m_outputTree->Branch("t_vz", &m_t_vz); + m_outputTree->Branch("t_px", &m_t_px); + m_outputTree->Branch("t_py", &m_t_py); + m_outputTree->Branch("t_pz", &m_t_pz); + m_outputTree->Branch("t_theta", &m_t_theta); + m_outputTree->Branch("t_phi", &m_t_phi); + m_outputTree->Branch("t_eta", &m_t_eta); + m_outputTree->Branch("t_p", &m_t_p); + m_outputTree->Branch("t_pT", &m_t_pT); + + m_outputTree->Branch("hasFittedParams", &m_hasFittedParams); + m_outputTree->Branch("eLOC0_fit", &m_eLOC0_fit); + m_outputTree->Branch("eLOC1_fit", &m_eLOC1_fit); + m_outputTree->Branch("ePHI_fit", &m_ePHI_fit); + m_outputTree->Branch("eTHETA_fit", &m_eTHETA_fit); + m_outputTree->Branch("eQOP_fit", &m_eQOP_fit); + m_outputTree->Branch("eT_fit", &m_eT_fit); + m_outputTree->Branch("err_eLOC0_fit", &m_err_eLOC0_fit); + m_outputTree->Branch("err_eLOC1_fit", &m_err_eLOC1_fit); + m_outputTree->Branch("err_ePHI_fit", &m_err_ePHI_fit); + m_outputTree->Branch("err_eTHETA_fit", &m_err_eTHETA_fit); + m_outputTree->Branch("err_eQOP_fit", &m_err_eQOP_fit); + m_outputTree->Branch("err_eT_fit", &m_err_eT_fit); + m_outputTree->Branch("res_eLOC0_fit", &m_res_eLOC0_fit); + m_outputTree->Branch("res_eLOC1_fit", &m_res_eLOC1_fit); + m_outputTree->Branch("res_ePHI_fit", &m_res_ePHI_fit); + m_outputTree->Branch("res_eTHETA_fit", &m_res_eTHETA_fit); + m_outputTree->Branch("res_eQOP_fit", &m_res_eQOP_fit); + m_outputTree->Branch("res_eT_fit", &m_res_eT_fit); + m_outputTree->Branch("pull_eLOC0_fit", &m_pull_eLOC0_fit); + m_outputTree->Branch("pull_eLOC1_fit", &m_pull_eLOC1_fit); + m_outputTree->Branch("pull_ePHI_fit", &m_pull_ePHI_fit); + m_outputTree->Branch("pull_eTHETA_fit", &m_pull_eTHETA_fit); + m_outputTree->Branch("pull_eQOP_fit", &m_pull_eQOP_fit); + m_outputTree->Branch("pull_eT_fit", &m_pull_eT_fit); + + return StatusCode::SUCCESS; +} + + +StatusCode RootTrajectorySummaryWriterTool::finalize() { + m_outputFile->cd(); + m_outputTree->Write(); + m_outputFile->Close(); + return StatusCode::SUCCESS; +} + + +StatusCode RootTrajectorySummaryWriterTool::write( + const Acts::GeometryContext& geoContext, const TrajectoriesContainer& trajectories) const { + EventContext ctx = Gaudi::Hive::currentContext(); + + SG::ReadHandle<TrackerSimDataCollection> simData {m_simDataCollectionKey, ctx}; + ATH_CHECK(simData.isValid()); + + SG::ReadHandle<McEventCollection> mcEvents {m_mcEventCollectionKey, ctx}; + ATH_CHECK(mcEvents.isValid()); + if (mcEvents->size() != 1) { + ATH_MSG_ERROR("There should be exactly one event in the McEventCollection."); + return StatusCode::FAILURE; + } + + std::map<int, const HepMC::GenParticle*> particles {}; + for (const HepMC::GenParticle* particle : mcEvents->front()->particle_range()) { + particles[particle->barcode()] = particle; + } + + // For each particle within a track, how many hits did it contribute + std::vector<ParticleHitCount> particleHitCounts; + + // Get the event number + m_eventNr = ctx.eventID().event_number(); + + // Loop over the trajectories + for (size_t itraj = 0; itraj < trajectories.size(); ++itraj) { + const auto& traj = trajectories[itraj]; + + if (traj.empty()) { + ATH_MSG_WARNING("Empty trajectories object " << itraj); + continue; + } + + // The trajectory index + m_multiTrajNr.push_back(itraj); + + // The trajectory entry indices and the multiTrajectory + const auto& mj = traj.multiTrajectory(); + const auto& trackTips = traj.tips(); + + // Loop over the entry indices for the subtrajectories + for (unsigned int isubtraj = 0; isubtraj < trackTips.size(); ++isubtraj) { + // The subtrajectory index + m_subTrajNr.push_back(isubtraj); + // The entry index for this subtrajectory + const auto& trackTip = trackTips[isubtraj]; + + // Collect the trajectory summary info + auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); + m_nStates.push_back(trajState.nStates); + m_nMeasurements.push_back(trajState.nMeasurements); + m_nOutliers.push_back(trajState.nOutliers); + m_nHoles.push_back(trajState.nHoles); + m_nSharedHits.push_back(trajState.nSharedHits); + m_chi2Sum.push_back(trajState.chi2Sum); + m_NDF.push_back(trajState.NDF); + m_measurementChi2.push_back(trajState.measurementChi2); + m_outlierChi2.push_back(trajState.measurementChi2); + // They are stored as double (as the vector of vector of int is not known to ROOT) + m_measurementVolume.emplace_back(trajState.measurementVolume.begin(), trajState.measurementVolume.end()); + m_measurementLayer.emplace_back(trajState.measurementLayer.begin(), trajState.measurementLayer.end()); + m_outlierVolume.emplace_back(trajState.outlierVolume.begin(), trajState.outlierVolume.end()); + m_outlierLayer.emplace_back(trajState.outlierLayer.begin(), trajState.outlierLayer.end()); + + // Initialize the truth particle info + uint64_t majorityParticleId = NaNint; + unsigned int nMajorityHits = NaNint; + float t_charge = NaNint; + float t_time = NaNfloat; + float t_vlx = NaNfloat; + float t_vly = NaNfloat; + float t_vx = NaNfloat; + float t_vy = NaNfloat; + float t_vz = NaNfloat; + float t_px = NaNfloat; + float t_py = NaNfloat; + float t_pz = NaNfloat; + float t_theta = NaNfloat; + float t_phi = NaNfloat; + float t_eta = NaNfloat; + float t_p = NaNfloat; + float t_pT = NaNfloat; + + // Get the perigee surface + Acts::Surface* pSurface = nullptr; + if (traj.hasTrackParameters(trackTip)) { + const auto& boundParam = traj.trackParameters(trackTip); + pSurface = const_cast<Acts::Surface*>(&boundParam.referenceSurface()); + } + + // Get the majority truth particle to this track + ATH_MSG_VERBOSE("get majority truth particle"); + identifyContributingParticles(*simData, traj, trackTip, particleHitCounts); + for (const auto& particle : particleHitCounts) { + ATH_MSG_VERBOSE(particle.particleId << ": " << particle.hitCount << " hits"); + } + + bool foundMajorityParticle = false; + // Get the truth particle info + if (not particleHitCounts.empty()) { + // Get the barcode of the majority truth particle + majorityParticleId = particleHitCounts.front().particleId; + nMajorityHits = particleHitCounts.front().hitCount; + + // Find the truth particle via the barcode + auto ip = particles.find(majorityParticleId); + if (ip != particles.end()) { + foundMajorityParticle = true; + + const HepMC::GenParticle* particle = ip->second; + ATH_MSG_DEBUG("Find the truth particle with barcode = " << majorityParticleId); + + // extrapolate parameters from vertex to reference surface at origin. + std::unique_ptr<const Acts::BoundTrackParameters> truthParameters + = extrapolateToReferenceSurface(ctx, particle); + if (!truthParameters) { + continue; + } + // Get the truth particle info at vertex + const HepMC::GenVertex* vertex = particle->production_vertex(); + t_p = truthParameters->momentum().mag(); + t_charge = truthParameters->charge(); + t_time = truthParameters->time(); + t_vx = truthParameters->position(geoContext).x(); + t_vy = truthParameters->position(geoContext).y(); + t_vz = truthParameters->position(geoContext).z(); + t_px = truthParameters->momentum().x(); + t_py = truthParameters->momentum().y(); + t_pz = truthParameters->momentum().z(); + t_theta = theta(truthParameters->momentum().normalized()); + t_phi = phi(truthParameters->momentum().normalized()); + t_eta = eta(truthParameters->momentum().normalized()); + t_pT = t_p * perp(truthParameters->momentum().normalized()); + + auto unitDirection = Acts::Vector3(t_px, t_py, t_pz).normalized(); + auto positon = Acts::Vector3 (t_vx, t_vy, t_vz); + + if (pSurface) { + // get the truth perigee parameter + auto lpResult = pSurface->globalToLocal(geoContext, positon, unitDirection); + if (lpResult.ok()) { + t_vlx = lpResult.value()[Acts::BoundIndices::eBoundLoc0]; + t_vly = lpResult.value()[Acts::BoundIndices::eBoundLoc1]; + } else { + ATH_MSG_ERROR("Global to local transformation did not succeed."); + } + } + } else { + ATH_MSG_WARNING("Truth particle with barcode = " << majorityParticleId << " not found in the input collection!"); + } + } + if (not foundMajorityParticle) { + ATH_MSG_WARNING("Truth particle for mj " << itraj << " subtraj " << isubtraj << " not found!"); + } + + // Push the corresponding truth particle info for the track. + // Always push back even if majority particle not found + m_majorityParticleId.push_back(majorityParticleId); + m_nMajorityHits.push_back(nMajorityHits); + m_t_charge.push_back(t_charge); + m_t_time.push_back(t_time); + m_t_vx.push_back(t_vx); + m_t_vy.push_back(t_vy); + m_t_vz.push_back(t_vz); + m_t_px.push_back(t_px); + m_t_py.push_back(t_py); + m_t_pz.push_back(t_pz); + m_t_theta.push_back(t_theta); + m_t_phi.push_back(t_phi); + m_t_eta.push_back(t_eta); + m_t_p.push_back(t_p); + m_t_pT.push_back(t_pT); + + // Initialize the fitted track parameters info + std::array<float, Acts::eBoundSize> param = {NaNfloat, NaNfloat, NaNfloat, NaNfloat, NaNfloat, NaNfloat}; + std::array<float, Acts::eBoundSize> res = {NaNfloat, NaNfloat, NaNfloat, NaNfloat, NaNfloat, NaNfloat}; + std::array<float, Acts::eBoundSize> error = {NaNfloat, NaNfloat, NaNfloat, NaNfloat, NaNfloat, NaNfloat}; + std::array<float, Acts::eBoundSize> pull = {NaNfloat, NaNfloat, NaNfloat, NaNfloat, NaNfloat, NaNfloat}; + bool hasFittedParams = false; + if (traj.hasTrackParameters(trackTip)) { + hasFittedParams = true; + const auto& boundParam = traj.trackParameters(trackTip); + const auto& parameter = boundParam.parameters(); + for (unsigned int i = 0; i < Acts::eBoundSize; ++i) { + param[i] = parameter[i]; + } + + res = {param[Acts::eBoundLoc0] - t_vlx, + param[Acts::eBoundLoc1] - t_vly, + param[Acts::eBoundPhi] - t_phi, + param[Acts::eBoundTheta] - t_theta, + param[Acts::eBoundQOverP] - t_charge / t_p, + param[Acts::eBoundTime] - t_time}; + + if (boundParam.covariance().has_value()) { + const auto& covariance = *boundParam.covariance(); + for (unsigned int i = 0; i < Acts::eBoundSize; ++i) { + error[i] = std::sqrt(covariance(i, i)); + pull[i] = res[i] / error[i]; + } + } + } + + // Push the fitted track parameters. + // Always push back even if no fitted track parameters + m_eLOC0_fit.push_back(param[Acts::eBoundLoc0]); + m_eLOC1_fit.push_back(param[Acts::eBoundLoc1]); + m_ePHI_fit.push_back(param[Acts::eBoundPhi]); + m_eTHETA_fit.push_back(param[Acts::eBoundTheta]); + m_eQOP_fit.push_back(param[Acts::eBoundQOverP]); + m_eT_fit.push_back(param[Acts::eBoundTime]); + + m_res_eLOC0_fit.push_back(res[Acts::eBoundLoc0]); + m_res_eLOC1_fit.push_back(res[Acts::eBoundLoc1]); + m_res_ePHI_fit.push_back(res[Acts::eBoundPhi]); + m_res_eTHETA_fit.push_back(res[Acts::eBoundTheta]); + m_res_eQOP_fit.push_back(res[Acts::eBoundQOverP]); + m_res_eT_fit.push_back(res[Acts::eBoundTime]); + + m_err_eLOC0_fit.push_back(error[Acts::eBoundLoc0]); + m_err_eLOC1_fit.push_back(error[Acts::eBoundLoc1]); + m_err_ePHI_fit.push_back(error[Acts::eBoundPhi]); + m_err_eTHETA_fit.push_back(error[Acts::eBoundTheta]); + m_err_eQOP_fit.push_back(error[Acts::eBoundQOverP]); + m_err_eT_fit.push_back(error[Acts::eBoundTime]); + + m_pull_eLOC0_fit.push_back(pull[Acts::eBoundLoc0]); + m_pull_eLOC1_fit.push_back(pull[Acts::eBoundLoc1]); + m_pull_ePHI_fit.push_back(pull[Acts::eBoundPhi]); + m_pull_eTHETA_fit.push_back(pull[Acts::eBoundTheta]); + m_pull_eQOP_fit.push_back(pull[Acts::eBoundQOverP]); + m_pull_eT_fit.push_back(pull[Acts::eBoundTime]); + + m_hasFittedParams.push_back(hasFittedParams); + } // all subtrajectories + } // all trajectories + + + // fill the variables + m_outputTree->Fill(); + + m_multiTrajNr.clear(); + m_subTrajNr.clear(); + m_nStates.clear(); + m_nMeasurements.clear(); + m_nOutliers.clear(); + m_nHoles.clear(); + m_nSharedHits.clear(); + m_chi2Sum.clear(); + m_NDF.clear(); + m_measurementChi2.clear(); + m_outlierChi2.clear(); + m_measurementVolume.clear(); + m_measurementLayer.clear(); + m_outlierVolume.clear(); + m_outlierLayer.clear(); + + m_nMajorityHits.clear(); + m_majorityParticleId.clear(); + m_t_charge.clear(); + m_t_time.clear(); + m_t_vx.clear(); + m_t_vy.clear(); + m_t_vz.clear(); + m_t_px.clear(); + m_t_py.clear(); + m_t_pz.clear(); + m_t_theta.clear(); + m_t_phi.clear(); + m_t_p.clear(); + m_t_pT.clear(); + m_t_eta.clear(); + + m_hasFittedParams.clear(); + m_eLOC0_fit.clear(); + m_eLOC1_fit.clear(); + m_ePHI_fit.clear(); + m_eTHETA_fit.clear(); + m_eQOP_fit.clear(); + m_eT_fit.clear(); + m_err_eLOC0_fit.clear(); + m_err_eLOC1_fit.clear(); + m_err_ePHI_fit.clear(); + m_err_eTHETA_fit.clear(); + m_err_eQOP_fit.clear(); + m_err_eT_fit.clear(); + m_res_eLOC0_fit.clear(); + m_res_eLOC1_fit.clear(); + m_res_ePHI_fit.clear(); + m_res_eTHETA_fit.clear(); + m_res_eQOP_fit.clear(); + m_res_eT_fit.clear(); + m_pull_eLOC0_fit.clear(); + m_pull_eLOC1_fit.clear(); + m_pull_ePHI_fit.clear(); + m_pull_eTHETA_fit.clear(); + m_pull_eQOP_fit.clear(); + m_pull_eT_fit.clear(); + + return StatusCode::SUCCESS; +} + + +std::unique_ptr<const Acts::BoundTrackParameters> RootTrajectorySummaryWriterTool::extrapolateToReferenceSurface( + const EventContext& ctx, const HepMC::GenParticle* particle) const { + const HepMC::FourVector &vertex = particle->production_vertex()->position(); + const HepMC::FourVector &momentum = particle->momentum(); + + // The coordinate system of the Acts::PlaneSurface is defined as + // T = Z = normal, U = X x T = -Y, V = T x U = x + auto startSurface = Acts::Surface::makeShared<Acts::PlaneSurface>( + Acts::Vector3(0, 0, vertex.z()), Acts::Vector3(0, 0, 1)); + auto targetSurface = Acts::Surface::makeShared<Acts::PlaneSurface>( + Acts::Vector3(0, 0, 0), Acts::Vector3(0, 0, -1)); + Acts::BoundVector params = Acts::BoundVector::Zero(); + params[Acts::eBoundLoc0] = -vertex.y(); + params[Acts::eBoundLoc1] = vertex.x(); + params[Acts::eBoundPhi] = momentum.phi(); + params[Acts::eBoundTheta] = momentum.theta(); + // FIXME get charge of HepMC::GenParticle, the following does not work, e.g. for pions + double charge = particle->pdg_id() > 0 ? -1 : 1; + double MeV2GeV = 1e-3; + params[Acts::eBoundQOverP] = charge / (momentum.rho() * MeV2GeV); + params[Acts::eBoundTime] = vertex.t(); + Acts::BoundTrackParameters startParameters(std::move(startSurface), params, charge); + std::unique_ptr<const Acts::BoundTrackParameters> targetParameters = + m_extrapolationTool->propagate(ctx, startParameters, *targetSurface); + return targetParameters; +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/SegmentFitClusterTrackFinderTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/SegmentFitClusterTrackFinderTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b12215257197a931266e251620f2c63ecef7b10a --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/SegmentFitClusterTrackFinderTool.cxx @@ -0,0 +1,151 @@ +#include "FaserActsKalmanFilter/SegmentFitClusterTrackFinderTool.h" + +#include "Acts/Definitions/TrackParametrization.hpp" +#include "Acts/EventData/Measurement.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Surfaces/Surface.hpp" +#include "FaserActsKalmanFilter/IndexSourceLink.h" +#include "Identifier/Identifier.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "TrkTrack/Track.h" +#include "TrkTrack/TrackStateOnSurface.h" +#include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +//#include "TrackerPrepRawData/FaserSCT_ClusterCollection.h" +#include <random> + + +SegmentFitClusterTrackFinderTool::SegmentFitClusterTrackFinderTool(const std::string& type, const std::string& name, const IInterface* parent) + : base_class(type, name, parent) {} + + +StatusCode SegmentFitClusterTrackFinderTool::initialize() { + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + ATH_CHECK(detStore()->retrieve(m_detManager, "SCT")); + ATH_CHECK(m_trackingGeometryTool.retrieve()); + ATH_CHECK(m_trackCollection.initialize()); + return StatusCode::SUCCESS; +} + + +StatusCode SegmentFitClusterTrackFinderTool::run() { + SG::ReadHandle<TrackCollection> trackCollection {m_trackCollection}; + ATH_CHECK(trackCollection.isValid()); + + using IdentifierMap = std::map<Identifier, Acts::GeometryIdentifier>; + std::shared_ptr<IdentifierMap> identifierMap = m_trackingGeometryTool->getIdentifierMap(); + + // create source links and measurements + const int kSize = 1; + using ThisMeasurement = Acts::Measurement<IndexSourceLink, Acts::BoundIndices, kSize>; + std::array<Acts::BoundIndices, kSize> Indices = {Acts::eBoundLoc0}; + std::vector<IndexSourceLink> sourceLinks; + std::vector<Measurement> measurements; + std::map<int, Amg::Vector3D> positions; + std::map<int, Amg::Vector3D> directions; + std::map<Index, Identifier> identifierLinkMap; + std::vector<const Tracker::FaserSCT_Cluster*> clusters {}; + // TODO only take best track (most hits, smallest chi2) + // for now I assume that there is only one track in each station + for (const Trk::Track* track : *trackCollection) { + auto fitParameters = track->trackParameters()->front(); + const Amg::Vector3D fitPosition = fitParameters->position(); + const Amg::Vector3D fitMomentum = fitParameters->momentum(); + Identifier id; + for (const Trk::TrackStateOnSurface* state : *(track->trackStateOnSurfaces())) { + auto clusterOnTrack = dynamic_cast<const Tracker::FaserSCT_ClusterOnTrack*> ( + state->measurementOnTrack()); + if (clusterOnTrack) { + const Tracker::FaserSCT_Cluster* cluster = clusterOnTrack->prepRawData(); + id = cluster->detectorElement()->identify(); + // create source link + Acts::GeometryIdentifier geoId = identifierMap->at(id); + ATH_MSG_DEBUG(geoId); + ATH_MSG_DEBUG(m_idHelper->station(id) << "/" << + m_idHelper->layer(id) << "/" << + m_idHelper->phi_module(id) << "/" << + m_idHelper->eta_module(id) << "/" << + m_idHelper->side(id) + ); + identifierLinkMap[measurements.size()] = id; + IndexSourceLink sourceLink(geoId, measurements.size()); + // create measurement + const auto& par = cluster->localPosition(); + const auto& cov = cluster->localCovariance(); + Eigen::Matrix<double, 1, 1> myCov {m_sigmaCluster * m_sigmaCluster,}; + ThisMeasurement meas(sourceLink, Indices, par.head(1), myCov); +// ThisMeasurement meas(sourceLink, Indices, par.head(1), cov.block<1,1>(0,0)); + sourceLinks.push_back(sourceLink); + measurements.emplace_back(std::move(meas)); + clusters.push_back(cluster); + } + } + int station = m_idHelper->station(id); + positions[station] = fitPosition; + directions[station] = fitMomentum; + } + std::vector<std::vector<IndexSourceLink>> sourceLinkVector {sourceLinks}; + m_sourceLinks = std::make_shared<std::vector<std::vector<IndexSourceLink>>>(sourceLinkVector); + std::vector<std::vector<Measurement>> measurementVector {measurements}; + m_measurements = std::make_shared<std::vector<std::vector<Measurement>>>(measurementVector); + std::vector<std::map<Index, Identifier>> idLinkVector {identifierLinkMap}; + m_idLinks = std::make_shared<std::vector<std::map<Index, Identifier>>>(idLinkVector); + std::vector<std::vector<const Tracker::FaserSCT_Cluster*>> clusterVector {clusters}; + m_clusters = std::make_shared<std::vector<std::vector<const Tracker::FaserSCT_Cluster*>>>(clusterVector); + + // TODO how should we handle events without a track in each station? + if (positions.size() != 3) { + return StatusCode::RECOVERABLE; + } + + // create initial surface + m_initialSurface = Acts::Surface::makeShared<Acts::PlaneSurface>( + Acts::Vector3 {0, 0, 0}, Acts::Vector3{0, 0, 1}); + + // create initial parameters + Acts::Vector3 pos = positions[1] - positions[1].z()/directions[1].z() * directions[1]; + Acts::Vector4 pos4 {pos.x(), pos.y(), pos.z(), 0}; + Acts::Vector3 dir = positions[2] - positions[1]; + auto [abs_momentum, charge] = momentum(positions); +// Acts::Vector3 pos = positions[1] - positions[1].z()/directions[1].z() * directions[1]; +// Acts::Vector4 pos4 {pos.x(), pos.y(), pos.z(), 0}; +// Acts::Vector3 dir = {directions[1].x(), directions[1].y(), directions[1].z()}; +// double abs_momentum = 1000; +// double charge = 1; + + Acts::BoundSymMatrix cov = Acts::BoundSymMatrix::Zero(); + cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = m_covLoc0; + cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = m_covLoc1; + cov(Acts::eBoundPhi, Acts::eBoundPhi) = m_covPhi; + cov(Acts::eBoundTheta, Acts::eBoundTheta) = m_covTheta; + cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = m_covQOverP; + cov(Acts::eBoundTime, Acts::eBoundTime) = m_covTime; + + auto initialParameters = Acts::CurvilinearTrackParameters( + pos4, dir, abs_momentum, charge, cov); + std::vector<Acts::CurvilinearTrackParameters> paramVector {initialParameters}; + m_initialTrackParameters = std::make_shared<std::vector<Acts::CurvilinearTrackParameters>>(paramVector); + + return StatusCode::SUCCESS; +} + + +StatusCode SegmentFitClusterTrackFinderTool::finalize() { + return StatusCode::SUCCESS; +} + + +std::pair<double, double> SegmentFitClusterTrackFinderTool::momentum(const std::map<int, Amg::Vector3D>& pos, double B) { + Acts::Vector3 vec_l = pos.at(3) - pos.at(1); + double abs_l = std::sqrt(vec_l.y() * vec_l.y() + vec_l.z() * vec_l.z()); + double t = (pos.at(2).z() - pos.at(1).z()) / (pos.at(3).z() - pos.at(1).z()); + Acts::Vector3 vec_m = pos.at(1) + t * vec_l; + Acts::Vector3 vec_s = pos.at(2) - vec_m; + double abs_s = std::sqrt(vec_s.y() * vec_s.y() + vec_s.z() * vec_s.z()); + double p_yz = 0.3 * abs_l * abs_l * B / (8 * abs_s * 1000); + double charge = vec_s.y() < 0 ? 1 : -1; + return std::make_pair(p_yz, charge); +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/SegmentFitTrackFinderTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/SegmentFitTrackFinderTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..0aa77c3e8b3f18a75b55aafb730e216e388c10f5 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/SegmentFitTrackFinderTool.cxx @@ -0,0 +1,152 @@ +#include "FaserActsKalmanFilter/SegmentFitTrackFinderTool.h" + +#include "Acts/Definitions/TrackParametrization.hpp" +#include "Acts/EventData/Measurement.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Surfaces/Surface.hpp" +#include "FaserActsKalmanFilter/IndexSourceLink.h" +#include "Identifier/Identifier.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "TrkTrack/Track.h" +#include "TrkTrack/TrackStateOnSurface.h" +#include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" +#include "TrackerPrepRawData/FaserSCT_ClusterCollection.h" +#include <random> + + +SegmentFitTrackFinderTool::SegmentFitTrackFinderTool(const std::string& type, const std::string& name, const IInterface* parent) + : base_class(type, name, parent) {} + + +StatusCode SegmentFitTrackFinderTool::initialize() { + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + ATH_CHECK(detStore()->retrieve(m_detManager, "SCT")); + ATH_CHECK(m_trackingGeometryTool.retrieve()); + ATH_CHECK(m_trackCollection.initialize()); + ATH_CHECK(m_spacePointContainerKey.initialize()); + return StatusCode::SUCCESS; +} + + +StatusCode SegmentFitTrackFinderTool::run() { + SG::ReadHandle<TrackCollection> trackCollection {m_trackCollection}; + ATH_CHECK(trackCollection.isValid()); + + SG::ReadHandle<FaserSCT_SpacePointContainer> spacePointContainer {m_spacePointContainerKey}; + ATH_CHECK(spacePointContainer.isValid()); + + using IdentifierMap = std::map<Identifier, Acts::GeometryIdentifier>; + std::shared_ptr<IdentifierMap> identifierMap = m_trackingGeometryTool->getIdentifierMap(); + + // create vector of cluster identifiers which have been used by any track fit + std::vector<Identifier> trackIds; + std::map<int, Amg::Vector3D> positions; + std::map<int, Amg::Vector3D> directions; + // TODO only take best track (most hits, smallest chi2) + // for now I assume that there is only one track in each station + for (const Trk::Track* track : *trackCollection) { + auto fitParameters = track->trackParameters()->front(); + const Amg::Vector3D fitPosition = fitParameters->position(); + const Amg::Vector3D fitMomentum = fitParameters->momentum(); + Identifier id; + for (const Trk::TrackStateOnSurface* state : *(track->trackStateOnSurfaces())) { + auto clusterOnTrack = dynamic_cast<const Tracker::FaserSCT_ClusterOnTrack*> ( + state->measurementOnTrack()); + if (clusterOnTrack) { + id = clusterOnTrack->identify(); + trackIds.push_back(id); + } + } + int station = m_idHelper->station(id); + positions[station] = fitPosition; + directions[station] = fitMomentum; + } + + // create source links and measurements + const int kSize = 2; + using ThisMeasurement = Acts::Measurement<IndexSourceLink, Acts::BoundIndices, kSize>; + std::array<Acts::BoundIndices, kSize> Indices = {Acts::eBoundLoc0, Acts::eBoundLoc1}; + std::vector<IndexSourceLink> sourceLinks; + std::vector<Measurement> measurements; + std::vector<Tracker::FaserSCT_SpacePoint> spacePoints {}; + for (const FaserSCT_SpacePointCollection* spacePointCollection : *spacePointContainer) { + for (const Tracker::FaserSCT_SpacePoint *spacePoint: *spacePointCollection) { + Identifier id1 = spacePoint->cluster1()->identify(); + Identifier id2 = spacePoint->cluster2()->identify(); + // check if both clusters have been used to reconstruct track + if (std::find(trackIds.begin(), trackIds.end(), id1) != trackIds.end() && + std::find(trackIds.begin(), trackIds.end(), id2) != trackIds.end()) { + spacePoints.push_back(*spacePoint); + Identifier id = spacePoint->associatedSurface().associatedDetectorElementIdentifier(); + // create source link + Acts::GeometryIdentifier geoId = identifierMap->at(id); + IndexSourceLink sourceLink(geoId, measurements.size()); + // create measurement + const auto& par = spacePoint->localParameters(); + const auto& cov = spacePoint->localCovariance(); + ThisMeasurement meas(sourceLink, Indices, par, cov); + sourceLinks.push_back(sourceLink); + measurements.emplace_back(std::move(meas)); + } + } + } + m_sourceLinks = std::make_shared<std::vector<IndexSourceLink>>(sourceLinks); + m_measurements = std::make_shared<std::vector<Measurement>>(measurements); + m_spacePoints = std::make_shared<std::vector<Tracker::FaserSCT_SpacePoint>>(spacePoints); + + // TODO how should we handle events without a track in each station? + if (positions.size() != 3) { + return StatusCode::RECOVERABLE; + } + + // create initial surface + m_initialSurface = Acts::Surface::makeShared<Acts::PlaneSurface>( + Acts::Vector3 {0, 0, 0}, Acts::Vector3{0, 0, 1}); + + // create initial parameters + Acts::Vector3 pos = positions[1] - positions[1].z()/directions[1].z() * directions[1]; + Acts::Vector4 pos4 {pos.x(), pos.y(), pos.z(), 0}; + Acts::Vector3 dir = positions[2] - positions[1]; + Acts::Vector3 tmp {directions[1].x(), directions[1].y(), directions[1].z()}; + ATH_MSG_DEBUG(dir); + ATH_MSG_DEBUG(tmp); + double abs_momentum = momentum(positions); + // TODO get charge from momentum calculation + double charge = 1; + + Acts::BoundSymMatrix cov = Acts::BoundSymMatrix::Zero(); + cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = m_covLoc0; + cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = m_covLoc1; + cov(Acts::eBoundPhi, Acts::eBoundPhi) = m_covPhi; + cov(Acts::eBoundTheta, Acts::eBoundTheta) = m_covTheta; + cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = m_covQOverP; + cov(Acts::eBoundTime, Acts::eBoundTime) = m_covTime; + + auto initialParameters = Acts::CurvilinearTrackParameters( + pos4, dir, abs_momentum, charge, cov); + m_initialTrackParameters = std::make_shared<const Acts::CurvilinearTrackParameters>(initialParameters); + + return StatusCode::SUCCESS; +} + + +StatusCode SegmentFitTrackFinderTool::finalize() { + return StatusCode::SUCCESS; +} + + +double SegmentFitTrackFinderTool::momentum(const std::map<int, Amg::Vector3D>& pos, double B) { + Acts::Vector3 vec_l = pos.at(3) - pos.at(1); + double abs_l = std::sqrt(vec_l.y() * vec_l.y() + vec_l.z() * vec_l.z()); + double t = (pos.at(2).z() - pos.at(1).z()) / (pos.at(3).z() - pos.at(1).z()); + Acts::Vector3 vec_m = pos.at(1) + t * vec_l; + Acts::Vector3 vec_s = pos.at(2) - vec_m; + double abs_s = std::sqrt(vec_s.y() * vec_s.y() + vec_s.z() * vec_s.z()); + double p_yz = 0.3 * abs_l * abs_l * B / (8 * abs_s * 1000); + return p_yz; +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/SummaryPlotTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/SummaryPlotTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..f216042a6bbf915f169c41fe9ea0cc9b206f2c73 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/SummaryPlotTool.cxx @@ -0,0 +1,86 @@ +#include "FaserActsKalmanFilter/SummaryPlotTool.h" +#include <iostream> + +void SummaryPlotTool::book(SummaryPlotTool::SummaryPlotCache &trackSummaryPlotCache) const { + PlotHelpers::Binning bEta = m_varBinning.at("Eta"); + PlotHelpers::Binning bPt = m_varBinning.at("Pt"); + PlotHelpers::Binning bNum = m_varBinning.at("Num"); + // number of track states versus eta + trackSummaryPlotCache.nStates_vs_eta = PlotHelpers::bookProf( + "nStates_vs_eta", "Number of total states vs. #eta", bEta, bNum); + // number of measurements versus eta + trackSummaryPlotCache.nMeasurements_vs_eta = PlotHelpers::bookProf( + "nMeasurements_vs_eta", "Number of measurements vs. #eta", bEta, bNum); + // number of holes versus eta + trackSummaryPlotCache.nHoles_vs_eta = PlotHelpers::bookProf( + "nHoles_vs_eta", "Number of holes vs. #eta", bEta, bNum); + // number of outliers versus eta + trackSummaryPlotCache.nOutliers_vs_eta = PlotHelpers::bookProf( + "nOutliers_vs_eta", "Number of outliers vs. #eta", bEta, bNum); + // number of Shared Hits versus eta + trackSummaryPlotCache.nSharedHits_vs_eta = PlotHelpers::bookProf( + "nSharedHits_vs_eta", "Number of Shared Hits vs. #eta", bEta, bNum); + // number of track states versus pt + trackSummaryPlotCache.nStates_vs_pt = PlotHelpers::bookProf( + "nStates_vs_pT", "Number of total states vs. pT", bPt, bNum); + // number of measurements versus pt + trackSummaryPlotCache.nMeasurements_vs_pt = PlotHelpers::bookProf( + "nMeasurements_vs_pT", "Number of measurements vs. pT", bPt, bNum); + // number of holes versus pt + trackSummaryPlotCache.nHoles_vs_pt = PlotHelpers::bookProf( + "nHoles_vs_pT", "Number of holes vs. pT", bPt, bNum); + // number of outliers versus pt + trackSummaryPlotCache.nOutliers_vs_pt = PlotHelpers::bookProf( + "nOutliers_vs_pT", "Number of outliers vs. pT", bPt, bNum); + // number of Shared Hits versus pt + trackSummaryPlotCache.nSharedHits_vs_pt = PlotHelpers::bookProf( + "nSharedHits_vs_pT", "Number of Shared Hits vs. pT", bPt, bNum); +} + +void SummaryPlotTool::fill(SummaryPlotTool::SummaryPlotCache &trackSummaryPlotCache, + const Acts::BoundTrackParameters &fittedParameters, size_t nStates, size_t nMeasurements, + size_t nOutliers, size_t nHoles, size_t nSharedHits) const { + using Acts::VectorHelpers::eta; + using Acts::VectorHelpers::perp; + const auto& momentum = fittedParameters.momentum(); + const double fit_eta = eta(momentum); + const double fit_pT = perp(momentum); + + PlotHelpers::fillProf(trackSummaryPlotCache.nStates_vs_eta, fit_eta, nStates); + PlotHelpers::fillProf(trackSummaryPlotCache.nMeasurements_vs_eta, fit_eta, nMeasurements); + PlotHelpers::fillProf(trackSummaryPlotCache.nOutliers_vs_eta, fit_eta, nOutliers); + PlotHelpers::fillProf(trackSummaryPlotCache.nHoles_vs_eta, fit_eta, nHoles); + PlotHelpers::fillProf(trackSummaryPlotCache.nSharedHits_vs_eta, fit_eta, nSharedHits); + + PlotHelpers::fillProf(trackSummaryPlotCache.nStates_vs_pt, fit_pT, nStates); + PlotHelpers::fillProf(trackSummaryPlotCache.nMeasurements_vs_pt, fit_pT, nMeasurements); + PlotHelpers::fillProf(trackSummaryPlotCache.nOutliers_vs_pt, fit_pT, nOutliers); + PlotHelpers::fillProf(trackSummaryPlotCache.nHoles_vs_pt, fit_pT, nHoles); + PlotHelpers::fillProf(trackSummaryPlotCache.nSharedHits_vs_pt, fit_pT, nSharedHits); +} + +void SummaryPlotTool::write(const SummaryPlotTool::SummaryPlotCache &trackSummaryPlotCache) const { + trackSummaryPlotCache.nStates_vs_eta->Write(); + trackSummaryPlotCache.nMeasurements_vs_eta->Write(); + trackSummaryPlotCache.nOutliers_vs_eta->Write(); + trackSummaryPlotCache.nHoles_vs_eta->Write(); + trackSummaryPlotCache.nSharedHits_vs_eta->Write(); + trackSummaryPlotCache.nStates_vs_pt->Write(); + trackSummaryPlotCache.nMeasurements_vs_pt->Write(); + trackSummaryPlotCache.nOutliers_vs_pt->Write(); + trackSummaryPlotCache.nHoles_vs_pt->Write(); + trackSummaryPlotCache.nSharedHits_vs_pt->Write(); +} + +void SummaryPlotTool::clear(SummaryPlotTool::SummaryPlotCache &trackSummaryPlotCache) const { + delete trackSummaryPlotCache.nStates_vs_eta; + delete trackSummaryPlotCache.nMeasurements_vs_eta; + delete trackSummaryPlotCache.nOutliers_vs_eta; + delete trackSummaryPlotCache.nHoles_vs_eta; + delete trackSummaryPlotCache.nSharedHits_vs_eta; + delete trackSummaryPlotCache.nStates_vs_pt; + delete trackSummaryPlotCache.nMeasurements_vs_pt; + delete trackSummaryPlotCache.nOutliers_vs_pt; + delete trackSummaryPlotCache.nHoles_vs_pt; + delete trackSummaryPlotCache.nSharedHits_vs_pt; +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/ThreeStationTrackSeedTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/ThreeStationTrackSeedTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b9e53c66f50eb6f4974ca04fdbd7fa028f2954e3 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/ThreeStationTrackSeedTool.cxx @@ -0,0 +1,138 @@ +#include "FaserActsKalmanFilter/ThreeStationTrackSeedTool.h" +#include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "TrackerPrepRawData/FaserSCT_ClusterCollection.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "Identifier/Identifier.h" +#include "Acts/Geometry/GeometryIdentifier.hpp" + + +ThreeStationTrackSeedTool::ThreeStationTrackSeedTool( + const std::string& type, const std::string& name, const IInterface* parent) + : base_class(type, name, parent) {} + + +StatusCode ThreeStationTrackSeedTool::initialize() { + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + ATH_CHECK(detStore()->retrieve(m_detManager, "SCT")); + ATH_CHECK(m_trackingGeometryTool.retrieve()); + ATH_CHECK(m_trackCollection.initialize()); + ATH_CHECK(m_clusterContainerKey.initialize()); + return StatusCode::SUCCESS; +} + + +StatusCode ThreeStationTrackSeedTool::run() { + // create track seeds for multiple tracks + SG::ReadHandle<TrackCollection> trackCollection {m_trackCollection}; + ATH_CHECK(trackCollection.isValid()); + + SG::ReadHandle<Tracker::FaserSCT_ClusterContainer> clusterContainer {m_clusterContainerKey}; + ATH_CHECK(clusterContainer.isValid()); + + using IdentifierMap = std::map<Identifier, Acts::GeometryIdentifier>; + std::shared_ptr<IdentifierMap> identifierMap = m_trackingGeometryTool->getIdentifierMap(); + + const int kSize = 1; + using ThisMeasurement = Acts::Measurement<IndexSourceLink, Acts::BoundIndices, kSize>; + std::array<Acts::BoundIndices, kSize> Indices = {Acts::eBoundLoc0}; + std::vector<IndexSourceLink> sourceLinks; + std::vector<Measurement> measurements; + std::map<Index, Identifier> identifierLinkMap; + std::vector<const Tracker::FaserSCT_Cluster*> clusters {}; + for (const Tracker::FaserSCT_ClusterCollection* clusterCollection : *clusterContainer) { + for (const Tracker::FaserSCT_Cluster* cluster : *clusterCollection) { + Identifier id = cluster->detectorElement()->identify(); + identifierLinkMap[measurements.size()] = id; + if (identifierMap->count(id) != 0) { + Acts::GeometryIdentifier geoId = identifierMap->at(id); + IndexSourceLink sourceLink(geoId, measurements.size(), cluster); + // create measurement + const auto& par = cluster->localPosition(); + Eigen::Matrix<double, 1, 1> pos {par.x(),}; + Eigen::Matrix<double, 1, 1> cov {m_std_cluster * m_std_cluster,}; + ThisMeasurement meas(sourceLink, Indices, pos, cov); + sourceLinks.push_back(sourceLink); + measurements.emplace_back(std::move(meas)); + clusters.push_back(cluster); + } + } + } + + + std::map<int, std::vector<Amg::Vector3D>> station_position_map; + for (const Trk::Track* track : *trackCollection) { + auto momentum = track->trackParameters()->front()->momentum(); + ATH_MSG_DEBUG("track momentum: " << momentum.x() << ", " << momentum.y() << ", " << momentum.z()); + for (const Trk::TrackStateOnSurface* trackState : *(track->trackStateOnSurfaces())) { + auto clusterOnTrack = dynamic_cast<const Tracker::FaserSCT_ClusterOnTrack*> (trackState->measurementOnTrack()); + if (clusterOnTrack) { + Identifier id = clusterOnTrack->identify(); + int station = m_idHelper->station(id); + auto fitParameters = track->trackParameters()->front(); + Amg::Vector3D fitPosition = fitParameters->position(); + ATH_MSG_DEBUG("cluster position: " << fitPosition.x() << ", " << fitPosition.y() << ", " << fitPosition.z()); + station_position_map[station].push_back(fitPosition); + break; + } + } + } + + Acts::BoundSymMatrix cov = Acts::BoundSymMatrix::Zero(); + cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = m_covLoc0; + cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = m_covLoc1; + cov(Acts::eBoundPhi, Acts::eBoundPhi) = m_covPhi; + cov(Acts::eBoundTheta, Acts::eBoundTheta) = m_covTheta; + cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = m_covQOverP; + cov(Acts::eBoundTime, Acts::eBoundTime) = m_covTime; + + std::vector<Acts::CurvilinearTrackParameters> initParams {}; + for (const Amg::Vector3D& pos1 : station_position_map[1]) { + for (const Amg::Vector3D& pos2 : station_position_map[2]) { + for (const Amg::Vector3D& pos3 : station_position_map[3]) { + initParams.push_back(get_params(pos1, pos2, pos3, cov, m_origin)); + auto seed = initParams.back(); + auto seed_momentum = seed.momentum(); + } + } + } + + m_initialTrackParameters = std::make_shared<std::vector<Acts::CurvilinearTrackParameters>>(initParams); + m_sourceLinks = std::make_shared<std::vector<IndexSourceLink>>(sourceLinks); + m_idLinks = std::make_shared<IdentifierLink>(identifierLinkMap); + m_measurements = std::make_shared<std::vector<Measurement>>(measurements); + m_initialSurface = Acts::Surface::makeShared<Acts::PlaneSurface>( + Acts::Vector3 {0, 0, m_origin}, Acts::Vector3{0, 0, -1}); + m_clusters = std::make_shared<std::vector<const Tracker::FaserSCT_Cluster*>>(clusters); + + return StatusCode::SUCCESS; +} + + +StatusCode ThreeStationTrackSeedTool::finalize() { + return StatusCode::SUCCESS; +} + + +Acts::CurvilinearTrackParameters ThreeStationTrackSeedTool::get_params( + const Amg::Vector3D& position_st1, const Amg::Vector3D& position_st2, const Amg::Vector3D& position_st3, const Acts::BoundSymMatrix& cov, double origin) { + Acts::Vector3 dir = position_st2 - position_st1; + Acts::Vector3 pos = position_st1 - (position_st1.z() - origin)/dir.z() * dir; + Acts::Vector4 pos4 {pos.x(), pos.y(), pos.z(), 0}; + auto [abs_momenutm, charge] = momentum({{1, position_st1}, {2, position_st2}, {3, position_st3}}); + return Acts::CurvilinearTrackParameters(pos4, dir, abs_momenutm, charge, cov); +} +std::pair<double, double> ThreeStationTrackSeedTool::momentum(const std::map<int, Amg::Vector3D>& pos, double B) { + Acts::Vector3 vec_l = pos.at(3) - pos.at(1); + double abs_l = std::sqrt(vec_l.y() * vec_l.y() + vec_l.z() * vec_l.z()); + double t = (pos.at(2).z() - pos.at(1).z()) / (pos.at(3).z() - pos.at(1).z()); + Acts::Vector3 vec_m = pos.at(1) + t * vec_l; + Acts::Vector3 vec_s = pos.at(2) - vec_m; + double abs_s = std::sqrt(vec_s.y() * vec_s.y() + vec_s.z() * vec_s.z()); + double p_yz = 0.3 * abs_l * abs_l * B / (8 * abs_s * 1000); + double charge = vec_s.y() < 0 ? 1 : -1; + return std::make_pair(p_yz, charge); +} + + diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/TrackClassification.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/TrackClassification.cxx new file mode 100644 index 0000000000000000000000000000000000000000..3feae9515e6007f91ca0696e03c8151ebdb456ea --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/TrackClassification.cxx @@ -0,0 +1,66 @@ +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "FaserActsKalmanFilter/TrackClassification.h" + +namespace { + +/// Increase the hit count for the given particle id by one. +inline void increaseHitCount(std::vector<ParticleHitCount> &particleHitCounts, int particleId) { + // linear search since there is no ordering + auto it = std::find_if(particleHitCounts.begin(), particleHitCounts.end(), + [=](const ParticleHitCount &phc) { + return (phc.particleId == particleId); + }); + // either increase count if we saw the particle before or add it + if (it != particleHitCounts.end()) { + it->hitCount += 1u; + } else { + particleHitCounts.push_back({particleId, 1u}); + } +} + +/// Sort hit counts by decreasing values, i.e. majority particle comes first. +inline void sortHitCount(std::vector<ParticleHitCount> &particleHitCounts) { + std::sort(particleHitCounts.begin(), particleHitCounts.end(), + [](const ParticleHitCount &lhs, const ParticleHitCount &rhs) { + return (lhs.hitCount > rhs.hitCount); + }); +} + +} // namespace + + +/// Identify all particles that contribute to a trajectory. +void identifyContributingParticles( + const TrackerSimDataCollection& simDataCollection, + const FaserActsRecMultiTrajectory& trajectories, size_t tip, + std::vector<ParticleHitCount>& particleHitCounts) { + particleHitCounts.clear(); + + if (not trajectories.hasTrajectory(tip)) { + return; + } + + trajectories.multiTrajectory().visitBackwards(tip, [&](const auto& state) { + // no truth info with non-measurement state + if (not state.typeFlags().test(Acts::TrackStateFlag::MeasurementFlag)) { + return true; + } + // register all particles that generated this hit + Identifier id = state.uncalibrated().hit()->identify(); + if (simDataCollection.count(id) == 0) { + return true; + } + const auto& deposits = simDataCollection.find(id)->second.getdeposits(); + int barcode = 0; + float highestDep = 0; + for (const TrackerSimData::Deposit &deposit : deposits) { + if (deposit.second > highestDep) { + highestDep = deposit.second; + barcode = deposit.first->barcode(); + } + } + increaseHitCount(particleHitCounts, barcode); + return true; + }); + sortHitCount(particleHitCounts); +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/TrackFindingAlgorithmFunction.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/TrackFindingAlgorithmFunction.cxx index 954906a0f4263c6e17f17143b23d4639c5d1107a..44a86cbf06d0b10ae6aeca00bdd8bfd4e261d680 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/src/TrackFindingAlgorithmFunction.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/TrackFindingAlgorithmFunction.cxx @@ -6,94 +6,51 @@ #include "Acts/Propagator/Propagator.hpp" #include "Acts/TrackFitting/GainMatrixSmoother.hpp" #include "Acts/TrackFitting/GainMatrixUpdater.hpp" -#include "Acts/MagneticField/ConstantBField.hpp" -#include "Acts/MagneticField/InterpolatedBFieldMap.hpp" -#include "Acts/MagneticField/SharedBField.hpp" -#include <boost/variant/variant.hpp> -#include <boost/variant/apply_visitor.hpp> -#include <boost/variant/static_visitor.hpp> +namespace { using Updater = Acts::GainMatrixUpdater; using Smoother = Acts::GainMatrixSmoother; -using Stepper = Acts::EigenStepper<>; -using Propagator = Acts::Propagator<Stepper, Acts::Navigator>; - -namespace ActsExtrapolationDetail { - using VariantPropagatorBase = boost::variant< - Acts::Propagator<Acts::EigenStepper<>, Acts::Navigator>, - Acts::Propagator<Acts::EigenStepper<>, Acts::Navigator> - >; - - class VariantPropagator : public VariantPropagatorBase - { - public: - using VariantPropagatorBase::VariantPropagatorBase; - }; -} - -using ActsExtrapolationDetail::VariantPropagator; +using Stepper = Acts::EigenStepper<>; +using Navigator = Acts::Navigator; +using Propagator = Acts::Propagator<Stepper, Navigator>; +using CKF = Acts::CombinatorialKalmanFilter<Propagator, Updater, Smoother>; +using TrackParametersContainer = std::vector<CombinatorialKalmanFilterAlg::TrackParameters>; -template <typename TrackFinder> -struct TrackFinderFunctionImpl { - TrackFinder trackFinder; +struct TrackFinderFunctionImpl + : public CombinatorialKalmanFilterAlg::TrackFinderFunction { + CKF trackFinder; - TrackFinderFunctionImpl(TrackFinder&& f) : trackFinder(std::move(f)) {} + TrackFinderFunctionImpl(CKF&& f) : trackFinder(std::move(f)) {} CombinatorialKalmanFilterAlg::TrackFinderResult operator()( - const IndexSourceLinkContainer& sourceLinks, - const std::vector<Acts::CurvilinearTrackParameters>& initialParameters, - const CombinatorialKalmanFilterAlg::TrackFinderOptions& options) const - { - return trackFinder.findTracks(sourceLinks, initialParameters, options); - } + const IndexSourceLinkContainer& sourcelinks, + const TrackParametersContainer& initialParameters, + const CombinatorialKalmanFilterAlg::TrackFinderOptions& options) + const override { + return trackFinder.findTracks(sourcelinks, initialParameters, options); + }; }; +} // namespace -CombinatorialKalmanFilterAlg::TrackFinderFunction +std::shared_ptr<CombinatorialKalmanFilterAlg::TrackFinderFunction> CombinatorialKalmanFilterAlg::makeTrackFinderFunction( - std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry) -{ - const std::string fieldMode = "FASER"; - const std::vector<double> constantFieldVector = {0., 0., 0.55}; - - Acts::Navigator::Config cfg{trackingGeometry}; - cfg.resolvePassive = false; - cfg.resolveMaterial = true; - cfg.resolveSensitive = true; - Acts::Navigator navigator( cfg ); - - std::unique_ptr<ActsExtrapolationDetail::VariantPropagator> varProp; - - if (fieldMode == "FASER") { - auto bField = std::make_shared<FASERMagneticFieldWrapper>(); - auto stepper = Acts::EigenStepper<>(std::move(bField)); - auto propagator = Acts::Propagator<decltype(stepper), Acts::Navigator>(std::move(stepper), - std::move(navigator)); - varProp = std::make_unique<VariantPropagator>(propagator); - } - else if (fieldMode == "Constant") { - Acts::Vector3 constantFieldVector = Acts::Vector3(constantFieldVector[0], - constantFieldVector[1], - constantFieldVector[2]); - - auto bField = std::make_shared<Acts::ConstantBField>(constantFieldVector); - auto stepper = Acts::EigenStepper<>(std::move(bField)); - auto propagator = Acts::Propagator<decltype(stepper), Acts::Navigator>(std::move(stepper), - std::move(navigator)); - varProp = std::make_unique<VariantPropagator>(propagator); - } - - return boost::apply_visitor([&](const auto& propagator) -> TrackFinderFunction { - using Updater = Acts::GainMatrixUpdater; - using Smoother = Acts::GainMatrixSmoother; - using CKF = Acts::CombinatorialKalmanFilter<typename std::decay_t<decltype(propagator)>, Updater, Smoother>; - - CKF trackFinder(std::move(propagator)); - - return TrackFinderFunctionImpl<CKF>(std::move(trackFinder)); - }, *varProp); -} \ No newline at end of file + std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry, + bool resolvePassive, bool resolveMaterial, bool resolveSensitive) { + auto magneticField = std::make_shared<FASERMagneticFieldWrapper>(); + Stepper stepper(std::move(magneticField)); + Navigator::Config cfg{trackingGeometry}; + cfg.resolvePassive = resolvePassive; + cfg.resolveMaterial = resolveMaterial; + cfg.resolveSensitive = resolveSensitive; + Navigator navigator(cfg); + Propagator propagator(std::move(stepper), std::move(navigator)); + CKF trackFinder(std::move(propagator)); + + // build the track finder functions. owns the track finder object. + return std::make_shared<TrackFinderFunctionImpl>(std::move(trackFinder)); +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/TrackFittingFunction.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/TrackFittingFunction.cxx new file mode 100644 index 0000000000000000000000000000000000000000..0ece62669f80e7863a75b191a9fc7a51d759ca6c --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/TrackFittingFunction.cxx @@ -0,0 +1,118 @@ +#include "FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h" +#include "FaserActsGeometry/FASERMagneticFieldWrapper.h" + +#include "Acts/Propagator/EigenStepper.hpp" +#include "Acts/Propagator/Navigator.hpp" +#include "Acts/Propagator/Propagator.hpp" +#include "Acts/TrackFitting/GainMatrixSmoother.hpp" +#include "Acts/TrackFitting/GainMatrixUpdater.hpp" + + +namespace { + +using Updater = Acts::GainMatrixUpdater; +using Smoother = Acts::GainMatrixSmoother; +using Stepper = Acts::EigenStepper<>; +using Propagator = Acts::Propagator<Stepper, Acts::Navigator>; +using Fitter = Acts::KalmanFitter<Propagator, Updater, Smoother>; + +struct TrackFitterFunctionImpl + : public FaserActsKalmanFilterAlg::TrackFitterFunction { + Fitter trackFitter; + + TrackFitterFunctionImpl(Fitter &&f) : trackFitter(std::move(f)) {} + + FaserActsKalmanFilterAlg::TrackFitterResult operator()( + const std::vector<IndexSourceLink> &sourceLinks, + const FaserActsKalmanFilterAlg::TrackParameters &initialParameters, + const FaserActsKalmanFilterAlg::TrackFitterOptions &options) + const override { + return trackFitter.fit(sourceLinks, initialParameters, options); + }; +}; + +} // namespace + + +std::shared_ptr<FaserActsKalmanFilterAlg::TrackFitterFunction> +FaserActsKalmanFilterAlg::makeTrackFitterFunction( + std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry) { + auto magneticField = std::make_shared<FASERMagneticFieldWrapper>(); + auto stepper = Stepper(std::move(magneticField)); + Acts::Navigator::Config cfg{trackingGeometry}; + cfg.resolvePassive = false; + cfg.resolveMaterial = true; + cfg.resolveSensitive = true; + Acts::Navigator navigator(cfg); + Propagator propagator(std::move(stepper), std::move(navigator)); + Fitter trackFitter(std::move(propagator)); + return std::make_shared<TrackFitterFunctionImpl>(std::move(trackFitter)); +} + +/* + +namespace ActsExtrapolationDetail { +using VariantPropagatorBase = boost::variant< + Acts::Propagator<Acts::EigenStepper<>, Acts::Navigator>, + Acts::Propagator<Acts::EigenStepper<>, Acts::Navigator>>; + +class VariantPropagator : public VariantPropagatorBase { +public: + using VariantPropagatorBase::VariantPropagatorBase; +}; +} // namespace ActsExtrapolationDetail + + +namespace { +template <typename Fitter> +struct FitterFunctionImpl { + Fitter fitter; + FitterFunctionImpl(Fitter&& f) : fitter(std::move(f)) {} + FaserActsKalmanFilterAlg::TrackFitterResult operator()( + const std::vector<IndexSourceLink>& sourceLinks, + const Acts::CurvilinearTrackParameters& initialParameters, + const Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder, Acts::VoidReverseFilteringLogic>& options) const { + return fitter.fit(sourceLinks, initialParameters, options); + }; +}; +} // namespace + +std::shared_ptr<FaserActsKalmanFilterAlg::TrackFitterFunction> +FaserActsKalmanFilterAlg::makeTrackFitterFunction(std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry) { + + const std::string fieldMode = "FASER"; + const std::vector<double> constantFieldVector = {0., 0., 0.55}; + + Acts::Navigator::Config cfg{trackingGeometry}; + cfg.resolvePassive = false; + cfg.resolveMaterial = true; + cfg.resolveSensitive = true; + Acts::Navigator navigator( cfg ); + + std::unique_ptr<ActsExtrapolationDetail::VariantPropagator> varProp; + + if (fieldMode == "FASER") { + auto bField = std::make_shared<FASERMagneticFieldWrapper>(); + auto stepper = Acts::EigenStepper<>(std::move(bField)); + auto propagator = Acts::Propagator<decltype(stepper), + Acts::Navigator>(std::move(stepper), std::move(navigator)); + varProp = std::make_unique<ActsExtrapolationDetail::VariantPropagator>(propagator); + } else if (fieldMode == "Constant") { + Acts::Vector3 constantFieldVector = Acts::Vector3( + constantFieldVector[0], constantFieldVector[1], constantFieldVector[2]); + auto bField = std::make_shared<Acts::ConstantBField>(constantFieldVector); + auto stepper = Acts::EigenStepper<>(std::move(bField)); + auto propagator = Acts::Propagator<decltype(stepper), + Acts::Navigator>(std::move(stepper), std::move(navigator)); + varProp = std::make_unique<ActsExtrapolationDetail::VariantPropagator>(propagator); + } + + return boost::apply_visitor([&](const auto& propagator) -> TrackFitterFunction { + using Updater = Acts::GainMatrixUpdater; + using Smoother = Acts::GainMatrixSmoother; + using Fitter = Acts::KalmanFitter<typename std::decay_t<decltype(propagator)>, Updater, Smoother>; + Fitter fitter(std::move(propagator)); + return FitterFunctionImpl<Fitter>(std::move(fitter)); + }, *varProp); +} + */ diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/TrackSelection.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/TrackSelection.cxx new file mode 100644 index 0000000000000000000000000000000000000000..fdc77b13a95da4e89a7ff0c869f24e781d4ed7cc --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/TrackSelection.cxx @@ -0,0 +1,41 @@ +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "FaserActsKalmanFilter/TrackSelection.h" + +namespace { + +inline void sortTracks(std::vector<TrackQuality>& tracks) { + std::sort(tracks.begin(), tracks.end(), + [](const TrackQuality& lhs, const TrackQuality& rhs) { + if (lhs.nMeasurements != rhs.nMeasurements) { + return lhs.nMeasurements > rhs.nMeasurements; + } + return lhs.chi2 < rhs.chi2; + }); +} + +} // namespace + + +void selectTracks(TrackFinderResult& results, std::vector<TrackQuality>& trackQuality) { + for (auto& result : results) { + if (not result.ok()) { + continue; + } + auto& ckfResult = result.value(); + auto traj = FaserActsRecMultiTrajectory(ckfResult.fittedStates, ckfResult.lastMeasurementIndices, ckfResult.fittedParameters); + const auto& mj = traj.multiTrajectory(); + const auto& trackTips = traj.tips(); + auto it = std::max_element(trackTips.begin(), trackTips.end(), + [&](const size_t& lhs, const size_t& rhs) { + auto trajState_lhs = Acts::MultiTrajectoryHelpers::trajectoryState(mj, lhs); + auto trajState_rhs = Acts::MultiTrajectoryHelpers::trajectoryState(mj, rhs); + if (trajState_lhs.nMeasurements != trajState_rhs.nMeasurements) { + return trajState_lhs.nMeasurements > trajState_rhs.nMeasurements; + } + return trajState_lhs.chi2Sum < trajState_rhs.chi2Sum; + }); + auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, *it); + trackQuality.push_back({ckfResult, trajState.nMeasurements, trajState.chi2Sum}); + } + sortTracks(trackQuality); +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/TrajectoryWriterTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/TrajectoryWriterTool.cxx index aca7bd57a3df15bfbecffc5e6afb996daffb7020..55dfda762765da67bea84b219d5279ce0bf1a197 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/src/TrajectoryWriterTool.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/TrajectoryWriterTool.cxx @@ -1,3 +1,4 @@ +#include "TrackerPrepRawData/FaserSCT_Cluster.h" #include "FaserActsKalmanFilter/TrajectoryWriterTool.h" #include "FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h" #include "Acts/EventData/MultiTrajectoryHelpers.hpp" @@ -80,6 +81,15 @@ void TrajectoryWriterTool::initializeTree() { m_tree->Branch("g_x_fit" , &m_x_fit); m_tree->Branch("g_y_fit" , &m_y_fit); m_tree->Branch("g_z_fit" , &m_z_fit); + m_tree->Branch("lx_hit" , &m_lx_hit); + m_tree->Branch("ly_hit" , &m_ly_hit); + m_tree->Branch("x_hit" , &m_x_hit); + m_tree->Branch("y_hit" , &m_y_hit); + m_tree->Branch("z_hit" , &m_z_hit); + m_tree->Branch("meas_eLOC0" , &m_meas_eLOC0); + m_tree->Branch("meas_eLOC1" , &m_meas_eLOC1); + m_tree->Branch("meas_cov_eLOC0" , &m_meas_cov_eLOC0); + m_tree->Branch("meas_cov_eLOC1" , &m_meas_cov_eLOC1); m_tree->Branch("nPredicted", &m_nPredicted); m_tree->Branch("predicted", &m_prt); @@ -228,7 +238,10 @@ void TrajectoryWriterTool::writeout(TrajectoriesContainer trajectories, m_eta_ini.push_back(eta(initialparameters[iTraj].position(geoContext))); // The trajectory entry indices and the multiTrajectory - const auto& [trackTips, mj] = traj.trajectory(); + // const auto& [trackTips, mj] = traj.multiTrajectory(); + const auto& mj = traj.multiTrajectory(); + const auto& trackTips = traj.tips(); + if (trackTips.empty()) { ATH_MSG_WARNING("Empty multiTrajectory."); m_nMeasurements = -1; @@ -308,11 +321,16 @@ void TrajectoryWriterTool::writeout(TrajectoriesContainer trajectories, // extract local and global position Acts::Vector2 local(meas[Acts::eBoundLoc0], meas[Acts::eBoundLoc1]); -const Acts::Vector3 dir = Acts::makeDirectionUnitFromPhiTheta(meas[Acts::eBoundPhi], meas[Acts::eBoundTheta]); + const Acts::Vector3 dir = Acts::makeDirectionUnitFromPhiTheta(meas[Acts::eBoundPhi], meas[Acts::eBoundTheta]); Acts::Vector3 mom(1, 1, 1); Acts::Vector3 global = surface.localToGlobal(geoContext, local, dir); + m_meas_eLOC0.push_back(state.calibrated()[Acts::eBoundLoc0]); + m_meas_eLOC1.push_back(state.calibrated()[Acts::eBoundLoc1]); + m_meas_cov_eLOC0.push_back(state.calibratedCovariance()(Acts::eBoundLoc0, Acts::eBoundLoc0)); + m_meas_cov_eLOC1.push_back(state.calibratedCovariance()(Acts::eBoundLoc1, Acts::eBoundLoc1)); + // fill the measurement info m_lx_hit.push_back(local[Acts::ePos0]); m_ly_hit.push_back(local[Acts::ePos1]); @@ -340,15 +358,15 @@ const Acts::Vector3 dir = Acts::makeDirectionUnitFromPhiTheta(meas[Acts::eBoundP /// Predicted residual m_res_eLOC0_prt.push_back(residual(Acts::eBoundLoc0)); - m_res_eLOC1_prt.push_back(residual(Acts::eBoundLoc1)); +// m_res_eLOC1_prt.push_back(residual(Acts::eBoundLoc1)); /// Predicted parameter pulls m_pull_eLOC0_prt.push_back( residual(Acts::eBoundLoc0) / sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_pull_eLOC1_prt.push_back( - residual(Acts::eBoundLoc1) / - sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); +// m_pull_eLOC1_prt.push_back( +// residual(Acts::eBoundLoc1) / +// sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); /// Predicted parameter m_eLOC0_prt.push_back(parameter.parameters()[Acts::eBoundLoc0]); @@ -429,15 +447,15 @@ const Acts::Vector3 dir = Acts::makeDirectionUnitFromPhiTheta(meas[Acts::eBoundP /// Filtered residual m_res_eLOC0_flt.push_back(residual(Acts::eBoundLoc0)); - m_res_eLOC1_flt.push_back(residual(Acts::eBoundLoc1)); +// m_res_eLOC1_flt.push_back(residual(Acts::eBoundLoc1)); /// Filtered parameter pulls m_pull_eLOC0_flt.push_back( residual(Acts::eBoundLoc0) / sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_pull_eLOC1_flt.push_back( - residual(Acts::eBoundLoc1) / - sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); +// m_pull_eLOC1_flt.push_back( +// residual(Acts::eBoundLoc1) / +// sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); /// Filtered parameter m_eLOC0_flt.push_back(parameter.parameters()[Acts::eBoundLoc0]); @@ -520,30 +538,30 @@ const Acts::Vector3 dir = Acts::makeDirectionUnitFromPhiTheta(meas[Acts::eBoundP auto residual = state.effectiveCalibrated() - H * state.smoothed(); m_res_x_hit.push_back(residual(Acts::eBoundLoc0)); - m_res_y_hit.push_back(residual(Acts::eBoundLoc1)); +// m_res_y_hit.push_back(residual(Acts::eBoundLoc1)); m_err_x_hit.push_back( sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_err_y_hit.push_back( - sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); +// m_err_y_hit.push_back( +// sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); m_pull_x_hit.push_back( residual(Acts::eBoundLoc0) / sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_pull_y_hit.push_back( - residual(Acts::eBoundLoc1) / - sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); +// m_pull_y_hit.push_back( +// residual(Acts::eBoundLoc1) / +// sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); m_dim_hit.push_back(state.calibratedSize()); /// Smoothed residual m_res_eLOC0_smt.push_back(residual(Acts::eBoundLoc0)); - m_res_eLOC1_smt.push_back(residual(Acts::eBoundLoc1)); +// m_res_eLOC1_smt.push_back(residual(Acts::eBoundLoc1)); /// Smoothed parameter pulls m_pull_eLOC0_smt.push_back( residual(Acts::eBoundLoc0) / sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_pull_eLOC1_smt.push_back( - residual(Acts::eBoundLoc1) / - sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); +// m_pull_eLOC1_smt.push_back( +// residual(Acts::eBoundLoc1) / +// sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1))); /// Smoothed parameter m_eLOC0_smt.push_back(parameter.parameters()[Acts::eBoundLoc0]); @@ -638,6 +656,10 @@ void TrajectoryWriterTool::clearVariables() const { m_x_hit.clear(); m_y_hit.clear(); m_z_hit.clear(); + m_meas_eLOC0.clear(); + m_meas_eLOC1.clear(); + m_meas_cov_eLOC0.clear(); + m_meas_cov_eLOC1.clear(); m_res_x_hit.clear(); m_res_y_hit.clear(); m_err_x_hit.clear(); diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/TruthBasedInitialParameterTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/TruthBasedInitialParameterTool.cxx index 85b1036e415fb3f28f9f6b8ee37679afb60304bd..f5b850d8a05877b9d7d48db65faadbff7cfac519 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/src/TruthBasedInitialParameterTool.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/TruthBasedInitialParameterTool.cxx @@ -51,8 +51,6 @@ Acts::CurvilinearTrackParameters TruthBasedInitialParameterTool::getInitialParam } } - std::cout << "?? px = " << momentum.x() << " py = " << momentum.y() << " pz = " << momentum.z() << std::endl; - Acts::Vector3 truthVertex = {vertex.x(), vertex.y(), vertex.z()}; // in mm Acts::Vector3 truthMomentum = {momentum.x() / 1000, momentum.y() / 1000, momentum.z() / 1000}; // in GeV m_simWriterTool->writeout(truthVertex, truthMomentum); diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/TruthSeededTrackFinderTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/TruthSeededTrackFinderTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4a574ee970e5dc9ccc67dcdd94143b2df20d1114 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/TruthSeededTrackFinderTool.cxx @@ -0,0 +1,252 @@ +#include "FaserActsKalmanFilter/TruthSeededTrackFinderTool.h" + +#include "Acts/Definitions/TrackParametrization.hpp" +#include "Acts/EventData/Measurement.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Surfaces/PlaneSurface.hpp" +#include "Acts/Surfaces/RectangleBounds.hpp" +#include "Acts/Surfaces/Surface.hpp" +#include "FaserActsKalmanFilter/IndexSourceLink.h" +#include "GeoPrimitives/CLHEPtoEigenConverter.h" +#include "Identifier/Identifier.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "TrackerReadoutGeometry/SiDetectorElement.h" +#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" +#include "TrackerSpacePoint/SpacePointForSeed.h" +#include <array> +#include <random> + + +TruthSeededTrackFinderTool::TruthSeededTrackFinderTool( + const std::string& type, const std::string& name, const IInterface* parent) : + base_class(type, name, parent) {} + + +StatusCode TruthSeededTrackFinderTool::initialize() { + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + ATH_CHECK(detStore()->retrieve(m_detManager, "SCT")); + ATH_CHECK(m_spacePointCollectionKey.initialize()); + ATH_CHECK(m_mcEventCollectionKey.initialize()); + ATH_CHECK(m_trackingGeometryTool.retrieve()); + return StatusCode::SUCCESS; +} + + +StatusCode TruthSeededTrackFinderTool::run() { +// SG::ReadHandle<FaserSiHitCollection> siHitCollection {m_siHitCollectionKey}; +// ATH_CHECK(siHitCollection.isValid()); +// ATH_MSG_DEBUG("Read FaserSiHitCollection with " << siHitCollection->size() << " hits"); + + using IdentifierMap = std::map<Identifier, Acts::GeometryIdentifier>; + std::shared_ptr<IdentifierMap> identifierMap = m_trackingGeometryTool->getIdentifierMap(); + + SG::ReadHandle<SpacePointForSeedCollection> spacePointCollection {m_spacePointCollectionKey}; + ATH_CHECK(spacePointCollection.isValid()); + + Acts::GeometryContext geoctx = m_trackingGeometryTool->getNominalGeometryContext().context(); + + std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry + = m_trackingGeometryTool->trackingGeometry(); + + const int kSize = 2; + using ThisMeasurement = Acts::Measurement<IndexSourceLink, Acts::BoundIndices, kSize>; + std::array<Acts::BoundIndices, kSize> myIndices = {Acts::eBoundLoc0, Acts::eBoundLoc1}; + + std::map<int, Acts::Vector3> spacePoints; + + std::vector<IndexSourceLink> sourcelinks; + std::vector<Measurement> measurements; + + for (const SpacePointForSeed* sp : *spacePointCollection) { + const Tracker::FaserSCT_SpacePoint* spacePoint = sp->SpacePoint(); + Identifier id = spacePoint->associatedSurface().associatedDetectorElementIdentifier(); + Acts::GeometryIdentifier geoId = identifierMap->at(id); + // const Acts::Surface *surface = m_trackingGeometryTool->trackingGeometry()->findSurface(geoId); + + auto par = spacePoint->localParameters(); + ATH_MSG_DEBUG("par " << par); + auto cov = spacePoint->localCovariance(); + ATH_MSG_DEBUG("cov " << cov); + ATH_MSG_DEBUG(cov(0, 0) << ", " << cov(0, 1) << ", " << cov(1, 0) << ", " << cov(1, 1)); + Acts::ActsSymMatrix<2> myCov = Acts::ActsSymMatrix<2>::Zero(); + myCov(0, 0) = m_covMeas00; + myCov(1, 1) = m_covMeas11; + myCov(0, 1) = m_covMeas01; + myCov(1, 0) = m_covMeas10; + + IndexSourceLink sourceLink(geoId, measurements.size()); + ThisMeasurement meas(sourceLink, myIndices, par, myCov); + sourcelinks.push_back(sourceLink); + measurements.emplace_back(std::move(meas)); + + Amg::Vector3D globalPosition = spacePoint->globalPosition(); + int station = m_idHelper->station(id); + int layer = m_idHelper->layer(id); + // TODO check if map already contains a space point for this layer + spacePoints[3*(station-1) + layer] = Acts::Vector3(globalPosition.x(), globalPosition.y(), globalPosition.z()); + + if (station == 1 && layer == 0) { + const TrackerDD::SiDetectorElement *element = m_detManager->getDetectorElement(id); + // Construct a plane surface as the target surface + const TrackerDD::SiDetectorDesign &design = element->design(); + double hlX = design.width()/2. * 1_mm; + double hlY = design.length()/2. * 1_mm; + auto rectangleBounds = std::make_shared<const Acts::RectangleBounds>(hlX, hlY); + Amg::Transform3D g2l = element->getMaterialGeom()->getDefAbsoluteTransform() + * Amg::CLHEPTransformToEigen(element->recoToHitTransform()); + m_initialSurface = Acts::Surface::makeShared<Acts::PlaneSurface>(g2l, rectangleBounds); + } + } + + // check if there is atleast one space point in each station + + if (map2vector(spacePoints, 1).empty() || map2vector(spacePoints, 2).empty() || map2vector(spacePoints, 0).empty()) { + return StatusCode::RECOVERABLE; + } + + Acts::Vector4 smearedPosition4; + Acts::Vector3 smearedDirection; + double smearedAbsoluteMomentum; + double charge; + if (m_useTrueInitialParameters) { + // get initial parameters from generated particle + SG::ReadHandle<McEventCollection> mcEventCollection {m_mcEventCollectionKey}; + ATH_CHECK(mcEventCollection.isValid()); + for (const HepMC::GenEvent* event : *mcEventCollection) { + for (const HepMC::GenParticle* particle : event->particle_range()) { + const HepMC::FourVector& momentum = particle->momentum(); + double abs_momentum = momentum.rho() * Acts::UnitConstants::MeV; + Acts::Vector3 direction = Acts::Vector3(momentum.x(), momentum.y(), momentum.z()); + const HepMC::FourVector vertex = particle->production_vertex()->position(); + charge = particle->pdg_id() > 0 ? -1 : 1; + + std::random_device rd; + std::default_random_engine rng {rd()}; + std::normal_distribution<> norm; + + auto theta = Acts::VectorHelpers::theta(direction); + auto phi = Acts::VectorHelpers::phi(direction); + auto angles = Acts::detail::normalizePhiTheta( + phi + m_sigmaPhi * norm(rng), + theta + m_sigmaTheta * norm(rng)); + smearedDirection = Acts::Vector3( + std::sin(angles.second) * std::cos(angles.first), + std::sin(angles.second) * std::sin(angles.first), + std::cos(angles.second)); + smearedAbsoluteMomentum = abs_momentum * (1 + m_sigmaP * norm(rng)); + + smearedPosition4 = Acts::Vector4(vertex.x() + m_sigmaLoc0 * norm(rng), vertex.y() + m_sigmaLoc1 * norm(rng), vertex.z(), 0); + } + } + } else { + // get initial parameters from track seed + auto [p, q] = momentum2(spacePoints); + double abs_momentum = p; + charge = q; + Acts::Vector3 initPos {0, 0, 0}; + if (spacePoints.count(0)) { + initPos = spacePoints.at(0); + } else { + ATH_MSG_ERROR("Could not find space point on first layer"); + } + smearedPosition4 = Acts::Vector4(initPos.x(), initPos.y(), initPos.z(), 0); + + auto [pos1, dir1] = linear_fit(map2vector(spacePoints, 1)); + auto [pos2, dir2] = linear_fit(map2vector(spacePoints, 2)); + smearedDirection = pos2 - pos1; +// smearedDirection = dir; + smearedAbsoluteMomentum = p; + } + + Acts::BoundSymMatrix cov = Acts::BoundSymMatrix::Zero(); + cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = m_covLoc0; + cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = m_covLoc1; + cov(Acts::eBoundPhi, Acts::eBoundPhi) = m_covPhi; + cov(Acts::eBoundTheta, Acts::eBoundTheta) = m_covTheta; + cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = m_covQOverP; + cov(Acts::eBoundTime, Acts::eBoundTime) = m_covTime; + + // auto initialParameters = Acts::BoundTrackParameters(surface->getSharedPtr(), params, charge, cov); + auto initialParameters = Acts::CurvilinearTrackParameters( + smearedPosition4, smearedDirection, smearedAbsoluteMomentum, charge, cov); + + // write out + double initialCharge = initialParameters.charge(); + double initialAbsoluteMomentum = initialParameters.absoluteMomentum(); + Acts::Vector3 initialPosition = initialParameters.position(geoctx); + Acts::Vector3 initialMomentum = initialParameters.momentum(); + ATH_MSG_DEBUG("initial charge: " << initialCharge); + ATH_MSG_DEBUG("initial absolute momentum: " << initialAbsoluteMomentum); + ATH_MSG_DEBUG("initial position: x=" << initialPosition.x() << ", y=" << initialPosition.y() << ", z=" << initialPosition.z()); + ATH_MSG_DEBUG("initial momentum: x=" << initialMomentum.x() << ", y=" << initialMomentum.y() << ", z=" << initialMomentum.z()); + m_initialTrackParameters = std::make_shared<const Acts::CurvilinearTrackParameters>(initialParameters); + + m_sourceLinks = std::make_shared<std::vector<IndexSourceLink>>(sourcelinks); + m_measurements = std::make_shared<std::vector<Measurement>>(measurements); + + return StatusCode::SUCCESS; +} + +StatusCode TruthSeededTrackFinderTool::finalize() { + return StatusCode::SUCCESS; +} + +Acts::Vector3 TruthSeededTrackFinderTool::average(const std::vector<Acts::Vector3>& spacePoints) { + Acts::Vector3 ret {0, 0, 0}; + if (!spacePoints.empty()) { + for (const Acts::Vector3& spacePoint : spacePoints) { + ret += spacePoint; + } + ret /= spacePoints.size(); + } + return ret; +} + +std::pair<Acts::Vector3, Acts::Vector3> +TruthSeededTrackFinderTool::linear_fit(const std::vector<Acts::Vector3>& hits) { + size_t n_hits = hits.size(); + Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> centers(n_hits, 3); + for (size_t i = 0; i < n_hits; ++i) centers.row(i) = hits[i]; + + Acts::Vector3 origin = centers.colwise().mean(); + Eigen::MatrixXd centered = centers.rowwise() - origin.transpose(); + Eigen::MatrixXd cov = centered.adjoint() * centered; + Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eig(cov); + Acts::Vector3 axis = eig.eigenvectors().col(2).normalized(); + + return std::make_pair(origin, axis); +} + + +std::vector<Acts::Vector3> +TruthSeededTrackFinderTool::map2vector(const std::map<int, Acts::Vector3>& map, int station) { + std::vector<Acts::Vector3> vec; + for (int layer = station * 3; layer < station * 3 + 3; ++layer) { + if (map.count(layer)) { + vec.push_back(map.at(layer)); + } + } + return vec; +} + + +std::pair<double, double> TruthSeededTrackFinderTool::momentum2(const std::map<int, Acts::Vector3>& hits, double B) { + Acts::Vector3 pos1 = average(map2vector(hits, 0)); + Acts::Vector3 pos2 = average(map2vector(hits, 1)); + Acts::Vector3 pos3 = average(map2vector(hits, 2)); + + Acts::Vector3 vec_l = pos3 - pos1; + double abs_l = std::sqrt(vec_l.y() * vec_l.y() + vec_l.z() * vec_l.z()); + double t = (pos2.z() - pos1.z()) / (pos3.z() - pos1.z()); + Acts::Vector3 vec_m = pos1 + t * vec_l; + Acts::Vector3 vec_s = pos2 - vec_m; + double abs_s = std::sqrt(vec_s.y() * vec_s.y() + vec_s.z() * vec_s.z()); + double p_yz = 0.3 * abs_l * abs_l * B / (8 * abs_s * 1000); // in GeV + // double charge = vec_s.y() < 0 ? 1 : -1; + double charge = 1; + + return std::make_pair(p_yz, charge); +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/TruthTrackFinderTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/TruthTrackFinderTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..16882021e4babed59f3a52030a565411290eb9ac --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/TruthTrackFinderTool.cxx @@ -0,0 +1,191 @@ +#include "FaserActsKalmanFilter/TruthTrackFinderTool.h" + +#include "Acts/Definitions/TrackParametrization.hpp" +#include "Acts/EventData/Measurement.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Surfaces/Surface.hpp" +#include "FaserActsKalmanFilter/IndexSourceLink.h" +#include "GeoPrimitives/CLHEPtoEigenConverter.h" +#include "Identifier/Identifier.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "TrackerReadoutGeometry/SiDetectorElement.h" +#include <array> +#include <random> + + +TruthTrackFinderTool::TruthTrackFinderTool(const std::string& type, const std::string& name, const IInterface* parent) + : base_class(type, name, parent) {} + + +StatusCode TruthTrackFinderTool::initialize() { + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + ATH_CHECK(detStore()->retrieve(m_detManager, "SCT")); + ATH_CHECK(m_siHitCollectionKey.initialize()); + ATH_CHECK(m_trackingGeometryTool.retrieve()); + return StatusCode::SUCCESS; +} + + +StatusCode TruthTrackFinderTool::run() { + SG::ReadHandle<FaserSiHitCollection> siHitCollection {m_siHitCollectionKey}; + ATH_CHECK(siHitCollection.isValid()); + ATH_MSG_DEBUG("Read FaserSiHitCollection with " << siHitCollection->size() << " hits"); + + std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry + = m_trackingGeometryTool->trackingGeometry(); + + using IdentifierMap = std::map<Identifier, Acts::GeometryIdentifier>; + std::shared_ptr<IdentifierMap> identifierMap = m_trackingGeometryTool->getIdentifierMap(); + Acts::GeometryContext gctx = m_trackingGeometryTool->getNominalGeometryContext().context(); + const int kSize = 2; + using ParametersVector = Acts::ActsVector<kSize>; + using CovarianceMatrix = Acts::ActsSymMatrix<kSize>; + using ThisMeasurement = Acts::Measurement<IndexSourceLink, Acts::BoundIndices, kSize>; + std::array<Acts::BoundIndices, kSize> myIndices = {Acts::eBoundLoc0, Acts::eBoundLoc1}; + + std::vector<IndexSourceLink> sourcelinks; + std::vector<Measurement> measurements; + + std::vector<Acts::GeometryIdentifier> geoIds = {}; + int station, layer, phi, eta, side; + for (const FaserSiHit &hit: *siHitCollection) { + if (!hit.particleLink() or std::abs(hit.particleLink()->pdg_id()) != 13) { + continue; + } + + station = hit.getStation(); + layer = hit.getPlane(); + phi = hit.getRow(); + eta = hit.getModule(); + side = hit.getSensor(); + + if (side == 0) { + continue; + } + + ATH_MSG_DEBUG(station << "/" << layer << "/" << phi << "/" << eta << "/" << side); + + Identifier id = m_idHelper->wafer_id(station, layer, phi, eta, side); + // TODO check if there can be multiple simulated muon hits in the same wafer + // currently I take the first hit in each wafer + Acts::GeometryIdentifier geoId = identifierMap->at(id); + if (std::find(geoIds.begin(), geoIds.end(), geoId) != geoIds.end()) { + continue; + } + geoIds.push_back(geoId); + ATH_MSG_DEBUG(geoIds); + + auto momentum = hit.particleLink()->momentum(); + double abs_momentum = momentum.rho() * Acts::UnitConstants::MeV; + double QOverP = 1 / abs_momentum; + auto direction = Acts::Vector3(momentum.x(), momentum.y(), momentum.z()).normalized(); + + const TrackerDD::SiDetectorElement *element = m_detManager->getDetectorElement(id); + + // create source links and measurements + const Acts::Surface *surface = m_trackingGeometryTool->trackingGeometry()->findSurface(geoId); + if (surface == nullptr) { + ATH_MSG_FATAL("Could not find surface"); + continue; + } + + const HepGeom::Point3D<double> localStartPos = hit.localStartPosition(); + if (element) { + const HepGeom::Point3D<double> globalStartPos = + Amg::EigenTransformToCLHEP(element->transformHit()) * HepGeom::Point3D<double>(localStartPos); + auto center = surface->center(gctx); + Acts::Vector3 position = {globalStartPos.x(), globalStartPos.y(), center.z()}; + Acts::Result<Acts::BoundVector> boundParamsRes + = Acts::detail::transformFreeToBoundParameters(position, hit.meanTime(), direction, QOverP, *surface, gctx); + if (!boundParamsRes.ok()) { + ATH_MSG_FATAL("Could not construct bound parameters"); + return StatusCode::FAILURE; + } + const auto &boundParams = boundParamsRes.value(); + ATH_MSG_DEBUG(boundParams[0] << ", " << boundParams[1]); + + std::random_device rd; + std::default_random_engine rng {rd()}; + std::normal_distribution<> norm; + + ParametersVector smearedBoundParams = { + boundParams[0] + norm(rng) * m_sigma0, boundParams[1] + norm(rng) * m_sigma1}; + + ParametersVector par = ParametersVector::Zero(); + par[0] = smearedBoundParams[0]; + par[1] = smearedBoundParams[1]; + + ATH_MSG_DEBUG("bound parameters: par0=" << boundParams[0] << ", par1=" << boundParams[1]); + ATH_MSG_DEBUG("smeared parameters: par0=" << smearedBoundParams[0] << ", par1=" << smearedBoundParams[1]); + + CovarianceMatrix cov = CovarianceMatrix::Zero(); + cov(0, 0) = std::max(m_covMeasLoc0.value(), m_sigma0 * m_sigma0); + cov(1, 1) = std::max(m_covMeasLoc1.value(), m_sigma1 * m_sigma1); + + IndexSourceLink sourceLink(geoId, measurements.size()); + sourcelinks.emplace_back(sourceLink); + ThisMeasurement meas(sourceLink, myIndices, par, cov); + measurements.emplace_back(std::move(meas)); + + // create initial parameters from hit in first layer + if ((station == m_first_station) && (layer == m_first_layer) && (side == m_first_side)) { + + // smear initial direction + auto theta = Acts::VectorHelpers::theta(direction); + auto phi = Acts::VectorHelpers::phi(direction); + auto angles = Acts::detail::normalizePhiTheta( + phi + m_sigmaPhi * M_PI/180. * norm(rng), + theta + m_sigmaTheta * M_PI/180. * norm(rng)); + Acts::Vector3 smearedDirection( + std::sin(angles.second) * std::cos(angles.first), + std::sin(angles.second) * std::sin(angles.first), + std::cos(angles.second)); + double smearedAbsoluteMomentum = abs_momentum * (1 + m_sigmaP * norm(rng)); + + double z_init = 0; + m_initialSurface = Acts::Surface::makeShared<Acts::PlaneSurface>(Acts::Vector3 {0, 0, z_init}, Acts::Vector3{0, 0, 1}); + + // extrapolate position on first layer to initial position + // TODO use first layer as initial layer instead? + Acts::Vector3 initPosition = position + (z_init - position.z()) / direction.z() * direction; + Acts::Vector3 smearedPosition {initPosition.x() + m_sigmaLoc0 * norm(rng), initPosition.y() + m_sigmaLoc1 * norm(rng), initPosition.z()}; + Acts::Vector4 smearedPosition4 {smearedPosition.x(), smearedPosition.y(), smearedPosition.z(), 0}; + double charge = hit.particleLink()->pdg_id() > 0 ? -1 : 1; + + Acts::BoundSymMatrix cov = Acts::BoundSymMatrix::Zero(); + cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = m_covLoc0; + cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = m_covLoc1; + cov(Acts::eBoundPhi, Acts::eBoundPhi) = m_covPhi; + cov(Acts::eBoundTheta, Acts::eBoundTheta) = m_covTheta; + cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = m_covQOverP; + cov(Acts::eBoundTime, Acts::eBoundTime) = m_covTime; + + // auto initialParameters = Acts::BoundTrackParameters(surface->getSharedPtr(), params, charge, cov); + auto initialParameters = Acts::CurvilinearTrackParameters(smearedPosition4, smearedDirection, smearedAbsoluteMomentum, charge, cov); + + // write out + double initialCharge = initialParameters.charge(); + double initialAbsoluteMomentum = initialParameters.absoluteMomentum(); + Acts::Vector3 initialPosition = initialParameters.position(gctx); + Acts::Vector3 initialMomentum = initialParameters.momentum(); + ATH_MSG_DEBUG("initial charge: " << initialCharge); + ATH_MSG_DEBUG("initial absolute momentum: " << initialAbsoluteMomentum); + ATH_MSG_DEBUG("initial position: x=" << initialPosition.x() << ", y=" << initialPosition.y() << ", z=" << initialPosition.z()); + ATH_MSG_DEBUG("initial momentum: x=" << initialMomentum.x() << ", y=" << initialMomentum.y() << ", z=" << initialMomentum.z()); + m_initialTrackParameters = std::make_shared<const Acts::CurvilinearTrackParameters>(initialParameters); + } + } + } + + m_sourceLinks = std::make_shared<std::vector<IndexSourceLink>>(sourcelinks); + m_measurements = std::make_shared<std::vector<Measurement>>(measurements); + + return StatusCode::SUCCESS; +} + +StatusCode TruthTrackFinderTool::finalize() { + return StatusCode::SUCCESS; +} \ No newline at end of file diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx index 0b86d895fdd266b4df4bb9ba6ecb3b928581c9db..0a79b99832495297ac3a3ebd419a1134c8f3a9e3 100755 --- a/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx @@ -2,19 +2,41 @@ Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration */ -//#include "FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h" +#include "FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h" #include "FaserActsKalmanFilter/CombinatorialKalmanFilterAlg.h" -#include "FaserActsKalmanFilter/TruthBasedInitialParameterTool.h" -#include "FaserActsKalmanFilter/SPSeedBasedInitialParameterTool.h" -#include "FaserActsKalmanFilter/SPSimpleInitialParameterTool.h" -#include "FaserActsKalmanFilter/TrajectoryWriterTool.h" -#include "FaserActsKalmanFilter/SimWriterTool.h" +//#include "FaserActsKalmanFilter/MultiTrackFinderTool.h" +//#include "FaserActsKalmanFilter/TruthBasedInitialParameterTool.h" +//#include "FaserActsKalmanFilter/TruthTrackFinderTool.h" +//#include "FaserActsKalmanFilter/SPSeedBasedInitialParameterTool.h" +//#include "FaserActsKalmanFilter/SPSimpleInitialParameterTool.h" +//#include "FaserActsKalmanFilter/TrajectoryWriterTool.h" +//#include "FaserActsKalmanFilter/SimWriterTool.h" +//#include "FaserActsKalmanFilter/TruthSeededTrackFinderTool.h" +//#include "FaserActsKalmanFilter/ProtoTrackWriterTool.h" +#include "FaserActsKalmanFilter/RootTrajectoryStatesWriterTool.h" +#include "FaserActsKalmanFilter/RootTrajectorySummaryWriterTool.h" +//#include "FaserActsKalmanFilter/SegmentFitClusterTrackFinderTool.h" +//#include "FaserActsKalmanFilter/SegmentFitTrackFinderTool.h" +//#include "FaserActsKalmanFilter/ClusterTrackSeedTool.h" +#include "FaserActsKalmanFilter/ThreeStationTrackSeedTool.h" +#include "FaserActsKalmanFilter/PerformanceWriterTool.h" -//DECLARE_COMPONENT(FaserActsKalmanFilterAlg) +DECLARE_COMPONENT(FaserActsKalmanFilterAlg) DECLARE_COMPONENT(CombinatorialKalmanFilterAlg) -DECLARE_COMPONENT(TruthBasedInitialParameterTool) -DECLARE_COMPONENT(SPSeedBasedInitialParameterTool) -DECLARE_COMPONENT(SPSimpleInitialParameterTool) -DECLARE_COMPONENT(TrajectoryWriterTool) -DECLARE_COMPONENT(SimWriterTool) +//DECLARE_COMPONENT(TruthBasedInitialParameterTool) +//DECLARE_COMPONENT(SPSeedBasedInitialParameterTool) +//DECLARE_COMPONENT(SPSimpleInitialParameterTool) +//DECLARE_COMPONENT(TrajectoryWriterTool) +//DECLARE_COMPONENT(TruthTrackFinderTool) +//DECLARE_COMPONENT(SimWriterTool) +//DECLARE_COMPONENT(TruthSeededTrackFinderTool) +//DECLARE_COMPONENT(ProtoTrackWriterTool) +//DECLARE_COMPONENT(SegmentFitClusterTrackFinderTool) +//DECLARE_COMPONENT(SegmentFitTrackFinderTool) +DECLARE_COMPONENT(RootTrajectoryStatesWriterTool) +DECLARE_COMPONENT(RootTrajectorySummaryWriterTool) +//DECLARE_COMPONENT(MultiTrackFinderTool) +//DECLARE_COMPONENT(ClusterTrackSeedTool) +DECLARE_COMPONENT(ThreeStationTrackSeedTool) +DECLARE_COMPONENT(PerformanceWriterTool) diff --git a/Tracking/Acts/FaserActsKalmanFilter/test/CombinatorialKalmanFilterAlg.py b/Tracking/Acts/FaserActsKalmanFilter/test/CombinatorialKalmanFilterAlg.py index eef29095e39bc064e2dde11149be503b0d0d79ea..887c03812bce040d5cdf43f0559a499cbbe02b89 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/test/CombinatorialKalmanFilterAlg.py +++ b/Tracking/Acts/FaserActsKalmanFilter/test/CombinatorialKalmanFilterAlg.py @@ -9,20 +9,19 @@ from CalypsoConfiguration.MainServicesConfig import MainServicesCfg from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg # from AthenaPoolCnvSvc.PoolWriteConfig import PoolWriteCfg from TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg -from TrackerSpacePointFormation.TrackerSpacePointFormationConfig import TrackerSpacePointFinderCfg -from TrackerSeedFinder.TrackerSeedFinderConfig import TrackerSeedFinderCfg +from TrackerSegmentFit.TrackerSegmentFitConfig import SegmentFitAlgCfg from FaserActsKalmanFilter.CombinatorialKalmanFilterConfig import CombinatorialKalmanFilterCfg log.setLevel(DEBUG) Configurable.configurableRun3Behavior = True ConfigFlags.Input.Files = ['my.RDO.pool.root'] -ConfigFlags.Output.ESDFileName = "myCKF.ESD.pool.root" -ConfigFlags.Output.AODFileName = "myCKF.AOD.pool.root" +ConfigFlags.Output.ESDFileName = "CKF.ESD.pool.root" ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" -# ConfigFlags.GeoModel.FaserVersion = "FASER-01" +ConfigFlags.GeoModel.FaserVersion = "FASER-01" ConfigFlags.GeoModel.Align.Dynamic = False ConfigFlags.Beam.NumberOfCollisions = 0. +# ConfigFlags.TrackingGeometry.MaterialSource = "Input" ConfigFlags.lock() acc = MainServicesCfg(ConfigFlags) @@ -30,9 +29,9 @@ acc.merge(PoolReadCfg(ConfigFlags)) # acc.merge(PoolWriteCfg(ConfigFlags)) acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags)) -acc.merge(TrackerSpacePointFinderCfg(ConfigFlags)) -acc.merge(TrackerSeedFinderCfg(ConfigFlags)) +acc.merge(SegmentFitAlgCfg(ConfigFlags)) acc.merge(CombinatorialKalmanFilterCfg(ConfigFlags)) +# acc.getEventAlgo("CombinatorialKalmanFilterAlg").OutputLevel = VERBOSE # logging.getLogger('forcomps').setLevel(INFO) # acc.foreach_component("*").OutputLevel = INFO @@ -42,6 +41,5 @@ acc.merge(CombinatorialKalmanFilterCfg(ConfigFlags)) # acc.printConfig(withDetails=True) # ConfigFlags.dump() -sc = acc.run(maxEvents=1000) - +sc = acc.run(maxEvents=-1) sys.exit(not sc.isSuccess()) diff --git a/Tracking/Acts/FaserActsKalmanFilter/test/FaserActsKalmanFilterAlg.py b/Tracking/Acts/FaserActsKalmanFilter/test/FaserActsKalmanFilterAlg.py index 06975170f670f0fe8dec65b9a2d608aea6fc4c36..b2efe5323cf53e0220925994ab7b2d544462f81e 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/test/FaserActsKalmanFilterAlg.py +++ b/Tracking/Acts/FaserActsKalmanFilter/test/FaserActsKalmanFilterAlg.py @@ -11,6 +11,7 @@ from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg from AthenaPoolCnvSvc.PoolWriteConfig import PoolWriteCfg from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg from TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg +from TrackerSegmentFit.TrackerSegmentFitConfig import SegmentFitAlgCfg from TrackerSpacePointFormation.TrackerSpacePointFormationConfig import TrackerSpacePointFinderCfg from TruthSeededTrackFinder.TruthSeededTrackFinderConfig import TruthSeededTrackFinderCfg from FaserActsKalmanFilter.FaserActsKalmanFilterConfig import FaserActsKalmanFilterCfg @@ -20,9 +21,10 @@ log.setLevel(DEBUG) Configurable.configurableRun3Behavior = True # Configure -ConfigFlags.Input.Files = ['my.RDO.pool.root'] -ConfigFlags.Output.ESDFileName = "tmp.root" -ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" # Always needed; must match FaserVersion +ConfigFlags.Input.Files = ['../my.RDO.pool.root'] +ConfigFlags.Output.ESDFileName = "FaserActsKalmanFilter.ESD.root" +ConfigFlags.Output.AODFileName = "FaserActsKalmanFilter.AOD.pool.root" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" ConfigFlags.GeoModel.Align.Dynamic = False ConfigFlags.Beam.NumberOfCollisions = 0. #ConfigFlags.Concurrency.NumThreads = 1 @@ -34,20 +36,20 @@ acc.merge(PoolReadCfg(ConfigFlags)) # Inner Detector acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags)) -acc.merge(TrackerSpacePointFinderCfg(ConfigFlags)) -acc.merge(TruthSeededTrackFinderCfg(ConfigFlags)) +acc.merge(SegmentFitAlgCfg(ConfigFlags)) +# acc.merge(TrackerSpacePointFinderCfg(ConfigFlags)) +# acc.merge(TruthSeededTrackFinderCfg(ConfigFlags)) acc.merge(FaserActsKalmanFilterCfg(ConfigFlags)) +acc.getEventAlgo("FaserActsKalmanFilterAlg").OutputLevel = DEBUG -logging.getLogger('forcomps').setLevel(VERBOSE) -acc.foreach_component("*").OutputLevel = VERBOSE -acc.foreach_component("*ClassID*").OutputLevel = INFO -acc.getService("StoreGateSvc").Dump = True -acc.getService("ConditionStore").Dump = True -acc.printConfig(withDetails=True) -ConfigFlags.dump() +# logging.getLogger('forcomps').setLevel(VERBOSE) +# acc.foreach_component("*").OutputLevel = VERBOSE +# acc.foreach_component("*ClassID*").OutputLevel = INFO +# acc.getService("StoreGateSvc").Dump = True +# acc.getService("ConditionStore").Dump = True +# acc.printConfig(withDetails=True) +# ConfigFlags.dump() # Execute and finish -sc = acc.run(maxEvents=-1) - -# Success should be 0 +sc = acc.run(maxEvents=1000) sys.exit(not sc.isSuccess()) diff --git a/Tracking/Acts/FaserActsKalmanFilter/test/TI12KalmanFilter.py b/Tracking/Acts/FaserActsKalmanFilter/test/TI12KalmanFilter.py new file mode 100644 index 0000000000000000000000000000000000000000..11b7e4217bed8400426f4257ef5cf43f5b7adbfd --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/test/TI12KalmanFilter.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +import sys +from AthenaCommon.Logging import log, logging +from AthenaCommon.Constants import DEBUG, VERBOSE, INFO +from AthenaCommon.Configurable import Configurable +from CalypsoConfiguration.AllConfigFlags import ConfigFlags +from AthenaConfiguration.TestDefaults import defaultTestFiles +from CalypsoConfiguration.MainServicesConfig import MainServicesCfg +from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg +from AthenaPoolCnvSvc.PoolWriteConfig import PoolWriteCfg +from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg +from FaserByteStreamCnvSvc.FaserByteStreamCnvSvcConfig import FaserByteStreamCnvSvcCfg +from TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg +from TrackerSegmentFit.TrackerSegmentFitConfig import SegmentFitAlgCfg +from TrackerSpacePointFormation.TrackerSpacePointFormationConfig import TrackerSpacePointFinderCfg +from FaserActsKalmanFilter.FaserActsKalmanFilterConfig import FaserActsKalmanFilterCfg + + +log.setLevel(DEBUG) +Configurable.configurableRun3Behavior = True + +# Configure +ConfigFlags.Input.Files = ['/home/tboeckh/tmp/Faser-Physics-006470-00093.raw_middleStation.SPs'] +ConfigFlags.Output.ESDFileName = "MiddleStation-KalmanFilter.ESD.pool.root" +ConfigFlags.Output.AODFileName = "MiddleStation-KalmanFilter.AOD.pool.root" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" +ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" +ConfigFlags.Input.ProjectName = "data21" +ConfigFlags.Input.isMC = False +ConfigFlags.GeoModel.FaserVersion = "FASER-02" +ConfigFlags.Common.isOnline = False +ConfigFlags.GeoModel.Align.Dynamic = False +ConfigFlags.Beam.NumberOfCollisions = 0. +ConfigFlags.Detector.GeometryFaserSCT = True +ConfigFlags.lock() + +# Core components +acc = MainServicesCfg(ConfigFlags) +acc.merge(FaserByteStreamCnvSvcCfg(ConfigFlags)) +acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags, name="LevelClustering", DataObjectName="SCT_LEVELMODE_RDOs", ClusterToolTimingPattern="X1X")) +acc.merge(SegmentFitAlgCfg(ConfigFlags, name=f"LevelFit", MaxClusters=44)) +# acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags)) +# acc.merge(SegmentFitAlgCfg(ConfigFlags)) +# acc.merge(TrackerSpacePointFinderCfg(ConfigFlags)) +acc.merge(FaserActsKalmanFilterCfg(ConfigFlags)) +acc.getEventAlgo("FaserActsKalmanFilterAlg").OutputLevel = DEBUG + +replicaSvc = acc.getService("DBReplicaSvc") +replicaSvc.COOLSQLiteVetoPattern = "" +replicaSvc.UseCOOLSQLite = True +replicaSvc.UseCOOLFrontier = False +replicaSvc.UseGeomSQLite = True + + +# logging.getLogger('forcomps').setLevel(VERBOSE) +# acc.foreach_component("*").OutputLevel = VERBOSE +# acc.foreach_component("*ClassID*").OutputLevel = INFO +# acc.getService("StoreGateSvc").Dump = True +# acc.getService("ConditionStore").Dump = True +# acc.printConfig(withDetails=True) +# ConfigFlags.dump() + +# Execute and finish +sc = acc.run(maxEvents=-1) +sys.exit(not sc.isSuccess()) diff --git a/Tracking/Acts/FaserActsKalmanFilter/test/TI12_CKF.py b/Tracking/Acts/FaserActsKalmanFilter/test/TI12_CKF.py new file mode 100644 index 0000000000000000000000000000000000000000..98acb56f00ace95d54277726768250e9543b06ab --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/test/TI12_CKF.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +import sys +from AthenaCommon.Logging import log, logging +from AthenaCommon.Constants import DEBUG, VERBOSE, INFO +from AthenaCommon.Configurable import Configurable +from CalypsoConfiguration.AllConfigFlags import ConfigFlags +from CalypsoConfiguration.MainServicesConfig import MainServicesCfg +from FaserByteStreamCnvSvc.FaserByteStreamCnvSvcConfig import FaserByteStreamCnvSvcCfg +from TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg +from TrackerSegmentFit.TrackerSegmentFitConfig import SegmentFitAlgCfg +from FaserActsKalmanFilter.CombinatorialKalmanFilterConfig import CombinatorialKalmanFilterCfg + +log.setLevel(DEBUG) +Configurable.configurableRun3Behavior = True + +ConfigFlags.Input.Files = ['/home/tboeckh/tmp/Faser-Physics-006470-00093.raw_middleStation.SPs'] +ConfigFlags.Output.ESDFileName = "CKF.ESD.pool.root" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" +ConfigFlags.GeoModel.FaserVersion = "FASER-02" +ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" +ConfigFlags.Input.ProjectName = "data21" +ConfigFlags.Input.isMC = False +ConfigFlags.Common.isOnline = False +ConfigFlags.GeoModel.Align.Dynamic = False +ConfigFlags.Beam.NumberOfCollisions = 0. +ConfigFlags.Detector.GeometryFaserSCT = True +ConfigFlags.lock() + +acc = MainServicesCfg(ConfigFlags) +acc.merge(FaserByteStreamCnvSvcCfg(ConfigFlags)) +acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags, name="LevelClustering", DataObjectName="SCT_LEVELMODE_RDOs", ClusterToolTimingPattern="X1X")) +acc.merge(SegmentFitAlgCfg(ConfigFlags, name=f"LevelFit", MaxClusters=44)) +# acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags, DataObjectName="SCT_RDOs", ClusterToolTimingPattern="XXX")) +# acc.merge(SegmentFitAlgCfg(ConfigFlags)) +acc.merge(CombinatorialKalmanFilterCfg(ConfigFlags)) +acc.getEventAlgo("CombinatorialKalmanFilterAlg").OutputLevel = VERBOSE + +replicaSvc = acc.getService("DBReplicaSvc") +replicaSvc.COOLSQLiteVetoPattern = "" +replicaSvc.UseCOOLSQLite = True +replicaSvc.UseCOOLFrontier = False +replicaSvc.UseGeomSQLite = True + +logging.getLogger('forcomps').setLevel(VERBOSE) +acc.foreach_component("*").OutputLevel = VERBOSE +acc.foreach_component("*ClassID*").OutputLevel = INFO +acc.getCondAlgo("FaserSCT_AlignCondAlg").OutputLevel = VERBOSE +acc.getCondAlgo("FaserSCT_DetectorElementCondAlg").OutputLevel = VERBOSE +acc.getService("StoreGateSvc").Dump = True +acc.getService("ConditionStore").Dump = True +acc.printConfig(withDetails=True) +ConfigFlags.dump() + +sc = acc.run(maxEvents=-1) +sys.exit(not sc.isSuccess())