LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
Cluster3D.cxx
Go to the documentation of this file.
1 //
3 // \brief Definition of 3D cluster object for LArSoft
4 //
5 // \author usher@slac.stanford.edu
6 //
8 
9 #include <iomanip>
10 #include <utility>
11 
14 
15 namespace reco {
16 
18  : m_statusBits(0)
19  , m_docaToAxis(9999.)
20  , m_arcLenToPoca(0.)
21  , m_xPosition(0.)
22  , m_timeTicks(0.)
23  , m_wireID(geo::WireID())
24  , m_hit(nullptr)
25  {}
26 
27  ClusterHit2D::ClusterHit2D(unsigned statusBits,
28  float doca,
29  float poca,
30  float xPosition,
31  float timeTicks,
32  const geo::WireID& wireID,
33  const recob::Hit* hit)
34  : m_statusBits(statusBits)
35  , m_docaToAxis(doca)
36  , m_arcLenToPoca(poca)
37  , m_xPosition(xPosition)
38  , m_timeTicks(timeTicks)
39  , m_wireID(wireID)
40  , m_hit(hit)
41  {}
42 
44  {
45  m_statusBits = toCopy.m_statusBits;
46  m_docaToAxis = toCopy.m_docaToAxis;
48  m_xPosition = toCopy.m_xPosition;
49  m_timeTicks = toCopy.m_timeTicks;
50  m_wireID = toCopy.m_wireID;
51  m_hit = toCopy.m_hit;
52  }
53 
55  {
56  using std::swap;
57  auto tmp = toCopy;
58  swap(tmp, *this);
59  return *this;
60  }
61 
62  std::ostream& operator<<(std::ostream& o, const ClusterHit2D& c)
63  {
64  o << c.getHit();
65  return o;
66  }
67 
68  bool operator<(const ClusterHit2D& a, const ClusterHit2D& b)
69  {
70  return a.getHit() < b.getHit();
71  }
72 
74  : fID(std::numeric_limits<size_t>::max())
75  , fStatusBits(0)
76  , fPosition(Eigen::Vector3f::Zero())
77  , fTotalCharge(0.)
78  , fAvePeakTime(-1.)
79  , fDeltaPeakTime(0.)
80  , fSigmaPeakTime(0.)
81  , fHitChiSquare(0.)
82  , fOverlapFraction(0.)
83  , fChargeAsymmetry(0.)
84  , fDocaToAxis(0.)
85  , fArclenToPoca(0.)
86  {
87  fHitDelTSigVec.clear();
88  fWireIDVector.clear();
89  fHitVector.clear();
90  fHitDelTSigVec.resize(3, 0.);
91  fWireIDVector.resize(3, geo::WireID());
92  fHitVector.resize(3, NULL);
93  }
94 
96  unsigned int statusBits,
97  const Eigen::Vector3f& position,
98  float totalCharge,
99  float avePeakTime,
100  float deltaPeakTime,
101  float sigmaPeakTime,
102  float hitChiSquare,
103  float overlapFraction,
104  float chargeAsymmetry,
105  float docaToAxis,
106  float arclenToPoca,
107  const ClusterHit2DVec& hitVec,
108  const std::vector<float>& hitDelTSigVec,
109  const std::vector<geo::WireID>& wireIDs)
110  : fID(id)
111  , fStatusBits(statusBits)
112  , fPosition(position)
113  , fTotalCharge(totalCharge)
114  , fAvePeakTime(avePeakTime)
115  , fDeltaPeakTime(deltaPeakTime)
116  , fSigmaPeakTime(sigmaPeakTime)
117  , fHitChiSquare(hitChiSquare)
118  , fOverlapFraction(overlapFraction)
119  , fChargeAsymmetry(chargeAsymmetry)
120  , fDocaToAxis(docaToAxis)
121  , fArclenToPoca(arclenToPoca)
122  , fHitDelTSigVec(hitDelTSigVec)
123  , fWireIDVector(wireIDs)
124  {
125  fHitVector.resize(3, NULL);
126  std::copy(hitVec.begin(), hitVec.end(), fHitVector.begin());
127  }
128 
130  {
131  fID = toCopy.fID;
132  fStatusBits = toCopy.fStatusBits;
133  fPosition = toCopy.fPosition;
134  fTotalCharge = toCopy.fTotalCharge;
135  fAvePeakTime = toCopy.fAvePeakTime;
138  fHitChiSquare = toCopy.fHitChiSquare;
141  fDocaToAxis = toCopy.fDocaToAxis;
142  fArclenToPoca = toCopy.fArclenToPoca;
143  fHitVector = toCopy.fHitVector;
145  fWireIDVector = toCopy.fWireIDVector;
146  }
147 
149  {
150  using std::swap;
151  auto tmp = toCopy;
152  swap(tmp, *this);
153  return *this;
154  }
155 
156  void ClusterHit3D::initialize(size_t id,
157  unsigned int statusBits,
158  const Eigen::Vector3f& position,
159  float totalCharge,
160  float avePeakTime,
161  float deltaPeakTime,
162  float sigmaPeakTime,
163  float hitChiSquare,
164  float overlapFraction,
165  float chargeAsymmetry,
166  float docaToAxis,
167  float arclenToPoca,
168  const ClusterHit2DVec& hitVec,
169  const std::vector<float>& hitDelTSigVec,
170  const std::vector<geo::WireID>& wireIDs)
171  {
172  fID = id;
173  fStatusBits = statusBits;
174  fPosition = position;
175  fTotalCharge = totalCharge;
176  fAvePeakTime = avePeakTime;
177  fDeltaPeakTime = deltaPeakTime;
178  fSigmaPeakTime = sigmaPeakTime;
179  fHitChiSquare = hitChiSquare;
180  fOverlapFraction = overlapFraction;
181  fChargeAsymmetry = chargeAsymmetry;
182  fDocaToAxis = docaToAxis;
183  fArclenToPoca = arclenToPoca;
184  fHitVector = hitVec;
185  fHitDelTSigVec = hitDelTSigVec;
186  fWireIDVector = wireIDs;
187 
188  return;
189  }
190 
191  void ClusterHit3D::setWireID(const geo::WireID& wid) const
192  {
193  fWireIDVector[wid.Plane] = wid;
194  }
195 
196  std::ostream& operator<<(std::ostream& o, const ClusterHit3D& c)
197  {
198  o << "ClusterHit3D has " << c.getHits().size() << " hits associated";
199 
200  return o;
201  }
202 
203  //bool operator < (const ClusterHit3D & a, const ClusterHit3D & b)
204  //{
205  // if (a.m_position[2] != b.m_position[2]) return a.m_position[2] < b.m_position[2];
206  // else return a.m_position[0] < b.m_position[0];
207  //}
208 
210  : m_svdOK(false)
211  , m_numHitsUsed(0)
212  , m_eigenValues(EigenValues::Zero())
213  , m_eigenVectors(EigenVectors::Zero())
214  , m_avePosition(Eigen::Vector3f::Zero())
215  , m_aveHitDoca(9999.)
216  {}
217 
219  int nHits,
220  const EigenValues& eigenValues,
221  const EigenVectors& eigenVecs,
222  const Eigen::Vector3f& avePos,
223  const float aveHitDoca)
224  : m_svdOK(ok)
225  , m_numHitsUsed(nHits)
226  , m_eigenValues(eigenValues)
227  , m_eigenVectors(eigenVecs)
228  , m_avePosition(avePos)
229  , m_aveHitDoca(aveHitDoca)
230  {}
231 
232  void PrincipalComponents::flipAxis(size_t axisDir)
233  {
234  m_eigenVectors.row(axisDir) = -m_eigenVectors.row(axisDir);
235 
236  return;
237  }
238 
239  std::ostream& operator<<(std::ostream& o, const PrincipalComponents& a)
240  {
241  if (a.m_svdOK) {
242  o << std::setiosflags(std::ios::fixed) << std::setprecision(2);
243  o << " PCAxis ID run with " << a.m_numHitsUsed << " space points" << std::endl;
244  o << " - center position: " << std::setw(6) << a.m_avePosition(0) << ", "
245  << a.m_avePosition(1) << ", " << a.m_avePosition(2) << std::endl;
246  o << " - eigen values: " << std::setw(8) << std::right << a.m_eigenValues(0) << ", "
247  << a.m_eigenValues(1) << ", " << a.m_eigenValues(1) << std::endl;
248  o << " - average doca: " << a.m_aveHitDoca << std::endl;
249  o << " - Principle axis: " << std::setw(7) << std::setprecision(4) << a.m_eigenVectors(0, 0)
250  << ", " << a.m_eigenVectors(0, 1) << ", " << a.m_eigenVectors(0, 2) << std::endl;
251  o << " - second axis: " << std::setw(7) << std::setprecision(4) << a.m_eigenVectors(1, 0)
252  << ", " << a.m_eigenVectors(1, 1) << ", " << a.m_eigenVectors(1, 2) << std::endl;
253  o << " - third axis: " << std::setw(7) << std::setprecision(4) << a.m_eigenVectors(2, 0)
254  << ", " << a.m_eigenVectors(2, 1) << ", " << a.m_eigenVectors(2, 2) << std::endl;
255  }
256  else
257  o << " Principal Components Axis is not valid" << std::endl;
258 
259  return o;
260  }
261 
263  {
264  if (a.m_svdOK && b.m_svdOK) return a.m_eigenValues(0) > b.m_eigenValues(0);
265 
266  return false; //They are equal
267  }
268 
270  : m_statusBits(0)
271  , m_pcaResults(PrincipalComponents())
272  , m_totalCharge(0.)
273  , m_startPosition{0., 0., 0.}
274  , m_endPosition{0., 0., 0.}
275  , m_clusterIdx(0)
276  {}
277 
278  Cluster3D::Cluster3D(unsigned statusBits,
279  const PrincipalComponents& pcaResults,
280  float totalCharge,
281  const float* startPosition,
282  const float* endPosition,
283  int idx)
284  : m_statusBits(statusBits)
285  , m_pcaResults(pcaResults)
286  , m_totalCharge(totalCharge)
287  , m_startPosition{startPosition[0], startPosition[1], startPosition[2]}
288  , m_endPosition{endPosition[0], endPosition[1], endPosition[2]}
289  , m_clusterIdx(idx)
290  {}
291 
292  //----------------------------------------------------------------------
293  // Addition operator.
294  //
296  {
297  /*
298  // throw exception if the clusters are not from the same plane
299  if( a.View() != this->View() )
300  throw cet::exception("Cluster+operator") << "Attempting to sum clusters from "
301  << "different views is not allowed\n";
302 
303  // check the start and end positions - for now the
304  // smallest wire number means start position, largest means end position
305  std::vector<float> astart(a.StartPos());
306  std::vector<float> aend (a.EndPos() );
307  std::vector<float> start(StartPos());
308  std::vector<float> end (EndPos() );
309  std::vector<float> sigstart(SigmaStartPos());
310  std::vector<float> sigend (SigmaEndPos() );
311 
312  if(astart[0] < fStartPos[0]){
313  start = astart;
314  sigstart = a.SigmaStartPos();
315  }
316 
317  if(aend[0] > fEndPos[0]){
318  end = aend;
319  sigend = a.SigmaEndPos();
320  }
321 
322  //take weighted mean in obtaining average slope and differential charge,
323  //based on total charge each cluster
324  float dtdw = ((this->Charge()*dTdW()) + (a.Charge()*a.dTdW()))/(this->Charge() + a.Charge());
325  float dqdw = ((this->Charge()*dQdW()) + (a.Charge()*a.dQdW()))/(this->Charge() + a.Charge());
326 
327  //hits.sort();//sort the PtrVector to organize Hits of new Cluster
328  float sigdtdw = TMath::Max(SigmadTdW(), a.SigmadTdW());
329  float sigdqdw = TMath::Max(SigmadQdW(), a.SigmadQdW());
330 
331  Cluster sum(//hits,
332  start[0], sigstart[0],
333  start[1], sigstart[1],
334  end[0], sigend[0],
335  end[1], sigend[1],
336  dtdw, sigdtdw,
337  dqdw, sigdqdw,
338  this->Charge() + a.Charge(),
339  this->View(),
340  ID());
341 */
342  //return sum;
343  return a;
344  }
345 
346  //----------------------------------------------------------------------
347  // ostream operator.
348  //
349  std::ostream& operator<<(std::ostream& o, const Cluster3D& c)
350  {
351  o << std::setiosflags(std::ios::fixed) << std::setprecision(2);
352  o << "Cluster ID " << std::setw(5) << std::right << c.getClusterIdx();
353  // << " : View = " << std::setw(3) << std::right << c.View()
354  // << " StartWire = " << std::setw(7) << std::right << c.StartPos()[0]
355  // << " EndWire = " << std::setw(7) << std::right << c.EndPos()[0]
356  // << " StartTime = " << std::setw(9) << std::right << c.StartPos()[1]
357  // << " EndTime = " << std::setw(9) << std::right << c.EndPos()[1]
358  // << " dTdW = " << std::setw(9) << std::right << c.dTdW()
359  // << " dQdW = " << std::setw(9) << std::right << c.dQdW()
360  // << " Charge = " << std::setw(10) << std::right << c.Charge();
361 
362  return o;
363  }
364 
365  //----------------------------------------------------------------------
366  // < operator.
367  //
368  bool operator<(const Cluster3D& a, const Cluster3D& b)
369  {
370  /*
371  if(a.View() != b.View())
372  return a.View() < b.View();
373  if(a.ID() != b. ID())
374  return a.ID() < b.ID();
375  if(a.StartPos()[0] != b.StartPos()[0])
376  return a.StartPos()[0] < b.StartPos()[0];
377  if(a.EndPos()[0] != b.EndPos()[0])
378  return a.EndPos()[0] < b.EndPos()[0];
379 */
380  if (a.getStartPosition()[2] < b.getStartPosition()[2]) return true;
381 
382  return false; //They are equal
383  }
384 
385  //------------------------------------------------------------------------------------------------------------------------------------------
386 
388  {
393  const recob::Hit* hit = clusterHit->getHit();
394 
395  // Need to keep track of stuff so we can form cluster
396  if (clusterHit->WireID().Wire < m_startWire) {
397  m_startWire = clusterHit->WireID().Wire;
398  m_startTime = hit->PeakTimeMinusRMS();
399  m_sigmaStartTime = hit->SigmaPeakTime();
400  }
401 
402  if (clusterHit->WireID().Wire > m_endWire) {
403  m_endWire = clusterHit->WireID().Wire;
404  m_endTime = hit->PeakTimePlusRMS();
405  m_sigmaEndTime = hit->SigmaPeakTime();
406  }
407 
408  m_totalCharge += hit->Integral();
409  m_plane = clusterHit->WireID().planeID();
410  m_view = hit->View();
411 
412  m_hitVector.push_back(clusterHit);
413 
414  return;
415  }
416 
417 } // namespace
void initialize(size_t id, unsigned int statusBits, const Eigen::Vector3f &position, float totalCharge, float avePeakTime, float deltaPeakTime, float sigmaPeakTime, float hitChiSquare, float overlapFraction, float chargeAsymmetry, float docaToAxis, float arclenToPoca, const ClusterHit2DVec &hitVec, const std::vector< float > &hitDelTSigVec, const std::vector< geo::WireID > &wireIDVec)
Definition: Cluster3D.cxx:156
ClusterHit3D & operator=(ClusterHit3D const &)
Definition: Cluster3D.cxx:148
ClusterHit2D & operator=(ClusterHit2D const &)
Definition: Cluster3D.cxx:54
float fDeltaPeakTime
Largest delta peak time of associated recob::Hits.
Definition: Cluster3D.h:204
void setWireID(const geo::WireID &wid) const
Definition: Cluster3D.cxx:191
bool m_svdOK
SVD Decomposition was successful.
Definition: Cluster3D.h:225
Cluster3D operator+(Cluster3D)
Definition: Cluster3D.cxx:295
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
float fTotalCharge
Sum of charges of all associated recob::Hits.
Definition: Cluster3D.h:202
void flipAxis(size_t axis)
Definition: Cluster3D.cxx:232
double m_aveHitDoca
Average doca of hits used in PCA.
Definition: Cluster3D.h:230
Declaration of signal hit object.
const geo::WireID & WireID() const
Definition: Cluster3D.h:76
const float * getStartPosition() const
Definition: Cluster3D.h:277
unsigned m_statusBits
Volatile status information of this 3D hit.
Definition: Cluster3D.h:41
size_t fID
"id" of this hit (useful for indexing)
Definition: Cluster3D.h:199
STL namespace.
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
Definition: Hit.h:244
geo::View_t View() const
View for the plane of the hit.
Definition: Hit.h:276
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:563
Float_t tmp
Definition: plot.C:35
float fSigmaPeakTime
Quad sum of peak time sigmas.
Definition: Cluster3D.h:205
float m_docaToAxis
DOCA of hit at POCA to associated cluster axis.
Definition: Cluster3D.h:42
friend bool operator<(const ClusterHit2D &a, const ClusterHit2D &b)
Definition: Cluster3D.cxx:68
float fAvePeakTime
Average peak time of all associated recob::Hits.
Definition: Cluster3D.h:203
friend bool operator<(const Cluster3D &a, const Cluster3D &b)
Definition: Cluster3D.cxx:368
const recob::Hit * getHit() const
Definition: Cluster3D.h:77
std::vector< geo::WireID > fWireIDVector
Wire ID&#39;s for the planes making up hit.
Definition: Cluster3D.h:213
std::vector< float > fHitDelTSigVec
Delta t of hit to matching pair / sig.
Definition: Cluster3D.h:212
EigenValues m_eigenValues
Eigen values from SVD decomposition.
Definition: Cluster3D.h:227
const recob::Hit * m_hit
Hit we are augmenting.
Definition: Cluster3D.h:47
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
float m_arcLenToPoca
arc length to POCA along cluster axis
Definition: Cluster3D.h:43
float m_totalCharge
Total charge in the cluster.
Definition: Cluster3D.h:261
Eigen::Vector3f EigenValues
Definition: Cluster3D.h:219
unsigned int fStatusBits
Volatile status information of this 3D hit.
Definition: Cluster3D.h:200
float m_timeTicks
The time (in ticks) for this hit.
Definition: Cluster3D.h:45
float fOverlapFraction
Hit overlap fraction start/stop of triplet.
Definition: Cluster3D.h:207
float m_endPosition[3]
"end" position for cluster
Definition: Cluster3D.h:263
Eigen::Vector3f m_avePosition
Average position of hits fed to PCA.
Definition: Cluster3D.h:229
float fHitChiSquare
Hit ChiSquare relative to the average time.
Definition: Cluster3D.h:206
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
float fDocaToAxis
DOCA to the associated cluster axis.
Definition: Cluster3D.h:209
float PeakTimeMinusRMS(float sigmas=+1.) const
Returns a time sigmas RMS away from the peak time.
Definition: Hit.h:290
Detector simulation of raw signals on wires.
std::vector< const reco::ClusterHit2D * > ClusterHit2DVec
Definition: Cluster3D.h:90
float fChargeAsymmetry
Assymetry of average of two closest to third charge.
Definition: Cluster3D.h:208
ClusterHit2DVec fHitVector
Hits comprising this 3D hit.
Definition: Cluster3D.h:211
float fArclenToPoca
arc length along axis to DOCA point
Definition: Cluster3D.h:210
geo::WireID m_wireID
Keep track this particular hit&#39;s wireID.
Definition: Cluster3D.h:46
Eigen::Matrix3f EigenVectors
Definition: Cluster3D.h:220
int m_clusterIdx
ID for this cluster.
Definition: Cluster3D.h:264
float SigmaPeakTime() const
Uncertainty for the signal peak, in tick units.
Definition: Hit.h:224
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:46
constexpr PlaneID const & planeID() const
Definition: geo_types.h:620
friend bool operator<(const PrincipalComponents &a, const PrincipalComponents &b)
Definition: Cluster3D.cxx:262
EigenVectors m_eigenVectors
The three principle axes.
Definition: Cluster3D.h:228
float m_xPosition
The x coordinate for this hit.
Definition: Cluster3D.h:44
float PeakTimePlusRMS(float sigmas=+1.) const
Returns a time sigmas RMS away from the peak time.
Definition: Hit.h:285
friend std::ostream & operator<<(std::ostream &o, const ClusterHit2D &c)
Definition: Cluster3D.cxx:62
Namespace collecting geometry-related classes utilities.
const ClusterHit2DVec & getHits() const
Definition: Cluster3D.h:168
int getClusterIdx() const
Definition: Cluster3D.h:279
void UpdateParameters(const reco::ClusterHit2D *hit)
Definition: Cluster3D.cxx:387
friend std::ostream & operator<<(std::ostream &o, const Cluster3D &c)
Definition: Cluster3D.cxx:349
Eigen::Vector3f fPosition
position of this hit combination in world coordinates
Definition: Cluster3D.h:201
friend std::ostream & operator<<(std::ostream &o, const ClusterHit3D &c)
Definition: Cluster3D.cxx:196
int m_numHitsUsed
Number of hits in the decomposition.
Definition: Cluster3D.h:226
friend std::ostream & operator<<(std::ostream &o, const PrincipalComponents &a)
Definition: Cluster3D.cxx:239