Belle II Software  release-08-01-10
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 
21 using namespace std;
22 using namespace Belle2;
23 using namespace CDC;
24 
25 std::unique_ptr<ADCCountTranslatorBase> CDCRecoHit::s_adcCountTranslator = 0;
26 std::unique_ptr<CDCGeometryTranslatorBase> CDCRecoHit::s_cdcGeometryTranslator = 0;
27 std::unique_ptr<TDCCountTranslatorBase> CDCRecoHit::s_tdcCountTranslator = 0;
28 bool CDCRecoHit::s_useTrackTime = false;
29 //temp4cosmics
30 bool CDCRecoHit::s_cosmics = false;
31 
32 
33 void CDCRecoHit::setTranslators(ADCCountTranslatorBase* const adcCountTranslator,
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 
47 CDCRecoHit::CDCRecoHit()
48  : genfit::AbsMeasurement(1),
49  m_tdcCount(0), m_adcCount(0), m_wireID(WireID()), m_cdcHit(nullptr), m_leftRight(0)
50 {
51 }
52 
53 CDCRecoHit::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));
70  setLeftRightResolution(lrInfo);
71  }
72 }
73 
75 {
76  return new CDCRecoHit(*this);
77 }
78 
79 
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 
140 std::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 
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 
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 }
B2Vector3< DataType > Cross(const B2Vector3< DataType > &p) const
Cross product.
Definition: B2Vector3.h:296
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
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 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
This class collects all information needed and produced by a specific AbsFitter and is specific to on...
Definition: AbsFitterInfo.h:42
Abstract base class for a track representation.
Definition: AbsTrackRep.h:66
virtual double extrapolateToLine(StateOnPlane &state, const TVector3 &linePoint, const TVector3 &lineDirection, bool stopAtBoundary=false, bool calcJacobianNoise=false) const =0
Extrapolates the state to the POCA to a line, and returns the extrapolation length and,...
virtual TVector3 getMom(const StateOnPlane &state) const =0
Get the cartesian momentum vector of a state.
virtual TVector3 getPos(const StateOnPlane &state) const =0
Get the cartesian position of a state.
Detector plane.
Definition: DetPlane.h:59
Exception class for error handling in GENFIT (provides storage for diagnostic information)
Definition: Exception.h:48
AbsHMatrix implementation for one-dimensional MeasurementOnPlane and RKTrackRep parameterization.
Definition: HMatrixU.h:37
#StateOnPlane with additional covariance matrix.
Measured coordinates on a plane.
AbsTrackRep with 5D track parameterization in plane coordinates: (q/p, u', v', u, v)
Definition: RKTrackRep.h:72
A state with arbitrary dimension defined in a DetPlane.
Definition: StateOnPlane.h:47
Hit object for use in TrackCand.
Definition: TrackCandHit.h:34
Object containing AbsMeasurement and AbsFitterInfo objects.
Definition: TrackPoint.h:46
AbsFitterInfo * getFitterInfo(const AbsTrackRep *rep=nullptr) const
Get fitterInfo for rep. Per default, use cardinal rep.
Definition: TrackPoint.cc:170
Hit object for use in TrackCand.
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.
Defines for I/O streams used for error and debug printing.
std::shared_ptr< genfit::DetPlane > SharedPlanePtr
Shared Pointer to a DetPlane.