Belle II Software development
CDCRecoHit.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <cdc/dataobjects/CDCRecoHit.h>
10#include <framework/utilities/MathHelpers.h>
11
12//Comment out the following line since it introduces dependence on cdclib (or circular dependence betw. cdc_objects and cdclib).
13//#include <cdc/geometry/CDCGeometryPar.h>
14#include <genfit/WireTrackCandHit.h>
15#include <genfit/AbsTrackRep.h>
16#include <genfit/RKTrackRep.h>
17#include <genfit/TrackPoint.h>
18#include <genfit/AbsFitterInfo.h>
19#include <genfit/Exception.h>
20#include <genfit/HMatrixU.h>
21
22using namespace std;
23using namespace Belle2;
24using namespace CDC;
25
26std::unique_ptr<ADCCountTranslatorBase> CDCRecoHit::s_adcCountTranslator = 0;
27std::unique_ptr<CDCGeometryTranslatorBase> CDCRecoHit::s_cdcGeometryTranslator = 0;
28std::unique_ptr<TDCCountTranslatorBase> CDCRecoHit::s_tdcCountTranslator = 0;
30//temp4cosmics
31bool CDCRecoHit::s_cosmics = false;
32
33
35 CDCGeometryTranslatorBase* const cdcGeometryTranslator,
36 TDCCountTranslatorBase* const tdcCountTranslator,
37 //temp4cosmics bool useTrackTime)
38 bool useTrackTime, bool cosmics)
39{
40 s_adcCountTranslator.reset(adcCountTranslator);
41 s_cdcGeometryTranslator.reset(cdcGeometryTranslator);
42 s_tdcCountTranslator.reset(tdcCountTranslator);
43 s_useTrackTime = useTrackTime;
44 //temp4cosmics
45 s_cosmics = cosmics;
46}
47
49 : genfit::AbsMeasurement(1),
51{
52}
53
54CDCRecoHit::CDCRecoHit(const CDCHit* cdcHit, const genfit::TrackCandHit* trackCandHit)
55 : genfit::AbsMeasurement(1), m_cdcHit(cdcHit), m_leftRight(0)
56{
58 B2FATAL("Can't produce CDCRecoHits without setting of the translators.");
59 }
60
61 // get information from cdcHit into local variables.
62 m_wireID = cdcHit->getID();
63 m_tdcCount = cdcHit->getTDCCount();
64 m_adcCount = cdcHit->getADCCount();
65
66 // set l-r info
67 const genfit::WireTrackCandHit* aTrackCandHitPtr = dynamic_cast<const genfit::WireTrackCandHit*>(trackCandHit);
68 if (aTrackCandHitPtr) {
69 signed char lrInfo = aTrackCandHitPtr->getLeftRightResolution();
70 B2DEBUG(250, "l/r: " << int(lrInfo));
72 }
73}
74
76{
77 return new CDCRecoHit(*this);
78}
79
80
81genfit::SharedPlanePtr CDCRecoHit::constructPlane(const genfit::StateOnPlane& state) const
82{
83 // We find the plane in two steps: first we neglect wire sag to get
84 // a good estimate of the z coordinate of the crossing. Then we use
85 // this z coordinate to find the point of closest approach to the
86 // sagging wire and its local direction.
87
88 // Don't use clone: we don't want to extrapolate covariances if
89 // state is a genfit::MeasuredStateOnPlane.
90 genfit::StateOnPlane st(state);
91
92 const B2Vector3D& noSagWire1(s_cdcGeometryTranslator->getWireBackwardPosition(m_wireID));
93 const B2Vector3D& noSagWire2(s_cdcGeometryTranslator->getWireForwardPosition(m_wireID));
94
95 // unit vector along the wire
96 B2Vector3D noSagWireDirection = noSagWire2 - noSagWire1;
97 noSagWireDirection.SetMag(1.);
98
99 // point of closest approach
100 const genfit::AbsTrackRep* rep = state.getRep();
101 rep->extrapolateToLine(st, noSagWire1, noSagWireDirection);
102 const B2Vector3D& noSagPoca = rep->getPos(st);
103
104 double zPOCA = (noSagWire1.Z()
105 + noSagWireDirection.Dot(noSagPoca - noSagWire1) * noSagWireDirection.Z());
106
107 // Now re-extrapolate taking Z of trajectory into account.
108 const B2Vector3D& wire1(s_cdcGeometryTranslator->getWireBackwardPosition(m_wireID, zPOCA));
109 const B2Vector3D& wire2(s_cdcGeometryTranslator->getWireForwardPosition(m_wireID, zPOCA));
110
111 // unit vector along the wire (will become V of plane)
112 B2Vector3D wireDirection = wire2 - wire1;
113 wireDirection.SetMag(1.);
114
115 // point of closest approach
116 rep->extrapolateToLine(st, wire1, wireDirection);
117 const B2Vector3D& poca = rep->getPos(st);
118 B2Vector3D dirInPoca = rep->getMom(st);
119 dirInPoca.SetMag(1.);
120 const B2Vector3D& pocaOnWire = wire1 + wireDirection.Dot(poca - wire1) * wireDirection;
121 //temp
122 // std::cout << (noSagWire1 + noSagWireDirection.Dot(noSagPoca - noSagWire1) * noSagWireDirection).Y() <<" "<< pocaOnWire.Y() <<" " << (noSagWire1 + noSagWireDirection.Dot(noSagPoca - noSagWire1) * noSagWireDirection - pocaOnWire).Y() << std::endl;
123 // std::cout << (noSagWire1 + noSagWireDirection.Dot(noSagPoca - noSagWire1) * noSagWireDirection).Perp() <<" "<< pocaOnWire.Perp() << std::endl;
124 // std::cout << (noSagWire1 + noSagWireDirection.Dot(noSagPoca - noSagWire1) * noSagWireDirection).Z() <<" "<< pocaOnWire.Z() << std::endl;
125
126 // check if direction is parallel to wire
127 if (fabs(wireDirection.Angle(dirInPoca)) < 0.01) {
128 genfit::Exception exc("CDCRecoHit::constructPlane(): Cannot construct detector plane, direction is parallel to wire", __LINE__,
129 __FILE__);
130 throw exc;
131 }
132
133 // construct orthogonal (unit) vector
134 const B2Vector3D& U = wireDirection.Cross(dirInPoca);
135
136 genfit::SharedPlanePtr pl = genfit::SharedPlanePtr(new genfit::DetPlane(pocaOnWire, U, wireDirection));
137 //pl->Print();
138 return pl;
139}
140
141std::vector<genfit::MeasurementOnPlane*> CDCRecoHit::constructMeasurementsOnPlane(const genfit::StateOnPlane& state) const
142{
143 double z = state.getPos().Z();
144 const B2Vector3D& p = state.getMom();
145 // Calculate alpha and theta. A description was given in
146 // https://indico.mpp.mpg.de/getFile.py/access?contribId=5&sessionId=3&resId=0&materialId=slides&confId=3195
147
148//Comment out the following 2 lines since they introduce dependence on cdclib (or circular dependence betw. cdc_objects and cdclib).
149// double alpha = CDCGeometryPar::Instance().getAlpha(state.getPlane()->getO(), p);
150// double theta = CDCGeometryPar::Instance().getTheta(p);
151
152//N.B. The following 8 lines are tentative to avoid the circular dependence mentioned above ! The definitions of alpha and theta should be identical to those defined in CDCGeometryPar.
153 const double wx = state.getPlane()->getO().X();
154 const double wy = state.getPlane()->getO().Y();
155 const double px = p.X();
156 const double py = p.Y();
157 const double cross = wx * py - wy * px;
158 const double dot = wx * px + wy * py;
159 double alpha = atan2(cross, dot);
160 double theta = atan2(p.Perp(), p.Z());
161 /*
162 double alpha0 = CDCGeometryPar::Instance().getAlpha(state.getPlane()->getO(), p);
163 double theta0 = CDCGeometryPar::Instance().getTheta(p);
164 if (alpha != alpha0) {
165 std::cout <<"alpha,alpha0= " << alpha <<" "<< alpha0 << std::endl;
166 exit(-1);
167 }
168 if (theta != theta0) {;
169 std::cout <<"theta,theta0= " << theta <<" "<< theta0 << std::endl;
170 exit(-2);
171 }
172 */
173
174 double trackTime = s_useTrackTime ? state.getTime() : 0;
175 //temp4cosmics
176 // std::cout <<"phi,trackTime= " << atan2(py,px) <<" "<< trackTime << std::endl;
177 if (s_cosmics) {
178 if (atan2(py, px) > 0.) {
179 // if (atan2(wy,wx) > 0.) {
180 trackTime *= -1.;
181 }
182 }
183
184 // The meaning of the left / right flag (called
185 // 'ambiguityDiscriminator' in TDCCounTranslatorBase) is inferred
186 // from CDCGeometryPar::getNewLeftRightRaw().
187 double mL = s_tdcCountTranslator->getDriftLength(m_tdcCount, m_wireID, trackTime,
188 false, //left
189 z, alpha, theta, m_adcCount);
190 double mR = s_tdcCountTranslator->getDriftLength(m_tdcCount, m_wireID, trackTime,
191 true, //right
192 z, alpha, theta, m_adcCount);
193 double VL = s_tdcCountTranslator->getDriftLengthResolution(mL, m_wireID,
194 false, //left
195 z, alpha, theta);
196 double VR = s_tdcCountTranslator->getDriftLengthResolution(mR, m_wireID,
197 true, //right
198 z, alpha, theta);
199
200 // static to avoid constructing these over and over.
201 static TVectorD m(1);
202 static TMatrixDSym cov(1);
203
204 m(0) = mR;
205 cov(0, 0) = VR;
206 auto mopR = new genfit::MeasurementOnPlane(m, cov, state.getPlane(), state.getRep(),
207 constructHMatrix(state.getRep()));
208 m(0) = -mL; // Convert from unsigned drift length to signed coordinate.
209 cov(0, 0) = VL;
210 auto mopL = new genfit::MeasurementOnPlane(m, cov, state.getPlane(), state.getRep(),
211 constructHMatrix(state.getRep()));
212
213 // set left/right weights
214 if (m_leftRight < 0) {
215 mopL->setWeight(1);
216 mopR->setWeight(0);
217 } else if (m_leftRight > 0) {
218 mopL->setWeight(0);
219 mopR->setWeight(1);
220 } else {
221 // In absence of L/R information set equal weight for mirror hits.
222 // We have this weight decrease as the drift distance increases.
223 // Since the average will always be close to the wire, the bias
224 // introduced by the averaged hit would increase as the drift
225 // radius increases. Reducing the initial weight effectively
226 // counteracts this. This way the DAF can figure the ambiguities
227 // out quickly.
228 //
229 // Wire spacing in the radial direction according to TDR is 10 mm
230 // in the innermost superlayer, 18 mm otherwise. Use these values
231 // times a safety margin of 1.5 as upper bound for the drift
232 // radii. The max distance between the mirror hits is twice the
233 // maximal drift radius.
234 double rMax = 1.5 * (m_wireID.getISuperLayer() == 0 ? 1. : 1.8);
235 double weight = 0.5 * square(std::max(0., 1 - (mR + mL) / 2 / rMax));
236 mopL->setWeight(weight);
237 mopR->setWeight(weight);
238 }
239
240 // Ignore hits with negative drift times. For these, the
241 // TDCCountTranslator returns a negative drift length.
242 if (mL < 0. || mR < 0.) {
243 B2DEBUG(150, "Ignoring hit with negative drift time.");
244 mopL->setWeight(0);
245 mopR->setWeight(0);
246 }
247
248 return {mopL, mopR};
249}
250
251
252const genfit::HMatrixU* CDCRecoHit::constructHMatrix(const genfit::AbsTrackRep* rep) const
253{
254 if (!dynamic_cast<const genfit::RKTrackRep*>(rep)) {
255 B2FATAL("CDCRecoHit can only handle state vectors of type RKTrackRep!");
256 }
257
258 return new genfit::HMatrixU();
259}
260
261
262std::vector<double> CDCRecoHit::timeDerivativesMeasurementsOnPlane(const genfit::StateOnPlane& state) const
263{
264 double z = state.getPos().Z();
265 const B2Vector3D& p = state.getMom();
266 // Calculate alpha and theta. A description was given by in
267 // https://indico.mpp.mpg.de/getFile.py/access?contribId=5&sessionId=3&resId=0&materialId=slides&confId=3195
268
269//Comment out the following 2 lines since they introduce dependence on cdclib (or circular dependence betw. cdc_objects and cdclib).
270// double alpha = CDCGeometryPar::Instance().getAlpha(state.getPlane()->getO(), p);
271// double theta = CDCGeometryPar::Instance().getTheta(p);
272
273//N.B. The following 8 lines are tentative to avoid the circular dependence mentioned above ! The definitions of alpha and theta should be identical to those defined in CDCGeometryPar.
274 const double wx = state.getPlane()->getO().X();
275 const double wy = state.getPlane()->getO().Y();
276 const double px = p.X();
277 const double py = p.Y();
278 const double cross = wx * py - wy * px;
279 const double dot = wx * px + wy * py;
280 double alpha = atan2(cross, dot);
281 double theta = atan2(p.Perp(), p.Z());
282 /*
283 double alpha0 = CDCGeometryPar::Instance().getAlpha(state.getPlane()->getO(), p);
284 double theta0 = CDCGeometryPar::Instance().getTheta(p);
285 if (alpha != alpha0) {
286 std::cout <<"alpha,alpha0= " << alpha <<" "<< alpha0 << std::endl;
287 exit(-1);
288 }
289 if (theta != theta0) {;
290 std::cout <<"theta,theta0= " << theta <<" "<< theta0 << std::endl;
291 exit(-2);
292 }
293 */
294
295 double trackTime = s_useTrackTime ? state.getTime() : 0;
296
297 // The meaning of the left / right flag (called
298 // 'ambiguityDiscriminator' in TDCCounTranslatorBase) is inferred
299 // from CDCGeometryPar::getNewLeftRightRaw().
300 auto fL = [&](const double & t) -> double {
301 return s_tdcCountTranslator->getDriftLength(m_tdcCount, m_wireID, t,
302 false, //left
303 z, alpha, theta, m_adcCount); };
304 auto fR = [&](const double & t) -> double {
305 return s_tdcCountTranslator->getDriftLength(m_tdcCount, m_wireID, t,
306 true, //right
307 z, alpha, theta, m_adcCount); };
308
309 // Calculate derivative for all left and right mirror hit.
310 //
311 // It's a polynomial, but let's not meddle with the innard of the
312 // CDC code for now.
313 //
314 // The algorithm follows the one in TF1::Derivative() :
315 // df(x) = (4 D(h/2) - D(h)) / 3
316 // with D(h) = (f(x + h) - f(x - h)) / (2 h).
317 double rightShort[2], rightFull[2];
318 double leftShort[2], leftFull[2];
319 const double defaultStepT = 1e-3 * trackTime;
320 double stepT;
321 {
322 double temp = trackTime + defaultStepT / 2;
323 // Find the actual size of the step, which will differ from
324 // defaultStepX due to roundoff. This is the step-size we will
325 // use for this direction. Idea taken from Numerical Recipes,
326 // 3rd ed., section 5.7.
327 //
328 // Note that if a number is exactly representable, it's double
329 // will also be exact. Outside denormals, this also holds for
330 // halving. Unless the exponent changes (which it only will in
331 // the vicinity of zero) adding or subtracing doesn't make a
332 // difference.
333 //
334 // We determine the roundoff error for the half-step. If this
335 // is exactly representable, the full step will also be.
336 stepT = 2 * (temp - trackTime);
337
338 rightShort[0] = fL(trackTime + .5 * stepT);
339 rightShort[1] = fR(trackTime + .5 * stepT);
340 }
341 {
342 leftShort[0] = fL(trackTime - .5 * stepT);
343 leftShort[1] = fR(trackTime - .5 * stepT);
344 }
345 {
346 rightFull[0] = fL(trackTime + stepT);
347 rightFull[1] = fR(trackTime + stepT);
348 }
349 {
350 leftFull[0] = fL(trackTime - stepT);
351 leftFull[1] = fR(trackTime - stepT);
352 }
353
354 // Calculate the derivatives for the individual components of
355 // the track parameters.
356 double derivFull[2];
357 double derivShort[2];
358 for (size_t j = 0; j < 2; ++j) {
359 derivFull[j] = (rightFull[j] - leftFull[j]) / (2.*stepT);
360 derivShort[j] = (rightShort[j] - leftShort[j]) / stepT;
361 }
362 //std::cout << rightShort[0] << " " << derivShort[0] << " " << trackTime << std::endl;
363 return { +(4.*derivShort[0] - derivFull[0]) / 3.,
364 -(4.*derivShort[1] - derivFull[1]) / 3.};
365}
366
367
368
370 B2Vector3D& trackDir,
371 const genfit::AbsTrackRep* rep,
372 bool usePlaneFromFit)
373{
374 const genfit::TrackPoint* tp = this->getTrackPoint();
375 if (!tp) {
376 B2ERROR("No genfit::TrackPoint for CDCRecoHit.");
377 return false;
378 }
379 const genfit::AbsFitterInfo* fi = tp->getFitterInfo(rep);
380 if (!fi) {
381 B2DEBUG(200, "No genfit::AbsFitterInfo for this CDCRecoHit.");
382 return false;
383 }
384
385 const genfit::MeasuredStateOnPlane& mop = fi->getFittedState();
386 B2Vector3D fittedPoca = mop.getPos();
387 // constructPlane places the coordinate center in the POCA to the
388 // wire. Using this is the default behavior. If this should be too
389 // slow, as it has to re-evaluate the POCA, alternatively the user
390 // can set usePlaneFromFit which uses the plane determined by the
391 // track fit.
392 B2Vector3D pocaOnWire = (usePlaneFromFit
393 ? mop.getPlane()->getO()
394 : this->constructPlane(mop)->getO());
395
396 // The vector from the wire to the track.
397 pointingVector = fittedPoca - pocaOnWire;
398
399 trackDir = mop.getMom();
400 trackDir.SetMag(1.);
401 return true;
402}
void SetMag(DataType mag)
Set magnitude keeping theta and phi constant.
Definition B2Vector3.h:182
DataType Z() const
access variable Z (= .at(2) without boundary check)
Definition B2Vector3.h:435
B2Vector3< DataType > Cross(const B2Vector3< DataType > &p) const
Cross product.
Definition B2Vector3.h:296
DataType Dot(const B2Vector3< DataType > &p) const
Scalar product.
Definition B2Vector3.h:290
DataType Angle(const B2Vector3< DataType > &q) const
The angle w.r.t.
Definition B2Vector3.h:302
Class containing the result of the unpacker in raw data and the result of the digitizer in simulation...
Definition CDCHit.h:40
short getTDCCount() const
Getter for TDC count.
Definition CDCHit.h:219
unsigned short getID() const
Getter for encoded wire number.
Definition CDCHit.h:193
unsigned short getADCCount() const
Getter for integrated charge.
Definition CDCHit.h:230
signed char m_leftRight
Flag showing left/right passage.
Definition CDCRecoHit.h:153
const CDCHit * m_cdcHit
Pointer to the CDCHit used to created this CDCRecoHit.
Definition CDCRecoHit.h:144
std::vector< genfit::MeasurementOnPlane * > constructMeasurementsOnPlane(const genfit::StateOnPlane &state) const override
build MeasurementsOnPlane
static void setTranslators(CDC::ADCCountTranslatorBase *const adcCountTranslator, CDC::CDCGeometryTranslatorBase *const cdcGeometryTranslator, CDC::TDCCountTranslatorBase *const tdcCountTranslator, bool useTrackTime=false, bool cosmics=false)
Setter for the Translators.
Definition CDCRecoHit.cc:34
static std::unique_ptr< CDC::ADCCountTranslatorBase > s_adcCountTranslator
Object for ADC Count translation.
Definition CDCRecoHit.h:120
unsigned short m_tdcCount
TDC Count as out of CDCHit.
Definition CDCRecoHit.h:147
static bool s_cosmics
Switch to use cosmic events, or physics events from IP.
Definition CDCRecoHit.h:136
unsigned short m_adcCount
ADC Count as out of CDCHit.
Definition CDCRecoHit.h:150
static bool s_useTrackTime
Whether to use the track time or not when building the measurementOnPlane.
Definition CDCRecoHit.h:131
bool getFlyByDistanceVector(B2Vector3D &pointingVector, B2Vector3D &trackDir, const genfit::AbsTrackRep *rep=nullptr, bool usePlaneFromFit=false)
Get the vector pointing from the wire to the fitted trajectory as well as the direction of the track ...
static std::unique_ptr< CDC::TDCCountTranslatorBase > s_tdcCountTranslator
Object for getting drift-length and -resolution.
Definition CDCRecoHit.h:126
std::vector< double > timeDerivativesMeasurementsOnPlane(const genfit::StateOnPlane &state) const
Get the time derivative of the MesuredStateOnPlane (derived from the track fit).
virtual const genfit::HMatrixU * constructHMatrix(const genfit::AbsTrackRep *) const override
construct error matrix
WireID m_wireID
Wire Identifier.
Definition CDCRecoHit.h:141
genfit::SharedPlanePtr constructPlane(const genfit::StateOnPlane &state) const override
Methods that actually interface to Genfit.
Definition CDCRecoHit.cc:81
void setLeftRightResolution(int lr)
select how to resolve the left/right ambiguity: -1: negative (left) side on vector (wire direction) x...
Definition CDCRecoHit.h:100
CDCRecoHit()
Default Constructor for ROOT IO.
Definition CDCRecoHit.cc:48
CDCRecoHit * clone() const override
Creating a copy of this hit.
Definition CDCRecoHit.cc:75
static std::unique_ptr< CDC::CDCGeometryTranslatorBase > s_cdcGeometryTranslator
Object for geometry translation.
Definition CDCRecoHit.h:123
Abstract Base class for the ADC count translator.
Abstract Base class for the geometry translator.
Base class for translation of Drift Time into Drift Length.
Class to identify a wire inside the CDC.
Definition WireID.h:34
constexpr T square(const T &x)
Calculate the square of the input.
Definition MathHelpers.h:21
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition B2Vector3.h:516
T dot(GeneralVector< T > a, GeneralVector< T > b)
dot product of two general vectors
Abstract base class for different kinds of events.
STL namespace.