9 #include "art/Framework/Core/EDProducer.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"
50 namespace lar_cluster3d {
58 struct Hit2DSetCompare {
62 using HitVector = std::vector<const reco::ClusterHit2D*>;
65 using Hit2DList = std::list<reco::ClusterHit2D>;
66 using Hit2DSet = std::set<const reco::ClusterHit2D*, Hit2DSetCompare>;
90 void produces(art::ProducesCollector&)
override;
92 void configure(
const fhicl::ParameterSet&)
override;
129 std::vector<recob::Hit>&,
136 art::Assns<recob::Wire, recob::Hit>&,
143 art::Assns<raw::RawDigit, recob::Hit>&,
156 std::vector<std::pair<HitVector::iterator, HitVector::iterator>>;
164 using HitMatchPair = std::pair<const reco::ClusterHit2D*, reco::ClusterHit3D>;
169 HitVector::iterator&,
170 HitVector::iterator&,
187 float hitWidthSclFctr = 1.,
188 size_t hitPairCntr = 0)
const;
202 size_t maxStatus = 4,
203 size_t minStatus = 0,
204 float minOverlap = 0.2)
const;
211 float pairDeltaTimeLimits)
const;
303 : m_geometry(art::ServiceHandle<geo::Geometry
const>{}.get())
304 , m_channelFilter(&art::ServiceHandle<lariov::ChannelStatusService const>()->GetProvider())
306 this->configure(pset);
314 collector.produces<std::vector<recob::Hit>>();
315 collector.produces<art::Assns<recob::Wire, recob::Hit>>();
316 collector.produces<art::Assns<raw::RawDigit, recob::Hit>>();
325 "HitFinderTagVec", std::vector<art::InputTag>() = {
"gaushit"});
331 m_invalidTPCVec = pset.get<std::vector<int>>(
"InvalidTPCVec", std::vector<int>());
336 m_geometry = art::ServiceHandle<geo::Geometry const>{}.get();
345 art::ServiceHandle<art::TFileService>
tfs;
348 m_tupleTree = tfs->make<TTree>(
"Hit3DBuilderTree",
"Tree by StandardHit3DBuilder");
437 const reco::HitPairList::iterator&
right)
439 return (*left).getAvePeakTime() < (*right).getAvePeakTime();
442 struct HitPairClusterOrder {
445 const reco::HitPairClusterMap::iterator& right)
448 if (left->second.size() == right->second.size())
return left->first < right->first;
450 return left->second.size() > right->second.size();
467 std::unique_ptr<std::vector<recob::Hit>> outputHitPtrVec(
new std::vector<recob::Hit>);
479 if (!hitPairList.empty())
485 std::unique_ptr<art::Assns<recob::Wire, recob::Hit>> wireAssns(
486 new art::Assns<recob::Wire, recob::Hit>);
491 std::unique_ptr<art::Assns<raw::RawDigit, recob::Hit>> rawDigitAssns(
492 new art::Assns<raw::RawDigit, recob::Hit>);
497 evt.put(std::move(outputHitPtrVec));
498 evt.put(std::move(wireAssns));
499 evt.put(std::move(rawDigitAssns));
518 cet::cpu_timer theClockMakeHits;
529 theClockMakeHits.stop();
534 mf::LogDebug(
"Cluster3D") <<
">>>>> 3D hit building done, found " << numHitPairs <<
" 3D Hits"
543 class SetHitEarliestTimeOrder {
545 SetHitEarliestTimeOrder() :
m_numRMS(1.) {}
546 SetHitEarliestTimeOrder(
float numRMS) :
m_numRMS(numRMS) {}
559 using HitVectorItrPair = std::pair<HitVector::iterator, HitVector::iterator>;
561 class SetStartTimeOrder {
567 operator()(
const HitVectorItrPair& left,
const HitVectorItrPair& right)
const
570 if (left.first != left.second && right.first != right.second) {
572 return (*left.first)->getTimeTicks() -
m_numRMS * (*left.first)->getHit()->RMS() <
573 (*right.first)->getTimeTicks() -
m_numRMS * (*right.first)->getHit()->RMS();
576 return left.first != left.second;
607 size_t totalNumHits(0);
608 size_t hitPairCntr(0);
611 size_t nDeadChanHits(0);
616 PlaneToHitVectorMap::iterator mapItr0 =
617 planeToHitVectorMap.find(
geo::PlaneID(cryoIdx, tpcIdx, 0));
618 PlaneToHitVectorMap::iterator mapItr1 =
619 planeToHitVectorMap.find(
geo::PlaneID(cryoIdx, tpcIdx, 1));
620 PlaneToHitVectorMap::iterator mapItr2 =
621 planeToHitVectorMap.find(
geo::PlaneID(cryoIdx, tpcIdx, 2));
623 size_t nPlanesWithHits =
624 (mapItr0 != planeToHitVectorMap.end() && !mapItr0->second.empty() ? 1 : 0) +
625 (mapItr1 != planeToHitVectorMap.end() && !mapItr1->second.empty() ? 1 : 0) +
626 (mapItr2 != planeToHitVectorMap.end() && !mapItr2->second.empty() ? 1 : 0);
628 if (nPlanesWithHits < 2)
continue;
635 std::sort(hitVector0.begin(),
638 std::sort(hitVector1.begin(),
641 std::sort(hitVector2.begin(),
646 HitVectorItrPair(hitVector0.begin(), hitVector0.end()),
647 HitVectorItrPair(hitVector1.begin(), hitVector1.end()),
648 HitVectorItrPair(hitVector2.begin(), hitVector2.end())};
658 mf::LogDebug(
"Cluster3D") <<
"Total number hits: " << totalNumHits << std::endl;
659 mf::LogDebug(
"Cluster3D") <<
"Created a total of " << hitPairList.size()
660 <<
" hit pairs, counted: " << hitPairCntr << std::endl;
661 mf::LogDebug(
"Cluster3D") <<
"-- Triplets: " << nTriplets
662 <<
", dead channel pairs: " << nDeadChanHits << std::endl;
664 return hitPairList.size();
682 auto SetStartIterator =
683 [](HitVector::iterator startItr, HitVector::iterator endItr,
float rms,
float startTime) {
684 while (startItr != endItr) {
686 if ((*startItr)->getTimeTicks() + numRMS * (*startItr)->getHit()->RMS() < startTime)
694 auto SetEndIterator =
695 [](HitVector::iterator firstItr, HitVector::iterator endItr,
float rms,
float endTime) {
696 while (firstItr != endItr) {
698 if ((*firstItr)->getTimeTicks() - numRMS * (*firstItr)->getHit()->RMS() < endTime)
707 size_t nDeadChanHits(0);
721 std::numeric_limits<float>::epsilon();
722 float goldenTimeEnd = goldenHit->getTimeTicks() +
724 std::numeric_limits<float>::epsilon();
727 HitVector::iterator hitItr1Start = SetStartIterator(
729 HitVector::iterator hitItr1End =
731 HitVector::iterator hitItr2Start = SetStartIterator(
733 HitVector::iterator hitItr2End =
737 size_t curHitListSize(hitPairList.size());
741 size_t n12Pairs =
findGoodHitPairs(goldenHit, hitItr1Start, hitItr1End, pair12Map);
742 size_t n13Pairs =
findGoodHitPairs(goldenHit, hitItr2Start, hitItr2End, pair13Map);
744 nDeadChanHits += hitPairList.size() - curHitListSize;
745 curHitListSize = hitPairList.size();
747 if (n12Pairs > n13Pairs)
752 nTriplets += hitPairList.size() - curHitListSize;
754 hitItrVec[0].first++;
756 int nPlanesWithHits(0);
758 for (
auto& pair : hitItrVec)
759 if (pair.first != pair.second) nPlanesWithHits++;
761 if (nPlanesWithHits < 2)
break;
764 return hitPairList.size();
769 HitVector::iterator& startItr,
770 HitVector::iterator& endItr,
776 while (startItr != endItr) {
785 hitMatchMap[wireID].emplace_back(hit, pair);
800 if (!pair12Map.empty()) {
802 std::vector<reco::ClusterHit3D> tempDeadChanVec;
806 std::map<const reco::ClusterHit3D*, bool> usedPairMap;
809 for (
const auto& pair13 : pair13Map) {
810 for (
const auto& hit2Dhit3DPair : pair13.second)
811 usedPairMap[&hit2Dhit3DPair.second] =
false;
815 for (
const auto& pair12 : pair12Map) {
816 if (pair12.second.empty())
continue;
820 for (
const auto& hit2Dhit3DPair12 : pair12.second) {
824 usedPairMap[&pair1] =
false;
827 for (
const auto& pair13 : pair13Map) {
828 if (pair13.second.empty())
continue;
830 for (
const auto& hit2Dhit3DPair13 : pair13.second) {
838 triplet.
setID(hitPairList.size());
839 hitPairList.emplace_back(triplet);
840 usedPairMap[&pair1] =
true;
841 usedPairMap[&pair2] =
true;
850 for (
const auto& pairMapPair : usedPairMap) {
851 if (pairMapPair.second)
continue;
857 tempDeadChanVec.emplace_back(deadChanPair);
861 if (!tempDeadChanVec.empty()) {
863 if (tempDeadChanVec.size() > 1) {
865 std::sort(tempDeadChanVec.begin(),
866 tempDeadChanVec.end(),
867 [](
const auto&
left,
const auto&
right) {
873 float firstSig = tempDeadChanVec.front().getDeltaPeakTime() /
874 tempDeadChanVec.front().getSigmaPeakTime();
876 tempDeadChanVec.back().getDeltaPeakTime() / tempDeadChanVec.back().getSigmaPeakTime();
877 float sigRange = lastSig - firstSig;
881 float maxSignificance = std::max(0.75 * (firstSig + lastSig), 1.0);
883 std::vector<reco::ClusterHit3D>::iterator firstBadElem = std::find_if(
884 tempDeadChanVec.begin(),
885 tempDeadChanVec.end(),
886 [&maxSignificance](
const auto& pair) {
887 return pair.getDeltaPeakTime() / pair.getSigmaPeakTime() > maxSignificance;
891 if (
std::distance(tempDeadChanVec.begin(), firstBadElem) > 20)
892 firstBadElem = tempDeadChanVec.begin() + 20;
894 else if (firstBadElem == tempDeadChanVec.begin())
897 tempDeadChanVec.resize(
std::distance(tempDeadChanVec.begin(), firstBadElem));
901 for (
auto& pair : tempDeadChanVec) {
902 pair.setID(hitPairList.size());
903 hitPairList.emplace_back(pair);
916 float hitWidthSclFctr,
917 size_t hitPairCntr)
const
950 float hit1Width = hitWidthSclFctr * hit1Sigma;
951 float hit2Width = hitWidthSclFctr * hit2Sigma;
954 if (fabs(hit1Peak - hit2Peak) <= (hit1Width + hit2Width)) {
956 float hit1SigSq = hit1Sigma * hit1Sigma;
957 float hit2SigSq = hit2Sigma * hit2Sigma;
958 float deltaPeakTime = std::fabs(hit1Peak - hit2Peak);
959 float sigmaPeakTime = std::sqrt(hit1SigSq + hit2SigSq);
965 float oneOverWghts = hit1SigSq * hit2SigSq / (hit1SigSq + hit2SigSq);
966 float avePeakTime = (hit1Peak / hit1SigSq + hit2Peak / hit2SigSq) * oneOverWghts;
968 float hitChiSquare = std::pow((hit1Peak - avePeakTime), 2) / hit1SigSq +
969 std::pow((hit2Peak - avePeakTime), 2) / hit2SigSq;
973 float xPosition = (xPositionHit1 / hit1SigSq + xPositionHit2 / hit2SigSq) * hit1SigSq *
974 hit2SigSq / (hit1SigSq + hit2SigSq);
976 Eigen::Vector3f position(
977 xPosition,
float(widIntersect.
y),
float(widIntersect.
z) -
m_zPosOffset);
993 hitVector.resize(3, NULL);
999 unsigned int tpcIdx = hit1->
WireID().
TPC;
1002 std::vector<geo::WireID> wireIDVec = {
geo::WireID(cryostatIdx, tpcIdx, 0, 0),
1010 std::vector<float> hitDelTSigVec = {0., 0., 0.};
1012 hitDelTSigVec[hit1->
WireID().
Plane] = deltaPeakTime / sigmaPeakTime;
1013 hitDelTSigVec[hit2->
WireID().
Plane] = deltaPeakTime / sigmaPeakTime;
1050 static const double wirePitch =
1071 if (hitWireDist < wirePitch) {
1084 hit0 = pairHitVec[2];
1086 hit1 = pairHitVec[2];
1098 unsigned int statusBits(0x7);
1099 float avePeakTime(0.);
1100 float weightSum(0.);
1101 float xPosition(0.);
1107 for (
size_t planeIdx = 0; planeIdx < 3; planeIdx++) {
1110 wireIDVec[planeIdx] = hit2D->
WireID();
1125 float weight = 1. / (hitRMS * hitRMS);
1127 avePeakTime += peakTime * weight;
1129 weightSum += weight;
1132 avePeakTime /= weightSum;
1133 xPosition /= weightSum;
1138 Eigen::Vector3f position(xPosition,
1139 float((pairYZVec[0] + pair0hYZVec[0] + pair1hYZVec[0]) / 3.),
1140 float((pairYZVec[1] + pair0hYZVec[1] + pair1hYZVec[1]) / 3.));
1143 float hitChiSquare(0.);
1144 float sigmaPeakTime(std::sqrt(1. / weightSum));
1145 std::vector<float> hitDelTSigVec;
1147 for (
const auto& hit2D : hitVector) {
1148 float hitRMS = hit2D->getHit()->RMS();
1151 if (hit2D->getHit()->DegreesOfFreedom() < 2)
1152 hitRMS = std::min(hit2D->getTimeTicks() - float(hit2D->getHit()->StartTick()),
1153 float(hit2D->getHit()->EndTick()) - hit2D->getTimeTicks());
1155 float combRMS = std::sqrt(hitRMS * hitRMS - sigmaPeakTime * sigmaPeakTime);
1156 float peakTime = hit2D->getTimeTicks();
1157 float deltaTime = peakTime - avePeakTime;
1158 float hitSig = deltaTime / combRMS;
1160 hitChiSquare += hitSig * hitSig;
1162 hitDelTSigVec.emplace_back(std::fabs(hitSig));
1167 int lowMinIndex(std::numeric_limits<int>::max());
1168 int lowMaxIndex(std::numeric_limits<int>::min());
1169 int hiMinIndex(std::numeric_limits<int>::max());
1170 int hiMaxIndex(std::numeric_limits<int>::min());
1173 for (
const auto& hit2D : hitVector) {
1174 float range = 2. * hit2D->getHit()->RMS();
1177 if (hit2D->getHit()->DegreesOfFreedom() < 2)
1178 range = std::min(hit2D->getTimeTicks() - float(hit2D->getHit()->StartTick()),
1179 float(hit2D->getHit()->EndTick()) - hit2D->getTimeTicks());
1181 int hitStart = hit2D->getHit()->PeakTime() - range - 0.5;
1182 int hitStop = hit2D->getHit()->PeakTime() + range + 0.5;
1184 lowMinIndex = std::min(hitStart, lowMinIndex);
1185 lowMaxIndex = std::max(hitStart, lowMaxIndex);
1186 hiMinIndex = std::min(hitStop + 1, hiMinIndex);
1187 hiMaxIndex = std::max(hitStop + 1, hiMaxIndex);
1191 if (hitChiSquare < m_maxHit3DChiSquare && hiMinIndex > lowMaxIndex) {
1193 std::vector<float> chargeVec;
1195 for (
const auto& hit2D : hitVector)
1197 hit2D->getHit()->PeakAmplitude(),
1198 hit2D->getHit()->RMS(),
1204 std::accumulate(chargeVec.begin(), chargeVec.end(), 0.) / float(chargeVec.size());
1205 float overlapRange = float(hiMinIndex - lowMaxIndex);
1206 float overlapFraction = overlapRange / float(hiMaxIndex - lowMinIndex);
1209 std::vector<float> smallestChargeDiffVec;
1210 std::vector<float> chargeAveVec;
1211 float smallestDiff(std::numeric_limits<float>::max());
1212 float maxDeltaPeak(0.);
1213 size_t chargeIndex(0);
1215 for (
size_t idx = 0; idx < 3; idx++) {
1216 size_t leftIdx = (idx + 2) % 3;
1217 size_t rightIdx = (idx + 1) % 3;
1219 smallestChargeDiffVec.push_back(
std::abs(chargeVec[leftIdx] - chargeVec[rightIdx]));
1220 chargeAveVec.push_back(
float(0.5 * (chargeVec[leftIdx] + chargeVec[rightIdx])));
1222 if (smallestChargeDiffVec.back() < smallestDiff) {
1223 smallestDiff = smallestChargeDiffVec.back();
1228 float deltaPeakTime =
1229 hitVector[leftIdx]->getTimeTicks() - hitVector[rightIdx]->getTimeTicks();
1231 if (
std::abs(deltaPeakTime) > maxDeltaPeak) maxDeltaPeak =
std::abs(deltaPeakTime);
1236 float chargeAsymmetry = (chargeAveVec[chargeIndex] - chargeVec[chargeIndex]) /
1237 (chargeAveVec[chargeIndex] + chargeVec[chargeIndex]);
1240 if (chargeAsymmetry < -1. || chargeAsymmetry > 1.) {
1243 std::cout <<
"============> Charge asymmetry out of range: " << chargeAsymmetry
1244 <<
" <============" << std::endl;
1246 <<
", Plane: " << hitWireID.
Plane <<
", Wire: " << hitWireID.
Wire
1248 std::cout <<
" charge: " << chargeVec[0] <<
", " << chargeVec[1] <<
", "
1249 << chargeVec[2] << std::endl;
1250 std::cout <<
" index: " << chargeIndex <<
", smallest diff: " << smallestDiff
1256 float deltaPeakTime = *std::max_element(hitDelTSigVec.begin(), hitDelTSigVec.end());
1271 if (maxDeltaPeak > overlapRange)
return result;
1310 for (
int sigPos = low; sigPos < hi; sigPos++) {
1311 float arg = (float(sigPos) - peakMean + 0.5) / peakSigma;
1312 integral += peakAmp *
std::exp(-0.5 * arg * arg);
1321 size_t maxChanStatus,
1322 size_t minChanStatus,
1323 float minOverlap)
const
1331 size_t missPlane(2);
1355 bool wireOneStatus = m_channelStatus[wireID.
Plane][wireID.
Wire + 1] < maxChanStatus &&
1356 m_channelStatus[wireID.
Plane][wireID.
Wire + 1] >= minChanStatus;
1359 if (wireStatus || wireOneStatus) {
1361 if (!wireStatus) wireID.
Wire += 1;
1370 Eigen::Vector3f newPosition(
1373 newPosition[1] = (newPosition[1] + widIntersect0.
y + widIntersect1.
y) / 3.;
1375 (newPosition[2] + widIntersect0.
z + widIntersect1.
z - 2. *
m_zPosOffset) / 3.;
1400 float pairDeltaTimeLimits)
const
1402 static const float minCharge(0.);
1409 for (
const auto& hit2D : hit2DSet) {
1410 if (hit2D->getHit()->Integral() < minCharge)
continue;
1412 float hitVPeakTime(hit2D->getTimeTicks());
1413 float deltaPeakTime(pairAvePeakTime - hitVPeakTime);
1415 if (deltaPeakTime > pairDeltaTimeLimits)
continue;
1417 if (deltaPeakTime < -pairDeltaTimeLimits)
break;
1419 pairDeltaTimeLimits = fabs(deltaPeakTime);
1431 static const float minCharge(0.);
1433 int numberInRange(0);
1437 for (
const auto& hit2D : hit2DSet) {
1438 if (hit2D->getHit()->Integral() < minCharge)
continue;
1440 float hitVPeakTime(hit2D->getTimeTicks());
1441 float deltaPeakTime(pairAvePeakTime - hitVPeakTime);
1443 if (deltaPeakTime > range)
continue;
1445 if (deltaPeakTime < -range)
break;
1450 return numberInRange;
1464 wireID.
Wire = int(distanceToWire);
1466 catch (std::exception& exc) {
1468 mf::LogWarning(
"Cluster3D") <<
"Exception caught finding nearest wire, position - "
1469 << exc.what() << std::endl;
1490 Eigen::Vector3d wireStart;
1491 Eigen::Vector3d wireEnd;
1496 Eigen::Vector3d hitPosition(wireStart[0], position[1], position[2]);
1499 Eigen::Vector3d wireDir = wireEnd - wireStart;
1501 wireDir.normalize();
1504 double arcLen = (hitPosition - wireStart).
dot(wireDir);
1506 Eigen::Vector3d docaVec = hitPosition - (wireStart + arcLen * wireDir);
1508 distance = docaVec.norm();
1510 catch (std::exception& exc) {
1512 mf::LogWarning(
"Cluster3D") <<
"Exception caught finding nearest wire, position - "
1513 << exc.what() << std::endl;
1546 std::vector<const recob::Hit*> recobHitVec;
1548 auto const clock_data =
1549 art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
1550 auto const det_prop =
1551 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clock_data);
1555 art::Handle<std::vector<recob::Hit>> recobHitHandle;
1556 evt.getByLabel(inputTag, recobHitHandle);
1558 if (!recobHitHandle.isValid() || recobHitHandle->size() == 0)
continue;
1560 recobHitVec.reserve(recobHitVec.size() + recobHitHandle->size());
1562 for (
const auto&
hit : *recobHitHandle)
1563 recobHitVec.push_back(&
hit);
1567 if (recobHitVec.empty())
return;
1569 cet::cpu_timer theClockMakeHits;
1575 std::map<geo::PlaneID, double> planeOffsetMap;
1578 std::string debugMessage(
"");
1591 det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 1)) -
1592 det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 0));
1594 det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 2)) -
1595 det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 0));
1599 std::ostringstream outputString;
1601 outputString <<
"***> plane 0 offset: "
1603 <<
", plane 1: " << planeOffsetMap[
geo::PlaneID(cryoIdx, tpcIdx, 1)]
1604 <<
", plane 2: " << planeOffsetMap[
geo::PlaneID(cryoIdx, tpcIdx, 2)]
1606 debugMessage += outputString.str();
1607 outputString <<
" Det prop plane 0: "
1608 << det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 0))
1610 << det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 1))
1612 << det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 2))
1614 debugMessage += outputString.str();
1620 mf::LogDebug(
"Cluster3D") << debugMessage << std::endl;
1627 for (
const auto& recobHit : recobHitVec) {
1629 if (recobHit->Integral() < 0.)
continue;
1636 for (
const auto& wireID : wireIDs) {
1646 double hitPeakTime(recobHit->PeakTime() - planeOffsetMap[planeID]);
1647 double xPosition(det_prop.ConvertTicksToX(
1659 std::sort(hitVectorMap.second.begin(), hitVectorMap.second.end(),
SetHitTimeOrder);
1662 theClockMakeHits.stop();
1676 std::vector<recob::Hit>& hitPtrVec,
1680 cet::cpu_timer theClockBuildNewHits;
1688 std::set<const reco::ClusterHit2D*> visitedHit2DSet;
1691 art::PtrMaker<recob::Hit> ptrMaker(event);
1701 for (
size_t idx = 0; idx < hit3D.getHits().size(); idx++) {
1705 if (visitedHit2DSet.find(hit2D) == visitedHit2DSet.end()) {
1706 visitedHit2DSet.insert(hit2D);
1709 hitPtrVec.emplace_back(
1716 recobHitToPtrMap[newHit] = ptrMaker(hitPtrVec.size() - 1);
1724 size_t numNewHits = hitPtrVec.size();
1727 theClockBuildNewHits.stop();
1732 mf::LogDebug(
"Cluster3D") <<
">>>>> New output recob::Hit size: " << numNewHits <<
" (vs "
1740 art::Assns<recob::Wire, recob::Hit>& wireAssns,
1744 wireAssns = art::Assns<recob::Wire, recob::Hit>();
1748 std::unordered_map<raw::ChannelID_t, art::Ptr<recob::Wire>> channelToWireMap;
1752 art::ValidHandle<std::vector<recob::Hit>> hitHandle =
1753 evt.getValidHandle<std::vector<recob::Hit>>(inputTag);
1755 art::FindOneP<recob::Wire> hitToWireAssns(hitHandle, evt, inputTag);
1757 if (hitToWireAssns.isValid()) {
1758 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) {
1770 std::unordered_map<raw::ChannelID_t, art::Ptr<recob::Wire>>::iterator chanWireItr =
1771 channelToWireMap.find(channel);
1773 if (!(chanWireItr != channelToWireMap.end())) {
1774 mf::LogDebug(
"Cluster3D") <<
"** Did not find channel to wire match! Skipping..."
1779 wireAssns.addSingle(chanWireItr->second, hitPtrPair.second);
1787 art::Assns<raw::RawDigit, recob::Hit>& rawDigitAssns,
1791 rawDigitAssns = art::Assns<raw::RawDigit, recob::Hit>();
1795 std::unordered_map<raw::ChannelID_t, art::Ptr<raw::RawDigit>> channelToRawDigitMap;
1799 art::ValidHandle<std::vector<recob::Hit>> hitHandle =
1800 evt.getValidHandle<std::vector<recob::Hit>>(inputTag);
1802 art::FindOneP<raw::RawDigit> hitToRawDigitAssns(hitHandle, evt, inputTag);
1804 if (hitToRawDigitAssns.isValid()) {
1805 for (
size_t rawDigitIdx = 0; rawDigitIdx < hitToRawDigitAssns.size(); rawDigitIdx++) {
1806 art::Ptr<raw::RawDigit> rawDigit = hitToRawDigitAssns.at(rawDigitIdx);
1808 channelToRawDigitMap[rawDigit->Channel()] = rawDigit;
1814 for (
const auto& hitPtrPair : recobHitPtrMap) {
1817 std::unordered_map<raw::ChannelID_t, art::Ptr<raw::RawDigit>>::iterator chanRawDigitItr =
1818 channelToRawDigitMap.find(channel);
1820 if (!(chanRawDigitItr != channelToRawDigitMap.end())) {
1821 mf::LogDebug(
"Cluster3D") <<
"** Did not find channel to wire match! Skipping..."
1826 rawDigitAssns.addSingle(chanRawDigitItr->second, hitPtrPair.second);
PlaneToWireToHitSetMap m_planeToWireToHitSetMap
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)
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_maxDeltaPeakVec
float m_wirePitchScaleFactor
Scaling factor to determine max distance allowed between candidate pairs.
void setWireID(const geo::WireID &wid) const
std::vector< float > m_chiSquare3DVec
double z
z position of intersection
std::list< reco::ClusterHit3D > HitPairList
const geo::Geometry * m_geometry
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.
std::vector< float > m_hitAsymmetryVec
void CreateNewRecobHitCollection(art::Event &, reco::HitPairList &, std::vector< recob::Hit > &, RecobHitToPtrMap &)
Create a new 2D hit collection from hits associated to 3D space points.
float getTimeTicks() const
std::vector< float > m_deltaTimeVec
std::vector< size_t > ChannelStatusVec
define data structure for keeping track of channel status
const Eigen::Vector3f getPosition() const
bool SetHitTimeOrder(const reco::ClusterHit2D *left, const reco::ClusterHit2D *right)
float RMS() const
RMS of the hit shape, in tick units.
Declaration of signal hit object.
size_t BuildHitPairMapByTPC(PlaneHitVectorItrPairVec &planeHitVectorItrPairVec, reco::HitPairList &hitPairList) const
The data type to uniquely identify a Plane.
const geo::WireID & WireID() const
TTree * m_tupleTree
output analysis tree
int findGoodHitPairs(const reco::ClusterHit2D *, HitVector::iterator &, HitVector::iterator &, HitMatchPairVecMap &) const
bool operator()(const reco::ClusterHit2D *, const reco::ClusterHit2D *) const
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.
float getTimeToExecute(IHit3DBuilder::TimeValues index) const override
If monitoring, recover the time to execute a particular function.
void BuildHit3D(reco::HitPairList &hitPairList) const
Given the ClusterHit2D objects, build the HitPairMap.
std::map< geo::WireID, HitMatchPairVec > HitMatchPairVecMap
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.
void produces(art::ProducesCollector &) override
Each algorithm may have different objects it wants "produced" so use this to let the top level produc...
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
void Hit3DBuilder(art::Event &, reco::HitPairList &, RecobHitToPtrMap &) override
Given a set of recob hits, run DBscan to form 3D clusters.
std::vector< float > m_timeVector
std::map< geo::PlaneID, WireToHitSetMap > PlaneToWireToHitSetMap
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
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.
bool SetPeakHitPairIteratorOrder(const reco::HitPairList::iterator &left, const reco::HitPairList::iterator &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.
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
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.
std::vector< float > m_spacePointChargeVec
IDparameter< geo::PlaneID > PlaneID
Member type of validated geo::PlaneID parameter.
float m_maxHit3DChiSquare
Provide ability to select hits based on "chi square".
unsigned short Status_t
type representing channel status
std::vector< int > m_smallIndexVec
float getAvePeakTime() const
std::map< size_t, HitVector > HitVectorMap
Class managing the creation of a new recob::Hit object.
void makeWireAssns(const art::Event &, art::Assns< recob::Wire, recob::Hit > &, RecobHitToPtrMap &) const
Create recob::Wire to recob::Hit associations.
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...
Helper functions to create a hit.
std::vector< art::InputTag > m_hitFinderTagVec
Data members to follow.
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
std::vector< int > m_invalidTPCVec
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.
bool m_outputHistograms
Take the time to create and fill some histograms for diagnostics.
std::map< geo::PlaneID, HitVector > PlaneToHitVectorMap
StandardHit3DBuilder class definiton.
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.
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.
Hit2DList m_clusterHit2DMasterList
void CollectArtHits(const art::Event &evt) const
Extract the ART hits and the ART hit-particle relationships.
float getXPosition() const
TimeValues
enumerate the possible values for time checking if monitoring timing
std::vector< float > m_maxSideVecVec
Class providing information about the quality of channels.
The geometry of one entire detector, as served by art.
std::vector< HitMatchPair > HitMatchPairVec
PlaneID_t Plane
Index of the plane within its TPC.
raw::TDCtick_t StartTick() const
Initial tdc tick for hit.
float chargeIntegral(float, float, float, float, int, int) const
Perform charge integration between limits.
IHit3DBuilder interface class definiton.
bool m_weHaveAllBeenHereBefore
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...
void makeRawDigitAssns(const art::Event &, art::Assns< raw::RawDigit, recob::Hit > &, RecobHitToPtrMap &) const
Create raw::RawDigit to recob::Hit associations.
This provides an art tool interface definition for tools which construct 3D hits used in 3D clusterin...
std::vector< const reco::ClusterHit2D * > ClusterHit2DVec
void findGoodTriplets(HitMatchPairVecMap &, HitMatchPairVecMap &, reco::HitPairList &, bool=false) const
This algorithm takes lists of hit pairs and finds good triplets.
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.
raw::TDCtick_t EndTick() const
Final tdc tick for hit.
const lariov::ChannelStatusProvider * m_channelFilter
std::map< geo::TPCID, PlaneToWireToHitSetMap > TPCToPlaneToWireToHitSetMap
ChannelStatusByPlaneVec m_channelStatus
std::vector< const reco::ClusterHit2D * > HitVector
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, geo::Point_t &intersection) const
Computes the intersection between two wires.
bool operator()(const reco::HitPairClusterMap::iterator &left, const reco::HitPairClusterMap::iterator &right)
std::map< geo::TPCID, PlaneToHitVectorMap > TPCToPlaneToHitVectorMap
float PeakTime() const
Time of the signal peak, in tick units.
bool operator()(const SnippetHitMapItrPair &left, const SnippetHitMapItrPair &right) const
std::pair< const reco::ClusterHit2D *, reco::ClusterHit3D > HitMatchPair
This builds a list of candidate hit pairs from lists of hits on two planes.
std::vector< float > m_qualityMetricVec
void setID(const size_t &id) const
std::vector< ChannelStatusVec > ChannelStatusByPlaneVec
double y
y position of intersection
std::vector< std::pair< HitVector::iterator, HitVector::iterator >> PlaneHitVectorItrPairVec
Given the ClusterHit2D objects, build the HitPairMap.
size_t BuildHitPairMap(PlaneToHitVectorMap &planeToHitVectorMap, reco::HitPairList &hitPairList) const
Given the ClusterHit2D objects, build the HitPairMap.
Interface for experiment-specific channel quality info provider.
int trigger_offset(DetectorClocksData const &data)
float getDeltaPeakTime() const
void WireEndPoints(geo::WireID const &wireid, double *xyzStart, double *xyzEnd) const
Fills two arrays with the coordinates of the wire end points.
StandardHit3DBuilder(fhicl::ParameterSet const &pset)
Constructor.
constexpr WireID()=default
Default constructor: an invalid TPC ID.
2D representation of charge deposited in the TDC/wire plane
art::ServiceHandle< art::TFileService > tfs
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.
double WireCoordinate(Point const &point) const
Returns the coordinate of the point on the plane, in wire units.
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.
std::vector< float > m_maxPullVec
const ClusterHit2DVec & getHits() const
void clear()
clear the tuple vectors before processing next event
std::unordered_map< const recob::Hit *, art::Ptr< recob::Hit >> RecobHitToPtrMap
Defines a structure mapping art representation to internal.
std::vector< float > m_smallChargeDiffVec
void setPosition(const Eigen::Vector3f &pos) const
bool SetPairStartTimeOrder(const reco::ClusterHit3D &left, const reco::ClusterHit3D &right)
void configure(const fhicl::ParameterSet &) override
Interface for configuring the particular algorithm tool.
art framework interface to geometry description
BEGIN_PROLOG could also be cout
std::vector< float > m_overlapRangeVec
void BuildChannelStatusVec(PlaneToWireToHitSetMap &planeToWiretoHitSetMap) const
Create the internal channel status vector (assume will eventually be event-by-event) ...
PlaneToHitVectorMap m_planeToHitVectorMap
std::map< unsigned int, Hit2DSet > WireToHitSetMap
unsigned getStatusBits() const
void setStatusBit(unsigned bits) const
std::vector< float > m_overlapFractionVec