31 #include "CLHEP/Random/RandFlat.h"
32 #include <TStopwatch.h>
35 #include "art/Framework/Principal/Event.h"
36 #include "art/Framework/Services/Registry/ServiceHandle.h"
37 #include "canvas/Persistency/Common/FindManyP.h"
38 #include "canvas/Persistency/Common/Ptr.h"
39 #include "canvas/Persistency/Common/PtrVector.h"
40 #include "fhiclcpp/ParameterSet.h"
41 #include "messagefacility/MessageLogger/MessageLogger.h"
60 constexpr
double PI = M_PI;
64 #define a2 -2.652905e-4f
66 #define a4 -1.964532e-3f
67 #define a5 1.02575e-2f
68 #define a6 -9.580378e-4f
70 #define _sin(x) ((((((a6 * (x) + a5) * (x) + a4) * (x) + a3) * (x) + a2) * (x) + a1) * (x) + a0)
71 #define _cos(x) _sin(TMath::Pi() * 0.5 - (x))
76 void Init(
unsigned int dx,
unsigned int dy,
float rhores,
unsigned int numACells);
96 void GetEquation(
float row,
float col,
float& rho,
float& theta)
const;
97 int GetMax(
int& xmax,
int& ymax)
const;
126 template <
typename T>
134 template <
typename K,
typename C,
size_t S,
typename A,
unsigned int SC>
138 unchecked_add_range_max(key_begin, key_end, +1, std::numeric_limits<SubCounter_t>::max());
141 template <
typename K,
typename C,
size_t S,
typename A,
unsigned int SC>
145 unchecked_add_range_max(key_begin, key_end, -1, std::numeric_limits<SubCounter_t>::max());
148 template <
typename K,
typename C,
size_t S,
typename A,
unsigned int SC>
152 PairValue_t max{Base_t::make_const_iterator(Base_t::counter_map.
end(), 0), current_max};
154 typename BaseMap_t::const_iterator iCBlock = Base_t::counter_map.begin(),
155 cend = Base_t::counter_map.end();
156 while (iCBlock !=
cend) {
158 for (
size_t index = 0; index < block.size(); ++index) {
159 if (block[index] > max.second)
160 max = {Base_t::make_const_iterator(iCBlock, index), block[index]};
167 template <
typename K,
typename C,
size_t S,
typename A,
unsigned int SC>
171 return get_max(std::numeric_limits<SubCounter_t>::max());
174 template <
typename K,
typename C,
size_t S,
typename A,
unsigned int SC>
180 typename BaseMap_t::iterator iIP)
182 if (key_begin > key_end)
return value;
184 size_t left = key_end - key_begin;
186 if ((iIP == Base_t::counter_map.
end()) || (iIP->first != key.block)) {
188 iIP = Base_t::counter_map.insert(iIP, {key.block, {}});
191 size_t n = std::min(left, Base_t::NCounters - key.counter);
192 block.fill(key.counter, n, value);
193 if (left -= n <= 0)
break;
200 template <
typename K,
typename C,
size_t S,
typename A,
unsigned int SC>
206 return unchecked_set_range(
207 key_begin, key_end, value, Base_t::counter_map.lower_bound(
CounterKey_t(key_begin).block));
210 template <
typename K,
typename C,
size_t S,
typename A,
unsigned int SC>
216 typename BaseMap_t::iterator iIP,
220 PairValue_t max{Base_t::make_const_iterator(Base_t::counter_map.
end(), 0), min_max};
221 if (key_begin > key_end)
return max;
223 size_t left = key_end - key_begin;
225 if ((iIP == Base_t::counter_map.
end()) || (iIP->first != key.block)) {
227 iIP = Base_t::counter_map.insert(iIP, {key.block, {}});
230 size_t n = std::min(left, Base_t::NCounters - key.counter);
234 if (value > max.second) { max = {Base_t::make_const_iterator(iIP, key.counter), value}; }
237 if (left <= 0)
break;
244 template <
typename K,
typename C,
size_t S,
typename A,
unsigned int SC>
253 return unchecked_add_range_max(key_begin,
256 Base_t::counter_map.lower_bound(
CounterKey_t(key_begin).block),
264 fMinHits = pset.get<
int>(
"MinHits");
283 CLHEP::HepRandomEngine& engine,
284 std::vector<unsigned int>* fpointId_to_clusterId,
285 unsigned int clusterId,
286 unsigned int* nClusters,
287 std::vector<protoTrack>* linesFound)
289 int nClustersTemp = *nClusters;
293 lar::providerFrom<lariov::ChannelStatusService>();
295 unsigned int wire = 0;
296 unsigned int wireMax = 0;
297 unsigned int cs = hits[0]->WireID().Cryostat;
298 unsigned int t = hits[0]->WireID().TPC;
302 std::vector<int> skip;
304 std::vector<double> wire_pitch(geom->
Nplanes(t, cs), 0.);
305 for (
size_t p = 0;
p < wire_pitch.size(); ++
p) {
310 std::vector<double> xyScale(geom->
Nplanes(t, cs), 0.);
315 for (
size_t p = 0;
p < xyScale.size(); ++
p)
316 xyScale[
p] = driftVelFactor *
sampling_rate(clockData) / wire_pitch[
p];
318 float tickToDist = driftVelFactor *
sampling_rate(clockData);
328 skip.resize(hits.size());
329 std::vector<int> listofxmax;
330 std::vector<int> listofymax;
331 std::vector<int> hitsTemp;
332 std::vector<int> sequenceHolder;
333 std::vector<int> channelHolder;
334 std::vector<int> currentHits;
335 std::vector<int> lastHits;
336 std::vector<art::Ptr<recob::Hit>> clusterHits;
337 float indcolscaling = 0.;
346 float centerofmassx = 0;
347 float centerofmassy = 0;
349 float intercept = 0.;
361 int accDx(0), accDy(0);
365 unsigned int fMaxWire = 0;
367 unsigned int fMinWire = 99999999;
385 mf::LogInfo(
"HoughBaseAlg") <<
"dealing with " << hits.size() <<
" hits";
391 c.
Init(dx, dy, fRhoResolutionFactor, fNumAngleCells);
400 unsigned int nLinesFound = 0;
401 std::vector<unsigned int> accumPoints(hits.size(), 0);
406 for (
auto fpointId_to_clusterIdItr = fpointId_to_clusterId->begin();
407 fpointId_to_clusterIdItr != fpointId_to_clusterId->end();
408 fpointId_to_clusterIdItr++)
409 if (*fpointId_to_clusterIdItr == clusterId) count++;
411 unsigned int randInd;
413 CLHEP::RandFlat flat(engine);
420 randInd = (
unsigned int)(flat.fire() * hits.size());
423 if (fpointId_to_clusterId->at(randInd) != clusterId)
continue;
428 if (skip[randInd] == 1) {
continue; }
431 if (accumPoints[randInd])
continue;
432 accumPoints[randInd] = 1;
435 for (
auto listofxmaxItr = listofxmax.begin(); listofxmaxItr != listofxmax.end();
437 yClearStart = listofymax[listofxmaxItr - listofxmax.begin()] - fRhoZeroOutRange;
438 if (yClearStart < 0) yClearStart = 0;
440 yClearEnd = listofymax[listofxmaxItr - listofxmax.begin()] + fRhoZeroOutRange;
441 if (yClearEnd >= accDy) yClearEnd = accDy - 1;
443 xClearStart = *listofxmaxItr - fThetaZeroOutRange;
444 if (xClearStart < 0) xClearStart = 0;
446 xClearEnd = *listofxmaxItr + fThetaZeroOutRange;
447 if (xClearEnd >= accDx) xClearEnd = accDx - 1;
449 for (y = yClearStart; y <= yClearEnd; ++
y) {
450 for (x = xClearStart; x <= xClearEnd; ++
x) {
457 uint32_t channel = hits[randInd]->Channel();
458 wireMax = hits[randInd]->WireID().Wire;
461 std::array<int, 3> max = c.
AddPointReturnMax(wireMax, (
int)(hits[randInd]->PeakTime()));
468 double binomProbSum = TMath::BinomialI(1 / (
double)accDx, nAccum, maxCell);
469 if (binomProbSum > 1
e-21)
continue;
473 denom = centerofmassx = centerofmassy = 0;
475 if (xMax > 0 && yMax > 0 && xMax + 1 < accDx && yMax + 1 < accDy) {
476 for (
int i = -1; i < 2; ++i) {
477 for (
int j = -1; j < 2; ++j) {
478 denom += c.
GetCell(yMax + i, xMax + j);
479 centerofmassx += j * c.
GetCell(yMax + i, xMax + j);
480 centerofmassy += i * c.
GetCell(yMax + i, xMax + j);
483 centerofmassx /= denom;
484 centerofmassy /= denom;
487 centerofmassx = centerofmassy = 0;
490 listofxmax.push_back(xMax);
491 listofymax.push_back(yMax);
494 c.
GetEquation(yMax + centerofmassy, xMax + centerofmassx, rho, theta);
495 MF_LOG_DEBUG(
"HoughBaseAlg") <<
"Transform(II) found maximum at (d=" << rho <<
" a=" << theta
497 " from absolute maximum "
498 << c.
GetCell(yMax, xMax) <<
" at (d=" << yMax <<
", a=" << xMax
500 slope = -1. / tan(theta);
501 intercept = (rho / sin(theta));
504 if (!std::isinf(slope) && !std::isnan(slope)) {
505 channelHolder.clear();
506 sequenceHolder.clear();
512 for (
auto hitsItr = hits.cbegin(); hitsItr != hits.cend(); ++hitsItr) {
513 wire = (*hitsItr)->WireID().Wire;
514 if (fpointId_to_clusterId->at(hitsItr - hits.begin()) != clusterId)
continue;
515 channel = (*hitsItr)->Channel();
516 distance = (
std::abs((*hitsItr)->PeakTime() - slope * (float)((*hitsItr)->WireID().Wire) -
518 (std::sqrt(
sqr(xyScale[(*hitsItr)->WireID().Plane] * slope) + 1.)));
519 if (distance < fMaxDistance + (*hitsItr)->RMS() + indcolscaling &&
520 skip[hitsItr - hits.begin()] != 1) {
521 hitsTemp.push_back(hitsItr - hits.begin());
522 sequenceHolder.push_back(wire);
523 channelHolder.push_back(channel);
527 if (hitsTemp.size() < 5)
continue;
531 currentHits.push_back(0);
532 for (
auto sequenceHolderItr = sequenceHolder.begin();
533 sequenceHolderItr + 1 != sequenceHolder.end();
534 ++sequenceHolderItr) {
536 while (channelStatus->IsBad(sequenceHolderItr - sequenceHolder.begin() + j))
538 if (sequenceHolder[sequenceHolderItr - sequenceHolder.begin() + 1] -
539 sequenceHolder[sequenceHolderItr - sequenceHolder.begin()] <=
541 currentHits.push_back(sequenceHolderItr - sequenceHolder.begin() + 1);
542 else if (currentHits.size() > lastHits.size()) {
543 lastHits = currentHits;
549 if (currentHits.size() > lastHits.size()) lastHits = currentHits;
553 if (lastHits.size() < (
unsigned int)fMinHits)
continue;
555 if (
std::abs(slope) > fMaxSlope) {
continue; }
559 std::vector<art::Ptr<recob::Hit>> lineHits;
561 for (
auto lastHitsItr = lastHits.begin(); lastHitsItr != lastHits.end(); ++lastHitsItr) {
562 fpointId_to_clusterId->at(hitsTemp[(*lastHitsItr)]) = nClustersTemp - 1;
563 totalQ += hits[hitsTemp[(*lastHitsItr)]]->Integral();
564 wire = hits[hitsTemp[(*lastHitsItr)]]->WireID().Wire;
566 if (!accumPoints[hitsTemp[(*lastHitsItr)]]) count--;
568 skip[hitsTemp[(*lastHitsItr)]] = 1;
570 lineHits.push_back(hits[hitsTemp[(*lastHitsItr)]]);
573 if (accumPoints[hitsTemp[(*lastHitsItr)]])
574 c.
SubtractPoint(wire, (
int)(hits[hitsTemp[(*lastHitsItr)]]->PeakTime()));
576 if (wire < fMinWire) {
578 iMinWire = hitsTemp[(*lastHitsItr)];
580 if (wire > fMaxWire) {
582 iMaxWire = hitsTemp[(*lastHitsItr)];
585 int pnum = hits[iMinWire]->WireID().Plane;
586 pCornerMin[0] = (hits[iMinWire]->WireID().Wire) * wire_pitch[pnum];
587 pCornerMin[1] = hits[iMinWire]->PeakTime() * tickToDist;
588 pCornerMax[0] = (hits[iMaxWire]->WireID().Wire) * wire_pitch[pnum];
589 pCornerMax[1] = hits[iMaxWire]->PeakTime() * tickToDist;
591 protoTrackToLoad.
Init(nClustersTemp - 1,
605 linesFound->push_back(protoTrackToLoad);
611 if (nLinesFound > (
unsigned int)fMaxLines)
break;
622 if (fSaveAccumulator) {
623 unsigned char* outPix =
new unsigned char[accDx * accDy];
625 int cell, pix = 0, maxCell = 0;
626 for (
int y = 0; y < accDy; ++
y) {
627 for (
int x = 0; x < accDx; ++
x) {
629 if (cell > maxCell) maxCell = cell;
632 for (
int y = 0; y < accDy; ++
y) {
633 for (
int x = 0; x < accDx; ++
x) {
635 if (maxCell > 0) pix = (int)((1500 * c.
GetCell(y, x)) / maxCell);
636 outPix[y * accDx +
x] = pix;
640 HLSSaveBMPFile(
"houghaccum.bmp", outPix, accDx, accDy);
644 *nClusters = nClustersTemp;
653 return m_accum[
row][col];
659 inline std::array<int, 3>
662 if ((x > (
int)m_dx) || (y > (
int)m_dy) || x < 0.0 || y < 0.0) {
663 std::array<int, 3> max;
667 return DoAddPointReturnMax(x, y,
false);
674 if ((x > (
int)m_dx) || (y > (
int)m_dy) || x < 0.0 || y < 0.0)
return false;
675 DoAddPointReturnMax(x, y,
true);
684 unsigned int numACells)
686 m_numAngleCells = numACells;
687 m_rhoResolutionFactor = rhores;
704 <std::pair<const DistancesMap_t::Key_t, DistancesMap_t::CounterBlock_t>>
711 m_numAccumulated = 0;
714 m_rowLength = (
unsigned int)(m_rhoResolutionFactor * 2 * std::sqrt(dx * dx + dy * dy));
715 m_accum.resize(m_numAngleCells);
718 double angleStep =
PI / m_numAngleCells;
719 m_cosTable.resize(m_numAngleCells);
720 m_sinTable.resize(m_numAngleCells);
721 for (
size_t iAngleStep = 0; iAngleStep < m_numAngleCells; ++iAngleStep) {
722 double a = iAngleStep * angleStep;
723 m_cosTable[iAngleStep] = cos(a);
724 m_sinTable[iAngleStep] = sin(a);
732 theta = (TMath::Pi() *
row) / m_numAngleCells;
733 rho = (col - (m_rowLength / 2.)) / m_rhoResolutionFactor;
741 for (
unsigned int i = 0; i < m_accum.size(); i++) {
744 if (max_counter.second > maxVal) {
745 maxVal = max_counter.second;
747 ymax = max_counter.first.key();
760 std::array<int, 3> max;
767 const int distCenter = (int)(m_rowLength / 2.);
771 int lastDist = (int)(distCenter + (m_rhoResolutionFactor * x));
776 for (
size_t iAngleStep = 1; iAngleStep < m_numAngleCells; ++iAngleStep) {
781 const int dist = (int)(distCenter + m_rhoResolutionFactor * (m_cosTable[iAngleStep] * x +
782 m_sinTable[iAngleStep] * y));
806 if (lastDist == dist) {
813 first_dist = dist > lastDist ? lastDist : dist + 1;
814 end_dist = dist > lastDist ? dist : lastDist + 1;
818 if (bSubtract) { distMap.
decrement(first_dist, end_dist); }
823 if (max_counter.second > max_val) {
828 max = {{max_counter.second, max_counter.first.key(), (int)iAngleStep}};
829 max_val = max_counter.second;
853 std::ofstream bmpFile(fileName, std::ios::binary);
854 bmpFile.write(
"B", 1);
855 bmpFile.write(
"M", 1);
856 int bitsOffset = 54 + 256 * 4;
857 int size = bitsOffset + dx * dy;
858 bmpFile.write((
const char*)&size, 4);
860 bmpFile.write((
const char*)&reserved, 4);
861 bmpFile.write((
const char*)&bitsOffset, 4);
863 bmpFile.write((
const char*)&bmiSize, 4);
864 bmpFile.write((
const char*)&dx, 4);
865 bmpFile.write((
const char*)&dy, 4);
867 bmpFile.write((
const char*)&planes, 2);
869 bmpFile.write((
const char*)&bitCount, 2);
871 for (i = 0; i < 6; i++)
872 bmpFile.write((
const char*)&temp, 4);
876 for (i = 0; i < 256; i++) {
877 lutEntry[0] = lutEntry[1] = lutEntry[2] = i;
878 bmpFile.write(lutEntry,
sizeof lutEntry);
881 bmpFile.write((
const char*)pix, dx * dy);
887 std::vector<recob::Cluster>& ccol,
888 std::vector<art::PtrVector<recob::Hit>>& clusHitsOut,
889 CLHEP::HepRandomEngine& engine,
890 art::Event
const&
evt,
891 std::string
const& label)
893 std::vector<int> skip;
895 art::FindManyP<recob::Hit> fmh(clusIn, evt, label);
900 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
902 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clockData);
910 std::vector<art::Ptr<recob::Hit>>
hit;
912 for (
auto view : geom->
Views()) {
914 MF_LOG_DEBUG(
"HoughBaseAlg") <<
"Analyzing view " << view;
916 art::PtrVector<recob::Cluster>::const_iterator clusterIter = clusIn.begin();
920 while (clusterIter != clusIn.end()) {
922 MF_LOG_DEBUG(
"HoughBaseAlg")
923 <<
"Analyzing cinctr=" << cinctr <<
" which is in view " << (*clusterIter)->View();
927 if ((*clusterIter)->View() == view) hit = fmh.at(cinctr);
930 while (clusterIter != clusIn.end()) {
931 if ((*clusterIter)->View() == view) {
933 hit = fmh.at(cinctr);
939 if (hit.size() == 0) {
947 MF_LOG_DEBUG(
"HoughBaseAlg") <<
"We have all the hits..." << hit.size();
949 std::vector<double> slopevec;
950 std::vector<ChargeInfo_t> totalQvec;
951 std::vector<art::PtrVector<recob::Hit>> planeClusHitsOut;
952 this->FastTransform(clockData,
detProp, hit, planeClusHitsOut, engine, slopevec, totalQvec);
954 MF_LOG_DEBUG(
"HoughBaseAlg") <<
"Made it through FastTransform" << planeClusHitsOut.size();
956 for (
size_t xx = 0; xx < planeClusHitsOut.size(); ++xx) {
957 auto const& hits = planeClusHitsOut.at(xx);
960 const unsigned int sw = FirstHit.
WireID().
Wire;
961 const unsigned int ew = LastHit.
WireID().
Wire;
970 ccol.emplace_back(
float(sw),
974 ClusterParamAlgo.StartCharge(gser).value(),
975 ClusterParamAlgo.StartAngle().value(),
976 ClusterParamAlgo.StartOpeningAngle().value(),
981 ClusterParamAlgo.EndCharge(gser).value(),
982 ClusterParamAlgo.EndAngle().value(),
983 ClusterParamAlgo.EndOpeningAngle().value(),
984 ClusterParamAlgo.Integral().value(),
985 ClusterParamAlgo.IntegralStdDev().value(),
986 ClusterParamAlgo.SummedADC().value(),
987 ClusterParamAlgo.SummedADCStdDev().value(),
988 ClusterParamAlgo.NHits(),
989 ClusterParamAlgo.MultipleHitDensity(),
990 ClusterParamAlgo.Width(gser),
997 clusHitsOut.push_back(planeClusHitsOut.at(xx));
1001 if (clusterIter != clusIn.end()) {
1019 std::vector<art::PtrVector<recob::Hit>>& clusHitsOut,
1020 CLHEP::HepRandomEngine& engine)
1022 std::vector<double> slopevec;
1023 std::vector<ChargeInfo_t> totalQvec;
1024 return FastTransform(clockData, detProp, clusIn, clusHitsOut, engine, slopevec, totalQvec);
1032 std::vector<art::PtrVector<recob::Hit>>& clusHitsOut,
1033 CLHEP::HepRandomEngine& engine,
1034 std::vector<double>& slopevec,
1035 std::vector<ChargeInfo_t>& totalQvec)
1037 std::vector<int> skip;
1041 lar::providerFrom<lariov::ChannelStatusService>();
1043 CLHEP::RandFlat flat(engine);
1045 std::vector<art::Ptr<recob::Hit>>
hit;
1049 for (
std::vector<art::Ptr<recob::Hit>>::const_iterator ii = clusIn.begin(); ii != clusIn.end();
1051 hit.push_back((*ii));
1053 if (hit.size() == 0) {
1054 if (fPerCluster) { ++cinctr; }
1058 unsigned int cs = hit.at(0)->WireID().Cryostat;
1059 unsigned int t = hit.at(0)->WireID().TPC;
1060 unsigned int p = hit.at(0)->WireID().Plane;
1065 if (hit.size() == 0) {
1066 if (fPerCluster) { ++cinctr; }
1070 std::vector<double> wire_pitch(geom->
Nplanes(t, cs), 0.);
1071 for (
size_t p = 0; p < wire_pitch.size(); ++
p) {
1076 std::vector<double> xyScale(geom->
Nplanes(t, cs), 0.);
1081 for (
size_t p = 0; p < xyScale.size(); ++
p)
1082 xyScale[p] = driftVelFactor *
sampling_rate(clockData) / wire_pitch[
p];
1088 skip.resize(hit.size());
1089 std::vector<int> listofxmax;
1090 std::vector<int> listofymax;
1091 std::vector<int> hitTemp;
1092 std::vector<int> sequenceHolder;
1093 std::vector<int> currentHits;
1094 std::vector<int> lastHits;
1095 art::PtrVector<recob::Hit> clusterHits;
1096 float indcolscaling = 0.;
1098 float centerofmassx = 0;
1099 float centerofmassy = 0;
1101 float intercept = 0.;
1108 int accDx(0), accDy(0);
1114 c.
Init(dx, dy, fRhoResolutionFactor, fNumAngleCells);
1117 unsigned int count = hit.size();
1118 std::vector<unsigned int> accumPoints;
1119 accumPoints.resize(hit.size());
1121 unsigned int nLinesFound = 0;
1123 for (; count > 0; count--) {
1126 unsigned int randInd = (
unsigned int)(flat.fire() * hit.size());
1128 MF_LOG_DEBUG(
"HoughBaseAlg") <<
"randInd=" << randInd <<
" and size is " << hit.size();
1131 if (skip.at(randInd) == 1)
continue;
1134 if (accumPoints.at(randInd))
continue;
1135 accumPoints.at(randInd) = 1;
1138 for (
unsigned int i = 0; i < listofxmax.size(); ++i) {
1139 int yClearStart = listofymax.at(i) - fRhoZeroOutRange;
1140 if (yClearStart < 0) yClearStart = 0;
1142 int yClearEnd = listofymax.at(i) + fRhoZeroOutRange;
1143 if (yClearEnd >= accDy) yClearEnd = accDy - 1;
1145 int xClearStart = listofxmax.at(i) - fThetaZeroOutRange;
1146 if (xClearStart < 0) xClearStart = 0;
1148 int xClearEnd = listofxmax.at(i) + fThetaZeroOutRange;
1149 if (xClearEnd >= accDx) xClearEnd = accDx - 1;
1151 for (y = yClearStart; y <= yClearEnd; ++
y) {
1152 for (x = xClearStart; x <= xClearEnd; ++
x) {
1160 unsigned int wireMax = hit.at(randInd)->WireID().Wire;
1163 std::array<int, 3> max = c.
AddPointReturnMax(wireMax, (
int)(hit.at(randInd)->PeakTime()));
1164 maxCell = max.at(0);
1170 if (maxCell < fMinHits)
continue;
1173 denom = centerofmassx = centerofmassy = 0;
1175 if (xMax > 0 && yMax > 0 && xMax + 1 < accDx && yMax + 1 < accDy) {
1176 for (
int i = -1; i < 2; ++i) {
1177 for (
int j = -1; j < 2; ++j) {
1178 int cell = c.
GetCell(yMax + i, xMax + j);
1180 centerofmassx += j * cell;
1181 centerofmassy += i * cell;
1184 centerofmassx /= denom;
1185 centerofmassy /= denom;
1188 centerofmassx = centerofmassy = 0;
1191 listofxmax.push_back(xMax);
1192 listofymax.push_back(yMax);
1195 c.
GetEquation(yMax + centerofmassy, xMax + centerofmassx, rho, theta);
1196 MF_LOG_DEBUG(
"HoughBaseAlg") <<
"Transform(I) found maximum at (d=" << rho <<
" a=" << theta
1198 " from absolute maximum "
1199 << c.
GetCell(yMax, xMax) <<
" at (d=" << yMax <<
", a=" << xMax
1201 slope = -1. / tan(theta);
1202 intercept = (rho / sin(theta));
1213 if (!std::isinf(slope) && !std::isnan(slope)) {
1214 sequenceHolder.clear();
1216 for (
size_t i = 0; i < hit.size(); ++i) {
1217 distance = (TMath::Abs(hit.at(i)->PeakTime() - slope * (double)(hit.at(i)->WireID().Wire) -
1219 (std::sqrt(pow(xyScale[hit.at(i)->WireID().Plane] * slope, 2) + 1)));
1221 if (distance < fMaxDistance + hit.at(i)->RMS() + indcolscaling && skip.at(i) != 1) {
1222 hitTemp.push_back(i);
1223 sequenceHolder.push_back(hit.at(i)->Channel());
1228 if (hitTemp.size() < 2)
continue;
1229 currentHits.clear();
1232 currentHits.push_back(0);
1233 for (
size_t i = 0; i + 1 < sequenceHolder.size(); ++i) {
1235 while ((channelStatus->IsBad(sequenceHolder.at(i) + j)) ==
true)
1237 if (sequenceHolder.at(i + 1) - sequenceHolder.at(i) <= j + fMissedHits)
1238 currentHits.push_back(i + 1);
1239 else if (currentHits.size() > lastHits.size()) {
1240 lastHits = currentHits;
1241 currentHits.clear();
1244 currentHits.clear();
1247 if (currentHits.size() > lastHits.size()) lastHits = currentHits;
1258 int lastHitsChannel = 0;
1259 int nHitsPerChannel = 1;
1261 MF_LOG_DEBUG(
"HoughBaseAlg") <<
"filling the pCorner arrays around here..."
1262 <<
"\n but first, lastHits size is " << lastHits.size()
1263 <<
" and lastHitsChannel=" << lastHitsChannel;
1267 unsigned int lastChannel = hit.at(hitTemp.at(lastHits.at(0)))->Channel();
1269 for (
size_t i = 0; i < lastHits.size() - 1; ++i) {
1270 bool newChannel =
false;
1272 if (hit.at(hitTemp.at(lastHits.at(i + 1)))->Channel() != lastChannel) {
1275 if (hit.at(hitTemp.at(lastHits.at(i + 1)))->Channel() == lastChannel) nHitsPerChannel++;
1281 if (slope > 0 || (!newChannel && nHitsPerChannel <= 1)) {
1283 pCorner0[0] = (hit.at(hitTemp.at(lastHits.at(i)))->Channel()) * wire_pitch[0];
1284 pCorner0[1] = hit.at(hitTemp.at(lastHits.at(i)))->PeakTime() * tickToDist;
1285 pCorner1[0] = (hit.at(hitTemp.at(lastHits.at(i + 1)))->Channel()) * wire_pitch[0];
1286 pCorner1[1] = hit.at(hitTemp.at(lastHits.at(i + 1)))->PeakTime() * tickToDist;
1287 if (std::sqrt(pow(pCorner0[0] - pCorner1[0], 2) + pow(pCorner0[1] - pCorner1[1], 2)) >
1288 fMissedHitsDistance)
1292 else if (slope < 0 && newChannel && nHitsPerChannel > 1) {
1295 (hit.at(hitTemp.at(lastHits.at(lastHitsChannel)))->Channel()) * wire_pitch[0];
1296 pCorner0[1] = hit.at(hitTemp.at(lastHits.at(lastHitsChannel)))->PeakTime() * tickToDist;
1297 pCorner1[0] = (hit.at(hitTemp.at(lastHits.at(i + 1)))->Channel()) * wire_pitch[0];
1298 pCorner1[1] = hit.at(hitTemp.at(lastHits.at(i + 1)))->PeakTime() * tickToDist;
1299 if (std::sqrt(pow(pCorner0[0] - pCorner1[0], 2) + pow(pCorner0[1] - pCorner1[1], 2)) >
1300 fMissedHitsDistance)
1302 lastChannel = hit.at(hitTemp.at(lastHits.at(i)))->Channel();
1303 lastHitsChannel = i + 1;
1304 nHitsPerChannel = 0;
1308 if ((
double)missedHits / ((
double)lastHits.size() - 1) > fMissedHitsToLineSize)
continue;
1310 clusterHits.clear();
1311 if (lastHits.size() < 5)
continue;
1316 for (
size_t i = 0; i < lastHits.size(); ++i) {
1317 clusterHits.push_back(hit.at(hitTemp.at(lastHits.at(i))));
1318 integralQ.
add(clusterHits.back()->Integral());
1319 summedQ.
add(clusterHits.back()->SummedADC());
1320 skip.at(hitTemp.at(lastHits.at(i))) = 1;
1323 if (
std::abs(slope) > fMaxSlope)
continue;
1325 clusHitsOut.push_back(clusterHits);
1326 slopevec.push_back(slope);
1327 totalQvec.emplace_back(integralQ.
Sum(),
1337 if (nLinesFound > (
unsigned int)fMaxLines)
break;
1343 if (fSaveAccumulator) {
1345 int cell, pix = 0, maxCell = 0;
1346 for (y = 0; y < accDy; ++
y) {
1347 for (x = 0; x < accDx; ++
x) {
1349 if (cell > maxCell) maxCell = cell;
1353 std::unique_ptr<unsigned char[]> outPix(
new unsigned char[accDx * accDy]);
1354 unsigned int PicIndex = 0;
1355 for (y = 0; y < accDy; ++
y) {
1356 for (x = 0; x < accDx; ++
x) {
1358 if (maxCell > 0) pix = (int)((1500 * c.
GetCell(y, x)) / maxCell);
1359 outPix[PicIndex++] = pix;
1363 HLSSaveBMPFile(
"houghaccum.bmp", outPix.get(), accDx, accDy);
1370 return clusHitsOut.size();
1382 art::ServiceHandle<geo::Geometry const> geom;
1384 int dx = geom->Nwires(0);
1387 c.
Init(dx, dy, fRhoResolutionFactor, fNumAngleCells);
1389 for (
unsigned int i = 0; i < hits.size(); ++i) {
1404 float centerofmassx = 0.;
1405 float centerofmassy = 0.;
1408 if (xMax > 0 && yMax > 0 && xMax + 1 < accDx && yMax + 1 < accDy) {
1409 for (
int i = -1; i < 2; ++i) {
1410 for (
int j = -1; j < 2; ++j) {
1411 denom += c.
GetCell(yMax + i, xMax + j);
1412 centerofmassx += j * c.
GetCell(yMax + i, xMax + j);
1413 centerofmassy += i * c.
GetCell(yMax + i, xMax + j);
1416 centerofmassx /= denom;
1417 centerofmassy /= denom;
1420 centerofmassx = centerofmassy = 0;
1424 c.
GetEquation(yMax + centerofmassy, xMax + centerofmassx, rho, theta);
1425 MF_LOG_DEBUG(
"HoughBaseAlg") <<
"Transform(III) found maximum at (d=" << rho <<
" a=" << theta
1427 " from absolute maximum "
1428 << c.
GetCell(yMax, xMax) <<
" at (d=" << yMax <<
", a=" << xMax
1430 slope = -1. / tan(theta);
1431 intercept = rho / sin(theta);
Utilities related to art service access.
typename Traits_t::CounterBlock_t CounterBlock_t
float fRhoResolutionFactor
Factor determining the resolution in rho.
BEGIN_PROLOG true icarus_rawdigitfilter FilterTools FilterPlane1 Plane
Encapsulate the construction of a single cyostat.
process_name opflash particleana ie x
KEY Key_t
type of counter key in the map
geo::WireID WireID() const
Declaration of signal hit object.
std::set< geo::View_t > const & Views() const
Returns a list of possible views in the detector.
double Temperature() const
In kelvin.
size_t FastTransform(const std::vector< art::Ptr< recob::Cluster >> &clusIn, std::vector< recob::Cluster > &ccol, std::vector< art::PtrVector< recob::Hit >> &clusHitsOut, CLHEP::HepRandomEngine &engine, art::Event const &evt, std::string const &label)
std::size_t size(FixedBins< T, C > const &) noexcept
unsigned int ReadOutWindowSize() const
geo::View_t View() const
View for the plane of the hit.
WireID_t Wire
Index of the wire within its plane.
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
Classes gathering simple statistics.
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
Weight_t RMS() const
Returns the root mean square.
auto cend(FixedBins< T, C > const &) noexcept
static const SentryArgument_t Sentry
An instance of the sentry object.
void ImportHits(util::GeometryUtilities const &gser, Iter begin, Iter end)
Calls SetHits() with the hits in the sequence.
double Efield(unsigned int planegap=0) const
kV/cm
int fMaxLines
Max number of lines that can be found.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
float fMissedHitsDistance
Distance between hits in a hough line before a hit is considered missed.
int fNumAngleCells
that fall into the "correct" bin will be small and consistent with noise.
int fSaveAccumulator
Save bitmap image of accumulator for debugging?
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
process_name opflash particleana ie ie y
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
Signal from induction planes.
Weight_t Sum() const
Returns the weighted sum of the values.
enum geo::_plane_sigtype SigType_t
Wrapper for ClusterParamsAlgBase objects to accept diverse input.
float fMaxDistance
Max distance that a hit can be from a line to be considered part of that line.
auto end(FixedBins< T, C > const &) noexcept
Aggressive allocator reserving a lot of memory in advance.
unsigned int NumberTimeSamples() const
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
float fMaxSlope
Max slope a line can have.
Wrapper for ClusterParamsAlgBase objects to accept arbitrary input.
Class providing information about the quality of channels.
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
Description of geometry of one entire detector.
Declaration of cluster object.
int fRhoZeroOutRange
Range in rho over which to zero out area around previously found lines in the accumulator.
float PeakTime() const
Time of the signal peak, in tick units.
Encapsulate the construction of a single detector plane.
Contains all timing reference information for the detector.
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc'th TPC in the cryostat.
services TFileService fileName
unsigned int Nwires() const
Number of wires in this plane.
Interface for experiment-specific channel quality info provider.
void Init(unsigned int num=999999, unsigned int pnum=999999, float slope=999999, float intercept=999999, float totalQTemp=-999999, float Min0=999999, float Min1=999999, float Max0=-999999, float Max1=-999999, int iMinWireTemp=999999, int iMaxWireTemp=-999999, int minWireTemp=999999, int maxWireTemp=-999999, std::vector< art::Ptr< recob::Hit >> hitsTemp=std::vector< art::Ptr< recob::Hit >>())
constexpr WireID()=default
Default constructor: an invalid TPC ID.
HoughBaseAlg(fhicl::ParameterSet const &pset)
float SigmaPeakTime() const
Uncertainty for the signal peak, in tick units.
size_t Transform(const detinfo::DetectorClocksData &clockData, detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &hits, CLHEP::HepRandomEngine &engine, std::vector< unsigned int > *fpointId_to_clusterId, unsigned int clusterId, unsigned int *nClusters, std::vector< protoTrack > *protoTracks)
PlaneGeo const & Plane(geo::View_t view) const
Return the plane in the tpc with View_t view.
2D representation of charge deposited in the TDC/wire plane
constexpr PlaneID const & planeID() const
Counter_t SubCounter_t
Type of the subcounter (that is, the actual counter)
Interface to class computing cluster parameters.
int fThetaZeroOutRange
Range in theta over which to zero out area around previously found lines in the accumulator.
std::size_t count(Cont const &cont)
Interface for experiment-specific service for channel quality info.
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
float fMissedHitsToLineSize
Ratio of missed hits to line size for a line to be considered a fake.
art framework interface to geometry description
Encapsulate the construction of a single detector plane.
void add(Data_t value, Weight_t weight=Weight_t(1.0))
Adds one entry with specified value and weight.
void HLSSaveBMPFile(char const *, unsigned char *, int, int)