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