Belle II Software  release-06-02-00
AlignableCDCRecoHit.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 <alignment/reconstruction/AlignableCDCRecoHit.h>
10 
11 #include <alignment/GlobalLabel.h>
12 #include <alignment/GlobalDerivatives.h>
13 #include <cdc/dataobjects/WireID.h>
14 #include <cdc/dbobjects/CDCTimeZeros.h>
15 #include <cdc/dbobjects/CDCTimeWalks.h>
16 #include <cdc/geometry/CDCGeometryPar.h>
17 #include "Math/ChebyshevPol.h"
18 
19 using namespace std;
20 using namespace Belle2;
21 using namespace CDC;
22 using namespace alignment;
23 
24 bool AlignableCDCRecoHit::s_enableTrackT0LocalDerivative = true;
25 bool AlignableCDCRecoHit::s_enableWireSaggingGlobalDerivative = false;
26 bool AlignableCDCRecoHit::s_enableWireByWireAlignmentGlobalDerivatives = false;
27 
28 std::pair<std::vector<int>, TMatrixD> AlignableCDCRecoHit::globalDerivatives(const genfit::StateOnPlane* sop)
29 {
30  GlobalDerivatives globals;
31  unsigned short LR = (int(m_leftRight) > 0.) ? 1 : 0;
32 
33  const TVector3& mom = sop->getMom();
34  const TVector3& wirePositon = sop->getPlane()->getO();
35  const unsigned short layer = getWireID().getICLayer();
36 
37  CDCGeometryPar& cdcgeo = CDCGeometryPar::Instance();
38  double alpha = cdcgeo.getAlpha(wirePositon, mom);
39  double theta = cdcgeo.getTheta(mom);
40  const TVectorD& stateOnPlane = sop->getState();
41  const double driftLengthEstimate = std::abs(stateOnPlane(3));
42  const double driftTime = cdcgeo.getDriftTime(driftLengthEstimate, layer, LR, alpha, theta);
43  const double driftVelocity = cdcgeo.getDriftV(driftTime, layer, LR, alpha, theta);
44 
45  // CDC Calibration -------------------------------------------------
46 
47  // Time zero calibration (per wire)
48  if (driftTime > 20 && driftTime < 200 && fabs(driftVelocity) < 1.0e-2) {
49  globals.add(
50  GlobalLabel::construct<CDCTimeZeros>(getWireID(), 0),
51  driftVelocity * double(int(m_leftRight))
52  );
53  }
54 
55  // Time walk calibration (per board)
56  if (driftTime > 20 && driftTime < 200 && fabs(driftVelocity) < 1.0e-2 && m_adcCount < 400 && m_adcCount > 2) {
58  unsigned short board = CDCGeometryPar::Instance().getBoardID(getWireID());
59  const std::vector<float> param = tws->getTimeWalkParams(board);
60  globals.add(
61  GlobalLabel::construct<CDCTimeWalks>(board, 0),
62  -driftVelocity * exp(-param[1]* m_adcCount) * double(int(m_leftRight))
63  );
64  globals.add(
65  GlobalLabel::construct<CDCTimeWalks>(board, 1),
66  driftVelocity * m_adcCount * param[0]*exp(-param[1]* m_adcCount) * double(int(m_leftRight))
67  );
68  }
69 
70  // Space time relations calibration
71  if (driftTime > 20 && driftTime < 500 && fabs(driftVelocity) < 1.0e-2) {
72  // TODO: ugly to need to ask XTRelations for something here...
73  // Can't I get this CDCGeometryPar or sth. like this?
74 
75  theta = cdcgeo.getOutgoingTheta(alpha, theta);
76  alpha = cdcgeo.getOutgoingAlpha(alpha);
78  auto xtid = xts->getXtID(getWireID().getICLayer(), LR, (float)alpha, (float)theta);
79  const auto& par = xts->getXtParams(xtid);
80  auto boundary = par.at(6);
81  if (driftTime < boundary) {
82  globals.add(
83  GlobalLabel::construct<CDCXtRelations>(xtid, 0),
84  ROOT::Math::Chebyshev5(driftTime, 1, 0, 0, 0, 0, 0) * double(int(m_leftRight))
85  );
86  globals.add(
87  GlobalLabel::construct<CDCXtRelations>(xtid, 1),
88  ROOT::Math::Chebyshev5(driftTime, 0, 1, 0, 0, 0, 0) * double(int(m_leftRight))
89  );
90  globals.add(
91  GlobalLabel::construct<CDCXtRelations>(xtid, 2),
92  ROOT::Math::Chebyshev5(driftTime, 0, 0, 1, 0, 0, 0) * double(int(m_leftRight))
93  );
94  globals.add(
95  GlobalLabel::construct<CDCXtRelations>(xtid, 3),
96  ROOT::Math::Chebyshev5(driftTime, 0, 0, 0, 1, 0, 0) * double(int(m_leftRight))
97  );
98  globals.add(
99  GlobalLabel::construct<CDCXtRelations>(xtid, 4),
100  ROOT::Math::Chebyshev5(driftTime, 0, 0, 0, 0, 1, 0) * double(int(m_leftRight))
101  );
102  globals.add(
103  GlobalLabel::construct<CDCXtRelations>(xtid, 5),
104  ROOT::Math::Chebyshev5(driftTime, 0, 0, 0, 0, 0, 1) * double(int(m_leftRight))
105  );
106  } else {
107  globals.add(
108  GlobalLabel::construct<CDCXtRelations>(xtid, 7),
109  double(int(m_leftRight))
110  );
111  globals.add(
112  GlobalLabel::construct<CDCXtRelations>(xtid, 8),
113  (driftTime - boundary) * double(int(m_leftRight))
114  );
115  }
116  }
117 
118 
119  // CDC Alignment ---------------------------------------------------
120 
121  auto tdir = sop->getDir();
122  auto ndir = sop->getPlane()->getNormal();
123  auto udir = sop->getPlane()->getU();
124  auto vdir = sop->getPlane()->getV();
125  auto pos = sop->getPos();
126 
127  auto tn = tdir[0] * ndir[0] + tdir[1] * ndir[1] + tdir[2] * ndir [2];
128  // d residual / d measurement
129  auto drdm = TMatrixD(3, 3);
130  drdm.UnitMatrix();
131  for (int i = 0; i < 3; ++i) {
132  for (int j = 0; j < 3; ++j) {
133  drdm(i, j) -= tdir[i] * ndir[j] / tn;
134  }
135  }
136  // d measurement / d global rigid body param
137  auto dmdg = TMatrixD(3, 6);
138  dmdg.Zero();
139  dmdg[0][0] = 1.; dmdg[0][4] = -pos[2]; dmdg[0][5] = pos[1];
140  dmdg[1][1] = 1.; dmdg[1][3] = pos[2]; dmdg[1][5] = -pos[0];
141  dmdg[2][2] = 1.; dmdg[2][3] = -pos[1]; dmdg[2][4] = pos[0];
142  // d local residual / d global residual
143  auto drldrg = TMatrixD(3, 3);
144  for (int i = 0; i < 3; ++i) {
145  drldrg(0, i) = udir[i];
146  drldrg(1, i) = vdir[i];
147  drldrg(2, i) = ndir[i];
148  }
149  // d local residual / d global rigid body param
150  auto drldg = drldrg * (drdm * dmdg);
151 
152  // wire ends
153  const double zWireM = s_cdcGeometryTranslator->getWireBackwardPosition(getWireID(), CDCGeometryPar::c_Aligned)[2];
154  const double zWireP = s_cdcGeometryTranslator->getWireForwardPosition(getWireID(), CDCGeometryPar::c_Aligned)[2];
155  // relative Z position [0..1]
156  const double zRel = std::max(0., std::min(1., (pos[2] - zWireM) / (zWireP - zWireM)));
157 
158  // Layer alignment
159  // wire 511 = no wire (0 is reserved for existing wires) - this has to be compatible with code in CDCGeometryPar::setWirPosAlignParams
160  auto layerID = WireID(getWireID().getICLayer(), 511);
161 
162  // Alignment of layer X (bwd)
163  globals.add(
164  GlobalLabel::construct<CDCAlignment>(layerID, CDCAlignment::layerX),
165  drldg(0, 0)
166  );
167 
168  // Alignment of layer Y (bwd)
169  globals.add(
170  GlobalLabel::construct<CDCAlignment>(layerID, CDCAlignment::layerY),
171  drldg(0, 1)
172  );
173 
174  // Alignment of layer rotation (gamma) (bwd)
175  globals.add(
176  GlobalLabel::construct<CDCAlignment>(layerID, CDCAlignment::layerPhi),
177  drldg(0, 5)
178  );
179 
180  // Difference between wire ends (end plates)
181  // Alignment of layer dX, dX = foward - backward endplate
182  globals.add(
183  GlobalLabel::construct<CDCAlignment>(layerID, CDCAlignment::layerDx),
184  drldg(0, 0) * zRel
185  );
186 
187  // Alignment of layer dY, dY = foward - backward endplate
188  globals.add(
189  GlobalLabel::construct<CDCAlignment>(layerID, CDCAlignment::layerDy),
190  drldg(0, 1) * zRel
191  );
192 
193  // Alignment of layer rotation difference d(gamma or phi), dPhi = foward - backward endplate
194  globals.add(
195  GlobalLabel::construct<CDCAlignment>(layerID, CDCAlignment::layerDPhi),
196  drldg(0, 5) * zRel
197  );
198 
199  //WARNING: experimental (disabled by default)
200  // Wire-by-wire alignment
201  if (s_enableWireByWireAlignmentGlobalDerivatives) {
202  // How much shift (in X or Y) on BWD wire-end will change the residual at estimated track crossing
203  // with the wire (at relative z-position on wire = zRel)
204  double zRelM = fabs(1. - zRel);
205  // Same as above but for FWD wire-end (residual at zRel = zRel * delta(X or Y at FWD wire-end)
206  double zRelP = fabs(zRel - 0.);
207 
208  // Alignment of wires X in global coords at BWD wire-end
209  globals.add(
210  GlobalLabel::construct<CDCAlignment>(getWireID().getEWire(), CDCAlignment::wireBwdX),
211  drldg(0, 0) * zRelM
212  );
213  // Alignment of wires X in global coords at FWD wire-end
214  globals.add(
215  GlobalLabel::construct<CDCAlignment>(getWireID().getEWire(), CDCAlignment::wireFwdX),
216  drldg(0, 0) * zRelP
217  );
218 
219  // Alignment of wires Y in global coords at BWD wire-end
220  globals.add(
221  GlobalLabel::construct<CDCAlignment>(getWireID().getEWire(), CDCAlignment::wireBwdY),
222  drldg(0, 1) * zRelM
223  );
224  // Alignment of wires Y in global coords at FWD wire-end
225  globals.add(
226  GlobalLabel::construct<CDCAlignment>(getWireID().getEWire(), CDCAlignment::wireFwdY),
227  drldg(0, 1) * zRelP
228  );
229  }
230 
231  //WARNING: experimental (disabled by default)
232  //TODO: missing some factors (we do not align directly the wire-sag coefficient, but
233  // wire tension ... coef = pi * ro * r * r / 8 / tension
234  //TODO: need to get these numbers from CDCGeometryPar!
235  if (s_enableWireSaggingGlobalDerivative) {
236  globals.add(
237  GlobalLabel::construct<CDCAlignment>(getWireID().getEWire(), CDCAlignment::wireTension),
238  drldg(0, 1) * 4.0 * zRel * (1.0 - zRel)
239  );
240  }
241 
242 
243 
244  return globals;
245 }
246 
247 
248 TMatrixD AlignableCDCRecoHit::localDerivatives(const genfit::StateOnPlane* sop)
249 {
250  if (!s_enableTrackT0LocalDerivative)
251  return TMatrixD();
252 
253  unsigned short LR = (int(m_leftRight) > 0.) ? 1 : 0;
254 
255  const TVector3& mom = sop->getMom();
256  const TVector3& wirePositon = sop->getPlane()->getO();
257  const unsigned short layer = getWireID().getICLayer();
258 
259  CDCGeometryPar& cdcgeo = CDCGeometryPar::Instance();
260  const double alpha = cdcgeo.getAlpha(wirePositon, mom);
261  const double theta = cdcgeo.getTheta(mom);
262  const TVectorD& stateOnPlane = sop->getState();
263  const double driftLengthEstimate = std::abs(stateOnPlane(3));
264  const double driftTime = cdcgeo.getDriftTime(driftLengthEstimate, layer, LR, alpha, theta);
265  const double driftVelocity = cdcgeo.getDriftV(driftTime, layer, LR, alpha, theta);
266 
267  TMatrixD locals(2, 1);
268  if (driftTime > 20 && driftTime < 200 && fabs(driftVelocity) < 1.0e-2) {
269  locals(0, 0) = - double(int(m_leftRight)) * driftVelocity;
270  locals(1, 0) = 0.; // insesitive coordinate along wire
271  }
272 
273  return locals;
274 }
The Class for CDC Geometry Parameters.
double getDriftV(double dt, unsigned short layer, unsigned short lr, double alpha=0., double theta=0.5 *M_PI) const
Get the realistic drift velocity.
double getAlpha(const TVector3 &posOnWire, const TVector3 &momentum) const
Returns track incident angle in rphi plane (alpha in rad.).
double getOutgoingAlpha(const double alpha) const
Converts incoming- to outgoing-alpha.
double getOutgoingTheta(const double alpha, const double theta) const
Converts incoming- to outgoing-theta.
double getTheta(const TVector3 &momentum) const
Returns track incident angle (theta in rad.).
double getDriftTime(double dist, unsigned short layer, unsigned short lr, double alpha, double theta) const
Return the drift time to the sense wire.
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
Class to identify a wire inside the CDC.
Definition: WireID.h:34
A state with arbitrary dimension defined in a DetPlane.
Definition: StateOnPlane.h:47
Abstract base class for different kinds of events.