All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Public Member Functions | Private Member Functions | Private Attributes | List of all members
sbn::MergedTrackIdentifier Class Reference
Inheritance diagram for sbn::MergedTrackIdentifier:

Public Member Functions

 MergedTrackIdentifier (fhicl::ParameterSet const &p)
 
 MergedTrackIdentifier (MergedTrackIdentifier const &)=delete
 
 MergedTrackIdentifier (MergedTrackIdentifier &&)=delete
 
MergedTrackIdentifieroperator= (MergedTrackIdentifier const &)=delete
 
MergedTrackIdentifieroperator= (MergedTrackIdentifier &&)=delete
 
void produce (art::Event &e) override
 

Private Member Functions

sbn::MergedTrackInfo BuildTrackInfo (const geo::GeometryCore *geo, const recob::Vertex &vtx, const recob::PFParticle &A, const recob::Track &Atrk, const recob::PFParticle &B, const recob::Track &Btrk, bool assume_a_is_trunk=false)
 

Private Attributes

art::InputTag fPFPLabel
 
art::InputTag fTrackLabel
 

Detailed Description

Definition at line 49 of file MergedTrackIdentifier_module.cc.

Constructor & Destructor Documentation

sbn::MergedTrackIdentifier::MergedTrackIdentifier ( fhicl::ParameterSet const &  p)
explicit

Definition at line 77 of file MergedTrackIdentifier_module.cc.

78  : EDProducer{p},
79  fPFPLabel(p.get<art::InputTag>("PFPLabel", "pandora")),
80  fTrackLabel(p.get<art::InputTag>("TrackLabel", "pandoraTrack"))
81 {
82  produces<std::vector<sbn::MergedTrackInfo>>();
83  produces<art::Assns<sbn::MergedTrackInfo, recob::PFParticle>>();
84 }
pdgs p
Definition: selectors.fcl:22
sbn::MergedTrackIdentifier::MergedTrackIdentifier ( MergedTrackIdentifier const &  )
delete
sbn::MergedTrackIdentifier::MergedTrackIdentifier ( MergedTrackIdentifier &&  )
delete

Member Function Documentation

sbn::MergedTrackInfo sbn::MergedTrackIdentifier::BuildTrackInfo ( const geo::GeometryCore geo,
const recob::Vertex vtx,
const recob::PFParticle A,
const recob::Track Atrk,
const recob::PFParticle B,
const recob::Track Btrk,
bool  assume_a_is_trunk = false 
)
private

Definition at line 102 of file MergedTrackIdentifier_module.cc.

