All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
TOFEstimators.cc
Go to the documentation of this file.
1 #include "TOFEstimators.h"
2 #include "TOFUtils.h"
3 
4 #include <chrono>
5 
6 #include "EVENT/LCCollection.h"
7 #include "UTIL/PIDHandler.h"
8 
9 #include "marlin/Global.h"
10 #include "marlin/ProcessorEventSeeder.h"
11 #include "marlin/VerbosityLevels.h"
12 #include "marlinutil/GeometryUtil.h"
13 #include "MarlinTrk/Factory.h"
14 #include "EVENT/SimTrackerHit.h"
15 #include "UTIL/LCRelationNavigator.h"
16 #include "CLHEP/Random/Randomize.h"
17 
18 using namespace TOFUtils;
19 using std::vector;
20 using std::string;
21 using EVENT::LCCollection;
22 using EVENT::ReconstructedParticle;
23 using EVENT::TrackerHit;
24 using EVENT::Track;
25 using EVENT::SimTrackerHit;
26 using EVENT::Cluster;
27 using EVENT::CalorimeterHit;
28 using EVENT::TrackState;
29 using EVENT::LCObject;
30 using UTIL::LCRelationNavigator;
31 using CLHEP::RandGauss;
33 
35 
36 
37 TOFEstimators::TOFEstimators() : marlin::Processor("TOFEstimators") {
38  _description = "TOFEstimators processor computes momentum harmonic mean, track length \
39  and time-of-flight of the chosen ReconstructedParticle to the \
40  specified end point (SET hit or Ecal surface). To be used for a further particle ID";
41 
42  registerInputCollection(LCIO::RECONSTRUCTEDPARTICLE,
43  "ReconstructedParticleCollection",
44  "Name of the ReconstructedParticle collection",
46  std::string("PandoraPFOs") );
47 
48  registerProcessorParameter("ExtrapolateToEcal",
49  "If true, track is extrapolated to the Ecal surface for track length calculation, \
50  time of flight estimated using Ecal hits. If false, track length calculated to the last tracker hit.\
51  Time of flight estimated using SET hit if exists.",
53  bool(true));
54 
55  registerProcessorParameter("TofMethod",
56  "name of the algorithm which estimates time of flight\
57  to the Ecal surface based on Ecal hits time information.\
58  Available options are: closest, frankAvg, frankFit.\
59  In case of _extrapolateToEcal==false is ignored",
60  _tofMethod,
61  std::string("closest") );
62 
63  registerProcessorParameter("TimeResolution",
64  "Time resolution of individual SET strips or Ecal hits in ps",
66  double(0.));
67 
68  registerProcessorParameter("MaxEcalLayer",
69  "Time of flight is calculated using Ecal hits only up to MaxLayer",
71  int(10) );
72 
73 }
74 
75 
77 
78  if(_tofMethod != "closest" && _tofMethod != "frankAvg" && _tofMethod != "frankFit"){
79  throw EVENT::Exception( "Invalid steering parameter for TofMethod is passed: " + _tofMethod + "\n Available options are: closest, frankAvg, frankFit" );
80  }
81 
82  marlin::Global::EVENTSEEDER->registerProcessor(this);
83 
84  _outputParNames = {"momentumHM", "trackLength", "timeOfFlight"};
85  _bField = MarlinUtil::getBzAtOrigin();
87  // internally we use time resolution in nanoseconds
89 
90  _trkSystem = MarlinTrk::Factory::createMarlinTrkSystem("DDKalTest", nullptr, "");
91  _trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::useQMS, true);
92  _trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::usedEdx, true);
93  _trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::useSmoothing, true);
94  _trkSystem->init();
95 }
96 
97 
98 void TOFEstimators::processEvent(EVENT::LCEvent * evt){
99  RandGauss::setTheSeed( marlin::Global::EVENTSEEDER->getSeed(this) );
100  ++_nEvent;
101  streamlog_out(DEBUG9)<<std::endl<<"==========Event========== "<<_nEvent<<std::endl;
102  auto startTime = std::chrono::steady_clock::now();
103 
104  LCCollection* pfos = evt->getCollection(_pfoCollectionName);
105  LCCollection* setRelations = evt->getCollection("SETSpacePointRelations");
106 
107  LCRelationNavigator navigatorSET = LCRelationNavigator( setRelations );
108 
109  PIDHandler pidHandler( pfos );
110  int algoID = pidHandler.addAlgorithm( name(), _outputParNames );
111 
112 
113  for (int i=0; i<pfos->getNumberOfElements(); ++i){
114  streamlog_out(DEBUG9)<<std::endl<<"Starting to analyze "<<i+1<<" PFO"<<std::endl;
115  ReconstructedParticle* pfo = static_cast <ReconstructedParticle*> ( pfos->getElementAt(i) );
116 
117  int nClusters = pfo->getClusters().size();
118  int nTracks = pfo->getTracks().size();
119 
120  if( nClusters != 1 || nTracks != 1){
121  // Analyze only simple pfos. Otherwise write dummy zeros
122  vector<float> results{0., 0., 0.};
123  pidHandler.setParticleID(pfo , 0, 0, 0., algoID, results);
124  continue;
125  }
126  Track* track = pfo->getTracks()[0];
127  Cluster* cluster = pfo->getClusters()[0];
128 
129  ///////////////////////////////////////////////////////////////
130  // This part calculates track length and momentum harmonic mean
131  ///////////////////////////////////////////////////////////////
132  vector<Track*> subTracks = getSubTracks(track);
133  vector<TrackStateImpl> trackStates = getTrackStatesPerHit(subTracks, _trkSystem, _extrapolateToEcal, _bField);
134 
135  double trackLength = 0.;
136  double harmonicMom = 0.;
137  int nTrackStates = trackStates.size();
138  for( int j=1; j < nTrackStates; ++j ){
139  //we check which track length formula to use
140  double nTurns = getHelixNRevolutions( trackStates[j-1], trackStates[j] );
141  double arcLength;
142  // we cannot calculate arc length for more than pi revolution using delta phi. Use formula with only z
143  if ( nTurns <= 0.5 ) arcLength = getHelixArcLength( trackStates[j-1], trackStates[j] );
144  else arcLength = getHelixLengthAlongZ( trackStates[j-1], trackStates[j] );
145 
146  Vector3D mom = getHelixMomAtTrackState( trackStates[j-1], _bField );
147  trackLength += arcLength;
148  harmonicMom += arcLength/mom.r2();
149  }
150  harmonicMom = std::sqrt(trackLength/harmonicMom);
151 
152  //////////////////////////////////////
153  // This part calculates Time of flight
154  //////////////////////////////////////
155  double timeOfFlight = 0.;
156  if( _extrapolateToEcal ){
157  if (_tofMethod == "closest"){
158  timeOfFlight = getTofClosest(cluster, track, _timeResolution);
159  }
160  else if (_tofMethod == "frankAvg"){
161  vector<CalorimeterHit*> frankHits = selectFrankEcalHits(cluster, track, _maxEcalLayer, _bField);
162  timeOfFlight = getTofFrankAvg(frankHits, track, _timeResolution);
163  }
164  else if (_tofMethod == "frankFit"){
165  vector<CalorimeterHit*> frankHits = selectFrankEcalHits(cluster, track, _maxEcalLayer, _bField);
166  timeOfFlight = getTofFrankFit(frankHits, track, _timeResolution);
167  }
168  }
169  else{
170  //define tof as an average time between two SET strips
171  //if no SET hits found, tof alreasy is 0, just skip
172  TrackerHit* hitSET = getSETHit(track, _tpcOuterR);
173  if ( hitSET != nullptr ){
174  const vector<LCObject*>& simHitsSET = navigatorSET.getRelatedToObjects( hitSET );
175  if ( simHitsSET.size() >= 2 ){
176  //It must be always 2, but just in case...
177  if (simHitsSET.size() > 2) streamlog_out(WARNING)<<"Found more than two SET strip hits! Writing TOF as an average of the first two elements in the array."<<std::endl;
178 
179  SimTrackerHit* simHitSETFront = static_cast <SimTrackerHit*>( simHitsSET[0] );
180  SimTrackerHit* simHitSETBack = static_cast <SimTrackerHit*>( simHitsSET[1] );
181  double timeFront = RandGauss::shoot(simHitSETFront->getTime(), _timeResolution);
182  double timeBack = RandGauss::shoot(simHitSETBack->getTime(), _timeResolution);
183  timeOfFlight = (timeFront + timeBack)/2.;
184  }
185  else if (simHitsSET.size() == 1){
186  streamlog_out(WARNING)<<"Found only one SET strip hit! Writing TOF from a single strip."<<std::endl;
187  SimTrackerHit* simHitSET = static_cast <SimTrackerHit*>(simHitsSET[0]);
188  timeOfFlight = RandGauss::shoot(simHitSET->getTime(), _timeResolution);
189  }
190  else{
191  // this happens very rarily (0.1%). When >1 simHits associated with a single strip none simHits are written by the DDSpacePointBuilder.
192  streamlog_out(WARNING)<<"Found NO simHits associated with the found SET hit! Writing TOF as 0."<<std::endl;
193  }
194  }
195  }
196  vector<float> results{float(harmonicMom), float(trackLength), float(timeOfFlight)};
197  pidHandler.setParticleID(pfo , 0, 0, 0., algoID, results);
198  streamlog_out(DEBUG9)<<"Final results for the "<<i+1<<" PFO"<<std::endl;
199  streamlog_out(DEBUG9)<<"momentum: "<< float(harmonicMom)<<" Gev"<<std::endl;
200  streamlog_out(DEBUG9)<<"track length: "<< float(trackLength)<<" mm"<<std::endl;
201  streamlog_out(DEBUG9)<<"time-of-flight: "<< float(timeOfFlight)<<" ns"<<std::endl;
202  streamlog_out(DEBUG9)<<std::endl<<std::endl;
203  }
204 
205  auto endTime = std::chrono::steady_clock::now();
206  std::chrono::duration<double> duration = endTime - startTime;
207  streamlog_out(DEBUG9)<<"Time spent (sec): "<<duration.count()<<std::endl;
208 }
double getHelixLengthAlongZ(const EVENT::TrackState &ts1, const EVENT::TrackState &ts2)
Get track length.
Definition: TOFUtils.cc:82
double getTofFrankAvg(std::vector< EVENT::CalorimeterHit * > selectedHits, EVENT::Track *track, double timeResolution)
Get the time-of-flight using average of the Frank ECal hits.
Definition: TOFUtils.cc:292
double getTofClosest(EVENT::Cluster *cluster, EVENT::Track *track, double timeResolution)
Get the time-of-flight using the closest ECal hit.
Definition: TOFUtils.cc:268
double getHelixNRevolutions(const EVENT::TrackState &ts1, const EVENT::TrackState &ts2)
Get number of helix revolutions.
Definition: TOFUtils.cc:90
MarlinTrk::IMarlinTrkSystem * _trkSystem
Kalman Filter System.
Definition: TOFEstimators.h:91
double _bField
Stores z component of the magnetic field at the origin in Tesla.
Definition: TOFEstimators.h:95
CLHEP::Hep3Vector Vector3D
void init()
Called at the begin of the job before anything is read.
TOFEstimators aTOFEstimators
std::string _pfoCollectionName
Stores ReconstructedParticleCollection steering parameter.
Definition: TOFEstimators.h:59
std::vector< std::string > _outputParNames
Stores names of the output parameters.
Definition: TOFEstimators.h:84
EVENT::TrackerHit * getSETHit(EVENT::Track *track, double tpcOuterR)
Returns SET hit.
Definition: TOFUtils.cc:112
double getTPCOuterR()
Returns TPC outer radius from the DD4hep detector geometry.
Definition: TOFUtils.cc:104
std::string _tofMethod
Stores TofMethod steering parameter.
Definition: TOFEstimators.h:67
double _tpcOuterR
Stores outer TPC radius in mm.
Definition: TOFEstimators.h:99
bool _extrapolateToEcal
Stores ExtrapolateToEcal steering parameter.
Definition: TOFEstimators.h:63
std::vector< IMPL::TrackStateImpl > getTrackStatesPerHit(std::vector< EVENT::Track * > tracks, MarlinTrk::IMarlinTrkSystem *trkSystem, bool extrapolateToEcal, double bField)
Get list of track states.
Definition: TOFUtils.cc:175
double _timeResolution
Stores TimeResolution steering parameter.
Definition: TOFEstimators.h:71
double getTofFrankFit(std::vector< EVENT::CalorimeterHit * > selectedHits, EVENT::Track *track, double timeResolution)
Get the time-of-flight using fit of the Frank ECal hits.
Definition: TOFUtils.cc:309
int _maxEcalLayer
Stores MaxEcalLayer steering parameter.
Definition: TOFEstimators.h:75
std::vector< EVENT::CalorimeterHit * > selectFrankEcalHits(EVENT::Cluster *cluster, EVENT::Track *track, int maxEcalLayer, double bField)
Get a subset of the cluster calorimeter hits.
Definition: TOFUtils.cc:122
double getHelixArcLength(const EVENT::TrackState &ts1, const EVENT::TrackState &ts2)
Get track length.
Definition: TOFUtils.cc:71
TOFEstimators()
Default constructor.
std::vector< EVENT::Track * > getSubTracks(EVENT::Track *track)
Get all subtracks of the Track.
Definition: TOFUtils.cc:149
void processEvent(EVENT::LCEvent *evt)
Called for every event - the working horse.
dd4hep::rec::Vector3D getHelixMomAtTrackState(const EVENT::TrackState &ts, double bField)
Get track momentum at the track state.
Definition: TOFUtils.cc:58
int _nEvent
Stores current event number.
Definition: TOFEstimators.h:79