QwAnalysis
QwTrackingTreeMatch Class Reference

Module that matches track segments for pairs of wire planes. More...

#include <QwTrackingTreeMatch.h>

Public Member Functions

 QwTrackingTreeMatch ()
 Default constructor. More...
 
virtual ~QwTrackingTreeMatch ()
 Destructor. More...
 
void SetDebugLevel (int debug)
 Set the debug level. More...
 
QwTreeLineMatchRegion3 (QwTreeLine *frontlist, QwTreeLine *backlist)
 Match the tree lines in two planes in region 3. More...
 

Private Attributes

int fDebug
 

Detailed Description

Module that matches track segments for pairs of wire planes.

Definition at line 53 of file QwTrackingTreeMatch.h.

Constructor & Destructor Documentation

QwTrackingTreeMatch::QwTrackingTreeMatch ( )
inline

Default constructor.

Definition at line 58 of file QwTrackingTreeMatch.h.

58 : fDebug(0) { };
virtual QwTrackingTreeMatch::~QwTrackingTreeMatch ( )
inlinevirtual

Destructor.

Definition at line 60 of file QwTrackingTreeMatch.h.

60 { };

Member Function Documentation

QwTreeLine * QwTrackingTreeMatch::MatchRegion3 ( QwTreeLine frontlist,
QwTreeLine backlist 
)

Match the tree lines in two planes in region 3.

Match the tree lines in two like-pitched planes in region 3.

In this function the list of tree lines in the front VDC plane is combined with the list of tree lines in the back VDC plane. The resulting list of combined tree lines is returned as a linked-list. The criterion for keeping a combined tree line is that the following slopes are within their slope matching resolutions:

  • the slope of the tree line through the front plane,
  • the slope between the central hits in the front and back planes,
  • the slope of the tree line through the back plane.

The reference frame for the matching is defined with the center of the first wire plane at the origin. The center of the second wire plane is then at (0, delta_para, delta_perp) assuming no lateral displacement. The difference in the u coordinate between the center of the chambers is then given by delta_u.

The line slopes are calculated in a different reference frame: the distance between the wires (in the plane) is represented by z, the perpendicular distance from the wire is represented by x.

Todo:
This function requires the wire planes to be parallel.
QwTrackingTreeMatch-1.jpg
QwTrackingTreeMatch-2.jpg
QwTrackingTreeMatch-3.jpg
QwTrackingTreeMatch-4.jpg
QwTrackingTreeMatch-5.jpg
Parameters
frontlistList of tree lines in the front plane
backlistList of tree lines in the back plane
Returns
List of tree lines after matching

Set up the geometry of the two wire planes: distances between them, relative orientation, etc.

Definition at line 63 of file QwTrackingTreeMatch.cc.

References QwTreeLine::AddHit(), QwTreeLine::CalculateAverageResidual(), QwLog::endl(), fDebug, QwHit::fDriftPosition, QwTreeLine::fHits, QwTreeLine::fNumHits, QwTreeLine::fNumMiss, QwHit::fWirePosition, VQwTrackingElement::GetDetectorInfo(), QwDetectorInfo::GetDetectorPitchCos(), QwDetectorInfo::GetDetectorPitchSin(), VQwTrackingElement::GetDirection(), QwHit::GetDriftPosition(), QwDetectorInfo::GetElementAngleCos(), QwDetectorInfo::GetElementCoordinate(), QwDetectorInfo::GetElementSpacing(), QwTreeLine::GetListOfHits(), VQwTrackingElement::GetPackage(), VQwTrackingElement::GetPlane(), VQwTrackingElement::GetRegion(), QwDetectorInfo::GetSlopeMatching(), QwHit::GetWirePosition(), QwDetectorInfo::GetXPosition(), QwDetectorInfo::GetYPosition(), QwDetectorInfo::GetZPosition(), kRegionID3, MAX_LAYERS, QwTreeLine::next, QwError, QwMessage, QwTrackingTreeCombine::r3_TreelineFit(), QwTreeLine::SetChi(), VQwTrackingElement::SetDirection(), VQwTrackingElement::SetOctant(), QwTreeLine::SetOffset(), VQwTrackingElement::SetPackage(), VQwTrackingElement::SetRegion(), QwTreeLine::SetSlope(), and QwTreeLine::SetValid().