105  {
106 
108 
109  ret.vertex = TVector3(vtx.position().x(), vtx.position().y(), vtx.position().z());
110 
111  ret.direction = (MeanDirection(vtx, Atrk) + MeanDirection(vtx, Btrk)).Unit();
112 
113  bool a_is_trunk = assume_a_is_trunk || ret.direction.Dot(Atrk.Start<TVector3>() - ret.vertex) < ret.direction.Dot(Btrk.Start<TVector3>() - ret.vertex);
114 
115  const recob::PFParticle &trunk = (a_is_trunk) ? A : B;
116  const recob::PFParticle &branch = (a_is_trunk) ? B : A;
117 
118  const recob::Track &trunk_trk = (a_is_trunk) ? Atrk : Btrk;
119  const recob::Track &branch_trk = (a_is_trunk) ? Btrk : Atrk;
120 
121  ret.trunk = trunk.Self();
122  ret.branch = branch.Self();
123 
124  ret.branch_start = ret.direction.Dot(branch_trk.Start<TVector3>() - ret.vertex);
125  ret.trunk_start = ret.direction.Dot(trunk_trk.Start<TVector3>() - ret.vertex);
126 
127  // TVector3 branch_start = branch_trk.LocationAtPoint<TVector3>(branch_trk.FirstValidPoint());
128  // for (unsigned i = 0; i < 3; i++) {
129  // ret.branch_wire_start[i] = geo->WireCoordinate(branch_start.Y(), branch_start.Z(), i, 0, 0);
130 
131  // TVector3 trunk_start = trunk_trk.LocationAtPoint<TVector3>(trunk_trk.FirstValidPoint());
132  // TVector3 trunk_start_p1 = trunk_trk.LocationAtPoint<TVector3>(trunk_trk.NextValidPoint(trunk_trk.FirstValidPoint()+1));
133 
134  // check if the tracks are ascending or descending
135  // ret.trunk_wire_direction_is_ascending[i] =
136  // geo->WireCoordinate(trunk_start.Y(), trunk_start.Z(), i, 0, 0) <
137  // geo->WireCoordinate(trunk_start_p1.Y(), trunk_start_p1.Z(), i, 0, 0);
138  // }
139 
140  bool set = false;
141  float trunk_min = -1;
142  float trunk_max = -1;
143 
144  for (unsigned i = trunk_trk.FirstValidPoint(); i < trunk_trk.NumberTrajectoryPoints(); i = trunk_trk.NextValidPoint(i+1)) {
145  float proj = ret.direction.Dot(trunk_trk.DirectionAtPoint<TVector3>(i) - ret.vertex);
146  if (!set || proj < trunk_min) trunk_min = proj;
147  if (!set || proj > trunk_max) trunk_max = proj;
148  set = true;
149  }
150 
151  unsigned n_point = 0;
152  unsigned n_overlap_point = 0;
153  for (unsigned i = branch_trk.FirstValidPoint(); i < branch_trk.NumberTrajectoryPoints(); i = branch_trk.NextValidPoint(i+1)) {
154  float proj = ret.direction.Dot(branch_trk.DirectionAtPoint<TVector3>(i) - ret.vertex);
155  if (proj > trunk_min && proj < trunk_max) {
156  n_overlap_point ++;
157  }
158  n_point ++;
159  }
160 
161  ret.branch_overlap = ((float)n_overlap_point) / n_point;
162 
163 
164  return ret;
165 }
size_t Self() const
Returns the index of this particle.
Definition: PFParticle.h:92
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
Point_t const & Start() const
Access to track position at different points.
size_t FirstValidPoint() const
Hierarchical representation of particle flow.
Definition: PFParticle.h:44
size_t NextValidPoint(size_t index) const
Vector_t DirectionAtPoint(size_t i) const
TVector3 MeanDirection(const recob::Vertex &vtx, const recob::Track &trk)
const Point_t & position() const
Return vertex 3D position.
Definition: Vertex.h:60
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a &quot;fitted&quot; track:
MergedTrackIdentifier& sbn::MergedTrackIdentifier::operator= ( MergedTrackIdentifier const &  )
delete
MergedTrackIdentifier& sbn::MergedTrackIdentifier::operator= ( MergedTrackIdentifier &&  )
delete
void sbn::MergedTrackIdentifier::produce ( art::Event &  e)
override

Definition at line 167 of file MergedTrackIdentifier_module.cc.

