LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
lar_cluster3d::Cluster3D Class Reference

Definition of the Cluster3D class. More...

Inheritance diagram for lar_cluster3d::Cluster3D:
art::EDProducer art::ProducerBase art::Consumer art::EngineCreator art::ProductRegistryHelper

Classes

class  ArtOutputHandler
 

Public Types

using ModuleType = EDProducer
 
using WorkerType = WorkerT< EDProducer >
 
template<typename UserConfig , typename KeysToIgnore = void>
using Table = ProducerBase::Table< UserConfig, KeysToIgnore >
 

Public Member Functions

 Cluster3D (fhicl::ParameterSet const &pset)
 Constructor. More...
 
virtual ~Cluster3D ()
 Destructor. More...
 
void beginJob ()
 declare the standard art functions that we'll implement in this producer module More...
 
void endJob ()
 
void produce (art::Event &evt)
 
void reconfigure (fhicl::ParameterSet const &pset)
 
template<typename PROD , BranchType B = InEvent>
ProductID getProductID (std::string const &instanceName={}) const
 
template<typename PROD , BranchType B>
ProductID getProductID (ModuleDescription const &moduleDescription, std::string const &instanceName) const
 
bool modifiesEvent () const
 
template<typename T , BranchType = InEvent>
ProductToken< T > consumes (InputTag const &)
 
template<typename T , art::BranchType BT>
art::ProductToken< T > consumes (InputTag const &it)
 
template<typename T , BranchType = InEvent>
void consumesMany ()
 
template<typename Element , BranchType = InEvent>
ViewToken< Element > consumesView (InputTag const &)
 
template<typename T , art::BranchType BT>
art::ViewToken< T > consumesView (InputTag const &it)
 
template<typename T , BranchType = InEvent>
ProductToken< T > mayConsume (InputTag const &)
 
template<typename T , art::BranchType BT>
art::ProductToken< T > mayConsume (InputTag const &it)
 
template<typename T , BranchType = InEvent>
void mayConsumeMany ()
 
template<typename Element , BranchType = InEvent>
ViewToken< Element > mayConsumeView (InputTag const &)
 
template<typename T , art::BranchType BT>
art::ViewToken< T > mayConsumeView (InputTag const &it)
 
base_engine_tcreateEngine (seed_t seed)
 
base_engine_tcreateEngine (seed_t seed, std::string const &kind_of_engine_to_make)
 
base_engine_tcreateEngine (seed_t seed, std::string const &kind_of_engine_to_make, label_t const &engine_label)
 
seed_t get_seed_value (fhicl::ParameterSet const &pset, char const key[]="seed", seed_t const implicit_seed=-1)
 

Static Public Member Functions

static cet::exempt_ptr< Consumernon_module_context ()
 

Protected Member Functions

CurrentProcessingContext const * currentContext () const
 
void validateConsumedProduct (BranchType const bt, ProductInfo const &pi)
 
void prepareForJob (fhicl::ParameterSet const &pset)
 
void showMissingConsumes () const
 

Private Types

using IdxToPCAMap = std::map< size_t, const reco::PrincipalComponents * >
 Special routine to handle creating and saving space points & edges PCA points. More...
 

Private Member Functions

void PrepareEvent (const art::Event &evt)
 Event Preparation. More...
 
void InitializeMonitoring ()
 Initialize the internal monitoring. More...
 
void findTrackSeeds (art::Event &evt, reco::ClusterParameters &cluster, RecobHitToPtrMap &hitToPtrMap, std::vector< recob::Seed > &seedVec, art::Assns< recob::Seed, recob::Hit > &seedHitAssns) const
 An interface to the seed finding algorithm. More...
 
void splitClustersWithMST (reco::ClusterParameters &clusterParameters, reco::ClusterParametersList &clusterParametersList) const
 Attempt to split clusters by using a minimum spanning tree. More...
 
void splitClustersWithHough (reco::ClusterParameters &clusterParameters, reco::ClusterParametersList &clusterParametersList) const
 Attempt to split clusters using the output of the Hough Filter. More...
 
size_t ConvertToArtOutput (ArtOutputHandler &output, reco::ClusterParameters &clusterParameters, size_t pfParticleParent, RecobHitToPtrMap &hitToPtrMap, Hit3DToSPPtrMap &hit3DToSPPtrMap) const
 Produces the art output from all the work done in this producer module. More...
 
void MakeAndSaveSpacePoints (ArtOutputHandler &output, reco::HitPairListPtr &clusHitPairVector, RecobHitToPtrMap &hitToPtrMap, Hit3DToSPPtrMap &hit3DToSPPtrMap, int spacePointStart) const
 Special routine to handle creating and saving space points. More...
 
void MakeAndSaveVertexPoints (ArtOutputHandler &, dcel2d::VertexList &, dcel2d::HalfEdgeList &) const
 Special routine to handle creating and saving space points & edges associated to voronoi diagrams. More...
 
void MakeAndSavePCAPoints (ArtOutputHandler &, const reco::PrincipalComponents &, IdxToPCAMap &) const
 
size_t FindAndStoreDaughters (ArtOutputHandler &output, reco::ClusterParameters &clusterParameters, size_t pfParticleParent, IdxToPCAMap &idxToPCAMap, RecobHitToPtrMap &hitToPtrMap, Hit3DToSPPtrMap &hit3DToSPPtrMap) const
 This will produce art output for daughters noting that it needs to be done recursively. More...
 
void ProduceArtClusters (ArtOutputHandler &output, reco::HitPairList &hitPairList, reco::ClusterParametersList &clusterParametersList, RecobHitToPtrMap &hitToPtrMap) const
 Top level output routine, allows checking cluster status. More...
 
bool aParallelHitsCluster (const reco::PrincipalComponents &pca) const
 There are several places we will want to know if a candidate cluster is a "parallel hits" type of cluster so encapsulate that here. More...
 
size_t countUltimateDaughters (reco::ClusterParameters &clusterParameters) const
 Count number of end of line daughters. More...
 

Private Attributes

bool m_enableMonitoring
 Turn on monitoring of this algorithm. More...
 
float m_parallelHitsCosAng
 Cut for PCA 3rd axis angle to X axis. More...
 
float m_parallelHitsTransWid
 Cut on transverse width of cluster (PCA 2nd eigenvalue) More...
 
TTree * m_pRecoTree
 
int m_run
 
int m_event
 
int m_hits
 Keeps track of the number of hits seen. More...
 
float m_totalTime
 Keeps track of total execution time. More...
 
float m_artHitsTime
 Keeps track of time to recover hits. More...
 
float m_makeHitsTime
 Keeps track of time to build 3D hits. More...
 
float m_buildNeighborhoodTime
 Keeps track of time to build epsilon neighborhood. More...
 
float m_dbscanTime
 Keeps track of time to run DBScan. More...
 
float m_pathFindingTime
 Keeps track of the path finding time. More...
 
float m_finishTime
 Keeps track of time to run output module. More...
 
std::string m_spacePointInstance
 Special instance name for vertex points. More...
 
geo::Geometrym_geometry
 pointer to the Geometry service More...
 
const detinfo::DetectorPropertiesm_detector
 Pointer to the detector properties. More...
 
std::unique_ptr< lar_cluster3d::IHit3DBuilderm_hit3DBuilderAlg
 Builds the 3D hits to operate on. More...
 
std::unique_ptr< lar_cluster3d::IClusterAlgm_clusterAlg
 Algorithm to do 3D space point clustering. More...
 
std::unique_ptr< lar_cluster3d::IClusterModAlgm_clusterMergeAlg
 Algorithm to do cluster merging. More...
 
std::unique_ptr< lar_cluster3d::IClusterModAlgm_clusterPathAlg
 Algorithm to do cluster path finding. More...
 
ClusterParamsBuilder m_clusterBuilder
 Common cluster builder tool. More...
 
PrincipalComponentsAlg m_pcaAlg
 Principal Components algorithm. More...
 
SkeletonAlg m_skeletonAlg
 Skeleton point finder. More...
 
HoughSeedFinderAlg m_seedFinderAlg
 Seed finder. More...
 
PCASeedFinderAlg m_pcaSeedFinderAlg
 Use PCA axis to find seeds. More...
 
ParallelHitsSeedFinderAlg m_parallelHitsAlg
 Deal with parallel hits clusters. More...
 

Detailed Description

Definition of the Cluster3D class.

Definition at line 109 of file Cluster3D_module.cc.

Member Typedef Documentation

using lar_cluster3d::Cluster3D::IdxToPCAMap = std::map<size_t,const reco::PrincipalComponents*>
private

Special routine to handle creating and saving space points & edges PCA points.

Parameters
outputthe object containting the art output
clusterParamsListList of clusters to get PCA's from

Definition at line 330 of file Cluster3D_module.cc.

using art::EDProducer::ModuleType = EDProducer
inherited

Definition at line 34 of file EDProducer.h.

template<typename UserConfig , typename KeysToIgnore = void>
using art::EDProducer::Table = ProducerBase::Table<UserConfig, KeysToIgnore>
inherited

Definition at line 43 of file EDProducer.h.

using art::EDProducer::WorkerType = WorkerT<EDProducer>
inherited

Definition at line 35 of file EDProducer.h.

Constructor & Destructor Documentation

lar_cluster3d::Cluster3D::Cluster3D ( fhicl::ParameterSet const &  pset)

Constructor.

Parameters
pset- reference to the parameters used by this module and its algorithms

Definition at line 433 of file Cluster3D_module.cc.

References m_spacePointInstance, and reconfigure().

433  :
434  m_clusterBuilder(pset.get<fhicl::ParameterSet>("ClusterParamsBuilder")),
435  m_pcaAlg(pset.get<fhicl::ParameterSet>("PrincipalComponentsAlg")),
436  m_skeletonAlg(pset.get<fhicl::ParameterSet>("SkeletonAlg")),
437  m_seedFinderAlg(pset.get<fhicl::ParameterSet>("SeedFinderAlg")),
438  m_pcaSeedFinderAlg(pset.get<fhicl::ParameterSet>("PCASeedFinderAlg")),
439  m_parallelHitsAlg(pset.get<fhicl::ParameterSet>("ParallelHitsAlg"))
440 {
441  this->reconfigure(pset);
442 
443  m_spacePointInstance = "Voronoi";
444 
445  produces< std::vector<recob::PCAxis>>();
446  produces< std::vector<recob::PFParticle>>();
447  produces< std::vector<recob::Cluster>>();
448  produces< std::vector<recob::SpacePoint>>();
449  produces< std::vector<recob::SpacePoint>>(m_spacePointInstance);
450  produces< std::vector<recob::Seed>>();
451  produces< std::vector<recob::Edge>>();
452  produces< std::vector<recob::Edge>>(m_spacePointInstance);
453  produces< art::Assns<recob::PFParticle, recob::PCAxis>>();
454  produces< art::Assns<recob::PFParticle, recob::Cluster>>();
455  produces< art::Assns<recob::PFParticle, recob::SpacePoint>>();
456  produces< art::Assns<recob::PFParticle, recob::Seed>>();
457  produces< art::Assns<recob::PFParticle, recob::Edge>>();
458  produces< art::Assns<recob::Seed, recob::Hit>>();
459  produces< art::Assns<recob::Cluster, recob::Hit>>();
460  produces< art::Assns<recob::SpacePoint, recob::Hit>>();
461  produces< art::Assns<recob::Edge, recob::SpacePoint>>();
462 }
SkeletonAlg m_skeletonAlg
Skeleton point finder.
std::string m_spacePointInstance
Special instance name for vertex points.
HoughSeedFinderAlg m_seedFinderAlg
Seed finder.
PCASeedFinderAlg m_pcaSeedFinderAlg
Use PCA axis to find seeds.
ParallelHitsSeedFinderAlg m_parallelHitsAlg
Deal with parallel hits clusters.
ClusterParamsBuilder m_clusterBuilder
Common cluster builder tool.
void reconfigure(fhicl::ParameterSet const &pset)
PrincipalComponentsAlg m_pcaAlg
Principal Components algorithm.
lar_cluster3d::Cluster3D::~Cluster3D ( )
virtual

Destructor.

Definition at line 466 of file Cluster3D_module.cc.

467 {
468 }

Member Function Documentation

bool lar_cluster3d::Cluster3D::aParallelHitsCluster ( const reco::PrincipalComponents pca) const
inlineprivate

There are several places we will want to know if a candidate cluster is a "parallel hits" type of cluster so encapsulate that here.

Parameters
pcaThe Principal Components Analysis parameters for the cluster

Definition at line 370 of file Cluster3D_module.cc.

References countUltimateDaughters(), reco::PrincipalComponents::getEigenValues(), reco::PrincipalComponents::getEigenVectors(), m_parallelHitsCosAng, and m_parallelHitsTransWid.

Referenced by findTrackSeeds().

371  {
372  return fabs(pca.getEigenVectors()[2][0]) > m_parallelHitsCosAng && 3. * sqrt(pca.getEigenValues()[1]) > m_parallelHitsTransWid;
373  }
float m_parallelHitsTransWid
Cut on transverse width of cluster (PCA 2nd eigenvalue)
float m_parallelHitsCosAng
Cut for PCA 3rd axis angle to X axis.
const float * getEigenValues() const
Definition: Cluster3D.h:226
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:227
void lar_cluster3d::Cluster3D::beginJob ( )
virtual

declare the standard art functions that we'll implement in this producer module

beginJob will be tasked with initializing monitoring, in necessary, but also to init the geometry and detector services (and this probably needs to go in a "beginEvent" method?)

Reimplemented from art::EDProducer.

Definition at line 492 of file Cluster3D_module.cc.

References InitializeMonitoring(), m_detector, m_enableMonitoring, and m_geometry.

493 {
498  if (m_enableMonitoring)
499  this->InitializeMonitoring();
500 
502 
503  m_geometry = &*geometry;
504  m_detector = lar::providerFrom<detinfo::DetectorPropertiesService>();
505 }
void InitializeMonitoring()
Initialize the internal monitoring.
const detinfo::DetectorProperties * m_detector
Pointer to the detector properties.
geo::Geometry * m_geometry
pointer to the Geometry service
bool m_enableMonitoring
Turn on monitoring of this algorithm.
template<typename T , BranchType = InEvent>
ProductToken<T> art::Consumer::consumes ( InputTag const &  )
inherited
template<typename T , art::BranchType BT>
art::ProductToken<T> art::Consumer::consumes ( InputTag const &  it)
inherited

Definition at line 147 of file Consumer.h.

References art::InputTag::instance(), art::InputTag::label(), and art::InputTag::process().

148 {
149  if (!moduleContext_)
150  return ProductToken<T>::invalid();
151 
152  consumables_[BT].emplace_back(ConsumableType::Product,
153  TypeID{typeid(T)},
154  it.label(),
155  it.instance(),
156  it.process());
157  return ProductToken<T>{it};
158 }
static ProductToken< T > invalid()
Definition: ProductToken.h:47
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
template<typename T , art::BranchType BT>
void art::Consumer::consumesMany ( )
inherited

Definition at line 162 of file Consumer.h.

