MyMarlinTPC  170316
RowTripletBasedTrackFinderProcessor.cc
Go to the documentation of this file.
1 // #ifdef USE_ROWTRIPLETS
3 
5 
6 #include <iostream>
7 #include <string>
8 #include <ctime>
9 #include <cmath>
10 
11 //GEAR
12 #include <gear/TPCParameters.h>
13 #include <gear/BField.h>
14 #include <gearimpl/Vector3D.h>
15 
16 // include what you need from lcio
17 #include <EVENT/LCEvent.h>
18 #include <IMPL/LCCollectionVec.h>
19 #include <UTIL/BitField64.h>
20 #include <UTIL/ILDConf.h>
21 #include <IMPL/TrackerHitImpl.h>
22 #include <IMPL/TrackImpl.h>
23 #include <IMPL/LCFlagImpl.h>
24 #include <Exceptions.h>
25 
26 // this is the inserted part
27 
28 using namespace lcio;
29 using namespace marlin;
30 using namespace std;
31 using namespace gear;
32 
33 namespace marlintpc {
34 
36 
38 RowTripletBasedTrackFinderProcessor::RowTripletBasedTrackFinderProcessor() :
39  Processor("RowTripletBasedTrackFinderProcessor") {
40  // the processor description
41  _description = "RowTripletBasedTrackFinderProcessor is intended to ...";
42 
43  registerInputCollection(LCIO::TRACKERHIT, "InputHits", "Name of the input Hit Collection", _inputColName, string("TPCHits"));
44 
45  registerOutputCollection(LCIO::TRACK, "OutputTracks", "Name of the output Track Collection", _outputColName,
46  string("TripletTracks"));
47 
48  registerOptionalParameter("BFieldScaleFactor", "Scales magnetic field (map), use 1.0 (default) for field ON or 0.0 for field OFF",
49  _bfieldScaleFactor, double(1.0));
50 
51  registerOptionalParameter("TripletPreSelectionDistCut", "Coarse cut on XY and Z residuals for triplet preselection", _distCut,
52  double(10.0));
53 
54  registerOptionalParameter("TripletDefinitionChi2Cut", "Chi2 cut for triplet definition on XY and Z residuals", _trpCut,
55  double(20.0));
56 
57  registerOptionalParameter("TripletPositionMatchingChi2Cut", "Chi2 cut for triplet position matching in XY and Z", _posCut,
58  double(20.0));
59 
60  registerOptionalParameter("TripletDirectionMatchingChi2Cut", "Chi2 cut for triplet direction matching in XY and Z", _dirCut,
61  double(20.0));
62 
63  registerOptionalParameter("SegmentMatchingChi2Cut", "Chi2/Ndf cut for segment matching (Ndf=4 for B off, 5 for B on)", _segCut,
64  double(30.0));
65 
66  registerOptionalParameter("UnusedHitMatchingChi2Cut", "Chi2 cut for matching unused hits in XY and Z", _unusedCut, double(20.0));
67 
68  registerOptionalParameter("UnusedHitMaxGapCut", "Maximal (row) gap for matching unused hits in XY and Z", _maxGap, int(4));
69 
70  registerOptionalParameter("EncodedModuleID", "Module ID encoded in CellID0", _encodedModuleID, bool(true));
71 
72  registerOptionalParameter("ReferencePointAtPca", "Use PCA as reference point, else 1. hit", _refAtPCA, bool(false));
73 }
74 
77  m_out(DEBUG) << " init() called " << endl;
78 
79  const gear::TPCParameters& tpcParameters = Global::GEAR->getTPCParameters();
80  bool cartesian = (tpcParameters.getCoordinateType() == PadRowLayout2D::CARTESIAN);
81  const std::vector<TPCModule*> moduleVector = tpcParameters.getModules();
82  m_out(DEBUG) << " Number of modules: " << moduleVector.size() << endl;
83  for (std::vector<TPCModule*>::const_iterator itMod = moduleVector.begin(); itMod != moduleVector.end(); ++itMod) {
84  int module = (*itMod)->getModuleID();
85  m_out(DEBUG) << " module " << module << " with " << (*itMod)->getNRows() << " rows" << endl;
86  for (std::vector<TPCModule*>::const_iterator itMod2 = itMod; itMod2 != moduleVector.end(); ++itMod2) {
87  if (areNeighbourModules(*itMod, *itMod2, cartesian)) {
88  _modNeighbours[module].push_back((*itMod2)->getModuleID());
89  m_out(DEBUG) << " neighbour " << (*itMod2)->getModuleID() << endl;
90  }
91  }
92  }
93 
94  // TPC center
95  _Xcenter = tpcParameters.getDoubleVal("TPC_cylinder_centre_c0");
96  _Ycenter = tpcParameters.getDoubleVal("TPC_cylinder_centre_c1");
97 }
98 
100  // do something for each run
101 }
102 
105  std::clock_t start1 = std::clock();
106 
107  m_out(DEBUG) << "Event Number: " << evt->getEventNumber() << endl;
108 
109  //get input collection
110  LCCollection* inputCol = 0;
111 
112  LCCollectionVec* outputCol = new LCCollectionVec(LCIO::TRACK);
113  LCFlagImpl trkFlag(0);
114  trkFlag.setBit(LCIO::TRBIT_HITS);
115  outputCol->setFlag(trkFlag.getFlag());
116 
117  // do a try / catch in case there is an empty event
118  try {
119  inputCol = evt->getCollection(_inputColName);
120  } catch (DataNotAvailableException &e) {
121  // no input data, just return and process the next event
122  return;
123  }
124 
125  Vector3D theTPCCenter(_Xcenter, _Ycenter, 0.);
126  Vector3D bfield = marlin::Global::GEAR->getBField().at(theTPCCenter);
127 
128  const bool bOff(bfield.z() * _bfieldScaleFactor == 0.);
129  if (bOff) {
130  m_out(DEBUG) << "BField(GEAR) is OFF" << std::endl;
131  } else {
132  m_out(DEBUG) << "BField(GEAR) is ON" << std::endl;
133  }
134  // constant magnetic field (in z direction)
135  _Bzc = bfield.z() * _bfieldScaleFactor * 0.0002998; // Bz*c
136 
138  modHitMapType hitData;
139 
140  UTIL::BitField64 encoder(lcio::ILDCellID0::encoder_string);
141  int nInput = inputCol->getNumberOfElements();
142  m_out(DEBUG) << "Event " << evt->getEventNumber() << " in run " << evt->getRunNumber() << ", number of input hits: " << nInput
143  << endl;
144  for (int iInput = 0; iInput < nInput; iInput++) {
145  TrackerHit* Hit = dynamic_cast<TrackerHit*>(inputCol->getElementAt(iInput));
146  encoder.setValue(Hit->getCellID0());
147  int mod =
149  encoder[ILDCellID0::module] :
150  Global::GEAR->getTPCParameters().getNearestModule(Hit->getPosition()[0], Hit->getPosition()[1]).getModuleID();
151  int row = encoder[ILDCellID0::layer];
152  rb_Hit* someHit = new rb_Hit(iInput, mod, row, *Hit);
153  hitData[mod][row].push_back(someHit);
154  }
155 
157  // map of modules with vectors of segments
158  modSegMapType segData;
159  const int step = 2; // row step size for triplets
160  rowHitMapType::iterator itRow1, itRow2, itRow3;
161  for (modHitMapType::iterator itMod = hitData.begin(); itMod != hitData.end(); ++itMod) {
162  const int module = itMod->first;
163  //std::cout << " Module " << module << std::endl;
165  rowHitMapType modData = itMod->second; // hits in module
166  const int numRows = modData.rbegin()->first - modData.begin()->first + 1;
167  trpListType triplets;
168  m_out(DEBUG) << " module " << module << " with " << endl;
169  m_out(DEBUG) << " " << modData.size() << " rows " << endl;
170  //cout << " row range " << modData.begin()->first << " " << modData.rbegin()->first << endl;
171  // loop through row triplet
172  for (int row = modData.begin()->first + step; row <= modData.rbegin()->first - step; ++row) {
173  // all 3 rows must have hits to build triplets
174  if ((itRow1 = modData.find(row - step)) == modData.end()) continue;
175  if ((itRow2 = modData.find(row)) == modData.end()) continue;
176  if ((itRow3 = modData.find(row + step)) == modData.end()) continue;
177  // 3-fold loop
178  for (hitListType::iterator itHit1 = itRow1->second.begin(); itHit1 != itRow1->second.end(); ++itHit1) {
179  for (hitListType::iterator itHit3 = itRow3->second.begin(); itHit3 != itRow3->second.end(); ++itHit3) {
180  rb_Doublet someDoublet(*itHit1, *itHit3); // doublet from outer hits
181  for (hitListType::iterator itHit2 = itRow2->second.begin(); itHit2 != itRow2->second.end(); ++itHit2) {
182  if (someDoublet.match(*itHit2, _distCut, _trpCut)) triplets.push_back(new rb_Triplet(someDoublet, *itHit2));
183  }
184  }
185  }
186  }
187  m_out(DEBUG) << " " << triplets.size() << " triplets " << endl;
188 
190  segListType segments;
191  // equivalence classes for triplet matching
192  simpleEquiClasses trpEquiClass;
193  // loop over triplet pairs, check matching
194  for (trpListType::iterator itTrp1 = triplets.begin(); itTrp1 != triplets.end(); ++itTrp1) {
195  trpEquiClass.addIndex(itTrp1 - triplets.begin());
196  for (trpListType::iterator itTrp2 = itTrp1; itTrp2 != triplets.end(); ++itTrp2) {
197  if ((*itTrp2)->getRow() - (*itTrp1)->getRow() > 2) break; // max. row distance <= 2
198  // matching triplets ?
199  if ((*itTrp1)->match(*itTrp2, _posCut, _dirCut))
200  trpEquiClass.addMatch(make_pair(itTrp1 - triplets.begin(), itTrp2 - triplets.begin()));
201  }
202  }
203  // get classes with indices
204  std::map<int, std::vector<int> > trpClasses = trpEquiClass.getClasses();
205  // order classes
206  std::multimap<int, int> rowInfo;
207  int row, nRows, firstRow, lastRow;
208  for (std::map<int, std::vector<int> >::iterator itC = trpClasses.begin(); itC != trpClasses.end(); ++itC) {
209  nRows = firstRow = lastRow = 0;
210  for (std::vector<int>::iterator itInd = itC->second.begin(); itInd != itC->second.end(); ++itInd) {
211  row = triplets[*itInd]->getRow();
212  if (nRows == 0) {
213  firstRow = lastRow = row;
214  nRows++;
215  } else if (row > lastRow) {
216  lastRow = row;
217  nRows++;
218  }
219  }
220  if (nRows > 1) rowInfo.insert(make_pair(nRows * numRows + lastRow - firstRow, itC->first)); // use only classes with at least 2 triplets
221  }
222  // allocate hits to classes (segments) ordered by rowInfo ( ~ number of rows)
223  for (std::multimap<int, int>::reverse_iterator rit = rowInfo.rbegin(); rit != rowInfo.rend(); ++rit) {
224  trpListType matchingTriplets;
225  for (std::vector<int>::iterator itInd = trpClasses[rit->second].begin(); itInd != trpClasses[rit->second].end(); ++itInd)
226  matchingTriplets.push_back(triplets[*itInd]);
227  rb_Segment* simpleSegment = new rb_Segment(_Bzc, matchingTriplets);
228  if (simpleSegment->getNdf() < 0)
229  delete simpleSegment;
230  else
231  segments.push_back(simpleSegment); // keep valid segments
232  }
233  m_out(DEBUG) << " " << segments.size() << " segments " << endl;
234  // get rid of triplets
235  for (trpListType::iterator itTrp = triplets.begin(); itTrp != triplets.end(); ++itTrp) {
236  delete *itTrp;
237  }
238  triplets.clear();
239 
241  simpleEquiClasses segEquiClass;
242  // loop over segment pairs, check matching
243  for (segListType::iterator itSeg1 = segments.begin(); itSeg1 != segments.end(); ++itSeg1) {
244  segEquiClass.addIndex(itSeg1 - segments.begin());
245  for (segListType::iterator itSeg2 = itSeg1; itSeg2 != segments.end(); ++itSeg2) {
246  // matching segments ?
247  if ((*itSeg1)->match(*itSeg2, _segCut, step))
248  segEquiClass.addMatch(make_pair(itSeg1 - segments.begin(), itSeg2 - segments.begin()));
249  }
250  }
251  // get classes with indices
252  std::map<int, std::vector<int> > segClasses = segEquiClass.getClasses();
253  for (std::map<int, std::vector<int> >::iterator itC = segClasses.begin(); itC != segClasses.end(); ++itC) {
254  //cout << " seg-link " << itC->first << ": " << itC->second.size() << endl;
255  segListType matchingSegments;
256  for (std::vector<int>::iterator itInd = itC->second.begin(); itInd != itC->second.end(); ++itInd)
257  matchingSegments.push_back(segments[*itInd]);
258  segData[module].push_back(new rb_Segment(matchingSegments)); // save combined segments
259  }
260  // get rid of (simple) segments
261  for (segListType::iterator itSeg = segments.begin(); itSeg != segments.end(); ++itSeg) {
262  delete *itSeg;
263  }
264  segments.clear();
265 
267  for (segListType::iterator itSeg = segData[module].begin(); itSeg != segData[module].end(); ++itSeg) {
268  map<int, int> rowMap;
269  (*itSeg)->fillRowMap(rowMap);
270  int centerRow = ((*itSeg)->getFirstRow() + (*itSeg)->getLastRow()) / 2;
271  // look forward
272  for (int row = centerRow + 1; row <= modData.rbegin()->first; ++row) {
273  if (row > (*itSeg)->getLastRow() + _maxGap) break; // too far away
274  if (rowMap.count(row) > 0) continue; // row already contained in segment
275  hitListType hits;
276  (*itSeg)->match(modData[row], hits, _unusedCut); // match list of hits
277  //if (!hits.empty()) cout << " match-fwd " << row << " " <<(*itSeg)->getFirstRow() << " " <<(*itSeg)->getLastRow() << ": " << hits.size() << endl;
278  if (hits.size() == 1) (*itSeg)->addHit(hits[0]); // single additional hit?
279  }
280  // look backward
281  for (int row = centerRow; row >= modData.begin()->first; --row) {
282  if (row < (*itSeg)->getFirstRow() - _maxGap) break; // too far away
283  if (rowMap.count(row) > 0) continue; // row already contained in segment
284  hitListType hits;
285  (*itSeg)->match(modData[row], hits, _unusedCut); // match list of hits
286  //if (!hits.empty()) cout << " match-bwd " << row << " " <<(*itSeg)->getFirstRow() << " " <<(*itSeg)->getLastRow() << ": " << hits.size() << endl;
287  if (hits.size() == 1) (*itSeg)->addHit(hits[0]); // single additional hit?
288  }
289  }
290  }
291 
293  std::vector<std::pair<int, int> > segIndex;
294  simpleEquiClasses segEquiClass;
295  // create segment index
296  for (modSegMapType::iterator itMod = segData.begin(); itMod != segData.end(); ++itMod) {
297  segListType segments = itMod->second;
298  for (segListType::iterator itSeg = segments.begin(); itSeg != segments.end(); ++itSeg) {
299  (*itSeg)->setId(segIndex.size());
300  segIndex.push_back(make_pair(itMod->first, itSeg - segments.begin()));
301  segEquiClass.addIndex((*itSeg)->getId());
302  }
303  }
304  // check segment matching with neighbour modules
305  for (modSegMapType::iterator itMod = segData.begin(); itMod != segData.end(); ++itMod) {
306  std::vector<int> neighbours = _modNeighbours[itMod->first];
307  segListType segments1 = itMod->second;
308  for (std::vector<int>::iterator itN = neighbours.begin(); itN != neighbours.end(); ++itN) {
309  segListType segments2 = segData[*itN];
310  for (segListType::iterator itSeg1 = segments1.begin(); itSeg1 != segments1.end(); ++itSeg1) {
311  for (segListType::iterator itSeg2 = segments2.begin(); itSeg2 != segments2.end(); ++itSeg2) {
312  // matching segments ?
313  if ((*itSeg1)->match(*itSeg2, _segCut, step)) segEquiClass.addMatch(make_pair((*itSeg1)->getId(), (*itSeg2)->getId()));
314  }
315  }
316  }
317  }
318  // get classes with indices
319  std::map<int, std::vector<int> > segClasses = segEquiClass.getClasses();
320  segListType trackCandidates;
321  for (std::map<int, std::vector<int> >::iterator itC = segClasses.begin(); itC != segClasses.end(); ++itC) {
322  //cout << " seg-link-m " << itC->first << ": " << itC->second.size() << endl;
323  segListType matchingSegments;
324  for (std::vector<int>::iterator itInd = itC->second.begin(); itInd != itC->second.end(); ++itInd) {
325  std::pair<int, int> index = segIndex[*itInd];
326  matchingSegments.push_back(segData[index.first][index.second]);
327  }
328  trackCandidates.push_back(new rb_Segment(matchingSegments)); // save combined segments
329  }
330  m_out(DEBUG) << " found " << trackCandidates.size() << " track candidates " << endl;
331 
333  for (segListType::iterator itSeg = trackCandidates.begin(); itSeg != trackCandidates.end(); ++itSeg) {
334  // new track
335  TrackImpl* theTrack = new TrackImpl();
336  // get hits
337  hitListType hits = (*itSeg)->getHitList();
338  // position of 1. hit
339  double posFirst[3];
340  hits.front()->getPos(posFirst);
341  // reference point, 1. hit or PCA (point of closest approach (to origin))
342  double refPos[] = { 0., 0., 0. };
343  if (!_refAtPCA) {
344  refPos[0] = posFirst[0];
345  refPos[1] = posFirst[1];
346  refPos[2] = posFirst[2];
347  }
348  float refPoint[3];
349  for (int i = 0; i < 3; ++i)
350  refPoint[i] = refPos[i];
351  // track parameters and covariance matrix
352  TVectorD parameters(5);
353  TMatrixDSym covariance(5);
354  (*itSeg)->getLCIOStateAtRefPoint(refPos, parameters, covariance); // ( d0, phi0, Omega, z0, tanLambda)
355 
356  theTrack->setOmega(parameters[2]);
357  theTrack->setTanLambda(parameters[4]);
358  theTrack->setPhi(parameters[1]);
359  theTrack->setD0(parameters[0]);
360  theTrack->setZ0(parameters[3]);
361  theTrack->setChi2((*itSeg)->getChi2());
362  theTrack->setNdf((*itSeg)->getNdf());
363  theTrack->setReferencePoint(refPoint);
364  /* prepare LCIO output; unknown parts:
365  *
366  * theTrack->setTypeBit (int index, bool val=true) // ?
367  * theTrack->setdEdx (float dEdx)
368  * theTrack->setdEdxError (float dEdxError) */
369  float rInner = sqrt(pow(posFirst[0], 2) + pow(posFirst[1], 2));
370  theTrack->setRadiusOfInnermostHit(rInner);
371  // compressed covariance matrix
372  float compressedCovariance[15];
373  int ind = 0;
374  for (int i = 0; i < 5; ++i)
375  for (int j = 0; j <= i; ++j)
376  compressedCovariance[ind++] = covariance[i][j];
377  theTrack->setCovMatrix(compressedCovariance);
378  // and finally add the hits to the track
379  for (hitListType::iterator itH = hits.begin(); itH != hits.end(); ++itH) {
380  TrackerHit* Hit = dynamic_cast<TrackerHit*>(inputCol->getElementAt((*itH)->getHitNum()));
381  theTrack->addHit(Hit);
382  }
383 
384  m_out(DEBUG) << " +++ the found track has a chi^2 value of " << theTrack->getChi2() << " for ndf = " << theTrack->getNdf()
385  << " and the parameters [omega, tanLambda, phi0, d0, z0] = [" << theTrack->getOmega() << "," << theTrack->getTanLambda()
386  << "," << theTrack->getPhi() << "," << theTrack->getD0() << "," << theTrack->getZ0() << "] at the reference position ["
387  << refPoint[0] << "," << refPoint[1] << "," << refPoint[2] << "]." << endl;
388 
389  outputCol->addElement(theTrack);
390  }
391 
392  m_out(DEBUG) << "RowTripletBasedTrackFinder ... done!" << endl;
393 
394  if (!outputCol->empty()) {
395  evt->addCollection(outputCol, _outputColName);
396  }
397 
398  m_out(DEBUG) << ((std::clock() - start1) / (double) CLOCKS_PER_SEC) << " sec" << endl;
399 
400  // clean up
401  for (modHitMapType::iterator itMod = hitData.begin(); itMod != hitData.end(); ++itMod) {
402  for (rowHitMapType::iterator itRow = itMod->second.begin(); itRow != itMod->second.end(); ++itRow) {
403  for (hitListType::iterator itH = itRow->second.begin(); itH != itRow->second.end(); ++itH) {
404  delete *itH;
405  }
406  }
407  }
408  hitData.clear();
409  for (modSegMapType::iterator itMod = segData.begin(); itMod != segData.end(); ++itMod) {
410  for (segListType::iterator itSeg = itMod->second.begin(); itSeg != itMod->second.end(); ++itSeg) {
411  delete *itSeg;
412  }
413  }
414  segData.clear();
415  for (segListType::iterator itSeg = trackCandidates.begin(); itSeg != trackCandidates.end(); ++itSeg) {
416  delete *itSeg;
417  }
418  trackCandidates.clear();
419 
420 }
421 
423  // check what is needed here
424 }
425 
427  // do something at the end of the processing, e.g. cleaning up
428 
429 }
430 
432 
438 bool RowTripletBasedTrackFinderProcessor::areNeighbourModules(gear::TPCModule* mod1, gear::TPCModule* mod2, bool cartesian) {
440  // are mod1 and mod2 neighbours?
441  if (mod1 == mod2) return false;
443  const std::vector<double> modExtend = mod1->getModuleExtent();
444  const double xm1 = 0.5 * (modExtend[1] + modExtend[0]), xs1 = 0.5 * (modExtend[1] - modExtend[0]);
445  const double ym1 = 0.5 * (modExtend[3] + modExtend[2]), ys1 = 0.5 * (modExtend[3] - modExtend[2]);
446  const std::vector<double> modExtend2 = mod2->getModuleExtent();
447  const double xm2 = 0.5 * (modExtend2[1] + modExtend2[0]), xs2 = 0.5 * (modExtend2[1] - modExtend2[0]);
448  const double ym2 = 0.5 * (modExtend2[3] + modExtend2[2]), ys2 = 0.5 * (modExtend2[3] - modExtend2[2]);
449  const double dx = xm2 - xm1, dy = ym2 - ym1;
450  return (pow(dx * dx + dy * dy, 2) / (pow((xs1 + xs2) * dx, 2) + pow((ys1 + ys2) * dy, 2)) < 2.);
451 }
452 
454 
460 rb_Hit::rb_Hit(const int iHit, const int mod, const int row, const TrackerHit& aHit) :
461  _hitNum(iHit), _hitModule(mod), _hitRow(row), _hitX(aHit.getPosition()[0]), _hitY(aHit.getPosition()[1]), _hitZ(
462  aHit.getPosition()[2]), _hitPhiMeas(_calcPhiMeas(aHit)), _hitVarXY(_getVarXY(aHit.getCovMatrix())), _hitVarR(
463  _getVarR(aHit.getCovMatrix())), _hitVarZ(_getVarZ(aHit.getCovMatrix())), _used(false), _cosb(1.) {
464 }
465 
467 void rb_Hit::print() const {
468  std::cout << " rb_Hit " << _hitNum << ": " << _hitModule << ", " << _hitRow << ", " << _hitX << ", " << _hitY << ", " << _hitZ
469  << ", " << _hitPhiMeas << "; " << _hitVarXY << ", " << _hitVarZ << std::endl;
470 }
471 
473 
477 double rb_Hit::_calcPhiMeas(const TrackerHit& aHit) {
478  const gear::TPCModule &module = Global::GEAR->getTPCParameters().getModule(_hitModule);
479  double phi; // azimuthal direction
480  if (module.getLocalPadLayout().getCoordinateType() == gear::PadRowLayout2D::POLAR) {
481  Vector2D correction = module.getOffset();
482  phi = atan2(aHit.getPosition()[0] - correction[0], correction[1] - aHit.getPosition()[1]);
483  //std::cout << " Polar " << phi << std::endl;
484  } else {
485  phi = module.getAngle(); // + 0.5 * M_PI; ??
486  //std::cout << " Cartesian " << phi << std::endl;
487  }
488  return phi;
489 }
490 
492 
496 double rb_Hit::_getVarXY(FloatVec covMatrix) {
497  double var = cos(_hitPhiMeas) * cos(_hitPhiMeas) * covMatrix[0] + 2. * sin(_hitPhiMeas) * cos(_hitPhiMeas) * covMatrix[1]
498  + sin(_hitPhiMeas) * sin(_hitPhiMeas) * covMatrix[2];
499  return (var > 0.) ? var : 1.;
500 }
501 
503 
507 double rb_Hit::_getVarR(FloatVec covMatrix) {
508  double var = sin(_hitPhiMeas) * sin(_hitPhiMeas) * covMatrix[0] - 2. * sin(_hitPhiMeas) * cos(_hitPhiMeas) * covMatrix[1]
509  + cos(_hitPhiMeas) * cos(_hitPhiMeas) * covMatrix[2];
510  return var;
511 }
512 
514 
518 double rb_Hit::_getVarZ(FloatVec covMatrix) {
519  return (covMatrix[5] > 0.) ? covMatrix[5] : 1.;
520 }
521 
523 int rb_Hit::getHitNum() const {
524  return _hitNum;
525 }
526 
528 int rb_Hit::getMod() const {
529  return _hitModule;
530 }
531 
533 int rb_Hit::getRow() const {
534  return _hitRow;
535 }
536 
538 double rb_Hit::getX() const {
539  return _hitX;
540 }
541 
543 double rb_Hit::getY() const {
544  return _hitY;
545 }
546 
548 double rb_Hit::getZ() const {
549  return _hitZ;
550 }
551 
553 
556 void rb_Hit::getPos(double* position) const {
557  position[0] = _hitX;
558  position[1] = _hitY;
559  position[2] = _hitZ;
560 }
561 
563 
566 double rb_Hit::getVarXY(const double der2) const {
567  return _hitVarXY + der2 * _hitVarR;
568 }
569 
571 
574 double rb_Hit::getVarZ(const double der2) const {
575  return _hitVarZ + der2 * _hitVarR;
576 }
577 
579 double rb_Hit::getPhiMeas() const {
580  return _hitPhiMeas;
581 }
582 
584 bool rb_Hit::getUsed() const {
585  return _used;
586 }
587 
589 
592 void rb_Hit::setUsed(const double cosb = 1.) {
593  _used = true;
594  _cosb = cosb;
595 }
596 
598 double rb_Hit::getCosBeta() const {
599  return _cosb;
600 }
601 
603 
609 double rb_Hit::getDistXY(const double x, const double y, const double ex, const double ey) const {
610  return (_hitX - x) * ex + (_hitY - y) * ey;
611 }
612 
614 
617 double rb_Hit::getDistZ(const double z) const {
618  return _hitZ - z;
619 }
620 
622 
627  double pos1[3], pos2[3], dx, dy, dz, ds, dr;
628  hit1->getPos(pos1);
629  hit2->getPos(pos2);
630  // hits
631  _hit[0] = hit1;
632  _hit[1] = hit2;
633  // measurement direction
634  _phiMeas = 0.5 * (hit1->getPhiMeas() + hit2->getPhiMeas());
635  _cosPhi = cos(_phiMeas);
636  _sinPhi = sin(_phiMeas);
637  // position
638  _xav = 0.5 * (pos1[0] + pos2[0]);
639  _yav = 0.5 * (pos1[1] + pos2[1]);
640  _zav = 0.5 * (pos1[2] + pos2[2]);
641  // slope
642  dx = pos2[0] - pos1[0];
643  dy = pos2[1] - pos1[1];
644  dz = pos2[2] - pos1[2];
645  ds = sqrt(dx * dx + dy * dy); // arc length
646  dr = dx * _sinPhi - dy * _cosPhi; // radial length
647  // phi
648  _phi = atan2(dy, dx);
649  // tanl
650  _tanl = dz / ds;
651  // length
652  _length = ds;
653  // cos(beta) (angle between measurement and normal to flight direction in XY)
654  _cosb = dr / ds;
655  // derivatives
656  const double cosb2 = _cosb * _cosb;
657  _der2XY = (1. - cosb2) / cosb2; // tan(beta)^2
658  _der2Z = _tanl * _tanl / cosb2; // tan(lambda)^2/cos(beta)^2
659  // variances
660  _varXY = hit1->getVarXY(_der2XY) + hit2->getVarXY(_der2XY);
661  _varZ = hit1->getVarZ(_der2Z) + hit2->getVarZ(_der2Z);
662 }
663 
665 
671 bool rb_Doublet::match(rb_Hit* hit, const double distCut, const double chi2Cut) const {
672  // triplet residuals
673  const double dz = hit->getDistZ(_zav);
674  // coarse (pre-)cut
675  if (abs(dz) > distCut) return false;
676  const double dxy = hit->getDistXY(_xav, _yav, _cosPhi, _sinPhi);
677  // coarse (pre-)cut
678  if (abs(dxy) > distCut) return false;
679  const double chi2xy = dxy * dxy / (hit->getVarXY(_der2XY) + 0.25 * _varXY);
680  const double chi2z = dz * dz / (hit->getVarZ(_der2Z) + 0.25 * _varZ);
681  // cout << "chi2 " << hit->getRow() << ": " << chi2xy << " " << chi2z << endl;
682  return (chi2xy < chi2Cut and chi2z < chi2Cut);
683 }
684 
686 
698 void rb_Doublet::getParameters(double& x, double& y, double& z, double& phiMeas, double& phi, double& dzds, double& ds,
699  double& cosb, double& varXY, double& varZ) const {
700  x = _xav;
701  y = _yav;
702  z = _zav;
703  phiMeas = _phiMeas;
704  phi = _phi;
705  dzds = _tanl;
706  ds = _length;
707  cosb = _cosb;
708  varXY = _varXY;
709  varZ = _varZ;
710 }
711 
713 
717 rb_Hit* rb_Doublet::getHit(const int ihit) const {
718  return _hit[ihit];
719 }
720 
722 
727  //hits
728  _hit[0] = doublet.getHit(0);
729  _hit[1] = hit;
730  _hit[2] = doublet.getHit(1);
731  // parameters
732  double sumVarXY, sumVarZ;
733  doublet.getParameters(_posX, _posY, _posZ, _phiMeas, _phi, _tanl, _length, _cosb, sumVarXY, sumVarZ);
734  // covarince matrices (diagonals)
735  _varXY[0] = 0.25 * sumVarXY;
736  _varXY[1] = sumVarXY / (_length * _length); // var(phi) = sumVarXY / (dr)^2 = sumVarXY / (ds * cosb)^2 = varXY[1] / cosb^2
737  _varZ[0] = 0.25 * sumVarZ;
738  _varZ[1] = sumVarZ / (_length * _length); // var(tanl) = sumVarZ / (ds)^2 = varZ[1]
739 }
740 
742 int rb_Triplet::getRow() const {
743  return _hit[1]->getRow();
744 }
745 
747 double rb_Triplet::getX() const {
748  return _posX;
749 }
750 
752 double rb_Triplet::getY() const {
753  return _posY;
754 }
755 
757 double rb_Triplet::getZ() const {
758  return _posZ;
759 }
760 
762 
765 void rb_Triplet::getPos(double* position) const {
766  position[0] = _posX;
767  position[1] = _posY;
768  position[2] = _posZ;
769 }
770 
772 
775 double rb_Triplet::getVarXYPos(const double ds) const {
776  return _varXY[0] + _varXY[1] * ds * ds;
777 }
778 
780 double rb_Triplet::getVarXYDir() const {
781  return _varXY[1] * (_cosb * _cosb);
782 }
783 
785 
788 double rb_Triplet::getVarZPos(const double ds) const {
789  return _varZ[0] + _varZ[1] * ds * ds;
790 }
791 
793 double rb_Triplet::getVarZDir() const {
794  return _varZ[1];
795 }
796 
798 double rb_Triplet::getPhiMeas() const {
799  return _phiMeas;
800 }
801 
803 double rb_Triplet::getPhi() const {
804  return _phi;
805 }
806 
808 double rb_Triplet::getTanl() const {
809  return _tanl;
810 }
811 
813 double rb_Triplet::getCosBeta() const {
814  return _cosb;
815 }
816 
818 
831 bool rb_Triplet::match(rb_Triplet* trp, const double posCut, const double dirCut) const {
832  const int rowDiff = trp->getRow() - this->getRow();
833  if (rowDiff == 0) return false; // min. row distance > 0
834  // compare triplet directions
835  const double dphi = trp->getPhi() - _phi;
836  const double dtanl = trp->getTanl() - _tanl;
837  const double varXYDir = this->getVarXYDir() + trp->getVarXYDir();
838  const double varZDir = this->getVarZDir() + trp->getVarZDir();
839  //cout << "chi2Dir " << this->getRow() << " " << trp->getRow() << " " << dphi << " " << varXYDir << " " << dtanl << " " << varZDir << endl;
840  if (dphi * dphi / varXYDir > dirCut or dtanl * dtanl / varZDir > dirCut) return false;
841  // compare triplet positions at mid point
842  double midPos1[3], midPos2[3], ds1, ds2;
843  const double xav = 0.5 * (_posX + trp->getX());
844  const double yav = 0.5 * (_posY + trp->getY());
845  this->getPosCloseTo(xav, yav, midPos1, ds1);
846  trp->getPosCloseTo(xav, yav, midPos2, ds2);
847  const double phiMeas = 0.5 * (this->getPhiMeas() + trp->getPhiMeas());
848  const double dxy = (midPos2[0] - midPos1[0]) * cos(phiMeas) + (midPos2[1] - midPos1[1]) * sin(phiMeas);
849  const double dz = midPos2[2] - midPos1[2];
850  const double varXYPos = this->getVarXYPos(ds1) + trp->getVarXYPos(ds2);
851  const double varZPos = this->getVarZPos(ds1) + trp->getVarZPos(ds2);
852  const double chi2xy = dxy * dxy / varXYPos;
853  const double chi2z = dz * dz / varZPos;
854  //cout << "chi2Pos " << this->getRow() << " " << trp->getRow() << " " << dxy << " " << varXYPos << " " << dz << " " << varZPos << endl;
855  return (chi2xy < posCut and chi2z < posCut);
856 }
857 
859 
865 void rb_Triplet::getPosCloseTo(const double xref, const double yref, double* position, double& ds) const {
866  const double ex = cos(_phi);
867  const double ey = sin(_phi);
868  ds = (xref - _posX) * ex + (yref - _posY) * ey;
869  position[0] = _posX + ds * ex;
870  position[1] = _posY + ds * ey;
871  position[2] = _posZ + _tanl * ds;
872 }
873 
875 
879 rb_Hit* rb_Triplet::getHit(const int ihit) const {
880  return _hit[ihit];
881 }
882 
884 
890 rb_Segment::rb_Segment(double Bzc, trpListType triplets) :
891  _segId(0), _hitList(), _bzc(Bzc), _npar((Bzc != 0.) ? 5 : 4), _parameters(_npar), _covariance(_npar) {
892  rowHitMapType rowList; // map of rows with lists of hits
893  for (trpListType::iterator itTrp = triplets.begin(); itTrp != triplets.end(); ++itTrp) {
894  for (int i = 0; i < 3; ++i) {
895  rb_Hit* iHit = (*itTrp)->getHit(i);
896  // Take all (previously) unused hits from the triplets
897  if (not iHit->getUsed()) {
898  rowList[iHit->getRow()].push_back(iHit);
899  iHit->setUsed((*itTrp)->getCosBeta());
900  }
901  }
902  }
903  // use only rows with single hit
904  for (rowHitMapType::iterator itRow = rowList.begin(); itRow != rowList.end(); ++itRow) {
905  if (itRow->second.size() == 1) _hitList.push_back(itRow->second[0]);
906  }
907  fitSegment(Bzc);
908 }
909 
911 
918 rb_Segment::rb_Segment(double Bzc, hitListType hits, unsigned int maxHitsPerRow) :
919  _segId(0), _hitList(), _bzc(Bzc), _npar((Bzc != 0.) ? 5 : 4), _parameters(_npar), _covariance(_npar) {
920  rowHitMapType rowList; // map of rows with lists of hits
921  for (hitListType::iterator itHit = hits.begin(); itHit != hits.end(); ++itHit) {
922  rb_Hit* iHit = (*itHit);
923  // Take all (previously) unused hits from the triplets
924  if (not iHit->getUsed()) {
925  rowList[iHit->getRow()].push_back(iHit);
926  }
927  }
928  // use only rows with single hit
929  for (rowHitMapType::iterator itRow = rowList.begin(); itRow != rowList.end(); ++itRow) {
930  if (itRow->second.size() <= maxHitsPerRow)
931  for (hitListType::iterator itHit = itRow->second.begin(); itHit != itRow->second.end(); ++itHit) {
932  rb_Hit* iHit = *itHit;
933  _hitList.push_back(iHit);
934  iHit->setUsed(1.);
935  }
936  }
937  fitSegment(Bzc);
938 }
939 
941 
949  _segId(0), _hitList(), _bzc(segments.front()->getBzc()), _npar((_bzc != 0.) ? 5 : 4), _parameters(_npar), _covariance(_npar) {
950  if (segments.size() > 1) {
951  // combine lists of hits
952  rowHitMapType rowList; // map of rows with lists of hits
953  for (segListType::iterator itSeg = segments.begin(); itSeg != segments.end(); ++itSeg) {
954  hitListType hits = (*itSeg)->getHitList();
955  for (hitListType::iterator itH = hits.begin(); itH != hits.end(); ++itH)
956  rowList[(*itH)->getRow()].push_back(*itH);
957  }
958  // use only rows with single hit
959  for (rowHitMapType::iterator itRow = rowList.begin(); itRow != rowList.end(); ++itRow) {
960  if (itRow->second.size() == 1) _hitList.push_back(itRow->second[0]);
961  }
962  // new reference point
963  calcRefPoint();
964  double oldRef[3], oldPar[5];
965  // weighted average of track parameters;
966  _ndf = 0;
967  _chi2 = 0.;
968  for (segListType::iterator itSeg = segments.begin(); itSeg != segments.end(); ++itSeg) {
969  (*itSeg)->getPar(oldPar);
970  (*itSeg)->getRefPoint(oldRef);
971  simpleHelix hlx(oldPar, oldRef, _bzc);
972  TVectorD newPar(_npar);
973  TMatrixDSym cov((*itSeg)->getCov()), newCov(_npar);
974  // track state at reference point
975  hlx.getStateAt(_refX, _refY, _refZ, cov, newPar, newCov);
976  if (itSeg == segments.begin()) {
977  // first segment
978  _parameters = newPar;
979  _covariance = newCov;
980  } else {
981  // weighted average
982  TMatrixDSym weight1(_covariance);
983  weight1.Invert(); // weight from previous segments
984  TMatrixDSym weight2(newCov);
985  weight2.Invert(); // weight from current segment
986  TMatrixDSym combCov(weight1 + weight2);
987  combCov.Invert(); // combined variance
988  TVectorD combPar(combCov * (weight1 * _parameters + weight2 * newPar)); // combined parameters
989  TVectorD resPrev(_parameters - combPar);
990  _chi2 += weight1.Similarity(resPrev); // chi2 contribution from prev. seg
991  TVectorD resCurr(newPar - combPar);
992  _chi2 += weight2.Similarity(resCurr); // chi2 contribution from curr.. seg
993  _ndf += _npar; // new degrees of freedom
994  _parameters = combPar;
995  _covariance = combCov;
996  }
997  _ndf += (*itSeg)->getNdf();
998  _chi2 += (*itSeg)->getChi2();
999  }
1000  //cout << " combined segment " << _hitList.size() << " " << _chi2 << " " << _ndf << endl;
1001  } else {
1002  // 'copy' input segment
1003  rb_Segment* seg(segments.front());
1004  _hitList = seg->getHitList();
1005  double refPoint[3];
1006  seg->getRefPoint(refPoint);
1007  _refX = refPoint[0];
1008  _refY = refPoint[1];
1009  _refZ = refPoint[2];
1010  _parameters = seg->getPar();
1011  _covariance = seg->getCov();
1012  _ndf = seg->getNdf();
1013  _chi2 = seg->getChi2();
1014  //cout << " single segment " << _hitList.size() << " " << _chi2 << " " << _ndf << endl;
1015  }
1016 }
1017 
1019 double rb_Segment::getBzc() const {
1020  return _bzc;
1021 }
1022 
1025  return _hitList.front()->getRow();
1026 }
1027 
1030  return _hitList.back()->getRow();
1031 }
1032 
1034 
1037 void rb_Segment::getRefPoint(double* position) const {
1038  position[0] = _refX;
1039  position[1] = _refY;
1040  position[2] = _refZ;
1041 }
1042 
1044 int rb_Segment::getNdf() const {
1045  return _ndf;
1046 }
1047 
1049 double rb_Segment::getChi2() const {
1050  return _chi2;
1051 }
1052 
1054 
1057 void rb_Segment::getPar(double* par) const {
1058  par[0] = 0.;
1059  for (int i = 0; i < _npar; ++i)
1060  par[5 - _npar + i] = _parameters[i];
1061 }
1062 
1065  return _hitList;
1066 }
1067 
1069 const TVectorD& rb_Segment::getPar() const {
1070  return _parameters;
1071 }
1072 
1074 const TMatrixDSym& rb_Segment::getCov() const {
1075  return _covariance;
1076 }
1077 
1079 int rb_Segment::getId() const {
1080  return _segId;
1081 }
1082 
1084 
1087 void rb_Segment::setId(int id) {
1088  _segId = id;
1089 }
1090 
1092 
1102 bool rb_Segment::match(rb_Segment* seg, const double chi2Cut, const int trpStepSize) const {
1103  int f1 = this->getFirstRow();
1104  int l1 = this->getLastRow();
1105  int f2 = seg->getFirstRow();
1106  int l2 = seg->getLastRow();
1107  // segments must not overlap (within triplet granularity)
1108  if (max(f1, f2) <= min(l1, l2) - trpStepSize) return false;
1109  // (row) gap must smaller than average size
1110  if (min(abs(l1 - f2), abs(l2 - f1)) > (l1 + l2 - f1 - f2) / 2) return false;
1111  // helices describing segments
1112  double refPoint1[3], refPoint2[3], par1[5], par2[5];
1113  this->getRefPoint(refPoint1);
1114  this->getPar(par1);
1115  simpleHelix hlx1(par1, refPoint1, _bzc);
1116  seg->getRefPoint(refPoint2);
1117  seg->getPar(par2);
1118  simpleHelix hlx2(par2, refPoint2, _bzc);
1119  // mid point
1120  const double xav = 0.5 * (refPoint1[0] + refPoint2[0]);
1121  const double yav = 0.5 * (refPoint1[1] + refPoint2[1]);
1122  const double zav = 0.5 * (refPoint1[2] + refPoint2[2]);
1123  TVectorD newPar1(_npar), newPar2(_npar);
1124  TMatrixDSym cov1(this->getCov()), cov2(seg->getCov()), newCov1(_npar), newCov2(_npar);
1125  // track states at midpoint
1126  hlx1.getStateAt(xav, yav, zav, cov1, newPar1, newCov1);
1127  hlx2.getStateAt(xav, yav, zav, cov2, newPar2, newCov2);
1128  TVectorD diffPar(newPar1 - newPar2);
1129  TMatrixDSym diffPrec(newCov1 + newCov2);
1130  diffPrec.Invert();
1131  // chi2
1132  double chi2 = diffPrec.Similarity(diffPar);
1133  //cout << " seg-match chi2 " << chi2 << endl;
1134  return (chi2 < chi2Cut * _npar);
1135 }
1136 
1138 
1146 bool rb_Segment::match(rb_Hit* hit, const double chi2Cut) const {
1147  double refPoint[3], par[5], pos[3], phiMeas, xyPos, zPos, sArc, phi, lambda;
1148  this->getRefPoint(refPoint);
1149  this->getPar(par);
1150  simpleHelix hlx(par, refPoint, _bzc);
1151  hit->getPos(pos);
1152  phiMeas = hit->getPhiMeas();
1153  // get prediction from helix
1154  if (!hlx.getExpectedPlanePos(pos, phiMeas, xyPos, zPos, sArc, phi, lambda)) return false;
1155  // cos(beta) (angle between measurement and normal to flight direction in XY)
1156  const double cosb2 = pow(sin(phiMeas - phi), 2);
1157  const double der2XY = (1. - cosb2) / cosb2;
1158  const double der2Z = pow(tan(lambda), 2) / cosb2;
1159  TVectorD newPar(_npar);
1160  TMatrixDSym cov(this->getCov()), newCov(_npar);
1161  // track state at predicted point
1162  pos[0] += xyPos * cos(phiMeas);
1163  pos[1] += xyPos * sin(phiMeas);
1164  pos[2] += zPos;
1165  hlx.getStateAt(pos[0], pos[1], pos[2], cov, newPar, newCov);
1166  double chi2xy = xyPos * xyPos / (newCov[_npar - 3][_npar - 3] / (cosb2) + hit->getVarXY(der2XY));
1167  double chi2z = zPos * zPos / (newCov[_npar - 1][_npar - 1] + hit->getVarZ(der2Z));
1168  //cout << " match hit, chi2 " << hit->getRow() << ": " << chi2xy << " " << chi2z << "/ " << zPos << endl;
1169  return (chi2xy < chi2Cut and chi2z < chi2Cut);
1170 }
1171 
1173 
1178 void rb_Segment::match(hitListType& hits, hitListType& matchingHits, const double chi2Cut) const {
1179  for (hitListType::iterator itHit = hits.begin(); itHit != hits.end(); ++itHit) {
1180  if ((*itHit)->getUsed()) continue; // hit already used
1181  if (this->match(*itHit, chi2Cut)) matchingHits.push_back(*itHit);
1182  }
1183 }
1184 
1186 
1194 void rb_Segment::getLCIOStateAtRefPoint(const double* refPos, TVectorD& newPar, TMatrixDSym& newCov) const {
1195  double refPoint[3], par[5];
1196  this->getRefPoint(refPoint);
1197  this->getPar(par);
1198  simpleHelix hlx(par, refPoint, _bzc);
1199  TVectorD tmpPar(_npar);
1200  TMatrixDSym cov(this->getCov()), tmpCov(_npar);
1201  // track state at reference point
1202  hlx.getStateAt(refPos[0], refPos[1], refPos[2], cov, tmpPar, tmpCov);
1203  TMatrixD hlx2LCIO = hlx.helixToLCIOJacobian().GetSub(0, 4, 5 - _npar, 4);
1204  newPar = hlx2LCIO * tmpPar;
1205  newCov = tmpCov.Similarity(hlx2LCIO);
1206 }
1207 
1210  double pos1[3], pos2[3];
1211  _hitList.front()->getPos(pos1);
1212  _hitList.back()->getPos(pos2);
1213  _refX = 0.5 * (pos1[0] + pos2[0]);
1214  _refY = 0.5 * (pos1[1] + pos2[1]);
1215  _refZ = 0.5 * (pos1[2] + pos2[2]);
1216 }
1217 
1219 void rb_Segment::fitSegment(double Bzc) {
1220  unsigned int nHit = _hitList.size();
1221  if (nHit < 4) {
1222  // to few hits
1223  _ndf = -1;
1224  _chi2 = -1.0;
1225  return;
1226  }
1227  //cout << " segment " << _hitList.size() << endl;
1228  calcRefPoint();
1229  double refPoint[] = { _refX, _refY, _refZ };
1230  //
1231  // fit segment
1232  //
1233  double pos[3], sArc, chi2XY, chi2ZS, cosb2, der2XY, derZ, phi, dzds;
1234  double parameters[] = { 0., 0., 0., 0., 0. };
1235  int nParXY, nPointXY, nPointZS, nParZS;
1236  // coarse unweighted xy prefit
1237  simpleFitXY xyPreFit((Bzc != 0.), _refX, _refY);
1238  for (hitListType::iterator itH = _hitList.begin(); itH != _hitList.end(); ++itH) {
1239  xyPreFit.addPoint((*itH)->getX(), (*itH)->getY(), 1.0);
1240  }
1241  nParXY = xyPreFit.fit(chi2XY, nPointXY);
1242  _parameters.SetSub(0, xyPreFit.getPar());
1243  for (int i = 0; i < nParXY; ++i)
1244  parameters[3 - nParXY + i] = _parameters[i];
1245  // simple helix
1246  simpleHelix hlx0(parameters, refPoint, Bzc);
1247  // xy fit (with weights)
1248  simpleFitXY xyFit((Bzc != 0.), _refX, _refY);
1249  for (hitListType::iterator itH = _hitList.begin(); itH != _hitList.end(); ++itH) {
1250  (*itH)->getPos(pos);
1251  sArc = hlx0.getArcLengthXY(pos);
1252  phi = parameters[0] * sArc + parameters[1];
1253  cosb2 = pow(sin(phi - (*itH)->getPhiMeas()), 2);
1254  der2XY = (1. - cosb2) / cosb2;
1255  xyFit.addPoint(pos[0], pos[1], 1.0 / ((*itH)->getVarXY(der2XY) * cosb2));
1256  }
1257  nParXY = xyFit.fit(chi2XY, nPointXY);
1258  _parameters.SetSub(0, xyFit.getPar());
1259  _covariance.SetSub(0, 0, xyFit.getCov());
1260  for (int i = 0; i < nParXY; ++i)
1261  parameters[3 - nParXY + i] = _parameters[i];
1262  // simple helix
1263  simpleHelix hlx(parameters, refPoint, Bzc);
1264  // coarse unweighted zs prefit
1265  simpleFitZS zsPreFit;
1266  for (hitListType::iterator itH = _hitList.begin(); itH != _hitList.end(); ++itH) {
1267  (*itH)->getPos(pos);
1268  sArc = hlx.getArcLengthXY(pos);
1269  zsPreFit.addPoint(sArc, pos[2] - _refZ, 1.0);
1270  }
1271  nParZS = zsPreFit.fit(chi2ZS, nPointZS);
1272  _parameters.SetSub(nParXY, zsPreFit.getPar());
1273  dzds = _parameters[nParXY];
1274  // zs fit (with weights)
1275  simpleFitZS zsFit;
1276  for (hitListType::iterator itH = _hitList.begin(); itH != _hitList.end(); ++itH) {
1277  (*itH)->getPos(pos);
1278  sArc = hlx.getArcLengthXY(pos);
1279  phi = parameters[0] * sArc + parameters[1];
1280  cosb2 = pow(sin(phi - (*itH)->getPhiMeas()), 2);
1281  derZ = dzds * dzds / cosb2;
1282  zsFit.addPoint(sArc, pos[2] - _refZ, 1.0 / (*itH)->getVarZ(derZ));
1283  }
1284  nParZS = zsFit.fit(chi2ZS, nPointZS);
1285  _parameters.SetSub(nParXY, zsFit.getPar());
1286  _covariance.SetSub(nParXY, nParXY, zsFit.getCov());
1287  // combine
1288  _ndf = nPointXY + nPointZS - _npar;
1289  _chi2 = chi2XY + chi2ZS;
1290  // cout << " cov " << endl; _covariance.Print();
1291 }
1292 
1294 
1297 void rb_Segment::fillRowMap(std::map<int, int>& rowMap) const {
1298  for (hitListType::const_iterator itH = _hitList.begin(); itH != _hitList.end(); ++itH)
1299  rowMap[(*itH)->getRow()] = 1;
1300 }
1301 
1303 
1309  const int row = hit->getRow();
1310  if (row > _hitList.back()->getRow())
1311  _hitList.push_back(hit); // add to end
1312  else {
1313  for (hitListType::iterator itH = _hitList.begin(); itH != _hitList.end(); ++itH)
1314  if ((*itH)->getRow() > row) {
1315  _hitList.insert(itH, hit);
1316  break;
1317  } // insert
1318  }
1319  hit->setUsed();
1320 }
1321 
1324  _index(), _matches() {
1325 }
1326 
1328 
1332  _index[aIndex] = aIndex;
1333 }
1334 
1336 
1339 void simpleEquiClasses::addMatch(std::pair<int, int> aMatch) {
1340  _matches.push_back(aMatch);
1341 }
1342 
1344 
1351 std::map<int, std::vector<int> > simpleEquiClasses::getClasses() {
1352  for (std::vector<std::pair<int, int> >::iterator it = _matches.begin(); it != _matches.end(); ++it) {
1353  int i1 = it->first; // trace first element up to is ancestor
1354  while (_index[i1] != i1)
1355  i1 = _index[i1];
1356  int i2 = it->second; // trace second element up to is ancestor
1357  while (_index[i2] != i2)
1358  i2 = _index[i2];
1359  if (i1 != i2) _index[i1] = i2;
1360  }
1361  // final sweep-up to highest ancestor
1362  for (std::map<int, int>::iterator it = _index.begin(); it != _index.end(); ++it) {
1363  int i1 = it->first;
1364  while (_index[i1] != _index[_index[i1]])
1365  _index[i1] = _index[_index[i1]];
1366  }
1367  std::map<int, std::vector<int> > classes;
1368  for (std::map<int, int>::iterator it = _index.begin(); it != _index.end(); ++it) {
1369  classes[it->second].push_back(it->first);
1370  }
1371  return classes;
1372 }
1373 
1374 } // close namespace brackets
1375 
1376 // #endif //#ifdef USE_ROWTRIPLETS
double _getVarXY(FloatVec)
Get variance in XY measurement direction (from float vector).
int fit(double &, int &)
Perform fit.
int getNdf() const
Get number of degrees of freedom (of segment fit).
int getLastRow() const
Get first last number.
double _segCut
Chi2/Ndf cut for segment matching (Ndf=4 for B off, 5 for B on)
double getCosBeta() const
Get cos(beta).
double getX() const
Get X coordinate.
double _getVarZ(FloatVec)
Get variance in Z measurement direction (from float vector).
double getVarZDir() const
Get Z variance (direction: tan(lambda)).
double getVarXY(const double=0.) const
Get XY variance.
void setUsed(const double)
Set use flag.
const double _hitVarR
variance in radial direction
bool match(rb_Hit *, const double, const double) const
Match doublet with third hit.
std::map< int, std::vector< int > > _modNeighbours
neighbour modules
double getCosBeta() const
Get cos(beta).
void getPar(double *) const
Get (all five helix) parameters from segment fit.
int getMod() const
Get module number.
void getPos(double *) const
Get position.
int _npar
number of parameters (5: helix, 4: line)
std::vector< rb_Triplet * > trpListType
const TVectorD & getPar() const
Get parameter vector.
std::map< int, segListType > modSegMapType
double getVarZ(const double=0.) const
Get Z variance.
TMatrixDSym getCov() const
Get covariance matrix.
double _chi2
chi2 from segment fit
double getPhiMeas() const
Get XY measurement direction.
bool match(rb_Segment *, const double, const int) const
Match segment with other segment.
std::map< int, std::vector< int > > getClasses()
Get equivalence classes.
double _refY
Y of reference point.
double _posCut
Chi2 cut for triplet position matching in XY and Z.
double getY() const
Get Y coordinate.
bool getExpectedPlanePos(const double *, const double, double &, double &, double &, double &, double &) const
Get expected position (and direction) in plane.
double getVarXYPos(const double=0.) const
Get XY variance (position).
void getPos(double *) const
Get position.
const TMatrixDSym & getCov() const
Get covariance matrix.
RowTripletBasedTrackFinderProcessor aRowTripletBasedTrackFinderProcessor
void addPoint(double, double, double)
Add point.
double getPhi() const
Get direction in XY.
void fillRowMap(std::map< int, int > &) const
Fill row map.
double getVarXYDir() const
Get XY variance (direction: phi).
void getStateAt(const double, const double, const double, TMatrixDSym &, TVectorD &, TMatrixDSym &)
Get state (parameters, covariance matrix) at point.
double getX() const
Get X coordinate.
double _trpCut
Chi2 cut for triplet definition on XY and Z residuals.
bool areNeighbourModules(gear::TPCModule *, gear::TPCModule *, bool)
Check if modules are neighbours.
double _bzc
magnetic field strength (Bz*c)
void fitSegment(double)
Fit segment from hits.
std::string _outputColName
Name of the output collection.
TMatrixDSym _covariance
covariance matrix
rb_Segment(double, trpListType)
Construct row based segment from (unused hits of) triplets.
int fit(double &, int &)
Perform fit.
const hitListType & getHitList() const
Get list of hits.
double _unusedCut
Chi2 cut for matching unused hits in XY and Z.
double _distCut
Coarse cut on XY and Z residuals for triplet preselection.
int getRow() const
Get row number.
double _dirCut
Chi2 cut for triplet direction matching in XY and Z.
int _ndf
number of degrees of freedom of segment fit
void calcRefPoint()
Calculate reference point (from first and last hit).
bool _refAtPCA
Use Pca as reference point (else 1. hit)
const int _hitNum
input hit collection index
double getPhiMeas() const
Get XY measurement direction (average of outer hits).
double getDistZ(const double) const
Get distance to point in Z.
std::vector< rb_Segment * > segListType
std::vector< rb_Hit * > hitListType
double getTanl() const
Get slope in ZS.
std::vector< std::pair< int, int > > _matches
list of matches
int _maxGap
Cut for (row) distance to segment for matching unused hits in XY and Z.
int getRow() const
Get row number (of center hit).
double getDistXY(const double, const double, const double, const double) const
Get distance to point in XY (along direction)
void getLCIOStateAtRefPoint(const double *, TVectorD &, TMatrixDSym &) const
Get segment state at reference point.
TVectorD getPar() const
Get parameters vector.
const double _hitPhiMeas
measurement direction in XY (tangential to row)
double getZ() const
Get Z coordinate.
void addPoint(double, double, double)
Add point.
double _getVarR(FloatVec)
Get variance in radial direction (from float vector).
double _refZ
Z of reference point.
double getZ() const
Get Z coordinate.
rb_Triplet(rb_Doublet &, rb_Hit *)
Construct row based triplet.
std::map< int, rowHitMapType > modHitMapType
int getHitNum() const
Get index to input hit collection.
bool getUsed() const
Get use flag.
void getParameters(double &, double &, double &, double &, double &, double &, double &, double &, double &, double &) const
Get parameters.
double _bfieldScaleFactor
scale factor for magnetic field (default: 1.0)
TMatrixDSym getCov() const
Get covariance matrix.
hitListType _hitList
pointers to hits
double getY() const
Get Y coordinate.
double getArcLengthXY(const double *) const
Get (2D) arc length for given point.
void addHit(rb_Hit *)
Add (unused) hit to segment.
double _refX
X of reference point.
rb_Doublet(rb_Hit *, rb_Hit *)
Construct row based doublet.
void getRefPoint(double *) const
Get reference point.
int getFirstRow() const
Get first row number.
rb_Hit * getHit(const int) const
Get hit.
TMatrixD helixToLCIOJacobian() const
Get transformation from helix to LCIO track parameters (at reference point)
virtual void processEvent(EVENT::LCEvent *evt)
Process event.
double getChi2() const
Get chi2 from segment fit.
std::map< int, hitListType > rowHitMapType
TVectorD getPar() const
Get parameters vector.
simpleEquiClasses()
Construct simple equivalence class.
rb_Hit * getHit(const int) const
Get hit.
rb_Hit(const int iHit, const int mod, const int row, const EVENT::TrackerHit &aHit)
Construct row based hit.
double _calcPhiMeas(const EVENT::TrackerHit &aHit)
Calculate measurement direction (in XY).
double getVarZPos(const double=0.) const
Get Z variance (position).
const double _hitVarZ
variance for Z measurement
bool match(rb_Triplet *, const double, const double) const
Match triplet with other triplet.
void addMatch(std::pair< int, int >)
Add match.
const double _hitVarXY
variance for XY measurement
void getPosCloseTo(const double, const double, double *, double &) const
Get position close to reference point.