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" 50 using Hit2DSet = std::set<const reco::ClusterHit2D*, Hit2DSetCompare>;
125 using HitMatchPair = std::pair<const reco::ClusterHit2D*,reco::ClusterHit3D>;
142 float hitWidthSclFctr = 1.,
143 size_t hitPairCntr = 0)
const;
192 float m_wirePitch[3];
212 m_channelFilter(&
art::ServiceHandle<
lariov::ChannelStatusService>()->GetProvider())
238 m_detector = lar::providerFrom<detinfo::DetectorPropertiesService>();
266 lariov::ChannelStatusProvider::Status_t chanStat =
m_channelFilter->Status(channel);
295 return (*left)->getAvePeakTime() < (*right)->getAvePeakTime();
303 if (left->second.size() == right->second.size())
304 return left->first < right->first;
306 return left->second.size() > right->second.size();
341 cet::cpu_timer theClockMakeHits;
353 theClockMakeHits.stop();
358 mf::LogDebug(
"Cluster3D") <<
">>>>> 3D hit building done, found " << numHitPairs <<
" 3D Hits" << std::endl;
371 using HitVectorItrPair = std::pair<HitVector::iterator,HitVector::iterator>;
373 class SetStartTimeOrder
376 SetStartTimeOrder() :
m_numRMS(1.) {}
377 SetStartTimeOrder(
float numRMS) :
m_numRMS(numRMS) {}
379 bool operator()(
const HitVectorItrPair& left,
const HitVectorItrPair& right)
const 382 if (left.first != left.second && right.first != right.second)
385 return (*left.first)->getTimeTicks() -
m_numRMS*(*left.first)->getHit().RMS() < (*right.first)->getTimeTicks() -
m_numRMS*(*right.first)->getHit().RMS();
388 return left.first != left.second;
395 bool SetPairStartTimeOrder(
const std::unique_ptr<reco::ClusterHit3D>& left,
const std::unique_ptr<reco::ClusterHit3D>& right)
415 size_t totalNumHits(0);
416 size_t hitPairCntr(0);
419 size_t nDeadChanHits(0);
430 size_t nPlanesWithHits = (mapItr0 != planeToHitVectorMap.end() && !mapItr0->second.empty() ? 1 : 0)
431 + (mapItr1 != planeToHitVectorMap.end() && !mapItr1->second.empty() ? 1 : 0)
432 + (mapItr2 != planeToHitVectorMap.end() && !mapItr2->second.empty() ? 1 : 0);
434 if (nPlanesWithHits < 2)
continue;
441 std::sort(hitVector0.begin(), hitVector0.end(), SetHitStartTimeOrder);
442 std::sort(hitVector1.begin(), hitVector1.end(), SetHitStartTimeOrder);
443 std::sort(hitVector2.begin(), hitVector2.end(), SetHitStartTimeOrder);
446 HitVectorItrPair(hitVector1.begin(),hitVector1.end()),
447 HitVectorItrPair(hitVector2.begin(),hitVector2.end())};
454 hitPairList.sort(SetPairStartTimeOrder);
457 mf::LogDebug(
"Cluster3D") <<
"Total number hits: " << totalNumHits << std::endl;
458 mf::LogDebug(
"Cluster3D") <<
"Created a total of " << hitPairList.size() <<
" hit pairs, counted: " << hitPairCntr << std::endl;
459 mf::LogDebug(
"Cluster3D") <<
"-- Triplets: " << nTriplets <<
", dead channel pairs: " << nDeadChanHits << std::endl;
461 return hitPairList.size();
479 while(startItr != endItr)
482 if ((*startItr)->getTimeTicks() + numRMS * (*startItr)->getHit().RMS() < startTime) startItr++;
490 while(firstItr != endItr)
493 if ((*firstItr)->getTimeTicks() - numRMS * (*firstItr)->getHit().RMS() < endTime) firstItr++;
500 size_t nDeadChanHits(0);
514 float goldenTimeEnd = goldenHit->getTimeTicks() +
m_numSigmaPeakTime * goldenHit->getHit().RMS() + 0.1;
523 size_t curHitListSize(hitPairList.size());
527 size_t n12Pairs =
findGoodHitPairs(goldenHit, hitItr1Start, hitItr1End, pair12Map);
528 size_t n13Pairs =
findGoodHitPairs(goldenHit, hitItr2Start, hitItr2End, pair13Map);
530 nDeadChanHits += hitPairList.size() - curHitListSize;
531 curHitListSize = hitPairList.size();
533 if (n12Pairs > n13Pairs)
findGoodTriplets(pair12Map, pair13Map, hitPairList);
536 nTriplets += hitPairList.size() - curHitListSize;
538 hitItrVec[0].first++;
540 int nPlanesWithHits(0);
542 for(
auto& pair : hitItrVec)
543 if (pair.first != pair.second) nPlanesWithHits++;
545 if (nPlanesWithHits < 2)
break;
548 return hitPairList.size();
559 while(startItr != endItr)
569 hitMatchMap[wireID].emplace_back(hit,pair);
580 if (!pair12Map.empty())
583 std::vector<reco::ClusterHit3D> tempDeadChanVec;
587 std::map<const reco::ClusterHit3D*,bool> usedPairMap;
590 for(
const auto& pair13 : pair13Map)
592 for(
const auto& hit2Dhit3DPair : pair13.second) usedPairMap[&hit2Dhit3DPair.second] =
false;
596 for(
const auto& pair12 : pair12Map)
598 if (pair12.second.empty())
continue;
604 size_t missPlane = 0;
606 if (!pair12.second.front().second.getHits()[1]) missPlane = 1;
607 else if (!pair12.second.front().second.getHits()[2]) missPlane = 2;
609 missingPlaneID.
Plane = missPlane;
613 for(
const auto& hit2Dhit3DPair : pair12.second)
621 usedPairMap[&pair1] =
false;
629 if (thirdPlaneHitMapItr == pair13Map.end())
633 thirdPlaneHitMapItr = pair13Map.find(wireID);
637 if (thirdPlaneHitMapItr != pair13Map.end())
639 for(
const auto& thirdPlaneHitItr : thirdPlaneHitMapItr->second)
649 triplet.
setID(hitPairList.size());
651 usedPairMap[&pair1] =
true;
652 usedPairMap[&pair2] =
true;
662 for(
const auto& pairMapPair : usedPairMap)
664 if (pairMapPair.second)
continue;
669 if (
makeDeadChannelPair(deadChanPair, *pair, 4, 0, 0.)) tempDeadChanVec.emplace_back(deadChanPair);
673 if(!tempDeadChanVec.empty())
676 if (tempDeadChanVec.size() > 1)
679 std::sort(tempDeadChanVec.begin(),tempDeadChanVec.end(),[](
const auto&
left,
const auto&
right){
return left.getDeltaPeakTime()/
left.getSigmaPeakTime() <
right.getDeltaPeakTime()/
right.getSigmaPeakTime();});
682 float firstSig = tempDeadChanVec.front().getDeltaPeakTime() / tempDeadChanVec.front().getSigmaPeakTime();
683 float lastSig = tempDeadChanVec.back().getDeltaPeakTime() / tempDeadChanVec.back().getSigmaPeakTime();
684 float sigRange = lastSig - firstSig;
689 float maxSignificance =
std::max(0.75 * (firstSig + lastSig),1.0);
691 std::vector<reco::ClusterHit3D>::iterator firstBadElem = std::find_if(tempDeadChanVec.begin(),tempDeadChanVec.end(),[&maxSignificance](
const auto& pair){
return pair.getDeltaPeakTime()/pair.getSigmaPeakTime() > maxSignificance;});
694 if (std::distance(tempDeadChanVec.begin(),firstBadElem) > 20) firstBadElem = tempDeadChanVec.begin() + 20;
696 else if (firstBadElem == tempDeadChanVec.begin()) firstBadElem++;
698 tempDeadChanVec.resize(std::distance(tempDeadChanVec.begin(),firstBadElem));
702 for(
auto& pair : tempDeadChanVec)
704 pair.setID(hitPairList.size());
717 float hitWidthSclFctr,
718 size_t hitPairCntr)
const 743 float hit1Width = hitWidthSclFctr * hit1Sigma;
744 float hit2Width = hitWidthSclFctr * hit2Sigma;
747 if (fabs(hit1Peak - hit2Peak) <= (hit1Width + hit2Width))
750 float hit1SigSq = hit1Sigma * hit1Sigma;
751 float hit2SigSq = hit2Sigma * hit2Sigma;
752 float avePeakTime = (hit1Peak / hit1SigSq + hit2Peak / hit2SigSq) * hit1SigSq * hit2SigSq / (hit1SigSq + hit2SigSq);
753 float deltaPeakTime = std::fabs(hit1Peak - hit2Peak);
754 float sigmaPeakTime = std::sqrt(hit1SigSq + hit2SigSq);
760 float hitChiSquare = std::pow((hit1Peak - avePeakTime),2) / hit1SigSq
761 + std::pow((hit2Peak - avePeakTime),2) / hit2SigSq;
765 float xPosition = (xPositionHit1 / hit1SigSq + xPositionHit2 / hit2SigSq) * hit1SigSq * hit2SigSq / (hit1SigSq + hit2SigSq);
767 float position[] = {xPosition, float(widIntersect.
y), float(widIntersect.
z)-
m_zPosOffset};
781 hitVector.resize(3, NULL);
790 std::vector<geo::WireID> wireIDVec = {
geo::WireID(cryostatIdx,tpcIdx,0,0),
798 std::vector<float> hitDelTSigVec = {0.,0.,0.};
835 static const float rmsToSig(1.0);
863 if (!hit0) hit0 = pairHitVec.at(2);
864 else if (!hit1) hit1 = pairHitVec.at(2);
874 float yzdistance = std::sqrt(deltaPairY * deltaPairY + deltaPairZ * deltaPairZ);
880 if (yzdistance < 0.3)
889 unsigned int statusBits(0x7);
890 float totalCharge(0.);
891 float avePeakTime(0.);
896 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)};
899 for(
size_t planeIdx = 0; planeIdx < 3; planeIdx++)
909 float hitRMS = rmsToSig * hit2D->
getHit().
RMS();
910 float weight = 1. / (hitRMS * hitRMS);
913 avePeakTime += peakTime *
weight;
919 avePeakTime /= weightSum;
920 xPosition /= weightSum;
922 float position[] = { xPosition,
927 float hitChiSquare(0.);
928 float sigmaPeakTime(std::sqrt(1./weightSum));
929 std::vector<float> hitDelTSigVec;
931 for(
const auto& hit2D : hitVector)
933 float hitRMS = rmsToSig * hit2D->getHit().RMS();
934 float combRMS = std::sqrt(hitRMS*hitRMS - sigmaPeakTime*sigmaPeakTime);
935 float peakTime = hit2D->getTimeTicks();
936 float deltaTime = peakTime - avePeakTime;
937 float hitSig = deltaTime / combRMS;
939 hitChiSquare += hitSig * hitSig;
941 hitDelTSigVec.emplace_back(std::fabs(hitSig));
945 float deltaPeakTime = *std::max_element(hitDelTSigVec.begin(),hitDelTSigVec.end());
974 size_t maxChanStatus,
975 size_t minChanStatus,
976 float minOverlap)
const 1009 bool wireOneStatus = m_channelStatus[wireID.
Plane][wireID.
Wire+1] < maxChanStatus && m_channelStatus[wireID.
Plane][wireID.
Wire+1] >= minChanStatus;
1012 if(wireStatus || wireOneStatus)
1015 if (!wireStatus) wireID.
Wire += 1;
1028 newPosition[1] = (newPosition[1] + widIntersect0.
y + widIntersect1.
y) / 3.;
1029 newPosition[2] = (newPosition[2] + widIntersect0.
z + widIntersect1.
z - 2. *
m_zPosOffset) / 3.;
1051 static const float minCharge(0.);
1058 for (
const auto& hit2D : hit2DSet)
1060 if (hit2D->getHit().Integral() < minCharge)
continue;
1062 float hitVPeakTime(hit2D->getTimeTicks());
1063 float deltaPeakTime(pairAvePeakTime-hitVPeakTime);
1065 if (deltaPeakTime > pairDeltaTimeLimits)
continue;
1067 if (deltaPeakTime < -pairDeltaTimeLimits)
break;
1069 pairDeltaTimeLimits = fabs(deltaPeakTime);
1078 static const float minCharge(0.);
1080 int numberInRange(0);
1084 for (
const auto& hit2D : hit2DSet)
1086 if (hit2D->getHit().Integral() < minCharge)
continue;
1088 float hitVPeakTime(hit2D->getTimeTicks());
1089 float deltaPeakTime(pairAvePeakTime-hitVPeakTime);
1091 if (deltaPeakTime > range)
continue;
1093 if (deltaPeakTime < -range)
break;
1098 return numberInRange;
1111 wireID.
Wire = int(distanceToWire);
1116 mf::LogWarning(
"Cluster3D") <<
"Exception caught finding nearest wire, position - " << exc.what() << std::endl;
1148 if (!recobHitHandle.
isValid())
return;
1150 cet::cpu_timer theClockMakeHits;
1156 std::map<geo::PlaneID, double> planeOffsetMap;
1178 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;
1185 for (
size_t cIdx = 0; cIdx < recobHitHandle->size(); cIdx++)
1200 hitToPtrMap[recobHitPtr] = recobHit;
1205 std::sort(hitVectorMap.second.begin(), hitVectorMap.second.end(),
SetHitTimeOrder);
1209 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