1 |
#ifndef CommonDet_Trajectory_H
|
2 |
#define CommonDet_Trajectory_H
|
3 |
|
4 |
#include "DataFormats/Common/interface/RefToBase.h"
|
5 |
#include "TrackingTools/PatternTools/interface/TrajectoryMeasurement.h"
|
6 |
#include "DataFormats/TrajectorySeed/interface/PropagationDirection.h"
|
7 |
#include "DataFormats/TrajectorySeed/interface/TrajectorySeed.h"
|
8 |
#include "TrackingTools/TransientTrackingRecHit/interface/TransientTrackingRecHit.h"
|
9 |
#include "FWCore/MessageLogger/interface/MessageLogger.h"
|
10 |
|
11 |
#include <vector>
|
12 |
#include <algorithm>
|
13 |
#include <boost/shared_ptr.hpp>
|
14 |
|
15 |
/** A class for detailed particle trajectory representation.
|
16 |
* It is used during trajectory building to "grow" a trajectory.
|
17 |
* The trajectory is represented as an ordered sequence of
|
18 |
* TrajectoryMeasurement objects with a stack-like interface.
|
19 |
* The measurements are added to the Trajectory in the order of
|
20 |
* increasing precision: each new TrajectoryMeasurement is assumed to improve
|
21 |
* the precision of the last one, normally by adding a constraint from
|
22 |
* a new RecHit.
|
23 |
* However the Trajectory class does not have the means to verify
|
24 |
* that measurements are added in the correct order, and thus cannot
|
25 |
* guarantee the order, which is the responsibility of the
|
26 |
* TrajectoryBuilder. The Trajectory provides some security by
|
27 |
* allowing to add or remove measurements only on one of it's ends,
|
28 |
* with push(TM) and pop() methods. The last measurement in a Trajectory
|
29 |
* can thus be either the innermost (closest to the interaction point)
|
30 |
* or the outermost, depending on the way the Trajectory was built.
|
31 |
* The direction of building is represented as a PropagationDirection,
|
32 |
* which has two possible values: alongMomentum (outwards) and
|
33 |
* oppositeToMomentum (inwards), and is accessed with the direction()
|
34 |
* method.
|
35 |
*/
|
36 |
|
37 |
|
38 |
class Trajectory
|
39 |
{
|
40 |
public:
|
41 |
|
42 |
typedef std::vector<TrajectoryMeasurement> DataContainer;
|
43 |
typedef TransientTrackingRecHit::ConstRecHitContainer ConstRecHitContainer;
|
44 |
typedef ConstRecHitContainer RecHitContainer;
|
45 |
|
46 |
|
47 |
/** Default constructor of an empty trajectory with undefined seed and
|
48 |
* undefined direction. This constructor is necessary in order to transiently
|
49 |
* copy vector<Trajectory> in the edm::Event
|
50 |
*/
|
51 |
|
52 |
Trajectory() :
|
53 |
theSeed(), seedRef_(),
|
54 |
theChiSquared(0), theChiSquaredBad(0),
|
55 |
theNumberOfFoundHits(0), theNumberOfLostHits(0),
|
56 |
theDirection(alongMomentum), theDirectionValidity(false), theValid(true)
|
57 |
{}
|
58 |
|
59 |
|
60 |
/** Constructor of an empty trajectory with undefined direction.
|
61 |
* The direction will be defined at the moment of the push of a second
|
62 |
* measurement, from the relative radii of the first and second
|
63 |
* measurements.
|
64 |
*/
|
65 |
|
66 |
Trajectory( const TrajectorySeed& seed) :
|
67 |
theSeed( new TrajectorySeed(seed) ), seedRef_(),
|
68 |
theChiSquared(0), theChiSquaredBad(0),
|
69 |
theNumberOfFoundHits(0), theNumberOfLostHits(0),
|
70 |
theDirection(alongMomentum), theDirectionValidity(false), theValid(true)
|
71 |
{}
|
72 |
|
73 |
/** Constructor of an empty trajectory with defined direction.
|
74 |
* No check is made in the push method that measurements are
|
75 |
* added in the correct direction.
|
76 |
*/
|
77 |
Trajectory( const TrajectorySeed& seed, PropagationDirection dir) :
|
78 |
theSeed( new TrajectorySeed(seed) ), seedRef_(),
|
79 |
theChiSquared(0), theChiSquaredBad(0),
|
80 |
theNumberOfFoundHits(0), theNumberOfLostHits(0),
|
81 |
theDirection(dir), theDirectionValidity(true), theValid(true)
|
82 |
|
83 |
{}
|
84 |
|
85 |
/** Constructor of an empty trajectory with defined direction.
|
86 |
* No check is made in the push method that measurements are
|
87 |
* added in the correct direction.
|
88 |
*/
|
89 |
Trajectory( const boost::shared_ptr<const TrajectorySeed> & seed, PropagationDirection dir) :
|
90 |
theSeed( seed ), seedRef_(),
|
91 |
theChiSquared(0), theChiSquaredBad(0),
|
92 |
theNumberOfFoundHits(0), theNumberOfLostHits(0),
|
93 |
theDirection(dir), theDirectionValidity(true), theValid(true)
|
94 |
{}
|
95 |
|
96 |
|
97 |
#if defined( __GXX_EXPERIMENTAL_CXX0X__)
|
98 |
Trajectory(Trajectory const & rh) :
|
99 |
theSeed(rh.theSeed), seedRef_(rh.seedRef_),
|
100 |
theData(rh.theData),
|
101 |
theChiSquared(rh.theChiSquared), theChiSquaredBad(rh.theChiSquaredBad),
|
102 |
theNumberOfFoundHits(rh.theNumberOfFoundHits), theNumberOfLostHits(rh.theNumberOfLostHits),
|
103 |
theDirection(rh.theDirection), theDirectionValidity(rh.theDirectionValidity), theValid(rh.theValid)
|
104 |
{}
|
105 |
|
106 |
|
107 |
Trajectory(Trajectory && rh) :
|
108 |
theSeed(std::move(rh.theSeed)), seedRef_(std::move(rh.seedRef_)),
|
109 |
theData(std::move(rh.theData)),
|
110 |
theChiSquared(rh.theChiSquared), theChiSquaredBad(rh.theChiSquaredBad),
|
111 |
theNumberOfFoundHits(rh.theNumberOfFoundHits), theNumberOfLostHits(rh.theNumberOfLostHits),
|
112 |
theDirection(rh.theDirection), theDirectionValidity(rh.theDirectionValidity), theValid(rh.theValid)
|
113 |
{}
|
114 |
|
115 |
Trajectory & operator=(Trajectory && rh) {
|
116 |
using std::swap;
|
117 |
swap(theData,rh.theData);
|
118 |
theChiSquared=rh.theChiSquared;
|
119 |
theChiSquaredBad=rh.theChiSquaredBad;
|
120 |
theValid=rh.theValid;
|
121 |
theNumberOfFoundHits=rh.theNumberOfFoundHits;
|
122 |
theNumberOfLostHits=rh.theNumberOfLostHits;
|
123 |
theDirection=rh.theDirection;
|
124 |
theDirectionValidity=rh.theDirectionValidity;
|
125 |
swap(theSeed,rh.theSeed);
|
126 |
swap(seedRef_,rh.seedRef_);
|
127 |
|
128 |
return *this;
|
129 |
|
130 |
}
|
131 |
|
132 |
Trajectory & operator=(Trajectory const & rh) {
|
133 |
theData = rh.theData;
|
134 |
theChiSquared=rh.theChiSquared;
|
135 |
theChiSquaredBad=rh.theChiSquaredBad;
|
136 |
theValid=rh.theValid;
|
137 |
theNumberOfFoundHits=rh.theNumberOfFoundHits;
|
138 |
theNumberOfLostHits=rh.theNumberOfLostHits;
|
139 |
theDirection=rh.theDirection;
|
140 |
theDirectionValidity=rh.theDirectionValidity;
|
141 |
theSeed = rh.theSeed;
|
142 |
seedRef_ = rh.seedRef_;
|
143 |
|
144 |
return *this;
|
145 |
|
146 |
}
|
147 |
|
148 |
|
149 |
#endif
|
150 |
|
151 |
/** Reserves space in the vector to avoid lots of allocations when
|
152 |
push_back-ing measurements */
|
153 |
void reserve (unsigned int n) { theData.reserve(n); }
|
154 |
|
155 |
/** Add a new measurement to a Trajectory.
|
156 |
* The Chi2 of the trajectory is incremented by the value
|
157 |
* of tm.estimate() .
|
158 |
*/
|
159 |
void push( const TrajectoryMeasurement& tm);
|
160 |
|
161 |
/** same as the one-argument push, but the trajectory Chi2 is incremented
|
162 |
* by chi2Increment. Useful e.g. in trajectory smoothing.
|
163 |
*/
|
164 |
void push( const TrajectoryMeasurement& tm, double chi2Increment);
|
165 |
|
166 |
/** Remove the last measurement from the trajectory.
|
167 |
*/
|
168 |
void pop();
|
169 |
|
170 |
/** Access to the last measurement.
|
171 |
* It's the most precise one in a trajectory before smoothing.
|
172 |
* It's the outermost measurement if direction() == alongMomentum,
|
173 |
* the innermost one if direction() == oppositeToMomentum.
|
174 |
*/
|
175 |
TrajectoryMeasurement const & lastMeasurement() const {
|
176 |
check();
|
177 |
if (theData.back().recHit()->hit()!=0) return theData.back();
|
178 |
else if (theData.size()>2) return *(theData.end()-2);
|
179 |
else throw cms::Exception("TrajectoryMeasurement::lastMeasurement - Too few measurements in trajectory");
|
180 |
}
|
181 |
|
182 |
/** Access to the first measurement.
|
183 |
* It is the least precise one in a trajectory before smoothing.
|
184 |
* It is precise in a smoothed trajectory.
|
185 |
* It's the innermost measurement if direction() == alongMomentum,
|
186 |
* the outermost one if direction() == oppositeToMomentum.
|
187 |
*/
|
188 |
TrajectoryMeasurement const & firstMeasurement() const {
|
189 |
check();
|
190 |
if (theData.front().recHit()->hit()!=0) return theData.front();
|
191 |
else if (theData.size()>2) return *(theData.begin()+1);
|
192 |
else throw cms::Exception("TrajectoryMeasurement::firstMeasurement - Too few measurements in trajectory");
|
193 |
}
|
194 |
|
195 |
/** Return all measurements in a container.
|
196 |
*/
|
197 |
DataContainer const & measurements() const { return theData;}
|
198 |
/// obsolete name, use measurements() instead.
|
199 |
DataContainer const & data() const { return measurements();}
|
200 |
|
201 |
/** Return all RecHits in a container.
|
202 |
*/
|
203 |
ConstRecHitContainer recHits(bool splitting=false) const;
|
204 |
|
205 |
void recHitsV(ConstRecHitContainer & cont,bool splitting = false) const;
|
206 |
|
207 |
/** Just valid hits..
|
208 |
*
|
209 |
*/
|
210 |
void validRecHits(ConstRecHitContainer & cont) const;
|
211 |
|
212 |
/** Number of valid RecHits used to determine the trajectory.
|
213 |
* Can be less than the number of measurements in data() since
|
214 |
* detector layers crossed without using RecHits from them are also
|
215 |
* stored as measurements.
|
216 |
*/
|
217 |
|
218 |
int foundHits() const { return theNumberOfFoundHits;}
|
219 |
|
220 |
/** Number of detector layers crossed without valid RecHits.
|
221 |
* Used mainly as a criteria for abandoning a trajectory candidate
|
222 |
* during trajectory building.
|
223 |
*/
|
224 |
|
225 |
int lostHits() const { return theNumberOfLostHits;}
|
226 |
|
227 |
/// True if trajectory has no measurements.
|
228 |
bool empty() const { return theData.empty();}
|
229 |
|
230 |
/// - Trajectories with at least 1 valid hit:
|
231 |
/// value of the raw Chi2 of the trajectory, not normalised to the N.D.F.
|
232 |
/// (evaluated using only valid hits)
|
233 |
/// - Trajectories with only invalid hits:
|
234 |
/// raw Chi2 (not norm.) of invalid hits w.r.t. the "default" trajectory
|
235 |
/// (traj. containing only the seed information)
|
236 |
double chiSquared() const { return (theNumberOfFoundHits ? theChiSquared : theChiSquaredBad);}
|
237 |
|
238 |
/// Number of dof of the trajectory. The method accepts a bool in order to properly
|
239 |
/// take into account the presence of magnetic field in the dof computation.
|
240 |
/// By default the MF is considered ON.
|
241 |
int ndof(bool bon = true) const;
|
242 |
|
243 |
|
244 |
/** Direction of "growing" of the trajectory.
|
245 |
* Possible values are alongMomentum (outwards) and
|
246 |
* oppositeToMomentum (inwards).
|
247 |
*/
|
248 |
PropagationDirection const & direction() const;
|
249 |
|
250 |
/** Returns true if the Trajectory is valid.
|
251 |
* Trajectories are invalidated e.g. during ambiguity resolution.
|
252 |
*/
|
253 |
bool isValid() const { return theValid;}
|
254 |
|
255 |
/// Method to invalidate a trajectory. Useful during ambiguity resolution.
|
256 |
void invalidate() { theValid = false;}
|
257 |
|
258 |
/// Access to the seed used to reconstruct the Trajectory
|
259 |
TrajectorySeed const & seed() const { return *theSeed;}
|
260 |
|
261 |
|
262 |
/** Definition of inactive Det from the Trajectory point of view.
|
263 |
*/
|
264 |
static bool inactive(//const Det& det
|
265 |
){return false;}//FIXME
|
266 |
|
267 |
/** Definition of what it means for a hit to be "lost".
|
268 |
* This definition is also used by the TrajectoryBuilder.
|
269 |
*/
|
270 |
static bool lost( const TransientTrackingRecHit& hit);
|
271 |
|
272 |
/** Returns true if the hit type is TrackingRecHit::bad
|
273 |
* Used in stand-alone trajectory construction
|
274 |
*/
|
275 |
static bool isBad( const TransientTrackingRecHit& hit);
|
276 |
|
277 |
/// Redundant method, returns the layer of lastMeasurement() .
|
278 |
const DetLayer* lastLayer() const {
|
279 |
check();
|
280 |
if (theData.back().recHit()->hit()!=0) return theData.back().layer();
|
281 |
else if (theData.size()>2) return (theData.end()-2)->layer();
|
282 |
else throw cms::Exception("TrajectoryMeasurement::lastMeasurement - Too few measurements in trajectory");
|
283 |
}
|
284 |
|
285 |
/** return the Reference to the trajectory seed in the original
|
286 |
* seeds collection. If the collection has been dropped from the
|
287 |
* Event, the reference may be invalid. Its validity should be tested,
|
288 |
* before the reference is actually used.
|
289 |
*/
|
290 |
edm::RefToBase<TrajectorySeed> seedRef(void) const { return seedRef_; }
|
291 |
|
292 |
void setSeedRef(const edm::RefToBase<TrajectorySeed> & seedRef) { seedRef_ = seedRef ; }
|
293 |
|
294 |
TrajectoryStateOnSurface geometricalInnermostState() const;
|
295 |
|
296 |
TrajectoryMeasurement const & closestMeasurement(GlobalPoint) const;
|
297 |
|
298 |
/// Reverse the propagation direction and the order of the trajectory measurements.
|
299 |
/// It doesn't reverse the forward and backward predicted states within each trajectory measurement
|
300 |
void reverse() ;
|
301 |
|
302 |
const boost::shared_ptr<const TrajectorySeed> & sharedSeed() const { return theSeed; }
|
303 |
private:
|
304 |
|
305 |
boost::shared_ptr<const TrajectorySeed> theSeed;
|
306 |
edm::RefToBase<TrajectorySeed> seedRef_;
|
307 |
|
308 |
DataContainer theData;
|
309 |
float theChiSquared;
|
310 |
float theChiSquaredBad;
|
311 |
|
312 |
signed short theNumberOfFoundHits;
|
313 |
signed short theNumberOfLostHits;
|
314 |
|
315 |
PropagationDirection theDirection;
|
316 |
bool theDirectionValidity;
|
317 |
bool theValid;
|
318 |
|
319 |
void check() const;
|
320 |
};
|
321 |
|
322 |
#endif
|