163 {
164  if (!moduleContext_)
165  return;
166 
167  consumables_[BT].emplace_back(ConsumableType::Many, TypeID{typeid(T)});
168 }
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
template<typename Element , BranchType = InEvent>
ViewToken<Element> art::Consumer::consumesView ( InputTag const &  )
inherited
template<typename T , art::BranchType BT>
art::ViewToken<T> art::Consumer::consumesView ( InputTag const &  it)
inherited

Definition at line 172 of file Consumer.h.

References art::InputTag::instance(), art::InputTag::label(), and art::InputTag::process().

173 {
174  if (!moduleContext_)
175  return ViewToken<T>::invalid();
176 
177  consumables_[BT].emplace_back(ConsumableType::ViewElement,
178  TypeID{typeid(T)},
179  it.label(),
180  it.instance(),
181  it.process());
182  return ViewToken<T>{it};
183 }
static ViewToken< Element > invalid()
Definition: ProductToken.h:75
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
size_t lar_cluster3d::Cluster3D::ConvertToArtOutput ( ArtOutputHandler output,
reco::ClusterParameters clusterParameters,
size_t  pfParticleParent,
RecobHitToPtrMap hitToPtrMap,
Hit3DToSPPtrMap hit3DToSPPtrMap 
) const
private

Produces the art output from all the work done in this producer module.

Parameters
outputthe object containting the art output
clusterParametersCluster info to output (in internal format)
pfParticleParentThe parent ID reference for the output PFParticle
hitToPtrMapThis maps our Cluster2D hits back to art Ptr's to reco Hits

Definition at line 1289 of file Cluster3D_module.cc.

References lar_cluster3d::Cluster3D::ArtOutputHandler::artClusterVector, lar_cluster3d::Cluster3D::ArtOutputHandler::artEdgeVector, lar_cluster3d::Cluster3D::ArtOutputHandler::artPCAxisVector, lar_cluster3d::Cluster3D::ArtOutputHandler::artPFParticleVector, lar_cluster3d::Cluster3D::ArtOutputHandler::artSeedVector, lar_cluster3d::Cluster3D::ArtOutputHandler::artSpacePointVector, reco::PrincipalComponents::getAveHitDoca(), reco::PrincipalComponents::getAvePosition(), reco::ClusterParameters::getBestEdgeList(), reco::ClusterParameters::getClusterParams(), reco::PrincipalComponents::getEigenValues(), reco::PrincipalComponents::getEigenVectors(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), reco::PrincipalComponents::getNumHitsUsed(), reco::ClusterParameters::getSkeletonPCA(), reco::PrincipalComponents::getSvdOK(), detinfo::DetectorProperties::GetXTicksCoefficient(), cluster::ClusterParamsImportWrapper< Algo >::ImportHits(), geo::kUnknown, m_detector, reco::RecobClusterParameters::m_endTime, reco::RecobClusterParameters::m_endWire, reco::RecobClusterParameters::m_hitVector, reco::RecobClusterParameters::m_sigmaEndTime, reco::RecobClusterParameters::m_sigmaStartTime, reco::RecobClusterParameters::m_startTime, reco::RecobClusterParameters::m_startWire, reco::RecobClusterParameters::m_view, reco::ClusterHit3D::MADESPACEPOINT, lar_cluster3d::Cluster3D::ArtOutputHandler::makeClusterHitAssns(), lar_cluster3d::Cluster3D::ArtOutputHandler::makePFPartClusterAssns(), lar_cluster3d::Cluster3D::ArtOutputHandler::makePFPartEdgeAssns(), lar_cluster3d::Cluster3D::ArtOutputHandler::makePFPartPCAAssns(), lar_cluster3d::Cluster3D::ArtOutputHandler::makePFPartSeedAssns(), lar_cluster3d::Cluster3D::ArtOutputHandler::makePFPartSpacePointAssns(), lar_cluster3d::Cluster3D::ArtOutputHandler::makeSpacePointHitAssns(), reco::ClusterHit3D::REJECTEDHIT, and recob::Cluster::Sentry.

Referenced by FindAndStoreDaughters(), and ProduceArtClusters().

1294 {
1295 
1296  // prepare the algorithm to compute the cluster characteristics;
1297  // we use the "standard" one here, except that we override selected items
1298  // (so, thanks to metaprogramming, we finally have wrappers of wrappers);
1299  // configuration would happen here, but we are using the default
1300  // configuration for that algorithm
1302 
1304 
1305  // It should be straightforward at this point to transfer information from our vector of clusters
1306  // to the larsoft objects... of course we still have some work to do first, in particular to
1307  // find the candidate seeds and their seed hits
1308 
1309  // We keep track of 2 PCA axes, the first is the "full" PCA run over all the 3D hits in the
1310  // candidate cluster. The second will be that derived from just using the "skeleton" hits.
1311  // Make a copy of the full PCA to keep that, then get a reference for the skeleton PCA
1312  reco::PrincipalComponents& fullPCA = clusterParameters.getFullPCA();
1313  reco::PrincipalComponents& skeletonPCA = clusterParameters.getSkeletonPCA();
1314 
1315  // As tracks become more parallel to the wire plane the number of "ambiguous" 3D hits can increase
1316  // rapidly. Now that we have more information we can go back through these hits and do a better job
1317  // selecting "the right ones". Here we call the "medial skeleton" algorithm which uses a modification
1318  // of a standard medial skeleton procedure to get the 3D hits we want
1319  // But note that even this is hopeless in the worst case and, in fact, it can be a time waster
1320  // So bypass when you recognize that condition
1321  /*
1322  if (!aParallelHitsCluster(fullPCA))
1323  {
1324  int nSkeletonPoints = m_skeletonAlg.FindMedialSkeleton(clusterParameters.getHitPairListPtr());
1325 
1326  // If enough skeleton points then rerun pca with only those
1327  if (nSkeletonPoints > 10)
1328  {
1329  // Now rerun the principal components axis on just those points
1330  m_pcaAlg.PCAAnalysis_3D(clusterParameters.getHitPairListPtr(), skeletonPCA, true);
1331 
1332  // If there was a failure (can that happen?) then restore the full PCA
1333  if (!skeletonPCA.getSvdOK()) skeletonPCA = fullPCA;
1334  }
1335 
1336  // Here we can try to handle a specific case. It can happen that two tracks (think CR muons here) pass so
1337  // close together at some point to get merged into one cluster. Now that we have skeletonized the hits and
1338  // have run the PCA on the skeleton points we can try to divide these two tracks. The signature will be that
1339  // their are a large number of total hits, that the PCA will have a large spread in two dimensions. The
1340  // spread in the third dimension will be an indicator of the actual separation between the two tracks
1341  // which we might try to exploit in the actual algorithm.
1342  // hardwire for now to see what is going on...
1343  if (skeletonPCA.getNumHitsUsed() > 1000 && skeletonPCA.getEigenValues()[1] > 100. && fabs(skeletonPCA.getEigenVectors()[2][0]) < m_parallelHitsCosAng)
1344  {
1345  mf::LogDebug("Cluster3D") << "--> Detected crossed axes!! Total # hits: " << fullPCA.getNumHitsUsed() <<
1346  "\n Skeleton PCA # hits: " << skeletonPCA.getNumHitsUsed() << ", eigenValues: " <<
1347  skeletonPCA.getEigenValues()[0] << ", " <<skeletonPCA.getEigenValues()[1] << ", " <<skeletonPCA.getEigenValues()[2] << std::endl;
1348 
1349  splitClustersWithHough(clusterParameters, clusterParametersList);
1350  }
1351  }
1352  */
1353  size_t clusterStart = output.artClusterVector->size();
1354 
1355  // Start loop over views to build out the hit lists and the 2D cluster objects
1356  for(reco::PlaneToClusterParamsMap::const_iterator planeItr = clusterParameters.getClusterParams().begin(); planeItr != clusterParameters.getClusterParams().end(); planeItr++)
1357  {
1358  const reco::RecobClusterParameters& clusParams = planeItr->second;
1359 
1360  // Protect against a missing view
1361  if (clusParams.m_view == geo::kUnknown) continue;
1362 
1363  // We love looping. In this case, our list of hits is comprised of "ClusterHits" and we need to get a RecobHitVector instead...
1364  RecobHitVector recobHits;
1365 
1366  for(reco::ClusterHit2DVec::const_iterator hitItr = clusParams.m_hitVector.begin(); hitItr != clusParams.m_hitVector.end(); hitItr++)
1367  {
1368  art::Ptr<recob::Hit> hitPtr = hitToPtrMap[&(*hitItr)->getHit()];
1369  recobHits.push_back(hitPtr);
1370  }
1371 
1372  // And sorting! Sorting is good for the mind, soul and body
1373  // ooopsss... don't do this else event display will look funky
1374  // std::sort(recobHits.begin(), recobHits.end());
1375 
1376  // Get the tdc/wire slope... from the unit vector...
1377  double startWire(clusParams.m_startWire);
1378  double endWire(clusParams.m_endWire);
1379  double startTime(clusParams.m_startTime);
1380  double endTime(clusParams.m_endTime);
1381 
1382  // plane ID is not a part of clusParams... get the one from the first hit
1383  geo::PlaneID plane; // invalid by default
1384  if (!recobHits.empty())
1385  plane = recobHits.front()->WireID().planeID();
1386 
1387  // feed the algorithm with all the cluster hits
1388  ClusterParamAlgo.ImportHits(recobHits);
1389 
1390  // create the recob::Cluster directly in the vector
1391  cluster::ClusterCreator artCluster(
1392  ClusterParamAlgo, // algo
1393  startWire, // start_wire
1394  0., // sigma_start_wire
1395  startTime, // start_tick
1396  clusParams.m_sigmaStartTime, // sigma_start_tick
1397  endWire, // end_wire
1398  0., // sigma_end_wire,
1399  endTime, // end_tick
1400  clusParams.m_sigmaEndTime, // sigma_end_tick
1401  output.artClusterVector->size(), // ID
1402  clusParams.m_view, // view
1403  plane, // plane
1404  recob::Cluster::Sentry // sentry
1405  );
1406 
1407  output.artClusterVector->emplace_back(artCluster.move());
1408 
1409  output.makeClusterHitAssns(recobHits);
1410  }
1411 
1412  // Last, let's try to get seeds for tracking..
1413  // Keep track of how many we have so far
1414  size_t numSeedsStart = output.artSeedVector->size();
1415 
1416  // Call the magical algorith to do the dirty work
1417  // findTrackSeeds(evt, clusterParameters, hitToPtrMap, *artSeedVector, *artSeedHitAssociations);
1418 
1419  // Deal with converting the Hit Pairs to art
1420  // Recover the hit pairs and start looping! Love to loop!
1421  reco::HitPairListPtr& clusHitPairVector = clusterParameters.getHitPairListPtr();
1422  // reco::HitPairListPtr& clusHitPairVector = clusterParameters.getBestHitPairListPtr();
1423 
1424  // Keep track of current start for space points
1425  int spacePointStart(output.artSpacePointVector->size());
1426 
1427  // Copy these hits to the vector to be stored with the event
1428  for (auto& hitPair : clusHitPairVector)
1429  {
1430  // Don't make space point if this hit was "rejected"
1431  if (hitPair->bitsAreSet(reco::ClusterHit3D::REJECTEDHIT)) continue;
1432 
1433  double chisq = hitPair->getHitChiSquare(); // secret handshake...
1434 
1435 // if ( hitPair->bitsAreSet(reco::ClusterHit3D::SKELETONHIT) && !hitPair->bitsAreSet(reco::ClusterHit3D::EDGEHIT)) chisq = -1.; // pure skeleton point
1436 // else if (!hitPair->bitsAreSet(reco::ClusterHit3D::SKELETONHIT) && hitPair->bitsAreSet(reco::ClusterHit3D::EDGEHIT)) chisq = -2.; // pure edge point
1437 // else if ( hitPair->bitsAreSet(reco::ClusterHit3D::SKELETONHIT) && hitPair->bitsAreSet(reco::ClusterHit3D::EDGEHIT)) chisq = -3.; // skeleton and edge point
1438 //
1439 // if (hitPair->bitsAreSet(reco::ClusterHit3D::SEEDHIT) ) chisq = -4.; // Seed point
1440 //
1441 // if ((hitPair->getStatusBits() & 0x7) != 0x7) chisq = -10.;
1442 
1443  // Mark this hit pair as in use
1444  hitPair->setStatusBit(reco::ClusterHit3D::MADESPACEPOINT);
1445 
1446  // Create and store the space point
1447  size_t spacePointID = output.artSpacePointVector->size();
1448  double spacePointPos[] = {hitPair->getPosition()[0],hitPair->getPosition()[1],hitPair->getPosition()[2]};
1449  double spacePointErr[] = {m_detector->GetXTicksCoefficient() * hitPair->getSigmaPeakTime(), 0., 0., 0.15, 0., 0.15};
1450  output.artSpacePointVector->push_back(recob::SpacePoint(spacePointPos, spacePointErr, chisq, output.artSpacePointVector->size()));
1451 
1452  // Update mapping
1453  hit3DToSPPtrMap[hitPair] = spacePointID;
1454 
1455  // space point hits associations
1456  RecobHitVector recobHits;
1457 
1458  for(const auto& hit : hitPair->getHits())
1459  {
1460  if (!hit) continue;
1461  art::Ptr<recob::Hit> hitPtr = hitToPtrMap[&hit->getHit()];
1462  recobHits.push_back(hitPtr);
1463  }
1464 
1465  if (!recobHits.empty()) output.makeSpacePointHitAssns(recobHits);
1466  }
1467 
1468  // Build the edges now
1469  size_t edgeStart(output.artEdgeVector->size());
1470 
1471  for(const auto& edge : clusterParameters.getBestEdgeList())
1472  output.artEdgeVector->emplace_back(std::get<2>(edge), hit3DToSPPtrMap[std::get<0>(edge)], hit3DToSPPtrMap[std::get<1>(edge)], output.artEdgeVector->size());
1473 
1474  // Empty daughter vector for now
1475  std::vector<size_t> nullVector;
1476  size_t pfParticleIdx(output.artPFParticleVector->size());
1477 
1478  recob::PFParticle pfParticle(13, pfParticleIdx, pfParticleParent, nullVector);
1479  output.artPFParticleVector->push_back(pfParticle);
1480 
1481  // Look at making the PCAxis and associations - for both the skeleton (the first) and the full
1482  // First need some float to double conversion containers
1483  recob::PCAxis::EigenVectors eigenVecs;
1484  double eigenVals[] = {0.,0.,0.};
1485  double avePosition[] = {0.,0.,0.};
1486 
1487  eigenVecs.resize(3);
1488 
1489  for(size_t outerIdx = 0; outerIdx < 3; outerIdx++)
1490  {
1491  avePosition[outerIdx] = skeletonPCA.getAvePosition()[outerIdx];
1492  eigenVals[outerIdx] = skeletonPCA.getEigenValues()[outerIdx];
1493 
1494  eigenVecs[outerIdx].resize(3);
1495 
1496  for(size_t innerIdx = 0; innerIdx < 3; innerIdx++) eigenVecs[outerIdx][innerIdx] = skeletonPCA.getEigenVectors()[outerIdx][innerIdx];
1497  }
1498 
1499 
1500  recob::PCAxis skelPcAxis(skeletonPCA.getSvdOK(),
1501  skeletonPCA.getNumHitsUsed(),
1502  eigenVals, //skeletonPCA.getEigenValues(),
1503  eigenVecs, //skeletonPCA.getEigenVectors(),
1504  avePosition, //skeletonPCA.getAvePosition(),
1505  skeletonPCA.getAveHitDoca(),
1506  output.artPCAxisVector->size());
1507 
1508  output.artPCAxisVector->push_back(skelPcAxis);
1509 
1510  for(size_t outerIdx = 0; outerIdx < 3; outerIdx++)
1511  {
1512  avePosition[outerIdx] = fullPCA.getAvePosition()[outerIdx];
1513  eigenVals[outerIdx] = fullPCA.getEigenValues()[outerIdx];
1514 
1515  for(size_t innerIdx = 0; innerIdx < 3; innerIdx++) eigenVecs[outerIdx][innerIdx] = fullPCA.getEigenVectors()[outerIdx][innerIdx];
1516  }
1517 
1518  recob::PCAxis fullPcAxis(fullPCA.getSvdOK(),
1519  fullPCA.getNumHitsUsed(),
1520  eigenVals, //fullPCA.getEigenValues(),
1521  eigenVecs, //fullPCA.getEigenVectors(),
1522  avePosition, //fullPCA.getAvePosition(),
1523  fullPCA.getAveHitDoca(),
1524  output.artPCAxisVector->size());
1525 
1526  output.artPCAxisVector->push_back(fullPcAxis);
1527 
1528  // Create associations to the PFParticle
1529  output.makePFPartPCAAssns();
1530  output.makePFPartSeedAssns(numSeedsStart);
1531  output.makePFPartClusterAssns(clusterStart);
1532  output.makePFPartSpacePointAssns(spacePointStart);
1533  output.makePFPartEdgeAssns(edgeStart);
1534 
1535  return pfParticleIdx;
1536 }
bool getSvdOK() const
Definition: Cluster3D.h:224
Class managing the creation of a new recob::Cluster object.
Unknown view.
Definition: geo_types.h:83
reco::PrincipalComponents & getSkeletonPCA()
Definition: Cluster3D.h:406
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Hit has been rejected for any reason.
Definition: Cluster3D.h:92
reco::EdgeList & getBestEdgeList()
Definition: Cluster3D.h:409
const float * getAvePosition() const
Definition: Cluster3D.h:228
int getNumHitsUsed() const
Definition: Cluster3D.h:225
A utility class used in construction of 3D clusters.
Definition: Cluster3D.h:280
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:404
reco::PlaneToClusterParamsMap & getClusterParams()
Definition: Cluster3D.h:402
static const SentryArgument_t Sentry
An instance of the sentry object.
Definition: Cluster.h:182
intermediate_table::const_iterator const_iterator
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:405
virtual double GetXTicksCoefficient(int t, int c) const =0
const detinfo::DetectorProperties * m_detector
Pointer to the detector properties.
Wrapper for ClusterParamsAlgBase objects to accept diverse input.
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:315
Detector simulation of raw signals on wires.
Hierarchical representation of particle flow.
Definition: PFParticle.h:44
const float * getEigenValues() const
Definition: Cluster3D.h:226
const float getAveHitDoca() const
Definition: Cluster3D.h:229
void ImportHits(Iter begin, Iter end)
Calls SetHits() with the hits in the sequence.
Hit has been made into Space Point.
Definition: Cluster3D.h:96
ClusterHit2DVec m_hitVector
Definition: Cluster3D.h:307
Algorithm collection class computing cluster parameters.
std::vector< std::vector< double > > EigenVectors
Definition: PCAxis.h:29
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:227
std::vector< art::Ptr< recob::Hit >> RecobHitVector
size_t lar_cluster3d::Cluster3D::countUltimateDaughters ( reco::ClusterParameters clusterParameters) const
private

