From 81ed6d340c665a7a46d9cd77658f553852ff5099 Mon Sep 17 00:00:00 2001 From: Chengdong Fu <fucd@ihep.ac.cn> Date: Wed, 19 Aug 2020 15:47:19 +0800 Subject: [PATCH] add TrackSubset --- .../SiliconTracking/src/TrackSubsetAlg.cpp | 338 ++++++++++++++++++ .../SiliconTracking/src/TrackSubsetAlg.h | 117 ++++++ 2 files changed, 455 insertions(+) create mode 100644 Reconstruction/SiliconTracking/src/TrackSubsetAlg.cpp create mode 100644 Reconstruction/SiliconTracking/src/TrackSubsetAlg.h diff --git a/Reconstruction/SiliconTracking/src/TrackSubsetAlg.cpp b/Reconstruction/SiliconTracking/src/TrackSubsetAlg.cpp new file mode 100644 index 00000000..8961484d --- /dev/null +++ b/Reconstruction/SiliconTracking/src/TrackSubsetAlg.cpp @@ -0,0 +1,338 @@ +#include "TrackSubsetAlg.h" + +#include "GearSvc/IGearSvc.h" +#include "TrackSystemSvc/ITrackSystemSvc.h" +#include "DataHelper/Navigation.h" + +#include <UTIL/ILDConf.h> + +#include <gear/BField.h> + +#include "KiTrack/SubsetSimple.h" +#include "KiTrack/SubsetHopfieldNN.h" +#include "Tools/Fitter.h" +#include "Tools/KiTrackMarlinTools.h" + +#include "TrackSystemSvc/MarlinTrkUtils.h" + +using namespace KiTrack; + +DECLARE_COMPONENT(TrackSubsetAlg) + +TrackSubsetAlg::TrackSubsetAlg(const std::string& name, ISvcLocator* svcLoc) + : GaudiAlgorithm(name, svcLoc){ + + // modify processor description + //_description = "TrackSubsetAlg takes tracks from multiple sources and outputs them (or modified versions, or a subset of them) as one track collection." ; + + //std::vector< std::string > trackInputColNamesDefault; + //trackInputColNamesDefault.push_back( "ForwardTracks" ); + //trackInputColNamesDefault.push_back( "SiTracks" ); + + declareProperty("TrackSubsetCollection", _outColHdl, "Handle of the SiTrack output collection"); +} + +StatusCode TrackSubsetAlg::initialize() { + + debug() << " init called " << endmsg; + + _nRun = 0 ; + _nEvt = 0 ; + + for(unsigned i=0; i<_trackInputColNames.size(); i++){ + _inTrackColHdls.push_back(new DataHandle<edm4hep::TrackCollection> (_trackInputColNames[i], Gaudi::DataHandle::Reader, this)); + } + + for(unsigned i=0; i<_trackerHitInputColNames.size(); i++){ + _inTrackerHitColHdls.push_back(new DataHandle<edm4hep::TrackerHitCollection> (_trackerHitInputColNames[i], Gaudi::DataHandle::Reader, this)); + } + /**********************************************************************************************/ + /* Initialise the MarlinTrkSystem, needed by the tracks for fitting */ + /**********************************************************************************************/ + auto _gear = service<IGearSvc>("GearSvc"); + if ( !_gear ) { + error() << "Failed to find GearSvc ..." << endmsg; + return StatusCode::FAILURE; + } + gear::GearMgr* gearMgr = _gear->getGearMgr(); + _bField = gearMgr->getBField().at( gear::Vector3D( 0.,0.,0.) ).z() ; + + // set upt the geometry + auto _trackSystemSvc = service<ITrackSystemSvc>("TrackSystemSvc"); + if ( !_trackSystemSvc ) { + error() << "Failed to find TrackSystemSvc ..." << endmsg; + return StatusCode::FAILURE; + } + _trkSystem = _trackSystemSvc->getTrackSystem(); + + if( _trkSystem == 0 ){ + error() << "Cannot initialize MarlinTrkSystem of Type: KalTest" <<endmsg; + return StatusCode::FAILURE; + } + + // set the options + _trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::useQMS, _MSOn ) ; //multiple scattering + _trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::usedEdx, _ElossOn) ; //energy loss + _trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::useSmoothing, _SmoothOn) ; //smoothing + + // initialise the tracking system + //_trkSystem->init() ; + + return GaudiAlgorithm::initialize(); +} + +StatusCode TrackSubsetAlg::finalize(){ + for(unsigned i=0; i<_inTrackColHdls.size(); i++){ + delete _inTrackColHdls[i]; + } + _inTrackColHdls.clear(); + + for(unsigned i=0; i<_inTrackerHitColHdls.size(); i++){ + delete _inTrackerHitColHdls[i]; + } + _inTrackerHitColHdls.clear(); + + return GaudiAlgorithm::finalize(); +} + +StatusCode TrackSubsetAlg::execute(){ + std::vector<edm4hep::Track> tracks; + + /**********************************************************************************************/ + /* Read in the collections */ + /**********************************************************************************************/ + debug() << "Try to load " << _trackInputColNames.size() << " input track collections" << endmsg; + + unsigned nTrackLoaded = 0; + + for( unsigned i=0; i < _inTrackColHdls.size(); i++ ){ + const edm4hep::TrackCollection* trackCol = nullptr; + try { + trackCol = _inTrackColHdls[i]->get(); + } + catch ( GaudiException &e ) { + debug() << "Collection " << _inTrackColHdls[i]->fullKey() << " is unavailable in event " << _nEvt << endmsg; + continue; + } + + if(trackCol){ + int nTracks = trackCol->size(); + debug() << "Load track input collection " << _trackInputColNames[i] << " with " << nTracks << " tracks" << endmsg; + + for(auto track : *trackCol){ + tracks.push_back( track ); + nTrackLoaded++; + } + } + else error() << "track input collection " << _trackInputColNames[i] << " could not be found, but not throw exception!!!" << endmsg; + } + + debug() << "Loaded all in all " << nTrackLoaded << " tracks, which will now get further processed" << endmsg; + if(tracks.size()==0) return StatusCode::SUCCESS; + + Navigation::Instance()->Initialize(); + for(unsigned i=0; i < _inTrackerHitColHdls.size(); i++){ + try { + auto trackCol = _inTrackerHitColHdls[i]->get(); + Navigation::Instance()->AddTrackerHitCollection(trackCol); + } + catch ( GaudiException &e ) { + debug() << "Collection " << _inTrackerHitColHdls[i]->fullKey() << " is unavailable in event " << _nEvt << endmsg; + continue; + } + } + /**********************************************************************************************/ + /* Make sure that all tracks are compatible: find the best subset */ + /**********************************************************************************************/ + debug() << "Find the best subset of tracks using the Hopfield Neural Network" << endmsg; + + TrackQI trackQI( _trkSystem ); + + debug() << "The tracks and their qualities (and their hits ): " << endmsg; + + std::vector<edm4hep::Track*> tracks_p; + for( unsigned i=0; i < tracks.size(); i++ ){ + edm4hep::Track* track = &tracks[i]; + tracks_p.push_back(track); + double qi = trackQI( track ); + debug() << "Track " << track->id() << " address " << track << "\t" << qi << "( "; + std::vector<edm4hep::ConstTrackerHit> hits; + std::copy(track->trackerHits_begin(), track->trackerHits_end(), std::back_inserter(hits)); + + std::sort( hits.begin(), hits.end(), KiTrackMarlin::compare_TrackerHit_z ); + + for( unsigned j=0; j<hits.size(); j++ ){ + debug() << hits[j].id() << " "; + double x = hits[j].getPosition()[0]; + double y = hits[j].getPosition()[1]; + double z = hits[j].getPosition()[2]; + debug() << "[" << x << "," << y << "," << z << "]"; + } + debug() << ")" << endmsg; + } + + TrackCompatibility comp; + + SubsetHopfieldNN<edm4hep::Track*> subset; + //SubsetSimple<edm4hep::Track* > subset; + subset.add( tracks_p ); + subset.setOmega( _omega ); + subset.calculateBestSet( comp, trackQI ); + + std::vector<edm4hep::Track*> accepted = subset.getAccepted(); + std::vector<edm4hep::Track*> rejected = subset.getRejected(); + + debug() << "\tThe accepted tracks:" << endmsg; + for( unsigned i=0; i < accepted.size(); i++ ){ + debug() << accepted[i]->id() << " address " << accepted[i] << endmsg; + } + + debug() << "\tThe rejected tracks:" << endmsg; + for( unsigned i=0; i < rejected.size(); i++ ){ + debug() << rejected[i]->id() << " address " << rejected[i] << endmsg; + } + + /**********************************************************************************************/ + /* Save the tracks to a collection (make new TrackImpls from them) */ + /**********************************************************************************************/ + debug() << "Fitting and saving of the tracks" << endmsg; + + auto trkCol = _outColHdl.createAndPut(); + + for( unsigned i=0; i < accepted.size(); i++ ){ + edm4hep::Track trackImpl; + + edm4hep::Track* track = accepted[i]; + + std::vector<edm4hep::ConstTrackerHit> trackerHitsObj; + std::vector<edm4hep::TrackerHit*> trackerHits; + std::copy(track->trackerHits_begin(), track->trackerHits_end(), std::back_inserter(trackerHitsObj)); + + for(unsigned i=0; i<trackerHitsObj.size(); i++){ + //debug() << trackerHitsObj[i].id() << endmsg; + trackerHits.push_back(Navigation::Instance()->GetTrackerHit(trackerHitsObj[i].getObjectID())); + } + // setup initial dummy covariance matrix + std::array<float,15> covMatrix; + for (unsigned icov = 0; icov<covMatrix.size(); ++icov) { + covMatrix[icov] = 0; + } + + covMatrix[0] = ( _initialTrackError_d0 ); //sigma_d0^2 + covMatrix[2] = ( _initialTrackError_phi0 ); //sigma_phi0^2 + covMatrix[5] = ( _initialTrackError_omega ); //sigma_omega^2 + covMatrix[9] = ( _initialTrackError_z0 ); //sigma_z0^2 + covMatrix[14] = ( _initialTrackError_tanL ); //sigma_tanl^2 + + std::vector< std::pair<float, edm4hep::TrackerHit*> > r2_values; + r2_values.reserve(trackerHits.size()); + + for (std::vector<edm4hep::TrackerHit*>::iterator it=trackerHits.begin(); it!=trackerHits.end(); ++it) { + edm4hep::TrackerHit* h = *it; + float r2 = h->getPosition()[0]*h->getPosition()[0]+h->getPosition()[1]*h->getPosition()[1]; + r2_values.push_back(std::make_pair(r2, *it)); + } + + sort(r2_values.begin(),r2_values.end()); + + trackerHits.clear(); + trackerHits.reserve(r2_values.size()); + + for (std::vector< std::pair<float, edm4hep::TrackerHit*> >::iterator it=r2_values.begin(); it!=r2_values.end(); ++it) { + trackerHits.push_back(it->second); + } + + bool fit_backwards = MarlinTrk::IMarlinTrack::backward; + + MarlinTrk::IMarlinTrack* marlinTrk = _trkSystem->createTrack(); + + int error = 0; + + try { + + error = MarlinTrk::createFinalisedLCIOTrack(marlinTrk, trackerHits, &trackImpl, fit_backwards, covMatrix, _bField, _maxChi2PerHit); + + } catch (...) { + + // delete Track; + // delete marlinTrk; + + throw ; + + } + + // Add hit numbers + + std::vector<std::pair<edm4hep::TrackerHit* , double> > hits_in_fit ; + std::vector<std::pair<edm4hep::TrackerHit* , double> > outliers ; + std::vector<edm4hep::TrackerHit*> all_hits; + all_hits.reserve(300); + + marlinTrk->getHitsInFit(hits_in_fit); + + for ( unsigned ihit = 0; ihit < hits_in_fit.size(); ++ihit) { + all_hits.push_back(hits_in_fit[ihit].first); + } + + UTIL::BitField64 cellID_encoder( lcio::ILDCellID0::encoder_string ) ; + + MarlinTrk::addHitNumbersToTrack(&trackImpl, all_hits, true, cellID_encoder); + + marlinTrk->getOutliers(outliers); + + for ( unsigned ihit = 0; ihit < outliers.size(); ++ihit) { + all_hits.push_back(outliers[ihit].first); + } + + MarlinTrk::addHitNumbersToTrack(&trackImpl, all_hits, false, cellID_encoder); + + delete marlinTrk; + + if( error != MarlinTrk::IMarlinTrack::success ) { + //delete trackImpl; + debug() << "TrackSubsetAlg:: Track fit failed with error code " << error << " track dropped. Number of hits = "<< trackerHits.size() << endmsg; + continue ; + } + + if( trackImpl.getNdf() < 0) { + //delete trackImpl; + debug() << "TrackSubsetAlg:: Track fit returns " << trackImpl.getNdf() << " degress of freedom track dropped. Number of hits = "<< trackerHits.size() << endmsg; + continue ; + } + + trkCol->push_back(trackImpl); + +// try{ +// +// Fitter fitter( trackImpl , _trkSystem ); +// +// TrackStateImpl* trkStateIP = new TrackStateImpl( fitter.getTrackState( lcio::TrackState::AtIP ) ) ; +// trackImpl->setChi2( fitter.getChi2( lcio::TrackState::AtIP ) ); +// trackImpl->setNdf( fitter.getNdf( lcio::TrackState::AtIP ) ); +// trkStateIP->setLocation( TrackState::AtIP ); +// trackImpl->addTrackState( trkStateIP ); +// +// trackVec->addElement(trackImpl); +// +// } +// catch( FitterException e ){ +// +// delete trackImpl; +// +// streamlog_out( ERROR ) << "TrackImpl nr " << i << " rejected, because fit failed: " << e.what() << "\n"; +// continue; +// +// } + } + + debug() << "Saving " << trkCol->size() << " tracks" << endmsg; + + _nEvt ++ ; + return StatusCode::SUCCESS; +} + + + + + + diff --git a/Reconstruction/SiliconTracking/src/TrackSubsetAlg.h b/Reconstruction/SiliconTracking/src/TrackSubsetAlg.h new file mode 100644 index 00000000..5676d977 --- /dev/null +++ b/Reconstruction/SiliconTracking/src/TrackSubsetAlg.h @@ -0,0 +1,117 @@ +#ifndef TrackSubsetAlg_h +#define TrackSubsetAlg_h 1 + +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" + +#include "edm4hep/TrackCollection.h" +//#include "edm4hep/Track.h" +#include "TrackSystemSvc/IMarlinTrkSystem.h" + +#include "Math/ProbFunc.h" + +/** Processor that takes tracks from multiple sources and outputs them (or modified versions, or a subset of them) + * as one track collection. + * + * <h4>Input - Prerequisites</h4> + * Track collections + * + * <h4>Output</h4> + * A single track collection + * + * @param TrackInputCollections A vector of the input track collections <br> + * (default value ForwardTracks SiTracks ) + * + * @param TrackOutputCollection Name of the output track collection <br> + * (default value SubsetTracks ) + * + * @param MultipleScatteringOn Whether to take multiple scattering into account when fitting the tracks<br> + * (default value true ) + * + * @param EnergyLossOn Whether to take energyloss into account when fitting the tracks<br> + * (default value true ) + * + * @param SmoothOn Whether to smooth all measurement sites in fit<br> + * (default value false ) + * + * @param Omega The parameter omega for the HNN. Controls the influence of the quality indicator. Between 0 and 1: + * 1 means high influence of quality indicator, 0 means no influence. + * + * @author Robin Glattauer, HEPHY + * + */ + +class TrackSubsetAlg : public GaudiAlgorithm { + public: + + TrackSubsetAlg(const std::string& name, ISvcLocator* svcLoc); + + virtual StatusCode initialize() ; + + virtual StatusCode execute() ; + + virtual StatusCode finalize() ; + + protected: + MarlinTrk::IMarlinTrkSystem* _trkSystem; + /* Input collection */ + std::vector<DataHandle<edm4hep::TrackCollection>* > _inTrackColHdls; + std::vector<DataHandle<edm4hep::TrackerHitCollection>* > _inTrackerHitColHdls; + /* Output collection */ + DataHandle<edm4hep::TrackCollection> _outColHdl{"SubsetTracks", Gaudi::DataHandle::Writer, this}; + + Gaudi::Property<std::vector<std::string> > _trackInputColNames{this, "TrackInputCollections", {"ForwardTracks", "SiTracks"}}; + Gaudi::Property<std::vector<std::string> > _trackerHitInputColNames{this, "RawTrackerHitCollections", + {"VXDTrackerHits", "SITTrackerHits", "FTDPixelTrackerHits", "FTDStripTrackerHits"}}; + Gaudi::Property<bool> _MSOn{this, "MultipleScatteringOn", true}; + Gaudi::Property<bool> _ElossOn{this, "EnergyLossOn", true}; + Gaudi::Property<bool> _SmoothOn{this, "SmoothOn", false}; + Gaudi::Property<float> _initialTrackError_d0{this, "InitialTrackErrorD0",1e6}; + Gaudi::Property<float> _initialTrackError_phi0{this, "InitialTrackErrorPhi0",1e2}; + Gaudi::Property<float> _initialTrackError_omega{this, "InitialTrackErrorOmega",1e-4}; + Gaudi::Property<float> _initialTrackError_z0{this, "InitialTrackErrorZ0",1e6}; + Gaudi::Property<float> _initialTrackError_tanL{this, "InitialTrackErrorTanL",1e2}; + Gaudi::Property<double> _maxChi2PerHit{this, "MaxChi2PerHit", 1e2}; + Gaudi::Property<double> _omega{this, "Omega", 0.75}; + + float _bField; + + int _nRun ; + int _nEvt ; +}; + +/** A functor to return whether two tracks are compatible: The criterion is if the share a TrackerHit or more */ +class TrackCompatibility{ + public: + inline bool operator()( edm4hep::Track* trackA, edm4hep::Track* trackB ){ + unsigned nHitsA = trackA->trackerHits_size(); + unsigned nHitsB = trackB->trackerHits_size(); + for( unsigned i=0; i < nHitsA; i++){ + for( unsigned j=0; j < nHitsB; j++){ + if ( trackA->getTrackerHits(i) == trackB->getTrackerHits(j) ) return false; // a hit is shared -> incompatible + } + } + + return true; + } +}; + + +/** A functor to return the quality of a track, which is currently the chi2 probability. */ +class TrackQI{ + public: + /** @param trkSystem a pointer to an IMarlinTrkSystem, needed for fitting of tracks */ + TrackQI( MarlinTrk::IMarlinTrkSystem* trkSystem ): _trkSystem(trkSystem){} + + inline double operator()( edm4hep::Track* track ){ + return ROOT::Math::chisquared_cdf_c( track->getChi2() , track->getNdf() ); + } + + protected: + + MarlinTrk::IMarlinTrkSystem* _trkSystem; +}; +#endif + + + -- GitLab