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