Count number of end of line daughters.

Parameters
clusterParamsinput cluster parameters to look at

Definition at line 1251 of file Cluster3D_module.cc.

References reco::ClusterParameters::daughterList().

Referenced by aParallelHitsCluster(), and ProduceArtClusters().

1252 {
1253  size_t localCount(0);
1254 
1255  if (!clusterParameters.daughterList().empty())
1256  {
1257  for(auto& clusterParams : clusterParameters.daughterList())
1258  localCount += countUltimateDaughters(clusterParams);
1259  }
1260  else localCount++;
1261 
1262  return localCount;
1263 }
ClusterParametersList & daughterList()
Definition: Cluster3D.h:378
size_t countUltimateDaughters(reco::ClusterParameters &clusterParameters) const
Count number of end of line daughters.
EngineCreator::base_engine_t & EngineCreator::createEngine ( seed_t  seed,
std::string const &  kind_of_engine_to_make 
)
inherited

Definition at line 32 of file EngineCreator.cc.

References art::EngineCreator::rng().

34 {
35  return rng()->createEngine(
36  placeholder_schedule_id(), seed, kind_of_engine_to_make);
37 }
long seed
Definition: chem4.cc:68
static art::ServiceHandle< art::RandomNumberGenerator > & rng()
EngineCreator::base_engine_t & EngineCreator::createEngine ( seed_t  seed,
std::string const &  kind_of_engine_to_make,
label_t const &  engine_label 
)
inherited

Definition at line 40 of file EngineCreator.cc.

References art::EngineCreator::rng().

43 {
44  return rng()->createEngine(
45  placeholder_schedule_id(), seed, kind_of_engine_to_make, engine_label);
46 }
long seed
Definition: chem4.cc:68
static art::ServiceHandle< art::RandomNumberGenerator > & rng()
CurrentProcessingContext const * art::EDProducer::currentContext ( ) const
protectedinherited

Definition at line 120 of file EDProducer.cc.

References art::EDProducer::current_context_.

121  {
122  return current_context_.get();
123  }
CPC_exempt_ptr current_context_
Definition: EDProducer.h:116
void lar_cluster3d::Cluster3D::endJob ( )
virtual

Reimplemented from art::EDProducer.

Definition at line 509 of file Cluster3D_module.cc.

510 {
511 }
size_t lar_cluster3d::Cluster3D::FindAndStoreDaughters ( ArtOutputHandler output,
reco::ClusterParameters clusterParameters,
size_t  pfParticleParent,
IdxToPCAMap idxToPCAMap,
RecobHitToPtrMap hitToPtrMap,
Hit3DToSPPtrMap hit3DToSPPtrMap 
) const
private

This will produce art output for daughters noting that it needs to be done recursively.

Parameters
outputthe object containting the art output
clusterParametersCluster info to output (in internal format)
pfParticleParentThe parent ID reference for the output PFParticle
daughterListList of PFParticle indices for stored daughters
hitToPtrMapThis maps our Cluster2D hits back to art Ptr's to reco Hits

Definition at line 1265 of file Cluster3D_module.cc.

References ConvertToArtOutput(), reco::ClusterParameters::daughterList(), and reco::ClusterParameters::getFullPCA().

Referenced by ProduceArtClusters().

1271 {
1272  // This is a recursive routine, we keep calling ourself as long as the daughter list is non empty
1273  if (!clusterParameters.daughterList().empty())
1274  {
1275  for(auto& clusterParams : clusterParameters.daughterList())
1276  FindAndStoreDaughters(output, clusterParams, pfParticleParent, idxToPCAMap, hitToPtrMap, hit3DToSPPtrMap);
1277  }
1278  // Otherwise we want to store the information
1279  else
1280  {
1281  size_t daughterIdx = ConvertToArtOutput(output, clusterParameters, pfParticleParent, hitToPtrMap, hit3DToSPPtrMap);
1282 
1283  idxToPCAMap[daughterIdx] = &clusterParameters.getFullPCA();
1284  }
1285 
1286  return idxToPCAMap.size();
1287 }
size_t FindAndStoreDaughters(ArtOutputHandler &output, reco::ClusterParameters &clusterParameters, size_t pfParticleParent, IdxToPCAMap &idxToPCAMap, RecobHitToPtrMap &hitToPtrMap, Hit3DToSPPtrMap &hit3DToSPPtrMap) const
This will produce art output for daughters noting that it needs to be done recursively.
ClusterParametersList & daughterList()
Definition: Cluster3D.h:378
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:405
size_t ConvertToArtOutput(ArtOutputHandler &output, reco::ClusterParameters &clusterParameters, size_t pfParticleParent, RecobHitToPtrMap &hitToPtrMap, Hit3DToSPPtrMap &hit3DToSPPtrMap) const
Produces the art output from all the work done in this producer module.
void lar_cluster3d::Cluster3D::findTrackSeeds ( art::Event evt,
reco::ClusterParameters cluster,
RecobHitToPtrMap hitToPtrMap,
std::vector< recob::Seed > &  seedVec,
art::Assns< recob::Seed, recob::Hit > &  seedHitAssns 
) const
private

An interface to the seed finding algorithm.

Parameters
evtthe ART event
clusterstructure of information representing a single cluster
hitToPtrMapThis maps our Cluster2D hits back to art Ptr's to reco Hits
seedVecthe output vector of candidate seeds
seedHitAssnsthe associations between the seeds and the 2D hits making them

This method provides an interface to various algorithms for finding candiate recob::Seed objects and, as well, their candidate related seed hits

Definition at line 631 of file Cluster3D_module.cc.

References aParallelHitsCluster(), lar_cluster3d::SkeletonAlg::AverageSkeletonPositions(), util::CreateAssn(), lar_cluster3d::HoughSeedFinderAlg::findTrackSeeds(), lar_cluster3d::PCASeedFinderAlg::findTrackSeeds(), lar_cluster3d::ParallelHitsSeedFinderAlg::findTrackSeeds(), reco::PrincipalComponents::getEigenValues(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), lar_cluster3d::SkeletonAlg::GetSkeletonHits(), reco::ClusterParameters::getSkeletonPCA(), m_parallelHitsAlg, m_pcaSeedFinderAlg, m_seedFinderAlg, and m_skeletonAlg.

636 {
642  // Make sure we are using the right pca
643  reco::PrincipalComponents& fullPCA = cluster.getFullPCA();
644  reco::PrincipalComponents& skeletonPCA = cluster.getSkeletonPCA();
645  reco::HitPairListPtr& hitPairListPtr = cluster.getHitPairListPtr();
646  reco::HitPairListPtr skeletonListPtr;
647 
648  // We want to work with the "skeleton" hits so first step is to call the algorithm to
649  // recover only these hits from the entire input collection
650  m_skeletonAlg.GetSkeletonHits(hitPairListPtr, skeletonListPtr);
651 
652  // Skeleton hits are nice but we can do better if we then make a pass through to "average"
653  // the skeleton hits position in the Y-Z plane
654  m_skeletonAlg.AverageSkeletonPositions(skeletonListPtr);
655 
656  SeedHitPairListPairVec seedHitPairVec;
657 
658  // Some combination of the elements below will be used to determine which seed finding algorithm
659  // to pursue below
660  float eigenVal0 = 3. * sqrt(skeletonPCA.getEigenValues()[0]);
661  float eigenVal1 = 3. * sqrt(skeletonPCA.getEigenValues()[1]);
662  float eigenVal2 = 3. * sqrt(skeletonPCA.getEigenValues()[2]);
663  float transRMS = sqrt(std::pow(eigenVal1,2) + std::pow(eigenVal2,2));
664 
665  bool foundGoodSeed(false);
666 
667  // Choose a method for finding the seeds based on the PCA that was run...
668  // Currently we have an ad hoc if-else block which I hope will be improved soon!
669  if (aParallelHitsCluster(fullPCA))
670  {
671  // In this case we have a track moving relatively parallel to the wire plane with lots of
672  // ambiguous 3D hits. Your best bet here is to use the "parallel hits" algorithm to get the
673  // best axis and seeds
674  // This algorithm does not fail (foundGoodSeed will always return true)
675  foundGoodSeed = m_parallelHitsAlg.findTrackSeeds(hitPairListPtr, skeletonPCA, seedHitPairVec);
676  }
677  else if (eigenVal0 > 40. && transRMS < 5.)
678  {
679  // If the input cluster is relatively "straight" then chances are it is a single straight track,
680  // probably a CR muon, and we can simply use the PCA to determine the seed
681  // This algorithm will check both "ends" of the input hits and if the angles become inconsistent
682  // then it will "fail"
683  foundGoodSeed = m_pcaSeedFinderAlg.findTrackSeeds(skeletonListPtr, skeletonPCA, seedHitPairVec);
684  }
685 
686  // In the event the above two methods failed then we hit it with the real seed finder
687  if (!foundGoodSeed)
688  {
689  // If here then we have a complicated 3D cluster and we'll use the hough transform algorithm to
690  // return a list of candidate seeds and seed hits
691  m_seedFinderAlg.findTrackSeeds(skeletonListPtr, skeletonPCA, seedHitPairVec);
692  }
693 
694  // Go through the returned lists and build out the art friendly seeds and hits
695  for(const auto& seedHitPair : seedHitPairVec)
696  {
697  seedVec.push_back(seedHitPair.first);
698 
699  // We use a set here because our 3D hits can share 2D hits
700  // The set will make sure we get unique combinations of 2D hits
701  std::set<art::Ptr<recob::Hit> > seedHitSet;
702 
703  for(const auto& hit3D : seedHitPair.second)
704  {
705  for(const auto& hit2D : hit3D->getHits())
706  {
707  if (!hit2D) continue;
708 
709  const recob::Hit* recobHit = &hit2D->getHit();
710 
711  seedHitSet.insert(hitToPtrMap[recobHit]);
712  }
713  }
714 
715  RecobHitVector seedHitVec;
716 
717  for(const auto& hit2D : seedHitSet) seedHitVec.push_back(hit2D);
718 
719  util::CreateAssn(*this, evt, seedVec, seedHitVec, seedHitAssns);
720  }
721 
722  return;
723 }
std::vector< SeedHitPairListPair > SeedHitPairListPairVec
bool aParallelHitsCluster(const reco::PrincipalComponents &pca) const
There are several places we will want to know if a candidate cluster is a "parallel hits" type of clu...
reco::PrincipalComponents & getSkeletonPCA()
Definition: Cluster3D.h:406
SkeletonAlg m_skeletonAlg
Skeleton point finder.
virtual bool findTrackSeeds(reco::HitPairListPtr &hitPairListPtr, reco::PrincipalComponents &inputPCA, SeedHitPairListPairVec &seedHitMap) const
Given the list of hits this will search for candidate Seed objects and return them.
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:404
HoughSeedFinderAlg m_seedFinderAlg
Seed finder.
void GetSkeletonHits(const reco::HitPairListPtr &inputHitList, reco::HitPairListPtr &skeletonHitList) const
Return the skeleton hits from the input list.
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:405
PCASeedFinderAlg m_pcaSeedFinderAlg
Use PCA axis to find seeds.
void AverageSkeletonPositions(reco::HitPairListPtr &skeletonHitList) const
Modifies the position of input skeleton hits by averaging along the "best" wire direction.
ParallelHitsSeedFinderAlg m_parallelHitsAlg
Deal with parallel hits clusters.
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:315
bool CreateAssn(PRODUCER const &prod, art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t indx=UINT_MAX)
Creates a single one-to-one association.
const float * getEigenValues() const
Definition: Cluster3D.h:226
virtual bool findTrackSeeds(reco::HitPairListPtr &hitPairListPtr, reco::PrincipalComponents &inputPCA, SeedHitPairListPairVec &seedHitPairVec) const
Given the list of hits this will search for candidate Seed objects and return them.
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:49
virtual bool findTrackSeeds(reco::HitPairListPtr &hitPairListPtr, reco::PrincipalComponents &inputPCA, SeedHitPairListPairVec &seedHitMap) const
Given the list of hits this will search for candidate Seed objects and return them.
std::vector< art::Ptr< recob::Hit >> RecobHitVector
EngineCreator::seed_t EngineCreator::get_seed_value ( fhicl::ParameterSet const &  pset,
char const  key[] = "seed",
seed_t const  implicit_seed = -1 
)
inherited

