7 #include "marlin/VerbosityLevels.h"
8 #include "marlinutil/CalorimeterHitType.h"
9 #include "HelixClass.h"
10 #include "DD4hep/Detector.h"
11 #include "DD4hep/DD4hepUnits.h"
12 #include "DDRec/DetectorData.h"
13 #include "CLHEP/Random/Randomize.h"
14 #include "CLHEP/Units/PhysicalConstants.h"
15 #include "TGraphErrors.h"
17 #include "MarlinTrk/MarlinTrkUtils.h"
18 #include "UTIL/LCRelationNavigator.h"
19 #include "UTIL/ILDConf.h"
20 #include "IMPL/TrackImpl.h"
23 using std::numeric_limits;
25 using EVENT::TrackerHit;
28 using EVENT::CalorimeterHit;
29 using EVENT::TrackState;
30 using dd4hep::Detector;
31 using dd4hep::DetElement;
33 using dd4hep::rec::FixedPadSizeTPCData;
34 using MarlinTrk::IMarlinTrack;
35 using MarlinTrk::IMarlinTrkSystem;
36 using UTIL::LCRelationNavigator;
38 using IMPL::TrackImpl;
39 using IMPL::TrackStateImpl;
40 using CLHEP::RandGauss;
45 return posA.rho() < posB.rho();
53 marlinTrk->getTrackState(hit, ts, chi2Dummy, ndfDummy);
59 double phi = ts.getPhi();
60 double d0 = ts.getD0();
61 double z0 = ts.getZ0();
62 double omega = ts.getOmega();
63 double tanL = ts.getTanLambda();
66 helix.Initialize_Canonical(phi, d0, z0, omega, tanL, bField);
67 return helix.getMomentum();
72 double omega = ts1.getOmega();
73 double z1 = ts1.getReferencePoint()[2] + ts1.getZ0();
74 double z2 = ts2.getReferencePoint()[2] + ts2.getZ0();
75 double dPhi = std::abs( ts2.getPhi() - ts1.getPhi() );
76 if (dPhi > M_PI) dPhi = 2*M_PI - dPhi;
78 return std::sqrt( std::pow(dPhi/omega, 2) + std::pow(z2-z1, 2) );
83 double tanL = ts1.getTanLambda();
84 double z1 = ts1.getReferencePoint()[2] + ts1.getZ0();
85 double z2 = ts2.getReferencePoint()[2] + ts2.getZ0();
87 return std::abs( (z2-z1)/tanL ) * std::sqrt( 1.+tanL*tanL );
91 double omega = ts1.getOmega();
92 double tanL = ts1.getTanLambda();
93 double z1 = ts1.getReferencePoint()[2] + ts1.getZ0();
94 double z2 = ts2.getReferencePoint()[2] + ts2.getZ0();
97 double circHelix = std::abs( (z2-z1)/tanL );
98 double circFull = 2*M_PI/std::abs(omega);
100 return circHelix/circFull;
105 auto& detector = Detector::getInstance();
106 DetElement tpcDet = detector.detector(
"TPC");
107 FixedPadSizeTPCData* tpc = tpcDet.extension <FixedPadSizeTPCData>();
113 vector<TrackerHit*> hits = track->getTrackerHits();
114 TrackerHit* lastHit = hits.back();
115 Vector3D pos (lastHit->getPosition());
117 if ( pos.rho() > tpcOuterR )
return lastHit;
123 const TrackState* tsEcal = track->getTrackState(TrackState::AtCalorimeter);
124 Vector3D trackPosAtEcal ( tsEcal->getReferencePoint() );
127 vector<CalorimeterHit*> selectedHits(maxEcalLayer,
nullptr);
128 vector<double> minDistances(maxEcalLayer, numeric_limits<double>::max());
130 for (
auto hit : cluster->getCalorimeterHits() ){
131 CHT hitType( hit->getType() );
132 bool isECALHit = ( hitType.caloID() == CHT::ecal );
133 int layer = hitType.layer();
134 if ( (!isECALHit) || ( layer >= maxEcalLayer) )
continue;
136 Vector3D hitPos( hit->getPosition() );
137 double dToLine = (hitPos - trackPosAtEcal).cross(trackMomAtEcal.unit()).r();
138 if ( dToLine < minDistances[layer] ){
139 minDistances[layer] = dToLine;
140 selectedHits[layer] = hit;
143 selectedHits.erase( std::remove_if( selectedHits.begin(), selectedHits.end(), [](CalorimeterHit* h) {
return h ==
nullptr; } ), selectedHits.end() );
150 vector<Track*> subTracks;
151 subTracks.push_back(track);
153 int nSubTracks = track->getTracks().size();
154 if (nSubTracks <= 1)
return subTracks;
156 int nTPCHits = track->getSubdetectorHitNumbers()[(ILDDetID::TPC)*2-1];
157 int nSubTrack0Hits = track->getTracks()[0]->getTrackerHits().size();
158 int nSubTrack1Hits = track->getTracks()[1]->getTrackerHits().size();
163 if( std::abs(nTPCHits - nSubTrack0Hits) <= 1 ) startIdx = 1;
164 else if ( std::abs(nTPCHits - nSubTrack1Hits) <= 1 ) startIdx = 2;
167 streamlog_out(WARNING)<<
"Can't understand which subTrack is responsible for the first TPC hits! Skip adding subTracks."<<std::endl;
170 for(
int j=startIdx; j < nSubTracks; ++j) subTracks.push_back( track->getTracks()[j] );
175 std::vector<IMPL::TrackStateImpl>
TOFUtils::getTrackStatesPerHit(std::vector<EVENT::Track*> tracks, MarlinTrk::IMarlinTrkSystem* trkSystem,
bool extrapolateToEcal,
double bField){
176 vector<TrackStateImpl> trackStatesPerHit;
177 int nTracks = tracks.size();
178 for(
int i=0; i<nTracks; ++i){
179 Track* track = tracks[i];
180 vector <TrackerHit*> hits = track->getTrackerHits();
181 std::sort(hits.begin(), hits.end(),
sortByRho);
184 vector<float> covMatrix(15);
186 covMatrix[0] = 1
e+06;
188 covMatrix[5] = 0.00001;
189 covMatrix[9] = 1
e+06;
190 covMatrix[14] = 100.;
191 double maxChi2PerHit = 100.;
192 std::unique_ptr<IMarlinTrack> marlinTrk( trkSystem->createTrack() );
193 TrackImpl refittedTrack;
196 TrackStateImpl preFit = *track->getTrackState(TrackState::AtLastHit);
197 preFit.setCovMatrix( covMatrix );
198 int errorFit = MarlinTrk::createFinalisedLCIOTrack(marlinTrk.get(), hits, &refittedTrack, IMarlinTrack::backward, &preFit, bField, maxChi2PerHit);
201 streamlog_out(DEBUG8)<<
"Fit backward fails! Trying to fit forward for "<<i+1<<
" subTrack in this PFO!"<<std::endl;
203 marlinTrk.reset( trkSystem->createTrack() );
204 errorFit = MarlinTrk::createFinalisedLCIOTrack(marlinTrk.get(), hits, &refittedTrack, IMarlinTrack::forward, &preFit, bField, maxChi2PerHit);
207 streamlog_out(WARNING)<<
"Fit fails in both directions. Skipping "<<i+1<<
" subTrack in this PFO!"<<std::endl;
211 vector< pair<TrackerHit*, double> > hitsInFit;
212 marlinTrk->getHitsInFit(hitsInFit);
215 bool loopForward =
true;
216 double zFirst = std::abs( hitsInFit.front().first->getPosition()[2] );
217 double zLast = std::abs( hitsInFit.back().first->getPosition()[2] );
220 if ( std::abs(zLast - zFirst) > 10. ){
221 if ( zLast < zFirst ) loopForward =
false;
222 streamlog_out(DEBUG8)<<
"Using Z to define loop direction over subTrack hits."<<std::endl;
223 streamlog_out(DEBUG8)<<
"subTrack "<<i+1<<
" zFirst: "<<hitsInFit.front().first->getPosition()[2]<<
" zLast: "<<hitsInFit.back().first->getPosition()[2]<<
" loop forward: "<<loopForward<<std::endl;
226 double rhoFirst =
std::hypot( hitsInFit.front().first->getPosition()[0], hitsInFit.front().first->getPosition()[1] );
227 double rhoLast =
std::hypot( hitsInFit.back().first->getPosition()[0], hitsInFit.back().first->getPosition()[1] );
228 if ( rhoLast < rhoFirst ) loopForward =
false;
229 streamlog_out(DEBUG8)<<
"Track is very perpendicular (dz < 10 mm). Using rho to define loop direction over subTrack hits."<<std::endl;
230 streamlog_out(DEBUG8)<<
"subTrack "<<i+1<<
" zFirst: "<<hitsInFit.front().first->getPosition()[2]<<
" zLast: "<<hitsInFit.back().first->getPosition()[2]<<std::endl;
231 streamlog_out(DEBUG8)<<
"subTrack "<<i+1<<
" rhoFirst: "<<rhoFirst<<
" rhoLast: "<<rhoLast<<
" loop forward: "<<loopForward<<std::endl;
234 int nHitsInFit = hitsInFit.size();
236 if ( trackStatesPerHit.empty() ) trackStatesPerHit.push_back(*(static_cast<const TrackStateImpl*> (refittedTrack.getTrackState(TrackState::AtIP)) ));
240 for(
int j=0; j<nHitsInFit; ++j ){
242 trackStatesPerHit.push_back(ts);
246 for(
int j=nHitsInFit-1; j>=0; --j ){
248 trackStatesPerHit.push_back(ts);
252 if (i == nTracks - 1){
257 trackStatesPerHit.push_back( *(static_cast<const TrackStateImpl*> (refittedTrack.getTrackState(TrackState::AtLastHit)) ) );
258 if (extrapolateToEcal) trackStatesPerHit.push_back( *(static_cast<const TrackStateImpl*> (refittedTrack.getTrackState(TrackState::AtCalorimeter) ) ) );
264 return trackStatesPerHit;
269 const TrackState* tsEcal = track->getTrackState(TrackState::AtCalorimeter);
270 Vector3D trackPosAtEcal ( tsEcal->getReferencePoint() );
272 double hitTime = numeric_limits<double>::max();
273 double closestDistance = numeric_limits<double>::max();
274 for(
auto hit : cluster->getCalorimeterHits() ){
275 CHT hitType( hit->getType() );
276 bool isECALHit = ( hitType.caloID() == CHT::ecal );
277 if (! isECALHit)
continue;
279 Vector3D hitPos( hit->getPosition() );
280 double dToTrack = (hitPos - trackPosAtEcal).r();
281 if( dToTrack < closestDistance ){
282 closestDistance = dToTrack;
283 hitTime = hit->getTime();
287 if ( hitTime == numeric_limits<double>::max() )
return 0.;
288 return RandGauss::shoot(hitTime, timeResolution) - closestDistance/CLHEP::c_light;
293 const TrackState* tsEcal = track->getTrackState(TrackState::AtCalorimeter);
294 Vector3D trackPosAtEcal ( tsEcal->getReferencePoint() );
296 int nHits = selectedHits.size();
297 if (nHits == 0)
return 0.;
300 for (
auto hit : selectedHits ){
301 Vector3D hitPos( hit->getPosition() );
302 double dToTrack = (hitPos - trackPosAtEcal).r();
303 tof += RandGauss::shoot(hit->getTime(), timeResolution) - dToTrack/CLHEP::c_light;
310 const TrackState* tsEcal = track->getTrackState(TrackState::AtCalorimeter);
311 Vector3D trackPosAtEcal ( tsEcal->getReferencePoint() );
313 int nHits = selectedHits.size();
314 if (nHits == 0)
return 0.;
315 else if (nHits == 1){
317 Vector3D hitPos( selectedHits[0]->getPosition() );
318 double dToTrack = (hitPos - trackPosAtEcal).r();
319 return RandGauss::shoot(selectedHits[0]->getTime(), timeResolution) - dToTrack/CLHEP::c_light;
322 vector <double> x, y;
323 for (
auto hit : selectedHits ){
324 Vector3D hitPos( hit->getPosition() );
325 double dToTrack = (hitPos - trackPosAtEcal).r();
326 x.push_back(dToTrack);
327 double time = RandGauss::shoot(hit->getTime(), timeResolution);
331 TGraph gr(nHits, x.data(), y.data());
333 return gr.GetFunction(
"pol1")->GetParameter(0);
double getHelixLengthAlongZ(const EVENT::TrackState &ts1, const EVENT::TrackState &ts2)
Get track length.
double getTofFrankAvg(std::vector< EVENT::CalorimeterHit * > selectedHits, EVENT::Track *track, double timeResolution)
Get the time-of-flight using average of the Frank ECal hits.
double getTofClosest(EVENT::Cluster *cluster, EVENT::Track *track, double timeResolution)
Get the time-of-flight using the closest ECal hit.
double getHelixNRevolutions(const EVENT::TrackState &ts1, const EVENT::TrackState &ts2)
Get number of helix revolutions.
CLHEP::Hep3Vector Vector3D
EVENT::TrackerHit * getSETHit(EVENT::Track *track, double tpcOuterR)
Returns SET hit.
double getTPCOuterR()
Returns TPC outer radius from the DD4hep detector geometry.
Real hypot(const Real &a, const Real &b)
std::vector< IMPL::TrackStateImpl > getTrackStatesPerHit(std::vector< EVENT::Track * > tracks, MarlinTrk::IMarlinTrkSystem *trkSystem, bool extrapolateToEcal, double bField)
Get list of track states.
double getTofFrankFit(std::vector< EVENT::CalorimeterHit * > selectedHits, EVENT::Track *track, double timeResolution)
Get the time-of-flight using fit of the Frank ECal hits.
std::vector< EVENT::CalorimeterHit * > selectFrankEcalHits(EVENT::Cluster *cluster, EVENT::Track *track, int maxEcalLayer, double bField)
Get a subset of the cluster calorimeter hits.
double getHelixArcLength(const EVENT::TrackState &ts1, const EVENT::TrackState &ts2)
Get track length.
std::vector< EVENT::Track * > getSubTracks(EVENT::Track *track)
Get all subtracks of the Track.
bool sortByRho(EVENT::TrackerHit *a, EVENT::TrackerHit *b)
Comparator function by radius for tracker hits.
IMPL::TrackStateImpl getTrackStateAtHit(MarlinTrk::IMarlinTrack *marlinTrk, EVENT::TrackerHit *hit)
Get track state at tracker hit.
dd4hep::rec::Vector3D getHelixMomAtTrackState(const EVENT::TrackState &ts, double bField)
Get track momentum at the track state.