CMS 3D CMS Logo

KDTreeLinkerTrackEcal.cc
Go to the documentation of this file.
2 
4 #include "TMath.h"
5 
6 // the text name is different so that we can easily
7 // construct it when calling the factory
10  "KDTreeTrackAndECALLinker");
11 
12 
15 {}
16 
18 {
19  clear();
20 }
21 
22 void
24 {
25  if( track->trackRefPF()->extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax ).isValid() ) {
26  targetSet_.insert(track);
27  }
28 }
29 
30 
31 void
33 {
34  const reco::PFClusterRef& clusterref = ecalCluster->clusterRef();
35 
36  // This test is more or less done in PFBlockAlgo.h. In others cases, it should be switch on.
37  // if (!((clusterref->layer() == PFLayer::ECAL_ENDCAP) ||
38  // (clusterref->layer() == PFLayer::ECAL_BARREL)))
39  // return;
40 
41  const std::vector<reco::PFRecHitFraction> &fraction = clusterref->recHitFractions();
42 
43  // We create a list of ecalCluster
44  fieldClusterSet_.insert(ecalCluster);
45  for(size_t rhit = 0; rhit < fraction.size(); ++rhit) {
46  const reco::PFRecHitRef& rh = fraction[rhit].recHitRef();
47  double fract = fraction[rhit].fraction();
48 
49  if ((rh.isNull()) || (fract < 1E-4))
50  continue;
51 
52  const reco::PFRecHit& rechit = *rh;
53 
54  // We save the links rechit to EcalClusters
55  rechit2ClusterLinks_[&rechit].insert(ecalCluster);
56 
57  // We create a liste of rechits
58  rechitsSet_.insert(&rechit);
59  }
60 }
61 
62 void
64 {
65  // List of pseudo-rechits that will be used to create the KDTree
66  std::vector<KDTreeNodeInfo<reco::PFRecHit const*>> eltList;
67 
68  // Filling of this list
69  for(RecHitSet::const_iterator it = rechitsSet_.begin();
70  it != rechitsSet_.end(); it++) {
71 
72  const reco::PFRecHit::REPPoint &posrep = (*it)->positionREP();
73 
74  KDTreeNodeInfo<reco::PFRecHit const*> rh1 (*it, posrep.eta(), posrep.phi());
75  eltList.push_back(rh1);
76 
77  // Here we solve the problem of phi circular set by duplicating some rechits
78  // too close to -Pi (or to Pi) and adding (substracting) to them 2 * Pi.
79  if (rh1.dim[1] > (M_PI - phiOffset_)) {
80  double phi = rh1.dim[1] - 2 * M_PI;
81  KDTreeNodeInfo rh2(*it, posrep.eta(), phi);
82  eltList.push_back(rh2);
83  }
84 
85  if (rh1.dim[1] < (M_PI * -1.0 + phiOffset_)) {
86  double phi = rh1.dim[1] + 2 * M_PI;
87  KDTreeNodeInfo rh3(*it, posrep.eta(), phi);
88  eltList.push_back(rh3);
89  }
90  }
91 
92  // Here we define the upper/lower bounds of the 2D space (eta/phi).
93  double phimin = -1.0 * M_PI - phiOffset_;
94  double phimax = M_PI + phiOffset_;
95 
96  // etamin-etamax, phimin-phimax
97  KDTreeBox region(-3.0, 3.0, phimin, phimax);
98 
99  // We may now build the KDTree
100  tree_.build(eltList, region);
101 }
102 
103 void
105 {
106  // Must of the code has been taken from LinkByRecHit.cc
107 
108  // We iterate over the tracks.
109  for(BlockEltSet::iterator it = targetSet_.begin();
110  it != targetSet_.end(); it++) {
111 
112  reco::PFRecTrackRef trackref = (*it)->trackRefPF();
113 
114  // We set the multilinks flag of the track to true. It will allow us to
115  // use in an optimized way our algo results in the recursive linking algo.
116  (*it)->setIsValidMultilinks(true);
117 
118  const reco::PFTrajectoryPoint& atECAL =
119  trackref->extrapolatedPoint(reco::PFTrajectoryPoint::ECALShowerMax);
120 
121  // The track didn't reach ecal
122  if( ! atECAL.isValid() ) continue;
123 
124  const reco::PFTrajectoryPoint& atVertex =
125  trackref->extrapolatedPoint( reco::PFTrajectoryPoint::ClosestApproach );
126 
127  double trackPt = sqrt(atVertex.momentum().Vect().Perp2());
128  double tracketa = atECAL.positionREP().eta();
129  double trackphi = atECAL.positionREP().phi();
130  double trackx = atECAL.position().X();
131  double tracky = atECAL.position().Y();
132  double trackz = atECAL.position().Z();
133 
134  // Estimate the maximal envelope in phi/eta that will be used to find rechit candidates.
135  // Same envelope for cap et barrel rechits.
136  double range = cristalPhiEtaMaxSize_ * (2.0 + 1.0 / std::min(1., trackPt / 2.));
137 
138  // We search for all candidate recHits, ie all recHits contained in the maximal size envelope.
139  std::vector<reco::PFRecHit const*> recHits;
140  KDTreeBox trackBox(tracketa-range, tracketa+range, trackphi-range, trackphi+range);
141  tree_.search(trackBox, recHits);
142 
143  // Here we check all rechit candidates using the non-approximated method.
144  for(auto const& recHit : recHits) {
145 
146  const auto & cornersxyz = recHit->getCornersXYZ();
147  const auto & posxyz = recHit->position();
148  const auto &rhrep = recHit->positionREP();
149  const auto & corners = recHit->getCornersREP();
150 
151  double rhsizeeta = fabs(corners[3].eta() - corners[1].eta());
152  double rhsizephi = fabs(corners[3].phi() - corners[1].phi());
153  if ( rhsizephi > M_PI ) rhsizephi = 2.*M_PI - rhsizephi;
154 
155  double deta = fabs(rhrep.eta() - tracketa);
156  double dphi = fabs(rhrep.phi() - trackphi);
157  if ( dphi > M_PI ) dphi = 2.*M_PI - dphi;
158 
159  // Find all clusters associated to given rechit
160  RecHit2BlockEltMap::iterator ret = rechit2ClusterLinks_.find(recHit);
161 
162  for(BlockEltSet::const_iterator clusterIt = ret->second.begin();
163  clusterIt != ret->second.end(); clusterIt++) {
164 
165  reco::PFClusterRef clusterref = (*clusterIt)->clusterRef();
166  double clusterz = clusterref->position().z();
167  int fracsNbr = clusterref->recHitFractions().size();
168 
169  if (clusterref->layer() == PFLayer::ECAL_BARREL){ // BARREL
170  // Check if the track is in the barrel
171  if (fabs(trackz) > 300.) continue;
172 
173  double _rhsizeeta = rhsizeeta * (2.00 + 1.0 / (fracsNbr * std::min(1.,trackPt/2.)));
174  double _rhsizephi = rhsizephi * (2.00 + 1.0 / (fracsNbr * std::min(1.,trackPt/2.)));
175 
176  // Check if the track and the cluster are linked
177  if(deta < (_rhsizeeta / 2.) && dphi < (_rhsizephi / 2.))
178  target2ClusterLinks_[*it].insert(*clusterIt);
179 
180 
181  } else { // ENDCAP
182 
183  // Check if the track is in the cap
184  if (fabs(trackz) < 300.) continue;
185  if (trackz * clusterz < 0.) continue;
186 
187  double x[5];
188  double y[5];
189  for ( unsigned jc=0; jc<4; ++jc ) {
190  auto cornerposxyz = cornersxyz[jc];
191  x[3-jc] = cornerposxyz.x() + (cornerposxyz.x()-posxyz.x())
192  * (1.00+0.50/fracsNbr /std::min(1.,trackPt/2.));
193  y[3-jc] = cornerposxyz.y() + (cornerposxyz.y()-posxyz.y())
194  * (1.00+0.50/fracsNbr /std::min(1.,trackPt/2.));
195  }
196 
197  x[4] = x[0];
198  y[4] = y[0];
199 
200  bool isinside = TMath::IsInside(trackx,
201  tracky,
202  5,x,y);
203 
204  // Check if the track and the cluster are linked
205  if( isinside )
206  target2ClusterLinks_[*it].insert(*clusterIt);
207  }
208  }
209  }
210  }
211 }
212 
213 void
215 {
216  //TODO YG : Check if cluster positionREP() is valid ?
217 
218  // Here we save in each track the list of phi/eta values of linked clusters.
219  for (BlockElt2BlockEltMap::iterator it = target2ClusterLinks_.begin();
220  it != target2ClusterLinks_.end(); ++it) {
221  reco::PFMultiLinksTC multitracks(true);
222 
223  for (BlockEltSet::iterator jt = it->second.begin();
224  jt != it->second.end(); ++jt) {
225 
226  double clusterphi = (*jt)->clusterRef()->positionREP().phi();
227  double clustereta = (*jt)->clusterRef()->positionREP().eta();
228 
229  multitracks.linkedClusters.push_back(std::make_pair(clusterphi, clustereta));
230  }
231 
232  it->first->setMultilinks(multitracks);
233  }
234 }
235 
236 void
238 {
239  targetSet_.clear();
240  fieldClusterSet_.clear();
241 
242  rechitsSet_.clear();
243 
244  rechit2ClusterLinks_.clear();
245  target2ClusterLinks_.clear();
246 
247  tree_.clear();
248 }
float phi() const
momentum azimuthal angle
Definition: PtEtaPhiMass.h:53
const REPPoint & positionREP() const
trajectory position in (rho, eta, phi) base
void insertTargetElt(reco::PFBlockElement *track) override
Abstract base class for a PFBlock element (track, cluster...)
virtual const PFClusterRef & clusterRef() const
const math::XYZPoint & position() const
cartesian position (x, y, z)
void insertFieldClusterElt(reco::PFBlockElement *ecalCluster) override
Particle flow rechit (rechit + geometry and topology information). See clustering algorithm in PFClus...
Definition: PFRecHit.h:31
Point of closest approach from beam axis (initial point in the case of PFSimParticle) ...
T sqrt(T t)
Definition: SSEVec.h:18
PFMultilinksType linkedClusters
void updatePFBlockEltWithLinks() override
void search(const KDTreeBox &searchBox, std::vector< DATA > &resRecHitList)
const Fraction< n, m >::type & fract()
Definition: Fraction.h:37
T min(T a, T b)
Definition: MathUtil.h:58
virtual const PFRecTrackRef & trackRefPF() const
bool isNull() const
Checks for null.
Definition: Ref.h:248
#define M_PI
void build(std::vector< KDTreeNodeInfo< DATA > > &eltList, const KDTreeBox &region)
const math::XYZTLorentzVector & momentum() const
4-momenta quadrivector
bool isValid() const
is this point valid ?
RecHit2BlockEltMap rechit2ClusterLinks_
BlockElt2BlockEltMap target2ClusterLinks_
KDTreeLinkerAlgo< reco::PFRecHit const * > tree_
#define DEFINE_EDM_PLUGIN(factory, type, name)
A PFTrack holds several trajectory points, which basically contain the position and momentum of a tra...
float eta() const
momentum pseudorapidity
Definition: PtEtaPhiMass.h:51