Definition at line 49 of file EngineCreator.cc.

References fhicl::ParameterSet::get().

Referenced by art::MixFilter< T >::initEngine_().

52 {
53  auto const& explicit_seeds = pset.get<std::vector<int>>(key, {});
54  return explicit_seeds.empty() ? implicit_seed : explicit_seeds.front();
55 }
template<typename PROD , BranchType B>
ProductID art::EDProducer::getProductID ( std::string const &  instanceName = {}) const
inlineinherited

Definition at line 123 of file EDProducer.h.

References art::EDProducer::moduleDescription_.

124  {
125  return ProducerBase::getProductID<PROD, B>(moduleDescription_,
126  instanceName);
127  }
ModuleDescription moduleDescription_
Definition: EDProducer.h:115
template<typename PROD , BranchType B>
ProductID art::ProducerBase::getProductID ( ModuleDescription const &  moduleDescription,
std::string const &  instanceName 
) const
inherited

Definition at line 56 of file ProducerBase.h.

References B, and art::ModuleDescription::moduleLabel().

Referenced by art::ProducerBase::modifiesEvent().

58  {
59  auto const& pd =
60  get_ProductDescription<PROD>(B, md.moduleLabel(), instanceName);
61  return pd.productID();
62  }
Int_t B
Definition: plot.C:25
void lar_cluster3d::Cluster3D::InitializeMonitoring ( )
private

Initialize the internal monitoring.

Definition at line 597 of file Cluster3D_module.cc.

References m_artHitsTime, m_buildNeighborhoodTime, m_dbscanTime, m_event, m_finishTime, m_hits, m_makeHitsTime, m_pathFindingTime, m_pRecoTree, m_run, m_totalTime, and art::TFileDirectory::make().

Referenced by beginJob().

598 {
600  m_pRecoTree = tfs->make<TTree>("monitoring", "LAr Reco");
601  m_pRecoTree->Branch("run", &m_run, "run/I");
602  m_pRecoTree->Branch("event", &m_event, "event/I");
603  m_pRecoTree->Branch("hits", &m_hits, "hits/I");
604  m_pRecoTree->Branch("totalTime", &m_totalTime, "time/F");
605  m_pRecoTree->Branch("artHitsTime", &m_artHitsTime, "time/F");
606  m_pRecoTree->Branch("makeHitsTime", &m_makeHitsTime, "time/F");
607  m_pRecoTree->Branch("buildneigborhoodTime", &m_buildNeighborhoodTime, "time/F");
608  m_pRecoTree->Branch("dbscanTime", &m_dbscanTime, "time/F");
609  m_pRecoTree->Branch("pathfindingtime", &m_pathFindingTime, "time/F");
610  m_pRecoTree->Branch("finishTime", &m_finishTime, "time/F");
611 }
float m_buildNeighborhoodTime
Keeps track of time to build epsilon neighborhood.
float m_makeHitsTime
Keeps track of time to build 3D hits.
float m_dbscanTime
Keeps track of time to run DBScan.
float m_finishTime
Keeps track of time to run output module.
int m_hits
Keeps track of the number of hits seen.
float m_pathFindingTime
Keeps track of the path finding time.
T * make(ARGS...args) const
float m_artHitsTime
Keeps track of time to recover hits.
float m_totalTime
Keeps track of total execution time.
void lar_cluster3d::Cluster3D::MakeAndSavePCAPoints ( ArtOutputHandler output,
const reco::PrincipalComponents fullPCA,
IdxToPCAMap idxToPCAMap 
) const
private

Definition at line 1658 of file Cluster3D_module.cc.

References lar_cluster3d::Cluster3D::ArtOutputHandler::artEdgeVector, lar_cluster3d::Cluster3D::ArtOutputHandler::artVertexEdgeVector, lar_cluster3d::Cluster3D::ArtOutputHandler::artVertexPointVector, reco::PrincipalComponents::getAvePosition(), reco::PrincipalComponents::getEigenVectors(), art::left(), and art::right().

1661 {
1662  // We actually do two things here:
1663  // 1) Create space points from the centroids of the PCA for each cluster
1664  // 2) Create the edges that link the space points together
1665 
1666  // The first task is to put the list of PCA's into some semblance of order... they may be
1667  // preordered by likely they are piecewise ordered so fix that here
1668 
1669  // We'll need the current PCA axis to determine doca and arclen
1670  Eigen::Vector3f avePosition(fullPCA.getAvePosition()[0], fullPCA.getAvePosition()[1], fullPCA.getAvePosition()[2]);
1671  Eigen::Vector3f axisDirVec(fullPCA.getEigenVectors()[0][0], fullPCA.getEigenVectors()[0][1], fullPCA.getEigenVectors()[0][2]);
1672 
1673  using DocaToPCAPair = std::pair<float, const reco::PrincipalComponents*>;
1674  using DocaToPCAVec = std::vector<DocaToPCAPair>;
1675 
1676  DocaToPCAVec docaToPCAVec;
1677 
1678  // Outer loop over views
1679  for (const auto& idxToPCA : idxToPCAMap)
1680  {
1681  const reco::PrincipalComponents* pca = idxToPCA.second;
1682 
1683  // Now we need to calculate the doca and poca...
1684  // Start by getting this hits position
1685  Eigen::Vector3f pcaPos(pca->getAvePosition()[0],pca->getAvePosition()[1],pca->getAvePosition()[2]);
1686 
1687  // Form a TVector from this to the cluster average position
1688  Eigen::Vector3f pcaToAveVec = pcaPos - avePosition;
1689 
1690  // With this we can get the arclength to the doca point
1691  float arclenToPoca = pcaToAveVec.dot(axisDirVec);
1692 
1693  docaToPCAVec.emplace_back(DocaToPCAPair(arclenToPoca,pca));
1694  }
1695 
1696  std::sort(docaToPCAVec.begin(),docaToPCAVec.end(),[](const auto& left, const auto& right){return left.first < right.first;});
1697 
1698  // Set up the space point creation
1699  // Right now error matrix is uniform...
1700  double spError[] = {1., 0., 1., 0., 0., 1.};
1701  double chisq = 1.;
1702 
1703  const reco::PrincipalComponents* lastPCA(NULL);
1704 
1705  // Set up to loop through the clusters
1706  for(const auto& docaToPCAPair : docaToPCAVec)
1707  {
1708  // Recover the PCA for this cluster
1709  const reco::PrincipalComponents* curPCA = docaToPCAPair.second;
1710 
1711  if(lastPCA)
1712  {
1713  double lastPointPos[] = {lastPCA->getAvePosition()[0],lastPCA->getAvePosition()[1],lastPCA->getAvePosition()[2]};
1714  size_t lastPointBin = output.artVertexPointVector->size();
1715  double curPointPos[] = {curPCA->getAvePosition()[0],curPCA->getAvePosition()[1],curPCA->getAvePosition()[2]};
1716  size_t curPointBin = lastPointBin + 1;
1717 
1718  output.artVertexPointVector->emplace_back(lastPointPos, spError, chisq, lastPointBin);
1719  output.artVertexPointVector->emplace_back(curPointPos, spError, chisq, curPointBin);
1720 
1721  Eigen::Vector3f distVec(curPointPos[0]-lastPointPos[0],curPointPos[1]-lastPointPos[1],curPointPos[2]-lastPointPos[2]);
1722 
1723  output.artVertexEdgeVector->emplace_back(distVec.norm(), lastPointBin, curPointBin, output.artEdgeVector->size());
1724  }
1725 
1726  lastPCA = curPCA;
1727  }
1728 
1729  return;
1730 }
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
const float * getAvePosition() const
Definition: Cluster3D.h:228
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:104
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:227
void lar_cluster3d::Cluster3D::MakeAndSaveSpacePoints ( ArtOutputHandler output,
reco::HitPairListPtr clusHitPairVector,
RecobHitToPtrMap hitToPtrMap,
Hit3DToSPPtrMap hit3DToSPPtrMap,
int  spacePointStart 
) const
private

Special routine to handle creating and saving space points.

Parameters
outputthe object containting the art output
clusterParametersCluster info to output (in internal format)
pfParticleParentThe parent ID reference for the output PFParticle
hitToPtrMapThis maps our Cluster2D hits back to art Ptr's to reco Hits

Definition at line 1538 of file Cluster3D_module.cc.

References lar_cluster3d::Cluster3D::ArtOutputHandler::artSpacePointVector, reco::ClusterHit3D::MADESPACEPOINT, lar_cluster3d::Cluster3D::ArtOutputHandler::makePFPartSpacePointAssns(), lar_cluster3d::Cluster3D::ArtOutputHandler::makeSpacePointHitAssns(), and reco::ClusterHit3D::REJECTEDHIT.

Referenced by ProduceArtClusters().

1543 {
1544  // Right now error matrix is uniform...
1545  double spError[] = {1., 0., 1., 0., 0., 1.};
1546 
1547  // Copy these hits to the vector to be stored with the event
1548  for (auto& hitPair : clusHitPairVector)
1549  {
1550  // Skip those space points that have already been created
1551  if (hit3DToSPPtrMap.find(hitPair) != hit3DToSPPtrMap.end()) continue;
1552 
1553  // Don't make space point if this hit was "rejected"
1554  if (hitPair->bitsAreSet(reco::ClusterHit3D::REJECTEDHIT)) continue;
1555 
1556  double chisq = hitPair->getHitChiSquare(); // secret handshake...
1557 
1558 // if ( hitPair->bitsAreSet(reco::ClusterHit3D::SKELETONHIT) && !hitPair->bitsAreSet(reco::ClusterHit3D::EDGEHIT)) chisq = -1.; // pure skeleton point
1559 // else if (!hitPair->bitsAreSet(reco::ClusterHit3D::SKELETONHIT) && hitPair->bitsAreSet(reco::ClusterHit3D::EDGEHIT)) chisq = -2.; // pure edge point
1560 // else if ( hitPair->bitsAreSet(reco::ClusterHit3D::SKELETONHIT) && hitPair->bitsAreSet(reco::ClusterHit3D::EDGEHIT)) chisq = -3.; // skeleton and edge point
1561 
1562 // if (hitPair->bitsAreSet(reco::ClusterHit3D::SEEDHIT) ) chisq = -4.; // Seed point
1563 
1564 // if ((hitPair->getStatusBits() & 0x7) != 0x7) chisq = -10.;
1565 
1566  // Mark this hit pair as in use
1567  hitPair->setStatusBit(reco::ClusterHit3D::MADESPACEPOINT);
1568 
1569  // Create and store the space point
1570  size_t spacePointID = output.artSpacePointVector->size();
1571  double spacePointPos[] = {hitPair->getPosition()[0],hitPair->getPosition()[1],hitPair->getPosition()[2]};
1572  output.artSpacePointVector->push_back(recob::SpacePoint(spacePointPos, spError, chisq, output.artSpacePointVector->size()));
1573 
1574  // Update mapping
1575  hit3DToSPPtrMap[hitPair] = spacePointID;
1576 
1577  // space point hits associations
1578  RecobHitVector recobHits;
1579 
1580  for(const auto& hit : hitPair->getHits())
1581  {
1582  if (!hit) continue;
1583  art::Ptr<recob::Hit> hitPtr = hitToPtrMap[&hit->getHit()];
1584  recobHits.push_back(hitPtr);
1585  }
1586 
1587  if (!recobHits.empty()) output.makeSpacePointHitAssns(recobHits);
1588  }
1589 
1590  output.makePFPartSpacePointAssns(spacePointStart);
1591 
1592  return;
1593 }
Hit has been rejected for any reason.
Definition: Cluster3D.h:92
Detector simulation of raw signals on wires.
Hit has been made into Space Point.
Definition: Cluster3D.h:96
std::vector< art::Ptr< recob::Hit >> RecobHitVector
void lar_cluster3d::Cluster3D::MakeAndSaveVertexPoints ( ArtOutputHandler output,
dcel2d::VertexList vertexList,
dcel2d::HalfEdgeList halfEdgeList 
) const
private

Special routine to handle creating and saving space points & edges associated to voronoi diagrams.

Parameters
outputthe object containting the art output
vertexListlist of vertices in the diagram
HalfEdgeListlist of half edges in the diagram

Definition at line 1595 of file Cluster3D_module.cc.

References lar_cluster3d::Cluster3D::ArtOutputHandler::artEdgeVector, lar_cluster3d::Cluster3D::ArtOutputHandler::artVertexEdgeVector, lar_cluster3d::Cluster3D::ArtOutputHandler::artVertexPointVector, dcel2d::Vertex::getCoords(), dcel2d::HalfEdge::getTargetVertex(), and dcel2d::HalfEdge::getTwinHalfEdge().

Referenced by ProduceArtClusters().

