QwAnalysis
QwTrackingTreeSearch.cc
Go to the documentation of this file.
1 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
2 //
3 // C++ Interface: QwTrackingTreeSearch
4 //
5 // Description:
6 //
7 //
8 // Author: Burnham Stocks <bestokes@jlab.org>
9 // Original HRC Author: wolfgang Wander <wwc@hermes.desy.de>
10 //
11 // Modified by: Wouter Deconinck <wdconinc@mit.edu>, (C) 2008
12 // Jie Pan <jpan@jlab.org>, Mon May 25 10:48:12 CDT 2009
13 //
14 // Copyright: See COPYING file that comes with this distribution
15 //
16 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
17 
18 /*! \class QwTrackingTreeSearch
19 
20  \file QwTrackingTreeSearch.cc
21 --------------------------------------------------------------------------*\
22 
23  PROGRAM: QTR (Qweak Track Reconstruction) AUTHOR: Burnham Stokes
24  bestokes@jlab.org
25  ORIGINAL HRC AUTHOR
26  Wolfgang Wander
27  wwc@hermes.desy.de
28 
29 
30  MODULE: QwTrackingTreeSearch.c COMMENTS: Brendan Fox
31  foxb@hermes.desy.de
32 
33  PURPOSE: This module contains the code for performing the treesearch
34  algorithm to generate one treeline. The code first use the hit
35  information for the planes to construct the bit pattern for each
36  tree-planes. Then, it searches through the treesearch database
37  and identifies each treenode in the database which is present
38  in the bit patterns for the tree-planes. These treenodes are
39  then used to generate the link-listed of possible treelines.
40 
41  CONTENTS: (brief description for now)
42 
43  (01) wireselection() - this function is called by TsSetPoints. It steps
44  through the hits from the unprimed and primed planes
45  for a tree-plane to decide whether hits should or
46  should not be paired together when the hit pattern
47  for the tree-plane is constructed.
48 
49  (02) _setpoints() - this function sets the bins in a hit pattern for
50  a range of positions. The range of hit patterns
51  is specified by a start and a stop position in
52  the detector. This function turns on the bins
53  in the hit pattern for each level of the
54  bin-division used in the treesearch algorithm.
55 
56  (03) _setpoint() - this function sets the bins in the hit pattern for
57  a range of positions around a central point within
58  a specified distance/resolution by calling the
59  _setpoints() function.
60 
61  (04) setpoint() - this function sets the bins in the hit pattern for a
62  range of positions specified by a center point and
63  a half-distance around the center point by calling
64  the setpoint() function.
65 
66  (05) TsSetPoint() - this function sets the bins in the hit pattern for
67  a range of positions around a central point within
68  a specified distance/resolution. This function
69  turns on the bins in the hit pattern for each level
70  of the bin-division in the treesearch algorithm.
71 
72  (06) exists() - this function searches through the link-list of
73  valid treelines to see if the bit pattern for the
74  specified treenode has already been accepted as
75  a valid treeline.
76 
77  (07) _SearchTreeLines() - this highly recursive function implements the
78  treesearch algorithm. For a specified list of
79  nodenodes, this function examines the attached
80  treenode. If the bit pattern in the treenode
81  does not match the bit pattern from the event,
82  the function looks at the next nodenode. Otherwise,
83  the function will call itself to see if any of
84  the sons of this treenode at the next level of
85  bin-division match the bit pattern from the event.
86  This recursive calling will continue until a
87  treenode at the deepest level of bin-division is
88  located inside the bit pattern from the event.
89  Since the pattern in this treenode is represents
90  a valid treeline for the event, a treeline is
91  constructed from the treenode and then appended
92  to the linked list of treelines being accumulated
93  by the treesearch.
94 
95  (08) SearchTreeLines() - this function initiates the treesearch for a set
96  of tree-planes by calling the _SearchTreeLines() function
97  described above.
98 
99  $date: Mon May 25 10:48:12 CDT 2009 $
100 
101 \brief This module contains the code for performing the treesearch
102  algorithm to generate one treeline.
103  */
104 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
105 
106 #include "QwTrackingTreeSearch.h"
107 
108 // Standard C and C++ headers
109 #include <cstdio>
110 #include <cmath>
111 #include <cstdlib>
112 #include <cassert>
113 #include <cstring>
114 #include <iostream>
115 
116 // Qweak headers
117 #include "QwLog.h"
118 #include "QwOptions.h"
119 #include "globals.h"
120 #include "QwHit.h"
121 #include "QwDetectorInfo.h"
122 #include "QwTreeLine.h"
123 #include "QwTrackingTreeRegion.h"
124 
125 // Qweak tracking tree headers
126 #include "shortnode.h"
127 #include "shorttree.h"
128 
129 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
130 
131 static int _hashgen = 1;
132 
133 static int hashgen(void) {
134  _hashgen += 2;
135  _hashgen &= 0x7ffffff;
136  return _hashgen;
137 }
138 
139 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
140 
142 : fNumPlanes(fNumLayers),fNumWires(fNumLayers)
143 {
144  fDebug = 1; // Reset debug level
145 
147 
148  fMaxMissedPlanes = gQwOptions.GetValue<int>("QwTracking.R2.MaxMissedPlanes");
149  fMaxMissedWires = gQwOptions.GetValue<int>("QwTracking.R3.MaxMissedWires");
150 }
151 
152 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
153 
155 {
156 }
157 
158 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
159 
160 std::vector<QwTreeLine*> QwTrackingTreeSearch::GetListOfTreeLines ()
161 {
162  return fTreeLineList;
163 }
164 
165 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
166 /**
167  _setpoints() - this function sets the bins in a hit pattern for a
168  range of positions. The range of hit patterns is specified
169  by a start and a stop position in the detector. This
170  function turns on the bins in the hit pattern for each
171  level of the bin-division used in the treesearch algorithm.
172 
173  inputs: (1) double posStart - position (in cm) of the start of the
174  range for which bins are to be turned
175  on
176  (2) double posEnd - position (in cm) of the stop of the
177  range for which bins are to be turned
178  on
179  (3) double detectorwidth - width of the tree-detector (in cm)
180  (4) unsigned binwidth - width of a bin at the deepest level
181  of bin-division in the treesearch.
182  (5) char *pattern - pointer to the hit pattern for this
183  tree-detector
184  (6) int *hash - pointer to ???
185 
186  outputs: (1) char *pattern - pointer to the hit pattern for this
187  tree-detector
188  (2) int *hash - pointer to ???
189 
190 */
192  double pos_start,
193  double pos_end,
194  double detectorwidth,
195  unsigned binwidth,
196  char *pattern,
197  int *hash)
198 {
199  int ia, ie, hashint = hashgen();
200  unsigned oldwidth = binwidth;
201  char *oldpattern = pattern;
202 
203 /* ---- compute the first bin in the deepest tree level to turn on ---- */
204 
205  ia = (int) floor (pos_start / detectorwidth * binwidth);
206 
207 /* ---- compute the last bin in the deepest tree level to turn on ---- */
208 
209  ie = (int) floor (pos_end / detectorwidth * binwidth);
210 
211 /* ---- step through each of the bins at the deepest bin-division
212  level in the hit pattern and turn on the bits in the
213  pattern at all the bin-division levels for this bin. ---- */
214 
215  for (int j = ia; j <= ie; j++) { /* loop over the bins to be set */
216 
217  int i = j; /* remember the bin at the deepest level which is being turn on */
218 
219  binwidth = oldwidth; /* the size of the bit pattern for the detector
220  at the deepest level of bin-division. */
221  pattern = oldpattern; /* pointer to start of the bit pattern */
222 
223 /* ---- check if the bin is inside the detector ---- */
224  //I added "(signed int)" to the
225  //following line to prevent the warning from comparing signed and
226  //unsigned integers
227  if (i >= (signed int) binwidth)
228  return;
229  if (i < 0)
230  continue;
231 /* ---- compute some hash value ---- */
232  hash[i] = ((hash[i]<<1) + hashint)|1 ;
233 /* ---- set the bits in the bit pattern at all depths of bin-division ---- */
234 
235  if (pattern) {
236  while (binwidth) { /* starting at maximum depth, loop over
237  each depth of the treesearch */
238  pattern[i] = 1; /* turn on the bit in this bin */
239  pattern += binwidth; /* set ahead to the part of the bit
240  pattern in which the bits for the
241  next higher bin-division are stored */
242  i >>= 1; /* go up one depth of the depth */
243  binwidth >>= 1; /* size of the bit pattern for the next
244  higher bin-division is half of the
245  size of the bit pattern for a given
246  level of bin-division. */
247 
248  } /* end of loop over the depths of the treesearch */
249  }
250  } /* end of loop over the bins to be set */
251 }
252 
253 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
254 /**
255  _setpoint() - this function sets the bins in the hit pattern for a
256  range of positions around a central point within a specified
257  distance/resolution by calling the setpoint() function
258  described above.
259 
260  inputs: (1) double position - position (in cm) of the center point
261  around which the bins are to be turned
262  on
263  (2) double resolution - distance (in cm) around the central
264  point for which bins are to be turned
265  on
266  (3) double detectorwidth - width of the tree-detector (in cm)
267  (4) unsigned binwidth - width of a bin at the deepest level
268  of bin-division in the treesearch.
269  (5) char *pattern - pointer to the hit pattern for this
270  tree-detector
271  (6) int *hash - ???
272 
273  outputs: (1) char *pattern - pointer to the hit pattern for this
274  tree-detector
275  (2) int *hash - pointer to ???
276 
277  */
279  double position,
280  double resolution,
281  double detectorwidth,
282  unsigned binwidth,
283  char *pattern,
284  int *hash)
285 {
286  _setpoints (position - resolution, position + resolution,
287  detectorwidth, binwidth, pattern, hash);
288 }
289 
290 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
291 /**
292  setpoint() - this function sets the bins in the hit pattern for a range
293  of positions specified by a center point and a half-distance
294  around the center point by calling the _setpoint() function
295  described above.
296 
297  If hit patterns are supplied to this function for both the
298  primed and unprimed planes, the two planes are treated as
299  separate tree-detectors. In this case, the hit patterns
300  are updated for each plane individually. This feature is
301  used for the front region when the VCs are not included
302  in the fit because, for these fits, each FC plane is treated
303  as a single tree-detector.
304 
305  Otherwise, the two planes are treated as a single
306  tree-detector and a single hit pattern is formed from the
307  hits seen in the two planes.
308 
309  inputs: (01) double off - alignment offset of the
310  tree-detector (in cm)
311  (02) double h1 - center point of hit range on
312  plane 1 (in cm)
313  (03) double res1 - width of hit range on plane 1 (in cm)
314  (04) double h2 - center point of hit range on
315  plane 2 (in cm)
316  (05) double res2 - width of hit range on plane 2 (in cm)
317  (06) double width - width of the tree-detector (in cm)
318  (07) unsigned binwidth - width of a bin at the deepest level
319  of bin-division in the treesearch.
320  (08) char *pa - pointer to the hit pattern for
321  tree-detector 1
322  (09) char *pb - pointer to the hit pattern for
323  tree-detector 2, =0 if there is no
324  tree-detector 2 because the planes are
325  being combined into one tree-detector
326  (10) int *hasha - pointer to ???
327  (11) int *hashb - pointer to ???
328 
329  outputs: (01) char *pa - pointer to the updated hit pattern
330  for tree-detector 1
331  (02) char *pb - pointer to the updated hit pattern for
332  tree-detector 2, = 0 if there is no
333  tree-detector 2 because the planes are
334  being combined into one tree-detector
335  (03) int *hasha - pointer to ???
336  (04) int *hashb - pointer to ???
337 
338  */
340  double off,
341  double h1,
342  double res1,
343  double h2,
344  double res2,
345  double width,
346  unsigned binwidth,
347  char *pa,
348  char *pb,
349  int *hasha,
350  int *hashb)
351 {
352  if (pb) { /* NOT combining two planes into one tree-detector, so
353  set bins in the hit pattern for each plane separately */
354  _setpoint (off + h1, res1, width, binwidth, pa, hasha);
355  _setpoint (off + h2, res2, width, binwidth, pb, hashb);
356  } else /* Combining two planes into one tree-detector, so just
357  set the bins for the overlap between the hit on the
358  two planes. Here, the resolutions are added linearly
359  instead of in quadrature to save cputime */
360  _setpoint (off + 0.5 * (h1+h2), 0.5 * (res1+res2), width, binwidth, pa, hasha);
361 }
362 
363 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
364 /**
365  TsSetPoint() - this function creates the bit patterns for two partner
366  planes (planes with the like-pitched wires in the
367  same chamber.
368 
369  This function can treat the two planes in two different
370  fashions, specifically:
371 
372  (1) the planes can be treated as one tree-detector. In
373  this case, a check is performed to see if a hit on
374  one of the planes can be matched to a hit on the
375  other plane (within the allowances of the maximum
376  track slope specified by the HRCset parameter
377  MaxSlope). If the hits are paired together by this
378  search, the bit pattern is set around the allowable
379  tracks through both hits. If a hit is not paired
380  in this search, the bit pattern is set for the region
381  around the hit. (This method is the standard for
382  the back chambers since they have eight planes per
383  treeline).
384 
385  (2) the planes are treated as individual tree-detectors.
386  In this case, a separate hit pattern is created for
387  both planes and the above described searching for
388  paired hits is not employed. (This method is the
389  standard for the front chambers since they have only
390  four planes per treeline).
391 
392  inputs: (01) double detectorwidth - width of the tree-detector (in cm)
393  (02) double zdistance - distance between the two planes
394  forming this tree-detector (in cm)
395  (03) Hit *Ha - linked list of hits for the unprimed
396  plane of this tree-detector
397  (04) Hit *Hb - linked list of hits for the primed
398  plane of this tree-detector
399  (05) unsigned binwidth - width of a bin (in cm) at the deepest
400  bin-division in the treesearch.
401 
402  outputs: (01) int TsSetPoint() - the number of single and paired hits
403  processed by this return
404  (02) char *patterna - pointer to the hit pattern for
405  tree-detector
406  (03) char *patternb - pointer to the hit pattern for
407  the optional second tree-detector
408  (04) int *hasha - pointer to ???
409  (05) int *hashb - pointer to ???
410 
411  */
412 // This TsSetPoint version is designed for setting the pattern for Region 2
413 // doing one hit at a time, using the QwHit class.
415  double detectorwidth,
416  double wirespacing,
417  QwHit *hit,
418  char *pattern,
419  int *hash,
420  unsigned binwidth)
421 {
422  // Get the wire number
423  int wire = hit->GetElement();
424  wirespacing = hit->GetDetectorInfo()->GetElementSpacing();
425 
426  // Set the points on the front/top side of the wire (R3/R2)
427  _setpoints(wirespacing * (wire+1) - hit->GetDriftDistance() - hit->GetDetectorInfo()->GetTrackResolution(),
428  wirespacing * (wire+1) - hit->GetDriftDistance() + hit->GetDetectorInfo()->GetTrackResolution(),
429  detectorwidth, binwidth, pattern, hash);
430 
431  // Set the points on the back/bottom side of the wire (R3/R2)
432  _setpoints(wirespacing * (wire+1) + hit->GetDriftDistance() - hit->GetDetectorInfo()->GetTrackResolution(),
433  wirespacing * (wire+1) + hit->GetDriftDistance() + hit->GetDetectorInfo()->GetTrackResolution(),
434  detectorwidth, binwidth, pattern, hash);
435 
436  return 0;
437 }
438 
439 /**
440  * This function searches through the link-list of valid treelines
441  * to see if the bit pattern for the specified treenode has already
442  * been accepted as a valid treeline.
443  *
444  * @param newa
445  * @param front
446  * @param back
447  * @param offset
448  * @param treelinelist Pointer to the linked list of treelines
449  * @return 0 if no such tree line exists, 1 otherwise
450  */
452  int *newa,
453  int front,
454  int back,
455  int offset)
456 {
457  int *olda;
458  int oldmiss, diff;
459 
460  int newmiss = 0;
461  for (unsigned int row = 0; row < fNumPlanes; row++)
462  if (! newa[row])
463  newmiss++;
464 
465  // Loop over the treelines
466  for (size_t i = 0; i < fTreeLineList.size(); i++) {
467  QwTreeLine* tl = fTreeLineList[fTreeLineList.size() - 1 - i];
468 
469  // If the treeline has been voided, go onto next one
470  if (tl->IsVoid())
471  continue;
472 
473  int over = 0;
474 
475  int wire_diff=0;
476  wire_diff=abs(offset-tl->fR3Offset);
477 
478  if(wire_diff<5 && offset!=-1){
479  if (tl->a_beg == front && front == tl->a_end )
480  over++;
481  if (tl->b_beg == back && back == tl->b_end )
482  over++;
483  }
484 
485  // r2
486  if(offset==-1){
487  if(tl->a_beg == front && front == tl->a_end )
488  ++over;
489  if(tl->b_beg == back && back == tl->b_end )
490  ++over;
491  }
492  if (over == 2) {
493  return 1;
494  }
495  if (over == 0)
496  continue;
497 
498  olda = tl->fHashArray;
499  oldmiss = 0;
500  diff = 0;
501 
502  for (unsigned int row = 0; row < fNumLayers; ++row) {
503  if (! olda[row]) {
504  oldmiss++;
505  } else {
506  if (newa[row] && olda[row] != newa[row]) {
507  diff = 1;
508  break;
509  }
510  }
511  }
512 
513 
514  if (! diff && offset!=-1) {
515  if ((newmiss == 0 && oldmiss == 0) ||
516  (!newa[0] && !olda[0]) ||
517  (!newa[fNumPlanes-1] && !olda[fNumPlanes-1]) ||
518  (newmiss && !oldmiss && (!newa[0] || !newa[fNumPlanes-1])) ||
519  (oldmiss && !newmiss && (!olda[0] || !olda[fNumPlanes-1]))
520  ) {
521  if (tl->a_beg > front)
522  tl->a_beg = front;
523  if (tl->a_end < front)
524  tl->a_end = front;
525  if (tl->b_beg > back)
526  tl->b_beg = back;
527  if (tl->b_end < back)
528  tl->b_end = back;
529 // std::cerr << "!diff" << std::endl;
530  return 1;
531  }
532  }
533  }
534  return 0;
535 }
536 
537 
538 /**
539  * This highly recursive function implements the tree search
540  * algorithm. For a specified list of nodenodes, this function
541  * examines the attached treenode. If the bit pattern in the
542  * treenode does not match the bit pattern from the event, the
543  * function looks at the next nodenode. Otherwise, the function
544  * will call itself to see if any of the sons of this treenode
545  * at the next level of bin division match the bit pattern from
546  * the event. This recursive calling will continue until a
547  * treenode at the deepest level of bin division is located
548  * inside the bit pattern from the event. Since the pattern in
549  * this treenode represents a valid treeline for the event, a
550  * treeline is constructed from the treenode and then appended
551  * to the linked list of treelines being accumulated by the
552  * tree search.
553  *
554  * @param node Pointer to the first node in the linked list
555  * @param level Depth of the treesearch, i.e. the level of the bin-division
556  * @param offset Offset of the treenode within the pattern
557  * @param row_offset Offset of the wire group in region 3
558  * @param reverse Flag "pattern is flipped"
559  * @param numwires Number of wires in region 3
560  */
562  shortnode *node,
563  int level,
564  int offset,
565  int row_offset,
566  int reverse,
567  int numwires)
568 {
569 
570 
571  // Next level in the recursive search
572  bool search_debug_level=0;
573  if(search_debug_level)
574  std::cout << "entering _SearchTreeLines with level" << level << " and row_offset " << row_offset << std::endl;
575  int nextlevel = level + 1;
576  std::vector<int> patterns(MAX_LAYERS);
577 
578  // Fail if we have already found enough treelines
580  return;
581 
582  /**
583  * Reminder about the bit pattern:
584  * - there are n levels of bin division, so 8,4,2,1 bins for 4 levels,
585  * - there are rows corresponding with the HDC planes or VDC wires.
586  *
587  * HDC planes (spaces between the 5 levels of bin division)
588  * for 16 bins in wire coordinate (e.g. 16 wires)
589  * and zero distance resolution
590  * \code
591  * plane 1: ......|......... ...|.... .|.. |. |
592  * plane 2: .......|........ ...|.... .|.. |. |
593  * plane 3: ........|....... ....|... ..|. .| |
594  * plane 4: .........|...... ....|... ..|. .| |
595  * \endcode
596  *
597  * VDC wires (spaces between the 4 levels of bin division)
598  * for 8 bins in drift distance and zero distance resolution
599  * \code
600  * wire 159: |......| |..| || |
601  * wire 160: .|....|. |..| || |
602  * wire 161: ..|..|.. .||. || |
603  * wire 162: ...||... .||. || |
604  * wire 163: ..|..|.. .||. || |
605  * wire 164: .|....|. |..| || |
606  * wire 165: |......| |..| || |
607  * \endcode
608  */
609 
610  /* Compute the offset in the bit pattern for the start position of this level
611  * of bin division. For n levels, there are 2^n - 1 used bins. Each level
612  * has 2^k bins (i.e. 1 bin at level 0, 2 at level 1). The start of level k
613  * is at position position (2^n - 1) - 2^k + 1 (counting from bin 0).
614  * and Sum (i = k..n) 2^i = (2^n - 1) - (2^k - 1)
615  *
616  * E.g.: For n = 4 there are 8,4,2,1 bins, so the start bin positions are
617  * 0,8,12,14 for k = 0,1,2,3,4.
618  */
619  unsigned long pattern_start = (unsigned long) 0xffffffffL;
620  pattern_start <<= level + 1;
621  pattern_start &= (unsigned long) 0xffffffffL >> (32 - fMaxLevel);
622  // Warn when this pattern_start puts us past the bit pattern
623  if (pattern_start > fPattern_fMaxBins)
624  QwWarning << "pattern start past end: " << pattern_start << QwLog::endl;
625  // Debug output
626  if (fDebug)
627  QwDebug << "pattern start = " << pattern_start << QwLog::endl;
628 
629  // NOTE: this procedure is used in region2, and number 4 is hard-coded(might be removed later)
630  static int has_planes[4];
631  unsigned int missed_planes =0 ;
632  if(level == 0 && numwires==0){
633  for(unsigned int plane=0;plane< fNumPlanes;plane++){
634  if(static_pattern[plane][pattern_start])
635  has_planes[plane]=1;
636  else{
637  has_planes[plane]=0;
638  missed_planes++;
639  }
640  }
641  }
642  /** Determine the rows which have hits first. This is used to determine how
643  * many wires in a region 3 group have been hit. If there are fewer than a
644  * preset number of wire hits, then the search is not even started.
645  */
646  static int has_hits[MAX_LAYERS];
647  unsigned int missed_rows = 0;
648  if (level == 0 && numwires>0 ) {
649  for (unsigned int row = 0; row < fNumPlanes; row++) {
650  // Bounds checking
651  assert(row_offset + row < fPattern_fMaxRows);
652  assert(pattern_start < fPattern_fMaxBins);
653  // Has this row a hit?
654  if (static_pattern[row_offset+row][pattern_start])
655  has_hits[row] = 1;
656  else {
657  has_hits[row] = 0;
658  missed_rows++;
659  }
660  }
661  }
662 
663 
664  /* Region 3 */
665  if (numwires > 0) {
666  while (node) {
667 
668  /* Look at the trees attached to each nodenode on the
669  * specified nodenode linked list
670  */
671  shorttree* tree = node->GetTree();
672 
673  /* Is the hit pattern in this treenode valid for this level
674  * of the treesearch? (i.e. check boundaries)
675  */
676  if (tree->fMinLevel > level + 1) { /* check for level boundaries */
677  QwError << "Tree invalid for this treesearch!" << QwLog::endl;
678  node = node->GetNext(); /* no, so look at the next nodenode */
679  continue;
680  }
681 
682  /* Match the hit pattern to this treenode by checking the
683  * hit pattern for each tree plane to see if the bits
684  * specified in the treenode are on.
685  */
686  unsigned long pattern_offset = pattern_start + offset;
687  int* tree_pattern = tree->fBit;
688 
689  unsigned int matched_wires = 0;
690 
691  // Reset the first and last wire
692  int firstwire = fPattern_fMaxRows;
693  int lastwire = -1;
694 
695  // Different treatment for reversed trees
696  if (reverse) {
697 
698  // This is not completely tested yet
699  QwError << "reversed patterns need checking/debugging" << QwLog::endl;
700 
701  // Loop over tree-planes
702  for (unsigned int row = 0; row < fNumWires; row++) {
703  int bin = (*tree_pattern++);
704  // Bounds checking
705  assert(row_offset + row < fPattern_fMaxRows);
706  assert(pattern_offset - bin < fPattern_fMaxBins);
707  // If the bin is set
708  if (static_pattern[row_offset + row][pattern_offset - bin]) {
709  matched_wires++; /* number of matched tree-planes */
710  if ((int) row < firstwire) firstwire = row;
711  if ((int) row > lastwire) lastwire = row;
712  }
713  } // end of loop over wires
714 
715  }
716  else {
717  /* loop over tree-planes */
718  for (unsigned int row = 0; row < fNumWires; row++) {
719  int bin = (*tree_pattern++);
720  if(search_debug_level)
721  std::cout << "for level" << level <<" bin:" << bin << std::endl;
722  // Bounds checking
723  patterns.at(row)=bin;
724  assert(row_offset + row < fPattern_fMaxRows);
725  assert(pattern_offset + bin < fPattern_fMaxBins);
726  // If the bin is set
727  if (static_pattern[row_offset + row][pattern_offset + bin]) {
728  matched_wires++; /* number of matched tree-planes */
729  if ((int) row < firstwire) firstwire = row;
730  if ((int) row > lastwire && bin != 0) lastwire = row;
731 
732  // But matching null hits is allowed in these patterns, i.e.
733  // missing wires are not treated as bad when the bin is not set
734  }
735  else if (bin == 0 && has_hits[row] == 0) {
736  matched_wires++;
737  }
738  } // end of loop over wires
739  } // end of if reversed
740 
741  // chcke if there's any missing wires in the middle or allow only 1 goofy wires
742 
743  if(matched_wires < fNumWires ){
744  int goofy=0;
745  int* tree_pattern_copy = tree->fBit;
746  if(reverse){
747  // needs to do something?
748  }
749  else{
750  for(unsigned int row=0;row<fNumWires;row++){
751  int bin = (*tree_pattern_copy++);
752  assert( row_offset + row < fPattern_fMaxRows);
753  assert(pattern_offset + bin < fPattern_fMaxBins);
754  if ((int)row > firstwire && (int)row <= lastwire){
755  if (static_pattern[row_offset + row][pattern_offset + bin])
756  continue;
757  else if (has_hits[row] == 0) matched_wires++;
758  else if(goofy<1) {matched_wires++;goofy++;}
759  }
760  }
761  }
762  }
763 
764  if(search_debug_level){
765  std::cout << "matched_wires: " << matched_wires << std::endl;
766  std::cout << "missed rows: " << missed_rows << std::endl;
767  }
768 
769 
770  /// Check if there was a treenode match now that the matching has been
771  /// completely tested, but allow for some missing wires.
772  if (matched_wires == fNumWires && missed_rows <= fMaxMissedWires) {
773 
774  /// Yes, there is a match, so now check if all the levels of the
775  /// tree search have been done.
776 
777  if (level == fMaxLevel - 1) {
778 
779  /// If so, then we have found a valid treeline.
780 
781  // Calculate the bin in the last layer
782  int backbin = reverse ? offset - tree->fBit[fNumPlanes-1]
783  : offset + tree->fBit[fNumPlanes-1];
784  if (reverse) {
785  backbin = 0;
786  for (unsigned int wire = 0; wire < fNumWires; wire++) {
787  if (offset - tree->fBit[wire] > backbin)
788  backbin = offset - tree->fBit[wire];
789  }
790  }
791  else {
792  backbin = 0;
793  for (unsigned int wire = 0; wire < fNumWires; wire++) {
794  if (offset + tree->fBit[wire] > backbin)
795  backbin = offset + tree->fBit[wire];
796  }
797  }
798 
799  // Calculate the bin in the first layer
800  int hashpat[fNumWires];
801  int frontbin = reverse ? offset - tree->fBit[0]
802  : offset + tree->fBit[0];
803  for (unsigned int wire = 0; wire < fNumWires; wire++) {
804  int bin = reverse ? offset - tree->fBit[wire]
805  : offset + tree->fBit[wire];
806  // And set the hash for this pattern
807  hashpat[wire] = static_hash[wire][bin];
808  }
809 
810  // Consider this a miss if the front layer or back layer did not
811  // have a hit
812  int miss = 0;
813  if (static_pattern[0+row_offset][frontbin] == 0)
814  miss = 1;
815  else if (static_pattern[fNumPlanes-1+row_offset][backbin] == 0)
816  miss = 1;
817 
818 
819  /* Check whether this treeline already exists */
820 
821  if (! exists(hashpat, frontbin, backbin, row_offset)) {
822 
823  /* Print tree */
824  if (fShowMatchingPatterns) tree->Print();
825 
826  /* Create new treeline */
827  QwTreeLine* treeline = new QwTreeLine (frontbin, frontbin, backbin, backbin);
828 
829  /* Number of treelines found */
830  fNTreeLines++;
831 
832  /* Copy hash pattern */
833  memcpy(treeline->fHashArray, hashpat, sizeof(int) * fNumWires);
834 
835  /* Missed front or back planes (?) */
836  /* (only used until TreeLineSort) */
837  treeline->fNumMiss = miss;
838 
839  /* Region 3 specific treeline info */
840  treeline->fR3Offset = row_offset;
841  treeline->fR3FirstWire = firstwire;
842  treeline->fR3LastWire = lastwire;
843  treeline->SetMatchingPattern(patterns);
844 // for(int i=0;i< patterns.size();i++)
845 // std::cout << "bin value: "<< patterns.at(i) << std::endl;
846  if (search_debug_level) {
847  std::cout << "first wire: " << firstwire << std::endl;
848  std::cout << "last wire: " << lastwire << std::endl;
849  }
850  /* Add this treeline to the linked-list */
851  if (firstwire != lastwire) {
852  fTreeLineList.push_back(treeline);
853  } else delete treeline;
854  }
855 
856 
857  } else { // if (level != fMaxLevel - 1)
858 
859  /// If not, then we descend to check the son patterns
860 
861  if(search_debug_level)
862  std::cout << "not the deepest level,begin recursive call!" << std::endl;
863  for (int rev = 0; rev < 4; rev += 2) {
864 
865  shortnode** cnode = tree->son + rev;
866 
867 
868  if (rev ^ reverse) {
869 
870  int off2 = (offset << 1) + 1;
871  for (int off = 0; off < 2; off++)
872  _SearchTreeLines (*cnode++, nextlevel, off2 - off, row_offset, 2, numwires);
873  } else {
874 
875  int off2 = (offset << 1);
876  for (int off = 0; off < 2; off++)
877  _SearchTreeLines (*cnode++, nextlevel, off2 + off, row_offset, 0, numwires);
878 
879  }
880 
881  } // end of for over son nodes
882 
883  } // end of if we have reached the maximum level (level == fMaxLevel - 1)
884 
885  }
886 
887  // There was no match, so go onto the next nodenode
888  node = node->GetNext();
889 
890  } // end of loop over nodes
891 
892 
893  } else { /* Region 2 */
894 
895  while (node) { /* search in all nodes */
896 
897 
898  shorttree* tree = node->GetTree();
899 
900 
901  /* ---- Is the hit pattern in this treenode valid for this level
902  of the treesearch? ---- */
903 
904  if (tree->fMinLevel >= level) { /* check for level boundaries */
905  node = node->GetNext(); /* no, so look at the next nodenode */
906  continue;
907  }
908 
909 
910  /* ---- Match the hit pattern to this treenode by checking the
911  hit pattern for each tree-plane to see if the bits
912  specified in the treenode are on ---- */
913 
914  //NOTE:to print out the final binoffset value
915  //int final[4] = {0}; // unused
916  unsigned long pattern_offset = pattern_start + offset;
917  int* tree_pattern = tree->fBit;
918  unsigned int matched_planes = 0;
919  int goofy_r2=0;
920  if (reverse) {
921  /* loop over tree-planes */
922  for (unsigned int plane = 0; plane < fNumPlanes; ++plane) {
923  int bin=(*tree_pattern++);
924  if (static_pattern[plane][pattern_offset - bin]) {
925  matched_planes++; /* number of matched tree-planes */
926  }
927  }
928  } else {
929  /* loop over tree-planes */
930  for (unsigned int plane = 0; plane < fNumPlanes; ++plane) {
931  int bin=(*tree_pattern++);
932  patterns.at(plane)=pattern_offset + bin;
933  if (static_pattern[plane][pattern_offset + bin] || has_planes[plane]==0) {
934  ++matched_planes; /* number of matched tree-planes */
935  //final[plane] = pattern_offset+bin; // unused
936  }
937  //else if(has_planes[plane]==0){
938  // ++matched_planes;
939  // final[plane]=pattern_offset+bin;
940  //}
941  else if(goofy_r2==0 && missed_planes==0 && level==fMaxLevel-1){
942  ++matched_planes;
943  ++goofy_r2;
944  }
945  }
946  }
947 
948 
949  /* ---- Check if there was a treenode match now that the
950  matching has been completely tested. ---- */
951 // if (matched_planes >= fNumPlanes - fMaxMissedPlanes) {
952 
953 
954  if (matched_planes == fNumPlanes && missed_planes <= fMaxMissedPlanes ){
955  /* ---- Yes, there is a match, so now check if all the levels
956  of the treesearch have been done. If so, then we have
957  found a valid treeline. ---- */
958 
959 
960  if (level == fMaxLevel - 1) {
961  /* all levels done -> now insert treeline */
962  int hashpat[fNumPlanes];
963  int frontbin = reverse ? offset - tree->fBit[0]
964  : offset + tree->fBit[0];
965  int backbin = reverse ? offset - tree->fBit[fNumPlanes-1]
966  : offset + tree->fBit[fNumPlanes-1];
967  for (unsigned int plane = 0; plane < fNumPlanes; plane++) {
968  int bin = reverse ? offset - tree->fBit[plane]
969  : offset + tree->fBit[plane];
970  hashpat[plane] = static_hash[plane][bin];
971  }
972 
973  /* If the front or back bin are null, this is considered a miss (?) */
974  int miss = 0;
975  if (static_pattern[0][frontbin] == 0)
976  miss = 1;
977  else if (static_pattern[fNumPlanes-1][backbin] == 0)
978  miss = 1;
979  /* Check whether this treeline already exists */
980  if (! exists(hashpat, frontbin, backbin, -1)) {
981 
982  /* Print tree */
983  if (fShowMatchingPatterns) tree->Print();
984 
985  /* Create new treeline */
986 
987  QwTreeLine* treeline = new QwTreeLine (frontbin, frontbin, backbin, backbin);
988  /* Number of treelines found */
989  ++fNTreeLines;
990 
991  /* Copy hash pattern */
992  memcpy(treeline->fHashArray, hashpat, sizeof(int) * fNumPlanes);
993 
994  /* Missed front or back planes (?) */
995  /* (only used until TreeLineSort) */
996  treeline->fNumMiss = miss;
997  treeline->SetMatchingPattern(patterns);
998  /* Add this treeline to the linked-list */
999  fTreeLineList.push_back(treeline);
1000  }
1001 
1002  } else { /* check son patterns */
1003 
1004  for (int rev = 0; rev < 4; rev += 2) {
1005  shortnode** cnode = tree->son + rev;
1006  if (rev ^ reverse) {
1007  int off2 = (offset << 1) + 1;
1008  for (int off = 0; off < 2; off++){
1009  _SearchTreeLines (*cnode++, nextlevel, off2 - off, 0, 2, 0);
1010  }
1011  } else {
1012  int off2 = offset << 1;
1013  for (int off = 0; off < 2; off++) {
1014  _SearchTreeLines (*cnode++, nextlevel, off2 + off, 0, 0, 0);
1015  }
1016  }
1017  } /* highly optimized - time critical */
1018  }
1019  }
1020  node = node->GetNext(); /* ok, there wasn't a match, so go onto the
1021  next nodenode */
1022 
1023  } // end of loop over nodes
1024 
1025  } // end of region 2
1026 
1027  return;
1028 }
1029 
1030 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1031 
1032 /**
1033  * Initiate the treesearch for a set of tree detectors by calling the
1034  * recursive _SearchTreeLines() function. The tree search algorithm is
1035  * explained in QwTrackingTreeSearch::_SearchTreeLine().
1036  *
1037  * @param searchtree Pattern search tree
1038  * @param pattern Hit pattern
1039  * @param hashpat Hash pattern
1040  * @param maxlevel Maximum number of levels
1041  * @param numwires Number of wires in region 3
1042  * @param numlayers Number of layers in region 3
1043  * @return Linked list of treelines
1044  */
1046  QwTrackingTreeRegion* searchtree,
1047  char **pattern,
1048  int **hashpat,
1049  int maxlevel,
1050  int numwires,
1051  int numlayers)
1052 {
1053  // Determine the top node of the search tree for the recursive search
1054  shortnode* topnode = searchtree->GetNode();
1055 
1056  // Store the number of rows (accessible through references named
1057  // fNumPlanes and fNumWires)
1058  fNumLayers = numlayers;
1059 
1060  // Store the maximum level, pattern and hash
1061  fMaxLevel = maxlevel;
1062 
1063  static_pattern = pattern;
1064  static_hash = hashpat;
1065 
1066  // Store the maximum bin index in a pattern:
1067  // total number of bins = 2^levels - 1 = (1UL << levels) - 1
1068  fPattern_fMaxBins = (1UL << maxlevel) - 1;
1069 
1070  // Reset the list of tree lines (this could cause memory leaks)
1071  fNTreeLines = 0; // number of tree lines
1072  fTreeLineList.clear();
1073 
1074  /// For every wire we perform a recursive search. For region 2 the number of
1075  /// wires is set to zero, so this will only execute once for every plane.
1076  /// For region 3 we will run over all the wires in the plane, and consider the
1077  /// next fNumWires wires (so we need to end early).
1078 
1079  if (numwires > 0) { // region 3
1080 
1081  // Store the maximum number of rows
1082  fPattern_fMaxRows = numwires;
1083 
1084  /// For region 3, we determine which groups of wires need to be considered:
1085  /// only those groups of numlayers wires with at least one hit are to be
1086  /// considered; the others are empty and the tree search should not even
1087  /// be started.
1088  std::vector<int> wiregroups; // list of wire groups to consider
1089  int last_wire_with_hit = -1; // last wire with a hit
1090  for (int wire = 0; wire < numwires; wire++) {
1091  // If this wire was hit (check in the single bin at the end of the pattern)
1092  if (pattern[wire][(1UL << maxlevel) - 2] == 1) {
1093  // Set all previous numlayers-1 groups active (including this wire)
1094  for (int wiregroup = std::max(wire - numlayers + 1, last_wire_with_hit);
1095  wiregroup < std::min(numwires - numlayers + 1, wire); wiregroup++) {
1096  if (wiregroup < 0) continue; // ignore negative wires
1097  wiregroups.push_back(wiregroup);
1098  }
1099  // Keep track of which wire had the last hit
1100  last_wire_with_hit = wire;
1101  }
1102  }
1103  // The region 3 version of SearchTreeLines
1104  // (search for groups of numlayers wires)
1105  for (size_t i = 0; i < wiregroups.size(); i++) {
1106  _SearchTreeLines (topnode, 0, 0, wiregroups.at(i), 0, numwires);
1107  }
1108 
1109  } else { // region 2
1110 
1111  // Store the maximum number of rows
1112  fPattern_fMaxRows = numlayers;
1113  // The region 2 version of SearchTreeLines
1114  _SearchTreeLines (topnode, 0, 0, 0, 0, 0);
1115 
1116  } // region 2
1117 
1118  // Write out the number of tree lines
1119  QwDebug << "Found " << fNTreeLines << " tree line(s)." << QwLog::endl;
1120 
1121 
1122  // Put in linked list
1123  QwTreeLine* list = 0;
1124  if (fTreeLineList.size() > 0) {
1125  for (size_t tl = 0; tl < fTreeLineList.size(); tl++) {
1126  fTreeLineList[tl]->next = list;
1127  list = fTreeLineList[tl];
1128  }
1129  }
1130 
1131  // Return the list of tree lines
1132  return list;
1133 }
int * fBit
Hit pattern, one bin specified per detector layer.
Definition: shorttree.h:64
unsigned int fMaxMissedPlanes
Maximum number of missed planes in region 2.
int exists(int *newa, int front, int back, int offset)
int fHashArray[2 *MAX_LAYERS]
///&lt; all hits that satisfy road requirement
Definition: QwTreeLine.h:226
#define TREESEARCH_MAX_TREELINES
QwTrackingTreeSearch()
Constructor.
void SetMatchingPattern(std::vector< int > &box)
Set the matching pattern.
Definition: QwTreeLine.cc:367
int fMaxLevel
Maximum level of this tree search.
int fR3Offset
offset of demultiplexed group of 8
Definition: QwTreeLine.h:228
int GetElement() const
Get the element number.
shortnode * GetNode()
Get the node to this tree region.
void Print(bool recursive=false, int indent=0)
Print some debugging information.
Definition: shorttree.cc:61
A container for the pattern databases for each detector region.
unsigned int & fNumPlanes
Number of region 2 HDC planes.
bool fShowMatchingPatterns
Flag to show matching patterns when found.
QwOptions gQwOptions
Definition: QwOptions.cc:27
int fR3LastWire
first and last wire in group of 8
Definition: QwTreeLine.h:229
unsigned int & fNumWires
Number of region 3 VDC wires.
static int hashgen(void)
unsigned int fMaxMissedWires
Maximum number of missed wires in region 3.
T GetValue(const std::string &key)
Get a templated value.
Definition: QwOptions.h:240
int fMinLevel
Minimum level at which this node is valid.
Definition: shorttree.h:61
void setpoint(double off, double h1, double res1, double h2, double res2, double width, unsigned binwidth, char *pa, char *pb, int *hasha, int *hashb)
#define QwDebug
Predefined log drain for debugging output.
Definition: QwLog.h:60
A logfile class, based on an identical class in the Hermes analyzer.
std::vector< QwTreeLine * > fTreeLineList
shortnode * son[4]
Each tree has four son nodes.
Definition: shorttree.h:72
Draft skeleton for the decoding-to-QTR interface class.
void _SearchTreeLines(shortnode *node, int level, int offset, int row_offset, int reverse, int numwires)
Recursive tree search algorithm.
void _setpoints(double pos_start, double pos_end, double detectorwidth, unsigned binwidth, char *pattern, int *hash)
Performs the treesearch algorithm to generate one treeline.
Similar to a treenode.
Definition: shorttree.h:44
static int _hashgen
const Double_t & GetDriftDistance() const
Definition: QwHit.h:92
int b_end
bin in last layer
Definition: QwTreeLine.h:219
shorttree * GetTree(int i=0) const
Get the tree.
Definition: shortnode.cc:54
Definition of a shortnode, the short version of a nodenode.
Definition of the one-dimensional track stubs.
static const double min
Definition: QwUnits.h:76
bool IsVoid() const
Is this tree line void?
Definition: QwTreeLine.h:87
void _setpoint(double position, double resolution, double detectorwidth, unsigned binwidth, char *pattern, int *hash)
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
std::vector< QwTreeLine * > GetListOfTreeLines()
Get the list of tree lines.
static std::ostream & endl(std::ostream &)
End of the line.
Definition: QwLog.cc:299
double GetElementSpacing() const
shortnode * GetNext() const
Get the next node.
Definition: shortnode.h:69
const QwDetectorInfo * GetDetectorInfo() const
Get the detector info pointer.
Similar to a nodenode.
Definition: shortnode.h:38
An options class which parses command line, config file and environment.
int fR3FirstWire
Definition: QwTreeLine.h:229
QwTreeLine * SearchTreeLines(QwTrackingTreeRegion *searchtree, char *pattern[16], int *hashpat[16], int maxlevel, int numwires, int numlayers)
Search for the tree lines consistent with the hit pattern.
Hit structure uniquely defining each hit.
Definition: QwHit.h:43
#define MAX_LAYERS
Definition: globals.h:8
int a_end
bin in first layer
Definition: QwTreeLine.h:218
unsigned int fNumLayers
Number of detector layers (general concept)
#define QwWarning
Predefined log drain for warnings.
Definition: QwLog.h:45
virtual ~QwTrackingTreeSearch()
Destructor.
int TsSetPoint(double detectorwidth, double wirespacing, QwHit *hit, char *pattern, int *hash, unsigned binwidth)
Method to set the tree pattern.
double GetTrackResolution() const
#define QwError
Predefined log drain for errors.
Definition: QwLog.h:40