9 #include "art/Framework/Core/ProducesCollector.h"
10 #include "art/Framework/Principal/Event.h"
11 #include "art/Framework/Principal/Handle.h"
12 #include "art/Framework/Services/Registry/ServiceHandle.h"
13 #include "art/Persistency/Common/PtrMaker.h"
14 #include "art/Utilities/ToolMacros.h"
15 #include "art_root_io/TFileDirectory.h"
16 #include "art_root_io/TFileService.h"
17 #include "canvas/Persistency/Common/Assns.h"
18 #include "canvas/Persistency/Common/FindOneP.h"
19 #include "canvas/Persistency/Common/Ptr.h"
20 #include "canvas/Utilities/InputTag.h"
21 #include "cetlib/cpu_timer.h"
22 #include "fhiclcpp/ParameterSet.h"
23 #include "messagefacility/MessageLogger/MessageLogger.h"
51 namespace lar_cluster3d {
59 struct Hit2DSetCompare
64 using HitVector = std::vector<const reco::ClusterHit2D*>;
69 using Hit2DList = std::list<reco::ClusterHit2D>;
70 using Hit2DSet = std::set<const reco::ClusterHit2D*, Hit2DSetCompare>;
95 virtual void produces(art::ProducesCollector&)
override;
97 virtual void configure(
const fhicl::ParameterSet&)
override;
154 using HitMatchTriplet = std::tuple<const reco::ClusterHit2D*,const reco::ClusterHit2D*,const reco::ClusterHit3D>;
171 float hitWidthSclFctr = 1.,
172 size_t hitPairCntr = 0)
const;
195 float closestApproach(
const Eigen::Vector3f&,
const Eigen::Vector3f&,
const Eigen::Vector3f&,
const Eigen::Vector3f&,
float&,
float&)
const;
292 m_channelFilter(&art::ServiceHandle<lariov::ChannelStatusService
const>()->GetProvider())
302 collector.produces< std::vector<recob::Hit>>();
303 collector.produces< art::Assns<recob::Wire, recob::Hit>>();
304 collector.produces< art::Assns<raw::RawDigit, recob::Hit>>();
311 m_hitFinderTagVec = pset.get<std::vector<art::InputTag>>(
"HitFinderTagVec", std::vector<art::InputTag>()={
"gaushit"});
320 m_invalidTPCVec = pset.get<std::vector<int> >(
"InvalidTPCVec", std::vector<int>());
325 m_geometry = art::ServiceHandle<geo::Geometry const>{}.get();
334 if (m_outputHistograms)
336 art::ServiceHandle<art::TFileService>
tfs;
338 m_tupleTree = tfs->make<TTree>(
"Hit3DBuilderTree",
"Tree by SnippetHit3DBuilder");
413 return (*left).getAvePeakTime() < (*right).getAvePeakTime();
416 struct HitPairClusterOrder
418 bool operator()(
const reco::HitPairClusterMap::iterator& left,
const reco::HitPairClusterMap::iterator& right)
421 if (left->second.size() == right->second.size())
422 return left->first < right->first;
424 return left->second.size() > right->second.size();
438 std::unique_ptr<std::vector<recob::Hit>> outputHitPtrVec(
new std::vector<recob::Hit>);
451 if (!hitPairList.empty())
457 std::unique_ptr<art::Assns<recob::Wire, recob::Hit>> wireAssns(
new art::Assns<recob::Wire, recob::Hit>);
462 std::unique_ptr<art::Assns<raw::RawDigit, recob::Hit>> rawDigitAssns(
new art::Assns<raw::RawDigit, recob::Hit>);
467 evt.put(std::move(outputHitPtrVec));
468 evt.put(std::move(wireAssns));
469 evt.put(std::move(rawDigitAssns));
488 cet::cpu_timer theClockMakeHits;
500 theClockMakeHits.stop();
505 mf::LogDebug(
"Cluster3D") <<
">>>>> 3D hit building done, found " << numHitPairs <<
" 3D Hits" << std::endl;
519 if (left.first == left.second)
return false;
520 if (right.first == right.second)
return true;
523 return left.first->first.first < right.first->first.first;
549 size_t totalNumHits(0);
550 size_t hitPairCntr(0);
553 size_t nDeadChanHits(0);
564 PlaneToSnippetHitMap::iterator mapItr0 = planeToSnippetHitMap.find(
geo::PlaneID(cryoIdx,tpcIdx,0));
565 PlaneToSnippetHitMap::iterator mapItr1 = planeToSnippetHitMap.find(
geo::PlaneID(cryoIdx,tpcIdx,1));
566 PlaneToSnippetHitMap::iterator mapItr2 = planeToSnippetHitMap.find(
geo::PlaneID(cryoIdx,tpcIdx,2));
568 size_t nPlanesWithHits = (mapItr0 != planeToSnippetHitMap.end() && !mapItr0->second.empty() ? 1 : 0)
569 + (mapItr1 != planeToSnippetHitMap.end() && !mapItr1->second.empty() ? 1 : 0)
570 + (mapItr2 != planeToSnippetHitMap.end() && !mapItr2->second.empty() ? 1 : 0);
572 if (nPlanesWithHits < 2)
continue;
590 mf::LogDebug(
"Cluster3D") <<
"Total number hits: " << totalNumHits << std::endl;
591 mf::LogDebug(
"Cluster3D") <<
"Created a total of " << hitPairList.size() <<
" hit pairs, counted: " << hitPairCntr << std::endl;
592 mf::LogDebug(
"Cluster3D") <<
"-- Triplets: " << nTriplets <<
", dead channel pairs: " << nDeadChanHits << std::endl;
594 return hitPairList.size();
610 auto SetStartIterator = [](SnippetHitMap::iterator startItr, SnippetHitMap::iterator endItr,
float startTime)
612 while(startItr != endItr)
614 if (startItr->first.second < startTime) startItr++;
620 auto SetEndIterator = [](SnippetHitMap::iterator lastItr, SnippetHitMap::iterator endItr,
float endTime)
622 while(lastItr != endItr)
624 if (lastItr->first.first < endTime) lastItr++;
631 size_t nDeadChanHits(0);
638 std::sort(snippetHitMapItrVec.begin(),snippetHitMapItrVec.end(),
SetStartTimeOrder());
641 int nPlanesWithHits(0);
643 for(
auto& pair : snippetHitMapItrVec)
644 if (pair.first != pair.second) nPlanesWithHits++;
646 if (nPlanesWithHits < 2)
break;
652 SnippetHitMap::iterator firstSnippetItr = snippetHitMapItrVec.front().first;
655 SnippetHitMap::iterator snippetHitMapItr1Start = SetStartIterator(snippetHitMapItrVec[1].
first, snippetHitMapItrVec[1].
second, firstSnippetItr->first.first);
656 SnippetHitMap::iterator snippetHitMapItr1End = SetEndIterator( snippetHitMapItr1Start, snippetHitMapItrVec[1].second, firstSnippetItr->first.second);
657 SnippetHitMap::iterator snippetHitMapItr2Start = SetStartIterator(snippetHitMapItrVec[2].first, snippetHitMapItrVec[2].second, firstSnippetItr->first.first);
658 SnippetHitMap::iterator snippetHitMapItr2End = SetEndIterator( snippetHitMapItr2Start, snippetHitMapItrVec[2].second, firstSnippetItr->first.second);
661 size_t curHitListSize(hitPairList.size());
665 size_t n12Pairs =
findGoodHitPairs(firstSnippetItr, snippetHitMapItr1Start, snippetHitMapItr1End, pair12Map);
666 size_t n13Pairs =
findGoodHitPairs(firstSnippetItr, snippetHitMapItr2Start, snippetHitMapItr2End, pair13Map);
668 nDeadChanHits += hitPairList.size() - curHitListSize;
669 curHitListSize = hitPairList.size();
671 if (n12Pairs > n13Pairs)
findGoodTriplets(pair12Map, pair13Map, hitPairList);
674 nTriplets += hitPairList.size() - curHitListSize;
676 snippetHitMapItrVec.front().first++;
679 return hitPairList.size();
683 SnippetHitMap::iterator& startItr,
684 SnippetHitMap::iterator& endItr,
689 HitVector::iterator firstMaxItr = std::max_element(firstSnippetItr->second.begin(),firstSnippetItr->second.end(),[](
const auto&
left,
const auto&
right){
return left->getHit()->PeakAmplitude() < right->getHit()->PeakAmplitude();});
690 float firstPHCut = firstMaxItr != firstSnippetItr->second.end() ?
m_pulseHeightFrac * (*firstMaxItr)->getHit()->PeakAmplitude() : 4096.;
693 for(
const auto& hit1 : firstSnippetItr->second)
696 if (hit1->getHit()->DegreesOfFreedom() > 1 && hit1->getHit()->PeakAmplitude() < firstPHCut && hit1->getHit()->PeakAmplitude() <
m_PHLowSelection)
continue;
699 SnippetHitMap::iterator secondHitItr = startItr;
702 while(secondHitItr != endItr)
704 HitVector::iterator secondMaxItr = std::max_element(secondHitItr->second.begin(),secondHitItr->second.end(),[](
const auto&
left,
const auto&
right){
return left->getHit()->PeakAmplitude() < right->getHit()->PeakAmplitude();});
705 float secondPHCut = secondMaxItr != secondHitItr->second.end() ?
m_pulseHeightFrac * (*secondMaxItr)->getHit()->PeakAmplitude() : 0.;
707 for(
const auto& hit2 : secondHitItr->second)
710 if (hit2->getHit()->DegreesOfFreedom() > 1 && hit2->getHit()->PeakAmplitude() < secondPHCut && hit2->getHit()->PeakAmplitude() <
m_PHLowSelection)
continue;
717 std::vector<const recob::Hit*> recobHitVec = {
nullptr,
nullptr,
nullptr};
719 recobHitVec[hit1->WireID().Plane] = hit1->getHit();
720 recobHitVec[hit2->WireID().Plane] = hit2->getHit();
724 hitMatchMap[wireID].emplace_back(hit1,hit2,pair);
739 if (!pair12Map.empty())
742 std::vector<reco::ClusterHit3D> tempDeadChanVec;
746 std::map<const reco::ClusterHit3D*,bool> usedPairMap;
749 for(
const auto& pair13 : pair13Map)
751 for(
const auto& hit2Dhit3DPair : pair13.second) usedPairMap[&std::get<2>(hit2Dhit3DPair)] =
false;
755 for(
const auto& pair12 : pair12Map)
757 if (pair12.second.empty())
continue;
761 for(
const auto& hit2Dhit3DPair12 : pair12.second)
766 usedPairMap[&pair1] =
false;
769 for(
const auto& pair13 : pair13Map)
771 if (pair13.second.empty())
continue;
773 for(
const auto& hit2Dhit3DPair13 : pair13.second)
776 if (std::get<0>(hit2Dhit3DPair12) != std::get<0>(hit2Dhit3DPair13))
continue;
786 triplet.
setID(hitPairList.size());
787 hitPairList.emplace_back(triplet);
788 usedPairMap[&pair1] =
true;
789 usedPairMap[&pair2] =
true;
799 for(
const auto& pairMapPair : usedPairMap)
801 if (pairMapPair.second)
continue;
806 if (
makeDeadChannelPair(deadChanPair, *pair, 4, 0, 0.)) tempDeadChanVec.emplace_back(deadChanPair);
810 if(!tempDeadChanVec.empty())
813 if (tempDeadChanVec.size() > 1)
819 float firstSig = tempDeadChanVec.front().getDeltaPeakTime() / tempDeadChanVec.front().getSigmaPeakTime();
820 float lastSig = tempDeadChanVec.back().getDeltaPeakTime() / tempDeadChanVec.back().getSigmaPeakTime();
821 float sigRange = lastSig - firstSig;
826 float maxSignificance = std::max(0.75 * (firstSig + lastSig),1.0);
828 std::vector<reco::ClusterHit3D>::iterator firstBadElem = std::find_if(tempDeadChanVec.begin(),tempDeadChanVec.end(),[&maxSignificance](
const auto& pair){
return pair.getDeltaPeakTime()/pair.getSigmaPeakTime() > maxSignificance;});
831 if (
std::distance(tempDeadChanVec.begin(),firstBadElem) > 20) firstBadElem = tempDeadChanVec.begin() + 20;
833 else if (firstBadElem == tempDeadChanVec.begin()) firstBadElem++;
835 tempDeadChanVec.resize(
std::distance(tempDeadChanVec.begin(),firstBadElem));
839 for(
auto& pair : tempDeadChanVec)
841 pair.setID(hitPairList.size());
842 hitPairList.emplace_back(pair);
854 float hitWidthSclFctr,
855 size_t hitPairCntr)
const
877 float hit1Width = hitWidthSclFctr * hit1Sigma;
878 float hit2Width = hitWidthSclFctr * hit2Sigma;
881 if (fabs(hit1Peak - hit2Peak) <= (hit1Width + hit2Width))
884 float hit1SigSq = hit1Sigma * hit1Sigma;
885 float hit2SigSq = hit2Sigma * hit2Sigma;
886 float deltaPeakTime = std::fabs(hit1Peak - hit2Peak);
887 float sigmaPeakTime = std::sqrt(hit1SigSq + hit2SigSq);
901 float oneOverWghts = hit1SigSq * hit2SigSq / (hit1SigSq + hit2SigSq);
902 float avePeakTime = (hit1Peak / hit1SigSq + hit2Peak / hit2SigSq) * oneOverWghts;
904 float hitChiSquare = std::pow((hit1Peak - avePeakTime),2) / hit1SigSq
905 + std::pow((hit2Peak - avePeakTime),2) / hit2SigSq;
909 float xPosition = (xPositionHit1 / hit1SigSq + xPositionHit2 / hit2SigSq) * hit1SigSq * hit2SigSq / (hit1SigSq + hit2SigSq);
911 Eigen::Vector3f position(xPosition,
float(widIntersect.
y),
float(widIntersect.
z)-
m_zPosOffset);
925 hitVector.resize(3, NULL);
931 unsigned int tpcIdx = hit1->
WireID().
TPC;
934 std::vector<geo::WireID> wireIDVec = {
geo::WireID(cryostatIdx,tpcIdx,0,0),
942 std::vector<float> hitDelTSigVec = {0.,0.,0.};
944 hitDelTSigVec[hit1->
WireID().
Plane] = deltaPeakTime / sigmaPeakTime;
945 hitDelTSigVec[hit2->
WireID().
Plane] = deltaPeakTime / sigmaPeakTime;
1003 if (hitWireDist < wirePitch)
1016 if (!hit0) hit0 = pairHitVec[2];
1017 else if (!hit1) hit1 = pairHitVec[2];
1029 unsigned int statusBits(0x7);
1030 float avePeakTime(0.);
1031 float weightSum(0.);
1032 float xPosition(0.);
1038 for(
size_t planeIdx = 0; planeIdx < 3; planeIdx++)
1042 wireIDVec[planeIdx] = hit2D->
WireID();
1055 float weight = 1. / (hitRMS * hitRMS);
1057 avePeakTime += peakTime * weight;
1059 weightSum += weight;
1062 avePeakTime /= weightSum;
1063 xPosition /= weightSum;
1068 Eigen::Vector3f position(xPosition,
1069 float((pairYZVec[0] + pair0hYZVec[0] + pair1hYZVec[0]) / 3.),
1070 float((pairYZVec[1] + pair0hYZVec[1] + pair1hYZVec[1]) / 3.));
1073 float hitChiSquare(0.);
1074 float sigmaPeakTime(std::sqrt(1./weightSum));
1075 std::vector<float> hitDelTSigVec;
1077 for(
const auto& hit2D : hitVector)
1079 float hitRMS = hit2D->getHit()->RMS();
1085 float combRMS = std::sqrt(hitRMS*hitRMS - sigmaPeakTime*sigmaPeakTime);
1086 float peakTime = hit2D->getTimeTicks();
1087 float deltaTime = peakTime - avePeakTime;
1088 float hitSig = deltaTime / combRMS;
1090 hitChiSquare += hitSig * hitSig;
1092 hitDelTSigVec.emplace_back(std::fabs(hitSig));
1097 int lowMinIndex(std::numeric_limits<int>::max());
1098 int lowMaxIndex(std::numeric_limits<int>::min());
1099 int hiMinIndex(std::numeric_limits<int>::max());
1100 int hiMaxIndex(std::numeric_limits<int>::min());
1103 for(
const auto& hit2D : hitVector)
1111 int hitStart = hit2D->getHit()->PeakTime() - range - 0.5;
1112 int hitStop = hit2D->getHit()->PeakTime() + range + 0.5;
1114 lowMinIndex = std::min(hitStart, lowMinIndex);
1115 lowMaxIndex = std::max(hitStart, lowMaxIndex);
1116 hiMinIndex = std::min(hitStop + 1, hiMinIndex);
1117 hiMaxIndex = std::max(hitStop + 1, hiMaxIndex);
1121 if (hitChiSquare < m_maxHit3DChiSquare && hiMinIndex > lowMaxIndex)
1124 std::vector<float> chargeVec;
1126 for(
const auto& hit2D : hitVector)
1127 chargeVec.push_back(
chargeIntegral(hit2D->getHit()->PeakTime(),hit2D->getHit()->PeakAmplitude(),hit2D->getHit()->RMS(),1.,lowMaxIndex,hiMinIndex));
1129 float totalCharge = std::accumulate(chargeVec.begin(),chargeVec.end(),0.) / float(chargeVec.size());
1130 float overlapRange = float(hiMinIndex - lowMaxIndex);
1131 float overlapFraction = overlapRange / float(hiMaxIndex - lowMinIndex);
1134 std::vector<float> smallestChargeDiffVec;
1135 std::vector<float> chargeAveVec;
1136 float smallestDiff(std::numeric_limits<float>::max());
1137 float maxDeltaPeak(0.);
1138 size_t chargeIndex(0);
1140 for(
size_t idx = 0; idx < 3; idx++)
1142 size_t leftIdx = (idx + 2) % 3;
1143 size_t rightIdx = (idx + 1) % 3;
1145 smallestChargeDiffVec.push_back(
std::abs(chargeVec[leftIdx] - chargeVec[rightIdx]));
1146 chargeAveVec.push_back(
float(0.5 * (chargeVec[leftIdx] + chargeVec[rightIdx])));
1148 if (smallestChargeDiffVec.back() < smallestDiff)
1150 smallestDiff = smallestChargeDiffVec.back();
1155 float deltaPeakTime = hitVector[leftIdx]->getTimeTicks() - hitVector[rightIdx]->getTimeTicks();
1157 if (
std::abs(deltaPeakTime) > maxDeltaPeak) maxDeltaPeak =
std::abs(deltaPeakTime);
1162 float chargeAsymmetry = (chargeAveVec[chargeIndex] - chargeVec[chargeIndex]) / (chargeAveVec[chargeIndex] + chargeVec[chargeIndex]);
1165 if (chargeAsymmetry < -1. || chargeAsymmetry > 1.)
1169 std::cout <<
"============> Charge asymmetry out of range: " << chargeAsymmetry <<
" <============" << std::endl;
1170 std::cout <<
" hit C: " << hitWireID.
Cryostat <<
", TPC: " << hitWireID.
TPC <<
", Plane: " << hitWireID.
Plane <<
", Wire: " << hitWireID.
Wire << std::endl;
1171 std::cout <<
" charge: " << chargeVec[0] <<
", " << chargeVec[1] <<
", " << chargeVec[2] << std::endl;
1172 std::cout <<
" index: " << chargeIndex <<
", smallest diff: " << smallestDiff << std::endl;
1177 float deltaPeakTime = *std::max_element(hitDelTSigVec.begin(),hitDelTSigVec.end());
1193 if (maxDeltaPeak > 3. * overlapRange)
return result;
1226 bool success(
false);
1236 double wirePosArr[3] = {0.,0.,0.};
1239 Eigen::Vector3f wirePos0(wirePosArr[0],wirePosArr[1],wirePosArr[2]);
1249 Eigen::Vector3f wirePos1(wirePosArr[0],wirePosArr[1],wirePosArr[2]);
1260 if (
closestApproach(wirePos0, wireDir0, wirePos1, wireDir1, arcLen0, arcLen1))
1265 Eigen::Vector3f poca0 = wirePos0 + arcLen0 * wireDir0;
1267 widIntersection.
y = poca0[1];
1268 widIntersection.
z = poca0[2];
1278 const Eigen::Vector3f& u0,
1279 const Eigen::Vector3f& P1,
1280 const Eigen::Vector3f& u1,
1282 float& arcLen1)
const
1285 Eigen::Vector3f w0 = P0 - P1;
1287 float b(u0.dot(u1));
1289 float d(u0.dot(w0));
1290 float e(u1.dot(w0));
1291 float den(a * c - b * b);
1293 arcLen0 = (b *
e - c * d) / den;
1294 arcLen1 = (a *
e - b * d) / den;
1296 Eigen::Vector3f poca0 = P0 + arcLen0 * u0;
1297 Eigen::Vector3f poca1 = P1 + arcLen1 * u1;
1299 return (poca0 - poca1).norm();
1311 for(
int sigPos = low; sigPos < hi; sigPos++)
1313 float arg = (float(sigPos) - peakMean + 0.5) / peakSigma;
1314 integral += peakAmp *
std::exp(-0.5 * arg * arg);
1322 size_t maxChanStatus,
1323 size_t minChanStatus,
1324 float minOverlap)
const
1332 size_t missPlane(2);
1357 bool wireOneStatus = m_channelStatus[wireID.
Plane][wireID.
Wire+1] < maxChanStatus && m_channelStatus[wireID.
Plane][wireID.
Wire+1] >= minChanStatus;
1360 if(wireStatus || wireOneStatus)
1363 if (!wireStatus) wireID.
Wire += 1;
1376 newPosition[1] = (newPosition[1] + widIntersect0.
y + widIntersect1.
y) / 3.;
1377 newPosition[2] = (newPosition[2] + widIntersect0.
z + widIntersect1.
z - 2. *
m_zPosOffset) / 3.;
1399 static const float minCharge(0.);
1406 for (
const auto& hit2D : hit2DSet)
1408 if (hit2D->getHit()->Integral() < minCharge)
continue;
1410 float hitVPeakTime(hit2D->getTimeTicks());
1411 float deltaPeakTime(pairAvePeakTime-hitVPeakTime);
1413 if (deltaPeakTime > pairDeltaTimeLimits)
continue;
1415 if (deltaPeakTime < -pairDeltaTimeLimits)
break;
1417 pairDeltaTimeLimits = fabs(deltaPeakTime);
1426 static const float minCharge(0.);
1428 int numberInRange(0);
1432 for (
const auto& hit2D : hit2DSet)
1434 if (hit2D->getHit()->Integral() < minCharge)
continue;
1436 float hitVPeakTime(hit2D->getTimeTicks());
1437 float deltaPeakTime(pairAvePeakTime-hitVPeakTime);
1439 if (deltaPeakTime > range)
continue;
1441 if (deltaPeakTime < -range)
break;
1446 return numberInRange;
1459 wireID.
Wire = int(distanceToWire);
1461 catch(std::exception& exc)
1464 mf::LogWarning(
"Cluster3D") <<
"Exception caught finding nearest wire, position - " << exc.what() << std::endl;
1476 float distance = std::numeric_limits<float>::max();
1485 double wirePosArr[3] = {0.,0.,0.};
1488 Eigen::Vector3f wirePos(wirePosArr[0],wirePosArr[1],wirePosArr[2]);
1497 Eigen::Vector3f hitPosition(wirePos[0],position[1],position[2]);
1500 double arcLen = (hitPosition - wirePos).
dot(wireDir);
1505 Eigen::Vector3f docaVec = hitPosition - (wirePos + arcLen * wireDir);
1507 distance = docaVec.norm();
1510 catch(std::exception& exc)
1513 mf::LogWarning(
"Cluster3D") <<
"Exception caught finding nearest wire, position - " << exc.what() << std::endl;
1543 std::vector<const recob::Hit*> recobHitVec;
1548 art::Handle< std::vector<recob::Hit> > recobHitHandle;
1549 evt.getByLabel(inputTag, recobHitHandle);
1551 if (!recobHitHandle.isValid() || recobHitHandle->size() == 0)
continue;
1553 recobHitVec.reserve(recobHitVec.size() + recobHitHandle->size());
1555 for(
const auto&
hit : *recobHitHandle) recobHitVec.push_back(&
hit);
1559 if (recobHitVec.empty())
return;
1561 cet::cpu_timer theClockMakeHits;
1567 std::map<geo::PlaneID, double> planeOffsetMap;
1570 auto const clock_data = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
1571 auto const det_prop = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clock_data);
1574 std::string debugMessage(
"");
1589 - det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx,tpcIdx,0));
1591 - det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx,tpcIdx,0));
1596 std::ostringstream outputString;
1598 outputString <<
"***> plane 0 offset: " << planeOffsetMap[
geo::PlaneID(cryoIdx,tpcIdx,0)] <<
", plane 1: " << planeOffsetMap[
geo::PlaneID(cryoIdx,tpcIdx,1)] <<
", plane 2: " << planeOffsetMap[
geo::PlaneID(cryoIdx,tpcIdx,2)] <<
"\n";
1599 debugMessage += outputString.str();
1600 outputString <<
" Det prop plane 0: " << det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx,tpcIdx,0)) <<
", plane 1: " << det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx,tpcIdx,1)) <<
", plane 2: " << det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx,tpcIdx,2)) <<
", Trig: " <<
trigger_offset(clock_data) <<
"\n";
1601 debugMessage += outputString.str();
1608 mf::LogDebug(
"Cluster3D") << debugMessage << std::endl;
1617 for (
const auto& recobHit : recobHitVec)
1620 if (recobHit->Integral() < 0.)
continue;
1627 HitStartEndPair hitStartEndPair(recobHit->StartTick(),recobHit->EndTick());
1630 if (hitStartEndPair.second <= hitStartEndPair.first)
1632 std::cout <<
"Yes, found a hit with end time less than start time: " << hitStartEndPair.first <<
"/" << hitStartEndPair.second <<
", mult: " << recobHit->Multiplicity() << std::endl;
1638 for(
auto wireID : wireIDs)
1647 double hitPeakTime(recobHit->PeakTime() - planeOffsetMap[planeID]);
1648 double xPosition(det_prop.ConvertTicksToX(recobHit->PeakTime(), planeID.
Plane, planeID.
TPC, planeID.
Cryostat));
1663 theClockMakeHits.stop();
1675 std::vector<recob::Hit>& hitPtrVec,
1679 cet::cpu_timer theClockBuildNewHits;
1687 std::set<const reco::ClusterHit2D*> visitedHit2DSet;
1690 art::PtrMaker<recob::Hit> ptrMaker(event);
1701 for(
size_t idx = 0; idx < hit3D.getHits().size(); idx++)
1706 if (visitedHit2DSet.find(hit2D) == visitedHit2DSet.end())
1708 visitedHit2DSet.insert(hit2D);
1717 recobHitToPtrMap[newHit] = ptrMaker(hitPtrVec.size()-1);
1725 size_t numNewHits = hitPtrVec.size();
1729 theClockBuildNewHits.stop();
1734 mf::LogDebug(
"Cluster3D") <<
">>>>> New output recob::Hit size: " << numNewHits <<
" (vs " <<
m_clusterHit2DMasterList.size() <<
" input)" << std::endl;
1742 wireAssns = art::Assns<recob::Wire, recob::Hit>();
1746 std::unordered_map<raw::ChannelID_t, art::Ptr<recob::Wire>> channelToWireMap;
1751 art::ValidHandle<std::vector<recob::Hit>> hitHandle = evt.getValidHandle<std::vector<recob::Hit>>(inputTag);
1753 art::FindOneP<recob::Wire> hitToWireAssns(hitHandle, evt, inputTag);
1755 if (hitToWireAssns.isValid())
1757 for(
size_t wireIdx = 0; wireIdx < hitToWireAssns.size(); wireIdx++)
1759 art::Ptr<recob::Wire> wire = hitToWireAssns.at(wireIdx);
1761 channelToWireMap[wire->Channel()] = wire;
1767 for(
const auto& hitPtrPair : recobHitPtrMap)
1771 std::unordered_map<raw::ChannelID_t, art::Ptr<recob::Wire>>::iterator chanWireItr = channelToWireMap.find(channel);
1773 if (!(chanWireItr != channelToWireMap.end()))
1779 wireAssns.addSingle(chanWireItr->second, hitPtrPair.second);
1788 rawDigitAssns = art::Assns<raw::RawDigit, recob::Hit>();
1792 std::unordered_map<raw::ChannelID_t, art::Ptr<raw::RawDigit>> channelToRawDigitMap;
1797 art::ValidHandle<std::vector<recob::Hit>> hitHandle = evt.getValidHandle<std::vector<recob::Hit>>(inputTag);
1799 art::FindOneP<raw::RawDigit> hitToRawDigitAssns(hitHandle, evt, inputTag);
1801 if (hitToRawDigitAssns.isValid())
1803 for(
size_t rawDigitIdx = 0; rawDigitIdx < hitToRawDigitAssns.size(); rawDigitIdx++)
1805 art::Ptr<raw::RawDigit> rawDigit = hitToRawDigitAssns.at(rawDigitIdx);
1807 channelToRawDigitMap[rawDigit->Channel()] = rawDigit;
1813 for(
const auto& hitPtrPair : recobHitPtrMap)
1817 std::unordered_map<raw::ChannelID_t, art::Ptr<raw::RawDigit>>::iterator chanRawDigitItr = channelToRawDigitMap.find(channel);
1819 if (chanRawDigitItr == channelToRawDigitMap.end())
1825 rawDigitAssns.addSingle(chanRawDigitItr->second, hitPtrPair.second);
TTree * m_tupleTree
output analysis tree
void initialize(size_t id, unsigned int statusBits, const Eigen::Vector3f &position, float totalCharge, float avePeakTime, float deltaPeakTime, float sigmaPeakTime, float hitChiSquare, float overlapFraction, float chargeAsymmetry, float docaToAxis, float arclenToPoca, const ClusterHit2DVec &hitVec, const std::vector< float > &hitDelTSigVec, const std::vector< geo::WireID > &wireIDVec)
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
PlaneToSnippetHitMap m_planeToSnippetHitMap
void clear()
clear the tuple vectors before processing next event
std::vector< int > m_invalidTPCVec
std::vector< float > m_overlapRangeVec
void setWireID(const geo::WireID &wid) const
double z
z position of intersection
std::list< reco::ClusterHit3D > HitPairList
void BuildChannelStatusVec(PlaneToWireToHitSetMap &planeToWiretoHitSetMap) const
Create the internal channel status vector (assume will eventually be event-by-event) ...
bool m_weHaveAllBeenHereBefore
constexpr auto dot(Vector const &a, Vector const &b)
Return cross product of two vectors.
PlaneGeo const & Plane(unsigned int const p, unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified wire.
float getTimeTicks() const
SnippetHit3DBuilder class definiton.
bool makeHitPair(reco::ClusterHit3D &pairOut, const reco::ClusterHit2D *hit1, const reco::ClusterHit2D *hit2, float hitWidthSclFctr=1., size_t hitPairCntr=0) const
Make a HitPair object by checking two hits.
std::vector< ChannelStatusVec > ChannelStatusByPlaneVec
std::vector< float > m_hitAsymmetryVec
int FindNumberInRange(const Hit2DSet &hit2DSet, const reco::ClusterHit3D &pair, float range) const
A utility routine for returning the number of 2D hits from the list in a given range.
void CreateNewRecobHitCollection(art::Event &, reco::HitPairList &, std::vector< recob::Hit > &, RecobHitToPtrMap &)
Create a new 2D hit collection from hits associated to 3D space points.
std::vector< float > m_smallChargeDiffVec
void findGoodTriplets(HitMatchTripletVecMap &, HitMatchTripletVecMap &, reco::HitPairList &, bool=false) const
This algorithm takes lists of hit pairs and finds good triplets.
const Eigen::Vector3f getPosition() const
bool SetHitTimeOrder(const reco::ClusterHit2D *left, const reco::ClusterHit2D *right)
const lariov::ChannelStatusProvider * m_channelFilter
float RMS() const
RMS of the hit shape, in tick units.
Declaration of signal hit object.
std::vector< size_t > ChannelStatusVec
define data structure for keeping track of channel status
The data type to uniquely identify a Plane.
const geo::WireID & WireID() const
const geo::Geometry * m_geometry
bool operator()(const reco::ClusterHit2D *, const reco::ClusterHit2D *) const
bool makeHitTriplet(reco::ClusterHit3D &pairOut, const reco::ClusterHit3D &pairIn, const reco::ClusterHit2D *hit2) const
Make a 3D HitPair object by checking two hits.
std::vector< float > m_chiSquare3DVec
void BuildHit3D(reco::HitPairList &hitPairList) const
Given the ClusterHit2D objects, build the HitPairMap.
virtual float getTimeToExecute(IHit3DBuilder::TimeValues index) const override
If monitoring, recover the time to execute a particular function.
size_t BuildHitPairMapByTPC(PlaneSnippetHitMapItrPairVec &planeSnippetHitMapItrPairVec, reco::HitPairList &hitPairList) const
Given the ClusterHit2D objects, build the HitPairMap.
int DegreesOfFreedom() const
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
CryostatID_t Cryostat
Index of cryostat.
SnippetHit3DBuilder(fhicl::ParameterSet const &pset)
Constructor.
std::vector< float > m_timeVector
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
WireID_t Wire
Index of the wire within its plane.
float getSigmaPeakTime() const
float DistanceFromPointToHitWire(const Eigen::Vector3f &position, const geo::WireID &wireID) const
Jacket the calls to finding the nearest wire in order to intercept the exceptions if out of range...
std::map< geo::PlaneID, WireToHitSetMap > PlaneToWireToHitSetMap
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
float m_wirePitchScaleFactor
Scaling factor to determine max distance allowed between candidate pairs.
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.
float m_maxHit3DChiSquare
Provide ability to select hits based on "chi square".
bool SetPeakHitPairIteratorOrder(const reco::HitPairList::iterator &left, const reco::HitPairList::iterator &right)
std::vector< float > m_maxPullVec
standard_dbscan3dalg useful for diagnostics hits not in a line will not be clustered on on only for track like only for track like on on the smaller the less shower like tracks low
std::tuple< const reco::ClusterHit2D *, const reco::ClusterHit2D *, const reco::ClusterHit3D > HitMatchTriplet
This builds a list of candidate hit pairs from lists of hits on two planes.
const recob::Hit * getHit() const
unsigned int Nchannels() const
Returns the number of TPC readout channels in the detector.
float PeakAmplitude() const
The estimated amplitude of the hit at its peak, in ADC units.
IDparameter< geo::PlaneID > PlaneID
Member type of validated geo::PlaneID parameter.
std::vector< SnippetHitMapItrPair > PlaneSnippetHitMapItrPairVec
unsigned short Status_t
type representing channel status
float getAvePeakTime() const
std::map< size_t, HitVector > HitVectorMap
Class managing the creation of a new recob::Hit object.
int findGoodHitPairs(SnippetHitMap::iterator &, SnippetHitMap::iterator &, SnippetHitMap::iterator &, HitMatchTripletVecMap &) const
Helper functions to create a hit.
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
std::list< reco::ClusterHit2D > Hit2DList
std::vector< float > m_pairWireDistVec
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
std::vector< float > m_maxSideVecVec
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
std::vector< float > m_maxDeltaPeakVec
virtual void configure(const fhicl::ParameterSet &) override
Interface for configuring the particular algorithm tool.
std::vector< HitMatchTriplet > HitMatchTripletVec
void makeWireAssns(const art::Event &, art::Assns< recob::Wire, recob::Hit > &, RecobHitToPtrMap &) const
Create recob::Wire to recob::Hit associations.
virtual Status_t Status(raw::ChannelID_t channel) const
Returns a status integer with arbitrary meaning.
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
virtual bool IsGood(raw::ChannelID_t channel) const
Returns whether the specified channel is physical and good.
float getXPosition() const
TimeValues
enumerate the possible values for time checking if monitoring timing
void makeRawDigitAssns(const art::Event &, art::Assns< raw::RawDigit, recob::Hit > &, RecobHitToPtrMap &) const
Create raw::RawDigit to recob::Hit associations.
Class providing information about the quality of channels.
PlaneToWireToHitSetMap m_planeToWireToHitSetMap
The geometry of one entire detector, as served by art.
PlaneID_t Plane
Index of the plane within its TPC.
std::vector< float > m_overlapFractionVec
std::vector< float > m_spacePointChargeVec
IHit3DBuilder interface class definiton.
std::vector< int > m_smallIndexVec
std::vector< art::InputTag > m_hitFinderTagVec
Data members to follow.
This provides an art tool interface definition for tools which construct 3D hits used in 3D clusterin...
std::vector< const reco::ClusterHit2D * > ClusterHit2DVec
std::set< const reco::ClusterHit2D *, Hit2DSetCompare > Hit2DSet
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
std::map< geo::TPCID, PlaneToWireToHitSetMap > TPCToPlaneToWireToHitSetMap
std::vector< const reco::ClusterHit2D * > HitVector
double HalfL() const
Returns half the length of the wire [cm].
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, geo::Point_t &intersection) const
Computes the intersection between two wires.
size_t BuildHitPairMap(PlaneToSnippetHitMap &planeToHitVectorMap, reco::HitPairList &hitPairList) const
Given the ClusterHit2D objects, build the HitPairMap.
geo::WireID NearestWireID(const Eigen::Vector3f &position, const geo::WireID &wireID) const
Jacket the calls to finding the nearest wire in order to intercept the exceptions if out of range...
bool operator()(const reco::HitPairClusterMap::iterator &left, const reco::HitPairClusterMap::iterator &right)
float PeakTime() const
Time of the signal peak, in tick units.
bool operator()(const SnippetHitMapItrPair &left, const SnippetHitMapItrPair &right) const
void setID(const size_t &id) const
virtual void produces(art::ProducesCollector &) override
Each algorithm may have different objects it wants "produced" so use this to let the top level produc...
bool makeDeadChannelPair(reco::ClusterHit3D &pairOut, const reco::ClusterHit3D &pair, size_t maxStatus=4, size_t minStatus=0, float minOverlap=0.2) const
Make a 3D HitPair object from a valid pair and a dead channel in the missing plane.
std::map< geo::PlaneID, SnippetHitMap > PlaneToSnippetHitMap
bool WireIDsIntersect(const geo::WireID &, const geo::WireID &, geo::WireIDIntersection &) const
function to detemine if two wires "intersect" (in the 2D sense)
void CollectArtHits(const art::Event &evt) const
Extract the ART hits and the ART hit-particle relationships.
double y
y position of intersection
std::map< geo::TPCID, PlaneToSnippetHitMap > TPCToPlaneToSnippetHitMap
ChannelStatusByPlaneVec m_channelStatus
Interface for experiment-specific channel quality info provider.
std::pair< SnippetHitMap::iterator, SnippetHitMap::iterator > SnippetHitMapItrPair
int trigger_offset(DetectorClocksData const &data)
float getDeltaPeakTime() const
std::map< geo::WireID, HitMatchTripletVec > HitMatchTripletVecMap
constexpr WireID()=default
Default constructor: an invalid TPC ID.
std::pair< raw::TDCtick_t, raw::TDCtick_t > HitStartEndPair
std::vector< float > m_deltaTimeVec
virtual void Hit3DBuilder(art::Event &, reco::HitPairList &, RecobHitToPtrMap &) override
Given a set of recob hits, run DBscan to form 3D clusters.
2D representation of charge deposited in the TDC/wire plane
art::ServiceHandle< art::TFileService > tfs
void GetCenter(double *xyz, double localz=0.0) const
Fills the world coordinate of a point on the wire.
double WireCoordinate(Point const &point) const
Returns the coordinate of the point on the plane, in wire units.
std::map< HitStartEndPair, HitVector > SnippetHitMap
unsigned int ChannelID_t
Type representing the ID of a readout channel.
TPCID_t TPC
Index of the TPC within its cryostat.
Interface for experiment-specific service for channel quality info.
process_name physics producers generator hPHist_pi physics producers generator P0
float m_LongHitStretchFctr
float closestApproach(const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, const Eigen::Vector3f &, float &, float &) const
function to compute the distance of closest approach and the arc length to the points of closest appr...
bool m_outputHistograms
Take the time to create and fill some histograms for diagnostics.
std::vector< float > m_qualityMetricVec
const ClusterHit2DVec & getHits() const
std::unordered_map< const recob::Hit *, art::Ptr< recob::Hit >> RecobHitToPtrMap
Defines a structure mapping art representation to internal.
void setPosition(const Eigen::Vector3f &pos) const
bool SetPairStartTimeOrder(const reco::ClusterHit3D &left, const reco::ClusterHit3D &right)
const reco::ClusterHit2D * FindBestMatchingHit(const Hit2DSet &hit2DSet, const reco::ClusterHit3D &pair, float pairDeltaTimeLimits) const
A utility routine for finding a 2D hit closest in time to the given pair.
Hit2DList m_clusterHit2DMasterList
art framework interface to geometry description
BEGIN_PROLOG could also be cout
std::map< unsigned int, Hit2DSet > WireToHitSetMap
WireGeo const & WireIDToWireGeo(geo::WireID const &wireid) const
unsigned getStatusBits() const
void setStatusBit(unsigned bits) const
float chargeIntegral(float, float, float, float, int, int) const
Perform charge integration between limits.