1598 {
1599  // We actually do two things here:
1600  // 1) Create space points to represent the vertex locations of the voronoi diagram
1601  // 2) Create the edges that link the space points together
1602 
1603  // Set up the space point creation
1604  // Right now error matrix is uniform...
1605  double spError[] = {1., 0., 1., 0., 0., 1.};
1606  double chisq = 1.;
1607 
1608  // Keep track of the vertex to space point association
1609  std::map<const dcel2d::Vertex*,size_t> vertexToSpacePointMap;
1610 
1611  // Copy these hits to the vector to be stored with the event
1612  for (auto& vertex : vertexList)
1613  {
1614  const dcel2d::Coords& coords = vertex.getCoords();
1615 
1616  // Create and store the space point
1617  double spacePointPos[] = {coords[0], coords[1], coords[2]};
1618 
1619  vertexToSpacePointMap[&vertex] = output.artVertexPointVector->size();
1620 
1621  output.artVertexPointVector->emplace_back(spacePointPos, spError, chisq, output.artVertexPointVector->size());
1622  }
1623 
1624  // Try to avoid double counting
1625  std::set<const dcel2d::HalfEdge*> halfEdgeSet;
1626 
1627  // Build the edges now
1628  for(const auto& halfEdge : halfEdgeList)
1629  {
1630  // Recover twin
1631  const dcel2d::HalfEdge* twin = halfEdge.getTwinHalfEdge();
1632 
1633  // It can happen that we have no twin... and also check that we've not been here before
1634  if (twin && halfEdgeSet.find(twin) == halfEdgeSet.end())
1635  {
1636  // Recover the vertices
1637  const dcel2d::Vertex* fromVertex = twin->getTargetVertex();
1638  const dcel2d::Vertex* toVertex = halfEdge.getTargetVertex();
1639 
1640  // It can happen for the open edges that there is no target vertex
1641  if (!toVertex || !fromVertex) continue;
1642 
1643  if (vertexToSpacePointMap.find(fromVertex) == vertexToSpacePointMap.end() ||
1644  vertexToSpacePointMap.find(toVertex) == vertexToSpacePointMap.end()) continue;
1645 
1646  // Need the distance between vertices
1647  Eigen::Vector3f distVec = toVertex->getCoords() - fromVertex->getCoords();
1648 
1649  output.artVertexEdgeVector->emplace_back(distVec.norm(), vertexToSpacePointMap.at(fromVertex), vertexToSpacePointMap.at(toVertex), output.artEdgeVector->size());
1650 
1651  halfEdgeSet.insert(&halfEdge);
1652  }
1653  }
1654 
1655  return;
1656 }
HalfEdge * getTwinHalfEdge() const
Definition: DCEL.h:159
Vertex * getTargetVertex() const
Definition: DCEL.h:157
Eigen::Vector3f Coords
Definition: DCEL.h:36
const Coords & getCoords() const
Definition: DCEL.h:61
vertex reconstruction
template<typename T , BranchType = InEvent>
ProductToken<T> art::Consumer::mayConsume ( InputTag const &  )
inherited
template<typename T , art::BranchType BT>
art::ProductToken<T> art::Consumer::mayConsume ( InputTag const &  it)
inherited

Definition at line 190 of file Consumer.h.

References art::InputTag::instance(), art::InputTag::label(), and art::InputTag::process().

191 {
192  if (!moduleContext_)
193  return ProductToken<T>::invalid();
194 
195  consumables_[BT].emplace_back(ConsumableType::Product,
196  TypeID{typeid(T)},
197  it.label(),
198  it.instance(),
199  it.process());
200  return ProductToken<T>{it};
201 }
static ProductToken< T > invalid()
Definition: ProductToken.h:47
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
template<typename T , art::BranchType BT>
void art::Consumer::mayConsumeMany ( )
inherited

Definition at line 205 of file Consumer.h.

206 {
207  if (!moduleContext_)
208  return;
209 
210  consumables_[BT].emplace_back(ConsumableType::Many, TypeID{typeid(T)});
211 }
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
template<typename Element , BranchType = InEvent>
ViewToken<Element> art::Consumer::mayConsumeView ( InputTag const &  )
inherited
template<typename T , art::BranchType BT>
art::ViewToken<T> art::Consumer::mayConsumeView ( InputTag const &  it)
inherited

Definition at line 215 of file Consumer.h.

References art::InputTag::instance(), art::InputTag::label(), and art::InputTag::process().

216 {
217  if (!moduleContext_)
218  return ViewToken<T>::invalid();
219 
220  consumables_[BT].emplace_back(ConsumableType::ViewElement,
221  TypeID{typeid(T)},
222  it.label(),
223  it.instance(),
224  it.process());
225  return ViewToken<T>{it};
226 }
static ViewToken< Element > invalid()
Definition: ProductToken.h:75
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
bool art::ProducerBase::modifiesEvent ( ) const
inlineinherited

Definition at line 40 of file ProducerBase.h.

References art::ProducerBase::getProductID().

41  {
42  return true;
43  }
void lar_cluster3d::Cluster3D::PrepareEvent ( const art::Event evt)
private

Event Preparation.

Parameters
evtthe ART event

Definition at line 615 of file Cluster3D_module.cc.

References art::EventID::event(), art::Event::id(), m_artHitsTime, m_buildNeighborhoodTime, m_dbscanTime, m_event, m_finishTime, m_hits, m_makeHitsTime, m_pathFindingTime, m_run, m_totalTime, and art::Event::run().

Referenced by produce().

616 {
617  m_run = evt.run();
618  m_event = evt.id().event();
619  m_hits = 0;
620  m_totalTime = 0.f;
621  m_artHitsTime = 0.f;
622  m_makeHitsTime = 0.f;
624  m_dbscanTime = 0.f;
625  m_pathFindingTime = 0.f;
626  m_finishTime = 0.f;
627 }
float m_buildNeighborhoodTime
Keeps track of time to build epsilon neighborhood.
float m_makeHitsTime
Keeps track of time to build 3D hits.
float m_dbscanTime
Keeps track of time to run DBScan.
float m_finishTime
Keeps track of time to run output module.
int m_hits
Keeps track of the number of hits seen.
float m_pathFindingTime
Keeps track of the path finding time.
EventNumber_t event() const
Definition: EventID.h:117
float m_artHitsTime
Keeps track of time to recover hits.
RunNumber_t run() const
Definition: Event.h:77
EventID id() const
Definition: Event.h:56
float m_totalTime
Keeps track of total execution time.
void art::Consumer::prepareForJob ( fhicl::ParameterSet const &  pset)
protectedinherited

Definition at line 89 of file Consumer.cc.

References fhicl::ParameterSet::get_if_present().

Referenced by art::EDProducer::doBeginJob(), art::EDFilter::doBeginJob(), and art::EDAnalyzer::doBeginJob().

90 {
91  if (!moduleContext_)
92  return;
93 
94  pset.get_if_present("errorOnMissingConsumes", requireConsumes_);
95  for (auto& consumablesPerBranch : consumables_) {
96  cet::sort_all(consumablesPerBranch);
97  }
98 }
bool requireConsumes_
Definition: Consumer.h:137
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
void lar_cluster3d::Cluster3D::produce ( art::Event evt)
virtual

Producer method for reovering the 2D hits and driving the 3D reconstruciton

Implements art::EDProducer.

Definition at line 515 of file Cluster3D_module.cc.

References lar_cluster3d::IClusterAlg::BUILDCLUSTERINFO, lar_cluster3d::IClusterAlg::BUILDHITTOHITMAP, lar_cluster3d::IHit3DBuilder::BUILDTHREEDHITS, lar_cluster3d::IHit3DBuilder::COLLECTARTHITS, art::EventID::event(), art::Event::id(), m_artHitsTime, m_buildNeighborhoodTime, m_clusterAlg, m_clusterMergeAlg, m_clusterPathAlg, m_dbscanTime, m_enableMonitoring, m_event, m_finishTime, m_hit3DBuilderAlg, m_hits, m_makeHitsTime, m_pathFindingTime, m_pRecoTree, m_run, m_spacePointInstance, m_totalTime, lar_cluster3d::Cluster3D::ArtOutputHandler::outputObjects(), lar_cluster3d::IClusterAlg::PATHFINDING, PrepareEvent(), ProduceArtClusters(), art::Event::run(), and lar_cluster3d::IClusterAlg::RUNDBSCAN.

516 {
520  mf::LogInfo("Cluster3D") << " *** Cluster3D::produce(...) [Run=" << evt.run() << ", Event=" << evt.id().event() << "] Starting Now! *** " << std::endl;
521 
522  // Set up for monitoring the timing... at some point this should be removed in favor of
523  // external profilers
524  cet::cpu_timer theClockTotal;
525  cet::cpu_timer theClockFinish;
526 
527  if (m_enableMonitoring) theClockTotal.start();
528 
529  // This really only does anything if we are monitoring since it clears our tree variables
530  this->PrepareEvent(evt);
531 
532  // Get instances of the primary data structures needed
533  reco::ClusterParametersList clusterParametersList;
534  IHit3DBuilder::RecobHitToPtrMap clusterHitToArtPtrMap;
535  std::unique_ptr< reco::HitPairList > hitPairList(new reco::HitPairList); // Potentially lots of hits, use heap instead of stack
536 
537  // Call the algorithm that builds 3D hits
538  m_hit3DBuilderAlg->Hit3DBuilder(evt, *hitPairList, clusterHitToArtPtrMap);
539 
540  std::cout << "++> Produced: " << hitPairList->size() << " hits" << std::endl;
541 
542  // Call the main workhorse algorithm for building the local version of candidate 3D clusters
543  m_clusterAlg->Cluster3DHits(*hitPairList, clusterParametersList);
544 
545  std::cout << "++> Produced: " << clusterParametersList.size() << " clusters" << std::endl;
546 
547  // Try merging clusters
548  m_clusterMergeAlg->ModifyClusters(clusterParametersList);
549 
550  // Run the path finding
551  m_clusterPathAlg->ModifyClusters(clusterParametersList);
552 
553  if(m_enableMonitoring) theClockFinish.start();
554 
555  // Get the art ouput object
556  ArtOutputHandler output(*this, evt, m_spacePointInstance);
557 
558  std::cout << "++> Outputting clusters" << std::endl;
559 
560  // Call the module that does the end processing (of which there is quite a bit of work!)
561  // This goes here to insure that something is always written to the data store
562  ProduceArtClusters(output, *hitPairList, clusterParametersList, clusterHitToArtPtrMap);
563 
564  // Output to art
565  output.outputObjects();
566 
567  if (m_enableMonitoring) theClockFinish.stop();
568 
569  // If monitoring then deal with the fallout
570  if (m_enableMonitoring)
571  {
572  theClockTotal.stop();
573 
574  m_run = evt.run();
575  m_event = evt.id().event();
576  m_totalTime = theClockTotal.accumulated_real_time();
580  m_dbscanTime = m_clusterAlg->getTimeToExecute(IClusterAlg::RUNDBSCAN) +
581  m_clusterAlg->getTimeToExecute(IClusterAlg::BUILDCLUSTERINFO);
583  m_finishTime = theClockFinish.accumulated_real_time();
584  m_hits = static_cast<int>(clusterHitToArtPtrMap.size());
585  m_pRecoTree->Fill();
586 
587  mf::LogDebug("Cluster3D") << "*** Cluster3D total time: " << m_totalTime << ", art: " << m_artHitsTime << ", make: " << m_makeHitsTime
588  << ", build: " << m_buildNeighborhoodTime << ", clustering: " << m_dbscanTime << ", path: " << m_pathFindingTime << ", finish: " << m_finishTime << std::endl;
589  }
590 
591  // Will we ever get here? ;-)
592  return;
593 }
float m_buildNeighborhoodTime
Keeps track of time to build epsilon neighborhood.
std::unique_ptr< lar_cluster3d::IClusterModAlg > m_clusterPathAlg
Algorithm to do cluster path finding.
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::string m_spacePointInstance
Special instance name for vertex points.
std::unique_ptr< lar_cluster3d::IClusterAlg > m_clusterAlg
Algorithm to do 3D space point clustering.
float m_makeHitsTime
Keeps track of time to build 3D hits.
float m_dbscanTime
Keeps track of time to run DBScan.
std::list< std::unique_ptr< reco::ClusterHit3D >> HitPairList
Definition: Cluster3D.h:319
float m_finishTime
Keeps track of time to run output module.
int m_hits
Keeps track of the number of hits seen.
std::map< const recob::Hit *, art::Ptr< recob::Hit >> RecobHitToPtrMap
Defines a structure mapping art representation to internal.
Definition: IHit3DBuilder.h:44
float m_pathFindingTime
Keeps track of the path finding time.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
std::unique_ptr< lar_cluster3d::IClusterModAlg > m_clusterMergeAlg
Algorithm to do cluster merging.
std::unique_ptr< lar_cluster3d::IHit3DBuilder > m_hit3DBuilderAlg
Builds the 3D hits to operate on.
EventNumber_t event() const
Definition: EventID.h:117
float m_artHitsTime
Keeps track of time to recover hits.
RunNumber_t run() const
Definition: Event.h:77
void PrepareEvent(const art::Event &evt)
Event Preparation.
EventID id() const
Definition: Event.h:56
float m_totalTime
Keeps track of total execution time.
std::list< ClusterParameters > ClusterParametersList
Definition: Cluster3D.h:335
void ProduceArtClusters(ArtOutputHandler &output, reco::HitPairList &hitPairList, reco::ClusterParametersList &clusterParametersList, RecobHitToPtrMap &hitToPtrMap) const
Top level output routine, allows checking cluster status.
bool m_enableMonitoring
Turn on monitoring of this algorithm.
void lar_cluster3d::Cluster3D::ProduceArtClusters ( ArtOutputHandler output,
reco::HitPairList hitPairList,
reco::ClusterParametersList clusterParametersList,
RecobHitToPtrMap hitToPtrMap 
) const
private

Top level output routine, allows checking cluster status.

Parameters
hitPairListList of all 3D Hits in internal Cluster3D format
clusterParametersListData structure containing the cluster information to output
hitToPtrMapThis maps our Cluster2D hits back to art Ptr's to reco Hits

The workhorse to take the candidate 3D clusters and produce all of the necessary art output

Definition at line 1065 of file Cluster3D_module.cc.

References lar_cluster3d::Cluster3D::ArtOutputHandler::artEdgeVector, lar_cluster3d::Cluster3D::ArtOutputHandler::artPCAxisVector, lar_cluster3d::Cluster3D::ArtOutputHandler::artPFParticleVector, lar_cluster3d::Cluster3D::ArtOutputHandler::artSpacePointVector, ConvertToArtOutput(), countUltimateDaughters(), FindAndStoreDaughters(), reco::PrincipalComponents::getAveHitDoca(), reco::PrincipalComponents::getAvePosition(), reco::PrincipalComponents::getEigenValues(), reco::PrincipalComponents::getEigenVectors(), reco::PrincipalComponents::getNumHitsUsed(), reco::PrincipalComponents::getSvdOK(), recob::PFParticle::kPFParticlePrimary, reco::ClusterHit3D::MADESPACEPOINT, MakeAndSaveSpacePoints(), MakeAndSaveVertexPoints(), lar_cluster3d::Cluster3D::ArtOutputHandler::makePFPartEdgeAssns(), lar_cluster3d::Cluster3D::ArtOutputHandler::makePFPartPCAAssns(), and lar_cluster3d::Cluster3D::ArtOutputHandler::makeSpacePointHitAssns().

Referenced by produce().

