diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_emi_100GeV-101104.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_emi_100GeV-101104.json index 6a457b299df5ab13110546ef453fd19e84880f60..89db76d6fba6ce5ffccb44cd3fc960118d86376e 100644 --- a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_emi_100GeV-101104.json +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_emi_100GeV-101104.json @@ -1,5 +1,5 @@ { - "file_length": 100, + "file_length": 200, "mass": 0.511, "maxE": 100.0, "minE": 100.0, diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_epl_100GeV-101103.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_epl_100GeV-101103.json index 02de3383c115c56eb3c327d23394809a1c0d912b..83c73af03df03cbbfdbb9da2f21d2e7fa879054e 100644 --- a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_epl_100GeV-101103.json +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_epl_100GeV-101103.json @@ -1,5 +1,5 @@ { - "file_length": 100, + "file_length": 200, "mass": 0.511, "maxE": 100.0, "minE": 100.0, diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_gam_100GeV-102201.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_gam_100GeV-102201.json index 11b14b31451de987fce19c7d7c3fa86fb2a94f45..2068c13e2f1c98aaedde8b3a24bf2e6278f13d69 100644 --- a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_gam_100GeV-102201.json +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_gam_100GeV-102201.json @@ -1,5 +1,5 @@ { - "file_length": 100, + "file_length": 200, "mass": 0.0, "maxE": 100.0, "minE": 100.0, diff --git a/Generators/DIFGenerator/python/DIFSampler.py b/Generators/DIFGenerator/python/DIFSampler.py index 69fe82660a4b9d9ae555799d2a8f76dbca5629c6..8ec22459aba93a430093c4bd7b2a3f13e2d0f206 100644 --- a/Generators/DIFGenerator/python/DIFSampler.py +++ b/Generators/DIFGenerator/python/DIFSampler.py @@ -5,7 +5,7 @@ import ParticleGun as PG from math import sqrt, sin, cos, acos from random import uniform -from AthenaCommon.SystemOfUnits import TeV, MeV +from AthenaCommon.SystemOfUnits import TeV, GeV, MeV from AthenaCommon.PhysicalConstants import pi from ROOT import TLorentzVector @@ -90,8 +90,12 @@ class DIFSampler(PG.ParticleSampler): else: self.mom = None - def __init__(self, daughter1_pid = 11, daughter2_pid = -11, mother_pid = None, mother_mom = PG.EThetaMPhiSampler(sqrt((1*TeV)**2 + (10*MeV)**2),0,10*MeV,0),mother_pos = CylinderSampler([0, 100**2],[0, 2*pi],[-1500, 0],0)): - self._mother_sampler = PG.ParticleSampler(pid = mother_pid, mom = mother_mom, pos = mother_pos) + # def __init__(self, daughter1_pid = 11, daughter2_pid = -11, mother_pid = None, mother_mom = PG.EThetaMPhiSampler(sqrt((1*TeV)**2 + (10*MeV)**2),0,10*MeV,0),mother_pos = CylinderSampler([0, 100**2],[0, 2*pi],[-1500, 0],0)): + def __init__(self, daughter1_pid=13, daughter2_pid=-13, mother_pid=None, + mother_mom=PG.EThetaMPhiSampler(sqrt((1*TeV)**2 + (500*MeV)**2), [0, 0.0002], 500*MeV, [0, 2*pi]), + my_z_position=-1500): + # mother_pos=CylinderSampler([0, 100**2], [0, 2*pi], [-1500, 0], 0)): + self._mother_sampler = PG.ParticleSampler(pid = mother_pid, mom = mother_mom, pos=CylinderSampler([0, 100**2], [0, 2*pi], my_z_position, 0)) self.daughter1 = self.particle(daughter1_pid) self.daughter2 = self.particle(daughter2_pid) diff --git a/Generators/FaserParticleGun/python/FaserParticleGunConfig.py b/Generators/FaserParticleGun/python/FaserParticleGunConfig.py index 866a51beeca0107b71df42a165dfd54537450829..ac30494a4815f5bb06a5d67408b4c0551297a63b 100644 --- a/Generators/FaserParticleGun/python/FaserParticleGunConfig.py +++ b/Generators/FaserParticleGun/python/FaserParticleGunConfig.py @@ -190,7 +190,8 @@ def FaserParticleGunForeseeCfg(ConfigFlags, **kwargs) : return cfg def FaserParticleGunCfg(ConfigFlags) : - generator = ConfigFlags.Sim.Gun.setdefault("Generator", "SingleParticle") + # generator = ConfigFlags.Sim.Gun.setdefault("Generator", "SingleParticle") + generator = ConfigFlags.Sim.Gun.setdefault("Generator", "DecayInFlight") kwargs = ConfigFlags.Sim.Gun if generator == "SingleEcalParticle" : return FaserParticleGunSingleEcalParticleCfg(ConfigFlags, **kwargs) diff --git a/Tracker/TrackerRecAlgs/FaserSpacePoints/CMakeLists.txt b/Tracker/TrackerRecAlgs/FaserSpacePoints/CMakeLists.txt index 4978495c385798463bd84f20276920cdde578765..e88d445536b1770103382549c17e502e4f5f8b09 100644 --- a/Tracker/TrackerRecAlgs/FaserSpacePoints/CMakeLists.txt +++ b/Tracker/TrackerRecAlgs/FaserSpacePoints/CMakeLists.txt @@ -1,12 +1,9 @@ -################################################################################ -# Package: FaserSpacePoints -################################################################################ +atlas_subdir(FaserSpacePoints) -# Declare the package name: -atlas_subdir( FaserSpacePoints ) +atlas_add_component( + FaserSpacePoints + src/components/*.cxx src/*.cxx src/*.h + LINK_LIBRARIES AthenaBaseComps TrackerSimData TrackerSimEvent TrackerSpacePoint TrackerPrepRawData) -atlas_add_component( FaserSpacePoints - src/components/*.cxx src/*.cxx src/*.h - LINK_LIBRARIES AthenaBaseComps TrackerSpacePoint TrackerPrepRawData) - -atlas_install_python_modules( python/*.py ) \ No newline at end of file +atlas_install_python_modules( python/*.py ) +atlas_install_scripts( test/*.py ) diff --git a/Tracker/TrackerRecAlgs/FaserSpacePoints/python/FaserSpacePointsConfig.py b/Tracker/TrackerRecAlgs/FaserSpacePoints/python/FaserSpacePointsConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..36a2008a833453937a2adf9c4c1c2f3d81525362 --- /dev/null +++ b/Tracker/TrackerRecAlgs/FaserSpacePoints/python/FaserSpacePointsConfig.py @@ -0,0 +1,17 @@ +""" +Copyright (C) 2021 CERN for the benefit of the FASER collaboration +""" + +from AthenaConfiguration.ComponentFactory import CompFactory +from FaserSCT_GeoModel.FaserSCT_GeoModelConfig import FaserSCT_GeometryCfg + + +def FaserSpacePointsCfg(flags, **kwargs): + acc = FaserSCT_GeometryCfg(flags) + Tracker__FaserSpacePoints = CompFactory.Tracker.FaserSpacePoints + acc.addEventAlgo(Tracker__FaserSpacePoints(**kwargs)) + + thistSvc = CompFactory.THistSvc() + thistSvc.Output += ["HIST DATAFILE='SpacePoints.root' OPT='RECREATE'"] + acc.addService(thistSvc) + return acc diff --git a/Tracker/TrackerRecAlgs/FaserSpacePoints/python/FaserSpacePointsCosmics.py b/Tracker/TrackerRecAlgs/FaserSpacePoints/python/FaserSpacePointsCosmics.py index 48197207d0c1b321e658b74ddb2d40d74ee244dd..78bae901d8c5319dd35ad4f101ff5cb291740395 100644 --- a/Tracker/TrackerRecAlgs/FaserSpacePoints/python/FaserSpacePointsCosmics.py +++ b/Tracker/TrackerRecAlgs/FaserSpacePoints/python/FaserSpacePointsCosmics.py @@ -22,7 +22,6 @@ Tracker__TruthSeededTrackFinder, THistSvc=CompFactory.getComps("Tracker::FaserSp def TruthSeededTrackFinderBasicCfg(flags, **kwargs): """Return ComponentAccumulator for TruthSeededTrackFinder""" acc = FaserSCT_GeometryCfg(flags) - kwargs.setdefault("SpacePointsSCTName", "SCT_SpacePointContainer") acc.addEventAlgo(Tracker__TruthSeededTrackFinder(**kwargs)) # attach ToolHandles return acc diff --git a/Tracker/TrackerRecAlgs/FaserSpacePoints/src/FaserSpacePoints.cxx b/Tracker/TrackerRecAlgs/FaserSpacePoints/src/FaserSpacePoints.cxx index b9722a7c2f4318fd6d8e4cf2c76437ced6078d8e..caa4af80a79286b6bdb76e18754541f7ee498568 100644 --- a/Tracker/TrackerRecAlgs/FaserSpacePoints/src/FaserSpacePoints.cxx +++ b/Tracker/TrackerRecAlgs/FaserSpacePoints/src/FaserSpacePoints.cxx @@ -1,104 +1,128 @@ #include "FaserSpacePoints.h" #include "Identifier/Identifier.h" +#include "TrackerSimEvent/FaserSiHit.h" #include "TrackerSpacePoint/FaserSCT_SpacePoint.h" #include "TrackerPrepRawData/FaserSCT_ClusterCollection.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" + namespace Tracker { - FaserSpacePoints::FaserSpacePoints(const std::string& name, ISvcLocator* pSvcLocator) - : AthReentrantAlgorithm(name, pSvcLocator) { } - - StatusCode FaserSpacePoints::initialize() { - ATH_MSG_INFO(name() << "::" << __FUNCTION__); +FaserSpacePoints::FaserSpacePoints(const std::string& name, ISvcLocator* pSvcLocator) + : AthReentrantAlgorithm(name, pSvcLocator), AthHistogramming(name), + m_histSvc("THistSvc/THistSvc", name) {} + + +StatusCode FaserSpacePoints::initialize() { + ATH_CHECK(m_spacePointContainerKey.initialize()); + ATH_CHECK(m_siHitCollectionKey.initialize()); + ATH_CHECK(m_simDataCollectionKey.initialize()); + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + ATH_CHECK(detStore()->retrieve(m_detMgr, "SCT")); + m_tree = new TTree("tree", "tree"); + m_tree->Branch("run", &m_run, "run/I"); + m_tree->Branch("event", &m_event, "event/I"); + m_tree->Branch("station", &m_station, "station/I"); + m_tree->Branch("layer", &m_layer, "layer/I"); + m_tree->Branch("phi", &m_phi, "phi/I"); + m_tree->Branch("eta", &m_eta, "eta/I"); + m_tree->Branch("side", &m_side, "side/I"); + m_tree->Branch("x", &m_x, "x/D"); + m_tree->Branch("y", &m_y, "y/D"); + m_tree->Branch("z", &m_z, "z/D"); + m_tree->Branch("muon_hit", &m_muon_hit, "muon_hit/B"); + m_tree->Branch("tx", &m_tx, "tx/D"); + m_tree->Branch("ty", &m_ty, "ty/D"); + m_tree->Branch("tz", &m_tz, "tz/D"); + ATH_CHECK(histSvc()->regTree("/HIST/spacePoints", m_tree)); + return StatusCode::SUCCESS; +} - if ( m_sct_spcontainer.key().empty()) { - ATH_MSG_FATAL( "SCTs selected and no name set for SCT clusters"); - return StatusCode::FAILURE; - } - ATH_CHECK( m_sct_spcontainer.initialize() ); - ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); +StatusCode FaserSpacePoints::finalize() { + return StatusCode::SUCCESS; +} - std::string filePath = m_filePath; - 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(); +bool FaserSpacePoints::muon_hit(const TrackerSimDataCollection* simDataMap, Identifier id) const { + // check if Identifier in simDataMap + if (!simDataMap->count(id)) { + return false; + } + // check if hit originates from a muon (if the pdg code of the hit is -13) + TrackerSimData simData = simDataMap->at(id); + const std::vector<TrackerSimData::Deposit>& deposits = simData.getdeposits(); + auto it = std::find_if( + deposits.begin(), deposits.end(), [](TrackerSimData::Deposit deposit) { + return deposit.first->pdg_id() == -13; + }); + return it != deposits.end(); +} - std::string treeName = m_treeName; - m_outputTree = new TTree(treeName.c_str(), "tree"); - if (m_outputTree == nullptr) { - ATH_MSG_ERROR("Unable to create TTree"); - return StatusCode::FAILURE; - } +StatusCode FaserSpacePoints::execute(const EventContext& ctx) const { + m_run = ctx.eventID().run_number(); + m_event = ctx.eventID().event_number(); - FaserSpacePoints::initializeTree(); - return StatusCode::SUCCESS; - } + SG::ReadHandle<FaserSCT_SpacePointContainer> spacePointContainer {m_spacePointContainerKey, ctx}; + ATH_CHECK(spacePointContainer.isValid()); - - StatusCode FaserSpacePoints::finalize() { - ATH_MSG_INFO(name() << "::" << __FUNCTION__); - m_outputFile->cd(); - m_outputTree->Write(); - return StatusCode::SUCCESS; - } + SG::ReadHandle<FaserSiHitCollection> siHitCollection {m_siHitCollectionKey, ctx}; + ATH_CHECK(siHitCollection.isValid()); + + SG::ReadHandle<TrackerSimDataCollection> simDataCollection {m_simDataCollectionKey, ctx}; + ATH_CHECK(simDataCollection.isValid()); - - StatusCode FaserSpacePoints::execute(const EventContext& ctx) const { - ATH_MSG_INFO(name() << "::" << __FUNCTION__); - - m_run = ctx.eventID().run_number(); - m_event = ctx.eventID().event_number(); - ATH_MSG_DEBUG("run = " << m_run); - ATH_MSG_DEBUG("event = " << m_event); - - SG::ReadHandle<FaserSCT_SpacePointContainer> sct_spcontainer( m_sct_spcontainer, ctx ); - if (!sct_spcontainer.isValid()){ - ATH_MSG_FATAL("Could not find the data object " << sct_spcontainer.name()); - return StatusCode::RECOVERABLE; + + // create map of the IdentifierHash of a SCT sensor and the true position of the corresponding hit + std::map<IdentifierHash, HepGeom::Point3D<double>> truePositions; + for (const FaserSiHit& hit: *siHitCollection) { + if ((!hit.particleLink()) || (hit.particleLink()->pdg_id() != -13)) { + continue; + } + Identifier waferId = m_idHelper->wafer_id(hit.getStation(), hit.getPlane(), hit.getRow(), hit.getModule(), hit.getSensor()); + IdentifierHash waferHash = m_idHelper->wafer_hash(waferId); + const HepGeom::Point3D<double> localPosition = hit.localStartPosition(); + const TrackerDD::SiDetectorElement* element = m_detMgr->getDetectorElement(waferId); + if (element) { + const HepGeom::Point3D<double> globalPosition = + Amg::EigenTransformToCLHEP(element->transformHit()) * localPosition; + truePositions[waferHash] = globalPosition; } + } + - m_nCollections = sct_spcontainer->size(); - ATH_MSG_DEBUG("nCollections = " << m_nCollections); - FaserSCT_SpacePointContainer::const_iterator it = sct_spcontainer->begin(); - FaserSCT_SpacePointContainer::const_iterator it_end = sct_spcontainer->end(); - - for(; it != it_end; ++it) { - const FaserSCT_SpacePointCollection* col = *it; - m_nSpacepoints = col->size(); - ATH_MSG_DEBUG("nSpacepoints = " << m_nSpacepoints); - - FaserSCT_SpacePointCollection::const_iterator it_sp = col->begin(); - FaserSCT_SpacePointCollection::const_iterator it_sp_end = col->end(); - for (; it_sp != it_sp_end; ++it_sp) { - const FaserSCT_SpacePoint* sp = *it_sp; - const auto id = sp->clusterList().first->identify(); - int station = m_idHelper->station(id); - int plane = m_idHelper->layer(id); - m_layer = (station - 1) * 3 + plane; - - Amg::Vector3D position = sp->globalPosition(); - m_x = position.x(); - m_y = position.y(); - m_z = position.z(); - - m_outputTree->Fill(); + for (const FaserSCT_SpacePointCollection* spacePointCollection : *spacePointContainer) { + for (const FaserSCT_SpacePoint* spacePoint : *spacePointCollection) { + Identifier id1 = spacePoint->cluster1()->identify(); + Identifier id2 = spacePoint->cluster2()->identify(); + m_station = m_idHelper->station(id1); + m_layer = m_idHelper->layer(id1); + m_phi = m_idHelper->phi_module(id1); + m_eta = m_idHelper->eta_module(id1); + m_side = m_idHelper->side(id1); + // check if both clusters originate from a muon + m_muon_hit = (muon_hit(simDataCollection.get(), id1) && muon_hit(simDataCollection.get(), id2)); + // global reconstructed position of space point + Amg::Vector3D position = spacePoint->globalPosition(); + m_x = position.x(); + m_y = position.y(); + m_z = position.z(); + // global true position of simulated hit + IdentifierHash waferHash = spacePoint->elementIdList().first; + if (truePositions.count(waferHash)) { + auto truePosition = truePositions[waferHash]; + m_tx = truePosition.x(); + m_ty = truePosition.y(); + m_tz = truePosition.z(); + } else { + m_tx = -1; + m_ty = -1; + m_tz = -1; } + m_tree->Fill(); } - return StatusCode::SUCCESS; } + return StatusCode::SUCCESS; +} - void FaserSpacePoints::initializeTree() { - m_outputTree->Branch("run", &m_run); - m_outputTree->Branch("event", &m_event); - m_outputTree->Branch("layer", &m_layer); - m_outputTree->Branch("n_collections", &m_nCollections); - m_outputTree->Branch("n_spacepoints", &m_nSpacepoints); - m_outputTree->Branch("x", &m_x); - m_outputTree->Branch("y", &m_y); - m_outputTree->Branch("z", &m_z); - } } diff --git a/Tracker/TrackerRecAlgs/FaserSpacePoints/src/FaserSpacePoints.h b/Tracker/TrackerRecAlgs/FaserSpacePoints/src/FaserSpacePoints.h index 28807d73e7ac7939c5b830a758846028feedb815..1cc43f65e2f1a674b692487a26421ad526b466f3 100644 --- a/Tracker/TrackerRecAlgs/FaserSpacePoints/src/FaserSpacePoints.h +++ b/Tracker/TrackerRecAlgs/FaserSpacePoints/src/FaserSpacePoints.h @@ -2,45 +2,70 @@ #define FASERSPACEPOINTS_H #include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "AthenaBaseComps/AthHistogramming.h" #include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerSimEvent/FaserSiHitCollection.h" #include "TrackerSpacePoint/FaserSCT_SpacePointContainer.h" +#include "TrackerSimData/TrackerSimDataCollection.h" #include <string> #include <atomic> #include "TTree.h" #include "TFile.h" +class FaserSCT_ID; +namespace TrackerDD { +class SCT_DetectorManager; +} + + namespace Tracker { - class FaserSpacePoints : public AthReentrantAlgorithm { - public: - FaserSpacePoints(const std::string& name, ISvcLocator* pSvcLocator); - virtual ~FaserSpacePoints() = default; - - virtual StatusCode initialize() override; - virtual StatusCode execute(const EventContext& ctx) const override; - virtual StatusCode finalize() override; - - private: - void initializeTree(); - - mutable int m_run{0}; - mutable int m_event{0}; - mutable int m_layer{0}; - mutable int m_nCollections{0}; - mutable int m_nSpacepoints{0}; - mutable float m_x{0}; - mutable float m_y{0}; - mutable float m_z{0}; - - const FaserSCT_ID* m_idHelper{nullptr}; - SG::ReadHandleKey<FaserSCT_SpacePointContainer> m_sct_spcontainer{this, "SpacePointsSCTName", "SCT spacepoint container"}; - - Gaudi::Property<std::string> m_filePath{this, "FilePath", "spacepoints.root", "Output root file for spacepoints"}; - Gaudi::Property<std::string> m_treeName{this, "TreeName", "tree", ""}; - - TFile* m_outputFile; - TTree* m_outputTree; - }; + +class FaserSpacePoints : public AthReentrantAlgorithm, AthHistogramming { + public: + FaserSpacePoints(const std::string& name, ISvcLocator* pSvcLocator); + virtual ~FaserSpacePoints() = default; + + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& ctx) const override; + virtual StatusCode finalize() override; + + const ServiceHandle<ITHistSvc>& histSvc() const; + + private: + const FaserSCT_ID* m_idHelper{nullptr}; + const TrackerDD::SCT_DetectorManager* m_detMgr {nullptr}; + bool muon_hit(const TrackerSimDataCollection* simDataMap, Identifier id) const; + ServiceHandle<ITHistSvc> m_histSvc; + + SG::ReadHandleKey<FaserSCT_SpacePointContainer> m_spacePointContainerKey { + this, "SpacePoints", "SCT_SpacePointContainer"}; + SG::ReadHandleKey<FaserSiHitCollection> m_siHitCollectionKey { + this, "FaserSiHitCollection", "SCT_Hits"}; + SG::ReadHandleKey<TrackerSimDataCollection> m_simDataCollectionKey { + this, "TrackerSimDataCollection", "SCT_SDO_Map"}; + + mutable TTree* m_tree; + mutable int m_run {0}; + mutable int m_event {0}; + mutable int m_station {0}; + mutable int m_layer {0}; + mutable int m_phi {0}; + mutable int m_eta {0}; + mutable int m_side {0}; + mutable double m_x {0}; + mutable double m_y {0}; + mutable double m_z {0}; + mutable bool m_muon_hit {false}; + mutable double m_tx {0}; + mutable double m_ty {0}; + mutable double m_tz {0}; +}; + +inline const ServiceHandle<ITHistSvc>& FaserSpacePoints::histSvc() const { + return m_histSvc; +} + } #endif // FASERSPACEPOINTS_H diff --git a/Tracker/TrackerRecAlgs/FaserSpacePoints/test/FaserSpacePointsDbg.py b/Tracker/TrackerRecAlgs/FaserSpacePoints/test/FaserSpacePointsDbg.py new file mode 100644 index 0000000000000000000000000000000000000000..a3d50f97a2127b4b33fec1c9cf50ab85218e8621 --- /dev/null +++ b/Tracker/TrackerRecAlgs/FaserSpacePoints/test/FaserSpacePointsDbg.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +import sys +from AthenaCommon.Logging import log +from AthenaCommon.Constants import DEBUG +from AthenaCommon.Configurable import Configurable +from CalypsoConfiguration.AllConfigFlags import ConfigFlags +from CalypsoConfiguration.MainServicesConfig import MainServicesCfg +from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg +from TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg +from TrackerSpacePointFormation.TrackerSpacePointFormationConfig import TrackerSpacePointFinderCfg +from FaserSpacePoints.FaserSpacePointsConfig import FaserSpacePointsCfg + +log.setLevel(DEBUG) +Configurable.configurableRun3Behavior = True + +ConfigFlags.Input.Files = ['my.RDO.pool.root'] +ConfigFlags.Output.ESDFileName = "spacePoints.ESD.pool.root" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" +ConfigFlags.GeoModel.Align.Dynamic = False +ConfigFlags.Beam.NumberOfCollisions = 0. +ConfigFlags.lock() + +# Core components +acc = MainServicesCfg(ConfigFlags) +acc.merge(PoolReadCfg(ConfigFlags)) +acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags)) +acc.merge(TrackerSpacePointFinderCfg(ConfigFlags)) +acc.merge(FaserSpacePointsCfg(ConfigFlags)) +acc.getEventAlgo("Tracker::FaserSpacePoints").OutputLevel = DEBUG + +sc = acc.run(maxEvents=1000) +sys.exit(not sc.isSuccess()) diff --git a/Tracker/TrackerRecAlgs/MCEvents/CMakeLists.txt b/Tracker/TrackerRecAlgs/MCEvents/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..edb6005ad67fab4e0fbb377aadee3a5fe3934235 --- /dev/null +++ b/Tracker/TrackerRecAlgs/MCEvents/CMakeLists.txt @@ -0,0 +1,10 @@ +atlas_subdir(MCEvents) + +atlas_add_component( + MCEvents + src/MCEventsAlg.h + src/MCEventsAlg.cxx + src/components/MCEvents_entries.cxx + LINK_LIBRARIES AthenaBaseComps GeneratorObjects StoreGateLib TrackerIdentifier TrackerSimEvent GaudiKernel) +atlas_install_python_modules(python/*.py) +atlas_install_scripts(test/*.py) diff --git a/Tracker/TrackerRecAlgs/MCEvents/python/MCEventsConfig.py b/Tracker/TrackerRecAlgs/MCEvents/python/MCEventsConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..87fabb5738421fa804d7b6eced90c6a074a3829c --- /dev/null +++ b/Tracker/TrackerRecAlgs/MCEvents/python/MCEventsConfig.py @@ -0,0 +1,9 @@ +from AthenaConfiguration.ComponentFactory import CompFactory +from FaserSCT_GeoModel.FaserSCT_GeoModelConfig import FaserSCT_GeometryCfg + + +def MCEventsCfg(flags, **kwargs): + acc = FaserSCT_GeometryCfg(flags) + mc_events_alg = CompFactory.MCEventsAlg + acc.addEventAlgo(mc_events_alg (**kwargs)) + return acc diff --git a/Tracker/TrackerRecAlgs/MCEvents/python/__init__.py b/Tracker/TrackerRecAlgs/MCEvents/python/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Tracker/TrackerRecAlgs/MCEvents/src/MCEventsAlg.cxx b/Tracker/TrackerRecAlgs/MCEvents/src/MCEventsAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e825850298b692e6841528cd61a897c3c3f584ff --- /dev/null +++ b/Tracker/TrackerRecAlgs/MCEvents/src/MCEventsAlg.cxx @@ -0,0 +1,53 @@ +#include "MCEventsAlg.h" +#include "TrackerIdentifier/FaserSCT_ID.h" + + +MCEventsAlg::MCEventsAlg(const std::string& name, ISvcLocator* pSvcLocator) + : AthReentrantAlgorithm(name, pSvcLocator) {} + + +StatusCode MCEventsAlg::initialize() { + ATH_CHECK(detStore()->retrieve(m_idHelper,"FaserSCT_ID")); + ATH_CHECK(m_mcEventKey.initialize()); + ATH_CHECK(m_faserSiHitKey.initialize()); + + return StatusCode::SUCCESS; +} + + +StatusCode MCEventsAlg::execute(const EventContext& ctx) const { + SG::ReadHandle<FaserSiHitCollection> siHitCollection (m_faserSiHitKey, ctx); + std::map<int, std::vector<const FaserSiHit*>> particle_map {}; + ATH_CHECK(siHitCollection.isValid()); + for (const FaserSiHit& hit : *siHitCollection) { + int barcode = hit.particleLink().barcode(); + particle_map[barcode].push_back(&hit); + } + + SG::ReadHandle<McEventCollection> mcEvents (m_mcEventKey, ctx); + ATH_CHECK(mcEvents.isValid()); + for (const HepMC::GenEvent* evt : *mcEvents) { + for (const HepMC::GenParticle* p : evt->particle_range()) { + const HepMC::FourVector vertex = p->production_vertex()->position(); + const HepMC::FourVector momentum = p->momentum(); + ATH_MSG_DEBUG("pdg: " << p->pdg_id() << ", barcode: " << p->barcode()); + ATH_MSG_DEBUG("vertex: " << vertex.x() << ", " << vertex.y() << ", " << vertex.z()); + ATH_MSG_DEBUG("momentum: " << momentum.px() << ", " << momentum.py() << ", " << momentum.pz()); + auto hits = particle_map[p->barcode()]; + for (const FaserSiHit* hit : hits) { + int station = hit->getStation(); + int layer = hit->getPlane(); + int phi = hit->getRow(); + int eta = hit->getModule(); + int side = hit->getSensor(); + ATH_MSG_DEBUG(station << "/" << layer << "/" << phi << "/" << eta << "/" << side); + } + } + } + return StatusCode::SUCCESS; +} + + +StatusCode MCEventsAlg::finalize() { + return StatusCode::SUCCESS; +} diff --git a/Tracker/TrackerRecAlgs/MCEvents/src/MCEventsAlg.h b/Tracker/TrackerRecAlgs/MCEvents/src/MCEventsAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..6b28d076f21f593e1ea0530e6148e55b22f28fd5 --- /dev/null +++ b/Tracker/TrackerRecAlgs/MCEvents/src/MCEventsAlg.h @@ -0,0 +1,26 @@ +#ifndef MCEVENTS_MCEVENTSALG_H +#define MCEVENTS_MCEVENTSALG_H + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "TrackerSimEvent/FaserSiHitCollection.h" +#include "GeneratorObjects/McEventCollection.h" + +class FaserSCT_ID; + +class MCEventsAlg : public AthReentrantAlgorithm { +public: + MCEventsAlg(const std::string& name, ISvcLocator* pSvcLocator); + virtual ~MCEventsAlg() = default; + + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& ctx) const override; + virtual StatusCode finalize() override; + +private: + const FaserSCT_ID* m_idHelper {nullptr}; + SG::ReadHandleKey<McEventCollection> m_mcEventKey { this, "McEventCollection", "BeamTruthEvent" }; + SG::ReadHandleKey<FaserSiHitCollection> m_faserSiHitKey { this, "FaserSiHitCollection", "SCT_Hits" }; +}; + + +#endif // MCEVENTS_MCEVENTSALG_H diff --git a/Tracker/TrackerRecAlgs/MCEvents/src/components/MCEvents_entries.cxx b/Tracker/TrackerRecAlgs/MCEvents/src/components/MCEvents_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2fbef91d7d22c81a1d230bee04fc9a88b5a1daaa --- /dev/null +++ b/Tracker/TrackerRecAlgs/MCEvents/src/components/MCEvents_entries.cxx @@ -0,0 +1,3 @@ +#include "../MCEventsAlg.h" + +DECLARE_COMPONENT(MCEventsAlg) \ No newline at end of file diff --git a/Tracker/TrackerRecAlgs/MCEvents/test/MCEventsDbg.py b/Tracker/TrackerRecAlgs/MCEvents/test/MCEventsDbg.py new file mode 100644 index 0000000000000000000000000000000000000000..b8e6ad587cdb132f93b7e1d57c5b958c9270fd9b --- /dev/null +++ b/Tracker/TrackerRecAlgs/MCEvents/test/MCEventsDbg.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +import sys +from AthenaCommon.Logging import log +from AthenaCommon.Constants import DEBUG +from AthenaCommon.Configurable import Configurable +from CalypsoConfiguration.AllConfigFlags import ConfigFlags +from CalypsoConfiguration.MainServicesConfig import MainServicesCfg +from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg +from MCEvents.MCEventsConfig import MCEventsCfg + + +log.setLevel(DEBUG) +Configurable.configurableRun3Behavior = True + +# Configure +ConfigFlags.Input.Files = ['my.RDO.pool.root'] +ConfigFlags.Output.ESDFileName = "MCEvents.ESD.root" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" +ConfigFlags.GeoModel.Align.Dynamic = False +ConfigFlags.Beam.NumberOfCollisions = 0. +ConfigFlags.lock() + +acc = MainServicesCfg(ConfigFlags) +acc.merge(PoolReadCfg(ConfigFlags)) +acc.merge(MCEventsCfg(ConfigFlags)) +acc.getEventAlgo("MCEventsAlg").OutputLevel = DEBUG + +sc = acc.run(maxEvents=10) +sys.exit(not sc.isSuccess()) diff --git a/Tracker/TrackerRecAlgs/MyClusters/CMakeLists.txt b/Tracker/TrackerRecAlgs/MyClusters/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..751e1f04a43c5f154013f81a2a74b44495df5dea --- /dev/null +++ b/Tracker/TrackerRecAlgs/MyClusters/CMakeLists.txt @@ -0,0 +1,11 @@ +atlas_subdir(MyClusters) + +atlas_add_component( + MyClusters + src/MyClustersAlg.h + src/MyClustersAlg.cxx + src/components/MyClusters_entries.cxx + LINK_LIBRARIES AthenaBaseComps GeneratorObjects TrackerPrepRawData StoreGateLib GaudiKernel) + +atlas_install_python_modules(python/*.py) +atlas_install_scripts(test/*.py) diff --git a/Tracker/TrackerRecAlgs/MyClusters/python/MyClustersConfig.py b/Tracker/TrackerRecAlgs/MyClusters/python/MyClustersConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..64757e1a96f8dff63993a8a2275ca5cc2db0b7c2 --- /dev/null +++ b/Tracker/TrackerRecAlgs/MyClusters/python/MyClustersConfig.py @@ -0,0 +1,17 @@ +""" +Copyright (C) 2022 CERN for the benefit of the FASER collaboration +""" + +from AthenaConfiguration.ComponentFactory import CompFactory +from FaserSCT_GeoModel.FaserSCT_GeoModelConfig import FaserSCT_GeometryCfg + + +def MyClustersCfg(flags, **kwargs): + acc = FaserSCT_GeometryCfg(flags) + my_clusters_alg = CompFactory.MyClustersAlg + acc.addEventAlgo(my_clusters_alg (**kwargs)) + + thistSvc = CompFactory.THistSvc() + thistSvc.Output += ["HIST DATAFILE='MyClusters.root' OPT='RECREATE'"] + acc.addService(thistSvc) + return acc diff --git a/Tracker/TrackerRecAlgs/MyClusters/python/__init__.py b/Tracker/TrackerRecAlgs/MyClusters/python/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Tracker/TrackerRecAlgs/MyClusters/src/MyClustersAlg.cxx b/Tracker/TrackerRecAlgs/MyClusters/src/MyClustersAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..050e5bed4949ad32855e899196bac03f91634ba8 --- /dev/null +++ b/Tracker/TrackerRecAlgs/MyClusters/src/MyClustersAlg.cxx @@ -0,0 +1,70 @@ +#include "MyClustersAlg.h" +#include "TrackerPrepRawData/FaserSCT_ClusterCollection.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "TrackerIdentifier/FaserSCT_ID.h" + + +MyClustersAlg::MyClustersAlg(const std::string& name, ISvcLocator* pSvcLocator) + : AthReentrantAlgorithm(name, pSvcLocator), AthHistogramming(name), + m_histSvc("THistSvc/THistSvc", name) {} + + +StatusCode MyClustersAlg::initialize() { + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + + ATH_CHECK(m_clusterContainerKey.initialize()); + + m_tree = new TTree("tree", "tree"); + m_tree->Branch("run", &m_run, "run/I"); + m_tree->Branch("event", &m_event, "event/I"); + m_tree->Branch("station", &m_station, "station/I"); + m_tree->Branch("layer", &m_layer, "layer/I"); + m_tree->Branch("phi", &m_phi, "phi/I"); + m_tree->Branch("eta", &m_eta, "eta/I"); + m_tree->Branch("side", &m_side, "side/I"); + m_tree->Branch("x", &m_x, "x/D"); + m_tree->Branch("y", &m_y, "y/D"); + m_tree->Branch("z", &m_z, "z/D"); + m_tree->Branch("lx", &m_lx, "lx/D"); + m_tree->Branch("ly", &m_ly, "ly/D"); + ATH_CHECK(histSvc()->regTree("/HIST/clusters", m_tree)); + return StatusCode::SUCCESS; +} + + +StatusCode MyClustersAlg::execute(const EventContext& ctx) const { + m_run = ctx.eventID().run_number(); + m_event = ctx.eventID().event_number(); + + SG::ReadHandle<Tracker::FaserSCT_ClusterContainer> clusterContainer {m_clusterContainerKey, ctx}; + ATH_CHECK(clusterContainer.isValid()); + + for (const auto& clusterCollection : *clusterContainer) { + for (const auto& cluster : *clusterCollection) { + auto id = cluster->identify(); + m_station = m_idHelper->station(id); + m_layer = m_idHelper->layer(id); + m_eta = m_idHelper->eta_module(id); + m_phi = m_idHelper->phi_module(id); + m_side = m_idHelper->side(id); + auto localPos = cluster->localPosition(); + m_lx = localPos.x(); + m_ly = localPos.y(); + auto localCov = cluster->localCovariance(); + auto pos = cluster->globalPosition(); + m_x = pos.x(); + m_y = pos.y(); + m_z = pos.z(); + m_tree->Fill(); + ATH_MSG_DEBUG("global position\n" << pos); + ATH_MSG_DEBUG("local position\n" << localPos); + ATH_MSG_DEBUG("local covariance\n" << localCov); + } + } + return StatusCode::SUCCESS; +} + + +StatusCode MyClustersAlg::finalize() { + return StatusCode::SUCCESS; +} diff --git a/Tracker/TrackerRecAlgs/MyClusters/src/MyClustersAlg.h b/Tracker/TrackerRecAlgs/MyClusters/src/MyClustersAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..04c6202a7e7f36a886a25d854ef31fae2e555946 --- /dev/null +++ b/Tracker/TrackerRecAlgs/MyClusters/src/MyClustersAlg.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2021 CERN for the benefit of the FASER collaboration +*/ + +#ifndef MYCLUSTERS_MYCLUSTERSALG_H +#define MYCLUSTERS_MYCLUSTERSALG_H + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "AthenaBaseComps/AthHistogramming.h" +#include "TrackerPrepRawData/FaserSCT_ClusterContainer.h" + +class TTree; +class FaserSCT_ID; + +class MyClustersAlg : public AthReentrantAlgorithm, AthHistogramming { +public: + MyClustersAlg(const std::string& name, ISvcLocator* pSvcLocator); + virtual ~MyClustersAlg() = default; + + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& ctx) const override; + virtual StatusCode finalize() override; + + const ServiceHandle<ITHistSvc>& histSvc() const; + +private: + SG::ReadHandleKey<Tracker::FaserSCT_ClusterContainer> m_clusterContainerKey { + this, "FaserSCT_ClusterContainer", "SCT_ClusterContainer", "cluster container"}; + ServiceHandle<ITHistSvc> m_histSvc; + const FaserSCT_ID* m_idHelper {nullptr}; + mutable TTree* m_tree; + + mutable unsigned int m_run; + mutable unsigned int m_event; + mutable unsigned int m_station; + mutable unsigned int m_layer; + mutable int m_eta; + mutable int m_phi; + mutable int m_side; + mutable double m_lx; + mutable double m_ly; + mutable double m_x; + mutable double m_y; + mutable double m_z; +}; + + +inline const ServiceHandle<ITHistSvc>& MyClustersAlg::histSvc() const { + return m_histSvc; +} + + +#endif // MYCLUSTERS_MYCLUSTERSALG_H diff --git a/Tracker/TrackerRecAlgs/MyClusters/src/components/MyClusters_entries.cxx b/Tracker/TrackerRecAlgs/MyClusters/src/components/MyClusters_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..93cf0f53b350ced62ddc1c00a401a082fbb68f2a --- /dev/null +++ b/Tracker/TrackerRecAlgs/MyClusters/src/components/MyClusters_entries.cxx @@ -0,0 +1,3 @@ +#include "../MyClustersAlg.h" + +DECLARE_COMPONENT(MyClustersAlg) \ No newline at end of file diff --git a/Tracker/TrackerRecAlgs/MyClusters/test/MyClustersDbg.py b/Tracker/TrackerRecAlgs/MyClusters/test/MyClustersDbg.py new file mode 100644 index 0000000000000000000000000000000000000000..c4ae4953adbe00bf94bcb2933d20bff32fcc107b --- /dev/null +++ b/Tracker/TrackerRecAlgs/MyClusters/test/MyClustersDbg.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python + +import sys +from AthenaCommon.Logging import log +from AthenaCommon.Constants import DEBUG +from AthenaCommon.Configurable import Configurable +from CalypsoConfiguration.AllConfigFlags import ConfigFlags +from CalypsoConfiguration.MainServicesConfig import MainServicesCfg +from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg +from TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg +from MyClusters.MyClustersConfig import MyClustersCfg + + +log.setLevel(DEBUG) +Configurable.configurableRun3Behavior = True + +# Configure +ConfigFlags.Input.Files = ['my.RDO.pool.root'] +ConfigFlags.Output.ESDFileName = "MyClusters.ESD.root" +ConfigFlags.Output.AODFileName = "MyClsuters.AOD.pool.root" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" +ConfigFlags.GeoModel.Align.Dynamic = False +ConfigFlags.Beam.NumberOfCollisions = 0. +ConfigFlags.lock() + +acc = MainServicesCfg(ConfigFlags) +acc.merge(PoolReadCfg(ConfigFlags)) +acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags)) +acc.merge(MyClustersCfg(ConfigFlags)) +acc.getEventAlgo("MyClustersAlg").OutputLevel = DEBUG + +sc = acc.run(maxEvents=10) +sys.exit(not sc.isSuccess()) diff --git a/Tracker/TrackerRecAlgs/MyExtrapolationExample/CMakeLists.txt b/Tracker/TrackerRecAlgs/MyExtrapolationExample/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..72f4a7ac272d63a1060b39cb89a222fb4fc4e026 --- /dev/null +++ b/Tracker/TrackerRecAlgs/MyExtrapolationExample/CMakeLists.txt @@ -0,0 +1,12 @@ +atlas_subdir(MyExtrapolationExample) + +atlas_add_component( + MyExtrapolationExample + src/MyExtrapolationExample.h + src/MyExtrapolationExample.cxx + src/components/MyExtrapolationExample_entries.cxx + LINK_LIBRARIES AthenaBaseComps StoreGateLib GeneratorObjects FaserActsGeometryLib TrackerSimEvent TrackerIdentifier TrackerReadoutGeometry +) + +atlas_install_python_modules(python/*.py) +atlas_install_scripts(test/*.py) diff --git a/Tracker/TrackerRecAlgs/MyExtrapolationExample/python/MyExtrapolationExampleConfig.py b/Tracker/TrackerRecAlgs/MyExtrapolationExample/python/MyExtrapolationExampleConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..6c2738946d33457377968f29831b007461af969e --- /dev/null +++ b/Tracker/TrackerRecAlgs/MyExtrapolationExample/python/MyExtrapolationExampleConfig.py @@ -0,0 +1,30 @@ +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory +from FaserSCT_GeoModel.FaserSCT_GeoModelConfig import FaserSCT_GeometryCfg +from MagFieldServices.MagFieldServicesConfig import MagneticFieldSvcCfg + +# def FaserActsTrackingGeometrySvcCfg(flags, **kwargs): +# acc = ComponentAccumulator() +# FaserActsTrackingGeometrySvc = CompFactory.FaserActsTrackingGeometrySvc +# acc.addService(FaserActsTrackingGeometrySvc(name="FaserActsTrackingGeometrySvc", **kwargs)) +# return acc + +# def FaserActsAlignmentCondAlgCfg(flags, **kwargs): +# acc = ComponentAccumulator() +# acc.addCondAlgo(CompFactory.FaserActsAlignmentCondAlg(name="FaserActsAlignmentCondAlg", **kwargs)) +# return acc + +def MyExtrapolationExampleCfg(flags, **kwargs): + acc = FaserSCT_GeometryCfg(flags) + acc.merge(MagneticFieldSvcCfg(flags)) + # acc.merge(FaserActsTrackingGeometrySvcCfg(flags)) + # acc.merge(FaserActsAlignmentCondAlgCfg(flags)) + + actsExtrapolationTool = CompFactory.FaserActsExtrapolationTool("FaserActsExtrapolationTool") + actsExtrapolationTool.MaxSteps = 1000 + actsExtrapolationTool.TrackingGeometryTool = CompFactory.FaserActsTrackingGeometryTool("TrackingGeometryTool") + + my_extrapolation_example = CompFactory.Tracker.MyExtrapolationExample(**kwargs) + my_extrapolation_example.ExtrapolationTool = actsExtrapolationTool + acc.addEventAlgo(my_extrapolation_example) + return acc diff --git a/Tracker/TrackerRecAlgs/MyExtrapolationExample/python/__init__.py b/Tracker/TrackerRecAlgs/MyExtrapolationExample/python/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Tracker/TrackerRecAlgs/MyExtrapolationExample/src/MyExtrapolationExample.cxx b/Tracker/TrackerRecAlgs/MyExtrapolationExample/src/MyExtrapolationExample.cxx new file mode 100644 index 0000000000000000000000000000000000000000..aecebc372e415c6c58f1464706c6f25ea6001dc2 --- /dev/null +++ b/Tracker/TrackerRecAlgs/MyExtrapolationExample/src/MyExtrapolationExample.cxx @@ -0,0 +1,114 @@ +#include "MyExtrapolationExample.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" +#include "GeoPrimitives/CLHEPtoEigenConverter.h" +#include "Acts/Surfaces/PerigeeSurface.hpp" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "TrackerReadoutGeometry/SiDetectorElement.h" +#include <cmath> + + +namespace Tracker { + +MyExtrapolationExample::MyExtrapolationExample(const std::string &name, ISvcLocator *pSvcLocator) + : AthReentrantAlgorithm(name, pSvcLocator) {} + +StatusCode MyExtrapolationExample::initialize() { + ATH_CHECK(m_mcEventCollectionKey.initialize()); + ATH_CHECK(m_faserSiHitKey.initialize()); + ATH_CHECK(m_extrapolationTool.retrieve()); + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + ATH_CHECK(detStore()->retrieve(m_detMgr, "SCT")); + return StatusCode::SUCCESS; +} + +StatusCode MyExtrapolationExample::execute(const EventContext &ctx) const { + const Acts::GeometryContext gctx = + m_extrapolationTool->trackingGeometryTool()->getNominalGeometryContext().context(); + + std::vector<double> z_positions {}; + SG::ReadHandle<FaserSiHitCollection> siHitCollection {m_faserSiHitKey, ctx}; + ATH_CHECK(siHitCollection.isValid()); + for (const FaserSiHit& hit : *siHitCollection) { + if ((hit.getStation() == 1) && (hit.getPlane() == 0) && (hit.getSensor() == 0)) { + if (hit.particleLink()) { + if (std::abs(hit.particleLink()->pdg_id()) != 13) + continue; + Identifier id = m_idHelper->wafer_id(hit.getStation(), hit.getPlane(), hit.getRow(), hit.getModule(), hit.getSensor()); + const TrackerDD::SiDetectorElement* element = m_detMgr->getDetectorElement(id); + const HepGeom::Point3D<double> globalStartPosition = + Amg::EigenTransformToCLHEP(element->transformHit()) * hit.localStartPosition(); + z_positions.push_back(globalStartPosition.z()); + ATH_MSG_DEBUG("SiHit: " << globalStartPosition.x() << ", " << globalStartPosition.y() << ", " << globalStartPosition.z()); + } + } + } + + double z_mean = 0; + for (double z : z_positions) { + z_mean += z; + } + z_mean /= z_positions.size(); + + 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; + } + + + for (const HepMC::GenParticle* particle : mcEvents->front()->particle_range()) { + if ((std::abs(particle->pdg_id()) != 13)) { + continue; + } + const HepMC::FourVector& vertex = particle->production_vertex()->position(); + if (vertex.z() > 0) { + continue; + } + const HepMC::FourVector& momentum = particle->momentum(); + double phi = momentum.phi(); + double theta = momentum.theta(); + double charge = particle->pdg_id() > 0 ? -1 : 1; + double abs_momentum = momentum.rho() * m_MeV2GeV; + double qop = charge / abs_momentum; + // The coordinate system of the Acts::PlaneSurface is defined as + // T = Z = normal, U = X x T = -Y, V = T x U = x +// Acts::BoundVector pars; +// pars << -vertex.y(), vertex.x(), phi, theta, qop, vertex.t(); + Acts::BoundVector pars = Acts::BoundVector::Zero(); + pars[Acts::eBoundLoc0] = -vertex.y(); + pars[Acts::eBoundLoc1] = vertex.x(); + pars[Acts::eBoundPhi] = phi; + pars[Acts::eBoundTheta] = theta; + pars[Acts::eBoundQOverP] = qop; + pars[Acts::eBoundTime] = vertex.t(); + + 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, z_mean), Acts::Vector3(0, 0, 1)); + Acts::BoundTrackParameters startParameters( + std::move(startSurface), pars, charge); + ATH_MSG_DEBUG("vertex: " << vertex.x() << ", " << vertex.y() << ", " << vertex.z()); + ATH_MSG_DEBUG("vertex momentum: " << momentum.x() * m_MeV2GeV << ", " << momentum.y() * m_MeV2GeV << ", " << momentum.z() * m_MeV2GeV); + std::unique_ptr<const Acts::BoundTrackParameters> targetParameters = + m_extrapolationTool->propagate(ctx, startParameters, *targetSurface); + if (targetParameters) { + Acts::Vector3 targetPosition = targetParameters->position(gctx); + Acts::Vector3 targetMomentum = targetParameters->momentum(); + ATH_MSG_DEBUG("vertex: " << vertex.x() << ", " << vertex.y() << ", " << vertex.z()); + ATH_MSG_DEBUG("origin: " << targetPosition.x() << ", " << targetPosition.y() << ", " << targetPosition.z()); + ATH_MSG_DEBUG("vertex momentum: " << momentum.x() * m_MeV2GeV << ", " << momentum.y() * m_MeV2GeV << ", " << momentum.z() * m_MeV2GeV); + ATH_MSG_DEBUG("origin momentum: " << targetMomentum.x() << ", " << targetMomentum.y() << ", " << targetMomentum.z()); + } + } + + return StatusCode::SUCCESS; +} + +StatusCode MyExtrapolationExample::finalize() { + return StatusCode::SUCCESS; +} + +} // Tracker diff --git a/Tracker/TrackerRecAlgs/MyExtrapolationExample/src/MyExtrapolationExample.h b/Tracker/TrackerRecAlgs/MyExtrapolationExample/src/MyExtrapolationExample.h new file mode 100644 index 0000000000000000000000000000000000000000..cd5a2ed077310d3a07e5edd41787033593642c18 --- /dev/null +++ b/Tracker/TrackerRecAlgs/MyExtrapolationExample/src/MyExtrapolationExample.h @@ -0,0 +1,42 @@ +/* +Copyright (C) 2022 CERN for the benefit of the FASER collaboration +*/ + +#ifndef MYEXTRAPOLATIONEXAMPLE_MYEXTRAPOLATIONEXAMPLE_H +#define MYEXTRAPOLATIONEXAMPLE_MYEXTRAPOLATIONEXAMPLE_H + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "FaserActsGeometryInterfaces/IFaserActsExtrapolationTool.h" +#include "GeneratorObjects/McEventCollection.h" +#include "TrackerSimEvent/FaserSiHitCollection.h" + +class FaserSCT_ID; +namespace TrackerDD { +class SCT_DetectorManager; + +} +namespace Tracker { + +class MyExtrapolationExample : public AthReentrantAlgorithm { + public: + MyExtrapolationExample(const std::string& name, ISvcLocator* pSvcLocator); + + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& ctx) const override; + virtual StatusCode finalize() override; + +private: + double m_MeV2GeV = 1e-3; + const FaserSCT_ID* m_idHelper {nullptr}; + const TrackerDD::SCT_DetectorManager* m_detMgr {nullptr}; + SG::ReadHandleKey<McEventCollection> m_mcEventCollectionKey { + this, "McEventCollection", "TruthEvent"}; + SG::ReadHandleKey <FaserSiHitCollection> m_faserSiHitKey { + this, "FaserSiHitCollection", "SCT_Hits"}; + ToolHandle<IFaserActsExtrapolationTool> m_extrapolationTool { + this, "ExtrapolationTool", "FaserActsExtrapolationTool"}; +}; + +} // namespace Tracker + +#endif // MYEXTRAPOLATIONEXAMPLE_MYEXTRAPOLATIONEXAMPLE_H diff --git a/Tracker/TrackerRecAlgs/MyExtrapolationExample/src/components/MyExtrapolationExample_entries.cxx b/Tracker/TrackerRecAlgs/MyExtrapolationExample/src/components/MyExtrapolationExample_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6601e0a3fe0e99d45ca137db49d8b63bb89573d1 --- /dev/null +++ b/Tracker/TrackerRecAlgs/MyExtrapolationExample/src/components/MyExtrapolationExample_entries.cxx @@ -0,0 +1,3 @@ +#include "../MyExtrapolationExample.h" + +DECLARE_COMPONENT(Tracker::MyExtrapolationExample) \ No newline at end of file diff --git a/Tracker/TrackerRecAlgs/MyExtrapolationExample/test/MyExtrapolationExampleDbg.py b/Tracker/TrackerRecAlgs/MyExtrapolationExample/test/MyExtrapolationExampleDbg.py new file mode 100644 index 0000000000000000000000000000000000000000..fe83560fa4fe694fb643bfd514cfd2d2c8df4c14 --- /dev/null +++ b/Tracker/TrackerRecAlgs/MyExtrapolationExample/test/MyExtrapolationExampleDbg.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +import sys +from AthenaCommon.Logging import log +from AthenaCommon.Constants import DEBUG, VERBOSE +from AthenaCommon.Configurable import Configurable +from CalypsoConfiguration.AllConfigFlags import ConfigFlags +from CalypsoConfiguration.MainServicesConfig import MainServicesCfg +from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg +from MyExtrapolationExample.MyExtrapolationExampleConfig import MyExtrapolationExampleCfg + + +log.setLevel(DEBUG) +Configurable.configurableRun3Behavior = True + +# Configure +ConfigFlags.Input.Files = ['my.HITS.pool.root'] +ConfigFlags.Output.ESDFileName = "MyExtrapolationExample.ESD.root" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" +ConfigFlags.GeoModel.Align.Dynamic = False +ConfigFlags.Beam.NumberOfCollisions = 0. +ConfigFlags.lock() + +acc = MainServicesCfg(ConfigFlags) +acc.merge(PoolReadCfg(ConfigFlags)) +acc.merge(MyExtrapolationExampleCfg(ConfigFlags)) +acc.getEventAlgo("Tracker::MyExtrapolationExample").OutputLevel = VERBOSE + +sc = acc.run(maxEvents=10) +sys.exit(not sc.isSuccess()) diff --git a/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/CMakeLists.txt b/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f712d3881883fb0cdff9e8186b5b36578d48bf62 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/CMakeLists.txt @@ -0,0 +1,12 @@ +atlas_subdir(TrackSeedPerformanceWriter) + +atlas_add_component( + TrackSeedPerformanceWriter + src/TrackSeedPerformanceWriter.h + src/TrackSeedPerformanceWriter.cxx + src/components/TrackSeedPerformanceWriter_entries.cxx + LINK_LIBRARIES AthenaBaseComps StoreGateLib TrkTrack TrackerSimData TrackerPrepRawData TrkRIO_OnTrack TrackerRIO_OnTrack +) + +atlas_install_python_modules(python/*.py) +atlas_install_scripts(test/*.py) diff --git a/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/python/TrackSeedPerformanceWriterConfig.py b/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/python/TrackSeedPerformanceWriterConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..f8b0eca720b42ed668d7918bac86569007f4d68f --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/python/TrackSeedPerformanceWriterConfig.py @@ -0,0 +1,30 @@ +""" +Copyright (C) 2022 CERN for the benefit of the FASER collaboration +""" + +from AthenaConfiguration.ComponentFactory import CompFactory +from FaserSCT_GeoModel.FaserSCT_GeoModelConfig import FaserSCT_GeometryCfg +from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg + + + +def TrackSeedPerformanceWriterCfg(flags, **kwargs): + acc = FaserSCT_GeometryCfg(flags) + kwargs.setdefault("TrackCollection", "SegmentFit") + TrackSeedPerformanceWriter = CompFactory.Tracker.TrackSeedPerformanceWriter + acc.addEventAlgo(TrackSeedPerformanceWriter(**kwargs)) + + itemList = ["xAOD::EventInfo#*", + "xAOD::EventAuxInfo#*", + "xAOD::FaserTriggerData#*", + "xAOD::FaserTriggerDataAux#*", + "FaserSCT_RDO_Container#*", + "Tracker::FaserSCT_ClusterContainer#*", + "TrackCollection#*" + ] + acc.merge(OutputStreamCfg(flags, "ESD", itemList)) + + thistSvc = CompFactory.THistSvc() + thistSvc.Output += ["HIST1 DATAFILE='TrackSeedPerformanceWriter.root' OPT='RECREATE'"] + acc.addService(thistSvc) + return acc diff --git a/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/python/__init__.py b/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/python/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/src/TrackSeedPerformanceWriter.cxx b/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/src/TrackSeedPerformanceWriter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..9c43a4e2a1bffc98af9c2fdd49385ddfaac0f2f9 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/src/TrackSeedPerformanceWriter.cxx @@ -0,0 +1,124 @@ +#include "TrackSeedPerformanceWriter.h" +#include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "TrackerIdentifier/FaserSCT_ID.h" + + +namespace Tracker { + + TrackSeedPerformanceWriter::TrackSeedPerformanceWriter(const std::string &name, ISvcLocator *pSvcLocator) + : AthReentrantAlgorithm(name, pSvcLocator), AthHistogramming(name), + m_idHelper(nullptr), m_histSvc("THistSvc/THistSvc", name) {} + + + StatusCode TrackSeedPerformanceWriter::initialize() { + ATH_CHECK(m_trackCollectionKey.initialize()); + ATH_CHECK(m_simDataCollectionKey.initialize()); + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + + m_tree = new TTree("tree", "tree"); + m_tree->Branch("run", &m_run, "run/I"); + m_tree->Branch("event", &m_event, "event/I"); + m_tree->Branch("station", &m_station, "station/I"); + m_tree->Branch("chi2", &m_chi2, "chi2/D"); + m_tree->Branch("dof", &m_dof, "dof/I"); + m_tree->Branch("nHits", &m_nHits, "nHits/I"); + m_tree->Branch("x", &m_x, "x/D"); + m_tree->Branch("y", &m_y, "y/D"); + m_tree->Branch("z", &m_z, "z/D"); + m_tree->Branch("px", &m_px, "px/D"); + m_tree->Branch("py", &m_py, "py/D"); + m_tree->Branch("pz", &m_pz, "pz/D"); + // m_tree->Branch("barcode", &m_barcode, "barcode/I"); + m_tree->Branch("barcodes", &m_barcodes); + m_tree->Branch("nMajorityHits", &m_nMajorityHits, "nMajorityHits/I"); + m_tree->Branch("nMajorityParticle", &m_majorityParticle, "nMajorityParticle/I"); + // m_tree->Branch("run", &m_run); + // m_tree->Branch("event", &m_event); + // m_tree->Branch("station", &m_station); + // m_tree->Branch("barcodes", &m_barcodes); + ATH_CHECK(histSvc()->regTree("/HIST1/TrackSeedPerformance", m_tree)); + + return StatusCode::SUCCESS; + } + + + StatusCode TrackSeedPerformanceWriter::execute(const EventContext &ctx) const { + m_run = ctx.eventID().run_number(); + m_event = ctx.eventID().event_number(); + + SG::ReadHandle<TrackCollection> trackCollection{m_trackCollectionKey, ctx}; + ATH_CHECK(trackCollection.isValid()); + + SG::ReadHandle<TrackerSimDataCollection> simDataCollection {m_simDataCollectionKey, ctx}; + ATH_CHECK(simDataCollection.isValid()); + + for (const Trk::Track *track: *trackCollection) { + m_chi2 = track->fitQuality()->chiSquared(); + m_dof = track->fitQuality()->numberDoF(); + const Amg::Vector3D trackPosition = track->trackParameters()->front()->position(); + const Amg::Vector3D trackMomentum = track->trackParameters()->front()->momentum(); + m_x = trackPosition.x(); + m_y = trackPosition.y(); + m_z = trackPosition.z(); + m_px = trackMomentum.x(); + m_py = trackMomentum.y(); + m_pz = trackMomentum.z(); + m_nHits = track->measurementsOnTrack()->size(); + m_barcodes = {}; + m_hitCounts = {}; + for (const auto meas: *track->measurementsOnTrack()) { + const auto *clusterOnTrack = dynamic_cast<const Tracker::FaserSCT_ClusterOnTrack *>(meas); + if (clusterOnTrack) { + const Tracker::FaserSCT_Cluster *cluster = clusterOnTrack->prepRawData(); + Identifier id = cluster->identify(); + m_barcode = matchHit(id, simDataCollection.get()); + // fill hit map + if (m_hitCounts.count(m_barcode) > 0) { + m_hitCounts[m_barcode] += 1; + } else { + m_hitCounts[m_barcode] = 1; + } + m_barcodes.push_back(m_barcode); + m_station = m_idHelper->station(id); + } + } + + // find majority particle + m_nMajorityHits = 0; + m_majorityParticle = 0; + for (const auto& hit : m_hitCounts) { + if (hit.second > m_nMajorityHits) { + m_majorityParticle = hit.first; + m_nMajorityHits = hit.second; + } + } + m_tree->Fill(); + } + + return StatusCode::SUCCESS; + } + + + StatusCode TrackSeedPerformanceWriter::finalize() { + return StatusCode::SUCCESS; + } + + + int TrackSeedPerformanceWriter::matchHit( + Identifier id, const TrackerSimDataCollection *simDataCollection) const { + int barcode = 0; + if (simDataCollection->count(id) != 0) { + const auto& deposits = simDataCollection->find(id)->second.getdeposits(); + float highestDep = 0; + for (const TrackerSimData::Deposit &deposit : deposits) { + if (deposit.second > highestDep) { + highestDep = deposit.second; + barcode = deposit.first->barcode(); + } + } + } + return barcode; + } + +} // namespace Tracker diff --git a/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/src/TrackSeedPerformanceWriter.h b/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/src/TrackSeedPerformanceWriter.h new file mode 100644 index 0000000000000000000000000000000000000000..86192d77c69193ee86b41a2123e42819d27051cc --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/src/TrackSeedPerformanceWriter.h @@ -0,0 +1,61 @@ +#ifndef FASERACTSKALMANFILTER_TRACKSEEDPERFORMANCEWRITER_H +#define FASERACTSKALMANFILTER_TRACKSEEDPERFORMANCEWRITER_H + + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "AthenaBaseComps/AthHistogramming.h" +#include "TrkTrack/TrackCollection.h" +#include "TrackerSimData/TrackerSimDataCollection.h" + +class TTree; +class FaserSCT_ID; + + +namespace Tracker { + class TrackSeedPerformanceWriter : public AthReentrantAlgorithm, AthHistogramming { + public: + TrackSeedPerformanceWriter(const std::string &name, ISvcLocator *pSvcLocator); + virtual ~TrackSeedPerformanceWriter() = default; + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext &ctx) const override; + virtual StatusCode finalize() override; + const ServiceHandle<ITHistSvc> &histSvc() const; + + private: + int matchHit(Identifier id, const TrackerSimDataCollection *simDataCollection) const; + SG::ReadHandleKey<TrackCollection> m_trackCollectionKey { + this, "TrackCollection", "SegmentFit", "Input track collection name"}; + SG::ReadHandleKey<TrackerSimDataCollection> m_simDataCollectionKey { + this, "TrackerSimDataCollection", "SCT_SDO_Map"}; + ServiceHandle<ITHistSvc> m_histSvc; + const FaserSCT_ID *m_idHelper; + mutable TTree *m_tree; + + mutable unsigned int m_run; + mutable unsigned int m_event; + mutable unsigned int m_station; + mutable double m_chi2; + mutable int m_dof; + mutable int m_nHits; + 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_barcode; + mutable int m_majorityParticle; + mutable int m_nMajorityHits; + mutable std::vector<int> m_barcodes; + mutable std::map<int, int> m_hitCounts; + }; + + + inline const ServiceHandle<ITHistSvc> &TrackSeedPerformanceWriter::histSvc() const { + return m_histSvc; + } + +} // namespace Tracker + + +#endif // FASERACTSKALMANFILTER_TRACKSEEDPERFORMANCEWRITER_H diff --git a/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/src/components/TrackSeedPerformanceWriter_entries.cxx b/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/src/components/TrackSeedPerformanceWriter_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..9e569f003a45ef87af33da385a561d3b6a77c95a --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/src/components/TrackSeedPerformanceWriter_entries.cxx @@ -0,0 +1,3 @@ +#include "../TrackSeedPerformanceWriter.h" + +DECLARE_COMPONENT(Tracker::TrackSeedPerformanceWriter) diff --git a/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/test/TrackSeedPerformanceWriterDbg.py b/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/test/TrackSeedPerformanceWriterDbg.py new file mode 100644 index 0000000000000000000000000000000000000000..b00b9a623561d8b7ef3b57bc0f7bca7e824699c0 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackSeedPerformanceWriter/test/TrackSeedPerformanceWriterDbg.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +""" +Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +""" + +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 TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg +from TrackerSegmentFit.TrackerSegmentFitConfig import SegmentFitAlgCfg +from TrackSeedPerformanceWriter.TrackSeedPerformanceWriterConfig import TrackSeedPerformanceWriterCfg + +log.setLevel(DEBUG) +Configurable.configurableRun3Behavior = True + +ConfigFlags.Input.Files = ['my.RDO.pool.root'] +ConfigFlags.Output.ESDFileName = "seeds.ESD.pool.root" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" +ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" +ConfigFlags.Input.ProjectName = "data21" +ConfigFlags.Input.isMC = True +ConfigFlags.GeoModel.FaserVersion = "FASER-01" +ConfigFlags.Common.isOnline = False +ConfigFlags.GeoModel.Align.Dynamic = False +ConfigFlags.Beam.NumberOfCollisions = 0. +ConfigFlags.lock() + +acc = MainServicesCfg(ConfigFlags) +acc.merge(PoolReadCfg(ConfigFlags)) +acc.merge(PoolWriteCfg(ConfigFlags)) +acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags)) +acc.merge(SegmentFitAlgCfg(ConfigFlags, MaxClusters=20, TanThetaCut=0.1)) +acc.merge(TrackSeedPerformanceWriterCfg(ConfigFlags)) +#acc.getEventAlgo("Tracker::SegmentFitAlg").OutputLevel = DEBUG +acc.getEventAlgo("Tracker::TrackSeedPerformanceWriter").OutputLevel = DEBUG + +sc = acc.run(maxEvents=1000) +sys.exit(not sc.isSuccess()) diff --git a/Tracker/TrackerRecAlgs/TrackerData/CMakeLists.txt b/Tracker/TrackerRecAlgs/TrackerData/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..62e3b8e58115a157382c1e6b434e35ad0b4cb842 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerData/CMakeLists.txt @@ -0,0 +1,15 @@ +atlas_subdir(TrackerData) + +atlas_add_component( + TrackerData + src/TrackerSegmentFitDataAlg.h + src/TrackerSegmentFitDataAlg.cxx + src/TrackerTruthDataAlg.h + src/TrackerTruthDataAlg.cxx + src/components/TrackerData_entries.cxx + LINK_LIBRARIES AthenaBaseComps GeneratorObjects TrackerSimEvent TrackerIdentifier + TrackerReadoutGeometry TrackerRIO_OnTrack TrackerPrepRawData TrkTrack +) + +atlas_install_python_modules(python/*.py) +atlas_install_scripts(test/*.py) \ No newline at end of file diff --git a/Tracker/TrackerRecAlgs/TrackerData/README b/Tracker/TrackerRecAlgs/TrackerData/README new file mode 100644 index 0000000000000000000000000000000000000000..5c7cd869e46e21b3f82e68d2d55811f8d5b9b0d9 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerData/README @@ -0,0 +1,9 @@ +This package can be used to write out the data from simulated hits and from +tracks reconstructed with the TrackerSegmentFit algorithm. + +To write out information for the simulated hits run G4FaserAlgConfigNew_Test.py +to simulate hits and TrackerTruthDbg.py to write out the information. + +To write out information for the tracks run G4FaserAlgConfigNew_Test.py to +simulate hits, FaserSCT_DigitizationDbg.py to digitize them and +TrackerSegmentFitDbg.py to write out the information. \ No newline at end of file diff --git a/Tracker/TrackerRecAlgs/TrackerData/python/TrackerSegmentFitDataConfig.py b/Tracker/TrackerRecAlgs/TrackerData/python/TrackerSegmentFitDataConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..74497753353d66363d6c09ba12cb9a4c899351ad --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerData/python/TrackerSegmentFitDataConfig.py @@ -0,0 +1,19 @@ +""" +Copyright (C) 2022 CERN for the benefit of the FASER collaboration +""" + +from AthenaConfiguration.ComponentFactory import CompFactory +from FaserSCT_GeoModel.FaserSCT_GeoModelConfig import FaserSCT_GeometryCfg + + +def TrackerSegmentFitDataCfg(flags, **kwargs): + acc = FaserSCT_GeometryCfg(flags) + kwargs.setdefault("TrackCollection", "SegmentFit") + TrackerSegmentFitDataAlg = CompFactory.Tracker.TrackerSegmentFitDataAlg + acc.addEventAlgo(TrackerSegmentFitDataAlg(**kwargs)) + + thistSvc = CompFactory.THistSvc() + thistSvc.Output += ["HIST2 DATAFILE='TrackerSegmentFitData.root' OPT='RECREATE'"] + acc.addService(thistSvc) + + return acc diff --git a/Tracker/TrackerRecAlgs/TrackerData/python/TrackerTruthDataConfig.py b/Tracker/TrackerRecAlgs/TrackerData/python/TrackerTruthDataConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..206fda5f90eebb94b06f61b2176938daee08c3b6 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerData/python/TrackerTruthDataConfig.py @@ -0,0 +1,19 @@ +""" +Copyright (C) 2022 CERN for the benefit of the FASER collaboration +""" + +from AthenaConfiguration.ComponentFactory import CompFactory +from FaserSCT_GeoModel.FaserSCT_GeoModelConfig import FaserSCT_GeometryCfg + + +def TrackerTruthDataCfg(flags, **kwargs): + acc = FaserSCT_GeometryCfg(flags) + kwargs.setdefault("FaserSiHitCollection", "SCT_Hits") + TrackerTruthDataAlg = CompFactory.Tracker.TrackerTruthDataAlg + acc.addEventAlgo(TrackerTruthDataAlg(**kwargs)) + + thistSvc = CompFactory.THistSvc() + thistSvc.Output += ["HIST1 DATAFILE='TrackerTruthData.root' OPT='RECREATE'"] + acc.addService(thistSvc) + + return acc diff --git a/Tracker/TrackerRecAlgs/TrackerData/python/__init__.py b/Tracker/TrackerRecAlgs/TrackerData/python/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Tracker/TrackerRecAlgs/TrackerData/src/TrackerSegmentFitDataAlg.cxx b/Tracker/TrackerRecAlgs/TrackerData/src/TrackerSegmentFitDataAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..92545f3202a58880bbfb6ec6cfa55e3a0bc4396f --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerData/src/TrackerSegmentFitDataAlg.cxx @@ -0,0 +1,107 @@ +#include "TrackerSegmentFitDataAlg.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "TrackerReadoutGeometry/SiDetectorElement.h" +#include "TrkTrack/Track.h" +#include "TrkTrack/TrackStateOnSurface.h" +#include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include <TTree.h> + + +namespace Tracker { + +TrackerSegmentFitDataAlg::TrackerSegmentFitDataAlg(const std::string &name, ISvcLocator *pSvcLocator) + : AthReentrantAlgorithm(name, pSvcLocator), AthHistogramming(name), + m_detMgr(nullptr), m_idHelper(nullptr), m_histSvc("THistSvc/THistSvc", name) {} + + +StatusCode TrackerSegmentFitDataAlg::initialize() { + ATH_CHECK(detStore()->retrieve(m_detMgr, "SCT")); + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + ATH_CHECK(m_trackCollection.initialize()); + + m_tracks = new TTree("tracks", "tracks"); + m_tracks->Branch("run_number", &m_run_number, "run_number/I"); + m_tracks->Branch("event_number", &m_event_number, "event_number/I"); + m_tracks->Branch("chi2", &m_chi2, "chi2/I"); + m_tracks->Branch("dof", &m_nDOF, "dof/I"); + m_tracks->Branch("number_clusters", &m_nClusters, "clusters/I"); + m_tracks->Branch("x", &m_track_x, "x/D"); + m_tracks->Branch("y", &m_track_y, "y/D"); + m_tracks->Branch("z", &m_track_z, "z/D"); + m_tracks->Branch("px", &m_track_px, "px/D"); + m_tracks->Branch("py", &m_track_py, "py/D"); + m_tracks->Branch("pz", &m_track_pz, "pz/D"); + ATH_CHECK(histSvc()->regTree("/HIST2/tracks", m_tracks)); + + m_hits = new TTree("hits", "hits"); + m_hits->Branch("run_number", &m_run_number, "run_number/I"); + m_hits->Branch("event_number", &m_event_number, "event_number/I"); + m_hits->Branch("station", &m_station, "station/I"); + m_hits->Branch("plane", &m_plane, "plane/I"); + m_hits->Branch("module", &m_module, "module/I"); + m_hits->Branch("row", &m_row, "row/I"); + m_hits->Branch("sensor", &m_sensor, "sensor/I"); + m_hits->Branch("x", &m_x, "x/D"); + m_hits->Branch("y", &m_y, "y/D"); + m_hits->Branch("z", &m_z, "z/D"); + ATH_CHECK(histSvc()->regTree("/HIST2/hits", m_hits)); + + return StatusCode::SUCCESS; +} + +StatusCode TrackerSegmentFitDataAlg::execute(const EventContext &ctx) const { + + m_run_number = ctx.eventID().run_number(); + m_event_number = ctx.eventID().event_number(); + + // Fill tree with clusters from tracker segment fit + SG::ReadHandle<TrackCollection> trackCollection {m_trackCollection, ctx}; + ATH_CHECK(trackCollection.isValid()); + + for (const Trk::Track* track : *trackCollection) { + m_chi2 = track->fitQuality()->chiSquared(); + m_nDOF = track->fitQuality()->numberDoF(); + m_nClusters = track->trackParameters()->size() - 1; + auto fitParameters = track->trackParameters()->front(); + const Amg::Vector3D fitPosition = fitParameters->position(); + const Amg::Vector3D fitMomentum = fitParameters->momentum(); + m_track_x = fitPosition.x(); + m_track_y = fitPosition.y(); + m_track_z = fitPosition.z(); + m_track_px = fitMomentum.x(); + m_track_py = fitMomentum.y(); + m_track_pz = fitMomentum.z(); + m_tracks->Fill(); + + for (const Trk::TrackStateOnSurface* trackState : *track->trackStateOnSurfaces()) { + const auto* clusterOnTrack = + dynamic_cast<const FaserSCT_ClusterOnTrack*>(trackState->measurementOnTrack()); + if (!clusterOnTrack) + continue; + const FaserSCT_Cluster* cluster = clusterOnTrack->prepRawData(); + Identifier id = cluster->identify(); + m_station = m_idHelper->station(id); + m_plane = m_idHelper->layer(id); + m_module = m_idHelper->eta_module(id); + m_row = m_idHelper->phi_module(id); + m_sensor = m_idHelper->side(id); + m_strip = m_idHelper->strip(id); + Amg::Vector3D position = cluster->globalPosition(); + m_x = position.x(); + m_y = position.y(); + m_z = position.z(); + m_hits->Fill(); + } + } + + return StatusCode::SUCCESS; +} + + +StatusCode TrackerSegmentFitDataAlg::finalize() { + return StatusCode::SUCCESS; +} + +} // namespace Tracker diff --git a/Tracker/TrackerRecAlgs/TrackerData/src/TrackerSegmentFitDataAlg.h b/Tracker/TrackerRecAlgs/TrackerData/src/TrackerSegmentFitDataAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..08ce4dd73290eadadc12c95a24932c5e52a781ea --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerData/src/TrackerSegmentFitDataAlg.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2022 CERN for the benefit of the FASER collaboration +*/ + +#ifndef TRACKERDATA_TRACKERSEGMENTFITDATAALG_H +#define TRACKERDATA_TRACKERSEGMENTFITDATAALG_H + + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "AthenaBaseComps/AthHistogramming.h" +#include "TrkTrack/TrackCollection.h" + +class TTree; +class FaserSCT_ID; +namespace TrackerDD { +class SCT_DetectorManager; +} + + +namespace Tracker { + +class TrackerSegmentFitDataAlg : public AthReentrantAlgorithm, AthHistogramming { +public: + TrackerSegmentFitDataAlg(const std::string &name, ISvcLocator *pSvcLocator); + virtual ~TrackerSegmentFitDataAlg() = default; + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext &ctx) const override; + virtual StatusCode finalize() override; + const ServiceHandle <ITHistSvc> &histSvc() const; + +private: + SG::ReadHandleKey<TrackCollection> m_trackCollection {this, "TrackCollection", "SegmentFit", "Input track collection name"}; + + ServiceHandle <ITHistSvc> m_histSvc; + + const TrackerDD::SCT_DetectorManager *m_detMgr; + const FaserSCT_ID *m_idHelper; + + mutable TTree* m_tracks; + mutable TTree* m_hits; + + mutable unsigned int m_run_number; + mutable unsigned int m_event_number; + + mutable double m_chi2; + mutable unsigned int m_nDOF; + mutable unsigned int m_nClusters; + mutable double m_track_x; + mutable double m_track_y; + mutable double m_track_z; + mutable double m_track_px; + mutable double m_track_py; + mutable double m_track_pz; + + mutable unsigned int m_station; + mutable unsigned int m_plane; + mutable unsigned int m_module; + mutable unsigned int m_row; + mutable unsigned int m_sensor; + mutable unsigned int m_strip; + mutable double m_x; + mutable double m_y; + mutable double m_z; +}; + + +inline const ServiceHandle <ITHistSvc> &TrackerSegmentFitDataAlg::histSvc() const { + return m_histSvc; +} + +} // namespace Tracker + +#endif // TRACKERDATA_TRACKERSEGMENTFITDATAALG_H diff --git a/Tracker/TrackerRecAlgs/TrackerData/src/TrackerTruthDataAlg.cxx b/Tracker/TrackerRecAlgs/TrackerData/src/TrackerTruthDataAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..188f8afb930a7c8006561076d582e2b685da4692 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerData/src/TrackerTruthDataAlg.cxx @@ -0,0 +1,123 @@ +#include "TrackerTruthDataAlg.h" +#include "TrackerSimEvent/FaserSiHitCollection.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "TrackerReadoutGeometry/SiDetectorElement.h" +#include <TTree.h> +#include <cmath> + + +namespace Tracker { + +TrackerTruthDataAlg::TrackerTruthDataAlg(const std::string &name, ISvcLocator *pSvcLocator) + : AthReentrantAlgorithm(name, pSvcLocator), AthHistogramming(name), + m_sct(nullptr), m_sID(nullptr), m_histSvc("THistSvc/THistSvc", name) {} + + +StatusCode TrackerTruthDataAlg::initialize() { + ATH_CHECK(detStore()->retrieve(m_sct, "SCT")); + ATH_CHECK(detStore()->retrieve(m_sID, "FaserSCT_ID")); + ATH_CHECK(m_mcEventCollectionKey.initialize()); + ATH_CHECK(m_faserSiHitKey.initialize()); + + m_hits = new TTree("hits", "hits"); + m_hits->Branch("run_number", &m_run_number, "run_number/I"); + m_hits->Branch("event_number", &m_event_number, "event_number/I"); + m_hits->Branch("station", &m_station, "station/I"); + m_hits->Branch("plane", &m_plane, "plane/I"); + m_hits->Branch("module", &m_module, "module/I"); + m_hits->Branch("row", &m_row, "row/I"); + m_hits->Branch("sensor", &m_sensor, "sensor/I"); + m_hits->Branch("pdg", &m_pdg, "pdg/I"); + m_hits->Branch("local_x", &m_local_x, "local_x/D"); + m_hits->Branch("local_y", &m_local_y, "local_y/D"); + m_hits->Branch("global_x", &m_global_x, "global_x/D"); + m_hits->Branch("global_y", &m_global_y, "global_y/D"); + m_hits->Branch("global_z", &m_global_z, "global_z/D"); + m_hits->Branch("phi", &m_phi, "phi/D"); + m_hits->Branch("theta", &m_theta, "theta/D"); + ATH_CHECK(histSvc()->regTree("/HIST1/hits", m_hits)); + + m_particles = new TTree("particles", "particles"); + m_particles->Branch("run_number", &m_run_number, "run_number/I"); + m_particles->Branch("event_number", &m_event_number, "event_number/I"); + m_particles->Branch("pdg", &m_pdg, "pdg/I"); + m_particles->Branch("x", &m_vertex_x, "x/D"); + m_particles->Branch("y", &m_vertex_y, "y/D"); + m_particles->Branch("z", &m_vertex_z, "z/D"); + m_particles->Branch("px", &m_px, "px/D"); + m_particles->Branch("py", &m_py, "py/D"); + m_particles->Branch("pz", &m_pz, "pz/D"); + ATH_CHECK(histSvc()->regTree("/HIST1/particles", m_particles)); + + return StatusCode::SUCCESS; +} + + +StatusCode TrackerTruthDataAlg::execute(const EventContext &ctx) const { + + m_run_number = ctx.eventID().run_number(); + m_event_number = ctx.eventID().event_number(); + + // Fill tree with simulated particles + SG::ReadHandle<McEventCollection> mcEventCollection(m_mcEventCollectionKey, ctx); + ATH_CHECK(mcEventCollection.isValid()); + for (const HepMC::GenEvent* event : *mcEventCollection) { + for (const HepMC::GenParticle* particle : event->particle_range()) { + m_pdg = particle->pdg_id(); + const auto vertex = particle->production_vertex()->position(); + m_vertex_x = vertex.x(); + m_vertex_y = vertex.y(); + m_vertex_z = vertex.z(); + const HepMC::FourVector& momentum = particle->momentum(); + m_px = momentum.x(); + m_py = momentum.y(); + m_pz = momentum.z(); + m_particles->Fill(); + } + } + + // Fill tree with simulated hits + SG::ReadHandle<FaserSiHitCollection> siHitCollection(m_faserSiHitKey, ctx); + ATH_CHECK(siHitCollection.isValid()); + for (const FaserSiHit &hit: *siHitCollection) { + if (!hit.particleLink().isValid()) + continue; + m_station = hit.getStation(); + m_plane = hit.getPlane(); + m_module = hit.getModule(); + m_row = hit.getRow(); + m_sensor = hit.getSensor(); + Identifier id = m_sID->wafer_id(m_station, m_plane, m_row, m_module, m_sensor); + const TrackerDD::SiDetectorElement *geoelement = m_sct->getDetectorElement(id); + if (!geoelement) + continue; + const auto localStartPos = hit.localStartPosition(); + const HepGeom::Point3D<double> globalStartPos = + Amg::EigenTransformToCLHEP(geoelement->transformHit()) * HepGeom::Point3D<double>(localStartPos); + const auto localEndPos = hit.localEndPosition(); + const HepGeom::Point3D<double> globalEndPos = + Amg::EigenTransformToCLHEP(geoelement->transformHit()) * HepGeom::Point3D<double>(localEndPos); + m_pdg = hit.particleLink()->pdg_id(); + HepGeom::Vector3D<double> v = globalEndPos - globalStartPos; + m_phi = std::atan(v.y()/v.x()); + m_theta = std::atan(std::sqrt(v.x() * v.x() + v.y() * v.y())/v.z()); + ATH_MSG_DEBUG("local pos: " << localStartPos); + ATH_MSG_DEBUG("global pos: " << globalStartPos); + m_local_x = m_sensor == 0 ? -localStartPos.y() : localStartPos.y(); + m_local_y = -localStartPos.z(); + m_global_x = globalStartPos.x(); + m_global_y = globalStartPos.y(); + m_global_z = globalStartPos.z(); + m_hits->Fill(); + } + + return StatusCode::SUCCESS; +} + + +StatusCode TrackerTruthDataAlg::finalize() { + return StatusCode::SUCCESS; +} + +} // namespace Tracker diff --git a/Tracker/TrackerRecAlgs/TrackerData/src/TrackerTruthDataAlg.h b/Tracker/TrackerRecAlgs/TrackerData/src/TrackerTruthDataAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..6c4f51d2a6f19a44931457b3d91c94b935b0c0a2 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerData/src/TrackerTruthDataAlg.h @@ -0,0 +1,74 @@ +/* + Copyright (C) 2022 CERN for the benefit of the FASER collaboration +*/ + +#ifndef TRACKERDATA_TRACKERTRUTHDATAALG_H +#define TRACKERDATA_TRACKERTRUTHDATAALG_H + + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "AthenaBaseComps/AthHistogramming.h" +#include "TrackerSimEvent/FaserSiHitCollection.h" +#include "GeneratorObjects/McEventCollection.h" + +class TTree; +class FaserSCT_ID; +namespace TrackerDD { +class SCT_DetectorManager; +} + + +namespace Tracker { + +class TrackerTruthDataAlg : public AthReentrantAlgorithm, AthHistogramming { +public: + TrackerTruthDataAlg(const std::string &name, ISvcLocator *pSvcLocator); + virtual ~TrackerTruthDataAlg() = default; + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext &ctx) const override; + virtual StatusCode finalize() override; + const ServiceHandle <ITHistSvc> &histSvc() const; + +private: + SG::ReadHandleKey<McEventCollection> m_mcEventCollectionKey {this, "McEventCollection", "BeamTruthEvent"}; + SG::ReadHandleKey <FaserSiHitCollection> m_faserSiHitKey{this, "FaserSiHitCollection", "SCT_Hits"}; + + ServiceHandle <ITHistSvc> m_histSvc; + + const TrackerDD::SCT_DetectorManager *m_sct; + const FaserSCT_ID *m_sID; + + mutable TTree *m_particles; + mutable TTree *m_hits; + + mutable unsigned int m_run_number; + mutable unsigned int m_event_number; + mutable unsigned int m_station; + mutable unsigned int m_plane; + mutable unsigned int m_module; + mutable unsigned int m_row; + mutable unsigned int m_sensor; + mutable int m_pdg; + mutable double m_local_x; + mutable double m_local_y; + mutable double m_global_x; + mutable double m_global_y; + mutable double m_global_z; + mutable double m_vertex_x; + mutable double m_vertex_y; + mutable double m_vertex_z; + mutable double m_px; + mutable double m_py; + mutable double m_pz; + mutable double m_phi; + mutable double m_theta; +}; + + +inline const ServiceHandle <ITHistSvc> &TrackerTruthDataAlg::histSvc() const { + return m_histSvc; +} + +} // namespace Tracker + +#endif // TRACKERDATA_TRACKERTRUTHDATAALG_H diff --git a/Tracker/TrackerRecAlgs/TrackerData/src/components/TrackerData_entries.cxx b/Tracker/TrackerRecAlgs/TrackerData/src/components/TrackerData_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..01018d29702f995ccf656c466989a2d06a74e30a --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerData/src/components/TrackerData_entries.cxx @@ -0,0 +1,5 @@ +#include "../TrackerTruthDataAlg.h" +#include "../TrackerSegmentFitDataAlg.h" + +DECLARE_COMPONENT(Tracker::TrackerTruthDataAlg ) +DECLARE_COMPONENT(Tracker::TrackerSegmentFitDataAlg) \ No newline at end of file diff --git a/Tracker/TrackerRecAlgs/TrackerData/test/TI12TrackerSegmentFitDataDbg.py b/Tracker/TrackerRecAlgs/TrackerData/test/TI12TrackerSegmentFitDataDbg.py new file mode 100644 index 0000000000000000000000000000000000000000..b20d313f99654d07487651c645616b93a266789f --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerData/test/TI12TrackerSegmentFitDataDbg.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +"""" +Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +""" +import sys +from AthenaCommon.Logging import log +from AthenaCommon.Constants import DEBUG +from AthenaCommon.Configurable import Configurable +from CalypsoConfiguration.AllConfigFlags import ConfigFlags +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 TrackerData.TrackerSegmentFitDataConfig import TrackerSegmentFitDataCfg + +log.setLevel(DEBUG) +Configurable.configurableRun3Behavior = True + +ConfigFlags.Input.Files = ['/home/tboeckh/tmp/Faser-Physics-006470-00093.raw_middleStation.SPs'] +ConfigFlags.Output.ESDFileName = "TrackerSegmentFitData.ESD.pool.root" +ConfigFlags.addFlag("Output.xAODFileName", f"TrackerSegmentFitData_xAOD.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() + +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(TrackerSegmentFitDataCfg(ConfigFlags)) +acc.getEventAlgo("Tracker::TrackerSegmentFitDataAlg").OutputLevel = DEBUG +itemList = ["xAOD::EventInfo#*", + "xAOD::EventAuxInfo#*", + "xAOD::FaserTriggerData#*", + "xAOD::FaserTriggerDataAux#*", + "FaserSCT_RDO_Container#*", + "Tracker::FaserSCT_ClusterContainer#*", + "TrackCollection#*" + ] +acc.merge(OutputStreamCfg(ConfigFlags, "xAOD", itemList)) + +replicaSvc = acc.getService("DBReplicaSvc") +replicaSvc.COOLSQLiteVetoPattern = "" +replicaSvc.UseCOOLSQLite = True +replicaSvc.UseCOOLFrontier = False +replicaSvc.UseGeomSQLite = True + +sc = acc.run(maxEvents=-1) +sys.exit(not sc.isSuccess()) diff --git a/Tracker/TrackerRecAlgs/TrackerData/test/TrackerSegmentFitDataDbg.py b/Tracker/TrackerRecAlgs/TrackerData/test/TrackerSegmentFitDataDbg.py new file mode 100644 index 0000000000000000000000000000000000000000..bac4dd4035a48d731d77cdc98af54fd649f73948 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerData/test/TrackerSegmentFitDataDbg.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +"""" +Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +""" +import sys +from AthenaCommon.Logging import log +from AthenaCommon.Constants import DEBUG +from AthenaCommon.Configurable import Configurable +from CalypsoConfiguration.AllConfigFlags import ConfigFlags +from CalypsoConfiguration.MainServicesConfig import MainServicesCfg +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 TrackerData.TrackerSegmentFitDataConfig import TrackerSegmentFitDataCfg + +log.setLevel(DEBUG) +Configurable.configurableRun3Behavior = True + +ConfigFlags.Input.Files = ["my.RDO.pool.root"] +ConfigFlags.Output.ESDFileName = "TrackerSegmentFitData.ESD.pool.root" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" +ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" +ConfigFlags.Input.ProjectName = "data22" +ConfigFlags.Input.isMC = True +ConfigFlags.GeoModel.FaserVersion = "FASER-01" +ConfigFlags.Common.isOnline = False +ConfigFlags.GeoModel.Align.Dynamic = False +ConfigFlags.Beam.NumberOfCollisions = 0. +ConfigFlags.Detector.GeometryFaserSCT = True +ConfigFlags.addFlag("Output.xAODFileName", f"TrackerSegmentFitData_xAOD.root") +ConfigFlags.lock() + +acc = MainServicesCfg(ConfigFlags) +acc.merge(PoolReadCfg(ConfigFlags)) +acc.merge(PoolWriteCfg(ConfigFlags)) + +acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags, DataObjectName="SCT_RDOs")) +acc.merge(SegmentFitAlgCfg(ConfigFlags, SharedHitFraction=0.5, MinClustersPerFit=5, TanThetaCut=0.25)) +acc.merge(TrackerSegmentFitDataCfg(ConfigFlags)) +acc.getEventAlgo("Tracker::TrackerSegmentFitDataAlg").OutputLevel = DEBUG +itemList = ["xAOD::EventInfo#*", + "xAOD::EventAuxInfo#*", + "xAOD::FaserTriggerData#*", + "xAOD::FaserTriggerDataAux#*", + "FaserSCT_RDO_Container#*", + "Tracker::FaserSCT_ClusterContainer#*", + "TrackCollection#*" + ] +acc.merge(OutputStreamCfg(ConfigFlags, "ESD", itemList)) + +sc = acc.run(maxEvents=-1) +sys.exit(not sc.isSuccess()) diff --git a/Tracker/TrackerRecAlgs/TrackerData/test/TrackerTruthDataDbg.py b/Tracker/TrackerRecAlgs/TrackerData/test/TrackerTruthDataDbg.py new file mode 100644 index 0000000000000000000000000000000000000000..a6b366d6ba9543d4bba4f87384d25b0e9b756603 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerData/test/TrackerTruthDataDbg.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +"""" +Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +""" +import sys +from AthenaCommon.Logging import log +from AthenaCommon.Constants import DEBUG +from AthenaCommon.Configurable import Configurable +from CalypsoConfiguration.AllConfigFlags import ConfigFlags +from CalypsoConfiguration.MainServicesConfig import MainServicesCfg +from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg +from TrackerData.TrackerTruthDataConfig import TrackerTruthDataCfg + +log.setLevel(DEBUG) +Configurable.configurableRun3Behavior = True + +ConfigFlags.Input.Files = ["my.HITS.pool.root"] +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" +ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" +ConfigFlags.Input.ProjectName = "data22" +ConfigFlags.Input.isMC = True +ConfigFlags.GeoModel.FaserVersion = "FASER-01" +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(PoolReadCfg(ConfigFlags)) + +acc.merge(TrackerTruthDataCfg(ConfigFlags)) +acc.getEventAlgo("Tracker::TrackerTruthDataAlg").OutputLevel = DEBUG + +# Execute and finish +sc = acc.run(maxEvents=-1) +sys.exit(not sc.isSuccess()) diff --git a/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.cxx b/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.cxx index ff163e105d51b02267ce35e3fdfe43737c5a184c..f12ccaa7d336bce3f9be4f0758d4ca06e1b878b9 100644 --- a/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.cxx +++ b/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.cxx @@ -507,16 +507,19 @@ SegmentFitAlg::selectFits(const FitMap& fits) const auto content = *it; ATH_MSG_VERBOSE("clusters: " << content->clusterMask.count() << " / chi2: " << content->fitChi2) ; } - ClusterSet usedClusters { clusterInfo::nClusters }; while (info.size() > 0) { auto selected = info.front(); ATH_MSG_VERBOSE("Selected nclust = " << selected->clusterMask.count() << " with chi2 = " << selected->fitChi2); selectedFits[selected->clusterMask] = selected; - usedClusters |= selected->clusterMask; - info.remove_if([&](std::shared_ptr<fitInfo> p) {return (p->clusterMask & ~usedClusters) != p->clusterMask;}); + // remove fits for which the fraction of shared hits is larger than m_sharedFraction or the number of hits is + // smaller than m_minClustersPerFit + info.remove_if([&](std::shared_ptr<fitInfo> p) {return + ((p->clusterMask & selected->clusterMask).count() > m_sharedHitFraction * p->clusterMask.count()) + || (p->clusterMask.count() < m_minClustersPerFit) ;} + ); } m_numberOfSelectedFits += selectedFits.size(); diff --git a/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.h b/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.h index eb41946cd0a9094a24919eaf6824705094afa234..757eb1a22752acbe72e0da7a0c6c7a89878bf76a 100644 --- a/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.h +++ b/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.h @@ -414,6 +414,8 @@ class SegmentFitAlg : public AthReentrantAlgorithm DoubleProperty m_yResidualCut { this, "ResidualCut", 3 * Gaudi::Units::mm, "Cluster y tolerance for compatibility with extrapolated fit." }; DoubleProperty m_tanThetaCut { this, "TanThetaCut", 0.0, "Maximum accepted tangent of track angle from beam axis; 0 means no cut."}; DoubleProperty m_reducedChi2Cut { this, "ReducedChi2Cut", 10.0, "Maximum accepted chi^2 per degree of freedom for final fits; 0 means no cut." }; + DoubleProperty m_sharedHitFraction { this, "SharedHitFraction", -1., "Fraction of hits which are allowed to be shared between two fits." }; + IntegerProperty m_minClustersPerFit { this, "MinClustersPerFit", 4, "Minimum number of clusters a fit has to have." }; mutable std::atomic<int> m_numberOfEvents{0}; mutable std::atomic<int> m_numberExcessOccupancy{0}; diff --git a/Tracker/TrackerRecAlgs/TrackerSegmentFit/test/MCTrackerSegmentFit.py b/Tracker/TrackerRecAlgs/TrackerSegmentFit/test/MCTrackerSegmentFit.py new file mode 100644 index 0000000000000000000000000000000000000000..05d4be97bc18d8598512b8a22a79f8cdf6436af7 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerSegmentFit/test/MCTrackerSegmentFit.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +"""Test various ComponentAccumulator Digitization configuration modules + +Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +""" +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 Digitization.DigitizationParametersConfig import writeDigitizationMetadata +from WaveRecAlgs.WaveRecAlgsConfig import WaveformReconstructionCfg +from TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg +from TrackerSegmentFit.TrackerSegmentFitConfig import SegmentFitAlgCfg +from TrackerSpacePointFormation.TrackerSpacePointFormationConfig import TrackerSpacePointFinderCfg +#from MCTruthSimAlgs.RecoTimingConfig import MergeRecoTimingObjCfg + +# Set up logging and new style config +log.setLevel(DEBUG) +Configurable.configurableRun3Behavior = True + +# Configure +ConfigFlags.Input.Files = ['my.RDO.pool.root'] +ConfigFlags.Output.ESDFileName = "segmentFit.ESD.pool.root" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" +ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" +ConfigFlags.Input.ProjectName = "data21" +ConfigFlags.Input.isMC = True +ConfigFlags.GeoModel.FaserVersion = "FASER-01" +ConfigFlags.Common.isOnline = False +ConfigFlags.GeoModel.Align.Dynamic = False +ConfigFlags.Beam.NumberOfCollisions = 0. +ConfigFlags.addFlag("Output.xAODFileName", "segmentFit.xAOD.pool.root") +# ConfigFlags.Detector.GeometryFaserSCT = True +ConfigFlags.lock() + +# Core components +acc = MainServicesCfg(ConfigFlags) +acc.merge(PoolReadCfg(ConfigFlags)) +acc.merge(PoolWriteCfg(ConfigFlags)) + +acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags)) +acc.merge(SegmentFitAlgCfg(ConfigFlags)) +#acc.getEventAlgo("Tracker::SegmentFitAlg").OutputLevel = DEBUG + +from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg +itemList = ["xAOD::EventInfo#*", + "xAOD::EventAuxInfo#*", + "xAOD::FaserTriggerData#*", + "xAOD::FaserTriggerDataAux#*", + "FaserSCT_RDO_Container#*", + "Tracker::FaserSCT_ClusterContainer#*", + "TrackCollection#*" + ] +acc.merge(OutputStreamCfg(ConfigFlags, "ESD", itemList)) + +# Dump config +# 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() + +# Execute and finish +sc = acc.run(maxEvents=-1) +sys.exit(not sc.isSuccess()) diff --git a/Tracker/TrackerRecAlgs/TrackerTruth/CMakeLists.txt b/Tracker/TrackerRecAlgs/TrackerTruth/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b52a694c458489bb341116be7568c18ffd9de8e6 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerTruth/CMakeLists.txt @@ -0,0 +1,12 @@ +atlas_subdir(TrackerTruth) + +atlas_add_component( + TrackerTruth + src/TrackerTruthAlg.h + src/TrackerTruthAlg.cxx + src/components/TrackerTruth_entries.cxx + LINK_LIBRARIES AthenaBaseComps GeneratorObjects TrackerSimEvent TrackerIdentifier TrackerReadoutGeometry +) + +atlas_install_python_modules( python/*.py ) +atlas_install_scripts( test/*.py ) \ No newline at end of file diff --git a/Tracker/TrackerRecAlgs/TrackerTruth/ReadMe b/Tracker/TrackerRecAlgs/TrackerTruth/ReadMe new file mode 100644 index 0000000000000000000000000000000000000000..a763932b380cc4982774d5e409328dadea867411 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerTruth/ReadMe @@ -0,0 +1,6 @@ +This package can be used to write out the truth information of particles and hits from MC generated events. +For particles the run number, event number, pdg code, vertex and momentum is written out and for hits the +run number, event number, station, plane, module, row, sensor, local position, global position and pdg code of the +corresponding particle is written out. + +To write out truth information generate MC data using the G4FaserAlgConfigNew_Test.py and run TrackerTruthDbg.py diff --git a/Tracker/TrackerRecAlgs/TrackerTruth/python/TrackerTruthConfig.py b/Tracker/TrackerRecAlgs/TrackerTruth/python/TrackerTruthConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..475e7ba6f60844cdea8c4b5da0ef4f43da70d2f5 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerTruth/python/TrackerTruthConfig.py @@ -0,0 +1,19 @@ +""" +Copyright (C) 2022 CERN for the benefit of the FASER collaboration +""" + +from AthenaConfiguration.ComponentFactory import CompFactory +from FaserSCT_GeoModel.FaserSCT_GeoModelConfig import FaserSCT_GeometryCfg + + +def TrackerTruthCfg(flags, **kwargs): + acc = FaserSCT_GeometryCfg(flags) + kwargs.setdefault("FaserSiHitCollection", "SCT_Hits") + TrackerTruthAlg = CompFactory.Tracker.TrackerTruthAlg + acc.addEventAlgo(TrackerTruthAlg(**kwargs)) + + thistSvc = CompFactory.THistSvc() + thistSvc.Output += ["HIST1 DATAFILE='TrackerTruth.root' OPT='RECREATE'"] + acc.addService(thistSvc) + + return acc diff --git a/Tracker/TrackerRecAlgs/TrackerTruth/python/__init__.py b/Tracker/TrackerRecAlgs/TrackerTruth/python/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Tracker/TrackerRecAlgs/TrackerTruth/src/TrackerTruthAlg.cxx b/Tracker/TrackerRecAlgs/TrackerTruth/src/TrackerTruthAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..cc600bad74f6e16341757becc305ea0343416889 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerTruth/src/TrackerTruthAlg.cxx @@ -0,0 +1,112 @@ +#include "TrackerTruthAlg.h" +#include "TrackerSimEvent/FaserSiHitCollection.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "TrackerReadoutGeometry/SiDetectorElement.h" +#include <TTree.h> + + +namespace Tracker { + +TrackerTruthAlg::TrackerTruthAlg(const std::string &name, ISvcLocator *pSvcLocator) + : AthReentrantAlgorithm(name, pSvcLocator), AthHistogramming(name), + m_sct(nullptr), m_sID(nullptr), m_histSvc("THistSvc/THistSvc", name) {} + + +StatusCode TrackerTruthAlg::initialize() { + ATH_CHECK(detStore()->retrieve(m_sct, "SCT")); + ATH_CHECK(detStore()->retrieve(m_sID, "FaserSCT_ID")); + ATH_CHECK(m_mcEventCollectionKey.initialize()); + ATH_CHECK(m_faserSiHitKey.initialize()); + + m_hits = new TTree("hits", "hits"); + m_hits->Branch("run_number", &m_run_number, "run_number/I"); + m_hits->Branch("event_number", &m_event_number, "event_number/I"); + m_hits->Branch("station", &m_station, "station/I"); + m_hits->Branch("plane", &m_plane, "plane/I"); + m_hits->Branch("module", &m_module, "module/I"); + m_hits->Branch("row", &m_row, "row/I"); + m_hits->Branch("sensor", &m_sensor, "sensor/I"); + m_hits->Branch("pdg", &m_pdg, "pdg/I"); + m_hits->Branch("local_x", &m_local_x, "local_x/D"); + m_hits->Branch("local_y", &m_local_y, "local_y/D"); + m_hits->Branch("global_x", &m_global_x, "global_x/D"); + m_hits->Branch("global_y", &m_global_y, "global_y/D"); + m_hits->Branch("global_z", &m_global_z, "global_z/D"); + ATH_CHECK(histSvc()->regTree("/HIST1/hits", m_hits)); + + m_particles = new TTree("particles", "particles"); + m_particles->Branch("run_number", &m_run_number, "run_number/I"); + m_particles->Branch("event_number", &m_event_number, "event_number/I"); + m_particles->Branch("pdg", &m_pdg, "pdg/I"); + m_particles->Branch("x", &m_vertex_x, "x/D"); + m_particles->Branch("y", &m_vertex_y, "y/D"); + m_particles->Branch("z", &m_vertex_z, "z/D"); + m_particles->Branch("px", &m_px, "px/D"); + m_particles->Branch("py", &m_px, "py/D"); + m_particles->Branch("pz", &m_px, "pz/D"); + ATH_CHECK(histSvc()->regTree("/HIST1/particles", m_particles)); + + return StatusCode::SUCCESS; +} + + +StatusCode TrackerTruthAlg::execute(const EventContext &ctx) const { + + m_run_number = ctx.eventID().run_number(); + m_event_number = ctx.eventID().event_number(); + + // Fill tree with simulated particles + SG::ReadHandle<McEventCollection> mcEventCollection(m_mcEventCollectionKey, ctx); + ATH_CHECK(mcEventCollection.isValid()); + for (const HepMC::GenEvent* event : *mcEventCollection) { + for (const HepMC::GenParticle* particle : event->particle_range()) { + m_pdg = particle->pdg_id(); + const auto vertex = particle->production_vertex()->position(); + m_vertex_x = vertex.x(); + m_vertex_y = vertex.y(); + m_vertex_z = vertex.z(); + const HepMC::FourVector& momentum = particle->momentum(); + m_px = momentum.x(); + m_py = momentum.y(); + m_pz = momentum.z(); + m_particles->Fill(); + } + } + + // Fill tree with simulated hits + SG::ReadHandle<FaserSiHitCollection> siHitCollection(m_faserSiHitKey, ctx); + ATH_CHECK(siHitCollection.isValid()); + for (const FaserSiHit &hit: *siHitCollection) { + if (!hit.particleLink().isValid()) + continue; + const HepGeom::Point3D<double> localStartPos = hit.localStartPosition(); + Identifier id = m_sID->wafer_id(hit.getStation(), hit.getPlane(), hit.getRow(), hit.getModule(), hit.getSensor()); + const TrackerDD::SiDetectorElement *geoelement = m_sct->getDetectorElement(id); + if (!geoelement) + continue; + const HepGeom::Point3D<double> globalStartPos = + Amg::EigenTransformToCLHEP(geoelement->transformHit()) * HepGeom::Point3D<double>(localStartPos); + m_station = hit.getStation(); + m_plane = hit.getPlane(); + m_module = hit.getModule(); + m_row = hit.getRow(); + m_sensor = hit.getSensor(); + m_pdg = hit.particleLink()->pdg_id(); + m_local_x = localStartPos.x(); + m_local_y = localStartPos.y(); + m_global_x = globalStartPos.x(); + m_global_y = globalStartPos.y(); + m_global_z = globalStartPos.z(); + m_hits->Fill(); + } + + return StatusCode::SUCCESS; +} + + +StatusCode TrackerTruthAlg::finalize() { + return StatusCode::SUCCESS; +} + +} // namespace Tracker diff --git a/Tracker/TrackerRecAlgs/TrackerTruth/src/TrackerTruthAlg.h b/Tracker/TrackerRecAlgs/TrackerTruth/src/TrackerTruthAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..7f21acc718500b5881bdb4956980fc1893c80747 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerTruth/src/TrackerTruthAlg.h @@ -0,0 +1,72 @@ +/* + Copyright (C) 2022 CERN for the benefit of the FASER collaboration +*/ + +#ifndef TRACKERTRUTH_TRACKERTRUTHALG_H +#define TRACKERTRUTH_TRACKERTRUTHALG_H + + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "AthenaBaseComps/AthHistogramming.h" +#include "TrackerSimEvent/FaserSiHitCollection.h" +#include "GeneratorObjects/McEventCollection.h" + +class TTree; +class FaserSCT_ID; +namespace TrackerDD { +class SCT_DetectorManager; +} + + +namespace Tracker { + +class TrackerTruthAlg : public AthReentrantAlgorithm, AthHistogramming { +public: + TrackerTruthAlg(const std::string &name, ISvcLocator *pSvcLocator); + virtual ~TrackerTruthAlg() = default; + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext &ctx) const override; + virtual StatusCode finalize() override; + const ServiceHandle <ITHistSvc> &histSvc() const; + +private: + SG::ReadHandleKey<McEventCollection> m_mcEventCollectionKey {this, "McEventCollection", "BeamTruthEvent"}; + SG::ReadHandleKey <FaserSiHitCollection> m_faserSiHitKey{this, "FaserSiHitCollection", "SCT_Hits"}; + + ServiceHandle <ITHistSvc> m_histSvc; + + const TrackerDD::SCT_DetectorManager *m_sct; + const FaserSCT_ID *m_sID; + + mutable TTree *m_particles; + mutable TTree *m_hits; + + mutable unsigned int m_run_number; + mutable unsigned int m_event_number; + mutable unsigned int m_station; + mutable unsigned int m_plane; + mutable unsigned int m_module; + mutable unsigned int m_row; + mutable unsigned int m_sensor; + mutable int m_pdg; + mutable double m_local_x; + mutable double m_local_y; + mutable double m_global_x; + mutable double m_global_y; + mutable double m_global_z; + mutable double m_vertex_x; + mutable double m_vertex_y; + mutable double m_vertex_z; + mutable double m_px; + mutable double m_py; + mutable double m_pz; +}; + + +inline const ServiceHandle <ITHistSvc> &TrackerTruthAlg::histSvc() const { + return m_histSvc; +} + +} // namespace Tracker + +#endif diff --git a/Tracker/TrackerRecAlgs/TrackerTruth/src/components/TrackerTruth_entries.cxx b/Tracker/TrackerRecAlgs/TrackerTruth/src/components/TrackerTruth_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..0f49f0e7edefeccc3908ebc6822928ad08abbe7c --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerTruth/src/components/TrackerTruth_entries.cxx @@ -0,0 +1,3 @@ +#include "../TrackerTruthAlg.h" + +DECLARE_COMPONENT(Tracker::TrackerTruthAlg ) \ No newline at end of file diff --git a/Tracker/TrackerRecAlgs/TrackerTruth/test/TrackerTruthDbg.py b/Tracker/TrackerRecAlgs/TrackerTruth/test/TrackerTruthDbg.py new file mode 100644 index 0000000000000000000000000000000000000000..479edc81bb284720c94ef4b16196a5aa7ac0f5d3 --- /dev/null +++ b/Tracker/TrackerRecAlgs/TrackerTruth/test/TrackerTruthDbg.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +"""" +Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +""" +import sys +from AthenaCommon.Logging import log +from AthenaCommon.Constants import DEBUG +from AthenaCommon.Configurable import Configurable +from CalypsoConfiguration.AllConfigFlags import ConfigFlags +from CalypsoConfiguration.MainServicesConfig import MainServicesCfg +from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg +from TrackerTruth.TrackerTruthConfig import TrackerTruthCfg + +log.setLevel(DEBUG) +Configurable.configurableRun3Behavior = True + +ConfigFlags.Input.Files = ["my.HITS.pool.root"] +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" +ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" +ConfigFlags.Input.ProjectName = "data22" +ConfigFlags.Input.isMC = True +ConfigFlags.GeoModel.FaserVersion = "FASER-01" +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(PoolReadCfg(ConfigFlags)) + +acc.merge(TrackerTruthCfg(ConfigFlags)) +acc.getEventAlgo("Tracker::TrackerTruthAlg").OutputLevel = DEBUG + +# Execute and finish +sc = acc.run(maxEvents=-1) +sys.exit(not sc.isSuccess()) diff --git a/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/TruthSeededTrackFinder.cxx b/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/TruthSeededTrackFinder.cxx index d23327e1c5b6c8d59bcf7e41e7a9dbf58ca164bf..c88414a505231ab1fee984801da34f83982394ce 100755 --- a/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/TruthSeededTrackFinder.cxx +++ b/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/TruthSeededTrackFinder.cxx @@ -113,10 +113,10 @@ namespace Tracker ATH_CHECK( m_faserSiHitKey.initialize() ); ATH_CHECK( m_faserRdoKey.initialize()); ATH_CHECK( m_sctMap.initialize()); - ATH_MSG_INFO( "Using GenEvent collection with key " << m_mcEventKey.key()); - ATH_MSG_INFO( "Using Faser SiHit collection with key " << m_faserSiHitKey.key()); - ATH_MSG_INFO( "Using FaserSCT RDO Container with key " << m_faserRdoKey.key()); - ATH_MSG_INFO( "Using SCT_SDO_Map with key "<< m_sctMap.key()); + ATH_MSG_DEBUG( "Using GenEvent collection with key " << m_mcEventKey.key()); + ATH_MSG_DEBUG( "Using Faser SiHit collection with key " << m_faserSiHitKey.key()); + ATH_MSG_DEBUG( "Using FaserSCT RDO Container with key " << m_faserRdoKey.key()); + ATH_MSG_DEBUG( "Using SCT_SDO_Map with key "<< m_sctMap.key()); m_hist_n=new TH1D("sp_n","sp_n",20,0,20); m_hist_x=new TH1D("sp_x","sp_x",100,-200,200); @@ -180,7 +180,7 @@ namespace Tracker CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/InitReso_py",m_hist_InitReso_py)); CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/InitReso_pz",m_hist_InitReso_pz)); //!!!!!!!!!!!!!!!!!!!! - ATH_MSG_INFO( "TruthTrackSeeds::initialized" ); + ATH_MSG_DEBUG( "TruthTrackSeeds::initialized" ); return StatusCode::SUCCESS; } @@ -194,11 +194,11 @@ namespace Tracker // Handles created from handle keys behave like pointers to the corresponding container SG::ReadHandle<McEventCollection> h_mcEvents(m_mcEventKey, ctx); - ATH_MSG_INFO("Read McEventContainer with " << h_mcEvents->size() << " events"); + ATH_MSG_DEBUG("Read McEventContainer with " << h_mcEvents->size() << " events"); if (h_mcEvents->size() == 0) return StatusCode::FAILURE; SG::ReadHandle<FaserSiHitCollection> h_siHits(m_faserSiHitKey, ctx); - ATH_MSG_INFO("Read FaserSiHitCollection with " << h_siHits->size() << " hits"); + ATH_MSG_DEBUG("Read FaserSiHitCollection with " << h_siHits->size() << " hits"); SG::ReadHandle<FaserSCT_RDO_Container> h_sctRDO(m_faserRdoKey, ctx); @@ -206,7 +206,7 @@ namespace Tracker SG::WriteHandle<SpacePointForSeedCollection> seedContainer_SCT(m_seed_spcontainerKey, ctx ); ATH_CHECK( seedContainer_SCT.record( std::make_unique<SpacePointForSeedCollection>() ) ); - ATH_MSG_INFO("Created SpacePointContainer " << m_seed_spcontainerKey.key() << " N= " << m_idHelper->wafer_hash_max()); + ATH_MSG_DEBUG("Created SpacePointContainer " << m_seed_spcontainerKey.key() << " N= " << m_idHelper->wafer_hash_max()); const TrackerDD::SiDetectorElementCollection* elements = nullptr; @@ -288,12 +288,12 @@ namespace Tracker SG::ReadHandle<TrackerSimDataCollection> h_collectionMap(m_sctMap, ctx); ATH_MSG_DEBUG("map size "<<h_collectionMap->size()); //!!!!!!!!!!!!!!!!!!!! - std::cout<<"!!!!!!!!! cluster: "<<sp->clusterList().first<<std::endl; +// std::cout<<"!!!!!!!!! cluster: "<<sp->clusterList().first<<std::endl; ATH_MSG_DEBUG("!!!!!!!!! cluster: "<<sp->clusterList().first->rdoList() ); //!!!!!!!!!!!!!!!!!!!! if( h_collectionMap->count(identifier) == 0) { - ATH_MSG_INFO("no map found w/identifier "<<identifier); + ATH_MSG_DEBUG("no map found w/identifier "<<identifier); ++m_numberOfNoMap; continue; } @@ -309,14 +309,14 @@ namespace Tracker for( const auto& depositPair : deposits) { //!!!!!!!!!!!!!!!!!!!!!!!! - depositPair.first->print(std::cout); - std::cout<<"!!!!!!!!!!! pdg id = "<<depositPair.first->pdg_id()<<std::endl; +// depositPair.first->print(std::cout); +// std::cout<<"!!!!!!!!!!! pdg id = "<<depositPair.first->pdg_id()<<std::endl; if (depositPair.first->pdg_id() == -13) { HepMC::FourVector pv = depositPair.first->production_vertex()->position(); HepMC::FourVector ev = depositPair.first->end_vertex()->position (); truthmom = depositPair.first->momentum(); - std::cout<<"!!!!!!!!!!! production_vertex: ( "<<pv.x()<<", "<<pv.y()<<", "<<pv.z()<<" ) "<<std::endl; - std::cout<<"!!!!!!!!!!! end_vertex: ( "<<ev.x()<<", "<<ev.y()<<", "<<ev.z()<<" ) "<<std::endl; +// std::cout<<"!!!!!!!!!!! production_vertex: ( "<<pv.x()<<", "<<pv.y()<<", "<<pv.z()<<" ) "<<std::endl; +// std::cout<<"!!!!!!!!!!! end_vertex: ( "<<ev.x()<<", "<<ev.y()<<", "<<ev.z()<<" ) "<<std::endl; } //!!!!!!!!!!!!!!!!!!!!!!!! if( depositPair.second > highestDep) @@ -339,12 +339,12 @@ namespace Tracker { // TODO: Check that daughter->production_vertex() and daughter->end_vertex() exist, and bracket the point you're interested in if (daughter->barcode() % 1000000 == primary->barcode()) { - ATH_MSG_INFO(" daughter barcode: " << daughter->barcode() << " with energy " << daughter->momentum().e() << " px = " << daughter->momentum().px() << " py = " << daughter->momentum().py() << " pz = " << daughter->momentum().pz() ); + ATH_MSG_DEBUG(" daughter barcode: " << daughter->barcode() << " with energy " << daughter->momentum().e() << " px = " << daughter->momentum().px() << " py = " << daughter->momentum().py() << " pz = " << daughter->momentum().pz() ); if (daughter->production_vertex() != nullptr && daughter->end_vertex() != nullptr) { HepMC::FourVector pv = daughter->production_vertex()->position(); HepMC::FourVector ev = daughter->end_vertex()->position (); - std::cout<<"!!!!!!!!!!! production_vertex: ( "<<pv.x()<<", "<<pv.y()<<", "<<pv.z()<<" ) "<<std::endl; - std::cout<<"!!!!!!!!!!! end_vertex: ( "<<ev.x()<<", "<<ev.y()<<", "<<ev.z()<<" ) "<<std::endl; +// std::cout<<"!!!!!!!!!!! production_vertex: ( "<<pv.x()<<", "<<pv.y()<<", "<<pv.z()<<" ) "<<std::endl; +// std::cout<<"!!!!!!!!!!! end_vertex: ( "<<ev.x()<<", "<<ev.y()<<", "<<ev.z()<<" ) "<<std::endl; } } } @@ -387,8 +387,8 @@ namespace Tracker m_lp_end=hit.localEndPosition(); m_new_pos=m_lp_start+(m_lp_end-m_lp_start)*m_ran_pos; //muPos=Amg::EigenTransformToCLHEP(geoelement->transformHit()) * HepGeom::Point3D<double>(m_new_pos); - std::cout<<"!!!!!!!!!!! hit start pos: "<<Amg::EigenTransformToCLHEP(geoelement->transformHit()) * HepGeom::Point3D<double>(m_lp_start)<<std::endl; - std::cout<<"!!!!!!!!!!! hit end pos: "<<Amg::EigenTransformToCLHEP(geoelement->transformHit()) * HepGeom::Point3D<double>(m_lp_end)<<std::endl; +// std::cout<<"!!!!!!!!!!! hit start pos: "<<Amg::EigenTransformToCLHEP(geoelement->transformHit()) * HepGeom::Point3D<double>(m_lp_start)<<std::endl; +// std::cout<<"!!!!!!!!!!! hit end pos: "<<Amg::EigenTransformToCLHEP(geoelement->transformHit()) * HepGeom::Point3D<double>(m_lp_end)<<std::endl; } //!!!!!!!!!!!!!!!!!!!!!!!! } @@ -430,8 +430,8 @@ namespace Tracker if (istation==2 && ilayer==0) { match_N_2_0++; } if (istation==2 && ilayer==1) { match_N_2_1++; } if (istation==2 && ilayer==2) { match_N_2_2++; } - std::cout<<"!!!!!!!!!!! (station, layer) = ("<<istation<<", "<<ilayer<<") positopn = ("<<gloPos.x()<<", "<<gloPos.y()<<", "<<gloPos.z()<<") "<<std::endl; - if (std::fabs(gloPos.x())>100) std::cout<<"!!!!!!!!!!! badXXX "<<std::endl; +// std::cout<<"!!!!!!!!!!! (station, layer) = ("<<istation<<", "<<ilayer<<") positopn = ("<<gloPos.x()<<", "<<gloPos.y()<<", "<<gloPos.z()<<") "<<std::endl; +// if (std::fabs(gloPos.x())>100) std::cout<<"!!!!!!!!!!! badXXX "<<std::endl; //!!!!!!!!!!!!!!!!!!!! } ATH_MSG_VERBOSE( nReceivedSPSCT << " SpacePoints successfully added to Container !" ); @@ -441,8 +441,8 @@ namespace Tracker m_hist_n->Fill(nTruthSP); //!!!!!!!!!!!!!!!!!!!!!!!! - std::cout<<"!!!!!!!!!!! N_1_0 = "<<N_1_0<<", N_1_1 = "<<N_1_1<<", N_1_2 = "<<N_1_2<<", N_2_0 = "<<N_2_0<<", N_2_1 = "<<N_2_1<<", N_2_2 = "<<N_2_2<<std::endl; - std::cout<<"!!!!!!!!!!! match_N_1_0 = "<<match_N_1_0<<", match_N_1_1 = "<<match_N_1_1<<", match_N_1_2 = "<<match_N_1_2<<", match_N_2_0 = "<<match_N_2_0<<", match_N_2_1 = "<<match_N_2_1<<", match_N_2_2 = "<<match_N_2_2<<std::endl; +// std::cout<<"!!!!!!!!!!! N_1_0 = "<<N_1_0<<", N_1_1 = "<<N_1_1<<", N_1_2 = "<<N_1_2<<", N_2_0 = "<<N_2_0<<", N_2_1 = "<<N_2_1<<", N_2_2 = "<<N_2_2<<std::endl; +// std::cout<<"!!!!!!!!!!! match_N_1_0 = "<<match_N_1_0<<", match_N_1_1 = "<<match_N_1_1<<", match_N_1_2 = "<<match_N_1_2<<", match_N_2_0 = "<<match_N_2_0<<", match_N_2_1 = "<<match_N_2_1<<", match_N_2_2 = "<<match_N_2_2<<std::endl; if ( (N_1_0==1 && match_N_1_0==1) && (N_1_1==1 && match_N_1_1==1) && (N_1_2==1 && match_N_1_2==1) && (N_2_0==1 && match_N_2_0==1) && (N_2_1==1 && match_N_2_1==1) && (N_2_2==1 && match_N_2_2==1)) { Acts::Vector3 pos1_0(0., 0., 0.); Acts::Vector3 pos1_1(0., 0., 0.); @@ -482,12 +482,12 @@ namespace Tracker } } - 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; +// 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; double charge = 1; double B = 0.57; @@ -527,21 +527,21 @@ namespace Tracker // the direction of momentum in the first station Acts::Vector3 direct1 = d1.normalized(); - std::cout<<"!!!!!!!!!!! direct1 = ("<<direct1.x()<<", "<<direct1.y()<<", "<<direct1.z()<<") "<<std::endl; +// std::cout<<"!!!!!!!!!!! direct1 = ("<<direct1.x()<<", "<<direct1.y()<<", "<<direct1.z()<<") "<<std::endl; // the direction of momentum in the second station Acts::Vector3 direct2 = d2.normalized(); - std::cout<<"!!!!!!!!!!! direct2 = ("<<direct2.x()<<", "<<direct2.y()<<", "<<direct2.z()<<") "<<std::endl; +// std::cout<<"!!!!!!!!!!! direct2 = ("<<direct2.x()<<", "<<direct2.y()<<", "<<direct2.z()<<") "<<std::endl; // 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()); - std::cout<<"!!!!!!!!!!! (R1_y, R1_z) = ("<<R1_y<<", "<<R1_z<<") "<<std::endl; +// std::cout<<"!!!!!!!!!!! (R1_y, R1_z) = ("<<R1_y<<", "<<R1_z<<") "<<std::endl; // 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()); - std::cout<<"!!!!!!!!!!! (R2_y, R2_z) = ("<<R2_y<<", "<<R2_z<<") "<<std::endl; +// std::cout<<"!!!!!!!!!!! (R2_y, R2_z) = ("<<R2_y<<", "<<R2_z<<") "<<std::endl; // the norm of radius double R = (pos2_0.z() - pos1_2.z()) / (R2_z - R1_z); - std::cout<<"!!!!!!!!!!! R = "<<R<<std::endl; +// std::cout<<"!!!!!!!!!!! R = "<<R<<std::endl; // 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()); @@ -550,8 +550,8 @@ namespace Tracker // 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; - std::cout<<"!!!!!!!!!!! truth momentum: ( "<<truthmom.px()<<", "<<truthmom.py()<<", "<<truthmom.pz()<<", "<<truthmom.m()<<" ) "<<std::endl; +// std::cout<<"!!!!!!!!!!! InitTrack momentum on layer 0: ( "<<mom.x()*1000<<", "<<mom.y()*1000<<", "<<mom.z()*1000<<", "<<p*1000<<") "<<std::endl; +// std::cout<<"!!!!!!!!!!! truth momentum: ( "<<truthmom.px()<<", "<<truthmom.py()<<", "<<truthmom.pz()<<", "<<truthmom.m()<<" ) "<<std::endl; if ((p_x*1000 - truthmom.px()) / std::fabs(truthmom.px()) < -10) m_hist_InitReso_px->Fill( -9.5 ); else if ((p_x*1000 - truthmom.px()) / std::fabs(truthmom.px()) > 10) m_hist_InitReso_px->Fill( 9.5 ); @@ -593,15 +593,15 @@ namespace Tracker //--------------------------------------------------------------------------- StatusCode TruthSeededTrackFinder::finalize() { - ATH_MSG_INFO( "Finalizing" ); - ATH_MSG_INFO( m_numberOfEvents << " events processed" ); - ATH_MSG_INFO( m_numberOfSPCollection << " spacepoint collections processed" ); - ATH_MSG_INFO( m_numberOfEmptySPCollection<< " spacepoint collections empty" ); - ATH_MSG_INFO( m_numberOfSP<< " sct SP collections processed" ); - ATH_MSG_INFO( m_numberOfNoMap<< " not maped spacepoint" ); - ATH_MSG_INFO( m_numberOfHits<< " sim hits" ); - ATH_MSG_INFO( m_numberOfMatchSP<< " matched spacepoint" ); - ATH_MSG_INFO( m_numberOfFills<< " spacepoint saved" ); + ATH_MSG_DEBUG( "Finalizing" ); + ATH_MSG_DEBUG( m_numberOfEvents << " events processed" ); + ATH_MSG_DEBUG( m_numberOfSPCollection << " spacepoint collections processed" ); + ATH_MSG_DEBUG( m_numberOfEmptySPCollection<< " spacepoint collections empty" ); + ATH_MSG_DEBUG( m_numberOfSP<< " sct SP collections processed" ); + ATH_MSG_DEBUG( m_numberOfNoMap<< " not maped spacepoint" ); + ATH_MSG_DEBUG( m_numberOfHits<< " sim hits" ); + ATH_MSG_DEBUG( m_numberOfMatchSP<< " matched spacepoint" ); + ATH_MSG_DEBUG( m_numberOfFills<< " spacepoint saved" ); return StatusCode::SUCCESS; } diff --git a/Tracking/Acts/ActsInterop/CMakeLists.txt b/Tracking/Acts/ActsInterop/CMakeLists.txt index 41632f128825078ea3e7bc471117c1e35caae2fa..63c79212852d5d2213c74f3bb27f7f145cd604a6 100755 --- a/Tracking/Acts/ActsInterop/CMakeLists.txt +++ b/Tracking/Acts/ActsInterop/CMakeLists.txt @@ -4,7 +4,9 @@ atlas_subdir( ActsInterop ) # External dependencies: -find_package(Acts COMPONENTS Core) +#set( Acts_DIR /home/tboeckh/Documents/acts/run ) +#find_package( Acts REQUIRED COMPONENTS Core PATHS /home/tboeckh/Documents/acts/run NO_DEFAULT_PATH ) +find_package( Acts COMPONENTS Core ) # Component(s) in the package: atlas_add_library( ActsInteropLib diff --git a/Tracking/Acts/FaserActsGeometry/CMakeLists.txt b/Tracking/Acts/FaserActsGeometry/CMakeLists.txt index a121316e188cc27c35f3d90f9a81b569089b9d19..48c9abd929200339bfaa071bfa6625cf3e2a98cd 100755 --- a/Tracking/Acts/FaserActsGeometry/CMakeLists.txt +++ b/Tracking/Acts/FaserActsGeometry/CMakeLists.txt @@ -8,6 +8,8 @@ find_package( Eigen ) find_package( Boost ) find_package( nlohmann_json ) +#set( Acts_DIR /home/tboeckh/Documents/acts/run ) +#find_package( Acts REQUIRED COMPONENTS Core PATHS /home/tboeckh/Documents/acts/run NO_DEFAULT_PATH ) find_package( Acts COMPONENTS Core ) atlas_add_library( FaserActsGeometryLib diff --git a/Tracking/Acts/FaserActsGeometryInterfaces/CMakeLists.txt b/Tracking/Acts/FaserActsGeometryInterfaces/CMakeLists.txt index 7529f472a8de702fb76046cb78624a9111e65a03..b3f81e4ac59f82e9d53ebb75f68eaddbe3e4f74c 100644 --- a/Tracking/Acts/FaserActsGeometryInterfaces/CMakeLists.txt +++ b/Tracking/Acts/FaserActsGeometryInterfaces/CMakeLists.txt @@ -4,6 +4,8 @@ atlas_subdir( FaserActsGeometryInterfaces ) # External dependencies: find_package( Eigen ) +#set( Acts_DIR /home/tboeckh/Documents/acts/run ) +#find_package( Acts REQUIRED COMPONENTS Core PATHS /home/tboeckh/Documents/acts/run NO_DEFAULT_PATH ) find_package( Acts COMPONENTS Core ) find_package( nlohmann_json ) # Component(s) in the package: diff --git a/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt b/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt index 34d9584f9f6b30b1683c962d6baa59037bc8d6f3..c5c0c5e454ab0b43622689bda4f7c3691ee1abca 100755 --- a/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt +++ b/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt @@ -5,8 +5,11 @@ atlas_subdir(FaserActsKalmanFilter) find_package( CLHEP ) find_package( Eigen ) find_package( Boost ) +#set( Acts_DIR /home/tboeckh/Documents/acts/run ) +#find_package( Acts REQUIRED COMPONENTS Core PATHS /home/tboeckh/Documents/acts/run NO_DEFAULT_PATH ) find_package( Acts COMPONENTS Core ) + # Component(s) in the package: atlas_add_library( FaserActsKalmanFilterLib PUBLIC_HEADERS FaserActsKalmanFilter @@ -22,21 +25,25 @@ atlas_add_library( FaserActsKalmanFilterLib ) atlas_add_component(FaserActsKalmanFilter + FaserActsKalmanFilter/ActsTrackSeedTool.h + FaserActsKalmanFilter/CircleFit.h + FaserActsKalmanFilter/CKF2.h FaserActsKalmanFilter/CombinatorialKalmanFilterAlg.h FaserActsKalmanFilter/EffPlotTool.h FaserActsKalmanFilter/FASERSourceLink.h FaserActsKalmanFilter/FaserActsGeometryContainers.h FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h + FaserActsKalmanFilter/MyTrackSeedTool.h FaserActsKalmanFilter/IdentifierLink.h FaserActsKalmanFilter/IndexSourceLink.h FaserActsKalmanFilter/ITrackFinderTool.h FaserActsKalmanFilter/ITrackSeedTool.h + FaserActsKalmanFilter/KalmanFitterTool.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 @@ -49,16 +56,21 @@ atlas_add_component(FaserActsKalmanFilter FaserActsKalmanFilter/SPSimpleInitialParameterTool.h FaserActsKalmanFilter/SummaryPlotTool.h FaserActsKalmanFilter/TrackClassification.h + FaserActsKalmanFilter/TrackSeedWriterTool.h FaserActsKalmanFilter/TrackSelection.h FaserActsKalmanFilter/TrajectoryWriterTool.h # FaserActsKalmanFilter/ProtoTrackWriterTool.h FaserActsKalmanFilter/TruthBasedInitialParameterTool.h # FaserActsKalmanFilter/TruthSeededTrackFinderTool.h FaserActsKalmanFilter/ThreeStationTrackSeedTool.h + src/ActsTrackSeedTool.cxx + src/CKF2.cxx # src/ClusterTrackSeedTool.cxx src/CombinatorialKalmanFilterAlg.cxx src/EffPlotTool.cxx src/FaserActsKalmanFilterAlg.cxx + src/MyTrackSeedTool.cxx + src/KalmanFitterTool.cxx # src/MultiTrackFinderTool.cxx src/PerformanceWriterTool.cxx src/PlotHelpers.cxx @@ -77,6 +89,7 @@ atlas_add_component(FaserActsKalmanFilter src/TruthBasedInitialParameterTool.cxx src/SummaryPlotTool.cxx src/TrackClassification.cxx + src/TrackSeedWriterTool.cxx src/TrackSelection.cxx # src/TruthTrackFinderTool.cxx # src/TruthSeededTrackFinderTool.cxx diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ActsTrackSeedTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ActsTrackSeedTool.h new file mode 100644 index 0000000000000000000000000000000000000000..fe129a47d2867405ece6b807bf56803f814a2882 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ActsTrackSeedTool.h @@ -0,0 +1,110 @@ +#ifndef FASERACTSKALMANFILTER_ACTSTRACKSEEDTOOL_H +#define FASERACTSKALMANFILTER_ACTSTRACKSEEDTOOL_H + + +#include "TrackerPrepRawData/FaserSCT_ClusterContainer.h" +#include "AthenaBaseComps/AthAlgTool.h" +#include "FaserActsKalmanFilter/ITrackSeedTool.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" +#include "TrkTrack/TrackCollection.h" + +class FaserSCT_ID; +namespace TrackerDD { class SCT_DetectorManager; } + + +class ActsTrackSeedTool : public extends<AthAlgTool, ITrackSeedTool> { +public: + ActsTrackSeedTool(const std::string& type, const std::string& name, const IInterface* parent); + virtual ~ActsTrackSeedTool() = 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; + const std::shared_ptr<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>> seedClusters() const override; + const std::shared_ptr<std::vector<const Tracker::FaserSCT_SpacePoint*>> spacePoints() 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 {}; + std::shared_ptr<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>> m_seedClusters {}; + std::shared_ptr<std::vector<const Tracker::FaserSCT_SpacePoint*>> m_spacePoints {}; + + 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.023}; + + // 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 Acts::GeometryContext& gctx, const Amg::Vector3D& position_st1, + const Amg::Vector3D& position_st2, const Amg::Vector3D& position_st3, + const Acts::BoundSymMatrix& cov, double origin); +}; + +inline const std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>> +ActsTrackSeedTool::initialTrackParameters() const { + return m_initialTrackParameters; +} + +inline const std::shared_ptr<const Acts::Surface> +ActsTrackSeedTool::initialSurface() const { + return m_initialSurface; +} + +inline const std::shared_ptr<std::vector<IndexSourceLink>> +ActsTrackSeedTool::sourceLinks() const { + return m_sourceLinks; +} + +inline const std::shared_ptr<IdentifierLink> +ActsTrackSeedTool::idLinks() const { + return m_idLinks; +} + +inline const std::shared_ptr<std::vector<Measurement>> +ActsTrackSeedTool::measurements() const { + return m_measurements; +} + +inline const std::shared_ptr<std::vector<const Tracker::FaserSCT_Cluster*>> +ActsTrackSeedTool::clusters() const { + return m_clusters; +} + +inline const std::shared_ptr<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>> +ActsTrackSeedTool::seedClusters() const { + return m_seedClusters; +} + +inline const std::shared_ptr<std::vector<const Tracker::FaserSCT_SpacePoint*>> +ActsTrackSeedTool::spacePoints() const { + return m_spacePoints; +} + +#endif // FASERACTSKALMANFILTER_ACTSTRACKSEEDTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CKF2.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CKF2.h new file mode 100644 index 0000000000000000000000000000000000000000..7e3b0e76af52738963d42f7cd716a1c32644ca47 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CKF2.h @@ -0,0 +1,151 @@ +#ifndef FASERACTSKALMANFILTER_CKF2_H +#define FASERACTSKALMANFILTER_CKF2_H + + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "AthenaBaseComps/AthAlgorithm.h" +#include "TrackerSpacePoint/FaserSCT_SpacePointContainer.h" +#include "TrackerPrepRawData/FaserSCT_ClusterContainer.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" +#include "Acts/TrackFitting/KalmanFitter.hpp" +#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" +#include "FaserActsKalmanFilter/KalmanFitterTool.h" +#include <boost/dynamic_bitset.hpp> +using ConstTrackStateProxy = Acts::detail_lt::TrackStateProxy<IndexSourceLink, 6, true>; +using ClusterSet = boost::dynamic_bitset<>; + +class FaserSCT_ID; + +namespace Trk { +class TrackStateOnSurface; +} + +namespace TrackerDD { +class SCT_DetectorManager; +} + +class CKF2 : public AthAlgorithm { +public: + CKF2(const std::string& name, ISvcLocator* pSvcLocator); + virtual ~CKF2() = default; + + StatusCode initialize() override; + StatusCode execute() override; + StatusCode finalize() override; + + using TrackFinderOptions = + Acts::CombinatorialKalmanFilterOptions<IndexSourceLinkAccessor, + MeasurementCalibrator, + Acts::MeasurementSelector>; + using CKFResult = Acts::CombinatorialKalmanFilterResult<IndexSourceLink>; + using TrackFitterResult = Acts::Result<CKFResult>; + using TrackFinderResult = std::vector<TrackFitterResult>; + + using KFResult = + Acts::Result<Acts::KalmanFitterResult<IndexSourceLink>>; + + using TrackFitterOptions = + Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder, + Acts::VoidReverseFilteringLogic>; + + using TrackParameters = Acts::CurvilinearTrackParameters; + using TrackParametersContainer = std::vector<TrackParameters>; + + // Track Finding + 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); + + // Track Fitting + class TrackFitterFunction { + public: + virtual ~TrackFitterFunction() = default; + virtual KFResult operator()(const std::vector<IndexSourceLink>&, + const Acts::BoundTrackParameters&, + const TrackFitterOptions&) const = 0; + }; + + struct TrajectoryInfo { + TrajectoryInfo(const FaserActsRecMultiTrajectory &traj) : + trajectory{traj}, clusterSet{nClusters} { + auto state = Acts::MultiTrajectoryHelpers::trajectoryState(traj.multiTrajectory(), traj.tips().front()); + traj.multiTrajectory().visitBackwards(traj.tips().front(), [&](const ConstTrackStateProxy& state) { + auto typeFlags = state.typeFlags(); + if (not typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) { + return true; + } + clusterSet.set(state.uncalibrated().index()); + return true; + }); + nMeasurements = state.nMeasurements; + chi2 = state.chi2Sum; + } + + static size_t nClusters; + FaserActsRecMultiTrajectory trajectory; + ClusterSet clusterSet; + size_t nMeasurements; + double chi2; + }; + + static std::shared_ptr<TrackFitterFunction> makeTrackFitterFunction( + std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry); + + virtual Acts::MagneticFieldContext getMagneticFieldContext(const EventContext& ctx) const; + +private: + void computeSharedHits(std::vector<IndexSourceLink>* sourceLinks, TrackFinderResult& results) const; + std::shared_ptr<TrackFinderFunction> m_fit; + std::shared_ptr<TrackFitterFunction> m_kf; + std::unique_ptr<const Acts::Logger> m_logger; + const FaserSCT_ID* m_idHelper {nullptr}; + const TrackerDD::SCT_DetectorManager* m_detManager {nullptr}; + + 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_noDiagnostics {this, "noDiagnostics", true, "Set ACTS logging level to INFO and do not run performance writer, states writer or summary writer"}; + 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"}; + 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"}; + ToolHandle<KalmanFitterTool> m_kalmanFitterTool1 {this, "KalmanFitterTool1", "KalmanFitterTool"}; + ToolHandle<KalmanFitterTool> m_kalmanFitterTool2 {this, "KalmanFitterTool2", "KalmanFitterTool"}; + + std::unique_ptr<Trk::Track> makeTrack(Acts::GeometryContext& tgContext, TrackFitterResult& fitResult) const; + std::unique_ptr<Trk::Track> makeTrack(const Acts::GeometryContext &geoCtx, const FaserActsRecMultiTrajectory &traj) const; + const Trk::TrackParameters* ConvertActsTrackParameterToATLAS(const Acts::BoundTrackParameters &actsParameter, const Acts::GeometryContext& gctx) const; + SG::WriteHandleKey<TrackCollection> m_trackCollection { this, "CKFTrackCollection", "CKFTrackCollection" }; +}; + +#endif // FASERACTSKALMANFILTER_CKF2_H + diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CircleFit.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CircleFit.h new file mode 100644 index 0000000000000000000000000000000000000000..664b7005ddfdb31998dc3a5665fdd871a9d8ce31 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CircleFit.h @@ -0,0 +1,188 @@ +#ifndef FASERACTSKALMANFILTER_CIRCLEFIT_H +#define FASERACTSKALMANFILTER_CIRCLEFIT_H + +#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" +#include <cmath> +#include <vector> + + +struct Circle { +public: + Circle() = default; + Circle(double cx, double cy, double r) : cx(cx), cy(cy), r(r) {}; + + double cx = 0; + double cy = 0; + double r = 0; + double s = 0; + double i = 0; + double j = 0; +}; + + +class CircleData { +public: + CircleData(const std::vector<const Tracker::FaserSCT_SpacePoint*> &spacePoints) { + for (auto sp : spacePoints) { + m_x.push_back(sp->globalPosition().z()); + m_y.push_back(sp->globalPosition().y()); + } + m_size = spacePoints.size(); + } + + double meanX() const { + double mean = 0; + for (double i : m_x) mean += i; + return mean / m_size; + } + + double meanY() const { + double mean = 0; + for (double i : m_y) mean += i; + return mean / m_size; + } + + double x(int i) const { + return m_x[i]; + } + + double y(int i) const { + return m_y[i]; + } + + int size() const { + return m_size; + } + +private: + std::vector<double> m_x {}; + std::vector<double> m_y {}; + int m_size = 0; +}; + + +double Sigma (CircleData& data, Circle& circle) { + double sum=0.,dx,dy; + + for (int i=0; i<data.size(); i++) { + dx = data.x(i) - circle.cx; + dy = data.y(i) - circle.cy; + sum += (sqrt(dx*dx+dy*dy) - circle.r) * (sqrt(dx*dx+dy*dy) - circle.r); + } + return sqrt(sum/data.size()); +} + + +Circle CircleFit(CircleData& data) +/* + Circle fit to a given set of data points (in 2D) + + This is an algebraic fit, due to Taubin, based on the journal article + + G. Taubin, "Estimation Of Planar Curves, Surfaces And Nonplanar + Space Curves Defined By Implicit Equations, With + Applications To Edge And Range Image Segmentation", + IEEE Trans. PAMI, Vol. 13, pages 1115-1138, (1991) + + Input: data - the class of data (contains the given points): + + data.size() - the number of data points + data.X[] - the array of X-coordinates + data.Y[] - the array of Y-coordinates + + Output: + circle - parameters of the fitting circle: + + circle.a - the X-coordinate of the center of the fitting circle + circle.b - the Y-coordinate of the center of the fitting circle + circle.r - the radius of the fitting circle + circle.s - the root mean square error (the estimate of sigma) + circle.j - the total number of iterations + + The method is based on the minimization of the function + + sum [(x-a)^2 + (y-b)^2 - R^2]^2 + F = ------------------------------- + sum [(x-a)^2 + (y-b)^2] + + This method is more balanced than the simple Kasa fit. + + It works well whether data points are sampled along an entire circle or + along a small arc. + + It still has a small bias and its statistical accuracy is slightly + lower than that of the geometric fit (minimizing geometric distances), + but slightly higher than that of the very similar Pratt fit. + Besides, the Taubin fit is slightly simpler than the Pratt fit + + It provides a very good initial guess for a subsequent geometric fit. + + Nikolai Chernov (September 2012) + +*/ +{ + int i,iter,IterMAX=99; + + double Xi,Yi,Zi; + double Mz,Mxy,Mxx,Myy,Mxz,Myz,Mzz,Cov_xy,Var_z; + double A0,A1,A2,A22,A3,A33; + double Dy,xnew,x,ynew,y; + double DET,Xcenter,Ycenter; + + Circle circle; + + Mxx=Myy=Mxy=Mxz=Myz=Mzz=0.; + for (i=0; i<data.size(); i++) { + Xi = data.x(i) - data.meanX(); + Yi = data.y(i) - data.meanY(); + Zi = Xi*Xi + Yi*Yi; + + Mxy += Xi*Yi; + Mxx += Xi*Xi; + Myy += Yi*Yi; + Mxz += Xi*Zi; + Myz += Yi*Zi; + Mzz += Zi*Zi; + } + Mxx /= data.size(); + Myy /= data.size(); + Mxy /= data.size(); + Mxz /= data.size(); + Myz /= data.size(); + Mzz /= data.size(); + + Mz = Mxx + Myy; + Cov_xy = Mxx*Myy - Mxy*Mxy; + Var_z = Mzz - Mz*Mz; + A3 = 4*Mz; + A2 = -3*Mz*Mz - Mzz; + A1 = Var_z*Mz + 4*Cov_xy*Mz - Mxz*Mxz - Myz*Myz; + A0 = Mxz*(Mxz*Myy - Myz*Mxy) + Myz*(Myz*Mxx - Mxz*Mxy) - Var_z*Cov_xy; + A22 = A2 + A2; + A33 = A3 + A3 + A3; + + for (x=0.,y=A0,iter=0; iter<IterMAX; iter++) { + Dy = A1 + x*(A22 + A33*x); + xnew = x - y/Dy; + if ((xnew == x)||(!std::isfinite(xnew))) break; + ynew = A0 + xnew*(A1 + xnew*(A2 + xnew*A3)); + if (abs(ynew)>=abs(y)) break; + x = xnew; y = ynew; + } + + DET = x*x - x*Mz + Cov_xy; + Xcenter = (Mxz*(Myy - x) - Myz*Mxy)/DET/2; + Ycenter = (Myz*(Mxx - x) - Mxz*Mxy)/DET/2; + + circle.cx = Xcenter + data.meanX(); + circle.cy = Ycenter + data.meanY(); + circle.r = sqrt(Xcenter*Xcenter + Ycenter*Ycenter + Mz); + circle.s = Sigma(data,circle); + circle.i = 0; + circle.j = iter; + + return circle; +} + + +#endif // FASERACTSKALMANFILTER_CIRCLEFIT_H \ No newline at end of file diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CombinatorialKalmanFilterAlg.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CombinatorialKalmanFilterAlg.h index 892b15b98bf957186cdf64000a130ed2f51ea223..ba983f245fdce513858c27cb0a814b48313eac0b 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CombinatorialKalmanFilterAlg.h +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/CombinatorialKalmanFilterAlg.h @@ -6,7 +6,6 @@ #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 "Acts/TrackFinding/CombinatorialKalmanFilter.hpp" @@ -19,6 +18,10 @@ #include "FaserActsKalmanFilter/RootTrajectoryStatesWriterTool.h" #include "FaserActsKalmanFilter/RootTrajectorySummaryWriterTool.h" #include "FaserActsKalmanFilter/PerformanceWriterTool.h" +#include "FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h" +#include <boost/dynamic_bitset.hpp> +using ConstTrackStateProxy = Acts::detail_lt::TrackStateProxy<IndexSourceLink, 6, true>; +using ClusterSet = boost::dynamic_bitset<>; class FaserSCT_ID; @@ -44,8 +47,8 @@ public: Acts::CombinatorialKalmanFilterOptions<IndexSourceLinkAccessor, MeasurementCalibrator, Acts::MeasurementSelector>; - using TrackFitterResult = - Acts::Result<Acts::CombinatorialKalmanFilterResult<IndexSourceLink>>; + using CKFResult = Acts::CombinatorialKalmanFilterResult<IndexSourceLink>; + using TrackFitterResult = Acts::Result<CKFResult>; using TrackFinderResult = std::vector<TrackFitterResult>; using TrackParameters = Acts::CurvilinearTrackParameters; using TrackParametersContainer = std::vector<TrackParameters>; @@ -58,6 +61,29 @@ public: const TrackFinderOptions&) const = 0; }; + struct TrajectoryInfo { + TrajectoryInfo(const FaserActsRecMultiTrajectory &traj) : + trajectory{traj}, clusterSet{nClusters} { + auto state = Acts::MultiTrajectoryHelpers::trajectoryState(traj.multiTrajectory(), traj.tips().front()); + traj.multiTrajectory().visitBackwards(traj.tips().front(), [&](const ConstTrackStateProxy& state) { + auto typeFlags = state.typeFlags(); + if (not typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) { + return true; + } + clusterSet.set(state.uncalibrated().index()); + return true; + }); + nMeasurements = state.nMeasurements; + chi2 = state.chi2Sum; + } + + static size_t nClusters; + FaserActsRecMultiTrajectory trajectory; + ClusterSet clusterSet; + size_t nMeasurements; + double chi2; + }; + static std::shared_ptr<TrackFinderFunction> makeTrackFinderFunction( std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry, bool resolvePassive, bool resolveMaterial, bool resolveSensitive); @@ -68,6 +94,7 @@ public: size_t m_numberOfTrackSeeds {0}; size_t m_numberOfFittedTracks {0}; size_t m_numberOfSelectedTracks {0}; + void computeSharedHits(std::vector<IndexSourceLink>* sourceLinks, TrackFinderResult& results) const; std::shared_ptr<TrackFinderFunction> m_fit; std::unique_ptr<const Acts::Logger> m_logger; @@ -84,10 +111,10 @@ public: Gaudi::Property<bool> m_resolveMaterial {this, "resolveMaterial", true}; Gaudi::Property<bool> m_resolveSensitive {this, "resolveSensitive", true}; Gaudi::Property<bool> m_noDiagnostics {this, "noDiagnostics", true, "Set ACTS logging level to INFO and do not run performance writer, states writer or summary writer"}; - Gaudi::Property<double> m_maxSteps {this, "maxSteps", 10000}; + Gaudi::Property<double> m_maxSteps {this, "maxSteps", 1000}; 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"}; ToolHandle<ITrackSeedTool> m_trackSeedTool {this, "TrackSeed", "ClusterTrackSeedTool"}; ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool {this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; @@ -95,9 +122,11 @@ public: 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" }; + std::unique_ptr<Trk::Track> makeTrack(Acts::GeometryContext& tgContext, TrackFitterResult& fitResult) const; + std::unique_ptr<Trk::Track> makeTrack(const Acts::GeometryContext &geoCtx, const FaserActsRecMultiTrajectory &traj) 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/ITrackSeedTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ITrackSeedTool.h index 34b5c23c2516ec620a73ab74d192e7f76ae278fc..8345823daedd83b2ce1220b843303492f3101a57 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ITrackSeedTool.h +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ITrackSeedTool.h @@ -8,6 +8,7 @@ #include "FaserActsKalmanFilter/Measurement.h" #include "Acts/EventData/TrackParameters.hpp" #include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" class ITrackSeedTool : virtual public IAlgTool { public: @@ -20,6 +21,8 @@ public: 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; + virtual const std::shared_ptr<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>> seedClusters() const = 0; + virtual const std::shared_ptr<std::vector<const Tracker::FaserSCT_SpacePoint*>> spacePoints() const = 0; }; #endif // FASERACTSKALMANFILTER_ITRACKSEEDTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/KalmanFitterTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/KalmanFitterTool.h new file mode 100644 index 0000000000000000000000000000000000000000..9c26faeb3f354618133ae478fca9a4f3cea947bd --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/KalmanFitterTool.h @@ -0,0 +1,72 @@ +#ifndef FASERACTSKALMANFILTER_KALMANFITTERTOOL_H +#define FASERACTSKALMANFILTER_KALMANFITTERTOOL_H + +#include "TrackerPrepRawData/FaserSCT_ClusterContainer.h" +#include "AthenaBaseComps/AthAlgTool.h" +#include "Acts/EventData/TrackParameters.hpp" +#include "Acts/TrackFitting/KalmanFitter.hpp" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" +#include "FaserActsKalmanFilter/IndexSourceLink.h" +#include "FaserActsKalmanFilter/Measurement.h" +#include "FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h" +#include "MagFieldConditions/FaserFieldCacheCondObj.h" +#include "FaserActsKalmanFilter/RootTrajectoryStatesWriterTool.h" +#include "FaserActsKalmanFilter/RootTrajectorySummaryWriterTool.h" +#include "TrkTrack/Track.h" + + +class FaserSCT_ID; + +class KalmanFitterTool : virtual public AthAlgTool { +public: + KalmanFitterTool(const std::string &type, const std::string &name, const IInterface *parent); + virtual ~KalmanFitterTool() = default; + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + + using TrackParameters = Acts::BoundTrackParameters; + using IndexedParams = std::unordered_map<size_t, TrackParameters>; + using TrackFitterOptions = + Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder, Acts::VoidReverseFilteringLogic>; + using TrackFitterResult = Acts::Result<Acts::KalmanFitterResult<IndexSourceLink>>; + class TrackFitterFunction { + public: + virtual ~TrackFitterFunction() = default; + virtual TrackFitterResult operator()(const std::vector<IndexSourceLink>&, + const TrackParameters&, + const TrackFitterOptions&) const = 0; + }; + static std::shared_ptr<TrackFitterFunction> makeTrackFitterFunction( + std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry); + + virtual Acts::MagneticFieldContext getMagneticFieldContext(const EventContext& ctx) const; + std::unique_ptr<Trk::Track> fit(const EventContext& ctx, const Trk::Track& inputTrack, + std::vector<FaserActsRecMultiTrajectory> &trajectories, + const Acts::BoundVector& inputVector) const; + +private: + const FaserSCT_ID* m_idHelper {nullptr}; + std::tuple<std::vector<IndexSourceLink>, std::vector<Measurement>> + getMeasurementsFromTrack(const Trk::Track &track) const; + // Acts::BoundTrackParameters getParametersFromTrack(const Acts::BoundVector& params, const Trk::TrackParameters *inputParameters) const; + Acts::BoundTrackParameters getParametersFromTrack(const Trk::TrackParameters *inputParameters, const Acts::BoundVector& inputVector) const; + std::shared_ptr<TrackFitterFunction> m_fit; + std::unique_ptr<const Acts::Logger> m_logger; + Gaudi::Property<std::string> m_actsLogging {this, "ActsLogging", "VERBOSE"}; + Gaudi::Property<std::size_t> m_minMeasurements {this, "MinMeasurements", 12, "minimum number of measurements of the input track"}; + Gaudi::Property<double> m_seedCovarianceScale {this, "SeedCovarianceScale", 100, "scale covariance from initial track"}; + Gaudi::Property<bool> m_isMC {this, "isMC", false}; + Gaudi::Property<bool> m_summaryWriter {this, "SummaryWriter", false}; + Gaudi::Property<bool> m_statesWriter {this, "StatesWriter", false}; + Gaudi::Property<bool> m_noDiagnostics {this, "noDiagnostics", true, "Set ACTS logging level to INFO and do not run performance writer, states writer or summary writer"}; + + SG::ReadCondHandleKey<FaserFieldCacheCondObj> m_fieldCondObjInputKey {this, "FaserFieldCacheCondObj", "fieldCondObj", "Name of the Magnetic Field conditions object key"}; + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool {this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; + 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; +}; + +#endif //FASERACTSKALMANFILTER_KALMANFITTERTOOL_H + diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/MyTrackSeedTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/MyTrackSeedTool.h new file mode 100644 index 0000000000000000000000000000000000000000..bd29bbf5f020fe5ce139c8cbd12eb52154511110 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/MyTrackSeedTool.h @@ -0,0 +1,117 @@ +#ifndef FASERACTSKALMANFILTER_MYTRACKSEEDTOOL_H +#define FASERACTSKALMANFILTER_MYTRACKSEEDTOOL_H + +#include "TrackerPrepRawData/FaserSCT_ClusterContainer.h" +#include "TrackerSpacePoint/FaserSCT_SpacePointContainer.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 MyTrackSeedTool : public extends<AthAlgTool, ITrackSeedTool> { +public: + MyTrackSeedTool(const std::string& type, const std::string& name, const IInterface* parent); + virtual ~MyTrackSeedTool() = 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; + const std::shared_ptr<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>> seedClusters() const override; + const std::shared_ptr<std::vector<const Tracker::FaserSCT_SpacePoint*>> spacePoints() 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 {}; + std::shared_ptr<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>> m_seedClusters {}; + std::shared_ptr<std::vector<const Tracker::FaserSCT_SpacePoint*>> m_spacePoints {}; + + 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"}; + SG::ReadHandleKey<FaserSCT_SpacePointContainer> m_spacePointContainerKey { + this, "SpacePoints", "SCT_SpacePointContainer"}; + + // 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& p1, const Amg::Vector3D& p2, 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>> +MyTrackSeedTool::initialTrackParameters() const { + return m_initialTrackParameters; +} + +inline const std::shared_ptr<const Acts::Surface> +MyTrackSeedTool::initialSurface() const { + return m_initialSurface; +} + +inline const std::shared_ptr<std::vector<IndexSourceLink>> +MyTrackSeedTool::sourceLinks() const { + return m_sourceLinks; +} + +inline const std::shared_ptr<IdentifierLink> +MyTrackSeedTool::idLinks() const { + return m_idLinks; +} + +inline const std::shared_ptr<std::vector<Measurement>> +MyTrackSeedTool::measurements() const { + return m_measurements; +} + +inline const std::shared_ptr<std::vector<const Tracker::FaserSCT_Cluster*>> +MyTrackSeedTool::clusters() const { + return m_clusters; +} + +inline const std::shared_ptr<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>> +MyTrackSeedTool::seedClusters() const { + return m_seedClusters; +} + +inline const std::shared_ptr<std::vector<const Tracker::FaserSCT_SpacePoint*>> +MyTrackSeedTool::spacePoints() const { + return m_spacePoints; +} + +#endif // FASERACTSKALMANFILTER_MYTRACKSEEDTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ThreeStationTrackSeedTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ThreeStationTrackSeedTool.h index a37f1dbf1061e636402e1069c49ac22a479c610b..3cf450414f20733b873ceda542f7c4ab44cdd573 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ThreeStationTrackSeedTool.h +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ThreeStationTrackSeedTool.h @@ -31,14 +31,31 @@ public: 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; + const std::shared_ptr<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>> seedClusters() const override; + const std::shared_ptr<std::vector<const Tracker::FaserSCT_SpacePoint*>> spacePoints() const override; private: + + struct Tracklet { + public: + Tracklet(const Amg::Vector3D& position, const std::vector<const Tracker::FaserSCT_Cluster*>& clusters) + : m_position(position), m_clusters(clusters) {} + inline const Amg::Vector3D position() const { return m_position; } + inline const std::vector<const Tracker::FaserSCT_Cluster*> clusters() const { return m_clusters; } + inline int size() const { return m_clusters.size(); } + private: + const Amg::Vector3D m_position; + const std::vector<const Tracker::FaserSCT_Cluster*> m_clusters; + }; + 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 {}; + std::shared_ptr<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>> m_seedClusters {}; + std::shared_ptr<std::vector<const Tracker::FaserSCT_SpacePoint*>> m_spacePoints {}; const FaserSCT_ID* m_idHelper {nullptr}; const TrackerDD::SCT_DetectorManager* m_detManager {nullptr}; @@ -98,5 +115,14 @@ ThreeStationTrackSeedTool::clusters() const { return m_clusters; } +inline const std::shared_ptr<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>> +ThreeStationTrackSeedTool::seedClusters() const { + return m_seedClusters; +} + +inline const std::shared_ptr<std::vector<const Tracker::FaserSCT_SpacePoint*>> +ThreeStationTrackSeedTool::spacePoints() const { + return m_spacePoints; +} #endif // FASERACTSKALMANFILTER_THREESTATIONTRACKSEEDTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TrackSeedWriterTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TrackSeedWriterTool.h new file mode 100644 index 0000000000000000000000000000000000000000..e078acc19edd584ce2f514a4a3985bbaf7cc326c --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/TrackSeedWriterTool.h @@ -0,0 +1,50 @@ +#ifndef FASERACTSKALMANFILTER_TRACKSEEDWRITERTOOL_H +#define FASERACTSKALMANFILTER_TRACKSEEDWRITERTOOL_H + + +#include "AthenaBaseComps/AthAlgTool.h" +#include "Acts/EventData/TrackParameters.hpp" + +class TFile; +class TTree; + +class TrackSeedWriterTool : public AthAlgTool { + public: + TrackSeedWriterTool(const std::string& type, + const std::string& name, const IInterface* parent); + virtual ~TrackSeedWriterTool() = default; + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + void writeout(const Acts::GeometryContext& gctx, + const std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>>& initialParameters) const; + +private: + void initializeTree(); + void clearVariables() const; + Gaudi::Property<std::string> m_filePath{this, "FilePath", "TrackSeeds.root", ""}; + Gaudi::Property<std::string> m_treeName{this, "TreeName", "tree", ""}; + TFile* m_file; + TTree* m_tree; + + mutable int m_runNumber; + mutable int m_eventNumber; + mutable std::vector<float> m_eLOC0; + mutable std::vector<float> m_eLOC1; + mutable std::vector<float> m_ePHI; + mutable std::vector<float> m_eTHETA; + mutable std::vector<float> m_eQOP; + mutable std::vector<float> m_err_eLOC0; + mutable std::vector<float> m_err_eLOC1; + mutable std::vector<float> m_err_ePHI; + mutable std::vector<float> m_err_eTHETA; + mutable std::vector<float> m_err_eQOP; + mutable std::vector<float> m_x; + mutable std::vector<float> m_y; + mutable std::vector<float> m_z; + mutable std::vector<float> m_px; + mutable std::vector<float> m_py; + mutable std::vector<float> m_pz; +}; + + +#endif // FASERACTSKALMANFILTER_TRACKSEEDWRITERTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/python/CKF2Config.py b/Tracking/Acts/FaserActsKalmanFilter/python/CKF2Config.py new file mode 100644 index 0000000000000000000000000000000000000000..728cc83e1cf04a37a67486bcaee6662e5dfb73ad --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/python/CKF2Config.py @@ -0,0 +1,116 @@ +# 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 FaserActsAlignmentCondAlgCfg(flags, **kwargs): + acc = ComponentAccumulator() + acc.addCondAlgo(CompFactory.FaserActsAlignmentCondAlg(name="FaserActsAlignmentCondAlg", **kwargs)) + return acc + + +def CKF2_OutputCfg(flags): + acc = ComponentAccumulator() + itemList = ["xAOD::EventInfo#*", + "xAOD::EventAuxInfo#*", + "TrackCollection#*", + ] + acc.merge(OutputStreamCfg(flags, "ESD", itemList)) + ostream = acc.getEventAlgo("OutputStreamESD") + ostream.TakeItemsFromInput = True + return acc + + +def CKF2Cfg(flags, **kwargs): + # 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() + # track_seed_tool = CompFactory.ActsTrackSeedTool() + # track_seed_tool = CompFactory.MyTrackSeedTool() + 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 = [1000, 1000, 100, 100, 10000] + initial_variance_inflation = [100, 100, 100, 100, 1000] + 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.0231 + track_seed_tool.origin = 0 + + trajectory_states_writer_tool = CompFactory.RootTrajectoryStatesWriterTool() + trajectory_states_writer_tool.noDiagnostics = kwargs["noDiagnostics"] + trajectory_states_writer_tool1 = CompFactory.RootTrajectoryStatesWriterTool() + trajectory_states_writer_tool1.noDiagnostics = kwargs["noDiagnostics"] + trajectory_states_writer_tool1.FilePath = "track_states_ckf1.root" + trajectory_states_writer_tool2 = CompFactory.RootTrajectoryStatesWriterTool() + trajectory_states_writer_tool2.FilePath = "track_states_ckf2.root" + trajectory_states_writer_tool2.noDiagnostics = kwargs["noDiagnostics"] + + trajectory_summary_writer_tool = CompFactory.RootTrajectorySummaryWriterTool(**kwargs) + trajectory_summary_writer_tool.noDiagnostics = kwargs["noDiagnostics"] + trajectory_summary_writer_tool1 = CompFactory.RootTrajectorySummaryWriterTool() + trajectory_summary_writer_tool1.FilePath = "track_summary_ckf1.root" + trajectory_summary_writer_tool1.noDiagnostics = kwargs["noDiagnostics"] + trajectory_summary_writer_tool2 = CompFactory.RootTrajectorySummaryWriterTool(**kwargs) + trajectory_summary_writer_tool2.FilePath = "track_summary_ckf2.root" + trajectory_summary_writer_tool2.noDiagnostics = kwargs["noDiagnostics"] + + actsExtrapolationTool = CompFactory.FaserActsExtrapolationTool("FaserActsExtrapolationTool") + actsExtrapolationTool.MaxSteps = 1000 + actsExtrapolationTool.TrackingGeometryTool = CompFactory.FaserActsTrackingGeometryTool("TrackingGeometryTool") + + trajectory_performance_writer_tool = CompFactory.PerformanceWriterTool("PerformanceWriterTool", **kwargs) + trajectory_performance_writer_tool.ExtrapolationTool = actsExtrapolationTool + trajectory_performance_writer_tool.noDiagnostics = kwargs["noDiagnostics"] + + + ckf = CompFactory.CKF2(**kwargs) + kalman_fitter1 = CompFactory.KalmanFitterTool(name="fitterTool1", **kwargs) + kalman_fitter1.noDiagnostics = kwargs["noDiagnostics"] + kalman_fitter1.ActsLogging = "INFO" + kalman_fitter1.SummaryWriter = True + kalman_fitter1.StatesWriter = True + kalman_fitter1.SeedCovarianceScale = 10 + kalman_fitter1.RootTrajectoryStatesWriterTool = trajectory_states_writer_tool1 + kalman_fitter1.RootTrajectorySummaryWriterTool = trajectory_summary_writer_tool1 + ckf.KalmanFitterTool1 = kalman_fitter1 + + kalman_fitter2 = CompFactory.KalmanFitterTool(name="fitterTool2", **kwargs) + kalman_fitter2.noDiagnostics = kwargs["noDiagnostics"] + kalman_fitter2.ActsLogging = "INFO" + kalman_fitter2.SummaryWriter = True + kalman_fitter2.StatesWriter = True + kalman_fitter2.SeedCovarianceScale = 1 + kalman_fitter2.RootTrajectoryStatesWriterTool = trajectory_states_writer_tool2 + kalman_fitter2.RootTrajectorySummaryWriterTool = trajectory_summary_writer_tool2 + ckf.KalmanFitterTool2 = kalman_fitter2 + + ckf.TrackSeed = track_seed_tool + ckf.ActsLogging = "INFO" + ckf.RootTrajectoryStatesWriterTool = trajectory_states_writer_tool + ckf.RootTrajectorySummaryWriterTool = trajectory_summary_writer_tool + ckf.PerformanceWriter = trajectory_performance_writer_tool + + ckf.nMax = 10 + ckf.chi2Max = 25 + acc.addEventAlgo(ckf) + acc.merge(CKF2_OutputCfg(flags)) + return acc diff --git a/Tracking/Acts/FaserActsKalmanFilter/python/CombinatorialKalmanFilterConfig.py b/Tracking/Acts/FaserActsKalmanFilter/python/CombinatorialKalmanFilterConfig.py index eff59e223aa10a06a3e1f7202f350f6d7cb58243..fac9e7ec1713f9e387da5746ea5c9fd98519202e 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/python/CombinatorialKalmanFilterConfig.py +++ b/Tracking/Acts/FaserActsKalmanFilter/python/CombinatorialKalmanFilterConfig.py @@ -34,8 +34,10 @@ def CombinatorialKalmanFilterCfg(flags, **kwargs): acts_tracking_geometry_svc = ActsTrackingGeometrySvcCfg(flags) acc.merge(acts_tracking_geometry_svc ) -# track_seed_tool = CompFactory.ClusterTrackSeedTool() + # track_seed_tool = CompFactory.ClusterTrackSeedTool() track_seed_tool = CompFactory.ThreeStationTrackSeedTool() + # track_seed_tool = CompFactory.ActsTrackSeedTool() + # track_seed_tool = CompFactory.MyTrackSeedTool() sigma_loc0 = 1.9e-2 sigma_loc1 = 9e-1 sigma_phi = 3.3e-2 @@ -43,31 +45,29 @@ def CombinatorialKalmanFilterCfg(flags, **kwargs): 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 + initial_variance_inflation = [100, 100, 100, 100, 1000] + track_seed_tool.covLoc0 = initial_variance_inflation[0] * sigma_loc0 * sigma_loc0 + track_seed_tool.covLoc1 = initial_variance_inflation[1] * sigma_loc1 * sigma_loc1 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 - actsExtrapolationTool = CompFactory.FaserActsExtrapolationTool("FaserActsExtrapolationTool") - actsExtrapolationTool.MaxSteps = 1000 - actsExtrapolationTool.TrackingGeometryTool = CompFactory.FaserActsTrackingGeometryTool("TrackingGeometryTool") - trajectory_states_writer_tool = CompFactory.RootTrajectoryStatesWriterTool() trajectory_states_writer_tool.noDiagnostics = kwargs["noDiagnostics"] trajectory_states_writer_tool.MC = True trajectory_summary_writer_tool = CompFactory.RootTrajectorySummaryWriterTool() - trajectory_summary_writer_tool .noDiagnostics = kwargs["noDiagnostics"] + trajectory_summary_writer_tool.noDiagnostics = kwargs["noDiagnostics"] + actsExtrapolationTool = CompFactory.FaserActsExtrapolationTool("FaserActsExtrapolationTool") + actsExtrapolationTool.MaxSteps = 1000 + actsExtrapolationTool.TrackingGeometryTool = CompFactory.FaserActsTrackingGeometryTool("TrackingGeometryTool") performance_writer_tool = CompFactory.PerformanceWriterTool("PerformanceWriterTool") performance_writer_tool.noDiagnostics = kwargs["noDiagnostics"] performance_writer_tool.ExtrapolationTool = actsExtrapolationTool - ckf = CompFactory.CombinatorialKalmanFilterAlg(**kwargs) ckf.TrackSeed = track_seed_tool ckf.ActsLogging = "INFO" @@ -75,10 +75,9 @@ def CombinatorialKalmanFilterCfg(flags, **kwargs): 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 + ckf.nMax = 10 + ckf.chi2Max = 25 acc.addEventAlgo(ckf) acc.merge(CombinatorialKalmanFilter_OutputCfg(flags)) return acc diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/ActsTrackSeedTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/ActsTrackSeedTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4d90b6c7c619ec160bee114123066c7c25aa30a3 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/ActsTrackSeedTool.cxx @@ -0,0 +1,147 @@ +#include "FaserActsKalmanFilter/ActsTrackSeedTool.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" +#include "boost/container/small_vector.hpp" +#include "Acts/Seeding/EstimateTrackParamsFromSeed.hpp" + +using namespace Acts::UnitLiterals; + + +ActsTrackSeedTool::ActsTrackSeedTool( + const std::string& type, const std::string& name, const IInterface* parent) + : base_class(type, name, parent) {} + + +StatusCode ActsTrackSeedTool::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 ActsTrackSeedTool::run() { + 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 FaserActsGeometryContext& gctx = m_trackingGeometryTool->getNominalGeometryContext(); + Acts::GeometryContext geoctx = gctx.context(); + + 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(); + 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(geoctx, 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 ActsTrackSeedTool::finalize() { + return StatusCode::SUCCESS; +} + + +Acts::CurvilinearTrackParameters ActsTrackSeedTool::get_params( + const Acts::GeometryContext& gctx, const Amg::Vector3D& pos1, + const Amg::Vector3D& pos2, const Amg::Vector3D& pos3, + const Acts::BoundSymMatrix& cov, double origin) { + const auto surface = Acts::Surface::makeShared<Acts::PlaneSurface>( + Acts::Vector3 {0, 0, pos1.z()}, Acts::Vector3{0, 0, -1}); + boost::container::small_vector<const Amg::Vector3D*, 3> spacepoints {}; + spacepoints.push_back(&pos1); + spacepoints.push_back(&pos2); + spacepoints.push_back(&pos3); + auto trackParams = Acts::CurvilinearTrackParameters(Acts::Vector4{0, 0, 0, 0}, Acts::Vector3{0, 0, 0}, 0, 0, cov); + auto optParams = Acts::estimateTrackParamsFromSeed( + gctx, spacepoints.begin(), spacepoints.end(), *surface, Acts::Vector3{0.57_T, 0, 0}, 0.1_T); + if (not optParams.has_value()) { + std::cout << "Estimation of track parameters failed." << std::endl; + } else { + const auto& params = optParams.value(); + double charge = std::copysign(1, params[Acts::eBoundQOverP]); + Acts::Vector4 pos {params.x(), params.y(), params.z(), params.w()}; + Acts::Vector3 dir{std::sin(params[Acts::eBoundTheta]) * std::cos(params[Acts::eBoundPhi]), + std::sin(params[Acts::eBoundTheta]) * std::sin(params[Acts::eBoundPhi]), + std::cos(params[Acts::eBoundTheta])}; + double abs_momentum = std::abs(1/params[Acts::eBoundQOverP]); + trackParams = Acts::CurvilinearTrackParameters(pos, dir, charge, abs_momentum, cov); + } + return trackParams; +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/CKF2.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/CKF2.cxx new file mode 100644 index 0000000000000000000000000000000000000000..355e4a930024de1239d222e24fddf1f7560b6feb --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/CKF2.cxx @@ -0,0 +1,647 @@ +#include "FaserActsKalmanFilter/CKF2.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 <algorithm> + +#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" + + +#include "Acts/EventData/Measurement.hpp" +#include "FaserActsKalmanFilter/CircleFit.h" + +size_t CKF2::TrajectoryInfo::nClusters {0}; + +using TrajectoriesContainer = std::vector<FaserActsRecMultiTrajectory>; +//std::array<Acts::BoundIndices, 2> indices = {Acts::eBoundLoc0, Acts::eBoundLoc1}; + + +CKF2::CKF2( + const std::string& name, ISvcLocator* pSvcLocator) + : AthAlgorithm(name, pSvcLocator) {} + + +StatusCode CKF2::initialize() { + ATH_CHECK(m_fieldCondObjInputKey.initialize()); + ATH_CHECK(m_trackingGeometryTool.retrieve()); + ATH_CHECK(m_trackSeedTool.retrieve()); + ATH_CHECK(m_kalmanFitterTool1.retrieve()); + ATH_CHECK(m_kalmanFitterTool2.retrieve()); + // ATH_CHECK(m_trackCollection.initialize()); + if (m_performanceWriter && !m_noDiagnostics) { + ATH_CHECK(m_performanceWriterTool.retrieve()); + } + if (m_statesWriter && !m_noDiagnostics) { + ATH_CHECK(m_trajectoryStatesWriterTool.retrieve()); + } + if (m_summaryWriter && !m_noDiagnostics) { + 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); + m_kf = makeTrackFitterFunction(m_trackingGeometryTool->trackingGeometry()); + // 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 CKF2::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 magFieldContext = getMagneticFieldContext(ctx); + Acts::CalibrationContext calibContext; + + 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::vector<Identifier> ids {}; + for (const auto& idLink : *idLinks) { + ids.push_back(idLink.second); + } + std::shared_ptr<std::vector<Measurement>> measurements = m_trackSeedTool->measurements(); + std::shared_ptr<std::vector<const Tracker::FaserSCT_Cluster*>> clusters = m_trackSeedTool->clusters(); + std::shared_ptr<std::vector<const Tracker::FaserSCT_SpacePoint*>> spacePoints = m_trackSeedTool->spacePoints(); + std::shared_ptr<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>> seedClusters = m_trackSeedTool->seedClusters(); + + TrajectoryInfo::nClusters = sourceLinks->size(); + + TrajectoriesContainer trajectories; + trajectories.reserve(initialParameters->size()); + + Acts::PropagatorPlainOptions pOptions; + pOptions.maxSteps = m_maxSteps; + + Acts::MeasurementSelector::Config measurementSelectorCfg = { + {Acts::GeometryIdentifier(), {m_chi2Max, m_nMax}}, + }; + + Acts::RotationMatrix3 rotation = Acts::RotationMatrix3::Identity(); + rotation.col(0) = Acts::Vector3(0, 0, -1); + rotation.col(1) = Acts::Vector3(0, 1, 0); + rotation.col(2) = Acts::Vector3(1, 0, 0); + Acts::Translation3 trans(0., 0., 0.); + Acts::Transform3 trafo(rotation * trans); + initialSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(trafo); + + // Set the CombinatorialKalmanFilter options + CKF2::TrackFinderOptions options( + geoctx, 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); + } + + for (const auto& init : *initialParameters) { + ATH_MSG_DEBUG(" position: " << init.position(geoctx).transpose()); + ATH_MSG_DEBUG(" momentum: " << init.momentum().transpose()); + ATH_MSG_DEBUG(" charge: " << init.charge()); + } + + auto results = (*m_fit)(tmp, *initialParameters, options); + + /* + for (std::size_t iseed = 0; iseed < results.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(geoctx, result); + + if (!trackFindingOutput.fittedParameters.empty()) { + const std::unordered_map<size_t, Acts::BoundTrackParameters> ¶ms = 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); + } + + m_kalmanFitterTool1->fit(ctx, *track); + + // 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()); + } + } + */ + + + // std::vector<TrackQuality> trackQuality; + // selectTracks(results, trackQuality); + // + // 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); + + // results contains a MultiTrajectory for each track seed with a trajectory of each branch of the CKF. + // To simplify the ambiguity solving a list of MultiTrajectories is created, each containing only a single track. + std::list<TrajectoryInfo> allTrajectories; + for (auto &result : results) { + if (not result.ok()) { + continue; + } + CKFResult ckfResult = result.value(); + for (size_t trackTip : ckfResult.lastMeasurementIndices) { + allTrajectories.emplace_back(TrajectoryInfo(FaserActsRecMultiTrajectory( + ckfResult.fittedStates, {trackTip}, {{trackTip, ckfResult.fittedParameters.at(trackTip)}}))); + } + } + + // the list of MultiTrajectories is sorted by the number of measurements using the chi2 value as a tie-breaker + allTrajectories.sort([](const TrajectoryInfo &left, const TrajectoryInfo &right) { + if (left.nMeasurements > right.nMeasurements) return true; + if (left.nMeasurements < right.nMeasurements) return false; + if (left.chi2 < right.chi2) return true; + else return false; + }); + + // select all tracks with at least 13 heats and with 6 or less shared hits, starting from the best track + // TODO use Gaudi parameters for the number of hits and shared hits + // TODO allow shared hits only in the first station? + std::vector<FaserActsRecMultiTrajectory> selectedTrajectories {}; + while (not allTrajectories.empty()) { + TrajectoryInfo selected = allTrajectories.front(); + selectedTrajectories.push_back(selected.trajectory); + allTrajectories.remove_if([&](const TrajectoryInfo &p) { + return (p.nMeasurements <= 12) || ((p.clusterSet & selected.clusterSet).count() > 6); + }); + } + + for (const FaserActsRecMultiTrajectory &traj : selectedTrajectories) { + const auto params = traj.trackParameters(traj.tips().front()); + ATH_MSG_DEBUG("Fitted parameters"); + ATH_MSG_DEBUG(" params: " << params.parameters().transpose()); + ATH_MSG_DEBUG(" position: " << params.position(geoctx).transpose()); + ATH_MSG_DEBUG(" momentum: " << params.momentum().transpose()); + ATH_MSG_DEBUG(" charge: " << params.charge()); + double charge = params.charge(); + std::unique_ptr<Trk::Track> track = makeTrack(geoctx, traj); + if (track) { + // outputTracks->push_back(std::move(track)); + std::unique_ptr<Trk::Track> track2 = m_kalmanFitterTool1->fit(ctx, *track, trajectories, Acts::BoundVector::Zero()); + if (track2) { + std::unique_ptr<Trk::Track> track3 = m_kalmanFitterTool2->fit(ctx, *track2, trajectories, Acts::BoundVector::Zero()); + outputTracks->push_back(std::move(track3)); + } + } + } + + // run the performance writer + if (m_statesWriter && !m_noDiagnostics) { + ATH_CHECK(m_trajectoryStatesWriterTool->write(geoctx, selectedTrajectories)); + } + if (m_summaryWriter && !m_noDiagnostics) { + ATH_CHECK(m_trajectorySummaryWriterTool->write(geoctx, selectedTrajectories)); + } + if (m_performanceWriter && !m_noDiagnostics) { + ATH_CHECK(m_performanceWriterTool->write(geoctx, selectedTrajectories)); + } + ATH_CHECK(trackContainer.record(std::move(outputTracks))); + + return StatusCode::SUCCESS; +} + + +StatusCode CKF2::finalize() { + return StatusCode::SUCCESS; +} + + +Acts::MagneticFieldContext CKF2::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> +CKF2::makeTrack(const Acts::GeometryContext &geoCtx, const FaserActsRecMultiTrajectory &traj) const { + using ConstTrackStateProxy = + Acts::detail_lt::TrackStateProxy<IndexSourceLink, 6, true>; + std::unique_ptr<Trk::Track> newtrack = nullptr; + //Get the fit output object + 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 + traj.multiTrajectory().visitBackwards(traj.tips().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; +} + + +std::unique_ptr<Trk::Track> +CKF2::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* +CKF2::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 CKF2::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); + }); + } + } +} + + +namespace { + +using Updater = Acts::GainMatrixUpdater; +using Smoother = Acts::GainMatrixSmoother; + +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<CKF2::TrackParameters>; + +struct TrackFinderFunctionImpl + : public CKF2::TrackFinderFunction { + CKF trackFinder; + + TrackFinderFunctionImpl(CKF&& f) : trackFinder(std::move(f)) {} + + CKF2::TrackFinderResult operator()( + const IndexSourceLinkContainer& sourcelinks, + const TrackParametersContainer& initialParameters, + const CKF2::TrackFinderOptions& options) + const override { + return trackFinder.findTracks(sourcelinks, initialParameters, options); + }; +}; + +} // namespace + +std::shared_ptr<CKF2::TrackFinderFunction> +CKF2::makeTrackFinderFunction( + 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)); +} + + +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 CKF2::TrackFitterFunction { + Fitter trackFitter; + + TrackFitterFunctionImpl(Fitter &&f) : trackFitter(std::move(f)) {} + + CKF2::KFResult operator()( + const std::vector<IndexSourceLink> &sourceLinks, + const Acts::BoundTrackParameters &initialParameters, + const CKF2::TrackFitterOptions &options) + const override { + return trackFitter.fit(sourceLinks, initialParameters, options); + }; +}; + +} // namespace + + +std::shared_ptr<CKF2::TrackFitterFunction> +CKF2::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)); +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/CombinatorialKalmanFilterAlg.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/CombinatorialKalmanFilterAlg.cxx index c565a135729fad666f5d1bdc4c2d6d4b5131579c..2ee66e278cd3488a4c99611c11d73a21bac2b3d2 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/src/CombinatorialKalmanFilterAlg.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/CombinatorialKalmanFilterAlg.cxx @@ -19,9 +19,11 @@ #include "Acts/Surfaces/PerigeeSurface.hpp" #include "Acts/MagneticField/MagneticFieldContext.hpp" #include "FaserActsKalmanFilter/TrackSelection.h" -#include "FaserActsKalmanFilter/MyAmbiguitySolver.h" #include <algorithm> + +size_t CombinatorialKalmanFilterAlg::TrajectoryInfo::nClusters {0}; + using TrajectoriesContainer = std::vector<FaserActsRecMultiTrajectory>; std::array<Acts::BoundIndices, 2> indices = {Acts::eBoundLoc0, Acts::eBoundLoc1}; @@ -36,13 +38,18 @@ StatusCode CombinatorialKalmanFilterAlg::initialize() { ATH_CHECK(m_trackingGeometryTool.retrieve()); ATH_CHECK(m_trackSeedTool.retrieve()); // ATH_CHECK(m_trackCollection.initialize()); - ATH_CHECK(m_performanceWriterTool.retrieve()); - ATH_CHECK(m_trajectoryStatesWriterTool.retrieve()); - ATH_CHECK(m_trajectorySummaryWriterTool.retrieve()); + if (m_performanceWriter && !m_noDiagnostics) { + ATH_CHECK(m_performanceWriterTool.retrieve()); + } + if (m_statesWriter && !m_noDiagnostics) { + ATH_CHECK(m_trajectoryStatesWriterTool.retrieve()); + } + if (m_summaryWriter && !m_noDiagnostics) { + 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_noDiagnostics) { m_logger = Acts::getDefaultLogger("KalmanFitter", Acts::Logging::VERBOSE); } else if (m_actsLogging == "DEBUG" && !m_noDiagnostics) { @@ -68,8 +75,8 @@ StatusCode CombinatorialKalmanFilterAlg::execute() { const FaserActsGeometryContext& gctx = m_trackingGeometryTool->getNominalGeometryContext(); auto geoctx = gctx.context(); - Acts::MagneticFieldContext magctx = getMagneticFieldContext(ctx); - Acts::CalibrationContext calctx; + Acts::MagneticFieldContext magFieldContext = getMagneticFieldContext(ctx); + Acts::CalibrationContext calibContext; CHECK(m_trackSeedTool->run()); std::shared_ptr<const Acts::Surface> initialSurface = @@ -81,6 +88,9 @@ StatusCode CombinatorialKalmanFilterAlg::execute() { 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(); + std::shared_ptr<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>> seedClusters = m_trackSeedTool->seedClusters(); + + TrajectoryInfo::nClusters = sourceLinks->size(); TrajectoriesContainer trajectories; trajectories.reserve(initialParameters->size()); @@ -88,114 +98,78 @@ StatusCode CombinatorialKalmanFilterAlg::execute() { 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}}, }; + Acts::RotationMatrix3 rotation = Acts::RotationMatrix3::Identity(); + rotation.col(0) = Acts::Vector3(0, 0, -1); + rotation.col(1) = Acts::Vector3(0, 1, 0); + rotation.col(2) = Acts::Vector3(1, 0, 0); + Acts::Translation3 trans(0., 0., 0.); + Acts::Transform3 trafo(rotation * trans); + initialSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(trafo); + // Set the CombinatorialKalmanFilter options CombinatorialKalmanFilterAlg::TrackFinderOptions options( - geoContext, magFieldContext, calibContext, + geoctx, magFieldContext, calibContext, IndexSourceLinkAccessor(), MeasurementCalibrator(*measurements), Acts::MeasurementSelector(measurementSelectorCfg), Acts::LoggerWrapper{*m_logger}, pOptions, &(*initialSurface)); + m_numberOfTrackSeeds += initialParameters->size(); + // Perform the track finding for all initial parameters ATH_MSG_DEBUG("Invoke track finding with " << initialParameters->size() << " seeds."); - m_numberOfTrackSeeds += initialParameters->size(); IndexSourceLinkContainer tmp; for (const auto& sl : *sourceLinks) { tmp.emplace_hint(tmp.end(), sl); } auto results = (*m_fit)(tmp, *initialParameters, options); - m_numberOfFittedTracks += results.size(); - - std::vector<TrackQuality> trackQuality; - selectTracks(results, trackQuality); - 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)); - } - m_numberOfSelectedTracks += selectedResults.size(); - /* - TrackFinderResult minTrackRequirements {}; - for (auto& result : results) { + // results contains a MultiTrajectory for each track seed with a trajectory of each branch of the CKF. + // To simplify the ambiguity solving a list of MultiTrajectories is created, each containing only a single track. + std::list<TrajectoryInfo> allTrajectories; + 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)); + CKFResult ckfResult = result.value(); + for (size_t trackTip : ckfResult.lastMeasurementIndices) { + allTrajectories.emplace_back(TrajectoryInfo(FaserActsRecMultiTrajectory( + ckfResult.fittedStates, {trackTip}, {{trackTip, ckfResult.fittedParameters.at(trackTip)}}))); } } - 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())); - } + // the list of MultiTrajectories is sorted by the number of measurements using the chi2 value as a tie-breaker + allTrajectories.sort([](const TrajectoryInfo &left, const TrajectoryInfo &right) { + if (left.nMeasurements > right.nMeasurements) return true; + if (left.nMeasurements < right.nMeasurements) return false; + if (left.chi2 < right.chi2) return true; + else return false; + }); + + // select all tracks with at least 13 heats and with 6 or less shared hits, starting from the best track + // TODO use Gaudi parameters for the number of hits and shared hits + // TODO allow shared hits only in the first station? + std::vector<FaserActsRecMultiTrajectory> selectedTrajectories {}; + while (not allTrajectories.empty()) { + TrajectoryInfo selected = allTrajectories.front(); + selectedTrajectories.push_back(selected.trajectory); + allTrajectories.remove_if([&](const TrajectoryInfo &p) { + return (p.nMeasurements <= 12) || ((p.clusterSet & selected.clusterSet).count() > 6); + }); } - */ - 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()); + // create Trk::Tracks from the trajectories + for (const FaserActsRecMultiTrajectory &traj : selectedTrajectories) { + std::unique_ptr<Trk::Track> track = makeTrack(geoctx, traj); + if (track) { + outputTracks->push_back(std::move(track)); } } + // run the performance writer if (m_statesWriter && !m_noDiagnostics) { ATH_CHECK(m_trajectoryStatesWriterTool->write(geoctx, trajectories)); } @@ -233,83 +207,80 @@ Acts::MagneticFieldContext CombinatorialKalmanFilterAlg::getMagneticFieldContext } std::unique_ptr<Trk::Track> -CombinatorialKalmanFilterAlg::makeTrack(Acts::GeometryContext& geoCtx, TrackFitterResult& fitResult) const { +CombinatorialKalmanFilterAlg::makeTrack(const Acts::GeometryContext &geoCtx, const FaserActsRecMultiTrajectory &traj) const { using ConstTrackStateProxy = - Acts::detail_lt::TrackStateProxy<IndexSourceLink, 6, true>; + 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); + 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 + traj.multiTrajectory().visitBackwards(traj.tips().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()) + }; } } - 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); - } + 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; } diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/KalmanFitterTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/KalmanFitterTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..686047ae7232deb09ca207f6599666f0bd022aa3 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/KalmanFitterTool.cxx @@ -0,0 +1,355 @@ +#include "FaserActsKalmanFilter/KalmanFitterTool.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" +#include "TrackerIdentifier/FaserSCT_ID.h" + +#include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" + + +KalmanFitterTool::KalmanFitterTool(const std::string& type, const std::string& name, const IInterface* parent) : + AthAlgTool(type, name, parent) {} + + +StatusCode KalmanFitterTool::initialize() { + ATH_CHECK(m_fieldCondObjInputKey.initialize()); + ATH_CHECK(m_trackingGeometryTool.retrieve()); + ATH_CHECK(detStore()->retrieve(m_idHelper,"FaserSCT_ID")); + if (m_statesWriter && !m_noDiagnostics) ATH_CHECK(m_trajectoryStatesWriterTool.retrieve()); + if (m_summaryWriter && !m_noDiagnostics) ATH_CHECK(m_trajectorySummaryWriterTool.retrieve()); + m_fit = makeTrackFitterFunction(m_trackingGeometryTool->trackingGeometry()); + if (m_actsLogging == "VERBOSE" && !m_noDiagnostics) { + m_logger = Acts::getDefaultLogger("KalmanFitter", Acts::Logging::VERBOSE); + } else if (m_actsLogging == "DEBUG" && !m_noDiagnostics) { + m_logger = Acts::getDefaultLogger("KalmanFitter", Acts::Logging::DEBUG); + } else { + m_logger = Acts::getDefaultLogger("KalmanFitter", Acts::Logging::INFO); + } + return StatusCode::SUCCESS; +} + + +StatusCode KalmanFitterTool::finalize() { + return StatusCode::SUCCESS; +} + +std::unique_ptr<Trk::Track> +KalmanFitterTool::fit(const EventContext &ctx, const Trk::Track &inputTrack, + std::vector<FaserActsRecMultiTrajectory> &trajectories, + const Acts::BoundVector& inputVector = Acts::BoundVector::Zero()) const { + std::unique_ptr<Trk::Track> newTrack = nullptr; + std::vector<FaserActsRecMultiTrajectory> myTrajectories; + + if (!inputTrack.measurementsOnTrack() || inputTrack.measurementsOnTrack()->size() < m_minMeasurements) { + ATH_MSG_DEBUG("Input track has no or too little measurements and cannot be fitted"); + return nullptr; + } + + if (!inputTrack.trackParameters() || inputTrack.trackParameters()->empty()) { + ATH_MSG_DEBUG("Input track has no track parameters and cannot be fitted"); + return nullptr; + } + + + auto pSurface = Acts::Surface::makeShared<Acts::PlaneSurface>( + Acts::Vector3 {0, 0, 0}, Acts::Vector3{0, 0, -1}); + + Acts::GeometryContext gctx = m_trackingGeometryTool->getNominalGeometryContext().context(); + Acts::MagneticFieldContext mfContext = getMagneticFieldContext(ctx); + Acts::CalibrationContext calibContext = Acts::CalibrationContext(); + + auto [sourceLinks, measurements] = getMeasurementsFromTrack(inputTrack); + auto trackParameters = getParametersFromTrack(inputTrack.trackParameters()->front(), inputVector); + ATH_MSG_DEBUG("trackParameters: " << trackParameters.parameters().transpose()); + ATH_MSG_DEBUG("position: " << trackParameters.parameters().transpose()); + ATH_MSG_DEBUG("momentum: " << trackParameters.momentum().transpose()); + ATH_MSG_DEBUG("charge: " << trackParameters.charge()); + + Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder, Acts::VoidReverseFilteringLogic> + kfOptions(gctx, mfContext, calibContext, MeasurementCalibrator(measurements), + Acts::VoidOutlierFinder(), Acts::VoidReverseFilteringLogic(), Acts::LoggerWrapper{*m_logger}, + Acts::PropagatorPlainOptions(), &(*pSurface)); + kfOptions.multipleScattering = false; + kfOptions.energyLoss = false; + + ATH_MSG_DEBUG("Invoke fitter"); + auto result = (*m_fit)(sourceLinks, trackParameters, kfOptions); + + if (result.ok()) { + const auto& fitOutput = result.value(); + if (fitOutput.fittedParameters) { + const auto& params = fitOutput.fittedParameters.value(); + ATH_MSG_DEBUG("ReFitted parameters"); + ATH_MSG_DEBUG(" params: " << params.parameters().transpose()); + ATH_MSG_DEBUG(" position: " << params.position(gctx).transpose()); + ATH_MSG_DEBUG(" momentum: " << params.momentum().transpose()); + ATH_MSG_DEBUG(" charge: " << params.charge()); + using IndexedParams = std::unordered_map<size_t, Acts::BoundTrackParameters>; + IndexedParams indexedParams; + indexedParams.emplace(fitOutput.lastMeasurementIndex, std::move(params)); + std::vector<size_t> trackTips; + trackTips.reserve(1); + trackTips.emplace_back(fitOutput.lastMeasurementIndex); + // trajectories.emplace_back(std::move(fitOutput.fittedStates), + // std::move(trackTips), + // std::move(indexedParams)); + myTrajectories.emplace_back(std::move(fitOutput.fittedStates), + std::move(trackTips), + std::move(indexedParams)); + } else { + ATH_MSG_DEBUG("No fitted parameters for track"); + } + newTrack = makeTrack(gctx, result); + } + + if (m_statesWriter && !m_noDiagnostics) { + StatusCode statusStatesWriterTool = m_trajectoryStatesWriterTool->write(gctx, myTrajectories); + } + if (m_summaryWriter && !m_noDiagnostics) { + StatusCode statusSummaryWriterTool = m_trajectorySummaryWriterTool->write(gctx, myTrajectories); + } + + return newTrack; +} + + +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 KalmanFitterTool::TrackFitterFunction { + Fitter trackFitter; + + TrackFitterFunctionImpl(Fitter &&f) : trackFitter(std::move(f)) {} + + KalmanFitterTool::TrackFitterResult operator()( + const std::vector<IndexSourceLink> &sourceLinks, + const KalmanFitterTool::TrackParameters &initialParameters, + const KalmanFitterTool::TrackFitterOptions &options) + const override { + return trackFitter.fit(sourceLinks, initialParameters, options); + }; +}; + +} // namespace + + +std::shared_ptr<KalmanFitterTool::TrackFitterFunction> +KalmanFitterTool::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)); +} + + +Acts::MagneticFieldContext KalmanFitterTool::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::tuple<std::vector<IndexSourceLink>, std::vector<Measurement>> +KalmanFitterTool::getMeasurementsFromTrack(const Trk::Track &track) const { + const int kSize = 1; + std::array<Acts::BoundIndices, kSize> Indices = {Acts::eBoundLoc0}; + using ThisMeasurement = Acts::Measurement<IndexSourceLink, Acts::BoundIndices, kSize>; + using IdentifierMap = std::map<Identifier, Acts::GeometryIdentifier>; + + std::shared_ptr<IdentifierMap> identifierMap = m_trackingGeometryTool->getIdentifierMap(); + std::vector<IndexSourceLink> sourceLinks; + std::vector<Measurement> measurements; + for (const Trk::MeasurementBase *meas : *track.measurementsOnTrack()) { + const auto* clusterOnTrack = dynamic_cast<const Tracker::FaserSCT_ClusterOnTrack*>(meas); + const Tracker::FaserSCT_Cluster* cluster = clusterOnTrack->prepRawData(); + if (clusterOnTrack) { + Identifier id = clusterOnTrack->identify(); + Identifier waferId = m_idHelper->wafer_id(id); + if (identifierMap->count(waferId) != 0) { + Acts::GeometryIdentifier geoId = identifierMap->at(waferId); + IndexSourceLink sourceLink(geoId, measurements.size(), cluster); + Eigen::Matrix<double, 1, 1> pos {meas->localParameters()[Trk::locX],}; + Eigen::Matrix<double, 1, 1> cov {0.08 * 0.08 / 12}; + ThisMeasurement actsMeas(sourceLink, Indices, pos, cov); + sourceLinks.push_back(sourceLink); + measurements.emplace_back(std::move(actsMeas)); + } + } + } + return std::make_tuple(sourceLinks, measurements); +} + + +Acts::BoundTrackParameters +KalmanFitterTool::getParametersFromTrack(const Trk::TrackParameters *inputParameters, + const Acts::BoundVector& inputVector) const { + using namespace Acts::UnitLiterals; + std::shared_ptr<const Acts::Surface> pSurface = Acts::Surface::makeShared<Acts::PlaneSurface>( + Acts::Vector3 {0, 0, 0}, Acts::Vector3{0, 0, -1}); + + auto atlasParam = inputParameters->parameters(); + auto center = inputParameters->associatedSurface().center(); + // Acts::BoundVector params {center[Trk::locY], center[Trk::locX], + // atlasParam[Trk::phi0], atlasParam[Trk::theta], + // charge / (inputParameters->momentum().norm() * 1_MeV), + // 0.}; + Acts::BoundVector params; + if (inputVector == Acts::BoundVector::Zero()) { + params(0.0) = center[Trk::locY]; + params(1.0) = center[Trk::locX]; + params(2.0) = atlasParam[Trk::phi0]; + params(3.0) = atlasParam[Trk::theta]; + // input charge is 1 for positively charged particles and 0 for negatively charged particles! + double charge = 2 * inputParameters->charge() - 1; + params(4.0) = charge / (inputParameters->momentum().norm() * 1_MeV); + params(5.0) = 0.; + } else { + params = inputVector; + } + Acts::BoundSymMatrix cov = Acts::BoundSymMatrix::Identity(); + cov.topLeftCorner(5, 5) = *inputParameters->covariance(); + + for(int i=0; i < cov.rows(); i++){ + cov(i, 4) = cov(i, 4)/1_MeV; + } + for(int i=0; i < cov.cols(); i++){ + cov(4, i) = cov(4, i)/1_MeV; + } + for (int i = 0; i < 6; ++i) { + cov(i,i) = m_seedCovarianceScale * cov(i,i); + } + + return Acts::BoundTrackParameters(pSurface, params, inputParameters->charge(), cov); +} + + +std::unique_ptr<Trk::Track> +KalmanFitterTool::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) { + 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 = 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* +KalmanFitterTool::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/MyTrackSeedTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/MyTrackSeedTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c2648161b595230fc626544d4e9dd11fdf4118e5 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/MyTrackSeedTool.cxx @@ -0,0 +1,143 @@ +#include "FaserActsKalmanFilter/MyTrackSeedTool.h" + +#include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "TrackerPrepRawData/FaserSCT_ClusterCollection.h" +#include "TrackerSpacePoint/FaserSCT_SpacePoint.h" +#include "TrackerSpacePoint/FaserSCT_SpacePointCollection.h" +#include "Identifier/Identifier.h" +#include "Acts/Geometry/GeometryIdentifier.hpp" + + +MyTrackSeedTool::MyTrackSeedTool( const std::string& type, const std::string& name, const IInterface* parent) : + base_class(type, name, parent) {} + + +StatusCode MyTrackSeedTool::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()); + ATH_CHECK(m_spacePointContainerKey.initialize()); + return StatusCode::SUCCESS; +} + + +StatusCode MyTrackSeedTool::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()); + + 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(); + + std::map<Identifier, const Tracker::FaserSCT_SpacePoint*> spacePointMap {}; + for (const FaserSCT_SpacePointCollection* spacePointCollection : *spacePointContainer) { + for (const Tracker::FaserSCT_SpacePoint *spacePoint: *spacePointCollection) { + Identifier id1 = spacePoint->cluster1()->identify(); + spacePointMap[id1] = spacePoint; + Identifier id2 = spacePoint->cluster2()->identify(); + spacePointMap[id2] = spacePoint; + } + } + + 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_SpacePoint*> spacePoints {}; + 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); + if (spacePointMap.count(cluster->identify()) > 0) { + spacePoints.push_back(spacePointMap[cluster->identify()]); + } else { + spacePoints.push_back(nullptr); + } + } + } + } + + + 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::map<int, std::vector<Amg::Vector3D>> stationHitMap {}; + for (const Trk::Track* track : *trackCollection) { + const Amg::Vector3D position = track->trackParameters()->front()->position(); + for (const Trk::TrackStateOnSurface* trackState : *(track->trackStateOnSurfaces())) { + auto clusterOnTrack = dynamic_cast<const Tracker::FaserSCT_ClusterOnTrack*> (trackState->measurementOnTrack()); + if (clusterOnTrack) { + int station = m_idHelper->station(clusterOnTrack->identify()); + stationHitMap[station].push_back(position); + break; + } + } + } + + + std::vector<Acts::CurvilinearTrackParameters> initParams {}; + for (size_t i = 0; i < stationHitMap.size(); ++i) { + for (size_t j = i+1; j < stationHitMap.size(); ++j) { + for (const auto &p1 : stationHitMap[i]) { + for (const auto &p2 : stationHitMap[j]) { + initParams.push_back(get_params(p1, p2, 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); + m_spacePoints = std::make_shared<std::vector<const Tracker::FaserSCT_SpacePoint*>>(spacePoints); + // m_seedClusters = std::make_shared<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>>({}); + return StatusCode::SUCCESS; +} + + +StatusCode MyTrackSeedTool::finalize() { + return StatusCode::SUCCESS; +} + + +Acts::CurvilinearTrackParameters MyTrackSeedTool::get_params(const Amg::Vector3D& p1, const Amg::Vector3D& p2, const Acts::BoundSymMatrix& cov, double origin) { + Acts::Vector3 dir = p2 - p1; + Acts::Vector3 pos = p1 - (p1.z() - origin)/dir.z() * dir; + Acts::Vector4 pos4 {pos.x(), pos.y(), pos.z(), 0}; + return Acts::CurvilinearTrackParameters(pos4, dir, 10000000, 1, cov); +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/PerformanceWriterTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/PerformanceWriterTool.cxx index b01d58ed37c095c451c3f453cbbcc4f261945cec..c545c551adeb640a985ab4999d0864ecd817fb7c 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/src/PerformanceWriterTool.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/PerformanceWriterTool.cxx @@ -11,23 +11,23 @@ PerformanceWriterTool::PerformanceWriterTool( StatusCode PerformanceWriterTool::initialize() { - if (!m_noDiagnostics) { 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; + if (!m_noDiagnostics) { + 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; } diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectoryStatesWriterTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectoryStatesWriterTool.cxx index b857ce4788a0a8b51ad8bcc8080761bb732adac9..634e356a887d45afa6ddf7c06a1d8e4566d0ef8b 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectoryStatesWriterTool.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectoryStatesWriterTool.cxx @@ -23,13 +23,13 @@ RootTrajectoryStatesWriterTool::RootTrajectoryStatesWriterTool( : AthAlgTool(type, name, parent) {} StatusCode RootTrajectoryStatesWriterTool::initialize() { - if (!m_noDiagnostics) { - 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")); + 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")); + if (!m_noDiagnostics) { std::string filePath = m_filePath; std::string treeName = m_treeName; m_outputFile = TFile::Open(filePath.c_str(), "RECREATE"); diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectorySummaryWriterTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectorySummaryWriterTool.cxx index 2d8765e3163930e003b0d1a6eeaeb999256b9432..bb916b9bfefeaf47c013b29122c12eb48f17abf7 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectorySummaryWriterTool.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/RootTrajectorySummaryWriterTool.cxx @@ -32,11 +32,11 @@ RootTrajectorySummaryWriterTool::RootTrajectorySummaryWriterTool( StatusCode RootTrajectorySummaryWriterTool::initialize() { - if (!m_noDiagnostics) { - ATH_CHECK(m_simDataCollectionKey.initialize()); - ATH_CHECK(m_mcEventCollectionKey.initialize()); - ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + ATH_CHECK(m_simDataCollectionKey.initialize()); + ATH_CHECK(m_mcEventCollectionKey.initialize()); + ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); + if (!m_noDiagnostics) { std::string filePath = m_filePath; std::string treeName = m_treeName; m_outputFile = TFile::Open(filePath.c_str(), "RECREATE"); diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/ThreeStationTrackSeedTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/ThreeStationTrackSeedTool.cxx index b9e53c66f50eb6f4974ca04fdbd7fa028f2954e3..8c6eb8c0328b0ca194cb06083cc3c019cdbc0fd7 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/src/ThreeStationTrackSeedTool.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/ThreeStationTrackSeedTool.cxx @@ -61,22 +61,26 @@ StatusCode ThreeStationTrackSeedTool::run() { } - std::map<int, std::vector<Amg::Vector3D>> station_position_map; + std::map<int, std::vector<Tracklet>> station_tracklet_map; for (const Trk::Track* track : *trackCollection) { auto momentum = track->trackParameters()->front()->momentum(); - ATH_MSG_DEBUG("track momentum: " << momentum.x() << ", " << momentum.y() << ", " << momentum.z()); + int station = -1; + Amg::Vector3D trackletPosition {0, 0, 0}; + std::vector<const Tracker::FaserSCT_Cluster*> trackletClusters {}; 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; + const Tracker::FaserSCT_Cluster* cluster = clusterOnTrack->prepRawData(); + trackletClusters.push_back(cluster); + if (station == -1) { + Identifier id = clusterOnTrack->identify(); + station = m_idHelper->station(id); + auto fitParameters = track->trackParameters()->front(); + trackletPosition = fitParameters->position(); + } } } + station_tracklet_map[station].push_back(Tracklet(trackletPosition, trackletClusters)); } Acts::BoundSymMatrix cov = Acts::BoundSymMatrix::Zero(); @@ -88,12 +92,13 @@ StatusCode ThreeStationTrackSeedTool::run() { 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(); + std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>> seeds; + for (const auto& tracklet1 : station_tracklet_map[1]) { + for (const auto& tracklet2 : station_tracklet_map[2]) { + for (const auto& tracklet3 : station_tracklet_map[3]) { + initParams.push_back(get_params(tracklet1.position(), tracklet2.position(), tracklet3.position(), cov, m_origin)); + std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3> seed {tracklet1.clusters(), tracklet2.clusters(), tracklet3.clusters()}; + seeds.push_back(seed); } } } @@ -105,6 +110,7 @@ StatusCode ThreeStationTrackSeedTool::run() { 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); + m_seedClusters = std::make_shared<std::vector<std::array<std::vector<const Tracker::FaserSCT_Cluster*>, 3>>>(seeds); return StatusCode::SUCCESS; } @@ -120,8 +126,8 @@ Acts::CurvilinearTrackParameters ThreeStationTrackSeedTool::get_params( 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); + auto [abs_momentum, charge] = momentum({{1, position_st1}, {2, position_st2}, {3, position_st3}}); + return Acts::CurvilinearTrackParameters(pos4, dir, abs_momentum, 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); diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/TrackClassification.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/TrackClassification.cxx index 3feae9515e6007f91ca0696e03c8151ebdb456ea..785bf2be17d9fe0c612b0250c6eae67ae801626e 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/src/TrackClassification.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/TrackClassification.cxx @@ -46,20 +46,16 @@ void identifyContributingParticles( 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(); + std::vector<Identifier> ids = state.uncalibrated().hit()->rdoList(); + for (const Identifier &id : ids) { + if (simDataCollection.count(id) == 0) { + return true; + } + const auto &deposits = simDataCollection.find(id)->second.getdeposits(); + for (const TrackerSimData::Deposit &deposit : deposits) { + increaseHitCount(particleHitCounts, deposit.first->barcode()); } } - increaseHitCount(particleHitCounts, barcode); return true; }); sortHitCount(particleHitCounts); diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/TrackSeedWriterTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/TrackSeedWriterTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..42c4d1b7969d00e67b1f73ee21ff08a043c15df6 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/TrackSeedWriterTool.cxx @@ -0,0 +1,116 @@ +#include "FaserActsKalmanFilter/TrackSeedWriterTool.h" +#include "TFile.h" +#include "TTree.h" + +TrackSeedWriterTool::TrackSeedWriterTool(const std::string& type, + const std::string& name, + const IInterface* parent) + : AthAlgTool( type, name, parent ) {} + + +StatusCode TrackSeedWriterTool::initialize() { + ATH_MSG_INFO("TrackSeedWriterTool::initialize"); + + std::string filePath = m_filePath; + std::string treeName = m_treeName; + + 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_tree = new TTree(treeName.c_str(), "tree"); + if (m_tree == nullptr) { + ATH_MSG_ERROR("Unable to create TTree"); + return StatusCode::FAILURE; + } + + TrackSeedWriterTool::initializeTree(); + + return StatusCode::SUCCESS; +} + + +StatusCode TrackSeedWriterTool::finalize() { + m_file->cd(); + m_tree->Write(); + return StatusCode::SUCCESS; +} + + +void TrackSeedWriterTool::initializeTree() { + m_tree->Branch("run_number", &m_runNumber); + m_tree->Branch("event_number", &m_eventNumber); + m_tree->Branch("eLOC0", &m_eLOC0); + m_tree->Branch("eLOC1", &m_eLOC1); + m_tree->Branch("ePHI", &m_ePHI); + m_tree->Branch("eTHETA", &m_eTHETA); + m_tree->Branch("eQOP", &m_eQOP); + m_tree->Branch("err_eLOC0", &m_err_eLOC0); + m_tree->Branch("err_eLOC1", &m_err_eLOC1); + m_tree->Branch("err_ePHI", &m_err_ePHI); + m_tree->Branch("err_eTHETA", &m_err_eTHETA); + m_tree->Branch("err_eQOP", &m_err_eQOP); + m_tree->Branch("x", &m_x); + m_tree->Branch("y", &m_y); + m_tree->Branch("z", &m_z); + m_tree->Branch("px", &m_px); + m_tree->Branch("py", &m_py); + m_tree->Branch("pz", &m_pz); +} + + +void TrackSeedWriterTool::writeout( + const Acts::GeometryContext& gctx, + const std::shared_ptr<std::vector<Acts::CurvilinearTrackParameters>>& initialParametersContainer) const { + m_runNumber = Gaudi::Hive::currentContext().eventID().run_number(); + m_eventNumber = Gaudi::Hive::currentContext().eventID().event_number(); + for (Acts::CurvilinearTrackParameters initialParameters : *initialParametersContainer) { + const auto& parameters = initialParameters.parameters(); + const Acts::Vector3& center = initialParameters.referenceSurface().center(gctx); + m_eLOC0.push_back(center[Acts::eBoundLoc0]); + m_eLOC1.push_back(center[Acts::eBoundLoc1]); + m_ePHI.push_back(parameters[Acts::eBoundPhi]); + m_eTHETA.push_back(parameters[Acts::eBoundTheta]); + m_eQOP.push_back(parameters[Acts::eBoundQOverP]); + + const auto& covariance = *initialParameters.covariance(); + m_err_eLOC0.push_back(sqrt(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0))); + m_err_eLOC1.push_back(sqrt(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1))); + m_err_ePHI.push_back(sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi))); + m_err_eTHETA.push_back(sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta))); + m_err_eQOP.push_back(sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP))); + + const auto& position = initialParameters.position(gctx); + const auto& momentum = initialParameters.momentum(); + m_x.push_back(position.x()); + m_y.push_back(position.y()); + m_z.push_back(position.z()); + m_px.push_back(momentum.x()); + m_py.push_back(momentum.y()); + m_pz.push_back(momentum.z()); + } + m_tree->Fill(); + clearVariables(); +} + + +void TrackSeedWriterTool::clearVariables() const { + m_eLOC0.clear(); + m_eLOC1.clear(); + m_ePHI.clear(); + m_eTHETA.clear(); + m_eQOP.clear(); + m_err_eLOC0.clear(); + m_err_eLOC1.clear(); + m_err_ePHI.clear(); + m_err_eTHETA.clear(); + m_err_eQOP.clear(); + m_x.clear(); + m_y.clear(); + m_z.clear(); + m_px.clear(); + m_py.clear(); + m_pz.clear(); +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx index 0a79b99832495297ac3a3ebd419a1134c8f3a9e3..8d56370abefe0f7399095ac3b62d5bc387ad2f35 100755 --- a/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx @@ -20,6 +20,11 @@ //#include "FaserActsKalmanFilter/ClusterTrackSeedTool.h" #include "FaserActsKalmanFilter/ThreeStationTrackSeedTool.h" #include "FaserActsKalmanFilter/PerformanceWriterTool.h" +#include "FaserActsKalmanFilter/TrackSeedWriterTool.h" +#include "FaserActsKalmanFilter/ActsTrackSeedTool.h" +#include "FaserActsKalmanFilter/CKF2.h" +#include "FaserActsKalmanFilter/KalmanFitterTool.h" +#include "FaserActsKalmanFilter/MyTrackSeedTool.h" DECLARE_COMPONENT(FaserActsKalmanFilterAlg) @@ -40,3 +45,8 @@ DECLARE_COMPONENT(RootTrajectorySummaryWriterTool) //DECLARE_COMPONENT(ClusterTrackSeedTool) DECLARE_COMPONENT(ThreeStationTrackSeedTool) DECLARE_COMPONENT(PerformanceWriterTool) +DECLARE_COMPONENT(TrackSeedWriterTool) +DECLARE_COMPONENT(ActsTrackSeedTool) +DECLARE_COMPONENT(CKF2) +DECLARE_COMPONENT(KalmanFitterTool) +DECLARE_COMPONENT(MyTrackSeedTool) diff --git a/Tracking/Acts/FaserActsKalmanFilter/test/CKF2.py b/Tracking/Acts/FaserActsKalmanFilter/test/CKF2.py new file mode 100644 index 0000000000000000000000000000000000000000..5d41a03a33273d3003677932920b059df871b3d5 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/test/CKF2.py @@ -0,0 +1,46 @@ +#!/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 AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg +# from AthenaPoolCnvSvc.PoolWriteConfig import PoolWriteCfg +from TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg +from TrackerSpacePointFormation.TrackerSpacePointFormationConfig import TrackerSpacePointFinderCfg +from TrackerSegmentFit.TrackerSegmentFitConfig import SegmentFitAlgCfg +from FaserActsKalmanFilter.CKF2Config import CKF2Cfg + +log.setLevel(DEBUG) +Configurable.configurableRun3Behavior = True + +ConfigFlags.Input.Files = ['my.RDO.pool.root'] +ConfigFlags.Output.ESDFileName = "CKF.ESD.pool.root" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-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) +acc.merge(PoolReadCfg(ConfigFlags)) +# acc.merge(PoolWriteCfg(ConfigFlags)) + +acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags)) +acc.merge(TrackerSpacePointFinderCfg(ConfigFlags)) +acc.merge(SegmentFitAlgCfg(ConfigFlags, SharedHitFraction=0.51, MinClustersPerFit=5, TanThetaCut=0.25)) +acc.merge(CKF2Cfg(ConfigFlags, noDiagnostics=True)) + +# logging.getLogger('forcomps').setLevel(VERBOSE) +# acc.foreach_component("*").OutputLevel = VERBOSE +# acc.foreach_component("*ClassID*").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()) diff --git a/Tracking/Acts/FaserActsKalmanFilter/test/CombinatorialKalmanFilterAlg.py b/Tracking/Acts/FaserActsKalmanFilter/test/CombinatorialKalmanFilterAlg.py index 887c03812bce040d5cdf43f0559a499cbbe02b89..308d6f1c55e0eacfa96c59cd4e82d59fd5cb0211 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/test/CombinatorialKalmanFilterAlg.py +++ b/Tracking/Acts/FaserActsKalmanFilter/test/CombinatorialKalmanFilterAlg.py @@ -9,6 +9,7 @@ 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 TrackerSegmentFit.TrackerSegmentFitConfig import SegmentFitAlgCfg from FaserActsKalmanFilter.CombinatorialKalmanFilterConfig import CombinatorialKalmanFilterCfg @@ -29,9 +30,10 @@ acc.merge(PoolReadCfg(ConfigFlags)) # acc.merge(PoolWriteCfg(ConfigFlags)) acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags)) -acc.merge(SegmentFitAlgCfg(ConfigFlags)) -acc.merge(CombinatorialKalmanFilterCfg(ConfigFlags)) -# acc.getEventAlgo("CombinatorialKalmanFilterAlg").OutputLevel = VERBOSE +acc.merge(TrackerSpacePointFinderCfg(ConfigFlags)) +acc.merge(SegmentFitAlgCfg(ConfigFlags, SharedHitFraction=0.51, MinClustersPerFit=5, TanThetaCut=0.25)) +acc.merge(CombinatorialKalmanFilterCfg(ConfigFlags, noDiagnostics=True)) +acc.getEventAlgo("CombinatorialKalmanFilterAlg").OutputLevel = VERBOSE # logging.getLogger('forcomps').setLevel(INFO) # acc.foreach_component("*").OutputLevel = INFO diff --git a/Tracking/Acts/FaserActsKalmanFilter/test/CombinatorialKalmanFilterAlg_Data.py b/Tracking/Acts/FaserActsKalmanFilter/test/CombinatorialKalmanFilterAlg_Data.py index 81b9f6acd6c2c42d74de52e12d775d4dff2d0307..3ea0fccd734ab65888d3b3a9c7505d2d2dc63738 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/test/CombinatorialKalmanFilterAlg_Data.py +++ b/Tracking/Acts/FaserActsKalmanFilter/test/CombinatorialKalmanFilterAlg_Data.py @@ -17,6 +17,7 @@ Configurable.configurableRun3Behavior = True ConfigFlags.Input.Files = ['/home/tboeckh/Documents/data/raw/TI12/MiddleStationTrack.raw'] ConfigFlags.Output.ESDFileName = "CKF.ESD.pool.root" +ConfigFlags.addFlag("Output.xAODFileName", f"CKF.xAOD.root") ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-01" ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" ConfigFlags.Input.ProjectName = "data21" @@ -33,7 +34,19 @@ acc.merge(PoolWriteCfg(ConfigFlags)) acc.merge(FaserByteStreamCnvSvcCfg(ConfigFlags)) acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags, DataObjectName="SCT_LEVELMODE_RDOs", ClusterToolTimingPattern="X1X")) acc.merge(SegmentFitAlgCfg(ConfigFlags)) -acc.merge(CombinatorialKalmanFilterCfg(ConfigFlags, noDiagnostics=True)) +acc.merge(CombinatorialKalmanFilterCfg(ConfigFlags, SummaryWriter=False, StatesWriter=False, PerformanceWriter=False)) +acc.getEventAlgo("CombinatorialKalmanFilterAlg").OutputLevel = VERBOSE + +from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg +itemList = ["xAOD::EventInfo#*", + "xAOD::EventAuxInfo#*", + "FaserSCT_RDO_Container#*", + "Tracker::FaserSCT_ClusterContainer#*", + "TrackCollection#*"] +acc.merge(OutputStreamCfg(ConfigFlags, "xAOD", itemList)) + +print( "Writing out xAOD objects:" ) +print( acc.getEventAlgo("OutputStreamxAOD").ItemList ) # logging.getLogger('forcomps').setLevel(VERBOSE) # acc.foreach_component("*").OutputLevel = VERBOSE @@ -50,5 +63,5 @@ replicaSvc.UseCOOLSQLite = True replicaSvc.UseCOOLFrontier = False replicaSvc.UseGeomSQLite = True -sc = acc.run(maxEvents=-1) +sc = acc.run(maxEvents=20) sys.exit(not sc.isSuccess()) diff --git a/Tracking/Acts/README.md b/Tracking/Acts/README.md index 2a0874fce87ed08d42fa4ac7c77d0226d430e318..5b4c24356a742621045dc568190bcb9c2315acca 100644 --- a/Tracking/Acts/README.md +++ b/Tracking/Acts/README.md @@ -6,3 +6,13 @@ 3) To write the tracking geometry, type the command: FaserActsWriteTrackingGeometry.py 4) To run the extrapolator, type the command: FaserActsExtrapolationAlg.py + +5) The track finding requires a json file with the correct material in the directory in which you run it. A copy can be found on lxplus: /afs/cern.ch/user/t/tboeckh/public/material/material-maps.json + If you do not want to use the material you have to comment out this line: ConfigFlags.TrackingGeometry.MaterialSource = "Input" + +6) To enable additional output set the noDiagnostics flag to False + +7) To do the track finding, type the command: CombinatorialKalmanFilterAlg.py + +8) To do the track finding and re-fit the best tracks, type the command: CKF2.py + (this is the recommended approach)