Commit 57f37e7d authored by Shaun Roe's avatar Shaun Roe Committed by Walter Lampl
Browse files

refactor trk ambiguity processor

change scoring interfaces to use TrackCollection, avoid additional copying of TrackCollection to vector
parent 83904e48
/*
Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
*/
......
/*
Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
*/
......
/*
Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
*/
#include "TrkAmbiguitySolver/TrkAmbiguityScore.h"
......@@ -22,47 +22,34 @@ Trk::TrkAmbiguityScore::~TrkAmbiguityScore(void)
//-----------------------------------------------------------------------
StatusCode
Trk::TrkAmbiguityScore::initialize()
{
ATH_MSG_INFO( "TrkAmbiguityScore::initialize(). " );
Trk::TrkAmbiguityScore::initialize(){
ATH_MSG_VERBOSE( "TrkAmbiguityScore::initialize(). " );
ATH_CHECK(m_scoreTool.retrieve( DisableTool{m_scoreTool.empty()} ));
ATH_CHECK(m_scoredTracksKey.initialize());
ATH_CHECK(m_originTracksKey.initialize());
return StatusCode::SUCCESS;
}
//-------------------------------------------------------------------------
StatusCode
Trk::TrkAmbiguityScore::execute(const EventContext& ctx) const
{
Trk::TrkAmbiguityScore::execute(const EventContext& ctx) const{
std::vector<SG::ReadHandle<TrackCollection>> handles = m_originTracksKey.makeHandles(ctx);
size_t totalsize = 0;
for (SG::ReadHandle<TrackCollection>& trackColHandle : handles) {
if (!trackColHandle.isValid())
msg(MSG::WARNING) << "Could not retrieve tracks from "<< trackColHandle.key() << endmsg;
totalsize += trackColHandle->size();
ATH_MSG_DEBUG(handles.size() << " handles are requested");
if (handles.size() > 1){
ATH_MSG_WARNING("More than one collection has been requested. Only the first collection is taken");
}
std::vector<const Track*> originTracks;
originTracks.reserve(totalsize);
for (SG::ReadHandle<TrackCollection>& trackColHandle : handles) {
for(const Track* trk: *trackColHandle ) {
if (std::find(originTracks.begin(), originTracks.end(),trk) == originTracks.end()) {
originTracks.push_back(trk);
}
}
auto & theTrackCollectionHandle = handles.at(0);
if (not theTrackCollectionHandle.isValid()){
ATH_MSG_FATAL( "Could not retrieve tracks from "<< theTrackCollectionHandle.key() );
return StatusCode::FAILURE;
}
const auto & theTrackCollection = *theTrackCollectionHandle;
std::unique_ptr<TracksScores> scoredTracks(new TracksScores);
if (m_scoreTool.isEnabled()){
m_scoreTool->process(&originTracks, scoredTracks.get());
}
else{
scoredTracks->reserve(originTracks.size());
for(const Track* trk: originTracks ){
m_scoreTool->process(theTrackCollection, scoredTracks.get());
} else {
scoredTracks->reserve(theTrackCollection.size());
for(const Track* trk: theTrackCollection ){
scoredTracks->push_back( std::pair<const Track*, float>(trk, 0));//TODO: logpT
}
}
......
/*
Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
*/
#include "TrkAmbiguitySolver/TrkAmbiguitySolver.h"
......@@ -58,8 +58,7 @@ Trk::TrkAmbiguitySolver::execute(const EventContext& ctx) const
//---------------------------------------------------------------------------
StatusCode
Trk::TrkAmbiguitySolver::finalize()
{
Trk::TrkAmbiguitySolver::finalize(){
if (m_ambiTool.isEnabled()) {
m_ambiTool->statistics();
}
......
......@@ -35,13 +35,14 @@ find_package( HepPDT )
atlas_add_library( TrkAmbiguityProcessorLib
src/DenseEnvironmentsAmbiguityProcessorTool.cxx
src/DenseEnvironmentsAmbiguityScoreProcessorTool.cxx
src/AmbiguityProcessorUtility.cxx
src/AmbiguityProcessorBase.cxx
PUBLIC_HEADERS TrkAmbiguityProcessor
PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaKernel AthenaBaseComps AtlasDetDescr GaudiKernel InDetPrepRawData InDetRecToolInterfaces TrkDetElementBase TrkEventPrimitives TrkParameters TrkRIO_OnTrack TrkTrack TrkTrackSummary TrkTruthData TrkFitterInterfaces TrkToolInterfaces TrkValInterfaces TrkExInterfaces TrkCaloClusterROI)
atlas_add_component( TrkAmbiguityProcessor
src/SimpleAmbiguityProcessorTool.cxx src/TrackScoringTool.cxx src/TrackSelectionProcessorTool.cxx
src/SimpleAmbiguityProcessorTool.cxx src/TrackScoringTool.cxx src/TrackSelectionProcessorTool.cxx src/AmbiguityProcessorUtility.cxx src/AmbiguityProcessorBase.cxx
src/components/*.cxx
INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${HEPPDT_INCLUDE_DIRS}
LINK_LIBRARIES ${CLHEP_LIBRARIES} ${HEPPDT_LIBRARIES} TrkAmbiguityProcessorLib )
......
/*
Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
*/
#include "AmbiguityProcessorBase.h"
#include "TrackScoringTool.h"
#include "AmbiguityProcessorUtility.h"
namespace Trk {
AmbiguityProcessorBase::AmbiguityProcessorBase(const std::string& t, const std::string& n, const IInterface* p ):
AthAlgTool(t,n,p),
m_etaBounds{0.8, 1.6, 2.5, 4.0},
m_stat(m_etaBounds),
m_scoringTool("Trk::TrackScoringTool/TrackScoringTool"){
}
//
bool
AmbiguityProcessorBase::shouldTryBremRecovery(const Trk::Track & track) const{
return m_tryBremFit and
not (track.info().trackProperties(Trk::TrackInfo::BremFit)) and
(track.trackParameters()->front()->pT() > m_pTminBrem) and
((not m_caloSeededBrem) or track.info().patternRecoInfo(Trk::TrackInfo::TrackInCaloROI));
}
bool
AmbiguityProcessorBase::shouldTryBremRecovery(const Trk::Track & track, const TrackParameters * pPar) const{
return m_tryBremFit and
(pPar->pT() > m_pTminBrem) and
((not m_caloSeededBrem) or track.info().patternRecoInfo(Trk::TrackInfo::TrackInCaloROI));
}
//
Track *
AmbiguityProcessorBase::refitTrack( const Trk::Track* track,Trk::PRDtoTrackMap &prdToTrackMap, Counter &stat) const{
std::unique_ptr<Trk::Track> newTrack;
if (!m_suppressTrackFit){
if (m_refitPrds) {
// simple case, fit PRD directly
ATH_MSG_VERBOSE ("Refit track "<<track<<" from PRDs");
newTrack.reset(refitPrds (track,prdToTrackMap, stat));
}else {
// ok, we fit ROTs
ATH_MSG_VERBOSE ("Refit track "<<track<<" from ROTs");
newTrack.reset(refitRots (track,stat));
}
} else {
newTrack = AmbiguityProcessor::createNewFitQualityTrack(*track);
}
if (newTrack) {
ATH_MSG_DEBUG ("New track "<<newTrack.get()<<" successfully fitted from "<<track);
} else {
ATH_MSG_DEBUG ("Fit failed !");
}
return newTrack.release();
}
//
void
AmbiguityProcessorBase::addTrack(Trk::Track* in_track,const bool fitted,
TrackScoreMap &trackScoreTrackMap,
Trk::PRDtoTrackMap &prdToTrackMap,
std::vector<std::unique_ptr<const Trk::Track> >& trackDustbin,
Counter &stat) const {
std::unique_ptr<Trk::Track> atrack(in_track);
// compute score
TrackScore score;
bool suppressHoleSearch = fitted ? m_suppressHoleSearch : true;
if (m_trackSummaryTool.isEnabled()) {
m_trackSummaryTool->computeAndReplaceTrackSummary(*atrack,&prdToTrackMap,suppressHoleSearch);
}
score = m_scoringTool->score( *atrack, suppressHoleSearch );
// do we accept the track ?
if (score!=0){
ATH_MSG_DEBUG ("Track ("<< atrack.get() <<") has score "<<score);
// statistic
stat.incrementCounterByRegion(CounterIndex::kNscoreOk,atrack.get());
// add track to map, map is sorted small to big !
trackScoreTrackMap.emplace(-score, TrackPtr(atrack.release(), fitted));
return;
}
// do we try to recover the track ?
if (fitted and shouldTryBremRecovery(*atrack)){
ATH_MSG_DEBUG ("Track score is zero, try to recover it via brem fit");
// run track fit using electron hypothesis
auto bremTrack(doBremRefit(*atrack));
if (!bremTrack){
ATH_MSG_DEBUG ("Brem refit failed, drop track");
// statistic
stat.incrementCounterByRegion(CounterIndex::kNscoreZeroBremRefitFailed,atrack.get());
stat.incrementCounterByRegion(CounterIndex::kNfailedFits,atrack.get());
// clean up
trackDustbin.push_back(std::move(atrack));
} else {
// statistic
stat.incrementCounterByRegion(CounterIndex::kNgoodFits,bremTrack.get());
// rerun score
if (m_trackSummaryTool.isEnabled()) {
m_trackSummaryTool->computeAndReplaceTrackSummary(*bremTrack, &prdToTrackMap,suppressHoleSearch);
}
score = m_scoringTool->score( *bremTrack, suppressHoleSearch );
//put original track in the bin, ready to preserve a new Brem track
trackDustbin.push_back(std::move(atrack) );
// do we accept the track ?
if (score!=0){
ATH_MSG_DEBUG ("Brem refit successful, recovered track ("<< bremTrack.get() <<") has score "<<score);
// statistics
stat.incrementCounterByRegion(CounterIndex::kNscoreZeroBremRefit,bremTrack.get());
// add track to map, map is sorted small to big !
trackScoreTrackMap.emplace(-score, TrackPtr(bremTrack.release(), fitted) );
return;
} else {
ATH_MSG_DEBUG ("Brem refit gave still track score zero, reject it");
// statistic
stat.incrementCounterByRegion(CounterIndex::kNscoreZeroBremRefitScoreZero,bremTrack.get());
}
}
} else {
ATH_MSG_DEBUG ("Track score is zero, reject it");
// statistic
stat.incrementCounterByRegion(CounterIndex::kNscoreZero,atrack.get());
trackDustbin.push_back(std::move(atrack));
}
}
const TrackParameters *
AmbiguityProcessorBase::getTrackParameters(const Trk::Track* track) const{
const TrackParameters* par = track->perigeeParameters();
if (not par) {
ATH_MSG_DEBUG ("Track ("<<track<<") has no perigee! Try any other ?");
par = track->trackParameters()->front();
}
if (not par) ATH_MSG_DEBUG ("Track ("<<track<<") has no Track Parameters ! No refit !");
return par;
}
//==================================================================================================
Trk::Track*
AmbiguityProcessorBase::refitRots(const Trk::Track* track,Counter &stat) const{
ATH_MSG_VERBOSE ("Refit track "<<track);
// refit using first parameter, do outliers
std::unique_ptr<Trk::Track> newTrack{};
if (m_tryBremFit and track->info().trackProperties(Trk::TrackInfo::BremFit)){
stat.incrementCounterByRegion(CounterIndex::kNbremFits,track);
ATH_MSG_VERBOSE ("Brem track, refit with electron brem fit");
newTrack = doBremRefit(*track);
} else {
stat.incrementCounterByRegion(CounterIndex::kNfits,track);
ATH_MSG_VERBOSE ("Normal track, refit");
newTrack = fit(*track, true, m_particleHypothesis);
if ( (not newTrack) and shouldTryBremRecovery(*track)){
stat.incrementCounterByRegion(CounterIndex::kNrecoveryBremFits,track);
ATH_MSG_VERBOSE ("Normal fit failed, try brem recovery");
newTrack = doBremRefit(*track);
}
}
if(newTrack){
stat.incrementCounterByRegion(CounterIndex::kNgoodFits,newTrack.get());
//keeping the track of previously accumulated TrackInfo
const Trk::TrackInfo& originalInfo = track->info();
newTrack->info().addPatternReco(originalInfo);
} else {
stat.incrementCounterByRegion(CounterIndex::kNfailedFits,track);
}
return newTrack.release();
}
}
\ No newline at end of file
/*
Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
*/
#ifndef AmbiguityProcessorBase_h
#define AmbiguityProcessorBase_h
#include "AthenaBaseComps/AthAlgTool.h"
#include "TrkToolInterfaces/ITrackAmbiguityProcessorTool.h"
#include "TrkToolInterfaces/IExtendedTrackSummaryTool.h"
#include "AmbiCounter.icc"
#include "GaudiKernel/ToolHandle.h"
#include "TrackPtr.h"
#include "TrkEventPrimitives/TrackScore.h"
#include <vector>
#include <map> //multimap
#include <memory> //unique_ptr
#include <mutex> //mutex
namespace Trk {
//fwd declare
class ITrackScoringTool;
class Track;
class PRDtoTrackMap;
//base class for SimpleAmbiguityProcessorTool and DenseEnvironmentsAmbiguityProcessorTool
class AmbiguityProcessorBase : public AthAlgTool, virtual public ITrackAmbiguityProcessorTool {
public:
enum class CounterIndex {
kNcandidates,
kNcandScoreZero,
kNcandDouble,
kNscoreOk,
kNscoreZeroBremRefit,
kNscoreZeroBremRefitFailed,
kNscoreZeroBremRefitScoreZero,
kNscoreZero,
kNaccepted,
kNsubTrack,
kNnoSubTrack,
kNacceptedBrem,
kNbremFits,
kNfits,
kNrecoveryBremFits,
kNgoodFits,
kNfailedFits,
kNCounter
};
using Counter = AmbiCounter<CounterIndex>;
using TrackScoreMap = std::multimap< TrackScore, TrackPtr > ;
// default methods
AmbiguityProcessorBase(const std::string&,const std::string&,const IInterface*);
virtual ~AmbiguityProcessorBase () = default;
protected:
// methods
// should try a Brem refit? based on track properties
bool
shouldTryBremRecovery(const Trk::Track & track) const;
// should try a Brem refit? based on track properties and previously obtained track parameters
bool
shouldTryBremRecovery(const Trk::Track & track, const TrackParameters * pPar) const;
// do a brem refit; implemented in the derived classes
virtual std::unique_ptr<Trk::Track>
doBremRefit(const Trk::Track & track) const = 0;
/** refit track */
Track *
refitTrack( const Trk::Track* track,Trk::PRDtoTrackMap &prdToTrackMap, Counter &stat) const;
//refit PRD
virtual Trk::Track*
refitPrds( const Trk::Track* track, Trk::PRDtoTrackMap &prdToTrackMap,Counter &stat) const = 0;
//refit ROTs
virtual Trk::Track*
refitRots( const Trk::Track* track, Counter &stat) const;
//generic normal fit
virtual std::unique_ptr<Trk::Track>
fit(const Track &track, bool flag, Trk::ParticleHypothesis hypo) const = 0;
void
addTrack(Trk::Track* in_track, const bool fitted,
TrackScoreMap &trackScoreTrackMap,
Trk::PRDtoTrackMap &prdToTrackMap,
std::vector<std::unique_ptr<const Trk::Track> >& trackDustbin,
Counter &stat) const;
const TrackParameters *
getTrackParameters(const Trk::Track* track) const;
//variables accessible to derived classes
std::vector<float> m_etaBounds; //!< eta intervals for internal monitoring
mutable std::mutex m_statMutex;
mutable Counter m_stat ATLAS_THREAD_SAFE;
/**Scoring tool
This tool is used to 'score' the tracks, i.e. to quantify what a good track is.
@todo The actual tool that is used should be configured through job options*/
ToolHandle<ITrackScoringTool> m_scoringTool;
ToolHandle<Trk::IExtendedTrackSummaryTool> m_trackSummaryTool{this, "TrackSummaryTool", "InDetTrackSummaryToolNoHoleSearch"};
/** brem recovery mode with brem fit ? */
bool m_tryBremFit{};
bool m_caloSeededBrem{};
float m_pTminBrem{1000.};
bool m_suppressHoleSearch{};
// for track refit
bool m_suppressTrackFit{};
bool m_refitPrds{};
/** by default tracks at input get refitted */
bool m_forceRefit{true};
/** read in as an integer and convert to particle hypothesis */
/** reference: /TrkEventPrimitives/ParticleHypothesis.h **/
int m_matEffects{3};//pion
Trk::ParticleHypothesis m_particleHypothesis{undefined};
};
}//namespace
#endif
/*
Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
*/
#include "AmbiguityProcessorUtility.h"
#include "AthContainers/DataVector.h"
#include "TrkTrack/TrackStateOnSurface.h"
#include "TrkEventPrimitives/FitQuality.h"
#include "TrkTrack/TrackInfo.h"
#include "TrkTrack/Track.h"
namespace AmbiguityProcessor{
TrackFilterCategory
categoriseTrack(const Trk::Track & track, const Trk::TrackScore & score, const bool dropDuplicates, const AssociationTool & associate, AssociationMap & map, DuplicationCheckSet & set){
if (score == 0) return TrackFilterCategory::ScoreIsZero;
if (dropDuplicates){
if(const auto & [p, uniqueTrack] = set.insert(associate->getPrdsOnTrack( map, track)); not uniqueTrack) return TrackFilterCategory::TrackIsDuplicate;
}
return TrackFilterCategory::TrackAccepted;
}
//
float
calculateFitQuality(const Trk::Track & track){
float result{0.0};
if (const auto quality=track.fitQuality(); quality and quality->numberDoF()>0 ){
result = quality->chiSquared()/quality->numberDoF();
}
return result;
}
//
std::unique_ptr<Trk::Track>
createNewFitQualityTrack(const Trk::Track & track){
double reXi2 = 0.;
int nDF = 0;
const DataVector<const Trk::TrackStateOnSurface>* tsos = track.trackStateOnSurfaces();
DataVector<const Trk::TrackStateOnSurface>* vecTsos = new DataVector<const Trk::TrackStateOnSurface>();
// loop over TSOS, copy TSOS and push into vector
DataVector<const Trk::TrackStateOnSurface>::const_iterator iTsos = tsos->begin();
DataVector<const Trk::TrackStateOnSurface>::const_iterator iTsosEnd = tsos->end();
for ( ; iTsos != iTsosEnd ; ++iTsos) {
const Trk::TrackStateOnSurface* newTsos = new Trk::TrackStateOnSurface(**iTsos);
vecTsos->push_back(newTsos);
if((*iTsos)->type(Trk::TrackStateOnSurface::Measurement)){ //Get the chi2 and number of hits
if ((*iTsos)->fitQualityOnSurface()) {
reXi2 += (*iTsos)->fitQualityOnSurface()->chiSquared();
nDF += (*iTsos)->fitQualityOnSurface()->numberDoF();
}
}
}
Trk::FitQuality* fq = new Trk::FitQuality(reXi2,nDF-5);
Trk::TrackInfo info;
info.addPatternRecoAndProperties(track.info());
Trk::TrackInfo newInfo;
newInfo.setPatternRecognitionInfo(Trk::TrackInfo::SimpleAmbiguityProcessorTool);
info.addPatternReco(newInfo);
return std::make_unique<Trk::Track>(info, vecTsos, fq);
}
}
/*
Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
*/
#ifndef AmbiguityProcessorUtility_h
#define AmbiguityProcessorUtility_h
#include "GaudiKernel/ToolHandle.h"
#include "TrkToolInterfaces/IPRDtoTrackMapTool.h"
#include "TrkEventUtils/PRDtoTrackMap.h"
#include "TrkEventPrimitives/TrackScore.h"
#include <vector>
#include <set>
#include <array>
#include <string>
#include <memory> //unique_ptr
namespace Trk{
class Track;
class PrepRawData;
}
namespace AmbiguityProcessor{
enum TrackFilterCategory{ ScoreIsZero, TrackIsDuplicate, TrackAccepted, nCategories};
using AssociationTool = ToolHandle<Trk::IPRDtoTrackMapTool>;
using AssociationMap = Trk::PRDtoTrackMap;
using DuplicationCheckSet = std::set<std::vector<const Trk::PrepRawData*>> ;
//
//categorise the track as zero-score, duplicate or 'accepted'
TrackFilterCategory
categoriseTrack(const Trk::Track & track, const Trk::TrackScore & score, const bool dropDuplicates, const AssociationTool &, AssociationMap &, DuplicationCheckSet &);
//
//give appropriate text for each category
const static std::array<std::string , nCategories> debugMessage {"Score is zero, reject.", "Track is duplicate, reject.", "Track is accepted."};
//calculate a simple chi^2/ndof
float calculateFitQuality(const Trk::Track & track);
//create a track from a new FitQuality object looping over track-state-on-surfaces to calculate
std::unique_ptr<Trk::Track> createNewFitQualityTrack(const Trk::Track & track);
}//namespace
#endif
......@@ -5,11 +5,7 @@
#ifndef DenseEnvironmentsAmbiguityProcessorTool_H
#define DenseEnvironmentsAmbiguityProcessorTool_H
#include "AthenaBaseComps/AthAlgTool.h"
#include "GaudiKernel/ToolHandle.h"
#include "TrkToolInterfaces/ITrackAmbiguityProcessorTool.h"
#include "TrkEventPrimitives/TrackScore.h"
#include "AmbiguityProcessorBase.h"
#include "TrkFitterInterfaces/ITrackFitter.h"
#include "TrkToolInterfaces/IAmbiTrackSelectionTool.h"
#include "InDetPrepRawData/PixelGangedClusterAmbiguities.h"
......@@ -18,7 +14,6 @@
#include "TrkToolInterfaces/IPRDtoTrackMapTool.h"
#include "TrkEventUtils/PRDtoTrackMap.h"
#include "TrkToolInterfaces/IExtendedTrackSummaryTool.h"
//need to include the following, since its a typedef and can't be forward declared.
#include "TrkTrack/TrackCollection.h"
......@@ -30,7 +25,7 @@
#include <map>
#include <vector>
#include "TrackPtr.h"
class AtlasDetectorID;
......@@ -43,34 +38,11 @@ namespace InDet{
}
namespace Trk {
class ITrackScoringTool;
class ITruthToTrack;
class IExtrapolator;
//
class DenseEnvironmentsAmbiguityProcessorTool : public AthAlgTool,
virtual public ITrackAmbiguityProcessorTool{
class DenseEnvironmentsAmbiguityProcessorTool : public AmbiguityProcessorBase{
public:
enum class EStatType {
kNtracks,
kNinvalid,
kNcandidates,
kNscoreOk,
kNscoreZeroBremRefit,
kNscoreZeroBremRefitFailed,
kNscoreZeroBremRefitScoreZero,
kNscoreZero,
kNaccepted,
kNsubTrack,
kNnoSubTrack,