1069 {
1074  mf::LogDebug("Cluster3D") << " *** Cluster3D::ProduceArtClusters() *** " << std::endl;
1075 
1076  // Make sure there is something to do here!
1077  if (!clusterParametersList.empty())
1078  {
1079  // This is the loop over candidate 3D clusters
1080  // Note that it might be that the list of candidate clusters is modified by splitting
1081  // So we use the following construct to make sure we get all of them
1082  for(auto& clusterParameters : clusterParametersList)
1083  {
1084  // It should be straightforward at this point to transfer information from our vector of clusters
1085  // to the larsoft objects... of course we still have some work to do first, in particular to
1086  // find the candidate seeds and their seed hits
1087 
1088  // The chances of getting here and this condition not being true are probably zero... but check anyway
1089  if (!clusterParameters.getFullPCA().getSvdOK())
1090  {
1091  mf::LogDebug("Cluster3D") << "--> no feature extraction done on this cluster!!" << std::endl;
1092  continue;
1093  }
1094 
1095  // Keep track of hit 3D to SP for when we do edges
1096  Hit3DToSPPtrMap hit3DToSPPtrMap;
1097 
1098  // Keep track of current start for space points
1099  int spacePointStart(output.artSpacePointVector->size());
1100 
1101  // Do a special output of voronoi vertices here...
1102  dcel2d::VertexList& vertexList = clusterParameters.getVertexList();
1103  dcel2d::HalfEdgeList& halfEdgeList = clusterParameters.getHalfEdgeList();
1104 
1105  std::cout << "Preparing to save the vertex point list, size: " << vertexList.size() << ", half edges: " << halfEdgeList.size() << std::endl;
1106 
1107  MakeAndSaveVertexPoints(output, vertexList, halfEdgeList);
1108 
1109  // Special case handling... if no daughters then call standard conversion routine to make sure space points
1110  // created, etc.
1111  if (clusterParameters.daughterList().empty())
1112  {
1113  ConvertToArtOutput(output, clusterParameters, recob::PFParticle::kPFParticlePrimary, hitToPtrMap, hit3DToSPPtrMap);
1114  }
1115  // Otherwise, the cluster has daughters so we handle specially
1116  else
1117  {
1118  // Set up to keep track of parent/daughters
1119  IdxToPCAMap idxToPCAMap;
1120  size_t numTotalDaughters = countUltimateDaughters(clusterParameters);
1121  size_t pfParticleIdx(output.artPFParticleVector->size() + numTotalDaughters);
1122 
1123  FindAndStoreDaughters(output, clusterParameters, pfParticleIdx, idxToPCAMap, hitToPtrMap, hit3DToSPPtrMap);
1124 
1125  // Now make the piecewise curve
1126 // MakeAndSavePCAPoints(output, clusterParameters.getFullPCA(), idxToPCAMap);
1127 
1128  // Need to make a daughter vec from our map
1129  std::vector<size_t> daughterVec;
1130 
1131  for(auto& idxToPCA : idxToPCAMap) daughterVec.emplace_back(idxToPCA.first);
1132 
1133  // Now create/handle the parent PFParticle
1134  recob::PFParticle pfParticle(13, pfParticleIdx, recob::PFParticle::kPFParticlePrimary, daughterVec);
1135  output.artPFParticleVector->push_back(pfParticle);
1136 
1137  recob::PCAxis::EigenVectors eigenVecs;
1138  double eigenVals[] = {0.,0.,0.};
1139  double avePosition[] = {0.,0.,0.};
1140 
1141  eigenVecs.resize(3);
1142 
1143  reco::PrincipalComponents& skeletonPCA = clusterParameters.getSkeletonPCA();
1144 
1145  for(size_t outerIdx = 0; outerIdx < 3; outerIdx++)
1146  {
1147  avePosition[outerIdx] = skeletonPCA.getAvePosition()[outerIdx];
1148  eigenVals[outerIdx] = skeletonPCA.getEigenValues()[outerIdx];
1149 
1150  eigenVecs[outerIdx].resize(3);
1151 
1152  for(size_t innerIdx = 0; innerIdx < 3; innerIdx++) eigenVecs[outerIdx][innerIdx] = skeletonPCA.getEigenVectors()[outerIdx][innerIdx];
1153  }
1154 
1155 
1156  recob::PCAxis skelPcAxis(skeletonPCA.getSvdOK(),
1157  skeletonPCA.getNumHitsUsed(),
1158  eigenVals, //skeletonPCA.getEigenValues(),
1159  eigenVecs, //skeletonPCA.getEigenVectors(),
1160  avePosition, //skeletonPCA.getAvePosition(),
1161  skeletonPCA.getAveHitDoca(),
1162  output.artPCAxisVector->size());
1163 
1164  output.artPCAxisVector->push_back(skelPcAxis);
1165 
1166  reco::PrincipalComponents& fullPCA = clusterParameters.getFullPCA();
1167 
1168  for(size_t outerIdx = 0; outerIdx < 3; outerIdx++)
1169  {
1170  avePosition[outerIdx] = fullPCA.getAvePosition()[outerIdx];
1171  eigenVals[outerIdx] = fullPCA.getEigenValues()[outerIdx];
1172 
1173  for(size_t innerIdx = 0; innerIdx < 3; innerIdx++) eigenVecs[outerIdx][innerIdx] = fullPCA.getEigenVectors()[outerIdx][innerIdx];
1174  }
1175 
1176  recob::PCAxis fullPcAxis(fullPCA.getSvdOK(),
1177  fullPCA.getNumHitsUsed(),
1178  eigenVals, //fullPCA.getEigenValues(),
1179  eigenVecs, //fullPCA.getEigenVectors(),
1180  avePosition, //fullPCA.getAvePosition(),
1181  fullPCA.getAveHitDoca(),
1182  output.artPCAxisVector->size());
1183 
1184  output.artPCAxisVector->push_back(fullPcAxis);
1185 
1186  // Create associations to the PFParticle
1187  output.makePFPartPCAAssns();
1188 
1189  // Make associations to all space points for this cluster
1190  MakeAndSaveSpacePoints(output, clusterParameters.getHitPairListPtr(), hitToPtrMap, hit3DToSPPtrMap, spacePointStart);
1191 
1192  // Build the edges now
1193  size_t edgeStart(output.artEdgeVector->size());
1194 
1195  for(const auto& edge : clusterParameters.getBestEdgeList())
1196  {
1197  Hit3DToSPPtrMap::iterator hit0Itr = hit3DToSPPtrMap.find(std::get<0>(edge));
1198  Hit3DToSPPtrMap::iterator hit1Itr = hit3DToSPPtrMap.find(std::get<1>(edge));
1199 
1200  bool hit0Found = hit0Itr != hit3DToSPPtrMap.end();
1201  bool hit1Found = hit1Itr != hit3DToSPPtrMap.end();
1202 
1203  if (!hit0Found || !hit1Found) std::cout << "<<<<< Did not find matching space point " << hit0Found << ", " << hit1Found << " >>>>>>" << std::endl;
1204 
1205  output.artEdgeVector->push_back(recob::Edge(std::get<2>(edge), hit3DToSPPtrMap[std::get<0>(edge)], hit3DToSPPtrMap[std::get<1>(edge)], output.artEdgeVector->size()));
1206  }
1207 
1208  output.makePFPartEdgeAssns(edgeStart);
1209  }
1210  }
1211  }
1212 
1213  // Right now error matrix is uniform...
1214  int nFreePoints(0);
1215 
1216  // Run through the HitPairVector and add any unused hit pairs to the list
1217  for(auto& hitPair : hitPairVector)
1218  {
1219  if (hitPair->bitsAreSet(reco::ClusterHit3D::MADESPACEPOINT)) continue;
1220 
1221  double spacePointPos[] = {hitPair->getPosition()[0],hitPair->getPosition()[1],hitPair->getPosition()[2]};
1222  double spacePointErr[] = {1., 0., 0., 1., 0., 1.};
1223  double chisq(-100.);
1224 
1225  RecobHitVector recobHits;
1226 
1227  for(const auto hit : hitPair->getHits())
1228  {
1229  if (!hit)
1230  {
1231  chisq = -1000.;
1232  continue;
1233  }
1234 
1235  art::Ptr<recob::Hit> hitPtr = hitToPtrMap[&hit->getHit()];
1236  recobHits.push_back(hitPtr);
1237  }
1238 
1239  nFreePoints++;
1240 
1241  output.artSpacePointVector->push_back(recob::SpacePoint(spacePointPos, spacePointErr, chisq, output.artSpacePointVector->size()));
1242 
1243  if (!recobHits.empty()) output.makeSpacePointHitAssns(recobHits);
1244  }
1245 
1246  std::cout << "++++>>>> total num hits: " << hitPairVector.size() << ", num free: " << nFreePoints << std::endl;
1247 
1248  return;
1249 }
bool getSvdOK() const
Definition: Cluster3D.h:224
size_t FindAndStoreDaughters(ArtOutputHandler &output, reco::ClusterParameters &clusterParameters, size_t pfParticleParent, IdxToPCAMap &idxToPCAMap, RecobHitToPtrMap &hitToPtrMap, Hit3DToSPPtrMap &hit3DToSPPtrMap) const
This will produce art output for daughters noting that it needs to be done recursively.
intermediate_table::iterator iterator
static constexpr size_t kPFParticlePrimary
Define index to signify primary particle.
Definition: PFParticle.h:61
std::list< HalfEdge > HalfEdgeList
Definition: DCEL.h:180
const float * getAvePosition() const
Definition: Cluster3D.h:228
int getNumHitsUsed() const
Definition: Cluster3D.h:225
size_t countUltimateDaughters(reco::ClusterParameters &clusterParameters) const
Count number of end of line daughters.
size_t ConvertToArtOutput(ArtOutputHandler &output, reco::ClusterParameters &clusterParameters, size_t pfParticleParent, RecobHitToPtrMap &hitToPtrMap, Hit3DToSPPtrMap &hit3DToSPPtrMap) const
Produces the art output from all the work done in this producer module.
Detector simulation of raw signals on wires.
std::map< size_t, const reco::PrincipalComponents * > IdxToPCAMap
Special routine to handle creating and saving space points & edges PCA points.
Hierarchical representation of particle flow.
Definition: PFParticle.h:44
const float * getEigenValues() const
Definition: Cluster3D.h:226
const float getAveHitDoca() const
Definition: Cluster3D.h:229
Hit has been made into Space Point.
Definition: Cluster3D.h:96
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
void MakeAndSaveVertexPoints(ArtOutputHandler &, dcel2d::VertexList &, dcel2d::HalfEdgeList &) const
Special routine to handle creating and saving space points & edges associated to voronoi diagrams...
void MakeAndSaveSpacePoints(ArtOutputHandler &output, reco::HitPairListPtr &clusHitPairVector, RecobHitToPtrMap &hitToPtrMap, Hit3DToSPPtrMap &hit3DToSPPtrMap, int spacePointStart) const
Special routine to handle creating and saving space points.
std::vector< std::vector< double > > EigenVectors
Definition: PCAxis.h:29
std::list< Vertex > VertexList
Definition: DCEL.h:178
const EigenVectors & getEigenVectors() const
Definition: Cluster3D.h:227
Edge is an object containing the results of a Principal Components Analysis of a group of space point...
Definition: Edge.h:61
std::vector< art::Ptr< recob::Hit >> RecobHitVector
std::map< const reco::ClusterHit3D *, size_t > Hit3DToSPPtrMap
void lar_cluster3d::Cluster3D::reconfigure ( fhicl::ParameterSet const &  pset)

Definition at line 472 of file Cluster3D_module.cc.

References fhicl::ParameterSet::get(), m_clusterAlg, m_clusterMergeAlg, m_clusterPathAlg, m_enableMonitoring, m_hit3DBuilderAlg, m_parallelHitsAlg, m_parallelHitsCosAng, m_parallelHitsTransWid, m_pcaAlg, m_pcaSeedFinderAlg, m_seedFinderAlg, m_skeletonAlg, lar_cluster3d::HoughSeedFinderAlg::reconfigure(), lar_cluster3d::SkeletonAlg::reconfigure(), lar_cluster3d::PCASeedFinderAlg::reconfigure(), lar_cluster3d::ParallelHitsSeedFinderAlg::reconfigure(), and lar_cluster3d::PrincipalComponentsAlg::reconfigure().

Referenced by Cluster3D().

473 {
474  m_enableMonitoring = pset.get<bool> ("EnableMonitoring", false);
475  m_parallelHitsCosAng = pset.get<float> ("ParallelHitsCosAng", 0.999);
476  m_parallelHitsTransWid = pset.get<float> ("ParallelHitsTransWid", 25.0);
477 
478  m_hit3DBuilderAlg = art::make_tool<lar_cluster3d::IHit3DBuilder>(pset.get<fhicl::ParameterSet>("Hit3DBuilderAlg"));
479  m_clusterAlg = art::make_tool<lar_cluster3d::IClusterAlg>(pset.get<fhicl::ParameterSet>("ClusterAlg"));
480  m_clusterMergeAlg = art::make_tool<lar_cluster3d::IClusterModAlg>(pset.get<fhicl::ParameterSet>("ClusterMergeAlg"));
481  m_clusterPathAlg = art::make_tool<lar_cluster3d::IClusterModAlg>(pset.get<fhicl::ParameterSet>("ClusterPathAlg"));
482 
483  m_pcaAlg.reconfigure(pset.get<fhicl::ParameterSet>("PrincipalComponentsAlg"));
484  m_skeletonAlg.reconfigure(pset.get<fhicl::ParameterSet>("SkeletonAlg"));
485  m_seedFinderAlg.reconfigure(pset.get<fhicl::ParameterSet>("SeedFinderAlg"));
486  m_pcaSeedFinderAlg.reconfigure(pset.get<fhicl::ParameterSet>("PCASeedFinderAlg"));
487  m_parallelHitsAlg.reconfigure(pset.get<fhicl::ParameterSet>("ParallelHitsAlg"));
488 }
std::unique_ptr< lar_cluster3d::IClusterModAlg > m_clusterPathAlg
Algorithm to do cluster path finding.
virtual void reconfigure(fhicl::ParameterSet const &pset)
a handler for the case where the algorithm control parameters are to be reset
float m_parallelHitsTransWid
Cut on transverse width of cluster (PCA 2nd eigenvalue)
void reconfigure(fhicl::ParameterSet const &pset)
a handler for the case where the algorithm control parameters are to be reset
float m_parallelHitsCosAng
Cut for PCA 3rd axis angle to X axis.
virtual void reconfigure(fhicl::ParameterSet const &pset)
a handler for the case where the algorithm control parameters are to be reset
SkeletonAlg m_skeletonAlg
Skeleton point finder.
HoughSeedFinderAlg m_seedFinderAlg
Seed finder.
std::unique_ptr< lar_cluster3d::IClusterAlg > m_clusterAlg
Algorithm to do 3D space point clustering.
void reconfigure(fhicl::ParameterSet const &pset)
a handler for the case where the algorithm control parameters are to be reset
Definition: SkeletonAlg.cxx:43
virtual void reconfigure(fhicl::ParameterSet const &pset)
a handler for the case where the algorithm control parameters are to be reset
PCASeedFinderAlg m_pcaSeedFinderAlg
Use PCA axis to find seeds.
ParallelHitsSeedFinderAlg m_parallelHitsAlg
Deal with parallel hits clusters.
std::unique_ptr< lar_cluster3d::IClusterModAlg > m_clusterMergeAlg
Algorithm to do cluster merging.
std::unique_ptr< lar_cluster3d::IHit3DBuilder > m_hit3DBuilderAlg
Builds the 3D hits to operate on.
PrincipalComponentsAlg m_pcaAlg
Principal Components algorithm.
bool m_enableMonitoring
Turn on monitoring of this algorithm.
void art::Consumer::showMissingConsumes ( ) const
protectedinherited