168 {
169  // output data products
170  std::unique_ptr<std::vector<sbn::MergedTrackInfo>> infos(new std::vector<sbn::MergedTrackInfo>);
171  std::unique_ptr<art::Assns<sbn::MergedTrackInfo, recob::PFParticle>> assn(new art::Assns<sbn::MergedTrackInfo, recob::PFParticle>);
172 
173  art::PtrMaker<sbn::MergedTrackInfo> infoPtrMaker {e};
174 
175  // input data
176  art::Handle<std::vector<recob::Slice>> slice_handle;
177  e.getByLabel(fPFPLabel, slice_handle);
178 
179  std::vector<art::Ptr<recob::Slice>> slices;
180  art::fill_ptr_vector(slices, slice_handle);
181 
182  art::FindManyP<recob::PFParticle> slicePFPs(slices, e, fPFPLabel);
183 
184  // services
185  const geo::GeometryCore *geo = lar::providerFrom<geo::Geometry>();
186 
187  for (unsigned i_slc = 0; i_slc < slices.size(); i_slc++) {
188  // collect the PFPs
189  const std::vector<art::Ptr<recob::PFParticle>> &this_slice_pfps = slicePFPs.at(i_slc);
190 
191  art::FindManyP<recob::Vertex> slicePFPVtxs(this_slice_pfps, e, fPFPLabel);
192 
193  art::Ptr<recob::Vertex> vtx;
194  art::Ptr<recob::PFParticle> primary;
195  // get the primary particle in each Slice
196  for (unsigned i_pfp = 0; i_pfp < this_slice_pfps.size(); i_pfp++) {
197  if (this_slice_pfps[i_pfp]->IsPrimary() && slicePFPVtxs.at(i_pfp).size()) {
198  primary = this_slice_pfps[i_pfp];
199  vtx = slicePFPVtxs.at(i_pfp).at(0);
200  break;
201  }
202  }
203 
204  // no primary PFParticle -- ignore
205  if (!primary) continue;
206 
207  std::vector<art::Ptr<recob::PFParticle>> topTracks;
208 
209  // primary is a Neutrino -- will have a number of daughters -- which we call primary
211  for (unsigned d: primary->Daughters()) {
212  for (unsigned i_pfp = 0; i_pfp < this_slice_pfps.size(); i_pfp++) {
213  if (this_slice_pfps[i_pfp]->Self() == d) {
214  if (lar_pandora::LArPandoraHelper::IsTrack(this_slice_pfps[i_pfp])) topTracks.push_back(this_slice_pfps[i_pfp]);
215  break;
216  }
217  }
218  }
219  }
220  // primary is a track -- this is the only top-level-track
221  else if (lar_pandora::LArPandoraHelper::IsTrack(primary)) {
222  topTracks.push_back(primary);
223  }
224 
225  art::FindManyP<recob::Track> topTrackTracks(topTracks, e, fTrackLabel);
226 
227  std::map<art::Ptr<recob::PFParticle>, std::vector<std::pair<art::Ptr<recob::PFParticle>, sbn::MergedTrackInfo>>> possible_merge_parents;
228  std::map<art::Ptr<recob::PFParticle>, std::vector<std::pair<art::Ptr<recob::PFParticle>, sbn::MergedTrackInfo>>> possible_merge_children;
229 
230  // First iterate over all pairs of top-level tracks
231  for (unsigned i = 0; i < topTracks.size(); i++) {
232  for (unsigned j = i+1; j < topTracks.size(); j++) {
233  if (!topTrackTracks.at(i).size() || !topTrackTracks.at(j).size()) continue;
234 
235  sbn::MergedTrackInfo info = BuildTrackInfo(geo, *vtx, *topTracks[i], *topTrackTracks.at(i).at(0), *topTracks[j], *topTrackTracks.at(j).at(0));
236 
237  // std::cout << "CONSIDERING MATCH: " << topTracks[i]->Self() << " paired " << topTracks[j]->Self() << " overlap: " << info.branch_overlap << " trunk: " << info.trunk << std::endl;
238 
239  // only take cases with 50% overlap
240  if (info.branch_overlap < 0.5) continue;
241 
242  // std::cout << "Overlaps!\n";
243 
244  if ((unsigned)info.trunk == topTracks[i]->Self()) {
245  possible_merge_parents[topTracks[i]].push_back({topTracks[j], info});
246  possible_merge_children[topTracks[j]].push_back({topTracks[i], info});
247 
248  }
249  else {
250  possible_merge_parents[topTracks[j]].push_back({topTracks[i], info});
251  possible_merge_children[topTracks[i]].push_back({topTracks[j], info});
252  }
253 
254  }
255  }
256 
257  // also get cases with a top-track w/ a daughter track
258  for (unsigned i = 0; i < topTracks.size(); i++) {
259  std::vector<art::Ptr<recob::PFParticle>> daughters;
260  for (unsigned d: topTracks[i]->Daughters()) {
261  for (unsigned i_pfp = 0; i_pfp < this_slice_pfps.size(); i_pfp++) {
262  if (this_slice_pfps[i_pfp]->Self() == d) {
263  if (lar_pandora::LArPandoraHelper::IsTrack(this_slice_pfps[i_pfp])) daughters.push_back(this_slice_pfps[i_pfp]);
264  break;
265  }
266  }
267  }
268 
269  art::FindManyP<recob::Track> daughterTracks(daughters, e, fTrackLabel);
270  for (unsigned j = 0; j < daughters.size(); j++) {
271  if (!topTrackTracks.at(i).size() || !daughterTracks.at(j).size()) continue;
272 
273  sbn::MergedTrackInfo info = BuildTrackInfo(geo, *vtx, *topTracks[i], *topTrackTracks.at(i).at(0), *daughters[j], *daughterTracks.at(j).at(0), true);
274 
275  // std::cout << "CONSIDERING MATCH: " << topTracks[i]->Self() << " daughter " << daughters[j]->Self() << " overlap: " << info.branch_overlap << " trunk: " << info.trunk << std::endl;
276 
277  if (info.branch_overlap < 0.5) continue;
278 
279  possible_merge_parents[topTracks[i]].push_back({daughters[j], info});
280  possible_merge_children[daughters[j]].push_back({topTracks[j], info});
281  }
282  }
283 
284  // Evaluate all the possible merges
285  // Each track should only have one other possible merge
286  for (auto const &pair: possible_merge_parents) {
287  // std::cout << "Possible Merged: " << pair.first->Self() << " N parents: " << possible_merge_children[pair.first].size() << std::endl;
288  // for (auto const &pair_v: pair.second) {
289  // std::cout << "Child: " << pair_v.first->Self() << " with N parents: " << possible_merge_children[pair_v.first].size() << std::endl;
290  // std::cout << "Info: trunk: " << pair_v.second.trunk << " overlap: " << pair_v.second.branch_overlap << std::endl;
291  // }
292 
293  if (pair.second.size() == 1 && possible_merge_children[pair.first].size() == 0) {
294  art::Ptr<recob::PFParticle> branch = pair.second[0].first;
295  if (possible_merge_parents[branch].size() == 0 && possible_merge_children[branch].size() == 1) {
296  infos->push_back(pair.second[0].second);
297  art::Ptr<sbn::MergedTrackInfo> infoPtr = infoPtrMaker(infos->size()-1);
298  assn->addSingle(infoPtr, pair.first);
299  assn->addSingle(infoPtr, branch);
300  }
301  }
302  }
303  } // end iterate over slices
304 
305  e.put(std::move(infos));
306  e.put(std::move(assn));
307 
308 }
sbn::MergedTrackInfo BuildTrackInfo(const geo::GeometryCore *geo, const recob::Vertex &vtx, const recob::PFParticle &A, const recob::Track &Atrk, const recob::PFParticle &B, const recob::Track &Btrk, bool assume_a_is_trunk=false)
static bool IsNeutrino(const art::Ptr< recob::PFParticle > particle)
Determine whether a particle has been reconstructed as a neutrino.
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
bool IsPrimary(const caf::SRTrueParticleProxy &p)
Whether this is a primary particle or generated by a secondary interaction.
Description of geometry of one entire detector.
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
static bool IsTrack(const art::Ptr< recob::PFParticle > particle)
Determine whether a particle has been reconstructed as track-like.
do i e

Member Data Documentation

art::InputTag sbn::MergedTrackIdentifier::fPFPLabel
private

Definition at line 66 of file MergedTrackIdentifier_module.cc.

art::InputTag sbn::MergedTrackIdentifier::fTrackLabel
private

Definition at line 67 of file MergedTrackIdentifier_module.cc.


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