33 inline constexpr T
sqr(T v) {
return v*v; }
36 inline constexpr T sumsq(T a, T b) {
return sqr(a) +
sqr(b); }
39 inline constexpr T
norm(T a, T b) {
return std::sqrt(sumsq(a, b)); }
60 int clusterNumber=-999999;
66 clusterProtoTracks.emplace_back(std::move(protoTrackTemp));
71 for(
auto& trackToAdd: tracksToAdd)
72 trackToAdd.clusterNumber = clusterNumber;
73 clusterProtoTracks.reserve
74 (clusterProtoTracks.size() + tracksToAdd.size());
75 std::move(tracksToAdd.begin(),tracksToAdd.end(),
76 std::back_inserter(clusterProtoTracks));
81 clusterProtoTracks.clear();
113 : fHBAlg(pset.get<
fhicl::ParameterSet >(
"HoughBaseAlg")),
114 fDBScan(pset.get<
fhicl::ParameterSet >(
"DBScanAlg"))
155 std::set<uint32_t> badChannels)
175 unsigned int cs=allhits[0]->WireID().
Cryostat;
176 unsigned int t=allhits[0]->WireID().
TPC;
179 for (
size_t p = 0; p <
fWirePitch.size(); ++p) {
192 std::vector<double> p(dims);
193 for (
auto allhitsItr = allhits.begin(); allhitsItr < allhits.end(); allhitsItr++){
195 p[0] = ((*allhitsItr)->WireID().Wire)*
fWirePitch[(*allhitsItr)->WireID().Plane];
196 p[1] = (*allhitsItr)->PeakTime()*tickToDist;
197 p[2] = (*allhitsItr)->Integral();
206 mf::LogInfo(
"fuzzyCluster") <<
"Initfuzzy: hits vector size is " <<
fps.size();
220 if(allhits.size() <= 1)
223 mf::LogInfo(
"fuzzyClusterAlg") <<
"Clustering " << allhits.size() <<
" hits";
237 uint32_t channel = allhits[0]->WireID().Wire;
253 double indcolscaling = 0.;
265 unsigned int nClusters = 1;
266 unsigned int nClustersTemp = 1;
271 unsigned int nWires = geom->
Nwires(allhits[0]->WireID().
Plane);
273 std::vector<unsigned int> wireBoundaries;
274 std::vector<unsigned int> timeBoundaries;
275 for(
size_t i = 0; i < fNumberWireBoundaries+1; i++){
276 wireBoundaries.push_back(i*nWires/fNumberWireBoundaries);
279 timeBoundaries.push_back(i*nTicks/fNumberTimeBoundaries);
281 for(
auto hitsItr = allhits.cbegin(); hitsItr != allhits.cend(); ++hitsItr){
283 if(( *hitsItr)->WireID().Wire >= wireBoundaries[i] && (*hitsItr)->WireID().Wire < wireBoundaries[i+1]){
285 if((*hitsItr)->PeakTime() >= timeBoundaries[j] && (*hitsItr)->PeakTime() < timeBoundaries[j+1]){
300 std::vector<protoTrack> protoTracksFound;
302 for (
unsigned int i = 0; i <= (
unsigned int)nClustersTemp-1; ++i){
304 <<
"Running Hough transform on protocluster " << i;
309 std::vector<showerCluster> showerClusters;
310 std::vector<trackCluster> trackClusters;
311 double totalBkgDistCharge;
314 double peakTimePerpMin;
315 double peakTimePerpMax;
316 for(
auto protoTracksFoundItr = protoTracksFound.begin(); protoTracksFoundItr < protoTracksFound.end(); ++protoTracksFoundItr){
317 totalBkgDistCharge = 0;
319 for(
auto hitsItr = allhits.cbegin(); hitsItr != allhits.cend(); ++hitsItr){
323 distance = (std::abs((*hitsItr)->PeakTime()-protoTracksFoundItr->clusterSlope*(double)((*hitsItr)->WireID().Wire)-protoTracksFoundItr->clusterIntercept)/(std::sqrt(
sqr(xyScale/
fWirePitch[(*hitsItr)->WireID().Plane]*protoTracksFoundItr->clusterSlope)+1)));
325 peakTimePerpMin=-(1/protoTracksFoundItr->clusterSlope)*(
double)((*hitsItr)->WireID().Wire)+allhits[protoTracksFoundItr->iMinWire]->PeakTime()+(1/protoTracksFoundItr->clusterSlope)*(allhits[protoTracksFoundItr->iMinWire]->WireID().Wire);
326 peakTimePerpMax=-(1/protoTracksFoundItr->clusterSlope)*(
double)((*hitsItr)->WireID().Wire)+allhits[protoTracksFoundItr->iMaxWire]->PeakTime()+(1/protoTracksFoundItr->clusterSlope)*(allhits[protoTracksFoundItr->iMaxWire]->WireID().Wire);
327 if(distance > 1*(fMaxDistance+(*hitsItr)->RMS()+indcolscaling)
328 && distance < 25*(fMaxDistance+(*hitsItr)->RMS()+indcolscaling)){
329 if((protoTracksFoundItr->clusterSlope < 0 && (*hitsItr)->PeakTime() < peakTimePerpMin && (*hitsItr)->PeakTime() > peakTimePerpMax)
330 || (protoTracksFoundItr->clusterSlope > 0 && (*hitsItr)->PeakTime() > peakTimePerpMin && (*hitsItr)->PeakTime() < peakTimePerpMax)){
331 if((*hitsItr)->Integral() > 0.1){
332 totalBkgDistCharge+=distance/(*hitsItr)->Integral();
337 protoTracksFoundItr->showerLikeness = totalBkgDistCharge/(double)protoTracksFoundItr->hits.size();
341 showerClusters.push_back(
showerCluster(*protoTracksFoundItr));
343 trackClusters.push_back(
trackCluster(*protoTracksFoundItr));
352 bool showerTrackMerged;
356 while(i < trackClusters.size()-1){
357 int ip = trackClusters[i].clusterProtoTracks[0].planeNumber;
369 while(i < showerClusters.size()-1){
370 int ip = showerClusters[i].clusterProtoTracks[0].planeNumber;
382 while(i < showerClusters.size()){
383 int ip = showerClusters[i].clusterProtoTracks[0].planeNumber;
385 while(j < trackClusters.size()){
390 if(showerTrackMerged)
401 while(i < showerClusters.size()-1){
402 int ip = showerClusters[i].clusterProtoTracks[0].planeNumber;
415 for(
auto trackClustersItr = trackClusters.begin(); trackClustersItr != trackClusters.end(); ++trackClustersItr){
416 for(
auto protoTracksFoundItr = trackClustersItr->clusterProtoTracks.begin(); protoTracksFoundItr < trackClustersItr->clusterProtoTracks.end(); ++protoTracksFoundItr){
417 if(*fpointId_to_clusterIdItr == (
unsigned int)protoTracksFoundItr->oldClusterNumber)
418 *fpointId_to_clusterIdItr = protoTracksFoundItr->clusterNumber;
421 for(
auto showerClustersItr = showerClusters.begin(); showerClustersItr != showerClusters.end(); ++showerClustersItr){
422 for(
auto protoTracksFoundItr = showerClustersItr->clusterProtoTracks.begin(); protoTracksFoundItr < showerClustersItr->clusterProtoTracks.end(); ++protoTracksFoundItr){
423 if(*fpointId_to_clusterIdItr == (
unsigned int)protoTracksFoundItr->oldClusterNumber){
424 *fpointId_to_clusterIdItr = protoTracksFoundItr->clusterNumber;
433 std::map<int,double> protoTracksFoundSizes;
434 for(
auto protoTracksFoundItr = protoTracksFound.begin(); protoTracksFoundItr < protoTracksFound.end(); ++protoTracksFoundItr){
435 double d =
::norm(protoTracksFoundItr->pMin0-protoTracksFoundItr->pMax0, protoTracksFoundItr->pMin1-protoTracksFoundItr->pMax1);
436 if(!protoTracksFoundSizes.count(protoTracksFoundItr->clusterNumber))
437 protoTracksFoundSizes[protoTracksFoundItr->clusterNumber] = d;
439 protoTracksFoundSizes[protoTracksFoundItr->clusterNumber]+= d;
446 for(
auto allhitsItr = allhits.cbegin(); allhitsItr != allhits.cend(); ++allhitsItr){
452 std::vector< art::Ptr<recob::Hit> > unclusteredhits;
453 std::vector<unsigned int> unclusteredhitsToAllhits;
458 double minDistanceShower;
461 for(
auto allhitsItr = allhits.cbegin(); allhitsItr != allhits.cend(); ++allhitsItr){
470 int ip = (*allhitsItr)->WireID().Plane;
471 p0 = ((*allhitsItr)->WireID().Wire)*
fWirePitch[ip];
472 p1 = (*allhitsItr)->PeakTime()*tickToDist;
475 minDistanceShower = 999999;
476 for(
auto showerClustersItr = showerClusters.begin(); showerClustersItr != showerClusters.end(); ++showerClustersItr){
477 for(
auto protoTracksItr = showerClustersItr->clusterProtoTracks.begin(); protoTracksItr < showerClustersItr->clusterProtoTracks.end(); ++protoTracksItr){
479 distance =
PointSegmentDistance( p0, p1, protoTracksItr->pMin0, protoTracksItr->pMin1, protoTracksItr->pMax0, protoTracksItr->pMax1);
488 if(distance < minDistanceShower){
490 minDistanceShower = distance;
521 unclusteredhitsToAllhits.push_back(allhitsItr-allhits.begin());
522 unclusteredhits.push_back(*allhitsItr);
545 size_t cid = nClusters + nDBClusters;
569 <<
" when only " << cid
570 <<
" clusters were found [0-" << cid-1
576 mf::LogInfo(
"fuzzyCluster") <<
"DWM (R*-tree): Found " 577 << cid <<
" clusters...";
578 for (
unsigned int c = 0; c < cid; ++c){
582 mf::LogVerbatim(
"fuzzyCluster") <<
"\t" <<
"...and " << noise <<
" noise points.";
603 std::vector<unsigned int> toMerge;
604 std::vector<double> mergeSlope;
605 std::vector<double> mergeTheta;
608 bool potentialBestMerge=
false;
609 bool performedBestMerge=
false;
610 unsigned int bestTrackClusterProtoTrack;
611 unsigned int bestShowerClusterProtoTrack;
613 int bestShowerRightLeft = -1;
615 double bestToMergeTrackClusterProtoTrackDistance=999999;
627 trackClusterProtoTrackItr++){
639 int nInDistanceTrackClusterLeft = 1;
640 int nInDistanceTrackClusterRight = 1;
646 ++showerClusterProtoTrackItr){
648 double segmentDistance =
HoughLineDistance(trackClusterProtoTrackItr->pMin0,trackClusterProtoTrackItr->pMin1,
649 trackClusterProtoTrackItr->pMax0,trackClusterProtoTrackItr->pMax1,
650 showerClusterProtoTrackItr->pMin0,showerClusterProtoTrackItr->pMin1,
651 showerClusterProtoTrackItr->pMax0,showerClusterProtoTrackItr->pMax1);
654 toMerge.push_back(showerClusterProtoTrackItr-showerClusterI->
clusterProtoTracks.begin());
655 mergeSlope.push_back(trackClusterProtoTrackItr->clusterSlope*xyScale);
662 double x11 = showerClusterProtoTrackItr->pMin0;
663 double y11 = showerClusterProtoTrackItr->pMin1;
664 double x12 = showerClusterProtoTrackItr->pMax0;
665 double y12 = showerClusterProtoTrackItr->pMax1;
666 double x21 = trackClusterProtoTrackItr->pMin0;
667 double y21 = trackClusterProtoTrackItr->pMin1;
668 double x22 = trackClusterProtoTrackItr->pMax0;
669 double y22 = trackClusterProtoTrackItr->pMax1;
672 double mergeRightClusIndexStartDist =
::norm(x11-x22, y11-y22);
674 double mergeLeftClusIndexStartDist =
::norm(x12-x21, y12-y21);
678 if( mergeRightClusIndexStartDist > mergeLeftClusIndexStartDist )
679 ++nInDistanceTrackClusterLeft;
681 ++nInDistanceTrackClusterRight;
690 mergeTheta.resize(toMerge.size());
693 for(
auto mergeThetaItr = mergeTheta.begin(); mergeThetaItr != mergeTheta.end(); ++mergeThetaItr){
694 double toMergeSlope = showerClusterI->
clusterProtoTracks[toMerge[mergeThetaItr-mergeTheta.begin()]].clusterSlope*xyScale;
695 mergeTheta[mergeThetaItr-mergeTheta.begin()] = std::atan(std::abs(( toMergeSlope - mergeSlope[mergeThetaItr-mergeTheta.begin()])/(1 + toMergeSlope*mergeSlope[mergeThetaItr-mergeTheta.begin()] )))*(180/TMath::Pi());
700 for(
auto toMergeItr = toMerge.begin(); toMergeItr != toMerge.end(); toMergeItr++){
709 double closestDistance=999999;
710 for (
auto showerClusterProtoTrackHitItr = showerClusterI->
clusterProtoTracks[*toMergeItr].hits.begin(); showerClusterProtoTrackHitItr != showerClusterI->
clusterProtoTracks[*toMergeItr].hits.end(); ++showerClusterProtoTrackHitItr) {
711 for (
auto trackClusterProtoTrackHitItr = trackClusterProtoTrackItr->hits.begin(); trackClusterProtoTrackHitItr != trackClusterProtoTrackItr->hits.end(); trackClusterProtoTrackHitItr++) {
716 *showerClusterProtoTrackHitItr,
719 if(distance < closestDistance){
720 closestDistance = distance;
737 x21 = trackClusterProtoTrackItr->pMin0;
738 y21 = trackClusterProtoTrackItr->pMin1;
739 x22 = trackClusterProtoTrackItr->pMax0;
740 y22 = trackClusterProtoTrackItr->pMax1;
743 std::array<double, 4> distances = {{
752 double minDistance = 999999;
753 int minDistanceIndex = -1;
754 for(
unsigned int j = 0; j < distances.size(); j++){
755 if (distances[j] < minDistance){
756 minDistance = distances[j];
757 minDistanceIndex = j;
761 if(minDistanceIndex == 0 || minDistanceIndex == 3)
768 trackClusterProtoTrackItr->mergedLeft =
true;
772 trackClusterProtoTrackItr->mergedRight =
true;
789 potentialBestMerge=
true;
792 if(minDistance < bestToMergeTrackClusterProtoTrackDistance){
793 bestShowerClusterProtoTrack=*toMergeItr;
794 bestTrackClusterProtoTrack=trackClusterProtoTrackItr-trackClusterJ->
clusterProtoTracks.begin();
796 bestToMergeTrackClusterProtoTrackDistance=minDistance;
799 if(minDistanceIndex == 1){
800 bestShowerRightLeft = 0;
803 if(minDistanceIndex == 2){
804 bestShowerRightLeft = 1;
814 if(potentialBestMerge){
817 if(bestShowerRightLeft == 0){
820 performedBestMerge=
true;
822 if(bestShowerRightLeft == 1){
825 performedBestMerge=
true;
828 if(performedBestMerge){
838 return performedBestMerge;
846 std::vector<trackCluster> *trackClusters,
855 if(trackClusters->size() == 0 || trackClusters->size() == 1)
859 if(trackClusters->size() == clusIndexStart+1)
862 std::vector<unsigned int> toMerge;
863 std::vector<double> mergeSlope;
864 std::vector<double> mergeTheta;
867 bool potentialBestMerge=
false;
868 bool performedBestMerge=
false;
869 unsigned int bestToMergeTrackCluster;
870 unsigned int bestTrackClustersClusIndexStartProtoTrack;
871 unsigned int bestToMergeTrackClusterProtoTrack;
873 int bestToMergeRightLeft = -1;
875 double bestToMergeTrackClusterProtoTrackDistance=999999;
877 for(
auto trackClustersClusIndexStartProtoTrackItr = trackClusters->at(clusIndexStart).clusterProtoTracks.begin();
878 trackClustersClusIndexStartProtoTrackItr != trackClusters->at(clusIndexStart).clusterProtoTracks.end();
879 ++trackClustersClusIndexStartProtoTrackItr){
882 int nInDistanceClusIndexStartLeft = 1;
883 int nInDistanceClusIndexStartRight = 1;
886 for(
auto trackClustersToMergeItr = trackClusters->begin()+clusIndexStart+1; trackClustersToMergeItr != trackClusters->end(); trackClustersToMergeItr++){
887 if(trackClusters->at(clusIndexStart).clusterNumber == trackClustersToMergeItr->clusterNumber)
895 for(
auto trackClustersToMergeProtoTrackItr = trackClustersToMergeItr->clusterProtoTracks.begin();
896 trackClustersToMergeProtoTrackItr != trackClustersToMergeItr->clusterProtoTracks.end();
897 ++trackClustersToMergeProtoTrackItr){
899 double segmentDistance =
HoughLineDistance(trackClustersClusIndexStartProtoTrackItr->pMin0,trackClustersClusIndexStartProtoTrackItr->pMin1,
900 trackClustersClusIndexStartProtoTrackItr->pMax0,trackClustersClusIndexStartProtoTrackItr->pMax1,
901 trackClustersToMergeProtoTrackItr->pMin0,trackClustersToMergeProtoTrackItr->pMin1,
902 trackClustersToMergeProtoTrackItr->pMax0,trackClustersToMergeProtoTrackItr->pMax1);
905 toMerge.push_back(trackClustersToMergeProtoTrackItr-trackClustersToMergeItr->clusterProtoTracks.begin());
906 mergeSlope.push_back(trackClustersClusIndexStartProtoTrackItr->clusterSlope*xyScale);
913 double x11 = trackClustersToMergeProtoTrackItr->pMin0;
914 double y11 = trackClustersToMergeProtoTrackItr->pMin1;
915 double x12 = trackClustersToMergeProtoTrackItr->pMax0;
916 double y12 = trackClustersToMergeProtoTrackItr->pMax1;
917 double x21 = trackClustersClusIndexStartProtoTrackItr->pMin0;
918 double y21 = trackClustersClusIndexStartProtoTrackItr->pMin1;
919 double x22 = trackClustersClusIndexStartProtoTrackItr->pMax0;
920 double y22 = trackClustersClusIndexStartProtoTrackItr->pMax1;
923 double mergeRightClusIndexStartDist = std::sqrt(
sqr(x11-x22) +
sqr(y11-y22));
925 double mergeLeftClusIndexStartDist = std::sqrt(
sqr(x12-x21) +
sqr(y12-y21));
929 if( mergeRightClusIndexStartDist > mergeLeftClusIndexStartDist )
930 nInDistanceClusIndexStartLeft++;
932 nInDistanceClusIndexStartRight++;
939 mergeTheta.resize(toMerge.size());
942 for(
auto mergeThetaItr = mergeTheta.begin(); mergeThetaItr != mergeTheta.end(); ++mergeThetaItr){
943 double toMergeSlope = trackClustersToMergeItr->clusterProtoTracks[toMerge[mergeThetaItr-mergeTheta.begin()]].clusterSlope*xyScale;
944 mergeTheta[mergeThetaItr-mergeTheta.begin()] = std::atan(std::abs(( toMergeSlope - mergeSlope[mergeThetaItr-mergeTheta.begin()])/(1 + toMergeSlope*mergeSlope[mergeThetaItr-mergeTheta.begin()] )))*(180/TMath::Pi());
949 for(
auto toMergeItr = toMerge.begin(); toMergeItr != toMerge.end(); toMergeItr++){
952 int closestToMerge=-1;
953 int closestClusIndexStart=-1;
954 double closestDistance=999999;
955 for (
auto toMergeHitItr = trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits.begin(); toMergeHitItr != trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits.end(); toMergeHitItr++) {
956 for (
auto clusIndStHitItr = trackClustersClusIndexStartProtoTrackItr->hits.begin(); clusIndStHitItr != trackClustersClusIndexStartProtoTrackItr->hits.end(); clusIndStHitItr++) {
964 if(distance < closestDistance){
965 closestDistance = distance;
966 closestToMerge=toMergeHitItr-trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits.begin();
967 closestClusIndexStart=clusIndStHitItr-trackClustersClusIndexStartProtoTrackItr->hits.begin();
974 using Pair_I_D = std::pair<int,double>;
975 std::vector<Pair_I_D> closestToMergeDist;
976 for (
auto toMergeHitItr = trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits.begin(); toMergeHitItr != trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits.end(); ++toMergeHitItr) {
977 if(closestToMerge==toMergeHitItr-trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits.begin())
979 double distance =
DistanceBetweenHits(trackClustersClusIndexStartProtoTrackItr->hits[closestClusIndexStart],
984 bool foundCloser =
false;
985 for(
auto closestToMergeDistItr = closestToMergeDist.begin(); closestToMergeDistItr != closestToMergeDist.end(); closestToMergeDistItr++) {
986 if(closestToMergeDistItr->second > distance){
992 || closestToMergeDist.size() < trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits.size()-1
993 || closestToMergeDist.size() < 9){
994 closestToMergeDist.emplace_back(toMergeHitItr-trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits.begin(),distance);
995 std::sort(closestToMergeDist.begin(), closestToMergeDist.end(),
996 [](
const Pair_I_D& a,
const Pair_I_D& b){
return a.second < b.second; }
1000 if(closestToMergeDist.size() > trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits.size()-1 ||
1001 closestToMergeDist.size() > 9)
1002 closestToMergeDist.erase(closestToMergeDist.end());
1011 std::vector<Pair_I_D> closestClusIndexStartDist;
1012 for (
auto clusIndexStartHitItr = trackClustersClusIndexStartProtoTrackItr->hits.begin(); clusIndexStartHitItr != trackClustersClusIndexStartProtoTrackItr->hits.end(); ++clusIndexStartHitItr) {
1013 if(closestClusIndexStart==clusIndexStartHitItr-trackClustersClusIndexStartProtoTrackItr->hits.begin())
1017 trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits[closestToMerge],
1021 bool foundCloser =
false;
1022 for(
auto closestClusIndexStartDistItr = closestClusIndexStartDist.begin(); closestClusIndexStartDistItr != closestClusIndexStartDist.end(); ++closestClusIndexStartDistItr) {
1023 if(closestClusIndexStartDistItr->second > distance){
1029 || closestClusIndexStartDist.size() < trackClustersClusIndexStartProtoTrackItr->hits.size()-1
1030 || closestClusIndexStartDist.size() < 9){
1031 closestClusIndexStartDist.emplace_back(clusIndexStartHitItr-trackClustersClusIndexStartProtoTrackItr->hits.begin(),distance);
1032 std::sort(closestClusIndexStartDist.begin(), closestClusIndexStartDist.end(),
1033 [](
const Pair_I_D& a,
const Pair_I_D& b){
return a.second < b.second; }
1036 if(closestClusIndexStartDist.size() > trackClustersClusIndexStartProtoTrackItr->hits.size()-1 ||
1037 closestClusIndexStartDist.size() > 9)
1038 closestClusIndexStartDist.erase(closestClusIndexStartDist.end());
1043 double toMergeAveCharge = trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits[closestToMerge]->Integral();
1044 double toMergeAveSigmaCharge = trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits[closestToMerge]->SigmaIntegral();
1045 for(
auto closestToMergeDistItr = closestToMergeDist.begin(); closestToMergeDistItr != closestToMergeDist.end(); ++closestToMergeDistItr) {
1046 toMergeAveCharge+= trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits[closestToMergeDistItr->first]->Integral();
1047 toMergeAveSigmaCharge+= trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits[closestToMergeDistItr->first]->SigmaIntegral();
1049 double clusIndexStartAveCharge = trackClustersClusIndexStartProtoTrackItr->hits[closestClusIndexStart]->Integral();
1050 double clusIndexStartAveSigmaCharge = trackClustersClusIndexStartProtoTrackItr->hits[closestClusIndexStart]->SigmaIntegral();
1051 for(
auto closestClusIndexStartDistItr = closestClusIndexStartDist.begin(); closestClusIndexStartDistItr != closestClusIndexStartDist.end(); ++closestClusIndexStartDistItr) {
1052 clusIndexStartAveCharge+= trackClustersClusIndexStartProtoTrackItr->hits[closestClusIndexStartDistItr->first]->Integral();
1053 clusIndexStartAveSigmaCharge+=trackClustersClusIndexStartProtoTrackItr->hits[closestClusIndexStartDistItr->first]->SigmaIntegral();
1058 double chargeAsymmetry = std::abs(toMergeAveCharge-clusIndexStartAveCharge)/(toMergeAveCharge+clusIndexStartAveCharge);
1059 double sigmaChargeAsymmetry = std::abs(toMergeAveSigmaCharge-clusIndexStartAveSigmaCharge)/(toMergeAveSigmaCharge+clusIndexStartAveSigmaCharge);
1060 double chargeAsymmetrySinAngle = chargeAsymmetry*std::abs(sin(mergeTheta[toMergeItr-toMerge.begin()]*TMath::Pi()/180));
1061 double sigmaChargeAsymmetrySinAngle = sigmaChargeAsymmetry*std::fabs(sin(mergeTheta[toMergeItr-toMerge.begin()]*TMath::Pi()/180));
1080 double x11 = trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].pMin0;
1081 double y11 = trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].pMin1;
1082 double x12 = trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].pMax0;
1083 double y12 = trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].pMax1;
1084 double x21 = trackClustersClusIndexStartProtoTrackItr->pMin0;
1085 double y21 = trackClustersClusIndexStartProtoTrackItr->pMin1;
1086 double x22 = trackClustersClusIndexStartProtoTrackItr->pMax0;
1087 double y22 = trackClustersClusIndexStartProtoTrackItr->pMax1;
1090 std::array<double, 4> distances = {{
1092 ::norm(x11-x21, y11-y21),
1093 ::norm(x11-x22, y11-y22),
1094 ::norm(x12-x21, y12-y21),
1099 double minDistance = 999999;
1100 int minDistanceIndex = -1;
1101 for(
unsigned int j = 0; j < distances.size(); j++){
1102 if (distances[j] < minDistance){
1103 minDistance = distances[j];
1104 minDistanceIndex = j;
1108 if(minDistanceIndex == 0 || minDistanceIndex == 3)
1116 trackClustersClusIndexStartProtoTrackItr->mergedLeft =
true;
1117 trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].mergedRight =
true;
1120 trackClustersClusIndexStartProtoTrackItr->mergedRight =
true;
1121 trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].mergedLeft =
true;
1128 if(trackClustersClusIndexStartProtoTrackItr->mergedLeft ==
true && minDistanceIndex == 2)
1130 if(trackClustersClusIndexStartProtoTrackItr->mergedRight ==
true && minDistanceIndex == 1)
1132 if(trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].mergedLeft ==
true && minDistanceIndex == 1)
1134 if(trackClustersToMergeItr->clusterProtoTracks[*toMergeItr].mergedRight ==
true && minDistanceIndex == 2)
1139 potentialBestMerge=
true;
1142 if(minDistance < bestToMergeTrackClusterProtoTrackDistance){
1143 bestToMergeTrackCluster=trackClustersToMergeItr-trackClusters->begin();
1144 bestToMergeTrackClusterProtoTrack=*toMergeItr;
1145 bestTrackClustersClusIndexStartProtoTrack=trackClustersClusIndexStartProtoTrackItr-trackClusters->at(clusIndexStart).clusterProtoTracks.begin();
1146 bestToMergeTrackClusterProtoTrackDistance=minDistance;
1149 if(minDistanceIndex == 1){
1150 bestToMergeRightLeft = 0;
1153 if(minDistanceIndex == 2){
1154 bestToMergeRightLeft = 1;
1164 if(potentialBestMerge){
1165 trackClusters->at(bestToMergeTrackCluster).clusterProtoTracks[bestToMergeTrackClusterProtoTrack].merged=
true;
1166 trackClusters->at(clusIndexStart).clusterProtoTracks[bestTrackClustersClusIndexStartProtoTrack].merged=
true;
1167 if(bestToMergeRightLeft == 0){
1168 trackClusters->at(bestToMergeTrackCluster).clusterProtoTracks[bestToMergeTrackClusterProtoTrack].mergedLeft =
true;
1169 trackClusters->at(clusIndexStart).clusterProtoTracks[bestTrackClustersClusIndexStartProtoTrack].mergedRight =
true;
1170 performedBestMerge=
true;
1172 if(bestToMergeRightLeft == 1){
1173 trackClusters->at(bestToMergeTrackCluster).clusterProtoTracks[bestToMergeTrackClusterProtoTrack].mergedRight =
true;
1174 trackClusters->at(clusIndexStart).clusterProtoTracks[bestTrackClustersClusIndexStartProtoTrack].mergedLeft =
true;
1175 performedBestMerge=
true;
1178 if(performedBestMerge){
1179 trackClusters->at(clusIndexStart).addProtoTracks(trackClusters->at(bestToMergeTrackCluster).clusterProtoTracks);
1180 trackClusters->at(bestToMergeTrackCluster).clearProtoTracks();
1205 return performedBestMerge;
1213 std::vector<showerCluster> *showerClusters,
1220 if(showerClusters->size() == 0 || showerClusters->size() == 1)
1224 if(showerClusters->size() == clusIndexStart+1)
1227 std::vector<unsigned int> toMerge;
1228 std::vector<double> mergeSlope;
1229 std::vector<double> mergeTheta;
1233 bool performedBestMerge=
false;
1234 unsigned int bestToMergeShowerCluster;
1235 unsigned int bestShowerClustersClusIndexStartProtoTrack;
1236 unsigned int bestToMergeShowerClusterProtoTrack;
1237 int bestToMergeRightLeft = -1;
1239 double bestToMergeShowerClusterProtoTrackDistance=999999;
1242 for(
auto showerClustersClusIndexStartProtoTrackItr = showerClusters->at(clusIndexStart).clusterProtoTracks.begin();
1243 showerClustersClusIndexStartProtoTrackItr != showerClusters->at(clusIndexStart).clusterProtoTracks.end();
1244 ++showerClustersClusIndexStartProtoTrackItr){
1246 for(
auto showerClustersToMergeItr = showerClusters->begin()+clusIndexStart+1; showerClustersToMergeItr != showerClusters->end(); ++showerClustersToMergeItr){
1253 for(
auto showerClustersToMergeProtoTrackItr = showerClustersToMergeItr->clusterProtoTracks.begin();
1254 showerClustersToMergeProtoTrackItr != showerClustersToMergeItr->clusterProtoTracks.end();
1255 ++showerClustersToMergeProtoTrackItr){
1257 if(showerClustersToMergeProtoTrackItr->clusterNumber == showerClustersClusIndexStartProtoTrackItr->clusterNumber)
1261 double segmentDistance =
HoughLineDistance(showerClustersClusIndexStartProtoTrackItr->pMin0,showerClustersClusIndexStartProtoTrackItr->pMin1,
1262 showerClustersClusIndexStartProtoTrackItr->pMax0,showerClustersClusIndexStartProtoTrackItr->pMax1,
1263 showerClustersToMergeProtoTrackItr->pMin0,showerClustersToMergeProtoTrackItr->pMin1,
1264 showerClustersToMergeProtoTrackItr->pMax0,showerClustersToMergeProtoTrackItr->pMax1);
1267 toMerge.push_back(showerClustersToMergeProtoTrackItr-showerClustersToMergeItr->clusterProtoTracks.begin());
1268 mergeSlope.push_back(showerClustersClusIndexStartProtoTrackItr->clusterSlope*xyScale);
1274 mergeTheta.resize(toMerge.size());
1277 for(
auto mergeThetaItr = mergeTheta.begin(); mergeThetaItr != mergeTheta.end(); ++mergeThetaItr){
1278 double toMergeSlope = showerClustersToMergeItr->clusterProtoTracks[toMerge[mergeThetaItr-mergeTheta.begin()]].clusterSlope*xyScale;
1279 mergeTheta[mergeThetaItr-mergeTheta.begin()] = std::atan(std::abs(( toMergeSlope - mergeSlope[mergeThetaItr-mergeTheta.begin()])/(1 + toMergeSlope*mergeSlope[mergeThetaItr-mergeTheta.begin()] )))*(180/TMath::Pi());
1284 for(
auto toMergeItr = toMerge.begin(); toMergeItr != toMerge.end(); ++toMergeItr){
1293 double closestDistance=999999;
1294 for (
auto toMergeHitItr = showerClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits.begin(); toMergeHitItr != showerClustersToMergeItr->clusterProtoTracks[*toMergeItr].hits.end(); ++toMergeHitItr) {
1295 for (
auto clusIndStHitItr = showerClustersClusIndexStartProtoTrackItr->hits.begin(); clusIndStHitItr != showerClustersClusIndexStartProtoTrackItr->hits.end(); ++clusIndStHitItr) {
1303 if(distance < closestDistance){
1304 closestDistance = distance;
1317 double x11 = showerClustersToMergeItr->clusterProtoTracks[*toMergeItr].pMin0;
1318 double y11 = showerClustersToMergeItr->clusterProtoTracks[*toMergeItr].pMin1;
1319 double x12 = showerClustersToMergeItr->clusterProtoTracks[*toMergeItr].pMax0;
1320 double y12 = showerClustersToMergeItr->clusterProtoTracks[*toMergeItr].pMax1;
1321 double x21 = showerClustersClusIndexStartProtoTrackItr->pMin0;
1322 double y21 = showerClustersClusIndexStartProtoTrackItr->pMin1;
1323 double x22 = showerClustersClusIndexStartProtoTrackItr->pMax0;
1324 double y22 = showerClustersClusIndexStartProtoTrackItr->pMax1;
1327 std::array<double, 4> distances = {{
1329 ::norm(x11-x21, y11-y21),
1330 ::norm(x11-x22, y11-y22),
1331 ::norm(x12-x21, y12-y21),
1336 double minDistance = 999999;
1337 int minDistanceIndex = -1;
1338 for(
unsigned int j = 0; j < distances.size(); ++j){
1339 if (distances[j] < minDistance){
1340 minDistance = distances[j];
1341 minDistanceIndex = j;
1345 if(minDistanceIndex == 0 || minDistanceIndex == 3)
1362 performedBestMerge=
true;
1365 if(closestDistance < bestToMergeShowerClusterProtoTrackDistance){
1366 bestToMergeShowerCluster=showerClustersToMergeItr-showerClusters->begin();
1367 bestToMergeShowerClusterProtoTrack=*toMergeItr;
1368 bestShowerClustersClusIndexStartProtoTrack=showerClustersClusIndexStartProtoTrackItr-showerClusters->at(clusIndexStart).clusterProtoTracks.begin();
1370 if(minDistanceIndex == 1){
1371 bestToMergeRightLeft = 0;
1374 if(minDistanceIndex == 2){
1375 bestToMergeRightLeft = 1;
1385 if(performedBestMerge){
1386 showerClusters->at(bestToMergeShowerCluster).clusterProtoTracks[bestToMergeShowerClusterProtoTrack].merged=
true;
1387 showerClusters->at(clusIndexStart).clusterProtoTracks[bestShowerClustersClusIndexStartProtoTrack].merged=
true;
1388 if(bestToMergeRightLeft == 0){
1389 showerClusters->at(bestToMergeShowerCluster).clusterProtoTracks[bestToMergeShowerClusterProtoTrack].mergedLeft =
true;
1390 showerClusters->at(clusIndexStart).clusterProtoTracks[bestShowerClustersClusIndexStartProtoTrack].mergedRight =
true;
1392 if(bestToMergeRightLeft == 1){
1393 showerClusters->at(bestToMergeShowerCluster).clusterProtoTracks[bestToMergeShowerClusterProtoTrack].mergedRight =
true;
1394 showerClusters->at(clusIndexStart).clusterProtoTracks[bestShowerClustersClusIndexStartProtoTrack].mergedLeft =
true;
1397 showerClusters->at(clusIndexStart).addProtoTracks(showerClusters->at(bestToMergeShowerCluster).clusterProtoTracks);
1398 showerClusters->at(bestToMergeShowerCluster).clearProtoTracks();
1403 return performedBestMerge;
1415 const double pHit0[2] = {
1419 const double pHit1[2] = {
1443 double x11 = p0MinLine1;
1444 double y11 = p1MinLine1;
1445 double x12 = p0MaxLine1;
1446 double y12 = p1MaxLine1;
1447 double x21 = p0MinLine2;
1448 double y21 = p1MinLine2;
1449 double x22 = p0MaxLine2;
1450 double y22 = p1MaxLine2;
1454 std::vector<double> distances;
1460 double minDistance = 999999;
1461 for(
unsigned int j = 0; j < distances.size(); j++){
1462 if (distances[j] < minDistance)
1463 minDistance = distances[j];
1486 double dx1 = x12 - x11;
1487 double dy1 = y12 - y11;
1488 double dx2 = x22 - x21;
1489 double dy2 = y22 - y21;
1491 double delta = dy2*dx1 - dx2*dy1;
1492 if (delta == 0)
return false;
1494 double t = (dx2*(y11 - y21) + dy2*(x21 - x11)) / delta;
1495 double s = (dx1*(y11 - y21) + dy1*(x21 - x11)) / delta;
1497 return (0 <= s && s <= 1 && 0 <= t && t <= 1);
1511 double dx = x2 -
x1;
1512 double dy = y2 -
y1;
1513 if ( dx == 0 && dy == 0 )
1517 double t = ((px -
x1)*dx + (py - y1)*dy) / ::sumsq(dx, dy);
1529 else if(0 <= t && t <= 1) {
1530 double near_x = x1 + t * dx;
1531 double near_y = y1 + t * dy;
std::vector< std::vector< double > > fsim3
bool mergeShowerClusters(unsigned int k, std::vector< showerCluster > *showerClusters, double xyScale, double wire_dist, double tickToDist)
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
const unsigned int kNO_CLUSTER
virtual unsigned int ReadOutWindowSize() const =0
std::vector< bool > fnoise
void run_fuzzy_cluster(const std::vector< art::Ptr< recob::Hit > > &allhits)
virtual void reconfigure(fhicl::ParameterSet const &pset)
double fFuzzyRemnantMergeCutoff
cut off on merging the fuzzy cluster remnants into the nearest shower or track
double fSigmaChargeAsymAngleCut
Cut on product of charge asymmetry and sin of angle between slopes of lines.
Float_t y1[n_points_granero]
std::vector< bool > fvisited
bool HoughLineIntersect(double x11, double y11, double x12, double y12, double x21, double y21, double x22, double y22)
trackCluster(protoTrack protoTrackTemp)
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
Float_t x1[n_points_granero]
Declaration of signal hit object.
std::vector< std::vector< double > > fsim2
std::set< uint32_t > fBadChannels
set of bad channels in this detector
double fTrackClusterMergeCutoff
Max distance between Hough lines before two lines are merged (muon tracks),.
int fMaxVertexLines
Max number of line end points allowed in a Hough line merge region for a merge to happen...
virtual double SamplingRate() const =0
Returns the period of the TPC readout electronics clock.
double fNumberWireBoundaries
Number of boundaries in wires for the drift window to be divided up to make the Hough line finder eas...
std::vector< std::vector< double > > fsim
bool fDoFuzzyRemnantMerge
Tell the algorithm to merge fuzzy cluster remnants into showers or tracks (0-off, 1-on) ...
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
Cluster finding and building.
This stores information about a tracklike cluster.
void addProtoTracks(std::vector< protoTrack > tracksToAdd)
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
double fShowerTrackClusterMergeAngle
Max angle between slopes before two lines are merged, for lines in shower line regions.
Float_t y2[n_points_geant4]
std::vector< protoTrack > clusterProtoTracks
void InitFuzzy(std::vector< art::Ptr< recob::Hit > > &allhits, std::set< uint32_t > badChannels)
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
size_t Transform(std::vector< art::Ptr< recob::Hit > > const &hits, std::vector< unsigned int > *fpointId_to_clusterId, unsigned int clusterId, unsigned int *nClusters, std::vector< protoTrack > *protoTracks)
const unsigned int kNOISE_CLUSTER
bool fDoTrackClusterMerge
Turn on cut on product of charge asymmetry and sin of angle between slopes of lines.
bool fDoShowerTrackClusterMerge
Turn on cut on product of charge asymmetry and sin of angle between slopes of lines.
bool fDoShowerClusterMerge
Turns on shower Hough line merging (0-off, 1-on)
Signal from induction planes.
enum geo::_plane_sigtype SigType_t
Enumerate the possible plane projections.
virtual double Temperature() const =0
T get(std::string const &key) const
baseCluster(protoTrack protoTrackTemp)
std::vector< uint32_t > fBadWireSum
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
This stores information about a cluster.
This stores information about a showerlike cluster.
double HoughLineDistance(double p0MinLine1, double p1MinLine1, double p0MaxLine1, double p1MaxLine1, double p0MinLine2, double p1MinLine2, double p0MaxLine2, double p1MaxLine2)
bool mergeTrackClusters(unsigned int k, std::vector< trackCluster > *trackClusters, double xyScale, double wire_dist, double tickToDist)
std::vector< std::vector< double > > fps
the collection of points we are working on
Definition of data types for geometry description.
bool fGenerateHoughLinesOnly
Show only the results of the Hough line finder, hits not in a line will not be clustered.
float PeakTime() const
Time of the signal peak, in tick units.
std::vector< unsigned int > fpointId_to_clusterId
mapping point_id -> clusterId
virtual ~fuzzyClusterAlg()
double fShowerClusterMergeAngle
Max angle between slopes before two lines are merged, for lines in shower line regions.
std::vector< double > fWirePitch
the pitch of the wires in each plane
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc'th TPC in the cryostat.
virtual double DriftVelocity(double efield=0., double temperature=0.) const =0
double fNumberTimeBoundaries
Number of boundaries in ticks for the drift window to be divided up to make the Hough line finder eas...
bool mergeShowerTrackClusters(showerCluster *showerClusterI, trackCluster *trackClusterJ, double xyScale, double wire_dist, double tickToDist)
double PointSegmentDistance(double px, double py, double x1, double y1, double x2, double y2)
void reconfigure(fhicl::ParameterSet const &p)
std::vector< std::vector< unsigned int > > fclusters
collection of something
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
double fShowerTrackClusterMergeCutoff
Max distance between Hough lines before two lines are merged (electron showers),. ...
virtual double Efield(unsigned int planegap=0) const =0
Returns the nominal electric field in the specified volume.
double fShowerLikenessCut
Cut on shower likeness (larger the more shower like, smaller the less shower like) ...
double fVertexLinesCutoff
Size of the vertex region to count up lines for fMaxVertexLines.
double fShowerClusterMergeCutoff
Max distance between Hough lines before two lines are merged (electron showers),. ...
fuzzyClusterAlg(fhicl::ParameterSet const &pset)
Float_t x2[n_points_geant4]
void reconfigure(fhicl::ParameterSet const &p)
recob::tracking::Plane Plane
raw::ChannelID_t Channel() const
ID of the readout channel the hit was extracted from.
double fChargeAsymAngleCut
Cut on product of charge asymmetry and sin of angle between slopes of lines.
double DistanceBetweenHits(art::Ptr< recob::Hit > hit0, art::Ptr< recob::Hit > hit1, double wire_dist, double tickToDist)
showerCluster(protoTrack protoTrackTemp)