Definition at line 125 of file Consumer.cc.

Referenced by art::EDProducer::doEndJob(), art::EDFilter::doEndJob(), art::EDAnalyzer::doEndJob(), and art::RootOutput::endJob().

126 {
127  if (!moduleContext_)
128  return;
129 
130  // If none of the branches have missing consumes statements, exit early.
131  if (std::all_of(cbegin(missingConsumes_),
132  cend(missingConsumes_),
133  [](auto const& perBranch) { return perBranch.empty(); }))
134  return;
135 
136  constexpr cet::HorizontalRule rule{60};
137  mf::LogPrint log{"MTdiagnostics"};
138  log << '\n'
139  << rule('=') << '\n'
140  << "The following consumes (or mayConsume) statements are missing from\n"
141  << module_context(moduleDescription_) << '\n'
142  << rule('-') << '\n';
143 
144  cet::for_all_with_index(
145  missingConsumes_, [&log](std::size_t const i, auto const& perBranch) {
146  for (auto const& pi : perBranch) {
147  log << " "
148  << assemble_consumes_statement(static_cast<BranchType>(i), pi)
149  << '\n';
150  }
151  });
152  log << rule('=');
153 }
cet::exempt_ptr< ModuleDescription const > moduleDescription_
Definition: Consumer.h:140
constexpr T pi()
Returns the constant pi (up to 35 decimal digits of precision)
bool moduleContext_
Definition: Consumer.h:136
ConsumableProductSets missingConsumes_
Definition: Consumer.h:139
void lar_cluster3d::Cluster3D::splitClustersWithHough ( reco::ClusterParameters clusterParameters,
reco::ClusterParametersList clusterParametersList 
) const
private

Attempt to split clusters using the output of the Hough Filter.

Parameters
clusterParametersThe given cluster parameters object to try to split
clusterParametersListThe list of clusters

Definition at line 923 of file Cluster3D_module.cc.

References lar_cluster3d::SkeletonAlg::AverageSkeletonPositions(), lar_cluster3d::ClusterParamsBuilder::FillClusterParams(), lar_cluster3d::HoughSeedFinderAlg::findTrackHits(), reco::PrincipalComponents::getAveHitDoca(), reco::ClusterParameters::getClusterParams(), reco::ClusterParameters::getFullPCA(), reco::ClusterParameters::getHitPairListPtr(), lar_cluster3d::SkeletonAlg::GetSkeletonHits(), reco::ClusterParameters::getSkeletonPCA(), reco::PrincipalComponents::getSvdOK(), m_clusterBuilder, m_pcaAlg, m_seedFinderAlg, m_skeletonAlg, lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_3D(), lar_cluster3d::PrincipalComponentsAlg::PCAAnalysis_calc3DDocas(), and x1.

925 {
926  // @brief A method for splitted "crossed tracks" clusters into separate clusters
927  //
928  // If this routine is called then we believe we have a cluster which needs splitting.
929  // The specific topology we are looking for is two long straight tracks which cross at some
930  // point in close proximity so their hits were joined into a single 3D cluster. The method
931  // to split this topology is to let the hough transform algorithm find the two leading candidates
932  // and then to see if we use those to build two clusters instead of one.
933 
934  // Recover the hits we'll work on.
935  // Note that we use on the skeleton hits so will need to recover them
936  reco::HitPairListPtr& hitPairListPtr = clusterParameters.getHitPairListPtr();
937  reco::HitPairListPtr skeletonListPtr;
938 
939  // We want to work with the "skeleton" hits so first step is to call the algorithm to
940  // recover only these hits from the entire input collection
941  m_skeletonAlg.GetSkeletonHits(hitPairListPtr, skeletonListPtr);
942 
943  // Skeleton hits are nice but we can do better if we then make a pass through to "average"
944  // the skeleton hits position in the Y-Z plane
945  m_skeletonAlg.AverageSkeletonPositions(skeletonListPtr);
946 
947  // Define the container for our lists of hits
948  reco::HitPairListPtrList hitPairListPtrList;
949 
950  // Now feed this to the Hough Transform to find candidate straight lines
951  m_seedFinderAlg.findTrackHits(skeletonListPtr, clusterParameters.getSkeletonPCA(), hitPairListPtrList);
952 
953  // We need at least two lists or else there is nothing to do
954  if (hitPairListPtrList.size() < 2) return;
955 
956  // The game plan will be the following:
957  // 1) Take the first list of hits and run the PCA on this to get an axis
958  // - Then calculate the 3d doca for ALL hits in the cluster to this axis
959  // - Move all hits within "3 sigam" of the axis to a new list
960  // 2) run the PCA on the second list of hits to get that axis
961  // - Then calculate the 3d doca for all hits in our first list
962  // - Copy hits in the first list which are within 3 sigma of the new axis
963  // back into our original cluster - these are shared hits
964  reco::HitPairListPtrList::iterator hitPairListIter = hitPairListPtrList.begin();
965  reco::HitPairListPtr& firstHitList = *hitPairListIter++;
966  reco::PrincipalComponents firstHitListPCA;
967 
968  m_pcaAlg.PCAAnalysis_3D(firstHitList, firstHitListPCA);
969 
970  // Make sure we have a successful calculation.
971  if (firstHitListPCA.getSvdOK())
972  {
973  // The fill routines below will expect to see unused 2D hits so we need to clear the
974  // status bits... and I am not sure of a better way...
975  for(const auto& hit3D : hitPairListPtr)
976  {
977  for(const auto& hit2D : hit3D->getHits())
978  if (hit2D) hit2D->clearStatusBits(0x1);
979  }
980 
981  // Calculate the 3D doca's for the hits which were used to make this PCA
982  m_pcaAlg.PCAAnalysis_calc3DDocas(firstHitList, firstHitListPCA);
983 
984  // Divine from the ether some maximum allowed range for transfering hits
985  float allowedHitRange = 6. * firstHitListPCA.getAveHitDoca();
986 
987  // Now go through and calculate the 3D doca's for ALL the hits in the original cluster
988  m_pcaAlg.PCAAnalysis_calc3DDocas(hitPairListPtr, firstHitListPCA);
989 
990  // Let's make a new cluster to hold the hits
991  clusterParametersList.push_back(reco::ClusterParameters());
992 
993  // Can we get a reference to what we just created?
994  reco::ClusterParameters& newClusterParams = clusterParametersList.back();
995 
996  reco::HitPairListPtr& newClusterHitList = newClusterParams.getHitPairListPtr();
997 
998  newClusterHitList.resize(hitPairListPtr.size());
999 
1000  // Do the actual copy of the hits we want
1001  reco::HitPairListPtr::iterator newListEnd =
1002  std::copy_if(hitPairListPtr.begin(), hitPairListPtr.end(), newClusterHitList.begin(), CopyIfInRange(allowedHitRange));
1003 
1004  // Shrink to fit
1005  newClusterHitList.resize(std::distance(newClusterHitList.begin(), newListEnd));
1006 
1007  // And now remove these hits from the original cluster
1008  hitPairListPtr.remove_if(CopyIfInRange(allowedHitRange));
1009 
1010  // Get an empty hit to cluster map...
1011  reco::Hit2DToClusterMap hit2DToClusterMap;
1012 
1013  // Now "fill" the cluster parameters but turn off the hit rejection
1014  m_clusterBuilder.FillClusterParams(newClusterParams, hit2DToClusterMap, 0., 1.);
1015 
1016  // Set the skeleton pca to the value calculated above on input
1017  clusterParameters.getSkeletonPCA() = firstHitListPCA;
1018 
1019  // We are done with splitting out one track. Because the two tracks cross in
1020  // close proximity, this is the one case where we might consider sharing 3D hits
1021  // So let's make a little detour here to try to copy some of those hits back into
1022  // the main hit list
1023  reco::HitPairListPtr& secondHitList = *hitPairListIter;
1024  reco::PrincipalComponents secondHitListPCA;
1025 
1026  m_pcaAlg.PCAAnalysis_3D(secondHitList, secondHitListPCA);
1027 
1028  // Make sure we have a successful calculation.
1029  if (secondHitListPCA.getSvdOK())
1030  {
1031  // Calculate the 3D doca's for the hits which were used to make this PCA
1032  m_pcaAlg.PCAAnalysis_calc3DDocas(secondHitList, secondHitListPCA);
1033 
1034  // Since this is the "other" cluster, we'll be a bit more generous in adding back hits
1035  float newAllowedHitRange = 6. * secondHitListPCA.getAveHitDoca();
1036 
1037  // Go through and calculate the 3D doca's for the hits in our new candidate cluster
1038  m_pcaAlg.PCAAnalysis_calc3DDocas(newClusterHitList, secondHitListPCA);
1039 
1040  // Create a temporary list to fill with the hits we might want to save
1041  reco::HitPairListPtr tempHitList(newClusterHitList.size());
1042 
1043  // Do the actual copy of the hits we want...
1044  reco::HitPairListPtr::iterator tempListEnd =
1045  std::copy_if(newClusterHitList.begin(), newClusterHitList.end(), tempHitList.begin(), CopyIfInRange(newAllowedHitRange));
1046 
1047  hitPairListPtr.insert(hitPairListPtr.end(), tempHitList.begin(), tempListEnd);
1048  }
1049 
1050  // Of course, now we need to modify the original cluster parameters
1051  reco::ClusterParameters originalParams(hitPairListPtr);
1052 
1053  // Now "fill" the cluster parameters but turn off the hit rejection
1054  m_clusterBuilder.FillClusterParams(originalParams, hit2DToClusterMap, 0., 1.);
1055 
1056  // Overwrite original cluster parameters with our new values
1057  clusterParameters.getClusterParams() = originalParams.getClusterParams();
1058  clusterParameters.getFullPCA() = originalParams.getFullPCA();
1059  clusterParameters.getSkeletonPCA() = secondHitListPCA;
1060  }
1061 
1062  return;
1063 }
void PCAAnalysis_calc3DDocas(const reco::HitPairListPtr &hitPairVector, const reco::PrincipalComponents &pca) const
bool getSvdOK() const
Definition: Cluster3D.h:224
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
intermediate_table::iterator iterator
Float_t x1[n_points_granero]
Definition: compare.C:5
reco::PrincipalComponents & getSkeletonPCA()
Definition: Cluster3D.h:406
SkeletonAlg m_skeletonAlg
Skeleton point finder.
std::list< HitPairListPtr > HitPairListPtrList
Definition: Cluster3D.h:317
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:404
reco::PlaneToClusterParamsMap & getClusterParams()
Definition: Cluster3D.h:402
HoughSeedFinderAlg m_seedFinderAlg
Seed finder.
void GetSkeletonHits(const reco::HitPairListPtr &inputHitList, reco::HitPairListPtr &skeletonHitList) const
Return the skeleton hits from the input list.
void FillClusterParams(reco::ClusterParameters &, reco::Hit2DToClusterMap &, double minUniqueFrac=0., double maxLostFrac=1.) const
Fill the cluster parameters (expose to outside world for case of splitting/merging clusters) ...
reco::PrincipalComponents & getFullPCA()
Definition: Cluster3D.h:405
void AverageSkeletonPositions(reco::HitPairListPtr &skeletonHitList) const
Modifies the position of input skeleton hits by averaging along the "best" wire direction.
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:315
virtual bool findTrackHits(reco::HitPairListPtr &hitPairListPtr, reco::PrincipalComponents &inputPCA, reco::HitPairListPtrList &hitPairListPtrList) const
Given the list of hits this will return the sets of hits which belong on the same line...
ClusterParamsBuilder m_clusterBuilder
Common cluster builder tool.
const float getAveHitDoca() const
Definition: Cluster3D.h:229
PrincipalComponentsAlg m_pcaAlg
Principal Components algorithm.
std::unordered_map< const reco::ClusterHit2D *, ClusterToHitPairSetMap > Hit2DToClusterMap
Definition: Cluster3D.h:437
void lar_cluster3d::Cluster3D::splitClustersWithMST ( reco::ClusterParameters clusterParameters,
reco::ClusterParametersList clusterParametersList 
) const
private

Attempt to split clusters by using a minimum spanning tree.

Parameters
clusterParametersThe given cluster parameters object to try to split
clusterParametersListThe list of clusters

Definition at line 733 of file Cluster3D_module.cc.

References lar_cluster3d::SkeletonAlg::AverageSkeletonPositions(), reco::ClusterHit3D::bitsAreSet(), reco::ClusterHit3D::clearStatusBits(), reco::PrincipalComponents::getEigenValues(), reco::ClusterParameters::getHitPairListPtr(), reco::ClusterHit3D::getPosition(), lar_cluster3d::SkeletonAlg::GetSkeletonHits(), reco::ClusterParameters::getSkeletonPCA(), art::left(), m_skeletonAlg, art::right(), reco::ClusterHit3D::SELECTEDBYMST, and reco::ClusterHit3D::setStatusBit().

