LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
SpacePointHit3DBuilder_tool.cc
Go to the documentation of this file.
1 
8 // Framework Includes
10 #include "cetlib/search_path.h"
11 #include "cetlib/cpu_timer.h"
13 
15 
16 // LArSoft includes
22 #include "larevt/CalibrationDBI/Interface/ChannelStatusService.h"
23 #include "larevt/CalibrationDBI/Interface/ChannelStatusProvider.h"
24 
25 // std includes
26 #include <string>
27 #include <functional>
28 #include <iostream>
29 #include <memory>
30 
31 //------------------------------------------------------------------------------------------------------------------------------------------
32 // implementation follows
33 
34 namespace lar_cluster3d {
35 
39 class SpacePointHit3DBuilder : virtual public IHit3DBuilder
40 {
41 public:
47  explicit SpacePointHit3DBuilder(fhicl::ParameterSet const &pset);
48 
53 
54  void configure(const fhicl::ParameterSet&) override;
55 
62  void Hit3DBuilder(const art::Event &evt, reco::HitPairList& hitPairList, RecobHitToPtrMap&) const override;
63 
67  float getTimeToExecute(IHit3DBuilder::TimeValues index) const override {return m_timeVector.at(index);}
68 
69 private:
70 
71  using Hit2DVector = std::vector<reco::ClusterHit2D>;
72 
77 
79  mutable std::vector<float> m_timeVector;
80 
81  // Get instances of the primary data structures needed
83 
84  geo::Geometry* m_geometry; //< pointer to the Geometry service
85  const detinfo::DetectorProperties* m_detector; //< Pointer to the detector properties
86 };
87 
89 {
90  this->configure(pset);
91 }
92 
93 //------------------------------------------------------------------------------------------------------------------------------------------
94 
96 {
97 }
98 
99 //------------------------------------------------------------------------------------------------------------------------------------------
100 
102 {
103  m_spacePointTag = pset.get<art::InputTag>("SpacePointTag");
104  m_enableMonitoring = pset.get<bool> ("EnableMonitoring", true);
105 
107 
108  m_geometry = &*geometry;
109  m_detector = lar::providerFrom<detinfo::DetectorPropertiesService>();
110 }
111 
112 
113 void SpacePointHit3DBuilder::Hit3DBuilder(const art::Event& evt, reco::HitPairList& hitPairList, RecobHitToPtrMap& recobHitToArtPtrMap) const
114 {
115  m_timeVector.resize(NUMTIMEVALUES, 0.);
116 
117  cet::cpu_timer theClockMakeHits;
118 
119  if (m_enableMonitoring) theClockMakeHits.start();
120 
125  // Start by recovering the associations between space points and hits
127  evt.getByLabel(m_spacePointTag, hitSpacePointAssnsHandle);
128 
129  if (!hitSpacePointAssnsHandle.isValid()) return;
130 
131  // First step is to loop through and get a mapping between space points and associated hits
132  // and, importantly, a list of unique hits (and mapping between art ptr and hit)
133  using SpacePointHitVecMap = std::map<const recob::SpacePoint*, std::vector<const recob::Hit*>>;
134  using RecobHitSet = std::set<const recob::Hit*>;
135 
136  SpacePointHitVecMap spacePointHitVecMap;
137  RecobHitSet recobHitSet;
138 
139  for(auto& assnPair : *hitSpacePointAssnsHandle)
140  {
141  const art::Ptr<recob::SpacePoint> spacePoint = assnPair.second;
142  const art::Ptr<recob::Hit>& recobHit = assnPair.first;
143 
144  spacePointHitVecMap[spacePoint.get()].push_back(recobHit.get());
145  recobHitSet.insert(recobHit.get());
146  recobHitToArtPtrMap[recobHit.get()] = recobHit;
147  }
148 
149  // We'll want to correct the hit times for the plane offsets
150  // (note this is already taken care of when converting to position)
151  std::map<geo::PlaneID, double> planeOffsetMap;
152 
153  // Initialize the plane to hit vector map
154  for(size_t cryoIdx = 0; cryoIdx < m_geometry->Ncryostats(); cryoIdx++)
155  {
156  for(size_t tpcIdx = 0; tpcIdx < m_geometry->NTPC(); tpcIdx++)
157  {
158  // What we want here are the relative offsets between the planes
159  // Note that plane 0 is assumed the "first" plane and is the reference
160  planeOffsetMap[geo::PlaneID(cryoIdx,tpcIdx,0)] = 0.;
161  planeOffsetMap[geo::PlaneID(cryoIdx,tpcIdx,1)] = m_detector->GetXTicksOffset(geo::PlaneID(cryoIdx,tpcIdx,1))
162  - m_detector->GetXTicksOffset(geo::PlaneID(cryoIdx,tpcIdx,0));
163  planeOffsetMap[geo::PlaneID(cryoIdx,tpcIdx,2)] = m_detector->GetXTicksOffset(geo::PlaneID(cryoIdx,tpcIdx,2))
164  - m_detector->GetXTicksOffset(geo::PlaneID(cryoIdx,tpcIdx,0));
165 
166  std::cout << "***> plane 0 offset: " << planeOffsetMap[geo::PlaneID(cryoIdx,tpcIdx,0)] << ", plane 1: " << planeOffsetMap[geo::PlaneID(cryoIdx,tpcIdx,1)] << ", plane 2: " << planeOffsetMap[geo::PlaneID(cryoIdx,tpcIdx,2)] << std::endl;
167  std::cout << " Det prop plane 0: " << m_detector->GetXTicksOffset(geo::PlaneID(cryoIdx,tpcIdx,0)) << ", plane 1: " << m_detector->GetXTicksOffset(geo::PlaneID(cryoIdx,tpcIdx,1)) << ", plane 2: " << m_detector->GetXTicksOffset(geo::PlaneID(cryoIdx,tpcIdx,2)) << ", Trig: " << m_detector->TriggerOffset() << std::endl;
168  }
169  }
170 
171  // We need temporary mapping from recob::Hit's to our 2D hits
172  using RecobHitTo2DHitMap = std::map<const recob::Hit*,const reco::ClusterHit2D*>;
173 
174  RecobHitTo2DHitMap recobHitTo2DHitMap;
175 
176  // Set the size of the container for our hits
177  m_clusterHit2DMasterVec.clear();
178  m_clusterHit2DMasterVec.reserve(recobHitSet.size());
179 
180  // Now go throught the list of unique hits and create the 2D hits we'll use
181  for(auto& recobHit : recobHitSet)
182  {
183  const geo::WireID& hitWireID(recobHit->WireID());
184 
185  double hitPeakTime(recobHit->PeakTime() - planeOffsetMap[hitWireID.planeID()]);
186  double xPosition(m_detector->ConvertTicksToX(recobHit->PeakTime(), hitWireID.Plane, hitWireID.TPC, hitWireID.Cryostat));
187 
188  m_clusterHit2DMasterVec.emplace_back(0, 0., 0., xPosition, hitPeakTime, *recobHit);
189 
190  recobHitTo2DHitMap[recobHit] = &m_clusterHit2DMasterVec.back();
191  }
192 
193  // Now we can go through the space points and build our 3D hits
194  for(auto& pointPair : spacePointHitVecMap)
195  {
196  const recob::SpacePoint* spacePoint = pointPair.first;
197  const std::vector<const recob::Hit*>& recobHitVec = pointPair.second;
198 
199  if (recobHitVec.size() != 3)
200  {
201  std::cout << "************>>>>>> do not have 3 hits associated to space point! " << recobHitVec.size() << " ***************" << std::endl;
202  continue;
203  }
204 
205  std::vector<const reco::ClusterHit2D*> hit2DVec(recobHitVec.size());
206 
207  for(const auto& recobHit : recobHitVec)
208  {
209  const reco::ClusterHit2D* hit2D = recobHitTo2DHitMap.at(recobHit);
210 
211  hit2DVec[hit2D->getHit().WireID().Plane] = hit2D;
212  }
213 
214  // Weighted average, delta, sigmas, chisquare, kitchen sink, refrigerator for beer, etc.
215  float avePeakTime(0.);
216  float weightSum(0.);
217 
218  for(const auto& hit2D : hit2DVec)
219  {
220  float hitSigma = hit2D->getHit().RMS();
221  float weight = 1. / (hitSigma * hitSigma);
222 
223  avePeakTime += weight * hit2D->getTimeTicks();
224  weightSum += weight;
225  }
226 
227  avePeakTime /= weightSum;
228 
229  // Armed with the average peak time, now get hitChiSquare and the sig vec
230  float hitChiSquare(0.);
231  float sigmaPeakTime(std::sqrt(1./weightSum));
232 
233  for(const auto& hit2D : hit2DVec)
234  {
235  float hitRMS = hit2D->getHit().RMS();
236  float combRMS = std::sqrt(hitRMS*hitRMS - sigmaPeakTime*sigmaPeakTime);
237  float peakTime = hit2D->getTimeTicks();
238  float deltaTime = peakTime - avePeakTime;
239  float hitSig = deltaTime / combRMS;
240 
241  hitChiSquare += hitSig * hitSig;
242  }
243 
244  // The x position is a weighted sum but the y-z position is simply the average
245  float position[] = { float(spacePoint->XYZ()[0]), float(spacePoint->XYZ()[1]), float(spacePoint->XYZ()[2])};
246  float totalCharge = hit2DVec[0]->getHit().Integral() + hit2DVec[1]->getHit().Integral() + hit2DVec[2]->getHit().Integral();
247 
248  reco::ClusterHit2DVec hitVector;
249 
250  hitVector.resize(3,NULL);
251 
252  // Make sure we have the hits
253  hitVector.at(hit2DVec[0]->getHit().WireID().Plane) = hit2DVec[0];
254  hitVector.at(hit2DVec[1]->getHit().WireID().Plane) = hit2DVec[1];
255  hitVector.at(hit2DVec[2]->getHit().WireID().Plane) = hit2DVec[2];
256 
257  // And get the wire IDs
258  std::vector<geo::WireID> wireIDVec = {geo::WireID(0,0,geo::kU,0), geo::WireID(0,0,geo::kV,0), geo::WireID(0,0,geo::kW,0)};
259 
260  for(const auto& hit : hitVector)
261  {
262  wireIDVec[hit->getHit().WireID().Plane] = hit->getHit().WireID();
263 
264  if (hit->getStatusBits() & reco::ClusterHit2D::USEDINTRIPLET) hit->setStatusBit(reco::ClusterHit2D::SHAREDINTRIPLET);
265 
266  hit->setStatusBit(reco::ClusterHit2D::USEDINTRIPLET);
267  }
268 
269  unsigned int statusBits(0x7);
270 
271  // For compiling at the moment
272  std::vector<float> hitDelTSigVec = {0.,0.,0.};
273 
274  hitDelTSigVec[0] = std::fabs(hitVector[0]->getTimeTicks() - 0.5 * (hitVector[1]->getTimeTicks() + hitVector[2]->getTimeTicks()));
275  hitDelTSigVec[1] = std::fabs(hitVector[1]->getTimeTicks() - 0.5 * (hitVector[2]->getTimeTicks() + hitVector[0]->getTimeTicks()));
276  hitDelTSigVec[2] = std::fabs(hitVector[2]->getTimeTicks() - 0.5 * (hitVector[0]->getTimeTicks() + hitVector[1]->getTimeTicks()));
277 
278  float deltaPeakTime = *std::min_element(hitDelTSigVec.begin(),hitDelTSigVec.end());
279 
280  // Create the 3D cluster hit
281  hitPairList.emplace_back(new reco::ClusterHit3D(0,
282  statusBits,
283  position,
284  totalCharge,
285  avePeakTime,
286  deltaPeakTime,
287  sigmaPeakTime,
288  hitChiSquare,
289  0.,
290  0.,
291  hitVector,
292  hitDelTSigVec,
293  wireIDVec));
294  }
295 
296  if (m_enableMonitoring)
297  {
298  theClockMakeHits.stop();
299 
300  m_timeVector[BUILDTHREEDHITS] = theClockMakeHits.accumulated_real_time();
301  }
302 
303  mf::LogDebug("Cluster3D") << ">>>>> 3D hit building done, found " << hitPairList.size() << " 3D Hits" << std::endl;
304 
305  return;
306 }
307 
308 //------------------------------------------------------------------------------------------------------------------------------------------
309 //------------------------------------------------------------------------------------------------------------------------------------------
310 
312 } // namespace lar_cluster3d
const detinfo::DetectorProperties * m_detector
#define DEFINE_ART_CLASS_TOOL(tool)
Definition: ToolMacros.h:45
virtual int TriggerOffset() const =0
art::InputTag m_spacePointTag
Data members to follow.
Planes which measure V.
Definition: geo_types.h:77
geo::WireID WireID() const
Initial tdc tick for hit.
Definition: Hit.h:234
float getTimeToExecute(IHit3DBuilder::TimeValues index) const override
If monitoring, recover the time to execute a particular function.
Declaration of signal hit object.
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
std::vector< reco::ClusterHit2D > Hit2DVector
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
std::list< std::unique_ptr< reco::ClusterHit3D >> HitPairList
Definition: Cluster3D.h:321
bool isValid() const
Definition: Handle.h:190
Planes which measure U.
Definition: geo_types.h:76
T get(std::string const &key) const
Definition: ParameterSet.h:231
const recob::Hit & getHit() const
Definition: Cluster3D.h:73
SpacePointHit3DBuilder class definiton.
const Double32_t * XYZ() const
Definition: SpacePoint.h:65
TimeValues
enumerate the possible values for time checking if monitoring timing
Definition: IHit3DBuilder.h:57
The geometry of one entire detector, as served by art.
Definition: Geometry.h:110
std::map< const recob::Hit *, art::Ptr< recob::Hit >> RecobHitToPtrMap
Defines a structure mapping art representation to internal.
Definition: IHit3DBuilder.h:44
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
IHit3DBuilder interface class definiton.
Definition: IHit3DBuilder.h:26
Detector simulation of raw signals on wires.
This provides an art tool interface definition for tools which construct 3D hits used in 3D clusterin...
std::vector< const reco::ClusterHit2D * > ClusterHit2DVec
Definition: Cluster3D.h:85
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
double weight
Definition: plottest35.C:25
Utility object to perform functions of association.
T const * get() const
Definition: Ptr.h:321
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
SpacePointHit3DBuilder(fhicl::ParameterSet const &pset)
Constructor.
void Hit3DBuilder(const art::Event &evt, reco::HitPairList &hitPairList, RecobHitToPtrMap &) const override
Given a set of recob hits, run DBscan to form 3D clusters.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
Planes which measure W (third view for Bo, MicroBooNE, etc).
Definition: geo_types.h:78
TCEvent evt
Definition: DataStructs.cxx:5
recob::tracking::Plane Plane
Definition: TrackState.h:17
art framework interface to geometry description
void configure(const fhicl::ParameterSet &) override
Interface for configuring the particular algorithm tool.
virtual double GetXTicksOffset(int p, int t, int c) const =0