Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
LArPandoraTrackCreation_module.cc
Go to the documentation of this file.
1
8
9#include "art/Framework/Core/EDProducer.h"
10#include "art/Framework/Core/ModuleMacros.h"
11#include "art/Framework/Principal/Event.h"
12
13#include "fhiclcpp/ParameterSet.h"
14
15#include "lardataobj/RecoBase/Hit.h"
16#include "lardataobj/RecoBase/SpacePoint.h"
17#include "lardataobj/RecoBase/Track.h"
18#include "lardataobj/RecoBase/TrackHitMeta.h"
19
20#include <memory>
21
22namespace lar_pandora {
23
24 class LArPandoraTrackCreation : public art::EDProducer {
25 public:
26 explicit LArPandoraTrackCreation(fhicl::ParameterSet const& pset);
27
32
33 void produce(art::Event& evt) override;
34
35 private:
42 recob::Track BuildTrack(const int id,
43 const lar_content::LArTrackStateVector& trackStateVector) const;
44
45 std::string m_pfParticleLabel;
46 unsigned int m_minTrajectoryPoints;
49 };
50
51 DEFINE_ART_MODULE(LArPandoraTrackCreation)
52
53} // namespace lar_pandora
54
55//------------------------------------------------------------------------------------------------------------------------------------------
56// implementation follows
57
58#include "art/Framework/Principal/Handle.h"
59#include "art/Framework/Principal/Run.h"
60#include "art/Framework/Principal/SubRun.h"
61
62#include "art/Persistency/Common/PtrMaker.h"
63
64#include "canvas/Utilities/InputTag.h"
65
66#include "larcore/Geometry/Geometry.h"
67
68#include "lardata/Utilities/AssociationUtil.h"
69
70#include "lardataobj/RecoBase/PFParticle.h"
71#include "lardataobj/RecoBase/SpacePoint.h"
72#include "lardataobj/RecoBase/Track.h"
73#include "lardataobj/RecoBase/Vertex.h"
74
75#include "messagefacility/MessageLogger/MessageLogger.h"
76
78
82
83#include <iostream>
84
85namespace lar_pandora {
86
87 LArPandoraTrackCreation::LArPandoraTrackCreation(fhicl::ParameterSet const& pset)
88 : EDProducer{pset}
89 , m_pfParticleLabel(pset.get<std::string>("PFParticleLabel"))
90 , m_minTrajectoryPoints(pset.get<unsigned int>("MinTrajectoryPoints", 2))
91 , m_slidingFitHalfWindow(pset.get<unsigned int>("SlidingFitHalfWindow", 20))
92 , m_useAllParticles(pset.get<bool>("UseAllParticles", false))
93 {
94 produces<std::vector<recob::Track>>();
95 produces<art::Assns<recob::PFParticle, recob::Track>>();
96 produces<art::Assns<recob::Track, recob::Hit>>();
97 produces<art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>>();
98
100 throw cet::exception("LArPandoraTrackCreation")
101 << "MinTrajectoryPoints should not be smaller than 2!";
102 }
103
104 //------------------------------------------------------------------------------------------------------------------------------------------
105
107 {
108 std::unique_ptr<std::vector<recob::Track>> outputTracks(new std::vector<recob::Track>);
109 std::unique_ptr<art::Assns<recob::PFParticle, recob::Track>> outputParticlesToTracks(
110 new art::Assns<recob::PFParticle, recob::Track>);
111 std::unique_ptr<art::Assns<recob::Track, recob::Hit>> outputTracksToHits(
112 new art::Assns<recob::Track, recob::Hit>);
113 std::unique_ptr<art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>>
114 outputTracksToHitsWithMeta(new art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>);
115
117 // 'wirePitchW` is here used only to provide length scale for binning hits and performing sliding/local linear fits.
118 const float wirePitchW(detType->WirePitchW());
119
120 int trackCounter(0);
121 const art::PtrMaker<recob::Track> makeTrackPtr(evt);
122
123 // Organise inputs
124 PFParticleVector pfParticleVector, extraPfParticleVector;
125 PFParticlesToSpacePoints pfParticlesToSpacePoints;
126 PFParticlesToClusters pfParticlesToClusters;
128 evt, m_pfParticleLabel, pfParticleVector, pfParticlesToSpacePoints);
130 evt, m_pfParticleLabel, extraPfParticleVector, pfParticlesToClusters);
131
132 VertexVector vertexVector;
133 PFParticlesToVertices pfParticlesToVertices;
134 LArPandoraHelper::CollectVertices(evt, m_pfParticleLabel, vertexVector, pfParticlesToVertices);
135
136 for (const art::Ptr<recob::PFParticle> pPFParticle : pfParticleVector) {
137 // Select track-like pfparticles
138 if (!m_useAllParticles && !LArPandoraHelper::IsTrack(pPFParticle)) continue;
139
140 // Obtain associated spacepoints
141 PFParticlesToSpacePoints::const_iterator particleToSpacePointIter(
142 pfParticlesToSpacePoints.find(pPFParticle));
143
144 if (pfParticlesToSpacePoints.end() == particleToSpacePointIter) {
145 mf::LogDebug("LArPandoraTrackCreation") << "No spacepoints associated to particle ";
146 continue;
147 }
148
149 // Obtain associated clusters
150 PFParticlesToClusters::const_iterator particleToClustersIter(
151 pfParticlesToClusters.find(pPFParticle));
152
153 if (pfParticlesToClusters.end() == particleToClustersIter) {
154 mf::LogDebug("LArPandoraShowerCreation") << "No clusters associated to particle ";
155 continue;
156 }
157
158 // Obtain associated vertex
159 PFParticlesToVertices::const_iterator particleToVertexIter(
160 pfParticlesToVertices.find(pPFParticle));
161
162 if ((pfParticlesToVertices.end() == particleToVertexIter) ||
163 (1 != particleToVertexIter->second.size())) {
164 mf::LogDebug("LArPandoraTrackCreation") << "Unexpected number of vertices for particle ";
165 continue;
166 }
167
168 // Copy information into expected pandora form
169 pandora::CartesianPointVector cartesianPointVector;
170 for (const art::Ptr<recob::SpacePoint> spacePoint : particleToSpacePointIter->second)
171 cartesianPointVector.emplace_back(pandora::CartesianVector(
172 spacePoint->XYZ()[0], spacePoint->XYZ()[1], spacePoint->XYZ()[2]));
173
174 double vertexXYZ[3] = {0., 0., 0.};
175 particleToVertexIter->second.front()->XYZ(vertexXYZ);
176 const pandora::CartesianVector vertexPosition(vertexXYZ[0], vertexXYZ[1], vertexXYZ[2]);
177
178 // Call pandora "fast" track fitter
179 lar_content::LArTrackStateVector trackStateVector;
180 pandora::IntVector indexVector;
181 try {
183 vertexPosition,
185 wirePitchW,
186 trackStateVector,
187 &indexVector);
188 }
189 catch (const pandora::StatusCodeException&) {
190 mf::LogDebug("LArPandoraTrackCreation") << "Unable to extract sliding fit trajectory";
191 continue;
192 }
193
194 if (trackStateVector.size() < m_minTrajectoryPoints) {
195 mf::LogDebug("LArPandoraTrackCreation")
196 << "Insufficient input trajectory points to build track: " << trackStateVector.size();
197 continue;
198 }
199
200 HitVector hitsFromSpacePoints, hitsFromClusters, hitsInParticle;
201 HitSet hitsInParticleSet;
202
205 particleToSpacePointIter->second,
206 hitsFromSpacePoints,
207 &indexVector);
209 evt, m_pfParticleLabel, particleToClustersIter->second, hitsFromClusters);
210 //ATTN: hits ordered from space points if available, rest added at the end
211 for (unsigned int hitIndex = 0; hitIndex < hitsFromSpacePoints.size(); hitIndex++) {
212 hitsInParticle.push_back(hitsFromSpacePoints.at(hitIndex));
213 (void)hitsInParticleSet.insert(hitsFromSpacePoints.at(hitIndex));
214 }
215
216 for (unsigned int hitIndex = 0; hitIndex < hitsFromClusters.size(); hitIndex++) {
217 if (hitsInParticleSet.count(hitsFromClusters.at(hitIndex)) == 0)
218 hitsInParticle.push_back(hitsFromClusters.at(hitIndex));
219 }
220
221 // Add invalid points at the end of the vector, so that the number of the trajectory points is the same as the number of hits
222 if (trackStateVector.size() > hitsFromSpacePoints.size()) {
223 throw cet::exception("LArPandoraTrackCreation")
224 << "trackStateVector.size() is greater than hitsFromSpacePoints.size()";
225 }
226 const unsigned int nInvalidPoints = hitsInParticle.size() - trackStateVector.size();
227 for (unsigned int i = 0; i < nInvalidPoints; ++i) {
228 trackStateVector.push_back(lar_content::LArTrackState(
229 pandora::CartesianVector(util::kBogusF, util::kBogusF, util::kBogusF),
230 pandora::CartesianVector(util::kBogusF, util::kBogusF, util::kBogusF),
231 nullptr));
232 }
233
234 // Output objects
235 outputTracks->emplace_back(
236 LArPandoraTrackCreation::BuildTrack(trackCounter++, trackStateVector));
237 art::Ptr<recob::Track> pTrack(makeTrackPtr(outputTracks->size() - 1));
238
239 // Output associations, after output objects are in place
240 util::CreateAssn(evt, pTrack, pPFParticle, *(outputParticlesToTracks.get()));
241 util::CreateAssn(evt, *(outputTracks.get()), hitsInParticle, *(outputTracksToHits.get()));
242
243 //ATTN: metadata added with index from space points if available, null for others
244 for (unsigned int hitIndex = 0; hitIndex < hitsInParticle.size(); hitIndex++) {
245 const art::Ptr<recob::Hit> pHit(hitsInParticle.at(hitIndex));
246 const int index((hitIndex < hitsFromSpacePoints.size()) ? hitIndex :
247 std::numeric_limits<int>::max());
248 recob::TrackHitMeta metadata(index, -std::numeric_limits<double>::max());
249 outputTracksToHitsWithMeta->addSingle(pTrack, pHit, metadata);
250 }
251 }
252
253 mf::LogDebug("LArPandoraTrackCreation")
254 << "Number of new tracks: " << outputTracks->size() << std::endl;
255
256 evt.put(std::move(outputTracks));
257 evt.put(std::move(outputTracksToHits));
258 evt.put(std::move(outputTracksToHitsWithMeta));
259 evt.put(std::move(outputParticlesToTracks));
260 }
261
262 //------------------------------------------------------------------------------------------------------------------------------------------
263
265 const int id,
266 const lar_content::LArTrackStateVector& trackStateVector) const
267 {
268 if (trackStateVector.empty())
269 throw cet::exception("LArPandoraTrackCreation")
270 << "BuildTrack - No input trajectory points provided ";
271
272 recob::tracking::Positions_t xyz;
273 recob::tracking::Momenta_t pxpypz;
274 recob::TrackTrajectory::Flags_t flags;
275
276 for (const lar_content::LArTrackState& trackState : trackStateVector) {
277 xyz.emplace_back(recob::tracking::Point_t(trackState.GetPosition().GetX(),
278 trackState.GetPosition().GetY(),
279 trackState.GetPosition().GetZ()));
280 pxpypz.emplace_back(recob::tracking::Vector_t(trackState.GetDirection().GetX(),
281 trackState.GetDirection().GetY(),
282 trackState.GetDirection().GetZ()));
283 // Set flag NoPoint if point has bogus coordinates, otherwise use clean flag set
284 if (std::fabs(trackState.GetPosition().GetX() - util::kBogusF) <
285 std::numeric_limits<float>::epsilon() &&
286 std::fabs(trackState.GetPosition().GetY() - util::kBogusF) <
287 std::numeric_limits<float>::epsilon() &&
288 std::fabs(trackState.GetPosition().GetZ() - util::kBogusF) <
289 std::numeric_limits<float>::epsilon()) {
290 flags.emplace_back(recob::TrajectoryPointFlags(recob::TrajectoryPointFlags::InvalidHitIndex,
291 recob::TrajectoryPointFlagTraits::NoPoint));
292 }
293 else {
294 flags.emplace_back(recob::TrajectoryPointFlags());
295 }
296 }
297
298 // note from gc: eventually we should produce a TrackTrajectory, not a Track with empty covariance matrix and bogus chi2, etc.
299 return recob::Track(
300 recob::TrackTrajectory(std::move(xyz), std::move(pxpypz), std::move(flags), false),
301 util::kBogusI,
302 util::kBogusF,
303 util::kBogusI,
304 recob::tracking::SMatrixSym55(),
305 recob::tracking::SMatrixSym55(),
306 id);
307 }
308
309} // namespace lar_pandora
Helper functions for extracting detector geometry for use in reconsruction.
helper function for LArPandoraInterface producer module
Header file for the pfo helper class.
Header file for lar pfo objects.
static void GetSlidingFitTrajectory(const pandora::CartesianPointVector &pointVector, const pandora::CartesianVector &vertexPosition, const unsigned int layerWindow, const float layerPitch, LArTrackStateVector &trackStateVector, pandora::IntVector *const pIndexVector=nullptr)
Apply 3D sliding fit to a set of 3D points and return track trajectory.
LArTrackState class.
Empty interface to map pandora to specifics in the LArSoft geometry.
virtual float WirePitchW() const =0
The wire pitch of the mapped W view.
static void CollectVertices(const art::Event &evt, const std::string &label, VertexVector &vertexVector, PFParticlesToVertices &particlesToVertices)
Collect the reconstructed PFParticles and associated Vertices from the ART event record.
static void GetAssociatedHits(const art::Event &evt, const std::string &label, const std::vector< art::Ptr< T > > &inputVector, HitVector &associatedHits, const pandora::IntVector *const indexVector=nullptr)
Get all hits associated with input clusters.
static bool IsTrack(const art::Ptr< recob::PFParticle > particle)
Determine whether a particle has been reconstructed as track-like.
static void CollectPFParticles(const art::Event &evt, const std::string &label, PFParticleVector &particleVector)
Collect the reconstructed PFParticles from the ART event record.
LArPandoraTrackCreation(LArPandoraTrackCreation const &)=delete
LArPandoraTrackCreation(fhicl::ParameterSet const &pset)
std::string m_pfParticleLabel
The pf particle label.
recob::Track BuildTrack(const int id, const lar_content::LArTrackStateVector &trackStateVector) const
Build a recob::Track object.
LArPandoraTrackCreation & operator=(LArPandoraTrackCreation const &)=delete
unsigned int m_slidingFitHalfWindow
The sliding fit half window.
unsigned int m_minTrajectoryPoints
The minimum number of trajectory points.
bool m_useAllParticles
Build a recob::Track for every recob::PFParticle.
LArPandoraTrackCreation(LArPandoraTrackCreation &&)=delete
LArPandoraTrackCreation & operator=(LArPandoraTrackCreation &&)=delete
CartesianVector class.
StatusCodeException class.
std::vector< LArTrackState > LArTrackStateVector
LArPandoraDetectorType * GetDetectorType()
Factory class that returns the correct detector type interface.
std::map< art::Ptr< recob::PFParticle >, ClusterVector > PFParticlesToClusters
std::vector< art::Ptr< recob::Vertex > > VertexVector
std::map< art::Ptr< recob::PFParticle >, SpacePointVector > PFParticlesToSpacePoints
std::vector< art::Ptr< recob::Hit > > HitVector
std::vector< art::Ptr< recob::PFParticle > > PFParticleVector
std::unordered_set< art::Ptr< recob::Hit > > HitSet
std::map< art::Ptr< recob::PFParticle >, VertexVector > PFParticlesToVertices
std::vector< int > IntVector
std::vector< CartesianVector > CartesianPointVector