734 {
735  // This is being left in place for future development. Essentially, it was an attempt to implement
736  // a Minimum Spanning Tree as a way to split a particular cluster topology, one where two straight
737  // tracks cross closely enought to appear as one cluster. As of Feb 2, 2015 I think the idea is still
738  // worth merit so am leaving this module in place for now.
739  //
740  // If this routine is called then we believe we have a cluster which needs splitting.
741  // The way we will do this is to use a Minimum Spanning Tree algorithm to associate all
742  // hits together by their distance apart. In theory, we should be able to split the cluster
743  // by finding the largest distance and splitting at that point.
744  //
745  // Typedef some data structures that we will use.
746  // Start with the adjacency map
747  typedef std::pair<float, const reco::ClusterHit3D*> DistanceHit3DPair;
748  typedef std::list<DistanceHit3DPair > DistanceHit3DPairList;
749  typedef std::map<const reco::ClusterHit3D*, DistanceHit3DPairList > Hit3DToDistanceMap;
750 
751  // Now typedef the lists we'll keep
752  typedef std::list<const reco::ClusterHit3D*> Hit3DList;
753  typedef std::pair<Hit3DList::iterator, Hit3DList::iterator> Hit3DEdgePair;
754  typedef std::pair<float, Hit3DEdgePair > DistanceEdgePair;
755  typedef std::list<DistanceEdgePair > DistanceEdgePairList;
756 
757  struct DistanceEdgePairOrder
758  {
759  bool operator()(const DistanceEdgePair& left, const DistanceEdgePair& right) const
760  {
761  return left.first > right.first;
762  }
763  };
764 
765  // Recover the hits we'll work on.
766  // Note that we use on the skeleton hits so will need to recover them
767  reco::HitPairListPtr& hitPairListPtr = clusterParameters.getHitPairListPtr();
768  reco::HitPairListPtr skeletonListPtr;
769 
770  // We want to work with the "skeleton" hits so first step is to call the algorithm to
771  // recover only these hits from the entire input collection
772  m_skeletonAlg.GetSkeletonHits(hitPairListPtr, skeletonListPtr);
773 
774  // Skeleton hits are nice but we can do better if we then make a pass through to "average"
775  // the skeleton hits position in the Y-Z plane
776  m_skeletonAlg.AverageSkeletonPositions(skeletonListPtr);
777 
778  // First task is to define and build the adjacency map
779  Hit3DToDistanceMap hit3DToDistanceMap;
780 
781  for(reco::HitPairListPtr::const_iterator hit3DOuterItr = skeletonListPtr.begin(); hit3DOuterItr != skeletonListPtr.end(); )
782  {
783  const reco::ClusterHit3D* hit3DOuter = *hit3DOuterItr++;
784  DistanceHit3DPairList& outerHitList = hit3DToDistanceMap[hit3DOuter];
785  TVector3 outerPos(hit3DOuter->getPosition()[0], hit3DOuter->getPosition()[1], hit3DOuter->getPosition()[2]);
786 
787  for(reco::HitPairListPtr::const_iterator hit3DInnerItr = hit3DOuterItr; hit3DInnerItr != skeletonListPtr.end(); hit3DInnerItr++)
788  {
789  const reco::ClusterHit3D* hit3DInner = *hit3DInnerItr;
790  TVector3 innerPos(hit3DInner->getPosition()[0], hit3DInner->getPosition()[1], hit3DInner->getPosition()[2]);
791  TVector3 deltaPos = innerPos - outerPos;
792  float hitDistance(float(deltaPos.Mag()));
793 
794  if (hitDistance > 20.) continue;
795 
796  hit3DToDistanceMap[hit3DInner].emplace_back(DistanceHit3DPair(hitDistance,hit3DOuter));
797  outerHitList.emplace_back(DistanceHit3DPair(hitDistance,hit3DInner));
798  }
799 
800  // Make sure our membership bit is clear
802  }
803 
804  // Make pass through again to order each of the lists
805  for(auto& mapPair : hit3DToDistanceMap)
806  {
807  mapPair.second.sort(Hit3DDistanceOrder());
808  }
809 
810  // Get the containers for the MST to operate on/with
811  Hit3DList hit3DList;
812  DistanceEdgePairList distanceEdgePairList;
813 
814  // Initialize with first element
815  hit3DList.emplace_back(skeletonListPtr.front());
816  distanceEdgePairList.emplace_back(DistanceEdgePair(0.,Hit3DEdgePair(hit3DList.begin(),hit3DList.begin())));
817 
818  skeletonListPtr.front()->setStatusBit(reco::ClusterHit3D::SELECTEDBYMST);
819 
820  float largestDistance(0.);
821  float averageDistance(0.);
822 
823  // Now run the MST
824  // Basically, we loop until the MST list is the same size as the input list
825  while(hit3DList.size() < skeletonListPtr.size())
826  {
827  Hit3DList::iterator bestHit3DIter = hit3DList.begin();
828  float bestDist = 10000000.;
829 
830  // Loop through all hits currently in the list and look for closest hit not in the list
831  for(Hit3DList::iterator hit3DIter = hit3DList.begin(); hit3DIter != hit3DList.end(); hit3DIter++)
832  {
833  const reco::ClusterHit3D* hit3D = *hit3DIter;
834 
835  // For the given 3D hit, find the closest to it that is not already in the list
836  DistanceHit3DPairList& nearestList = hit3DToDistanceMap[hit3D];
837 
838  while(!nearestList.empty())
839  {
840  const reco::ClusterHit3D* hit3DToCheck = nearestList.front().second;
841 
842  if (!hit3DToCheck->bitsAreSet(reco::ClusterHit3D::SELECTEDBYMST))
843  {
844  if (nearestList.front().first < bestDist)
845  {
846  bestHit3DIter = hit3DIter;
847  bestDist = nearestList.front().first;
848  }
849 
850  break;
851  }
852  else nearestList.pop_front();
853  }
854  }
855 
856  if (bestDist > largestDistance) largestDistance = bestDist;
857 
858  averageDistance += bestDist;
859 
860  // Now we add the best hit not in the list to our list, keep track of the distance
861  // to the object it was closest to
862  const reco::ClusterHit3D* bestHit3D = *bestHit3DIter; // "best" hit already in the list
863  const reco::ClusterHit3D* nextHit3D = hit3DToDistanceMap[bestHit3D].front().second; // "next" hit we are adding to the list
864 
865  Hit3DList::iterator nextHit3DIter = hit3DList.insert(hit3DList.end(),nextHit3D);
866 
867  distanceEdgePairList.emplace_back(DistanceEdgePair(bestDist,Hit3DEdgePair(bestHit3DIter,nextHit3DIter)));
868 
870  }
871 
872  averageDistance /= float(hit3DList.size());
873 
874  float thirdDist = 2.*sqrt(clusterParameters.getSkeletonPCA().getEigenValues()[2]);
875 
876  // Ok, find the largest distance in the iterator map
877  distanceEdgePairList.sort(DistanceEdgePairOrder());
878 
879  DistanceEdgePairList::iterator largestDistIter = distanceEdgePairList.begin();
880 
881  for(DistanceEdgePairList::iterator edgeIter = distanceEdgePairList.begin(); edgeIter != distanceEdgePairList.end(); edgeIter++)
882  {
883  if (edgeIter->first < thirdDist) break;
884 
885  largestDistIter = edgeIter;
886  }
887 
888  reco::HitPairListPtr::iterator breakIter = largestDistIter->second.second;
889  reco::HitPairListPtr bestList;
890 
891  bestList.resize(std::distance(hit3DList.begin(), breakIter));
892 
893  std::copy(hit3DList.begin(), breakIter, bestList.begin());
894 
895  // Remove from the grand hit list and see what happens...
896  // The pieces below are incomplete and were really for testing only.
897  hitPairListPtr.sort();
898  bestList.sort();
899 
900  reco::HitPairListPtr::iterator newListEnd =
901  std::set_difference(hitPairListPtr.begin(), hitPairListPtr.end(),
902  bestList.begin(), bestList.end(),
903  hitPairListPtr.begin() );
904 
905  hitPairListPtr.erase(newListEnd, hitPairListPtr.end());
906 
907  return;
908 }
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
intermediate_table::iterator iterator
reco::PrincipalComponents & getSkeletonPCA()
Definition: Cluster3D.h:406
void clearStatusBits(unsigned bits) const
Definition: Cluster3D.h:164
SkeletonAlg m_skeletonAlg
Skeleton point finder.
reco::HitPairListPtr & getHitPairListPtr()
Definition: Cluster3D.h:404
void GetSkeletonHits(const reco::HitPairListPtr &inputHitList, reco::HitPairListPtr &skeletonHitList) const
Return the skeleton hits from the input list.
Hit has been used in Cluster Splitting MST.
Definition: Cluster3D.h:103
intermediate_table::const_iterator const_iterator
void AverageSkeletonPositions(reco::HitPairListPtr &skeletonHitList) const
Modifies the position of input skeleton hits by averaging along the "best" wire direction.
std::list< const reco::ClusterHit3D * > HitPairListPtr
Definition: Cluster3D.h:315
const float * getPosition() const
Definition: Cluster3D.h:145
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:104
bool bitsAreSet(const unsigned int &bitsToCheck) const
Definition: Cluster3D.h:160
const float * getEigenValues() const
Definition: Cluster3D.h:226
void setStatusBit(unsigned bits) const
Definition: Cluster3D.h:163
void art::Consumer::validateConsumedProduct ( BranchType const  bt,
ProductInfo const &  pi 
)
protectedinherited

Definition at line 101 of file Consumer.cc.

References art::errors::ProductRegistrationFailure.

103 {
104  // Early exits if consumes tracking has been disabled or if the
105  // consumed product is an allowed consumable.
106  if (!moduleContext_)
107  return;
108 
109  if (cet::binary_search_all(consumables_[bt], pi))
110  return;
111 
112  if (requireConsumes_) {
114  "Consumer: an error occurred during validation of a "
115  "retrieved product\n\n")
116  << "The following consumes (or mayConsume) statement is missing from\n"
117  << module_context(moduleDescription_) << ":\n\n"
118  << " " << assemble_consumes_statement(bt, pi) << "\n\n";
119  }
120 
121  missingConsumes_[bt].insert(pi);
122 }
cet::exempt_ptr< ModuleDescription const > moduleDescription_
Definition: Consumer.h:140
bool requireConsumes_
Definition: Consumer.h:137
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
constexpr T pi()
Returns the constant pi (up to 35 decimal digits of precision)
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
ConsumableProductSets missingConsumes_
Definition: Consumer.h:139

Member Data Documentation

float lar_cluster3d::Cluster3D::m_artHitsTime
private

Keeps track of time to recover hits.

Definition at line 397 of file Cluster3D_module.cc.

Referenced by InitializeMonitoring(), PrepareEvent(), and produce().

float lar_cluster3d::Cluster3D::m_buildNeighborhoodTime
private

Keeps track of time to build epsilon neighborhood.

Definition at line 399 of file Cluster3D_module.cc.

Referenced by InitializeMonitoring(), PrepareEvent(), and produce().

std::unique_ptr<lar_cluster3d::IClusterAlg> lar_cluster3d::Cluster3D::m_clusterAlg
private

Algorithm to do 3D space point clustering.

Definition at line 413 of file Cluster3D_module.cc.

Referenced by produce(), and reconfigure().

ClusterParamsBuilder lar_cluster3d::Cluster3D::m_clusterBuilder
private

Common cluster builder tool.

Definition at line 416 of file Cluster3D_module.cc.

Referenced by splitClustersWithHough().

std::unique_ptr<lar_cluster3d::IClusterModAlg> lar_cluster3d::Cluster3D::m_clusterMergeAlg
private

Algorithm to do cluster merging.

Definition at line 414 of file Cluster3D_module.cc.

Referenced by produce(), and reconfigure().

std::unique_ptr<lar_cluster3d::IClusterModAlg> lar_cluster3d::Cluster3D::m_clusterPathAlg
private

Algorithm to do cluster path finding.

Definition at line 415 of file Cluster3D_module.cc.

Referenced by produce(), and reconfigure().

float lar_cluster3d::Cluster3D::m_dbscanTime
private

Keeps track of time to run DBScan.

Definition at line 400 of file Cluster3D_module.cc.

Referenced by InitializeMonitoring(), PrepareEvent(), and produce().

const detinfo::DetectorProperties* lar_cluster3d::Cluster3D::m_detector
private

Pointer to the detector properties.

Definition at line 409 of file Cluster3D_module.cc.

Referenced by beginJob(), and ConvertToArtOutput().

bool lar_cluster3d::Cluster3D::m_enableMonitoring
private

Turn on monitoring of this algorithm.

Algorithm parameters

Definition at line 385 of file Cluster3D_module.cc.

Referenced by beginJob(), produce(), and reconfigure().

int lar_cluster3d::Cluster3D::m_event
private

Definition at line 394 of file Cluster3D_module.cc.

Referenced by InitializeMonitoring(), PrepareEvent(), and produce().

float lar_cluster3d::Cluster3D::m_finishTime
private

Keeps track of time to run output module.

Definition at line 402 of file Cluster3D_module.cc.

Referenced by InitializeMonitoring(), PrepareEvent(), and produce().

geo::Geometry* lar_cluster3d::Cluster3D::m_geometry
private

pointer to the Geometry service

Other useful variables

Definition at line 408 of file Cluster3D_module.cc.

Referenced by beginJob().

std::unique_ptr<lar_cluster3d::IHit3DBuilder> lar_cluster3d::Cluster3D::m_hit3DBuilderAlg
private

Builds the 3D hits to operate on.

Definition at line 412 of file Cluster3D_module.cc.

Referenced by produce(), and reconfigure().

int lar_cluster3d::Cluster3D::m_hits
private

Keeps track of the number of hits seen.

Definition at line 395 of file Cluster3D_module.cc.

Referenced by InitializeMonitoring(), PrepareEvent(), and produce().

float lar_cluster3d::Cluster3D::m_makeHitsTime
private

Keeps track of time to build 3D hits.

Definition at line 398 of file Cluster3D_module.cc.

Referenced by InitializeMonitoring(), PrepareEvent(), and produce().

ParallelHitsSeedFinderAlg lar_cluster3d::Cluster3D::m_parallelHitsAlg
private

Deal with parallel hits clusters.

Definition at line 421 of file Cluster3D_module.cc.

Referenced by findTrackSeeds(), and reconfigure().

float lar_cluster3d::Cluster3D::m_parallelHitsCosAng
private

Cut for PCA 3rd axis angle to X axis.

Definition at line 386 of file Cluster3D_module.cc.

Referenced by aParallelHitsCluster(), and reconfigure().

float lar_cluster3d::Cluster3D::m_parallelHitsTransWid
private

Cut on transverse width of cluster (PCA 2nd eigenvalue)

Definition at line 387 of file Cluster3D_module.cc.

Referenced by aParallelHitsCluster(), and reconfigure().

float lar_cluster3d::Cluster3D::m_pathFindingTime
private

Keeps track of the path finding time.

Definition at line 401 of file Cluster3D_module.cc.

Referenced by InitializeMonitoring(), PrepareEvent(), and produce().

PrincipalComponentsAlg lar_cluster3d::Cluster3D::m_pcaAlg
private

Principal Components algorithm.

Definition at line 417 of file Cluster3D_module.cc.

Referenced by reconfigure(), and splitClustersWithHough().

PCASeedFinderAlg lar_cluster3d::Cluster3D::m_pcaSeedFinderAlg
private

Use PCA axis to find seeds.

Definition at line 420 of file Cluster3D_module.cc.

Referenced by findTrackSeeds(), and reconfigure().

TTree* lar_cluster3d::Cluster3D::m_pRecoTree
private

Tree variables for output

Definition at line 392 of file Cluster3D_module.cc.

Referenced by InitializeMonitoring(), and produce().

int lar_cluster3d::Cluster3D::m_run
private

Definition at line 393 of file Cluster3D_module.cc.

Referenced by InitializeMonitoring(), PrepareEvent(), and produce().

HoughSeedFinderAlg lar_cluster3d::Cluster3D::m_seedFinderAlg
private

Seed finder.

Definition at line 419 of file Cluster3D_module.cc.

Referenced by findTrackSeeds(), reconfigure(), and splitClustersWithHough().

SkeletonAlg lar_cluster3d::Cluster3D::m_skeletonAlg
private

Skeleton point finder.

Definition at line 418 of file Cluster3D_module.cc.

Referenced by findTrackSeeds(), reconfigure(), splitClustersWithHough(), and splitClustersWithMST().

std::string lar_cluster3d::Cluster3D::m_spacePointInstance
private

Special instance name for vertex points.

Definition at line 403 of file Cluster3D_module.cc.

Referenced by Cluster3D(), and produce().

float lar_cluster3d::Cluster3D::m_totalTime
private

Keeps track of total execution time.

Definition at line 396 of file Cluster3D_module.cc.

Referenced by InitializeMonitoring(), PrepareEvent(), and produce().


The documentation for this class was generated from the following file: