MyMarlinTPC  170316
GeneralBrokenLineInterfaceHelpers.cc
Go to the documentation of this file.
1 #ifdef USE_GBL
2 
4 
5 #include <iostream>
6 #include <string>
7 
8 // include what you need from lcio
9 #include <EVENT/LCEvent.h>
10 #include <IMPL/LCCollectionVec.h>
11 #include <EVENT/Track.h>
12 #include <EVENT/TrackerHit.h>
13 #include <EVENT/TrackerPulse.h>
14 
15 #include "IMPL/TrackImpl.h"
16 #include "IMPL/LCFlagImpl.h"
17 #include <Exceptions.h>
18 #include <UTIL/BitField64.h>
19 #include <UTIL/ILDConf.h>
20 
21 #include "marlin/Global.h"
22 
23 // GEAR
24 #include "GEAR.h"
25 #include <gear/TPCParameters.h>
26 #include <gear/TPCModule.h>
27 //#include <gear/BField.h>
28 #include <gearimpl/Vector3D.h>
29 
30 // the gbl includes
31 #include "GblPoint.h"
32 
33 // cr: needed for accessing the magnetic field
34 #include "GlobalFieldProcessor.h"
35 #include "CLHEP/Vector/ThreeVector.h"
36 
37 //#include "TMath.h"
38 
39 using namespace lcio;
40 using namespace marlin;
41 using namespace std;
42 using namespace gear;
43 
44 namespace marlintpc {
45 
47 
55 gblHelperHit::gblHelperHit(const EVENT::TrackerHit& aHit, const simpleHelix& refHelix, const bool milleOut, const bool enMID,
56  const int milleCalcMethod, const double phiSeed) :
57  _isMeas(true), _hitPhi(_calcLocalPhi(aHit, enMID, phiSeed)), _isValid(
58  refHelix.getExpectedPlanePos(aHit.getPosition(), _hitPhi + 0.5 * M_PI, _xyPred, _zPred, _s, _seedPhi, _seedLambda)), _eScaled(
59  _calcEScaled(aHit)), _l2M(_getL2M()), _res(_getRes()), _prec(_getPrec(aHit.getCovMatrix())), _numGlobals(0), _globalLab(), _globalDer() {
60  // needs only to be done if _writeMillepedeOut is true
61  if (milleOut) {
62  TVectorD dir(3);
63  dir[0] = cos(_seedPhi) * cos(_seedLambda);
64  dir[1] = sin(_seedPhi) * cos(_seedLambda);
65  dir[2] = sin(_seedLambda);
66  // calculate global derivatives
67 // std::cout<< "_seedPhi=" << _seedPhi <<std::endl;
68 // std::cout<< "_hitPhi=" << _hitPhi <<std::endl;
69 // std::cout<< "_seedPhi-_hitPhi=" << _seedPhi-_hitPhi <<std::endl;
70 
72  switch (milleCalcMethod) {
73  case 0:
74  calc.calcModuleAlignment(aHit, dir);
75  break;
76  case 1:
77  calc.calcTrackDistortions(aHit);
78  break;
79  case 2:
80  calc.calcHitCharge(aHit);
81  break;
82  case 3:
83  calc.calcDr(aHit, _seedPhi - _hitPhi);
84  break;
85  default:
86  calc.calcModuleAlignment(aHit, dir);
87  break;
88  }
89  _numGlobals = calc.getNumGlobals();
90  _globalLab = calc.getGlobalLabels();
91  _globalDer.ResizeTo(2, _numGlobals);
93  }
94 }
95 
97 
100 gblHelperHit::gblHelperHit(const double phi) :
101  _isMeas(false) {
102  _s = 0.;
103  _seedPhi = phi;
104  _isValid = true;
105 }
106 
108 
112  TMatrixD projectLocalToMeasurement(2, 2);
113  // Inverse (Pu = du/dm) is easy
114  projectLocalToMeasurement[0][0] = cos(_hitPhi - _seedPhi);
115  projectLocalToMeasurement[0][1] = 0.;
116  projectLocalToMeasurement[1][0] = sin(_hitPhi - _seedPhi) * sin(_seedLambda);
117  projectLocalToMeasurement[1][1] = cos(_seedLambda);
118  // Invert
119  projectLocalToMeasurement.Invert();
120  //cout << " proL2M " << endl;
121  //projectLocalToMeasurement.Print();
122 
123  return projectLocalToMeasurement;
124 }
125 
127 
130 TMatrixDSym gblHelperHit::_getPrec(FloatVec covMatrix) {
131  TMatrixDSym precision(2);
132  const double cosPhi = cos(_hitPhi);
133  const double sinPhi = sin(_hitPhi);
134  const double varRad = cosPhi * cosPhi * covMatrix[0] + 2. * sinPhi * cosPhi * covMatrix[1] + sinPhi * sinPhi * covMatrix[2];
135  const double varPhi = sinPhi * sinPhi * covMatrix[0] - 2. * sinPhi * cosPhi * covMatrix[1] + cosPhi * cosPhi * covMatrix[2];
136  const double varZ = covMatrix[5];
137  const double derXY = tan(_seedPhi - _hitPhi);
138  const double derZS = tan(_seedLambda) / cos(_seedPhi - _hitPhi);
139  // covariance matrix
140  precision[0][0] = varPhi + varRad * derXY * derXY;
141  precision[0][1] = (varRad > 1.0E-6 * varPhi) ? varRad * derXY * derZS : 0.; // avoid correlations only from float precision
142  precision[1][0] = precision[0][1];
143  precision[1][1] = varZ + varRad * derZS * derZS;
144  // needs to be inverted
145  const double det = precision[0][0] * precision[1][1] - precision[0][1] * precision[1][0];
146  if (det)
147  precision.InvertFast();
148  else {
149  precision.Zero();
150  streamlog_out(ERROR) << "Singular covariance matrix" << std::endl;
151  }
152  return precision;
153 }
154 
157  TVectorD residuals(2);
158  // predictions are relative to the measurements
159  residuals[0] = -_xyPred;
160  residuals[1] = -_zPred;
161  return residuals;
162 }
163 
165 
170 double gblHelperHit::_calcLocalPhi(const EVENT::TrackerHit& aHit, const bool encodedModuleID, const double phiTrack) {
171  FloatVec covMatrix = aHit.getCovMatrix();
172  double phi; // radial direction
173 
174  // analyze (XY) covariance matrix
175  // std::cout << " cov-xy " << aHit.getCellID0() << ": " << covMatrix[0] << " " << covMatrix[1] << " " << covMatrix[2] << " " << covMatrix[5] << std::endl;
176  const double trace = covMatrix[0] + covMatrix[2];
177  const double det = covMatrix[0] * covMatrix[2] - covMatrix[1] * covMatrix[1];
178  // std::cout << " T,D: " << trace << " " << det << " " << 4.0*det/(trace*trace) << std::endl;
179  if (4.0 * det / (trace * trace) < 0.9999) {
180  // eigenvalues are significantly different
181  // hit direction from covariance matrix (perpendicular to measurement direction)
182  double phiCov;
183  if (4.0 * det / (trace * trace) < 0.000001) {
184  // rank of XY covariance matrix is 1, hit direction has eigenvalue/variance 0.
185  phiCov = 0.5 * atan2(-2.0 * covMatrix[1], covMatrix[2] - covMatrix[0]);
186  } else {
187  // rank of XY covariance matrix is 2, hit direction has larger eigenvalue/variance (than measurement direction)
188  phiCov = 0.5 * atan2(2.0 * covMatrix[1], covMatrix[0] - covMatrix[2]);
189  }
190  // hit direction from GEAR
191  UTIL::BitField64 encoder(lcio::ILDCellID0::encoder_string);
192  encoder.setValue(aHit.getCellID0());
193  const gear::TPCModule &module =
194  encodedModuleID ?
195  Global::GEAR->getTPCParameters().getModule(encoder[ILDCellID0::module]) :
196  Global::GEAR->getTPCParameters().getNearestModule(aHit.getPosition()[0], aHit.getPosition()[1]);
197 
198  if (module.getLocalPadLayout().getCoordinateType() == gear::PadRowLayout2D::POLAR) {
199  Vector2D correction = module.getOffset();
200  phi = atan2(aHit.getPosition()[1] - correction[1], aHit.getPosition()[0] - correction[0]);
201  // std::cout << " Polar " << phi << std::endl;
202  } else {
203  phi = module.getAngle() - 0.5 * M_PI;
204  // std::cout << " Cartesian " << phi << std::endl;
205  }
206  if (abs(phi - phiCov) > 0.00001)
207  streamlog_out(WARNING) << " Inconsistent hit direction, check hit errors, use TPCHit_FixErrors_forTracking " << std::endl;
208  } else {
209  // eigenvalues are similar
210  // std::cout << " similar eigenvalues, phiTrack " << phiTrack << std::endl;
211  phi = phiTrack; // measurement is perpendicular to track direction
212  }
213  return phi;
214 }
215 
217 
220 double gblHelperHit::_calcEScaled(const EVENT::TrackerHit& aHit) {
221  return aHit.getEDep() * fabs(cos(_hitPhi - _seedPhi) * cos(_seedLambda));
222 }
223 
225 unsigned int gblHelperHit::getNumGlobals() const {
226  return _numGlobals;
227 }
228 
230 std::vector<int> gblHelperHit::getGlobalLabels() const {
231  return _globalLab;
232 }
233 
235 const TMatrixD& gblHelperHit::getGlobalDerivatives() const {
236  return _globalDer;
237 }
238 
240 
246  _numDer(0), _globalLab(), _globalDer() {
247 // switch (calcMethod) {
248 // case 0:
249 // trackerAlcaCalculator::calcModuleAlignment(aHit, tdir);
250 // break;
251 // case 1:
252 // trackerAlcaCalculator::calcTrackDistortions(aHit);
253 // break;
254 // case 2:
255 // trackerAlcaCalculator::calcHitCharge(aHit);
256 // break;
257 // default:
258 // trackerAlcaCalculator::calcModuleAlignment(aHit, tdir);
259 // }
260 }
261 
264  return _numDer;
265 }
266 
268 std::vector<int> trackerAlcaCalculator::getGlobalLabels() const {
269  return _globalLab;
270 }
271 
274  return _globalDer;
275 }
276 
278 
281 void trackerAlcaCalculator::calcTrackDistortions(const EVENT::TrackerHit& aHit) {
282 
283  // get module and row number
284 // UTIL::BitField64 encoder(lcio::ILDCellID0::encoder_string);
285 // encoder.setValue(aHit.getCellID0());
286  const gear::TPCModule &theModule = Global::GEAR->getTPCParameters().getNearestModule(aHit.getPosition()[0],
287  aHit.getPosition()[1]);
288  const int padIndex = theModule.getNearestPad(aHit.getPosition()[0], aHit.getPosition()[1]);
289  const int nModules = Global::GEAR->getTPCParameters().getNModules();
290  const int moduleNum = theModule.getModuleID();
291 // const int nRows = theModule.getNRows();
292 // const int layer = encoder[ILDCellID0::layer];
293  const int rowNum = theModule.getRowNumber(padIndex);
294  const int rowLabel = 100 * moduleNum + rowNum + 1;
295 
296  //
297  // === row-wise offsets
298 
299  _numDer = 2;
300  _globalLab.push_back(rowLabel);
301  _globalLab.push_back(rowLabel + 100 * nModules);
302  _globalDer.ResizeTo(2, _numDer);
303  _globalDer[0][0] = 1.; // offset in XY
304  _globalDer[1][1] = 1.; // offset in Z
305 }
306 
308 
312 void trackerAlcaCalculator::calcModuleAlignment(const TrackerHit & aHit, const TVectorD& tdir) {
313 
314  UTIL::BitField64 encoder(lcio::ILDCellID0::encoder_string);
315  encoder.setValue(aHit.getCellID0());
316 
317  // === pad plane alignment ===
318  // --- hit position in pad plane system
319  //int modNum = encoder[ILDCellID0::module];
320  const gear::TPCModule &module = Global::GEAR->getTPCParameters().getNearestModule(aHit.getPosition()[0], aHit.getPosition()[1]);
321  int modNum = module.getModuleID();
322  Vector2D correction = module.getOffset();
323  const double xHit = aHit.getPosition()[0] - correction[0];
324  const double yHit = aHit.getPosition()[1] - correction[1];
325  const double zHit = aHit.getPosition()[2];
326  const double phiHit = atan2(yHit, xHit);
327  // measurement direction (-sin(_phiHit), cos(_phiHit))
328  const double ex = -sin(phiHit);
329  const double ey = cos(phiHit);
330  // --- normal vector (to (virtual) measurement plane)
331  TVectorD normal(3);
332  normal[0] = ey;
333  normal[1] = -ex;
334  //cout << " tdir " << endl; tdir.Print();
335  //cout << " normal " << endl; _normal.Print();
336  // --- dr/dm (residual vs measurement)
337  TMatrixD drdm(3, 3);
338  drdm.UnitMatrix();
339  // product tdir * normal (scalar)
340  double tn = tdir[0] * normal[0] + tdir[1] * normal[1] + tdir[2] * normal[2];
341  // (subtract) product tdir * transposed(normal) (matrix)
342  for (unsigned int i = 0; i < 3; i++)
343  for (unsigned int j = 0; j < 3; j++)
344  drdm[i][j] -= tdir[i] * normal[j] / tn;
345  //cout << " drdm " << endl; _drdm.Print();
346  // --- dm/dg (measurement vs 6 rigid body parameters)
347  TMatrixD dmdg(3, 6);
348  dmdg[0][0] = 1.;
349  dmdg[0][4] = zHit;
350  dmdg[0][5] = -yHit;
351  dmdg[1][1] = 1.;
352  dmdg[1][3] = -zHit;
353  dmdg[1][5] = xHit;
354  dmdg[2][2] = 1.;
355  dmdg[2][3] = yHit;
356  dmdg[2][4] = -xHit;
357  //cout << " dmdg " << endl; _dmdg.Print();
358  // --- drl/drg (local vs global residuals)
359  TMatrixD drldrg(3, 3);
360  drldrg[0][0] = ex;
361  drldrg[0][1] = ey; // in pad direction
362  drldrg[1][2] = 1.; // in drift direction
363  drldrg[2][0] = -ey;
364  drldrg[2][1] = ex; // in row direction
365  //cout << " drldrg " << endl; _drldrg.Print();
366  // --- drl/dg (local residuals vs rigid body parameters)
367  //TMatrixD _tmp = _drdm * _dmdg;
368  //cout << " tmp " << endl; _tmp.Print();
369  TMatrixD drldg = drldrg * drdm * dmdg;
370  //cout << " drldg " << endl; _drldg.Print();
371  _numDer = 6; // +2; // for distorions
372  _globalDer.ResizeTo(2, _numDer);
373  for (unsigned int i = 0; i < 6; i++) {
374  _globalLab.push_back(10 * modNum + i + 1);
375  _globalDer[0][i] = drldg[0][i]; // derivatives for pad measurement
376  _globalDer[1][i] = drldg[1][i]; // derivatives for drift measurement
377  }
378  /* higher order distortions along rows
379  const double row = rowNum;
380  const double relRow = (row-14.5)/14.0; // relative row number in [-1 .. +1]
381  _globalLab.push_back(10*modNum + 7); // distortion for pad measurement
382  _globalDer[0][6] = pow(relRow,2) - 1./3.; // (rescaled) 2nd order Legendre polynomial
383  _globalLab.push_back(10*modNum + 8); // distortion for drift measurement
384  _globalDer[1][7] = pow(relRow,2) - 1./3.; // (rescaled) 2nd order Legendre polynomial
385  */
386 }
387 
389 
394 void trackerAlcaCalculator::calcHitCharge(const TrackerHit & aHit) {
395 
396  // get module and row number
397 // UTIL::BitField64 encoder(lcio::ILDCellID0::encoder_string);
398 // encoder.setValue(aHit.getCellID0());
399  const gear::TPCModule &theModule = Global::GEAR->getTPCParameters().getNearestModule(aHit.getPosition()[0],
400  aHit.getPosition()[1]);
401  const int padIndex = theModule.getNearestPad(aHit.getPosition()[0], aHit.getPosition()[1]);
402  const int nModules = Global::GEAR->getTPCParameters().getNModules();
403  const int moduleNum = theModule.getModuleID();
404 // const int nRows = theModule.getNRows();
405 // const int layer = encoder[ILDCellID0::layer];
406  const int rowNum = theModule.getRowNumber(padIndex);
407  const int rowLabel = 100 * moduleNum + rowNum + 1;
408 
409  //calc charge bin
410  double hitMaxPulseCharge = 0;
411  for (LCObjectVec::const_iterator pulseIter = aHit.getRawHits().begin(); pulseIter < aHit.getRawHits().end(); ++pulseIter) {
412  TrackerPulse const * pulse = dynamic_cast<TrackerPulse const *>(*pulseIter);
413  if (pulse->getCharge() > hitMaxPulseCharge) {
414  hitMaxPulseCharge = pulse->getCharge();
415  }
416  }
417  const double lgQ = log10(hitMaxPulseCharge);
418  int bin;
419  if (lgQ >= 4)
420  bin = 40;
421  else if (lgQ < 2)
422  bin = 1;
423  else {
424  bin = static_cast<int>((lgQ - 2) / 2 * 40) + 1;
425  }
426  if (bin < 1) bin = 1;
427 
428  _numDer = 4;
429  _globalLab.push_back(rowLabel);
430  _globalLab.push_back(rowLabel + 100 * nModules);
431  _globalLab.push_back(bin + 2 * 100 * nModules);
432  _globalLab.push_back(bin + 2 * 100 * nModules + 100);
433  _globalDer.ResizeTo(2, _numDer);
434  _globalDer[0][0] = 1.; // offset in XY
435  _globalDer[1][1] = 1.; // offset in Z
436  _globalDer[0][2] = 1.; // offset in XY
437  _globalDer[1][3] = 1.; // offset in Z
438 }
439 
441 
447 void trackerAlcaCalculator::calcDr(const TrackerHit & aHit, double phi) {
448 
449  // row number
450  UTIL::BitField64 encoder(lcio::ILDCellID0::encoder_string);
451  encoder.setValue(aHit.getCellID0());
452  int rowNum = encoder[ILDCellID0::layer];
453  //calc charge bin
454  _numDer = 2;
455  _globalLab.push_back(rowNum + 1);
456  _globalLab.push_back(rowNum + 1 + 100);
457  _globalDer.ResizeTo(2, _numDer);
458  _globalDer[0][0] = 1.; // offset in XY
459  _globalDer[0][1] = tan(phi); // offset in XY
460 }
461 
463 
467 trackerAlcaSelector::trackerAlcaSelector(const EVENT::Track& aTrack, const int milleMinHits) :
468  _selectionFlag(true) {
469  // for LPTPC require minimum track length (~ 1.5 modules)
470  unsigned int minHits = milleMinHits;
471  _selectionFlag = (aTrack.getTrackerHits().size() >= minHits);
472 }
473 
476  return _selectionFlag;
477 }
478 
479 } // close namespace brackets
480 #endif // conditional compilation if GBL program package is available on the system
double _calcEScaled(const EVENT::TrackerHit &)
Calculate scaled Edep.
bool _isValid
hit has valid prediction from track
TMatrixDSym _getPrec(FloatVec)
Get precision ( = inverse variance) in measurement system.
const bool isSelected() const
Get selection flag.
void calcTrackDistortions(const EVENT::TrackerHit &aHit)
Fills the global derivatives and labels for distortions studies as function of the row of the hits...
unsigned int getNumGlobals() const
Get number of global derivatives.
gblHelperHit(const EVENT::TrackerHit &, const simpleHelix &, const bool, const bool, const int, const double)
Construct helper hit from TrackerHit.
double _hitPhi
phi of hit (with respect to module offset)
void calcModuleAlignment(const EVENT::TrackerHit &aHit, const TVectorD &tdir)
Fills the global derivatives and labels for module alignment.
unsigned int getNumGlobals() const
Get number of global derivatives.
std::vector< int > _globalLab
labels for global derivatives
double _calcLocalPhi(const EVENT::TrackerHit &, const bool, const double)
Calculate local phi of hit.
double _seedLambda
lambda (ZS direction) from seed track
TVectorD _getRes()
Get residuals (measurement - prediction) in measurement system.
trackerAlcaCalculator()
Construct user-defined trackerAlcaCalculator.
const TMatrixD & getGlobalDerivatives() const
Get global derivatives.
double _xyPred
XY residual (measurement - prediction)
unsigned int _numDer
number of global derivatives
std::vector< int > getGlobalLabels() const
Get labels for global derivatives.
double _seedPhi
phi (XY direction) from seed track
const bool _isMeas
flag for measurements (else reference point)
TMatrixD _globalDer
global derivatives
std::vector< int > _globalLab
labels for global derivatives
const TMatrixD & getGlobalDerivatives() const
Get global derivatives.
void calcHitCharge(const EVENT::TrackerHit &aHit)
Fills the global derivatives and labels for distortions studies as function of the charge of the hits...
TMatrixD _getL2M()
Get transformation matrix.
void calcDr(const EVENT::TrackerHit &aHit, double phi)
Fills the global derivatives and labels for distortions studies as function of the charge of the hits...
std::vector< int > getGlobalLabels() const
Get labels for global derivatives.
User defined class to calculate global derivatives for Millepede-II.
trackerAlcaSelector(const EVENT::Track &, const int)
Construct user-defined trackerAlcaSelector.
unsigned int _numGlobals
number of global derivatives
double _zPred
Z residual (measurement - prediction)