15 #include "art_root_io/TFileService.h" 19 #include "cetlib/cpu_timer.h" 41 #include <unordered_map> 153 collector.
produces<std::vector<recob::Hit>>();
176 m_tupleTree = tfs->make<TTree>(
"Hit3DBuilderTree",
"Tree by StandardHit3DBuilder");
225 cet::cpu_timer theClockMakeHits;
233 if (!hitSpacePointAssnsHandle.
isValid())
return;
241 using SpacePointToWireIDMap = std::unordered_map<const recob::SpacePoint*, geo::WireID>;
243 SpacePointToWireIDMap spacePointToWireIDMap;
245 for (
const auto& assnPair : *hitSpacePointAssnsHandle) {
247 spacePointToWireIDMap[assnPair.second.get()] = assnPair.first->WireID();
252 using OldHitToNewHitMap = std::map<const recob::Hit*, const recob::Hit*>;
253 using SpacePointHitVecMap = std::map<const recob::SpacePoint*, std::vector<const recob::Hit*>>;
255 OldHitToNewHitMap oldHitToNewHitMap;
256 SpacePointHitVecMap spacePointHitVecMap;
259 std::unique_ptr<std::vector<recob::Hit>> newHitVecPtr(
new std::vector<recob::Hit>);
262 newHitVecPtr->reserve(3 * hitSpacePointAssnsHandle->size());
267 for (
auto& assnPair : *hitSpacePointAssnsHandle) {
272 if (oldHitToNewHitMap.find(recobHit.
get()) == oldHitToNewHitMap.end()) {
278 const std::vector<geo::WireID>& wireIDs =
282 for (
const auto& wireID : wireIDs) {
283 if (wireID.TPC != refWireID.
TPC || wireID.Cryostat != refWireID.
Cryostat)
continue;
294 spacePointHitVecMap[spacePoint.
get()].push_back(newHit);
296 recobHitToArtPtrMap[newHit] = ptrMaker(newHitVecPtr->size() - 1);
297 oldHitToNewHitMap[recobHit.
get()] = newHit;
300 spacePointHitVecMap[spacePoint.
get()].push_back(oldHitToNewHitMap[recobHit.
get()]);
305 std::map<geo::PlaneID, double> planeOffsetMap;
307 auto const clock_data =
309 auto const det_prop =
314 for (
size_t tpcIdx = 0; tpcIdx <
fGeometry->
NTPC(); tpcIdx++) {
319 det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 1)) -
320 det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 0));
322 det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 2)) -
323 det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 0));
325 std::cout <<
"***> plane 0 offset: " << planeOffsetMap[
geo::PlaneID(cryoIdx, tpcIdx, 0)]
326 <<
", plane 1: " << planeOffsetMap[
geo::PlaneID(cryoIdx, tpcIdx, 1)]
327 <<
", plane 2: " << planeOffsetMap[
geo::PlaneID(cryoIdx, tpcIdx, 2)] << std::endl;
328 std::cout <<
" Det prop plane 0: " 329 << det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 0))
330 <<
", plane 1: " << det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 1))
331 <<
", plane 2: " << det_prop.GetXTicksOffset(
geo::PlaneID(cryoIdx, tpcIdx, 2))
337 using RecobHitTo2DHitMap = std::map<const recob::Hit*, const reco::ClusterHit2D*>;
339 RecobHitTo2DHitMap recobHitTo2DHitMap;
346 for (
auto& hitPair : oldHitToNewHitMap) {
352 planeOffsetMap.at(hitWireID.planeID()));
353 double xPosition(det_prop.ConvertTicksToX(
354 recobHit->
PeakTime(), hitWireID.Plane, hitWireID.TPC, hitWireID.Cryostat));
362 for (
auto& pointPair : spacePointHitVecMap) {
364 const std::vector<const recob::Hit*>& recobHitVec = pointPair.second;
366 if (recobHitVec.size() != 3) {
367 std::cout <<
"************>>>>>> do not have 3 hits associated to space point! " 368 << recobHitVec.size() <<
" ***************" << std::endl;
374 for (
const auto& recobHit : recobHitVec) {
381 unsigned int statusBits(0x7);
382 float avePeakTime(0.);
389 for (
size_t planeIdx = 0; planeIdx < 3; planeIdx++) {
392 wireIDVec[planeIdx] = hit2D->
WireID();
400 float weight = 1. / (hitRMS * hitRMS);
403 avePeakTime += peakTime *
weight;
407 avePeakTime /= weightSum;
410 float hitChiSquare(0.);
411 float sigmaPeakTime(std::sqrt(1. / weightSum));
412 std::vector<float> hitDelTSigVec;
414 for (
const auto& hit2D : hitVector) {
415 float hitRMS = hit2D->getHit()->RMS();
416 float combRMS = std::sqrt(hitRMS * hitRMS - sigmaPeakTime * sigmaPeakTime);
417 float peakTime = hit2D->getTimeTicks();
418 float deltaTime = peakTime - avePeakTime;
419 float hitSig = deltaTime / combRMS;
421 hitChiSquare += hitSig * hitSig;
423 hitDelTSigVec.emplace_back(std::fabs(hitSig));
429 int lowMinIndex(std::numeric_limits<int>::max());
430 int lowMaxIndex(std::numeric_limits<int>::min());
431 int hiMinIndex(std::numeric_limits<int>::max());
432 int hiMaxIndex(std::numeric_limits<int>::min());
435 for (
const auto& hit2D : hitVector) {
436 int hitStart = hit2D->getHit()->PeakTime() - 2. * hit2D->getHit()->RMS() - 0.5;
437 int hitStop = hit2D->getHit()->PeakTime() + 2. * hit2D->getHit()->RMS() + 0.5;
439 lowMinIndex = std::min(hitStart, lowMinIndex);
440 lowMaxIndex = std::max(hitStart, lowMaxIndex);
441 hiMinIndex = std::min(hitStop + 1, hiMinIndex);
442 hiMaxIndex = std::max(hitStop + 1, hiMaxIndex);
446 if (hitChiSquare < m_maxHit3DChiSquare && hiMinIndex > lowMaxIndex) {
448 std::vector<float> chargeVec;
450 for (
const auto& hit2D : hitVector)
452 hit2D->getHit()->PeakAmplitude(),
453 hit2D->getHit()->RMS(),
458 std::accumulate(chargeVec.begin(), chargeVec.end(), 0.) / float(chargeVec.size());
459 float overlapRange = float(hiMinIndex - lowMaxIndex);
460 float overlapFraction = overlapRange / float(hiMaxIndex - lowMinIndex);
463 std::vector<float> smallestChargeDiffVec;
464 std::vector<float> chargeAveVec;
465 float smallestDiff(std::numeric_limits<float>::max());
466 size_t chargeIndex(0);
468 for (
size_t idx = 0; idx < 3; idx++) {
469 size_t leftIdx = (idx + 2) % 3;
470 size_t rightIdx = (idx + 1) % 3;
472 smallestChargeDiffVec.push_back(
std::abs(chargeVec[leftIdx] - chargeVec[rightIdx]));
473 chargeAveVec.push_back(
float(0.5 * (chargeVec[leftIdx] + chargeVec[rightIdx])));
475 if (smallestChargeDiffVec.back() < smallestDiff) {
476 smallestDiff = smallestChargeDiffVec.back();
482 float deltaPeakTime =
483 hitVector[leftIdx]->getTimeTicks() - hitVector[rightIdx]->getTimeTicks();
489 float chargeAsymmetry = (chargeAveVec[chargeIndex] - chargeVec[chargeIndex]) /
490 (chargeAveVec[chargeIndex] + chargeVec[chargeIndex]);
493 if (chargeAsymmetry < -1. || chargeAsymmetry > 1.) {
496 std::cout <<
"============> Charge asymmetry out of range: " << chargeAsymmetry
497 <<
" <============" << std::endl;
498 std::cout <<
" hit C: " << hitWireID.
Cryostat <<
", TPC: " << hitWireID.
TPC 499 <<
", Plane: " << hitWireID.
Plane <<
", Wire: " << hitWireID.
Wire << std::endl;
500 std::cout <<
" charge: " << chargeVec[0] <<
", " << chargeVec[1] <<
", " 501 << chargeVec[2] << std::endl;
502 std::cout <<
" index: " << chargeIndex <<
", smallest diff: " << smallestDiff
508 float deltaPeakTime = *std::max_element(hitDelTSigVec.begin(), hitDelTSigVec.end());
521 Eigen::Vector3f position(
522 float(spacePoint->
XYZ()[0]),
float(spacePoint->
XYZ()[1]),
float(spacePoint->
XYZ()[2]));
525 hitPairList.emplace_back(0,
546 hitRefiner.
use_hits(std::move(newHitVecPtr));
557 theClockMakeHits.stop();
562 mf::LogDebug(
"Cluster3D") <<
">>>>> 3D hit building done, found " << hitPairList.size()
563 <<
" 3D Hits" << std::endl;
576 for (
int sigPos = low; sigPos < hi; sigPos++) {
577 float arg = (float(sigPos) - peakMean + 0.5) / peakSigma;
578 integral += peakAmp * std::exp(-0.5 * arg * arg);
bool m_outputHistograms
Take the time to create and fill some histograms for diagnostics.
unsigned int NTPC(CryostatID const &cryoid=cryostat_zero) const
Returns the total number of TPCs in the specified cryostat.
std::list< reco::ClusterHit3D > HitPairList
art::InputTag fSpacePointProducerLabel
Data members to follow.
float getTimeTicks() const
std::vector< WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
float RMS() const
RMS of the hit shape, in tick units.
float getTimeToExecute(IHit3DBuilder::TimeValues index) const override
If monitoring, recover the time to execute a particular function.
Declaration of signal hit object.
std::vector< float > m_chiSquare3DVec
std::vector< float > m_overlapRangeVec
The data type to uniquely identify a Plane.
float chargeIntegral(float, float, float, int, int) const
Perform charge integration between limits.
const geo::WireID & WireID() const
std::vector< reco::ClusterHit2D > Hit2DVector
constexpr auto abs(T v)
Returns the absolute value of the argument.
CryostatID_t Cryostat
Index of cryostat.
~SpacePointHit3DBuilder()
Destructor.
WireID_t Wire
Index of the wire within its plane.
geo::WireID const & WireID() const
Initial tdc tick for hit.
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
std::vector< float > m_qualityMetricVec
void Hit3DBuilder(art::Event &evt, reco::HitPairList &hitPairList, RecobHitToPtrMap &) override
Given a set of recob hits, run DBscan to form 3D clusters.
const recob::Hit * getHit() const
IDparameter< geo::PlaneID > PlaneID
Member type of validated geo::PlaneID parameter.
bool isValid() const noexcept
void clear()
clear the tuple vectors before processing next event
Class managing the creation of a new recob::Hit object.
Helper functions to create a hit.
std::vector< float > m_deltaTimeVec
void produces(std::string const &instanceName={}, Persistable const persistable=Persistable::Yes)
void use_hits(std::unique_ptr< std::vector< recob::Hit >> &&srchits)
Uses the specified collection as data product.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
const geo::Geometry * fGeometry
void put_into(art::Event &)
Moves the data into the event.
Hit2DVector m_clusterHit2DMasterVec
T get(std::string const &key) const
A class handling a collection of hits and its associations.
SpacePointHit3DBuilder class definiton.
const Double32_t * XYZ() const
std::vector< int > m_smallIndexVec
std::vector< float > m_maxPullVec
TimeValues
enumerate the possible values for time checking if monitoring timing
The geometry of one entire detector, as served by art.
PlaneID_t Plane
Index of the plane within its TPC.
std::vector< float > m_smallChargeDiffVec
art::InputTag fHitProducerLabel
Definition of data types for geometry description.
IHit3DBuilder interface class definiton.
std::vector< float > m_maxSideVecVec
This provides an art tool interface definition for tools which construct 3D hits used in 3D clusterin...
std::vector< const reco::ClusterHit2D * > ClusterHit2DVec
virtual void produces(art::ProducesCollector &) override
Each algorithm may have different objects it wants "produced" so use this to let the top level produc...
float PeakTime() const
Time of the signal peak, in tick units.
float m_maxHit3DChiSquare
Provide ability to select hits based on "chi square".
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
SpacePointHit3DBuilder(fhicl::ParameterSet const &pset)
Constructor.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
std::vector< float > m_hitAsymmetryVec
std::vector< float > m_pairWireDistVec
int trigger_offset(DetectorClocksData const &data)
std::vector< float > m_overlapFractionVec
constexpr WireID()=default
Default constructor: an invalid TPC ID.
2D representation of charge deposited in the TDC/wire plane
TPCID_t TPC
Index of the TPC within its cryostat.
raw::ChannelID_t Channel() const
ID of the readout channel the hit was extracted from.
TTree * m_tupleTree
output analysis tree
std::unordered_map< const recob::Hit *, art::Ptr< recob::Hit >> RecobHitToPtrMap
Defines a structure mapping art representation to internal.
art framework interface to geometry description
std::vector< float > fTimeVector
std::vector< float > m_spacePointChargeVec
void configure(const fhicl::ParameterSet &) override
Interface for configuring the particular algorithm tool.
Signal from collection planes.
unsigned getStatusBits() const
void setStatusBit(unsigned bits) const