12 #include <gear/TPCParameters.h> 13 #include <gear/BField.h> 14 #include <gearimpl/Vector3D.h> 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> 36 static bool comparePadRow(pb_Pulse* one, pb_Pulse* two) {
37 return ((one->getRow()) < (two->getRow()));
40 static bool comparePadCol(pb_Pulse* one, pb_Pulse* two) {
41 return ((one->getColumn()) < (two->getColumn()));
44 static bool compareRelCharge(pb_Pulse* one, pb_Pulse* two) {
45 return ((one->getRelCharge()) > (two->getRelCharge()));
48 static bool compareCharge(pb_Pulse* one, pb_Pulse* two) {
49 return ((one->getCharge()) > (two->getCharge()));
55 RowBasedPadPulseRoadSearchProcessor::RowBasedPadPulseRoadSearchProcessor() :
56 Processor(
"RowBasedPadPulseRoadSearchProcessor") {
58 _description =
"RowBasedPadPulseRoadSearchProcessor is intended to simultaneously find TPC hits and tracks";
60 registerInputCollection(LCIO::TRACKERPULSE,
"InputTrackerPulses",
"Name of the input TrackerPulses collection",
63 registerOutputCollection(LCIO::TRACKERHIT,
"OutputTrackerHits",
"Name of the output TrackerHits collection",
66 registerOutputCollection(LCIO::TRACK,
"OutputTracks",
"Name of the output Track Collection",
_outputTrackColName,
69 registerOptionalParameter(
"BFieldScaleFactor",
"Scales magnetic field (map), use 1.0 (default) for field ON or 0.0 for field OFF",
72 registerOptionalParameter(
"DriftVelocity",
"Drift velocity",
_driftVelocity,
double(74.0));
74 registerOptionalParameter(
"MaxColDiffNeighbourhood",
"Maximal column difference to pulse in neighbourhood",
_maxColDiff,
int(1));
76 registerOptionalParameter(
"MaxTimeDiff",
"Maximum drift time difference in neighboorhood/hit",
_dtMax,
double(80.0));
78 registerOptionalParameter(
"MaxSeedsInRow",
"Maximum number of seeding pulses in row",
_maxSeedsInRow,
int(10));
80 registerOptionalParameter(
"MinRowDiff",
"Minimum row difference for pulse pair seeding road",
_minRowDiff,
int(5));
82 registerOptionalParameter(
"MaxDxyRoad",
"Maximum interpolation deviation in XY (road search)",
_maxDxyRoad,
double(2.0));
84 registerOptionalParameter(
"MaxDzRoad",
"Maximum interpolation deviation in Z (road search)",
_maxDzRoad,
double(3.0));
86 registerOptionalParameter(
"MinRowNum",
"Minimum number of rows for segment seed",
_minRows,
int(6));
88 registerOptionalParameter(
"MinRowDensity",
"Minimum row 'density' for segment seed",
_rowDensityCut,
double(0.8));
90 registerOptionalParameter(
"MaxVarXY",
"Maximum (average) XY variance (unweighted Chi2/ndf) for segment seed",
_maxVarXY,
93 registerOptionalParameter(
"MaxOverlapFraction",
"Maximum overlap fraction of segment seeds",
_maxOverlapFraction,
double(0.5));
95 registerOptionalParameter(
"MaxColDiffHit",
"Maximum distance of pad to seed in hit (if > 0)",
_maxColDiffHit,
int(0));
97 registerOptionalParameter(
"MinNumPulses",
"Minimum number of pulses in hit",
_minNumPulses,
int(2));
99 registerOptionalParameter(
"MaxColGap",
"Maximum column gap in hit",
_maxColGap,
int(1));
101 registerProcessorParameter(
"OffsetCol",
"sigma0^2 in column direction",
_offsetCol,
double(0.0085));
103 registerProcessorParameter(
"SlopeCol",
"diffusion in column direction",
_slopeCol,
double(0.00011));
105 registerProcessorParameter(
"OffsetDrift",
"sigma0^2 in drift direction",
_offsetDrift,
double(0.25));
107 registerProcessorParameter(
"SlopeDrift",
"diffusion term in drift direction",
_slopeDrift,
double(0.));
109 registerProcessorParameter(
"OffsetRow",
"sigma0^2 in row direction",
_offsetRow,
double(0.));
111 registerProcessorParameter(
"SlopeRow",
"diffusion in row direction",
_slopeRow,
double(0.));
113 registerOptionalParameter(
"ChargeConversionFactor",
"Optional: The charge conversion factor from ADC values to primary electrons",
116 registerOptionalParameter(
"SegmentMatchingChi2Cut",
"Chi2/Ndf cut for segment matching (Ndf=4 for B off, 5 for B on)",
_segCut,
119 registerOptionalParameter(
"ReferencePointAtPca",
"Use PCA as reference point, else 1. hit",
_refAtPCA,
bool(
false));
121 registerOptionalParameter(
"SkipRoadSearch",
"Skip road search, hit finding only",
_skipRoadSearch,
bool(
false));
123 registerOptionalParameter(
"SkipMultiplePulses",
"Skip multiple pulse candidates as road search seeds",
_skipMultiplePulses,
129 streamlog_out(DEBUG) <<
" init() called " << endl;
131 const gear::TPCParameters& tpcParameters = Global::GEAR->getTPCParameters();
132 bool cartesian = (tpcParameters.getCoordinateType() == PadRowLayout2D::CARTESIAN);
133 const std::vector<TPCModule*> moduleVector = tpcParameters.getModules();
136 std::vector<double> xOffset;
137 for (std::vector<TPCModule*>::const_iterator itMod = moduleVector.begin(); itMod != moduleVector.end(); ++itMod) {
138 Vector2D offset = (*itMod)->getOffset();
139 xOffset.push_back(offset[0]);
141 sort(xOffset.begin(), xOffset.end());
144 std::vector<double> layerOffset;
145 layerOffset.push_back(xOffset.front());
146 for (std::vector<double>::iterator it = xOffset.begin() + 1; it != xOffset.end(); ++it)
147 if (abs(layerOffset.back() - (*it)) > eps) layerOffset.push_back(*it);
148 const int nLayer = layerOffset.size();
149 std::vector<int> layerRows(nLayer);
151 for (std::vector<TPCModule*>::const_iterator itMod = moduleVector.begin(); itMod != moduleVector.end(); ++itMod) {
152 Vector2D offset = (*itMod)->getOffset();
154 while (abs(layerOffset[layer] - offset[0]) > eps)
156 layerRows[layer] = max(layerRows[layer], (*itMod)->getNRows());
159 streamlog_out(DEBUG) <<
" Number of modules: " << moduleVector.size() << endl;
160 for (std::vector<TPCModule*>::const_iterator itMod = moduleVector.begin(); itMod != moduleVector.end(); ++itMod) {
161 int module = (*itMod)->getModuleID();
162 Vector2D offset = (*itMod)->getOffset();
165 while (abs(layerOffset[layer] - offset[0]) > eps) {
169 streamlog_out(DEBUG) <<
" module " << module <<
" with " << (*itMod)->getNRows() <<
" rows, offset " 171 const std::vector<double> modExtend = (*itMod)->getLocalModuleExtent();
173 Vector2D localOffset = (*itMod)->globalToLocal(offset[0], offset[1]);
174 for (std::vector<TPCModule*>::const_iterator itMod2 = itMod; itMod2 != moduleVector.end(); ++itMod2) {
177 streamlog_out(DEBUG) <<
" neighbour " << (*itMod2)->getModuleID() << endl;
183 _Xcenter = tpcParameters.getDoubleVal(
"TPC_cylinder_centre_c0");
184 _Ycenter = tpcParameters.getDoubleVal(
"TPC_cylinder_centre_c1");
193 std::clock_t start1 = std::clock();
195 streamlog_out(DEBUG) <<
"Event Number: " << evt->getEventNumber() << endl;
198 LCCollection* inputCol = 0;
200 LCCollectionVec* outputHitCol =
new LCCollectionVec(LCIO::TRACKERHIT);
203 LCFlagImpl hitFlag(0);
204 hitFlag.setBit(LCIO::RTHBIT_ID1);
205 outputHitCol->setFlag(hitFlag.getFlag());
207 LCCollectionVec* outputTrackCol =
new LCCollectionVec(LCIO::TRACK);
208 LCFlagImpl trkFlag(0);
209 trkFlag.setBit(LCIO::TRBIT_HITS);
210 outputTrackCol->setFlag(trkFlag.getFlag());
215 }
catch (DataNotAvailableException &e) {
221 Vector3D bfield = marlin::Global::GEAR->getBField().at(theTPCCenter);
222 const gear::TPCParameters& tpcParameters = Global::GEAR->getTPCParameters();
226 streamlog_out(DEBUG) <<
"BField(GEAR) is OFF" << std::endl;
228 streamlog_out(DEBUG) <<
"BField(GEAR) is ON" << std::endl;
233 UTIL::BitField64 encoder(lcio::ILDCellID0::encoder_string);
238 int nInput = inputCol->getNumberOfElements();
239 streamlog_out(DEBUG) <<
"Event " << evt->getEventNumber() <<
" in run " << evt->getRunNumber() <<
", number of input pulses: " 242 double maxDriftLength = tpcParameters.getMaxDriftLength();
243 Vector2D globalPadCenter;
244 for (
int iInput = 0; iInput < nInput; iInput++) {
245 TrackerPulse* aPulse =
dynamic_cast<TrackerPulse*
>(inputCol->getElementAt(iInput));
246 const int moduleID = aPulse->getCellID1();
247 const TPCModule& theModule = tpcParameters.getModule(moduleID);
251 double zPosition = maxDriftLength -
_driftVelocity * (aPulse->getTime()) / 1000.;
255 pulseData[moduleID][somePulse->getRow()].push_back(somePulse);
263 for (modPulseMapType::iterator itMod = pulseData.begin(); itMod != pulseData.end(); ++itMod) {
264 const int moduleID = itMod->first;
265 streamlog_out(DEBUG) <<
" === Module " << moduleID << std::endl;
266 const TPCModule& theModule = tpcParameters.getModule(moduleID);
270 for (rowPulseMapType::iterator itRow = modData.begin(); itRow != modData.end(); ++itRow) {
273 sort(itRow->second.begin(), itRow->second.end(), comparePadCol);
274 for (pulseListType::iterator itP1 = itRow->second.begin(); itP1 != itRow->second.end() - 1; ++itP1) {
275 int col1 = (*itP1)->getColumn();
277 for (pulseListType::iterator itP2 = itP1 + 1; itP2 != itRow->second.end(); ++itP2) {
278 int col2 = (*itP2)->getColumn();
280 if (col2 > col1 +
_maxColDiff or col2 > colLast + 1)
break;
282 if (abs((*itP1)->getTime() - (*itP2)->getTime()) <
_dtMax) {
284 (*itP1)->addNeighbour(*itP2);
285 (*itP2)->addNeighbour(*itP1);
290 const int numSeeding = seedingPulses.size();
291 for (pulseListType::iterator itP = itRow->second.begin(); itP != itRow->second.end(); ++itP) {
292 (*itP)->setIndex(itP - itRow->second.begin());
293 if ((*itP)->getRelCharge() > 1.0) {
294 leadingPulses.push_back(*itP);
296 if ((*itP)->isMaxPulse()) seedingPulses.push_back(*itP);
298 trailingPulses.push_back(*itP);
301 if (seedingPulses.size() >
static_cast<unsigned int>(numSeeding +
_maxSeedsInRow)) seedingPulses.resize(numSeeding);
304 streamlog_out(DEBUG) <<
" pulses (leading, seeding, trailing) " << leadingPulses.size() <<
" " << seedingPulses.size() <<
" " 305 << trailingPulses.size() <<
" " << std::endl;
307 sort(seedingPulses.begin(), seedingPulses.end(), compareRelCharge);
311 insidePulses.reserve(max(leadingPulses.size(), trailingPulses.size()));
315 double pos1[3], pos2[3];
316 for (pulseListType::iterator itP1 = seedingPulses.begin(); itP1 != seedingPulses.end(); ++itP1) {
317 if ((*itP1)->inSeed())
continue;
318 const int row1 = (*itP1)->getRow();
319 (*itP1)->getPos(pos1);
321 for (pulseListType::iterator itP2 = itP1 + 1; itP2 != seedingPulses.end(); ++itP2) {
322 if ((*itP2)->inSeed())
continue;
323 const int row2 = (*itP2)->getRow();
327 (*itP2)->getPos(pos2);
328 const double dx(pos2[0] - pos1[0]), dy(pos2[1] - pos1[1]), dz(pos2[2] - pos1[2]), dist = sqrt(dx * dx + dy * dy);
329 const double ex(dx / dist), ey(dy / dist), dzds(dz / dist);
331 insidePulses.clear();
332 int numNearPulses = 0;
333 for (pulseListType::iterator itP = leadingPulses.begin(); itP != leadingPulses.end(); ++itP) {
334 (*itP)->getPos(pos2);
335 const double dx(pos2[0] - pos1[0]), dy(pos2[1] - pos1[1]), dxy(dy * ex - dx * ey);
336 const double ds(dx * ex + dy * ey), dz(pos2[2] - pos1[2] - ds * dzds);
339 insidePulses.push_back(*itP);
344 if (insidePulses.size() <
static_cast<unsigned int>(
_minRows))
continue;
352 if (numNearPulses > 0) {
361 someSeed = iteratedSeed;
367 seedList.push_back(someSeed);
375 seedListType::iterator itWorst = seedList.end();
377 for (seedListType::iterator itS = seedList.begin(); itS != seedList.end(); ++itS) {
378 if (!(*itS)->getValid())
continue;
379 int numUnique = (*itS)->getNumUniqueSeedPulses();
380 int numAll = (*itS)->getNumSeedPulses();
381 if (numUnique < 4) numUnique = -1;
382 double fraction = double(numUnique) / double(numAll);
383 if (fraction < worstFraction) {
384 worstFraction = fraction;
388 if (itWorst == seedList.end())
break;
391 (*itWorst)->freePulses();
392 (*itWorst)->setInvalid();
397 for (seedListType::iterator itS = seedList.begin(); itS != seedList.end(); ++itS) {
398 if (!(*itS)->getValid())
continue;
399 int numUnique = (*itS)->getNumUniqueSeedPulses();
400 int numAll = (*itS)->getNumSeedPulses();
401 if (numUnique < numAll) {
402 const int seedId = (*itS)->getSeedId();
406 for (pulseListType::iterator itP = allPulses.begin(); itP != allPulses.end(); ++itP) {
407 if ((*itP)->getNumSeeds() < 2) uniquePulses.push_back(*itP);
417 double pos[3], refPoint[3], par[5], xyPos, zPos, sArc, phi, lambda;
418 int numAmbigousPulses = 0;
419 int numReattachedPulses = 0;
420 for (pulseListType::iterator itP = leadingPulses.begin(); itP != leadingPulses.end(); ++itP) {
421 if ((*itP)->getNumSeeds() < 2)
continue;
423 numAmbigousPulses += 1;
428 for (seedIdListType::iterator itId = seedIds.begin(); itId != seedIds.end(); ++itId) {
429 pb_Seed* aSeed = seedList[*itId];
436 if (abs(xyPos) < bestDist) {
438 bestDist = abs(xyPos);
443 (*itP)->clearSeeds();
447 numReattachedPulses += 1;
448 (*itP)->addSeed(bestId);
449 seedList[bestId]->addPulse(*itP);
453 for (seedListType::iterator itS = seedList.begin(); itS != seedList.end(); ++itS) {
454 if (!(*itS)->getValid())
continue;
455 if ((*itS)->hasAddedPulses()) {
465 for (seedListType::iterator itS = seedList.begin(); itS != seedList.end(); ++itS) {
466 if (!(*itS)->getValid())
continue;
470 for (pulseListType::iterator itP = insidePulses.begin(); itP != insidePulses.end(); ++itP)
471 (*itP)->addSeed(seedId);
475 for (pulseListType::iterator itP = trailingPulses.begin(); itP != trailingPulses.end(); ++itP) {
476 if ((*itP)->getNumSeeds() < 2)
continue;
478 numAmbigousPulses += 1;
483 for (seedIdListType::iterator itId = seedIds.begin(); itId != seedIds.end(); ++itId) {
484 pb_Seed* aSeed = seedList[*itId];
491 if (abs(xyPos) < bestDist) {
493 bestDist = abs(xyPos);
498 (*itP)->clearSeeds();
502 numReattachedPulses += 1;
503 (*itP)->addSeed(bestId);
510 for (rowPulseMapType::iterator itRow = modData.begin(); itRow != modData.end(); ++itRow) {
511 const int row = itRow->first;
513 const int numPulses = rowPulses.size();
514 const int firstCol = theModule.getPadNumber(theModule.getPadsInRow(row).front());
515 const int lastCol = theModule.getPadNumber(theModule.getPadsInRow(row).back());
520 for (pulseListType::const_iterator itP = rowPulses.begin(); itP != rowPulses.end(); ++itP)
521 if ((*itP)->getRelCharge() > 1.0) seedingPulses.push_back(*itP);
523 hitPulses.reserve(numPulses);
525 sort(seedingPulses.begin(), seedingPulses.end(), compareCharge);
526 for (pulseListType::iterator itP = seedingPulses.begin(); itP != seedingPulses.end(); ++itP) {
528 if ((*itP)->inHit())
continue;
530 const double tSeed = (*itP)->getTime();
531 const int indSeed = (*itP)->getIndex();
532 const int colSeed = (*itP)->getColumn();
534 hitPulses.push_back(*itP);
537 int segSeedId = (*itP)->getSeedId();
540 for (
int iDir = -1; iDir <= 1; iDir += 2) {
541 int ind = indSeed + iDir;
542 int colLast = colSeed;
544 while (ind >= 0 and ind < numPulses) {
545 pb_Pulse* somePulse = rowPulses[ind];
547 if (somePulse->
inHit())
continue;
549 const int colDiff = abs(col - colLast);
550 const int segId = somePulse->
getSeedId();
551 const int maxGap = (segId >= 0) and (segId == segSeedId) ?
_maxColGap : 0;
552 if (colDiff > maxGap + 1)
break;
553 if (abs(col - colSeed) > maxColDiffHit)
break;
554 double dTime = abs(somePulse->
getTime() - tSeed);
555 if (dTime >
_dtMax)
continue;
556 if ((segId >= 0) and (segId != segSeedId)) {
564 if (dTime >= dtLast)
continue;
565 hitPulses.pop_back();
574 hitPulses.push_back(somePulse);
581 std::reverse(hitPulses.begin(), hitPulses.end());
586 if (hitPulses.size() <
static_cast<unsigned int>(
_minNumPulses))
continue;
588 (*itP)->setHitNum(numHits);
590 Vector2D localPadCenter;
591 double sumCharge = 0.;
592 double varCharge = 0.;
593 double sumChargePhiMeas = 0.;
594 double localPosition[2] = { 0., 0. };
595 for (pulseListType::iterator itHitP = hitPulses.begin(); itHitP != hitPulses.end(); ++itHitP) {
596 (*itHitP)->addToHit();
597 const double charge = (*itHitP)->getCharge();
598 localPadCenter = theModule.globalToLocal((*itHitP)->getX(), (*itHitP)->getY());
600 sumChargePhiMeas += charge * (*itHitP)->getPhiMeas();
601 localPosition[0] += charge * localPadCenter[0];
602 localPosition[1] += charge * localPadCenter[1];
604 Vector2D globalPosition2D = theModule.localToGlobal(localPosition[0] / sumCharge, localPosition[1] / sumCharge);
605 const double position[3] = { globalPosition2D[0], globalPosition2D[1], (*itP)->getZ() };
607 float covMatrix[6] = { 0., 0., 0., 0., 0., 0. };
608 const double cosPhiMeas = cos(sumChargePhiMeas / sumCharge);
609 const double sinPhiMeas = sin(sumChargePhiMeas / sumCharge);
612 const double zDrift = std::max(maxDriftLength - position[2], 0.);
621 covMatrix[0] = pow(cosPhiMeas, 2) * phiSigmaSquare + pow(sinPhiMeas, 2) * rSigmaSquare;
622 covMatrix[1] = sinPhiMeas * cosPhiMeas * (phiSigmaSquare - rSigmaSquare);
623 covMatrix[2] = pow(sinPhiMeas, 2) * phiSigmaSquare + pow(cosPhiMeas, 2) * rSigmaSquare;
624 covMatrix[5] = float(zSigmaSquare);
626 TrackerHitImpl* theHit =
new TrackerHitImpl();
628 theHit->setPosition(position);
629 theHit->setCovMatrix(covMatrix);
631 theHit->setCellID1((*itP)->getPadId());
635 encoder[ILDCellID0::subdet] = ILDDetID::TPC;
636 encoder[ILDCellID0::layer] = layer;
637 encoder[ILDCellID0::module] = moduleID;
638 theHit->setCellID0(encoder.lowWord());
641 for (pulseListType::iterator itHitP = hitPulses.begin(); itHitP != hitPulses.end(); ++itHitP) {
642 TrackerPulse* aHitPulse =
dynamic_cast<TrackerPulse*
>(inputCol->getElementAt((*itHitP)->getPulseNum()));
643 theHit->rawHits().push_back(aHitPulse);
646 int pulseQuality = aHitPulse->getQuality();
652 varCharge += aHitPulse->getCovMatrix()[0];
654 theHit->setQuality(qualityFlag);
660 theHit->setTime((*itP)->getTime());
663 rb_Hit* someHit =
new rb_Hit(numHits, moduleID, layer, *theHit);
664 hitData.push_back(someHit);
666 outputHitCol->addElement(theHit);
671 for (seedListType::iterator itS = seedList.begin(); itS != seedList.end(); ++itS) {
673 if (!(*itS)->getValid())
continue;
676 for (pulseListType::iterator itP = seedPulses.begin(); itP != seedPulses.end(); ++itP) {
677 const int iHit = (*itP)->getHitNum();
678 if (iHit >= 0) seedHits.push_back(hitData[iHit]);
681 streamlog_out(DEBUG) <<
" segment " << seedHits.size() <<
" " << aSegment->
getChi2() <<
" " << aSegment->
getNdf()
683 if (aSegment->
getNdf() < 0)
686 segData[moduleID].push_back(aSegment);
690 for (seedListType::iterator itS = seedList.begin(); itS != seedList.end(); ++itS)
695 std::vector<std::pair<int, int> > segIndex;
698 for (modSegMapType::iterator itMod = segData.begin(); itMod != segData.end(); ++itMod) {
701 for (segListType::iterator itSeg = segments.begin(); itSeg != segments.end(); ++itSeg) {
702 (*itSeg)->setId(segIndex.size());
703 segIndex.push_back(make_pair(itMod->first, itSeg - segments.begin()));
704 segEquiClass.
addIndex((*itSeg)->getId());
710 for (modSegMapType::iterator itMod = segData.begin(); itMod != segData.end(); ++itMod) {
713 for (std::vector<int>::iterator itN = neighbours.begin(); itN != neighbours.end(); ++itN) {
715 for (segListType::iterator itSeg1 = segments1.begin(); itSeg1 != segments1.end(); ++itSeg1) {
716 for (segListType::iterator itSeg2 = segments2.begin(); itSeg2 != segments2.end(); ++itSeg2) {
718 if ((*itSeg1)->match(*itSeg2,
_segCut, 0)) {
721 segMatches.push_back(someMatch);
729 for (segMatchListType::iterator itM = segMatches.begin(); itM != segMatches.end(); ++itM) {
730 forwardMatches[(*itM)->getSegId1()].push_back((*itM));
731 backwardMatches[(*itM)->getSegId2()].push_back((*itM));
734 for (segMatchMapType::iterator itSid = forwardMatches.begin(); itSid != forwardMatches.end(); ++itSid) {
735 for (segMatchListType::iterator itM1 = itSid->second.begin(); itM1 != itSid->second.end() - 1; ++itM1) {
736 for (segMatchListType::iterator itM2 = itM1 + 1; itM2 != itSid->second.end(); ++itM2) {
737 if ((*itM1)->overlap(*itM2)) {
738 (*itM1)->setInvalid();
739 (*itM2)->setInvalid();
740 streamlog_out(DEBUG) <<
" overlap of forward matches " << (*itM1)->getSegId1() <<
" " << (*itM1)->getSegId2() <<
", " 741 << (*itM2)->getSegId1() <<
" " << (*itM2)->getSegId2() << std::endl;
747 for (segMatchMapType::iterator itSid = backwardMatches.begin(); itSid != backwardMatches.end(); ++itSid) {
748 for (segMatchListType::iterator itM1 = itSid->second.begin(); itM1 != itSid->second.end() - 1; ++itM1) {
749 for (segMatchListType::iterator itM2 = itM1 + 1; itM2 != itSid->second.end(); ++itM2) {
750 if ((*itM1)->overlap(*itM2)) {
751 (*itM1)->setInvalid();
752 (*itM2)->setInvalid();
753 streamlog_out(DEBUG) <<
" overlap of backward matches " << (*itM1)->getSegId1() <<
" " << (*itM1)->getSegId2() <<
", " 754 << (*itM2)->getSegId1() <<
" " << (*itM2)->getSegId2() << std::endl;
760 for (segMatchListType::iterator itM = segMatches.begin(); itM != segMatches.end(); ++itM)
761 if ((*itM)->getValid()) segEquiClass.
addMatch(make_pair((*itM)->getSegId1(), (*itM)->getSegId2()));
763 std::map<int, std::vector<int> > segClasses = segEquiClass.
getClasses();
765 for (std::map<
int, std::vector<int> >::iterator itC = segClasses.begin(); itC != segClasses.end(); ++itC) {
767 for (std::vector<int>::iterator itInd = itC->second.begin(); itInd != itC->second.end(); ++itInd) {
768 std::pair<int, int> index = segIndex[*itInd];
769 matchingSegments.push_back(segData[index.first][index.second]);
771 trackCandidates.push_back(
new rb_Segment(matchingSegments));
773 streamlog_out(DEBUG) <<
" found " << numHits <<
" hits, " << trackCandidates.size() <<
" track candidates " << endl;
776 for (segListType::iterator itSeg = trackCandidates.begin(); itSeg != trackCandidates.end(); ++itSeg) {
778 TrackImpl* theTrack =
new TrackImpl();
783 hits.front()->getPos(posFirst);
785 double refPos[] = { 0., 0., 0. };
787 refPos[0] = posFirst[0];
788 refPos[1] = posFirst[1];
789 refPos[2] = posFirst[2];
792 for (
int i = 0; i < 3; ++i)
793 refPoint[i] = refPos[i];
795 TVectorD parameters(5);
796 TMatrixDSym covariance(5);
797 (*itSeg)->getLCIOStateAtRefPoint(refPos, parameters, covariance);
799 theTrack->setOmega(parameters[2]);
800 theTrack->setTanLambda(parameters[4]);
801 theTrack->setPhi(parameters[1]);
802 theTrack->setD0(parameters[0]);
803 theTrack->setZ0(parameters[3]);
804 theTrack->setChi2((*itSeg)->getChi2());
805 theTrack->setNdf((*itSeg)->getNdf());
806 theTrack->setReferencePoint(refPoint);
812 float rInner = sqrt(pow(posFirst[0], 2) + pow(posFirst[1], 2));
813 theTrack->setRadiusOfInnermostHit(rInner);
815 float compressedCovariance[15];
817 for (
int i = 0; i < 5; ++i)
818 for (
int j = 0; j <= i; ++j)
819 compressedCovariance[ind++] = covariance[i][j];
820 theTrack->setCovMatrix(compressedCovariance);
822 for (hitListType::iterator itH = hits.begin(); itH != hits.end(); ++itH) {
823 TrackerHit* Hit =
dynamic_cast<TrackerHit*
>(outputHitCol->getElementAt((*itH)->getHitNum()));
824 theTrack->addHit(Hit);
827 streamlog_out(DEBUG) <<
" +++ the found track has a chi^2 value of " << theTrack->getChi2() <<
" for ndf = " 828 << theTrack->getNdf() <<
" and the parameters [omega, tanLambda, phi0, d0, z0] = [" << theTrack->getOmega() <<
"," 829 << theTrack->getTanLambda() <<
"," << theTrack->getPhi() <<
"," << theTrack->getD0() <<
"," << theTrack->getZ0()
830 <<
"] at the reference position [" << refPoint[0] <<
"," << refPoint[1] <<
"," << refPoint[2] <<
"]." << endl;
832 outputTrackCol->addElement(theTrack);
835 streamlog_out(DEBUG) <<
"RowBasedPadPulseRoadSearch ... done!" << endl;
837 outputHitCol->parameters().setValue(
"CellIDEncoding", ILDCellID0::encoder_string);
841 streamlog_out(DEBUG) << ((std::clock() - start1) / (
double) CLOCKS_PER_SEC) <<
" sec" << endl;
844 for (modPulseMapType::iterator itMod = pulseData.begin(); itMod != pulseData.end(); ++itMod) {
845 for (rowPulseMapType::iterator itRow = itMod->second.begin(); itRow != itMod->second.end(); ++itRow) {
846 for (pulseListType::iterator itP = itRow->second.begin(); itP != itRow->second.end(); ++itP) {
852 for (hitListType::iterator itH = hitData.begin(); itH != hitData.end(); ++itH)
855 for (modSegMapType::iterator itMod = segData.begin(); itMod != segData.end(); ++itMod) {
856 for (segListType::iterator itSeg = itMod->second.begin(); itSeg != itMod->second.end(); ++itSeg) {
861 for (segMatchListType::iterator itM = segMatches.begin(); itM != segMatches.end(); ++itM)
885 if (mod1 == mod2)
return false;
887 const std::vector<double> modExtend = mod1->getModuleExtent();
888 const double xm1 = 0.5 * (modExtend[1] + modExtend[0]), xs1 = 0.5 * (modExtend[1] - modExtend[0]);
889 const double ym1 = 0.5 * (modExtend[3] + modExtend[2]), ys1 = 0.5 * (modExtend[3] - modExtend[2]);
890 const std::vector<double> modExtend2 = mod2->getModuleExtent();
891 const double xm2 = 0.5 * (modExtend2[1] + modExtend2[0]), xs2 = 0.5 * (modExtend2[1] - modExtend2[0]);
892 const double ym2 = 0.5 * (modExtend2[3] + modExtend2[2]), ys2 = 0.5 * (modExtend2[3] - modExtend2[2]);
893 const double dx = xm2 - xm1, dy = ym2 - ym1;
894 return (pow(dx * dx + dy * dy, 2) / (pow((xs1 + xs2) * dx, 2) + pow((ys1 + ys2) * dy, 2)) < 2.);
904 pb_Pulse::pb_Pulse(
const int iPulse,
const EVENT::TrackerPulse& aPulse,
const gear::TPCModule& aModule,
const double zPos) :
905 _pulseNum(iPulse), _pulseModule(aPulse.getCellID1()), _pulsePadID(aPulse.getCellID0()), _pulseRow(
906 aModule.getRowNumber(_pulsePadID)), _pulseCol(aModule.getPadNumber(_pulsePadID)), _pulseQuality(aPulse.getQuality()), _pulseCharge(
907 aPulse.getCharge()), _pulseTime(aPulse.getTime()), _pulseX(aModule.getPadCenter(_pulsePadID)[0]), _pulseY(
908 aModule.getPadCenter(_pulsePadID)[1]), _pulseZ(zPos), _pulsePhiMeas(
909 (aModule.getLocalPadLayout().getCoordinateType() ==
gear::PadRowLayout2D::POLAR) ?
910 atan2((_pulseX - aModule.getOffset()[0]), (aModule.getOffset()[1] - _pulseY)) : aModule.getAngle()), _pulseDirX(
911 cos(_pulsePhiMeas)), _pulseDirY(sin(_pulsePhiMeas)), _firstCol(_pulseCol), _lastCol(_pulseCol), _maxCharge(0.), _sumCharge(
912 _pulseCharge), _sumChargeDist(0.), _seeds(), _inHit(false), _indexCol(-1), _hitNum(-1) {
1036 return (
_seeds.size() > 0);
1121 const double maxVarXY) :
1122 _seedId(seedId), _bzc(Bzc), _checked(true), _numPulses(pulses.size()), _pulseList(pulses), _valid(false), _npar(
1123 (Bzc != 0.) ? 5 : 4), _parameters(_npar) {
1128 int lastRow = firstRow;
1130 const int row = (*itP)->getRow();
1131 if (row > lastRow) {
1137 if (numRows < minRows or numRows < (lastRow + 1 - firstRow) * rowDensityCut)
return;
1156 int lastRow = firstRow;
1158 const int row = (*itP)->getRow();
1159 if (row > lastRow) {
1173 if ((*itP)->getRow() == largestPulse->
getRow()) {
1174 if ((*itP)->getCharge() > largestPulse->
getCharge()) largestPulse = *itP;
1176 fitPulses.push_back(largestPulse);
1177 largestPulse = *itP;
1180 fitPulses.push_back(largestPulse);
1182 double pos1[3], pos2[3];
1183 fitPulses.front()->
getPos(pos1);
1184 fitPulses.back()->getPos(pos2);
1185 _refX = 0.5 * (pos1[0] + pos2[0]);
1186 _refY = 0.5 * (pos1[1] + pos2[1]);
1187 _refZ = 0.5 * (pos1[2] + pos2[2]);
1189 int nParXY, nPointXY, nParZS, nPointZS;
1190 double pos[3], sArc, chi2XY, chi2ZS;
1191 double parameters[] = { 0., 0., 0., 0., 0. };
1194 for (pulseListType::iterator itP = fitPulses.begin(); itP != fitPulses.end(); ++itP) {
1195 (*itP)->getCOG(pos);
1196 xyFit.
addPoint(pos[0], pos[1], 1.0);
1198 nParXY = xyFit.
fit(chi2XY, nPointXY);
1200 _varXY = chi2XY / (nPointXY - nParXY);
1202 for (
int i = 0; i < nParXY; ++i)
1208 for (pulseListType::iterator itP = fitPulses.begin(); itP != fitPulses.end(); ++itP) {
1209 (*itP)->getCOG(pos);
1211 zsFit.
addPoint(sArc, pos[2] - _refZ, 1.0);
1213 nParZS = zsFit.
fit(chi2ZS, nPointZS);
1215 _varZS = chi2ZS / (nPointZS - nParZS);
1250 if ((*itP)->getNumSeeds() < 2) num++;
1273 position[0] =
_refX;
1274 position[1] =
_refY;
1275 position[2] =
_refZ;
1284 for (
int i = 0; i <
_npar; ++i)
1320 insidePulses.clear();
1323 double refPoint[3], par[5];
1328 double pos[3], xyPos, zPos, sArc, phi, lambda;
1329 for (pulseListType::iterator itP = pulses.begin(); itP != pulses.end(); ++itP) {
1330 (*itP)->getCOG(pos);
1333 if (abs(xyPos) < maxDxy and abs(zPos) < maxDz) insidePulses.push_back(*itP);
1345 _segId1(segment1->getId()), _segId2(segment2->getId()), _firstRow1(segment1->getFirstRow()), _firstRow2(
1346 segment2->getFirstRow()), _lastRow1(segment1->getLastRow()), _lastRow2(segment2->getLastRow()),
_valid(true) {
1396 return first1 <= last1 and first2 <= last2;
const int _firstRow1
first row of first segment
void addToHit()
Add to hit.
bool inHit() const
Is used by hit.
int fit(double &, int &)
Perform fit.
virtual void processEvent(EVENT::LCEvent *evt)
Process event.
const double _pulsePhiMeas
measurement direction in XY (tangential to row)
int getNdf() const
Get number of degrees of freedom (of segment fit).
double getY() const
Get Y coordinate.
std::vector< rb_SegmentMatch * > segMatchListType
bool _skipRoadSearch
skip road search, hit finding only
const int _pulsePadID
pad ID
const double _bzc
magnetic field strength (Bz*c)
const int _segId2
second segment ID
int getLastRow2() const
Get last row of second segment.
int getNumSeeds() const
Get number of seeds.
double _slopeRow
measurement variance: diffusion term in row direction
std::map< int, std::vector< int > > _modNeighbours
neighbour modules
void getCOG(double *) const
Get (COG) )position.
double getRelCharge() const
Get relative charge.
int getSeedId() const
Get (unique) seedId.
void clearSeeds()
Clear (list of) seeds.
double _offsetRow
measurement variance: sigma0^2 in row direction (use rowHeight^2/12. if < 0.)
bool inSeed() const
Is used by seed.
std::map< int, pulseListType > rowPulseMapType
int getHitNum() const
Get hit number.
std::map< int, int > _moduleRowOffset
row offsets per module layer
std::vector< pb_Pulse * > pulseListType
const pulseListType & getPulseList() const
Get list of pulses.
int getQuality() const
Get quality.
int getPadId() const
Get pad ID.
int getFirstRow2() const
Get first row of second segment.
Simultaneous hit and track finding (pad row based).
void addSeed(int)
Add (segment) seed.
double getCharge() const
Get charge.
bool isAnomalousShape(int j)
int getRow() const
Get row.
std::list< int > seedIdListType
std::map< int, segListType > modSegMapType
void setMultipleHitCandidate(int &r)
bool isPlateauCutoff(int l)
void setPlateauCutoffPulse(int &t)
double getVarXY() const
Get XY variance (unweighted Chi2/ndf).
pulseListType _pulseList
pointers to pulses
double _offsetDrift
measurement variance: sigma0^2 in drift direction
double _Bzc
magnetic field strength (Bz*c)
const int _lastRow2
last row of second segment
virtual void init()
Initialize processor.
int _maxColDiffHit
maximum distance of pad to seed in hit (if > 0)
const double _pulseX
X position (local)
bool areNeighbourModules(gear::TPCModule *, gear::TPCModule *, bool)
Check if modules are neighbours.
void setOverflowPulse(int &m)
int _maxColDiff
maximal column difference to pulse in neighbourhood
std::map< int, std::vector< int > > getClasses()
Get equivalence classes.
void getRefPoint(double *) const
Get reference point.
const int _pulseNum
input pulse collection index
bool getExpectedPlanePos(const double *, const double, double &, double &, double &, double &, double &) const
Get expected position (and direction) in plane.
void getMeasDir(double *) const
Get measurement direction.
int getSegId1() const
Get ID of first segment.
void freePulses()
Free pulses.
double _maxOverlapFraction
maximum overlap fraction of segment seeds
bool getValid() const
Get validity flag.
int getIndex() const
Get (column) index.
int getNumSeedPulses() const
Get number of seed pulses.
void addPoint(double, double, double)
Add point.
std::string _outputTrackerHitsColName
Name of the TPC hit output collection.
const unsigned int _numPulses
number of pulses
std::string _inputTrackerPulsesColName
Name of the TPc pulse input collection.
TVectorD _parameters
parameter vector
int getModule() const
Get module.
void markPulses()
Mark pulses as used.
void setInvalid()
Set invalid.
double _dtMax
maximum drift time difference in neighboorhood/hit
double _rowDensityCut
minimum row 'density' for segment seed
const double _pulseTime
drift time
bool getValid() const
Get validity flag.
double _sumCharge
sum of charge in local neigbourhood
int _firstCol
start (column) of local neigbourhood
void addNeighbour(pb_Pulse *)
Add neighbour.
std::string _outputTrackColName
Name of the track output collection.
const int _pulseModule
module number
void addIndex(int)
Add index.
pb_Seed(const int seedID, const double Bzc, const pulseListType &pulses, const int minRows, const double rowDensityCut, const double maxVarXY)
Construct pad based seed with checks.
double _Ycenter
TPC center, Y coordinate.
int _minNumPulses
minimum number of pulses in hit
int _minRows
minimum number of rows for segment seed
void setHitNum(int)
Set hit number.
int fit(double &, int &)
Perform fit.
double getZ() const
Get Z coordinate.
double _varZS
chi2/ndf from (unweighted) ZS fit
rb_SegmentMatch(const rb_Segment *segment1, const rb_Segment *segment2)
Construct row based segment match.
const double _pulseY
Y position (local)
double _maxDxyRoad
maximum interpolation deviation in XY (road search)
virtual void check(EVENT::LCEvent *evt)
void roadSearch(pulseListType &pulses, pulseListType &insidePulses, const double maxDxy, const double maxDz) const
Road search.
double _maxCharge
maximum charge in local neigbourhood
int _indexCol
index in list of pulses per row
int _maxSeedsInRow
maximum number of seeding pulses in row
void setInvalid()
Set invalid.
const double _pulseDirY
measurement direction in Y
const double _pulseCharge
charge
int _minRowDiff
minimum row difference for pulse pair seeding road
Pad based (track segment) seed.
double getX() const
Get X coordinate.
const int _pulseQuality
quality
bool isMultiplePulseCandidate(int i)
int getSeedId() const
Get seed ID.
std::vector< rb_Segment * > segListType
std::vector< rb_Hit * > hitListType
virtual void processRunHeader(EVENT::LCRunHeader *run)
void setIndex(int)
Set (column) index.
const int _lastRow1
last row of first segment
TVectorD getPar() const
Get parameters vector.
double _varXY
chi2/ndf from (unweighted) XY fit
bool hasAddedPulses() const
Get flag for added pulses.
int getLastRow1() const
Get last row of first segment.
void addPoint(double, double, double)
Add point.
void setSplitPulse(int &n)
double _segCut
Chi2/Ndf cut for segment matching (Ndf=4 for B off, 5 for B on)
void setDeadChannel(int &i)
bool _inHit
flag for being part of a hit
int _lastCol
end (column) of local neigbourhood
double _maxVarXY
maximum (average) XY variance (unweighted Chi2/ndf) for segment seed
void getPos(double *) const
Get (pad) position.
seedIdListType _seeds
list of seeds (using pulse)
double _slopeCol
measurement variance: diffusion term in column direction
bool _refAtPCA
Use Pca as reference point (else 1. hit)
double _sumChargeDist
sum of charge*distance (to pulse) in local neigbourhood
double _driftVelocity
drift velocity
int getPulseNum() const
Get pulse number.
bool isMaxPulse() const
Is pulse with maximal charge in neighbourhood.
const double _pulseDirX
measurement direction in X
const seedIdListType & getSeedIdList() const
Get list of seeds.
void removeSeed(int)
Remove (segment) seed.
const double _pulseZ
Z position.
int getFirstRow1() const
Get first row of first segment.
void addPulse(pb_Pulse *)
Add pulse.
double getArcLengthXY(const double *) const
Get (2D) arc length for given point.
double _refZ
Z of reference point.
int _hitNum
index of seeded hit
double _refX
X of reference point.
int getNumUniqueSeedPulses() const
Get number of unique seed pulses.
std::map< int, segMatchListType > segMatchMapType
double _Xcenter
TPC center, X coordinate.
const int _firstRow2
first row of second segment
bool _skipMultiplePulses
skip multiple pulse candidates as road search seeds
void getPar(double *) const
Get (all five helix) parameters from segment fit.
double getChi2() const
Get chi2 from segment fit.
double _offsetCol
measurement variance: sigma0^2 in column direction
pb_Pulse(const int iPulse, const EVENT::TrackerPulse &aPulse, const gear::TPCModule &aModule, const double zPos)
Construct pad based Pulse.
const bool _checked
checked flag
const int _pulseCol
column number
RowBasedPadPulseRoadSearchProcessor aRowBasedPadPulseRoadSearchProcessor
std::vector< pb_Seed * > seedListType
TVectorD getPar() const
Get parameters vector.
const int _pulseRow
row number
double getTime() const
Get time.
std::map< int, rowPulseMapType > modPulseMapType
bool overlap(rb_SegmentMatch *) const
Check for (row) overlap.
const int _segId1
first segment ID
double _slopeDrift
measurement variance: diffusion term in drift direction
void setAtModuleBorder(int &k)
int getSegId2() const
Get ID of second segment.
int getColumn() const
Get column.
void setAnomalousPulseShape(int &p)
double _maxDzRoad
maximum interpolation deviation in Z (road search)
int _maxColGap
maximum column gap in hit
double _refY
Y of reference point.
double _chargeConversionFactor
charge conversion factor from ADC values to primary electrons
double getPhiMeas() const
Get measurement angle.
int _npar
number of parameters (5: helix, 4: line)
void addMatch(std::pair< int, int >)
Add match.
double _bfieldScaleFactor
scale factor for magnetic field (default: 1.0)