All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TwoPlaneStubMerge_tool.cc
Go to the documentation of this file.
1 /**
2  *
3  */
4 
5 // Framework Includes
6 #include "art/Framework/Principal/Event.h"
7 #include "art/Framework/Principal/Handle.h"
8 #include "art/Framework/Services/Registry/ServiceHandle.h"
9 #include "art/Persistency/Common/PtrMaker.h"
10 #include "art/Utilities/ToolMacros.h"
11 #include "cetlib/cpu_timer.h"
12 #include "fhiclcpp/ParameterSet.h"
13 #include "messagefacility/MessageLogger/MessageLogger.h"
14 
15 // local includes
18 
19 // LArSoft includes
24 
25 // std includes
26 #include <string>
27 #include <iostream>
28 #include <memory>
29 
30 namespace sbn{
31 /**
32  * @brief Art tool for merging stubs across planes.
33  *
34  * Uses requirements on total
35  * charge and hit timing. Re-computes location information of successful
36  * merges.
37  */
39 public:
40  /**
41  * @brief Constructor
42  */
43  TwoPlaneStubMerge(fhicl::ParameterSet const &pset);
44 
45  std::vector<sbn::StubInfo> Merge(const std::vector<sbn::StubInfo> &stubs,
46  const geo::GeometryCore *geo,
47  const spacecharge::SpaceCharge *sce,
48  const detinfo::DetectorClocksData &dclock,
49  const detinfo::DetectorPropertiesData &dprop) override;
50 
52  const geo::GeometryCore *geo,
53  const spacecharge::SpaceCharge *sce,
54  const detinfo::DetectorPropertiesData &dprop);
55 
56  bool SortStubs(const sbn::StubInfo &A, const sbn::StubInfo &B);
57 
58 private:
59  double fMaxMergeTOff;
60  double fMaxMergeQOff;
63 };
64 
65 TwoPlaneStubMerge::TwoPlaneStubMerge(fhicl::ParameterSet const &pset):
66  fMaxMergeTOff(pset.get<double>("MaxMergeTOff")),
67  fMaxMergeQOff(pset.get<double>("MaxMergeQOff")),
68  fRemoveDuplicateMerges(pset.get<bool>("RemoveDuplicateMerges")),
69  fSaveOldStubs(pset.get<bool>("SaveOldStubs"))
70 {
71 }
72 
73 // Return true if stub A is "better" than stub B
75  // Count the hits on the main stub
76  int A_nhit = A.stub.CoreNHit();
77  int B_nhit = B.stub.CoreNHit();
78 
79  // First -- try more hits
80  if (A_nhit != B_nhit) return A_nhit > B_nhit;
81 
82  // Sort by desirability of plane: 2 better than 0 better than 1
83  return ((A.vhit_hit->WireID().Plane + 1) % 3) < ((B.vhit_hit->WireID().Plane + 1) % 3);
84 }
85 
87  const geo::GeometryCore *geo,
88  const spacecharge::SpaceCharge *sce,
89  const detinfo::DetectorPropertiesData &dprop) {
90  sbn::StubInfo ret;
91 
92  // Metadata
93 
94  // Combine the hits
95  ret.hits.insert(ret.hits.end(), A.hits.begin(), A.hits.end());
96  ret.hits.insert(ret.hits.end(), B.hits.begin(), B.hits.end());
97 
98  // Figure out which is the "better" stub-plane -- probably the one with the lower pitch
99  const sbn::StubInfo &best = SortStubs(A, B) ? A : B;
100  const sbn::StubInfo &othr = SortStubs(A, B) ? B : A;
101 
102  ret.pfp = best.pfp;
103  ret.vhit = best.vhit;
104  ret.vhit_hit = best.vhit_hit;
105 
106  // The stub info
107  // Vertex should be the same between the two
108  ret.stub.vtx = A.stub.vtx;
109  // The real thing -- combine the two positions to get a new endpoint
110  ret.stub.end = sbn::TwoStubEndPosition(best, othr, geo, sce, dprop);
111 
112  // Save the EField at the start and end point
113  ret.stub.efield_vtx = sbn::GetEfield(dprop, sce, ret.stub.vtx, ret.vhit_hit->WireID(), false);
114  ret.stub.efield_end = sbn::GetEfield(dprop, sce, ret.stub.end, ret.vhit_hit->WireID(), false);
115 
116  // In all the plane info stuff put the best stub first
117  ret.stub.plane.push_back(best.stub.plane.front());
118  ret.stub.plane.push_back(othr.stub.plane.front());
119 
120  ret.stub.hits.push_back(best.stub.hits.front());
121  ret.stub.hits.push_back(othr.stub.hits.front());
122 
123  ret.stub.pitch.push_back(best.stub.pitch.front());
124  ret.stub.pitch.push_back(othr.stub.pitch.front());
125 
126  ret.stub.trkpitch.push_back(best.stub.trkpitch.front());
127  ret.stub.trkpitch.push_back(othr.stub.trkpitch.front());
128 
129  ret.stub.vtx_w.push_back(best.stub.vtx_w.front());
130  ret.stub.vtx_w.push_back(othr.stub.vtx_w.front());
131 
132  ret.stub.hit_w.push_back(best.stub.hit_w.front());
133  ret.stub.hit_w.push_back(othr.stub.hit_w.front());
134 
135  return ret;
136 }
137 
138 std::vector<sbn::StubInfo> TwoPlaneStubMerge::Merge(const std::vector<sbn::StubInfo> &stubs,
139  const geo::GeometryCore *geo,
140  const spacecharge::SpaceCharge *sce,
141  const detinfo::DetectorClocksData &dclock,
142  const detinfo::DetectorPropertiesData &dprop) {
143 
144  // Internal struct
145  struct MergeInfo {
146  float toff;
147  float qoff;
148  unsigned i;
149  unsigned j;
150  };
151 
152  std::vector<MergeInfo> merges;
153 
154  // Compute all of the possible cross-plane matches
155  for (unsigned i_stub = 0; i_stub < stubs.size(); i_stub++) {
156  for (unsigned j_stub = 0; j_stub < stubs.size(); j_stub++) {
157  const sbn::StubInfo &A = stubs[i_stub];
158  const sbn::StubInfo &B = stubs[j_stub];
159  if (A.stub.plane.size() != 1 || B.stub.plane.size() != 1) continue; // Only match 1-plane-stubs
160 
161  if (A.stub.plane.front().Plane == B.stub.plane.front().Plane) continue; // Match across planes
162  if (A.stub.plane.front().asTPCID() != B.stub.plane.front().asTPCID()) continue; // But should be in the same TPC
163 
164  float toff = sbn::StubTimeOffset(A, B, dclock, dprop);
165  float qoff = sbn::StubChargeOffset(A, B);
166 
167  merges.push_back({toff, qoff, i_stub, j_stub});
168  }
169  }
170 
171  // Greedily do the best matches
172  //
173  // Sort by the time-offset -- this one is more precise
174  std::sort(merges.begin(), merges.end(), [](auto const &lhs, auto const &rhs) {return lhs.toff < rhs.toff;});
175 
176  // keep track of which index stubs have been merged
177  std::set<unsigned> hasmerged;
178 
179  // keep track of which index stubs should not be saved
180  std::set<unsigned> dontsave;
181 
182  // Output list
183  std::vector<sbn::StubInfo> ret;
184 
185  for (unsigned i_mrg = 0; i_mrg < merges.size(); i_mrg++) {
186  const MergeInfo &thismrg = merges[i_mrg];
187  if (thismrg.toff < fMaxMergeTOff && thismrg.qoff < fMaxMergeQOff) {
188  if (!hasmerged.count(thismrg.i) && !hasmerged.count(thismrg.j)) {
189  ret.push_back(MergeStubs(stubs[thismrg.i], stubs[thismrg.j], geo, sce, dprop));
190  hasmerged.insert(thismrg.i);
191  hasmerged.insert(thismrg.j);
192  }
193  else if (!hasmerged.count(thismrg.i) && fRemoveDuplicateMerges) {
194  dontsave.insert(thismrg.i);
195  }
196  else if (!hasmerged.count(thismrg.j) && fRemoveDuplicateMerges) {
197  dontsave.insert(thismrg.j);
198  }
199  }
200  }
201 
202  // Save the stubs which were not merged across planes and not marked to be removed
203  for (unsigned i_stub = 0; i_stub < stubs.size(); i_stub++) {
204  if (fSaveOldStubs || (!hasmerged.count(i_stub) && !dontsave.count(i_stub))) {
205  ret.push_back(stubs[i_stub]);
206  }
207  }
208 
209  return ret;
210 }
211 
212 DEFINE_ART_CLASS_TOOL(TwoPlaneStubMerge)
213 
214 } // namespace sbn
float StubChargeOffset(const sbn::StubInfo &A, const sbn::StubInfo &B)
Difference of the total charge between two stubs.
float StubTimeOffset(const sbn::StubInfo &A, const sbn::StubInfo &B, const detinfo::DetectorClocksData &dclock, const detinfo::DetectorPropertiesData &dprop)
Abstract interface intended for art tools which take a list of stubs and return a new list with some ...
Definition: IStubMerge.h:30
Utilities related to art service access.
std::vector< geo::PlaneID > plane
The plane ID.
Definition: Stub.h:25
std::vector< std::vector< StubHit > > hits
Hits on each plane. Ordered vtx-&gt;end.
Definition: Stub.h:32
geo::Point_t end
End of Stub. Space charge corrected. [cm].
Definition: Stub.h:19
static constexpr bool
Internal struct: contains information on stub and other associated data products. ...
sbn::StubInfo MergeStubs(const sbn::StubInfo &A, const sbn::StubInfo &B, const geo::GeometryCore *geo, const spacecharge::SpaceCharge *sce, const detinfo::DetectorPropertiesData &dprop)
geo::Point_t vtx
Interaction Vertex / Start of Stub. Space charge corrected. [cm].
Definition: Stub.h:18
std::vector< float > vtx_w
Wire coordinate of the vertex on this plane.
Definition: Stub.h:29
std::vector< art::Ptr< recob::Hit > > hits
Access the description of detector geometry.
std::vector< short > hit_w
Wire of the end point hit on this plane.
Definition: Stub.h:30
art::Ptr< recob::Hit > vhit_hit
Description of geometry of one entire detector.
float efield_end
The E-Field at the stub end point.
Definition: Stub.h:21
float efield_vtx
The E-Field at the reconstructed vertex.
Definition: Stub.h:22
Provides a base class aware of world box coordinates.
TwoPlaneStubMerge(fhicl::ParameterSet const &pset)
Constructor.
art::Ptr< sbn::VertexHit > vhit
Contains all timing reference information for the detector.
geo::Point_t TwoStubEndPosition(const sbn::StubInfo &A, const sbn::StubInfo &B, const geo::GeometryCore *geo, const spacecharge::SpaceCharge *sce, const detinfo::DetectorPropertiesData &dprop)
Returns an updated end position of a stub after merging across two planes.
std::vector< sbn::StubInfo > Merge(const std::vector< sbn::StubInfo > &stubs, const geo::GeometryCore *geo, const spacecharge::SpaceCharge *sce, const detinfo::DetectorClocksData &dclock, const detinfo::DetectorPropertiesData &dprop) override
double GetEfield(const detinfo::DetectorPropertiesData &dprop, const spacecharge::SpaceCharge *sce, geo::Point_t loc, geo::TPCID TPC, bool correct_loc_sce, float xsign=1.)
Get the E-Field in the presence of space charge.
std::vector< float > trkpitch
Pitch of the matched track on each wire [cm].
Definition: Stub.h:28
int CoreNHit(unsigned plane_index=0) const
Returns the number of hits along the core of the stub on the given plane index.
Definition: Stub.cxx:41
float A
Definition: dedx.py:137
Art tool for merging stubs across planes.
std::vector< float > pitch
Pitch of stub on each wire [cm].
Definition: Stub.h:27
art framework interface to geometry description
bool SortStubs(const sbn::StubInfo &A, const sbn::StubInfo &B)
art::Ptr< recob::PFParticle > pfp