All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SpacePointAlg_TimeSort.cxx
Go to the documentation of this file.
1 /*!
2  * Title: SpacePointAlg_TimeSort class
3  * Author: wketchum@lanl.gov
4  * Inputs: std::vector<recob::Hit> (one for each plane)
5  * Outputs: std::vector<recob::SpacePoint>
6  *
7  * Description:
8  * This space point algorithm tries to improve speed by
9  * (1) keeping hit collections distinct among planes;
10  * (2) sorting hit collections by time; and,
11  * (3) having a lookup table for (y,z) coordinate positions.
12  * The original use case for this code was with the TTHitFinder,
13  * which produces an incredibly large number of hits per plane,
14  * making some sorted space point alg more attractive.
15  *
16  * This code is totally microboone specific, btw.
17  */
19 
20 #include <math.h>
21 
22 // Framework includes
23 #include "art/Framework/Services/Registry/ServiceHandle.h"
24 #include "canvas/Persistency/Common/Ptr.h"
25 #include "cetlib_except/exception.h"
26 #include "messagefacility/MessageLogger/MessageLogger.h"
27 
28 // LArSoft Includes
34 
35 //boost includes
36 #include "boost/multi_array.hpp"
37 
38 namespace {
39  inline bool
40  HitTimeComparison(art::Ptr<recob::Hit> const& a, art::Ptr<recob::Hit> const& b)
41  {
42  return a->PeakTime() < b->PeakTime();
43  }
44 }
45 
46 namespace sppt {
47 
48  //-------------------------------------------------
49  SpacePointAlg_TimeSort::SpacePointAlg_TimeSort(fhicl::ParameterSet const& pset)
50  {
51  fTimeDiffMax = pset.get<float>("TimeDiffMax");
52  fZDiffMax = pset.get<float>("ZDiffMax");
53  fYDiffMax = pset.get<float>("YDiffMax");
54 
55  //enforce a minimum time diff
56  if (fTimeDiffMax < 0) {
57  throw cet::exception("SpacePointAlg_TimeSort")
58  << "Time difference must be greater than zero.";
59  }
60  if (fZDiffMax < 0) {
61  throw cet::exception("SpacePointAlg_TimeSort")
62  << "Z-coordinate difference must be greater than zero.";
63  }
64  if (fYDiffMax < 0) {
65  throw cet::exception("SpacePointAlg_TimeSort")
66  << "Y-coordinate difference must be greater than zero.";
67  }
68  }
69 
70  //-------------------------------------------------
71  void
73  {
74  TIME_OFFSET_U = -1 * detProp.GetXTicksOffset(geo::View_t::kU, 0, 0);
75  TIME_OFFSET_V = -1 * detProp.GetXTicksOffset(geo::View_t::kV, 0, 0);
76  TIME_OFFSET_Y = -1 * detProp.GetXTicksOffset(geo::View_t::kZ, 0, 0);
77  TICKS_TO_X = detProp.GetXTicksCoefficient();
78 
79  TIME_OFFSET_SET = true;
80  }
81 
82  //-------------------------------------------------
83  void
85  {
86  art::ServiceHandle<geo::Geometry const> geom;
87  unsigned int nwires_u = geom->Nwires(geo::View_t::kU);
88  unsigned int nwires_v = geom->Nwires(geo::View_t::kV);
89  unsigned int nwires_y = geom->Nwires(geo::View_t::kZ);
90 
91  coordinates_UV_y.resize(boost::extents[nwires_v][nwires_u]);
92  coordinates_UV_z.resize(boost::extents[nwires_v][nwires_u]);
93  coordinates_UY_y.resize(boost::extents[nwires_y][nwires_u]);
94  coordinates_UY_z.resize(boost::extents[nwires_y][nwires_u]);
95  for (unsigned int iu = 0; iu < nwires_u; iu++) {
96  for (unsigned int iv = 0; iv < nwires_v; iv++) {
97  geom->IntersectionPoint(iu,
98  iv,
101  0,
102  0,
103  coordinates_UV_y[iv][iu], //y
104  coordinates_UV_z[iv][iu]); //z
105  }
106  for (unsigned int iy = 0; iy < nwires_y; iy++) {
107  geom->IntersectionPoint(iu,
108  iy,
111  0,
112  0,
113  coordinates_UY_y[iy][iu],
114  coordinates_UY_z[iy][iu]);
115  }
116  }
117 
118  COORDINATES_FILLED = true;
119  }
120 
121  //-------------------------------------------------
122  void
125  std::vector<art::Ptr<recob::Hit>>& hitVec_U,
126  std::vector<art::Ptr<recob::Hit>>& hitVec_V,
127  std::vector<art::Ptr<recob::Hit>>& hitVec_Y,
128  std::unique_ptr<std::vector<recob::SpacePoint>>& spptCollection,
129  std::unique_ptr<std::vector<std::vector<art::Ptr<recob::Hit>>>>& spptAssociatedHits)
130  {
131 
132  if (!TIME_OFFSET_SET) {
133  mf::LogWarning("SpacePointAlg_TimeSort")
134  << "Time offsets not set before createSpacePoints call!"
135  << "\nYou should call SpacePointAlg_TimeSort::setTimeOffsets() in beginRun()!"
136  << "\nWill be set now, but you should modify your code!";
137  setTimeOffsets(detProp);
138  }
139  if (!COORDINATES_FILLED) {
140  mf::LogWarning("SpacePointAlg_TimeSort")
141  << "Coordinate arrays not filled before createSpacePoints call!"
142  << "\nYou should call SpacePointAlg_TimeSort::fillCoordinateArrays() in beginRun()!"
143  << "\nWill be filled now, but you should modify your code!";
145  }
146 
147  //sort the hits by the time
148  sortHitsByTime(hitVec_U);
149  sortHitsByTime(hitVec_V);
150  sortHitsByTime(hitVec_Y);
151 
152  MF_LOG_DEBUG("SpacePointAlg_TimeSort")
153  << "Sorted " << hitVec_U.size() << " u hits, " << hitVec_V.size() << " v hits, "
154  << hitVec_Y.size() << " y hits.";
155 
156  //now, do the loop to search for like-timed hits across the three planes
157  std::vector<art::Ptr<recob::Hit>>::iterator ihitu = hitVec_U.begin();
158  std::vector<art::Ptr<recob::Hit>>::iterator ihitv = hitVec_V.begin();
159  std::vector<art::Ptr<recob::Hit>>::iterator ihity = hitVec_Y.begin();
160  std::vector<art::Ptr<recob::Hit>>::iterator ihitv_inner, ihity_inner;
161  double time_hitu = (*ihitu)->PeakTime() + TIME_OFFSET_U;
162  double time_hitv = (*ihitv)->PeakTime() + TIME_OFFSET_V;
163  double time_hity = (*ihity)->PeakTime() + TIME_OFFSET_Y;
164  double time_hitv_inner, time_hity_inner;
165  while (ihitu != hitVec_U.end()) {
166  time_hitu = (*ihitu)->PeakTime() + TIME_OFFSET_U;
167 
168  mf::LogInfo("SpacePointAlg_TimeSort")
169  << "Hit times (u,v,y)=(" << time_hitu << "," << time_hitv << "," << time_hity << ")";
170 
171  //if time_hitu is too much bigger than time_hitv, need to advance hitv iterator
172  while ((time_hitu - time_hitv) > fTimeDiffMax) {
173  ihitv++;
174  if (ihitv == hitVec_V.end()) break;
175  time_hitv = (*ihitv)->PeakTime() + TIME_OFFSET_V;
176  }
177  if (ihitv == hitVec_V.end()) break;
178 
179  //same thing with time_hitu and time_hity
180  while ((time_hitu - time_hity) > fTimeDiffMax) {
181  ihity++;
182  if (ihity == hitVec_Y.end()) break;
183  time_hity = (*ihity)->PeakTime() + TIME_OFFSET_Y;
184  }
185  if (ihity == hitVec_Y.end()) break;
186 
187  //OK, now we know time_hitu <= time_hitv and time_hitu <= time_hity.
188  //Next, check if time_hitu is near time_hitv and time_hit y. If not,
189  //we have to increment ihitu.
190  if (std::abs(time_hitu - time_hitv) > fTimeDiffMax ||
191  std::abs(time_hitu - time_hity) > fTimeDiffMax) {
192  ihitu++;
193  continue;
194  }
195 
196  //OK! Note we KNOW that these three match in time:
197  // -- time_hitu is within fTimeDiffMax of both time_hitv and time_hity; and
198  // -- time_hitu <= time_hitv AND time_hitu <=time_hity, so time_hitv and time_hity are near too
199 
200  mf::LogInfo("SpacePointAlg_TimeSort") << "Matching hit times (u,v,y)=(" << time_hitu << ","
201  << time_hitv << "," << time_hity << ")";
202 
203  //Next thing to do, we need to loop over all possible 3-hit matches for our given u-hit.
204  //We need new iterators in v and y at this location, and will loop over those
205  ihitv_inner = ihitv;
206  time_hitv_inner = (*ihitv_inner)->PeakTime() + TIME_OFFSET_V;
207  ihity_inner = ihity;
208  time_hity_inner = (*ihity_inner)->PeakTime() + TIME_OFFSET_Y;
209 
210  while (std::abs(time_hitu - time_hitv_inner) < fTimeDiffMax &&
211  std::abs(time_hitu - time_hity_inner) < fTimeDiffMax) {
212 
213  unsigned int uwire = (*ihitu)->WireID().Wire;
214  unsigned int vwire = (*ihitv_inner)->WireID().Wire;
215  unsigned int ywire = (*ihity_inner)->WireID().Wire;
216 
217  mf::LogInfo("SpacePointAlg_TimeSort")
218  << "(y,z) coordinate for uv/uy: (" << coordinates_UV_y[vwire][uwire] << ","
219  << coordinates_UV_z[vwire][uwire] << ")/(" << coordinates_UY_y[ywire][uwire] << ","
220  << coordinates_UY_z[ywire][uwire] << ")";
221 
222  if (std::abs(coordinates_UV_y[vwire][uwire] - coordinates_UY_y[ywire][uwire]) < fYDiffMax &&
223  std::abs(coordinates_UV_z[vwire][uwire] - coordinates_UY_z[ywire][uwire]) < fZDiffMax) {
224 
225  double xyz[3];
226  double xyz_err[6];
227  //triangular error matrix:
228  // | 0. |
229  // | 0. 0. |
230  // | 0. 0. 0. |
231 
232  //get average y and z, with errors
233  xyz[1] = (coordinates_UV_y[vwire][uwire] + coordinates_UY_y[ywire][uwire]) * 0.5;
234  xyz_err[2] = std::abs(coordinates_UV_y[vwire][uwire] - xyz[1]);
235  xyz[2] = (coordinates_UV_z[vwire][uwire] + coordinates_UY_z[ywire][uwire]) * 0.5;
236  xyz_err[5] = std::abs(coordinates_UV_z[vwire][uwire] - xyz[2]);
237 
238  double t_val = (time_hitu + time_hitv_inner + time_hity_inner) / 3.;
239  double t_err = 0.5 * std::sqrt((time_hitu - t_val) * (time_hitu - t_val) +
240  (time_hitv_inner - t_val) * (time_hitv_inner - t_val) +
241  (time_hity_inner - t_val) * (time_hity_inner - t_val));
242  xyz[0] = TICKS_TO_X * t_val;
243  xyz_err[0] = TICKS_TO_X * t_err;
244 
245  //make space point to put on event
246  recob::SpacePoint spt(xyz, xyz_err, 0., spptCollection->size());
247  spptCollection->push_back(spt);
248 
249  //make association with hits
250  std::vector<art::Ptr<recob::Hit>> myhits = {*ihitu, *ihitv_inner, *ihity_inner};
251  spptAssociatedHits->push_back(myhits);
252  }
253 
254  //now increment the v or y hit, whichever is smalles (closest to u hit) in time
255  if (time_hitv_inner <= time_hity_inner) {
256  ihitv_inner++;
257  if (ihitv_inner == hitVec_V.end()) break;
258  time_hitv_inner = (*ihitv_inner)->PeakTime() + TIME_OFFSET_V;
259  }
260  else {
261  ihity_inner++;
262  if (ihity_inner == hitVec_Y.end()) break;
263  time_hity_inner = (*ihity_inner)->PeakTime() + TIME_OFFSET_Y;
264  }
265  }
266 
267  ihitu++;
268  } // end while looping over u hits
269 
270  MF_LOG_DEBUG("SpacePointAlg_TimeSort")
271  << "Finished with " << spptCollection->size() << " spacepoints.";
272 
273  } //end createSpacePoints
274 
275  //-------------------------------------------------
276  void
277  SpacePointAlg_TimeSort::sortHitsByTime(std::vector<art::Ptr<recob::Hit>>& hitVec) const
278  {
279  std::sort(hitVec.begin(), hitVec.end(), HitTimeComparison);
280  }
281 
282 } //end sppt namespace
void sortHitsByTime(std::vector< art::Ptr< recob::Hit >> &hits_handle) const
SpacePointAlg_TimeSort(fhicl::ParameterSet const &pset)
float fYDiffMax
Maximum allowed time difference.
void setTimeOffsets(detinfo::DetectorPropertiesData const &detProp)
double GetXTicksCoefficient(int t, int c) const
Planes which measure V.
Definition: geo_types.h:130
double GetXTicksOffset(int p, int t, int c) const
Declaration of signal hit object.
boost::multi_array< double, 2 > coordinates_UV_y
Planes which measure Z direction.
Definition: geo_types.h:132
float fZDiffMax
Maximum allowed y-coordinate difference.
boost::multi_array< double, 2 > coordinates_UY_z
process_name gaushit a
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
T abs(T value)
Planes which measure U.
Definition: geo_types.h:129
bool TIME_OFFSET_SET
Maximum allowed z-coordinate difference.
Definition of data types for geometry description.
boost::multi_array< double, 2 > coordinates_UY_y
void createSpacePoints(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> &hitVec_U, std::vector< art::Ptr< recob::Hit >> &hitVec_V, std::vector< art::Ptr< recob::Hit >> &hitVec_Y, std::unique_ptr< std::vector< recob::SpacePoint >> &spptCollection, std::unique_ptr< std::vector< std::vector< art::Ptr< recob::Hit >>>> &spptAssociatedHits)
art framework interface to geometry description
auto const detProp
boost::multi_array< double, 2 > coordinates_UV_z