Referenced by QwTrackingWorker::ProcessEvent().

66 {
67  // Check the region of the tree lines (only region 3 is allowed)
68  if (frontlist->GetRegion() != kRegionID3
69  || backlist->GetRegion() != kRegionID3) {
70  QwError << "[TreeMatch::MatchR3] Tree line matching is only valid for region 3!"
71  << QwLog::endl;
72  return 0;
73  }
74 
75  // Check whether the front and back planes are consistent
76  if (frontlist->GetRegion() != backlist->GetRegion()
77  || frontlist->GetPackage() != backlist->GetPackage()
78  || frontlist->GetDirection() != backlist->GetDirection()) {
79  QwError << "[TreeMatch::MatchR3] The front and back planes are not consistent!"
80  << QwLog::endl;
81  return 0;
82  }
83 
84  // Check whether the planes are different
85  if (frontlist->GetPlane() == backlist->GetPlane()) {
86  QwError << "[TreeMatch::MatchR3] The front and back planes are identical!"
87  << QwLog::endl;
88  return 0;
89  }
90 
91 
92  // Initialize the list of combined tree lines to null
93  QwTreeLine* treelinelist = 0;
94 
95  // Initialize the tree combine object (TODO can this be avoided?)
96  QwTrackingTreeCombine *TreeCombine = new QwTrackingTreeCombine();
97 
98 
99  /// Set up the geometry of the two wire planes: distances between them,
100  /// relative orientation, etc.
101 
102  // Get detector identification
103  const QwDetectorInfo* frontdetector = frontlist->GetDetectorInfo();
104  const QwDetectorInfo* backdetector = backlist->GetDetectorInfo();
105 
106  // Rotation of the detector planes in the xz plane around the y axis
107  double cos_theta = frontdetector->GetDetectorPitchCos();
108  double sin_theta = frontdetector->GetDetectorPitchSin();
109 
110  // Differences in position between the front and back detector planes
111  // NOTE: these positions are still in the wrong coordinate system
112  double delta_x = backdetector->GetXPosition() - frontdetector->GetXPosition();
113  double delta_y = backdetector->GetYPosition() - frontdetector->GetYPosition();
114  double delta_z = backdetector->GetZPosition() - frontdetector->GetZPosition();
115 
116  // Distance between the chamber centers perpendicular to the wire planes
117  double delta_perp = delta_z * cos_theta + delta_y * sin_theta;
118 
119  // Distance between the chamber centers parallel to the wire planes
120  // 0.5 is tangent of wire angle, now includes x offset as well
121  double delta_para = - delta_z * sin_theta + delta_y * cos_theta + 0.5 * delta_x;
122 
123  // Parallel distance between the chamber centers in u or v coordinates
124  // NOTE: fabs because cos < 0 for v planes in one octant !@#$%
125  double delta_u = delta_para * fabs(frontdetector->GetElementAngleCos());
126 
127  // NOTE:pkg1 and pkg2 need different solution
128 
129  // For the good tree lines in the front and back VDC planes, we first need
130  // to set the 'z' coordinate in the wire direction. The 'z' position for
131  // VDC planes is the coordinate in the wire plane. By definition, the
132  // middle wire (141) has a 'z' position of zero.
133 
134  // Loop over the tree lines in the front VDC plane to set the wire position.
135  int numflines = 0;
136  for (QwTreeLine* frontline = frontlist; frontline;
137  frontline = frontline->next, numflines++) {
138  // Skip the the void tree lines
139  if (frontline->IsVoid()) continue;
140  // Loop over all hits of the valid tree lines
141  for (int hit = 0; hit < frontline->GetNumberOfHits(); hit++) {
142  int element = frontline->GetHit(hit)->GetElement();
143  double wire = frontdetector->GetElementCoordinate(element);
144  frontline->GetHit(hit)->SetWirePosition(wire);
145  if (fDebug) QwMessage << "wire " << element << ": "
146  << frontline->GetHit(hit)->GetWirePosition() << " "
147  << frontline->GetHit(hit)->GetDriftPosition() << QwLog::endl;
148  }
149  }
150  // Loop over the tree lines in the back VDC plane to set the wire position
151  int numblines = 0;
152  for (QwTreeLine* backline = backlist; backline;
153  backline = backline->next, numblines++) {
154  // Skip the the void tree lines
155  if (backline->IsVoid()) continue;
156  // Loop over all hits of the valid tree lines
157  for (int hit = 0; hit < backline->GetNumberOfHits(); hit++) {
158  int element = backline->GetHit(hit)->GetElement();
159  double wire = backdetector->GetElementCoordinate(element);
160  backline->GetHit(hit)->SetWirePosition(wire);
161  if (fDebug) QwMessage << "wire " << element << ": "
162  << backline->GetHit(hit)->GetWirePosition() + delta_u << " "
163  << backline->GetHit(hit)->GetDriftPosition() + delta_perp << QwLog::endl;
164  }
165  }
166 
167 
168  //###############################
169  // Find matching track segments #
170  //###############################
171  int fmatches[numflines]; // matches indexed by front tree lines
172  int bmatches[numblines]; // matches indexed by back tree lines
173  int reverse[numflines*numblines]; // to specify if ifront and ifback combination should flip the drift distance sign
174 
175 
176  // Initialize the array of best matches for all back plane tree lines
177  double bestmatches[numblines];
178  for (int i = 0; i < numblines; i++) bestmatches[i] = 99;
179 
180  // Loop over the tree lines in the front VDC plane
181  int ifront = 0;
182  for (QwTreeLine* frontline = frontlist; frontline;
183  frontline = frontline->next, ifront++) {
184 
185  // Initialization of fmatches
186  fmatches[ifront] = -1;
187 
188  // Skip void tree lines
189  if (frontline->IsVoid()) continue;
190 
191  // Get the hit with smallest drift distance
192  QwHit* fronthit = frontline->GetBestWireHit();
193 
194  // No match found yet
195  double bestmatch = 99;
196 
197  // Loop over the tree lines in the back VDC plane
198  int iback = 0;
199  for (QwTreeLine* backline = backlist; backline;
200  backline = backline->next, iback++) {
201 
202  // Skip void tree lines
203  if (backline->IsVoid()) continue;
204 
205  // Get the hit with smallest drift distance around the center of the
206  // second wire plane.
207  QwHit* backhit = backline->GetBestWireHit();
208 
209  // Get the positions of the best wire hit
210  double u[2], perp[2];
211  u[0] = fronthit->GetWirePosition(); // distance parallel to plane
212  u[1] = backhit->GetWirePosition(); // i.e. wire direction
213  perp[0] = fronthit->GetDriftPosition(); // distance perpendicular to plane
214  perp[1] = backhit->GetDriftPosition(); // i.e. drift distance
215 
216  // Slope between the front and back plane central hits
217  // NOTE: this is the slope wrt the normal to the plane
218 
219  double slope = 0;
220  // NOTE: pkg1 needs to minus delta_u while pkg2 needs to add delta_u due to the location of the first wire
221  if(backline->GetPackage()==1)
222  slope = (-1*delta_u + u[1] - u[0]) / (delta_perp + perp[1] - perp[0]);
223  else
224  slope = (delta_u + u[1] - u[0]) / (delta_perp + perp[1] - perp[0]);
225 
226  // Wire spacing and slope matching parameters for front and back planes
227  double wirespacing_f = frontdetector->GetElementSpacing();
228  double wirespacing_b = backdetector->GetElementSpacing();
229  double sloperes_f = frontdetector->GetSlopeMatching();
230  double sloperes_b = backdetector->GetSlopeMatching();
231 
232 
233  // Slope of the front and back tree line wrt the normal to the plane
234  // NOTE: the slopes of the tree line are wrt the plane
235  double fslope = wirespacing_f / frontline->GetSlope();
236  double bslope = wirespacing_b / backline->GetSlope();
237 
238  // NOTE:Do a preliminary slope check to align two treelines into one
239  if (fabs(fslope - slope) <= sloperes_f
240  && fabs(bslope - slope) <= sloperes_b
241  && fabs(fslope - slope) + fabs(bslope - slope) < bestmatch){
242  // if ok, do nothing at all
243  reverse[ifront*numblines+iback]=1;
244  } else {
245  // NOTE: if not, we need to flip the sign to see if it works
246  fslope*=-1;
247  bslope*=-1;
248  reverse[ifront*numblines+iback]=-1;
249  }
250  // Check whether this is a good match
251  if (fabs(fslope - slope) <= sloperes_f
252  && fabs(bslope - slope) <= sloperes_b
253  && fabs(fslope - slope) + fabs(bslope - slope) < bestmatch) {
254 
255  // If the back segment has been matched already
256  if (bestmatches[iback] != 99) {
257  // Check if it's better than what we had already
258  bestmatch = fabs(fslope - slope) + fabs(bslope - slope);
259  if (bestmatch > bestmatches[iback]) continue;
260  else fmatches[bmatches[iback]] = -1;
261  }
262 
263  // Set the match on both match arrays
264  fmatches[ifront] = iback;
265  bmatches[iback] = ifront;
266  bestmatch = bestmatches[iback] = fabs(fslope - slope) + fabs(bslope - slope);
267 
268  } // end of if good match
269 
270  } // end of loop over back VDC tree lines
271  } // end of loop over front VDC tree lines
272 
273  //################################
274  // Create the combined treelines #
275  //################################
276 
277  // Loop over the tree lines in the front VDC plane
278 
279  ifront = 0;
280  for (const QwTreeLine* frontline = frontlist; frontline;
281  frontline = frontline->next, ifront++) {
282 
283  // Loop over the tree lines in the back VDC plane
284  int iback = 0;
285  for (const QwTreeLine* backline = backlist; backline;
286  backline = backline->next, iback++) {
287 
288  // If this front segment was matched to this back segment
289  if (fmatches[ifront] == iback) {
290 
291  // Create a new tree line
292  QwTreeLine* treeline = new QwTreeLine;
293  // Set the detector identification
294  treeline->SetRegion(frontline->GetRegion());
295  treeline->SetPackage(frontline->GetPackage());
296  treeline->SetDirection(frontline->GetDirection());
297  treeline->SetOctant(frontline->GetOctant());
298 
299  // NOTE:Set the hits for front VDC, the reverse will determine how we should align the treelines
300  int fronthits = frontline->GetNumberOfHits();
301  for (int hit = 0; hit < fronthits; hit++) {
302  treeline->AddHit(frontline->GetHit(hit));
303  QwHit* this_hit = treeline->GetListOfHits().back();
304  this_hit->fDriftPosition *= reverse[ifront*numblines+iback];
305  }
306  // Set the hits for back VDC
307  int backhits = backline->GetNumberOfHits();
308  for (int hit = 0; hit < backhits; hit++) {
309  treeline->AddHit(backline->GetHit(hit));
310  QwHit* this_hit = treeline->GetListOfHits().back();
311 
312  if (backline->GetPackage() == 1)
313  this_hit->fWirePosition -= delta_u;
314  else
315  this_hit->fWirePosition += delta_u;
316 
317  this_hit->fDriftPosition *= reverse[ifront*numblines+iback];
318  this_hit->fDriftPosition += delta_perp;
319  }
320  int nhits = fronthits + backhits;
321 
322  // Fit a line to the hits
323  double slope, offset, chi, cov[3];
324  TreeCombine->r3_TreelineFit (slope, offset, cov, chi, treeline->GetListOfHits(), 0, -1);
325 
326  // Store the determined offset, slope, and chi^2 into the tree line
327  treeline->SetOffset(offset);
328  treeline->SetSlope(slope);
329  treeline->SetChi(chi);
330 
331  treeline->CalculateAverageResidual();
332 
333  treeline->fNumHits = nhits;
334  treeline->fNumMiss = 2 * MAX_LAYERS - nhits;
335 
336  // Set the tree line valid
337  treeline->SetValid();
338 
339  // TODO remove this along with fHits, this is just so the destructor of treeline is happy
340  for (int hit = 0; hit < fronthits + backhits; hit++) {
341  treeline->fHits[hit] = new QwHit();
342  }
343 
344  treeline->next = treelinelist;
345  treelinelist = treeline;
346  }
347  }
348  }
349 
350  // Delete the tree combining object
351  delete TreeCombine;
352 
353  // Return the list of matched tree lines (if no tree lines found, this is null)
354  return treelinelist;
355 }
double GetElementCoordinate(const int element) const
#define QwMessage
Predefined log drain for regular messages.
Definition: QwLog.h:50
double GetDetectorPitchSin() const
const std::vector< QwHit * > & GetListOfHits() const
Get the list of hits.
Definition: QwTreeLine.h:115
void SetRegion(EQwRegionID region)
Set the region.
void SetSlope(const double slope)
Set the slope.
Definition: QwTreeLine.h:177
void SetPackage(EQwDetectorPackage package)
Set the package.
double GetDetectorPitchCos() const
const Double_t & GetWirePosition() const
Definition: QwHit.h:94
EQwRegionID GetRegion() const
Get the region.
Double_t fDriftPosition
Position of the decoded hit in the drift cell.
Definition: QwHit.h:186
void SetChi(const double chi)
Set the chi^2.
Definition: QwTreeLine.h:181
int GetPlane() const
Get the plane number.
double GetSlopeMatching() const
void SetValid(const bool isvoid=false)
Definition: QwTreeLine.h:91
void SetOctant(int octant)
Set the octant number.
int fNumHits
number of hits on this treeline
Definition: QwTreeLine.h:221
void SetOffset(const double offset)
Set the offset.
Definition: QwTreeLine.h:173
const Double_t & GetDriftPosition() const
Definition: QwHit.h:93
void SetDirection(EQwDirectionID direction)
Set the direction.
double GetYPosition() const
One-dimensional (u, v, or x) track stubs and associated hits.
Definition: QwTreeLine.h:51
int fNumMiss
number of planes without hits
Definition: QwTreeLine.h:222
static std::ostream & endl(std::ostream &)
End of the line.
Definition: QwLog.cc:299
double GetElementSpacing() const
const QwDetectorInfo * GetDetectorInfo() const
Get the detector info pointer.
void AddHit(const QwHit *hit)
Add a single hit.
Definition: QwTreeLine.cc:219
Combines track segments and performs line fitting.
double GetElementAngleCos() const
QwTreeLine * next
Definition: QwTreeLine.h:231
void r3_TreelineFit(double &slope, double &offset, double cov[3], double &chi, const std::vector< QwHit * > hits, double z1, int wire_offset)
QwHit * fHits[2 *MAX_LAYERS]
Definition: QwTreeLine.h:224
Hit structure uniquely defining each hit.
Definition: QwHit.h:43
#define MAX_LAYERS
Definition: globals.h:8
double GetZPosition() const
double GetXPosition() const
EQwDirectionID GetDirection() const
Get the direction.
Double_t fWirePosition
Definition: QwHit.h:187
double CalculateAverageResidual()
Calculate the average residuals.
Definition: QwTreeLine.cc:296
#define QwError
Predefined log drain for errors.
Definition: QwLog.h:40
EQwDetectorPackage GetPackage() const
Get the package.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void QwTrackingTreeMatch::SetDebugLevel ( int  debug)
inline

Set the debug level.

Definition at line 63 of file QwTrackingTreeMatch.h.

References fDebug.

Referenced by QwTrackingWorker::QwTrackingWorker().

63 { fDebug = debug; };

+ Here is the caller graph for this function:

Field Documentation

int QwTrackingTreeMatch::fDebug
private

Definition at line 72 of file QwTrackingTreeMatch.h.

Referenced by MatchRegion3(), and SetDebugLevel().


The documentation for this class was generated from the following files: