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> 35 static bool compare(pair<unsigned int, float> one, pair<unsigned int, float> two) {
36 return ((one.second) > (two.second));
42 RowBasedFastHoughTransformationProcessor::RowBasedFastHoughTransformationProcessor() :
43 Processor(
"RowBasedFastHoughTransformationProcessor") {
45 _description =
"RowBasedFastHoughTransformationProcessor is intended to ...";
47 registerInputCollection(LCIO::TRACKERHIT,
"InputHits",
"Name of the input Hit Collection",
_inputColName,
string(
"TPCHits"));
48 registerOutputCollection(LCIO::TRACK,
"OutputTracks",
"Name of the output Track Collection",
_outputColName,
string(
"FHTTracks"));
50 registerOptionalParameter(
"BFieldScaleFactor",
"Scales magnetic field (map), use 1.0 (default) for field ON or 0.0 for field OFF",
53 registerProcessorParameter(
"CenterXYMeasurement",
"Center of XY (anode plane) measurement",
_centerXY,
double(60.));
55 registerProcessorParameter(
"RangeXYMeasurement",
"Range of XY (anode plane) measurement",
_rangeXY,
double(200.));
57 registerProcessorParameter(
"CenterXZMeasurement",
"Center of XZ (drift time) measurement",
_centerXZ,
double(300.));
59 registerProcessorParameter(
"RangeXZMeasurement",
"Range of XZ (drift time) measurement",
_rangeXZ,
double(600.));
61 registerOptionalParameter(
"UseXYMeasurement",
"Use XY (anode plane) measurement",
_useXY,
bool(
true));
63 registerOptionalParameter(
"UseXZMeasurement",
"Use XZ (drift time) measurement",
_useXZ,
bool(
true));
65 registerOptionalParameter(
"MinimumRows",
"Minimal number of (correlated) rows ",
_minRow,
int(8));
67 registerOptionalParameter(
"MaximumRowDifference",
"Row correation parameter ",
_maxRowDiff,
int(1));
69 registerOptionalParameter(
"FractionOfRows",
"Relative minimum cube content (rows >= fraction * (correlated) rows) ",
_fracRow,
72 registerOptionalParameter(
"MaximumCubes",
"Maximum number of (hyper) cubes to check ",
_maxCube,
int(250));
74 registerOptionalParameter(
"MinimumLevel",
"Minimum number of (hyper) cubes splittings ",
_minLevel,
int(5));
76 registerOptionalParameter(
"MaximumLevel",
"Maximum number of (hyper) cubes splittings ",
_maxLevel,
int(8));
78 registerOptionalParameter(
"EfficienyCut",
"Minimum hit density (hits/tracklength) ",
_effCut,
float(0.8));
80 registerOptionalParameter(
"PurityCut",
"Maximum hit density (hits/tracklength) ",
_purCut,
float(1.1));
82 registerOptionalParameter(
"MaxHitsPerRow",
"Maximum number of hits per row ",
_maxHitsPerRow,
int(1));
84 registerOptionalParameter(
"UnusedHitMatchingChi2Cut",
"Chi2 cut for matching unused hits in XY and Z",
_unusedCut,
double(20.0));
86 registerOptionalParameter(
"UnusedHitMaxGapCut",
"Maximal (row) gap for matching unused hits in XY and Z",
_maxGap,
int(4));
88 registerOptionalParameter(
"EncodedModuleID",
"Module ID encoded in CellID0",
_encodedModuleID,
bool(
true));
90 registerOptionalParameter(
"ReferencePointAtPca",
"Use PCA as reference point, else 1. hit",
_refAtPCA,
bool(
false));
92 registerOptionalParameter(
"TimePixFlag",
"Is timepix data",
_timePixFlag,
bool(
false));
98 m_out(DEBUG) <<
" init() called " << endl;
108 std::clock_t start1 = std::clock();
110 m_out(DEBUG) <<
"Event Number: " << evt->getEventNumber() << endl;
113 LCCollection* inputCol = 0;
115 LCCollectionVec* outputCol =
new LCCollectionVec(LCIO::TRACK);
116 LCFlagImpl trkFlag(0);
117 trkFlag.setBit(LCIO::TRBIT_HITS);
118 outputCol->setFlag(trkFlag.getFlag());
123 }
catch (DataNotAvailableException &e) {
129 Vector3D bfield = marlin::Global::GEAR->getBField().at(theTPCCenter);
133 m_out(DEBUG) <<
"BField(GEAR) is OFF" << std::endl;
135 m_out(DEBUG) <<
"BField(GEAR) is ON" << std::endl;
141 unsigned int setup[] = { 3, 2 };
142 if (bOff) setup[0] = 2;
143 if (!
_useXY) setup[0] = 0;
144 if (!
_useXZ) setup[1] = 0;
145 if (setup[0] + setup[1] == 0) {
146 m_out(ERROR) <<
" No active parameters ";
155 UTIL::BitField64 encoder(lcio::ILDCellID0::encoder_string);
156 int nInput = inputCol->getNumberOfElements();
157 m_out(DEBUG) <<
"Event " << evt->getEventNumber() <<
" in run " << evt->getRunNumber() <<
", number of input hits: " << nInput
161 for (
int iInput = 0; iInput < nInput; iInput++) {
162 TrackerHit* Hit =
dynamic_cast<TrackerHit*
>(inputCol->getElementAt(iInput));
163 encoder.setValue(Hit->getCellID0());
164 int mod = Hit->getCellID1();
165 int rowLoc = Hit->getCellID0() % 256 + mod * 256;
166 int row = (rowLoc > 1023) ? rowLoc - 1024 : 1023 - rowLoc;
168 hitData[row].push_back(someHit);
171 for (
int iInput = 0; iInput < nInput; iInput++) {
172 TrackerHit* Hit =
dynamic_cast<TrackerHit*
>(inputCol->getElementAt(iInput));
173 encoder.setValue(Hit->getCellID0());
176 encoder[ILDCellID0::module] :
177 Global::GEAR->getTPCParameters().getNearestModule(Hit->getPosition()[0], Hit->getPosition()[1]).getModuleID();
178 int row = encoder[ILDCellID0::layer];
180 hitData[row].push_back(someHit);
195 double xMin = 0., xMax = 0.;
196 for (rowHitMapType::iterator itRow = hitData.begin(); itRow != hitData.end(); ++itRow) {
197 const int row = itRow->first;
199 for (hitListType::iterator itHit = itRow->second.begin(); itHit != itRow->second.end(); ++itHit) {
200 if (!(*itHit)->getUsed()) {
201 double x = (*itHit)->getX();
218 m_out(DEBUG) <<
" ... rows " << numRows <<
" " << numRows2 << endl;
221 const double xCenter = 0.5 * (xMin + xMax);
222 const double xRange = 0.5 * (xMax - xMin);
224 rootDistances.reserve(nInput * dimension);
226 rootPlanes.reserve(nInput);
229 for (rowHitMapType::iterator itRow = hitData.begin(); itRow != hitData.end(); ++itRow) {
232 for (hitListType::iterator itHit = itRow->second.begin(); itHit != itRow->second.end(); ++itHit) {
233 if (!(*itHit)->getUsed()) {
234 const double u = ((*itHit)->getX() - xCenter) / xRange;
240 unsigned int ndim = 0;
241 for (
unsigned int idim = 0; idim < 2; idim++) {
242 if (setup[idim] > 0) {
246 if (setup[idim] > 2) vec[2] = 1.5 * u * u - 0.5;
248 for (doubleListType::iterator i = vec.begin(); i != vec.end(); ++i)
250 const double norm = sqrt(sum2);
251 for (doubleListType::iterator i = vec.begin(); i != vec.end(); ++i)
254 double r = -v[idim] / norm;
255 inside = inside and (abs(r * vec[0]) < 0.5);
256 dist[ndim++] = int(scale * r);
261 for (
unsigned int idim = 0; idim < ndim; idim++)
262 rootDistances.push_back(dist[idim]);
263 rootPlanes.push_back(hp);
268 m_out(DEBUG) <<
"rootPlanes " << rootPlanes.size() << endl;
269 if (rootPlanes.size() <
static_cast<unsigned int>(
_minRow))
break;
273 int minCubeRows = int(
float(numRows2) *
_fracRow);
274 m_out(DEBUG) <<
"minCubeRows " << minCubeRows << endl;
277 m_out(DEBUG) <<
"Candidate " << candidate.size() << endl;
279 if (candidate.size() > 0) {
283 if (aSegment->
getNdf() < 0)
288 map<int, int> rowMap;
292 for (
int row = centerRow + 1; row <= hitData.rbegin()->first; ++row) {
294 if (rowMap.count(row) > 0)
continue;
297 if (hits.size() <= maxHitsPerRow)
for (hitListType::iterator itHit = hits.begin(); itHit != hits.end(); ++itHit)
301 for (
int row = centerRow; row >= hitData.begin()->first; --row) {
302 if (row < aSegment->getFirstRow() -
_maxGap)
break;
303 if (rowMap.count(row) > 0)
continue;
306 if (hits.size() <= maxHitsPerRow)
for (hitListType::iterator itHit = hits.begin(); itHit != hits.end(); ++itHit)
310 trackCandidates.push_back(aSegment);
311 m_out(DEBUG) <<
"Segment " << trackCandidates.size() <<
" " << aSegment->
getHitList().size() << endl;
316 for (hyperPlaneListType::iterator itHp = rootPlanes.begin(); itHp != rootPlanes.end(); ++itHp)
319 rootDistances.clear();
322 m_out(DEBUG) <<
" found " << trackCandidates.size() <<
" track candidates " << endl;
325 for (segListType::iterator itSeg = trackCandidates.begin(); itSeg != trackCandidates.end(); ++itSeg) {
327 TrackImpl* theTrack =
new TrackImpl();
332 hits.front()->getPos(posFirst);
334 double refPos[] = { 0., 0., 0. };
336 refPos[0] = posFirst[0];
337 refPos[1] = posFirst[1];
338 refPos[2] = posFirst[2];
341 for (
int i = 0; i < 3; ++i)
342 refPoint[i] = refPos[i];
344 TVectorD parameters(5);
345 TMatrixDSym covariance(5);
346 (*itSeg)->getLCIOStateAtRefPoint(refPos, parameters, covariance);
348 theTrack->setOmega(parameters[2]);
349 theTrack->setTanLambda(parameters[4]);
350 theTrack->setPhi(parameters[1]);
351 theTrack->setD0(parameters[0]);
352 theTrack->setZ0(parameters[3]);
353 theTrack->setChi2((*itSeg)->getChi2());
354 theTrack->setNdf((*itSeg)->getNdf());
355 theTrack->setReferencePoint(refPoint);
361 float rInner = sqrt(pow(posFirst[0], 2) + pow(posFirst[1], 2));
362 theTrack->setRadiusOfInnermostHit(rInner);
364 float compressedCovariance[15];
366 for (
int i = 0; i < 5; ++i)
367 for (
int j = 0; j <= i; ++j)
368 compressedCovariance[ind++] = covariance[i][j];
369 theTrack->setCovMatrix(compressedCovariance);
371 for (hitListType::iterator itH = hits.begin(); itH != hits.end(); ++itH) {
372 TrackerHit* Hit =
dynamic_cast<TrackerHit*
>(inputCol->getElementAt((*itH)->getHitNum()));
373 theTrack->addHit(Hit);
376 m_out(DEBUG) <<
" +++ the found track has a chi^2 value of " << theTrack->getChi2() <<
" for ndf = " << theTrack->getNdf()
377 <<
" and the parameters [omega, tanLambda, phi0, d0, z0] = [" << theTrack->getOmega() <<
"," << theTrack->getTanLambda()
378 <<
"," << theTrack->getPhi() <<
"," << theTrack->getD0() <<
"," << theTrack->getZ0() <<
"] at the reference position [" 379 << refPoint[0] <<
"," << refPoint[1] <<
"," << refPoint[2] <<
"]." << endl;
381 outputCol->addElement(theTrack);
384 m_out(DEBUG) <<
"RowBasedFastHoughTransformation ... done!" << endl;
386 if (!outputCol->empty()) {
390 m_out(DEBUG) << ((std::clock() - start1) / (
double) CLOCKS_PER_SEC) <<
" sec" << endl;
393 for (rowHitMapType::iterator itRow = hitData.begin(); itRow != hitData.end(); ++itRow) {
394 for (hitListType::iterator itH = itRow->second.begin(); itH != itRow->second.end(); ++itH) {
401 for (segListType::iterator itSeg = trackCandidates.begin(); itSeg != trackCandidates.end(); ++itSeg) {
404 trackCandidates.clear();
425 _scaleBits(scaleBits), _hit(hit), _cut(), _steps() {
427 for (directionsType::iterator itDir = dirList.begin(); itDir != dirList.end(); ++itDir) {
428 _cut.push_back(
int(scale * distCut / (*itDir)[0]));
429 const unsigned int nSteps = 1 << itDir->size();
431 for (
unsigned int i = 0; i < nSteps; i++) {
434 for (doubleListType::iterator itNum = itDir->begin(); itNum != itDir->end(); ++itNum) {
435 step += (ii % 2 == 1) ? 0.5 * (*itNum) : -0.5 * (*itNum);
438 aSteps[i] = int(scale * step);
447 <<
_cut.back() << endl;
493 _planes(planes), _distances(distances), _level(level) {
497 _dimension = (setup[0] > 0 and setup[1] > 0) ? 2 : 1;
498 if (level == 0)
nCube = 0;
526 int scaleBits =
_planes.front()->getScaleBits();
527 int halfScale = scaleBits / 2;
528 int nChild0 = 1 <<
_setup[0];
529 int nChild1 = 1 <<
_setup[1];
531 unsigned int iOff = 0;
532 for (hyperPlaneListType::iterator itHp =
_planes.begin(); itHp !=
_planes.end(); ++itHp) {
538 vector<pair<int, int> > distNew1;
539 distNew1.reserve(nChild1);
540 for (
int b1 = 0; b1 < nChild1; b1++) {
542 if (abs(distChild1) < hp->
getCut(1)) distNew1.push_back(make_pair(b1, distChild1));
544 for (
int b0 = 0; b0 < nChild0; b0++) {
546 if (abs(distChild0) < hp->
getCut(0)) {
547 distChild0 >>= halfScale;
548 for (vector<pair<int, int> >::iterator itP = distNew1.begin(); itP != distNew1.end(); ++itP) {
549 int distChild1 = itP->second >> halfScale;
550 int b = b0 + (itP->first <<
_setup[0]);
552 if (row > lastRow[b]) {
556 sum2[b] += distChild0 * distChild0 + distChild1 * distChild1;
564 if (abs(distChild) < hp->
getCut(0)) {
565 distChild >>= halfScale;
567 if (row > lastRow[b]) {
571 sum2[b] += distChild * distChild;
578 vector<pair<unsigned int, int> > childList;
581 if (numRows[b] >= minRows) {
582 int weight = (numRows[b] << scaleBits) - (sum2[b] / numHits[b]);
583 childList.push_back(make_pair(b, weight));
586 sort(childList.begin(), childList.end(), compare);
588 for (vector<pair<unsigned int, int> >::iterator itP = childList.begin(); itP != childList.end(); ++itP) {
589 unsigned int b = itP->first;
592 childPlanes.reserve(numHits[b]);
594 childDistances.reserve(numHits[b] *
_dimension);
595 int b0 = b % (1 <<
_setup[0]);
598 for (hyperPlaneListType::iterator itHp =
_planes.begin(); itHp !=
_planes.end(); ++itHp) {
600 if (_dimension == 2) {
603 if (abs(distNew0) < hp->
getCut(0) and abs(distNew1) < hp->
getCut(1)) {
604 childPlanes.push_back(hp);
605 childDistances.push_back(distNew0);
606 childDistances.push_back(distNew1);
610 if (abs(distNew0) < hp->
getCut(0)) {
611 childPlanes.push_back(hp);
612 childDistances.push_back(distNew0);
618 int rowLength = childPlanes.back()->getRow() - childPlanes.front()->getRow() + 1;
619 float density = float(numHits[b]) / float(rowLength);
623 if ((effCut < density) && (density < purCut)) {
625 for (hyperPlaneListType::iterator itHp = childPlanes.begin(); itHp != childPlanes.end(); ++itHp)
626 hits.push_back((*itHp)->getHit());
633 if (
nCube > maxCube)
return hits;
634 hitListType candidate = newCube.
divide(maxCube, minRows, minLevel, maxLevel, effCut, purCut);
635 if (candidate.size() > 0)
return candidate;
int getNdf() const
Get number of degrees of freedom (of segment fit).
rb_Hit * _hit
pointers to hit
int getLastRow() const
Get first last number.
int _numChild
number of child cubes
std::vector< rb_HyperPlane * > _planes
list of hyperplanes
int _level
(splitting) level
unsigned int _setup[2]
setup (number of parameters for pad plane (3), drift time measurement (2))
std::vector< double > doubleListType
intListType getCut() const
Get distance cut(s).
bool match(rb_Segment *, const double, const int) const
Match segment with other segment.
std::vector< int > intListType
void fillRowMap(std::map< int, int > &) const
Fill row map.
intListType _distances
list distances
rb_HyperPlane(int, rb_Hit *, directionsType &, double=0.75)
Construct row based hyperplane.
unsigned int _dimension
(measurement) dimension (1 or 2)
rb_Hit * getHit() const
Get hit (pointer).
const hitListType & getHitList() const
Get list of hits.
int getRow() const
Get row number.
int _scaleBits
number of scale bits (2^(_scaleBits) = 1.0)
std::vector< intListType > _steps
steps (distance to childs projected on normal)
RowBasedFastHoughTransformationProcessor aRowBasedFastHoughTransformationProcessor
rb_HyperCube(unsigned int *, hyperPlaneListType &, intListType &, unsigned int=0)
Construct row based hypercube.
std::vector< rb_Segment * > segListType
std::vector< rb_Hit * > hitListType
int getStep(int, int) const
Get step (distances of child to mother hypercube center projected on normal).
void print() const
Print hypercube.
std::vector< rb_HyperPlane * > hyperPlaneListType
int getScaleBits() const
Get scale bits.
intListType _cut
distance cut for maximal component
int getHitNum() const
Get index to input hit collection.
std::vector< doubleListType > directionsType
hitListType divide(int, int, int, int, float, float)
Divide hypercube (recursively).
void addHit(rb_Hit *)
Add (unused) hit to segment.
int getFirstRow() const
Get first row number.
std::map< int, hitListType > rowHitMapType
std::vector< intListType > getSteps() const
Get steps (distances of child to mother hypercube center).
int getRow() const
Get row number.
void print() const
Print hyperplane.