10 #include "cetlib/search_path.h" 11 #include "cetlib/cpu_timer.h" 21 #include "larevt/CalibrationDBI/Interface/ChannelStatusService.h" 22 #include "larevt/CalibrationDBI/Interface/ChannelStatusProvider.h" 25 #include <Eigen/Dense> 53 using Hit2DSet = std::set<const reco::ClusterHit2D*, Hit2DSetCompare>;
128 using HitMatchPair = std::pair<const reco::ClusterHit2D*,reco::ClusterHit3D>;
145 float hitWidthSclFctr = 1.,
146 size_t hitPairCntr = 0)
const;
195 float m_wirePitch[3];
215 m_channelFilter(&
art::ServiceHandle<
lariov::ChannelStatusService>()->GetProvider())
241 m_detector = lar::providerFrom<detinfo::DetectorPropertiesService>();
269 lariov::ChannelStatusProvider::Status_t chanStat =
m_channelFilter->Status(channel);
298 return (*left)->getAvePeakTime() < (*right)->getAvePeakTime();
306 if (left->second.size() == right->second.size())
307 return left->first < right->first;
309 return left->second.size() > right->second.size();
344 cet::cpu_timer theClockMakeHits;
356 theClockMakeHits.stop();
361 mf::LogDebug(
"Cluster3D") <<
">>>>> 3D hit building done, found " << numHitPairs <<
" 3D Hits" << std::endl;
374 class SetHitEarliestTimeOrder
377 SetHitEarliestTimeOrder() :
m_numRMS(1.) {}
378 SetHitEarliestTimeOrder(
float numRMS) :
m_numRMS(numRMS) {}
389 using HitVectorItrPair = std::pair<HitVector::iterator,HitVector::iterator>;
391 class SetStartTimeOrder
394 SetStartTimeOrder() :
m_numRMS(1.) {}
395 SetStartTimeOrder(
float numRMS) :
m_numRMS(numRMS) {}
397 bool operator()(
const HitVectorItrPair&
left,
const HitVectorItrPair&
right)
const 400 if (left.first != left.second && right.first != right.second)
403 return (*left.first)->getTimeTicks() -
m_numRMS*(*left.first)->getHit().RMS() < (*right.first)->getTimeTicks() -
m_numRMS*(*right.first)->getHit().RMS();
406 return left.first != left.second;
413 bool SetPairStartTimeOrder(
const std::unique_ptr<reco::ClusterHit3D>&
left,
const std::unique_ptr<reco::ClusterHit3D>&
right)
433 size_t totalNumHits(0);
434 size_t hitPairCntr(0);
437 size_t nDeadChanHits(0);
448 size_t nPlanesWithHits = (mapItr0 != planeToHitVectorMap.end() && !mapItr0->second.empty() ? 1 : 0)
449 + (mapItr1 != planeToHitVectorMap.end() && !mapItr1->second.empty() ? 1 : 0)
450 + (mapItr2 != planeToHitVectorMap.end() && !mapItr2->second.empty() ? 1 : 0);
452 if (nPlanesWithHits < 2)
continue;
459 std::sort(hitVector0.begin(), hitVector0.end(), SetHitEarliestTimeOrder(
m_numSigmaPeakTime));
460 std::sort(hitVector1.begin(), hitVector1.end(), SetHitEarliestTimeOrder(
m_numSigmaPeakTime));
461 std::sort(hitVector2.begin(), hitVector2.end(), SetHitEarliestTimeOrder(
m_numSigmaPeakTime));
464 HitVectorItrPair(hitVector1.begin(),hitVector1.end()),
465 HitVectorItrPair(hitVector2.begin(),hitVector2.end())};
472 hitPairList.sort(SetPairStartTimeOrder);
475 mf::LogDebug(
"Cluster3D") <<
"Total number hits: " << totalNumHits << std::endl;
476 mf::LogDebug(
"Cluster3D") <<
"Created a total of " << hitPairList.size() <<
" hit pairs, counted: " << hitPairCntr << std::endl;
477 mf::LogDebug(
"Cluster3D") <<
"-- Triplets: " << nTriplets <<
", dead channel pairs: " << nDeadChanHits << std::endl;
479 return hitPairList.size();
497 while(startItr != endItr)
500 if ((*startItr)->getTimeTicks() + numRMS * (*startItr)->getHit().RMS() < startTime) startItr++;
508 while(firstItr != endItr)
511 if ((*firstItr)->getTimeTicks() - numRMS * (*firstItr)->getHit().RMS() < endTime) firstItr++;
518 size_t nDeadChanHits(0);
532 float goldenTimeEnd = goldenHit->getTimeTicks() +
m_numSigmaPeakTime * goldenHit->getHit().RMS() + std::numeric_limits<float>::epsilon();
541 size_t curHitListSize(hitPairList.size());
545 size_t n12Pairs =
findGoodHitPairs(goldenHit, hitItr1Start, hitItr1End, pair12Map);
546 size_t n13Pairs =
findGoodHitPairs(goldenHit, hitItr2Start, hitItr2End, pair13Map);
548 nDeadChanHits += hitPairList.size() - curHitListSize;
549 curHitListSize = hitPairList.size();
551 if (n12Pairs > n13Pairs)
findGoodTriplets(pair12Map, pair13Map, hitPairList);
554 nTriplets += hitPairList.size() - curHitListSize;
556 hitItrVec[0].first++;
558 int nPlanesWithHits(0);
560 for(
auto& pair : hitItrVec)
561 if (pair.first != pair.second) nPlanesWithHits++;
563 if (nPlanesWithHits < 2)
break;
566 return hitPairList.size();
577 while(startItr != endItr)
587 hitMatchMap[wireID].emplace_back(hit,pair);
598 if (!pair12Map.empty())
601 std::vector<reco::ClusterHit3D> tempDeadChanVec;
605 std::map<const reco::ClusterHit3D*,bool> usedPairMap;
608 for(
const auto& pair13 : pair13Map)
610 for(
const auto& hit2Dhit3DPair : pair13.second) usedPairMap[&hit2Dhit3DPair.second] =
false;
614 for(
const auto& pair12 : pair12Map)
616 if (pair12.second.empty())
continue;
622 size_t missPlane = 0;
624 if (!pair12.second.front().second.getHits()[1]) missPlane = 1;
625 else if (!pair12.second.front().second.getHits()[2]) missPlane = 2;
627 missingPlaneID.
Plane = missPlane;
631 for(
const auto& hit2Dhit3DPair : pair12.second)
639 usedPairMap[&pair1] =
false;
645 for(
int loopIdx = 0; loopIdx < 2; loopIdx++)
651 if (thirdPlaneHitMapItr != pair13Map.end())
653 for(
const auto& thirdPlaneHitItr : thirdPlaneHitMapItr->second)
663 triplet.
setID(hitPairList.size());
665 usedPairMap[&pair1] =
true;
666 usedPairMap[&pair2] =
true;
680 for(
const auto& pairMapPair : usedPairMap)
682 if (pairMapPair.second)
continue;
687 if (
makeDeadChannelPair(deadChanPair, *pair, 4, 0, 0.)) tempDeadChanVec.emplace_back(deadChanPair);
691 if(!tempDeadChanVec.empty())
694 if (tempDeadChanVec.size() > 1)
697 std::sort(tempDeadChanVec.begin(),tempDeadChanVec.end(),[](
const auto&
left,
const auto&
right){
return left.getDeltaPeakTime()/
left.getSigmaPeakTime() <
right.getDeltaPeakTime()/
right.getSigmaPeakTime();});
700 float firstSig = tempDeadChanVec.front().getDeltaPeakTime() / tempDeadChanVec.front().getSigmaPeakTime();
701 float lastSig = tempDeadChanVec.back().getDeltaPeakTime() / tempDeadChanVec.back().getSigmaPeakTime();
702 float sigRange = lastSig - firstSig;
707 float maxSignificance =
std::max(0.75 * (firstSig + lastSig),1.0);
709 std::vector<reco::ClusterHit3D>::iterator firstBadElem = std::find_if(tempDeadChanVec.begin(),tempDeadChanVec.end(),[&maxSignificance](
const auto& pair){
return pair.getDeltaPeakTime()/pair.getSigmaPeakTime() > maxSignificance;});
712 if (std::distance(tempDeadChanVec.begin(),firstBadElem) > 20) firstBadElem = tempDeadChanVec.begin() + 20;
714 else if (firstBadElem == tempDeadChanVec.begin()) firstBadElem++;
716 tempDeadChanVec.resize(std::distance(tempDeadChanVec.begin(),firstBadElem));
720 for(
auto& pair : tempDeadChanVec)
722 pair.setID(hitPairList.size());
735 float hitWidthSclFctr,
736 size_t hitPairCntr)
const 761 float hit1Width = hitWidthSclFctr * hit1Sigma;
762 float hit2Width = hitWidthSclFctr * hit2Sigma;
765 if (fabs(hit1Peak - hit2Peak) <= (hit1Width + hit2Width))
768 float hit1SigSq = hit1Sigma * hit1Sigma;
769 float hit2SigSq = hit2Sigma * hit2Sigma;
770 float avePeakTime = (hit1Peak / hit1SigSq + hit2Peak / hit2SigSq) * hit1SigSq * hit2SigSq / (hit1SigSq + hit2SigSq);
771 float deltaPeakTime = std::fabs(hit1Peak - hit2Peak);
772 float sigmaPeakTime = std::sqrt(hit1SigSq + hit2SigSq);
778 float hitChiSquare = std::pow((hit1Peak - avePeakTime),2) / hit1SigSq
779 + std::pow((hit2Peak - avePeakTime),2) / hit2SigSq;
783 float xPosition = (xPositionHit1 / hit1SigSq + xPositionHit2 / hit2SigSq) * hit1SigSq * hit2SigSq / (hit1SigSq + hit2SigSq);
785 float position[] = {xPosition, float(widIntersect.
y), float(widIntersect.
z)-
m_zPosOffset};
799 hitVector.resize(3, NULL);
808 std::vector<geo::WireID> wireIDVec = {
geo::WireID(cryostatIdx,tpcIdx,0,0),
816 std::vector<float> hitDelTSigVec = {0.,0.,0.};
853 static const float rmsToSig(1.0);
856 static const double wirePitch(0.3);
884 if (!hit0) hit0 = pairHitVec.at(2);
885 else if (!hit1) hit1 = pairHitVec.at(2);
898 std::vector<float> sideVec = {(pair0hYZVec - pair1hYZVec).
norm(),(pair1hYZVec - pairYZVec).
norm(),(pairYZVec - pair0hYZVec).
norm()};
902 if (*std::max_element(sideVec.begin(),sideVec.end()) < wirePitch)
911 unsigned int statusBits(0x7);
912 float totalCharge(0.);
913 float avePeakTime(0.);
918 std::vector<geo::WireID> wireIDVec = {
geo::WireID(0,0,
geo::kU,0),
geo::WireID(0,0,
geo::kV,0),
geo::WireID(0,0,
geo::kW,0)};
921 for(
size_t planeIdx = 0; planeIdx < 3; planeIdx++)
931 float hitRMS = rmsToSig * hit2D->
getHit().
RMS();
932 float weight = 1. / (hitRMS * hitRMS);
935 avePeakTime += peakTime *
weight;
941 avePeakTime /= weightSum;
942 xPosition /= weightSum;
944 float position[] = { xPosition,
945 float((pairYZVec[0] + pair0hYZVec[0] + pair1hYZVec[0]) / 3.),
946 float((pairYZVec[1] + pair0hYZVec[1] + pair1hYZVec[1]) / 3.)};
949 float hitChiSquare(0.);
950 float sigmaPeakTime(std::sqrt(1./weightSum));
951 std::vector<float> hitDelTSigVec;
953 for(
const auto& hit2D : hitVector)
955 float hitRMS = rmsToSig * hit2D->getHit().RMS();
956 float combRMS = std::sqrt(hitRMS*hitRMS - sigmaPeakTime*sigmaPeakTime);
957 float peakTime = hit2D->getTimeTicks();
958 float deltaTime = peakTime - avePeakTime;
959 float hitSig = deltaTime / combRMS;
961 hitChiSquare += hitSig * hitSig;
963 hitDelTSigVec.emplace_back(std::fabs(hitSig));
967 float deltaPeakTime = *std::max_element(hitDelTSigVec.begin(),hitDelTSigVec.end());
996 size_t maxChanStatus,
997 size_t minChanStatus,
998 float minOverlap)
const 1006 size_t missPlane(2);
1031 bool wireOneStatus = m_channelStatus[wireID.
Plane][wireID.
Wire+1] < maxChanStatus && m_channelStatus[wireID.
Plane][wireID.
Wire+1] >= minChanStatus;
1034 if(wireStatus || wireOneStatus)
1037 if (!wireStatus) wireID.
Wire += 1;
1050 newPosition[1] = (newPosition[1] + widIntersect0.
y + widIntersect1.
y) / 3.;
1051 newPosition[2] = (newPosition[2] + widIntersect0.
z + widIntersect1.
z - 2. *
m_zPosOffset) / 3.;
1073 static const float minCharge(0.);
1080 for (
const auto& hit2D : hit2DSet)
1082 if (hit2D->getHit().Integral() < minCharge)
continue;
1084 float hitVPeakTime(hit2D->getTimeTicks());
1085 float deltaPeakTime(pairAvePeakTime-hitVPeakTime);
1087 if (deltaPeakTime > pairDeltaTimeLimits)
continue;
1089 if (deltaPeakTime < -pairDeltaTimeLimits)
break;
1091 pairDeltaTimeLimits = fabs(deltaPeakTime);
1100 static const float minCharge(0.);
1102 int numberInRange(0);
1106 for (
const auto& hit2D : hit2DSet)
1108 if (hit2D->getHit().Integral() < minCharge)
continue;
1110 float hitVPeakTime(hit2D->getTimeTicks());
1111 float deltaPeakTime(pairAvePeakTime-hitVPeakTime);
1113 if (deltaPeakTime > range)
continue;
1115 if (deltaPeakTime < -range)
break;
1120 return numberInRange;
1133 wireID.
Wire = int(distanceToWire);
1138 mf::LogWarning(
"Cluster3D") <<
"Exception caught finding nearest wire, position - " << exc.what() << std::endl;
1170 if (!recobHitHandle.
isValid())
return;
1172 cet::cpu_timer theClockMakeHits;
1178 std::map<geo::PlaneID, double> planeOffsetMap;
1200 std::cout <<
"***> 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)] << std::endl;
1207 for (
size_t cIdx = 0; cIdx < recobHitHandle->size(); cIdx++)
1225 hitToPtrMap[recobHitPtr] = recobHit;
1230 std::sort(hitVectorMap.second.begin(), hitVectorMap.second.end(),
SetHitTimeOrder);
1234 theClockMakeHits.stop();
PlaneToWireToHitSetMap m_planeToWireToHitSetMap
bool makeHitTriplet(reco::ClusterHit3D &pairOut, const reco::ClusterHit3D &pairIn, const reco::ClusterHit2D *hit2) const
Make a 3D HitPair object by checking two hits.
PlaneID const & planeID() const
void setWireID(const geo::WireID &wid) const
double z
z position of intersection
std::map< size_t, HitVector > HitVectorMap
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
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
virtual int TriggerOffset() const =0
const detinfo::DetectorProperties * m_detector
std::vector< size_t > ChannelStatusVec
define data structure for keeping track of channel status
geo::WireID NearestWireID(const float *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 SetHitTimeOrder(const reco::ClusterHit2D *left, const reco::ClusterHit2D *right)
geo::WireID WireID() const
Initial tdc tick for hit.
float RMS() const
RMS of the hit shape, in tick units.
What follows are several highly useful typedefs which we want to expose to the outside world...
Declaration of signal hit object.
size_t BuildHitPairMapByTPC(PlaneHitVectorItrPairVec &planeHitVectorItrPairVec, reco::HitPairList &hitPairList) const
The data type to uniquely identify a Plane.
art::InputTag m_hitFinderTag
Data members to follow.
int findGoodHitPairs(const reco::ClusterHit2D *, HitVector::iterator &, HitVector::iterator &, HitMatchPairVecMap &) const
bool operator()(const reco::ClusterHit2D *, const reco::ClusterHit2D *) 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.
void BuildHit3D(reco::HitPairList &hitPairList) const
Given the ClusterHit2D objects, build the HitPairMap.
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.
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
std::vector< float > m_timeVector
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
std::map< geo::PlaneID, WireToHitSetMap > PlaneToWireToHitSetMap
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
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.
void Hit3DBuilder(const art::Event &evt, reco::HitPairList &hitPairList, RecobHitToPtrMap &) const override
Given a set of recob hits, run DBscan to form 3D clusters.
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::list< std::unique_ptr< reco::ClusterHit3D >> HitPairList
std::vector< reco::ClusterHit2D * > HitVector
float getAvePeakTime() const
std::vector< std::unique_ptr< reco::ClusterHit3D >> HitPairVector
~StandardHit3DBuilder()
Destructor.
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
std::map< geo::TPCID, PlaneToWireToHitSetMap > TPCToPlaneToWireToHitSetMap
std::map< geo::PlaneID, HitVector > PlaneToHitVectorMap
T get(std::string const &key) const
Hit2DVector m_clusterHit2DMasterVec
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.
const recob::Hit & getHit() const
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
float getXPosition() const
TimeValues
enumerate the possible values for time checking if monitoring timing
The geometry of one entire detector, as served by art.
std::vector< HitMatchPair > HitMatchPairVec
std::map< const recob::Hit *, art::Ptr< recob::Hit >> RecobHitToPtrMap
Defines a structure mapping art representation to internal.
PlaneID_t Plane
Index of the plane within its TPC.
IHit3DBuilder interface class definiton.
const float * getPosition() const
std::pair< const reco::ClusterHit2D *, reco::ClusterHit3D > HitMatchPair
This builds a list of candidate hit pairs from lists of hits on two planes.
Detector simulation of raw signals on wires.
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.
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
std::map< unsigned int, Hit2DSet > WireToHitSetMap
const lariov::ChannelStatusProvider * m_channelFilter
ChannelStatusByPlaneVec m_channelStatus
void initialize(size_t id, unsigned int statusBits, const float *position, float totalCharge, float avePeakTime, float deltaPeakTime, float sigmaPeakTime, float hitChiSquare, float docaToAxis, float arclenToPoca, const ClusterHit2DVec &hitVec, const std::vector< float > &hitDelTSigVec, const std::vector< geo::WireID > &wireIDVec)
void CollectArtHits(const art::Event &evt, RecobHitToPtrMap &hitToPtrMap) const
Extract the ART hits and the ART hit-particle relationships.
Filters for channels, events, etc.
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, geo::Point_t &intersection) const
Computes the intersection between two wires.
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
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.
Utility object to perform functions of association.
void setID(const size_t &id) const
void setPosition(const float *pos) const
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
std::vector< reco::ClusterHit2D > Hit2DVector
std::vector< ChannelStatusVec > ChannelStatusByPlaneVec
double y
y position of intersection
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
size_t BuildHitPairMap(PlaneToHitVectorMap &planeToHitVectorMap, reco::HitPairList &hitPairList) const
Given the ClusterHit2D objects, build the HitPairMap.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::map< geo::WireID, HitMatchPairVec > HitMatchPairVecMap
std::vector< std::pair< HitVector::iterator, HitVector::iterator >> PlaneHitVectorItrPairVec
Given the ClusterHit2D objects, build the HitPairMap.
StandardHit3DBuilder(fhicl::ParameterSet const &pset)
Constructor.
Planes which measure W (third view for Bo, MicroBooNE, etc).
2D representation of charge deposited in the TDC/wire plane
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.
TPCID_t TPC
Index of the TPC within its cryostat.
float getTimeToExecute(IHit3DBuilder::TimeValues index) const override
If monitoring, recover the time to execute a particular function.
const ClusterHit2DVec & getHits() const
geo::Geometry * m_geometry
std::set< const reco::ClusterHit2D *, Hit2DSetCompare > Hit2DSet
void configure(const fhicl::ParameterSet &) override
Interface for configuring the particular algorithm tool.
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
void BuildChannelStatusVec(PlaneToWireToHitSetMap &planeToWiretoHitSetMap) const
Create the internal channel status vector (assume will eventually be event-by-event) ...
PlaneToHitVectorMap m_planeToHitVectorMap
unsigned getStatusBits() const
virtual double GetXTicksOffset(int p, int t, int c) const =0
void setStatusBit(unsigned bits) const