EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HoughNodeGroup.h
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file HoughNodeGroup.h
1 //
2 // AYK (ayk@bnl.gov)
3 //
4 // Hough transform node definitions;
5 //
6 // Initial port from OLYMPUS sources: Oct'2015;
7 //
8 
9 #include <set>
10 #include <cassert>
11 #include <math.h>
12 
13 #include <TVector3.h>
14 
15 #include <SensitiveVolume.h>
16 #include <EicMagneticField.h>
17 #include <EicTrackingDigiHit.h>
18 
19 #ifndef _HOUGH_NODE_GROUP_
20 #define _HOUGH_NODE_GROUP_
21 
23 
24 // FIXME: use system definitions, please;
25 typedef unsigned short __u16;
26 typedef unsigned int __u32;
27 typedef unsigned long long __u64;
28 
29 // Well, in principle one would like to have a scheme where planes with
30 // different t_hough_range can be used at the same time; however from practical
31 // point of view even if one wants say to mix 1D and 2D detectors, it is easier
32 // to use the same type (sufficiently wide for everybody) and just pack the
33 // bits differently; this allows to use arrays of t_hough_range variables
34 // in several places rather than calculate nasty offsets or arrange more
35 // complicated STL objects (?); in this case there is no real advantage
36 // of "templatizing" GroupMember & HoughNodeGroup classes because will have
37 // to do the same with HoughTree (and then move all the sources to HoughTree.h
38 // file); so for now consider to use a single hardcoded type throughout the
39 // code (and if width becomes insufficient for certain application, just
40 // take __u64 or so and recompile);
42 
43 // So these definitions are already invariant over t_hough_range type; and in this
44 // approach they become global define's;
45 #define _MAX_USEFUL_BIT_COUNT_ ((sizeof(t_hough_range) << 3)-1)
46 #define __OUT_OF_RANGE_BIT_ (((t_hough_range)0x1) << _MAX_USEFUL_BIT_COUNT_)
47 
48 class GroupMember {
49 public:
50  GroupMember(const std::pair<void *, void *> &ptr, t_hough_range from, t_hough_range to):
51  mPtr(ptr), mFrom(from), mTo(to), mBusy(false) {};
52 
53  // Want to encapsulate everything and ultimately switch to a completely
54  // templated version with policies;
55  t_hough_range From() const { return mFrom; };
56  t_hough_range To() const { return mTo; };
57 
58  // Member can be booked during tree search, but not yet busy; vice versa is
59  // always true however; FIXME: may actually want to limit IsBooked() call to the
60  // current tree search pass (so that do not take into account owners from previous passes);
61  bool IsBusy() const { return mBusy; };
62  bool IsBooked() const { return (mMatchCandidates.size() != 0); };
63  void SetBusyFlag() { mBusy = true; };
64 
65  // Something which allows to identify this member hit back in the
66  // caller fit routine; FIXME: should be done better;
67  std::pair <void *, void *> mPtr;
68 
69  void InsertMatchCandidate(MatchCandidate *match) { mMatchCandidates.insert(match); };
70  void EraseMatchCandidate(MatchCandidate *match) { mMatchCandidates.erase(match); };
71 
72  // FIXME: allocate iterators once?;
73  std::set<MatchCandidate*>::iterator Begin() { return mMatchCandidates.begin(); };
74  std::set<MatchCandidate*>::iterator End() { return mMatchCandidates.end(); };
75 
76  private:
77  // Back-door pointers to match candidates which claim to own this hit;
78  // NB: since hit borrowing is allowed, there can in principle be more than
79  // one track candidate pretending to own any given hit (may eventually want to
80  // allow hit sharing, etc -> THINK later, but for now keep std::set here rather
81  // than a single pointer;);
82  std::set<MatchCandidate*> mMatchCandidates;
83 
84  // NB: can not use mMatchCandidates.size() as a BUSY sign, since several track
85  // candidates may want to claim a given hit during tree search; mBusy flag will be
86  // asserted only after tree search is finished and "best track candidate" grabs
87  // the hit (and then other track candidates with a lower chi^2 CCDF will not have
88  // access to it any longer during this particular search+fit pass);
89  bool mBusy;
90 
91  // Micro-cell geographical coordinates; NB: they are not guaranteed to
92  // be ordered in all componenets (ngroup->Overlap() call will check);
94 };
95 
96 // FIXME: may want to unify with EicBitMask at some point;
98  public:
99  CoordinateDescriptor(double min, double max, double gra, unsigned shift): mMin(min), mGra(gra), mShift(shift) {
100  // THINK: is this strictly true?;
101  mWdim = int((max - min)/gra);
102 
103  mWidth = bits(mWdim);
104  mMask = ~(t_hough_range(0)) >> ((sizeof(t_hough_range) << 3) - mWidth);
105  //printf("%2d -> %X %X\n", mWidth, mMask, wdim-1);
106  };
107 
108  double GetMin() const { return mMin; };
109  double GetGra() const { return mGra; };
110 
111  unsigned GetBitWidth() const { return mWidth; };
112 
113  // NB: assume I'm given 0-based values here (so also return 0-based one);
114  t_hough_range UnpackCoord(t_hough_range value) const { return (value >> mShift) & mMask; };
115  // Well, assume coordinates can be out of [0..mWdim-1] range and then need to
116  // be regularized; also assume, that 'int' width is sufficient for all practical cases;
117  t_hough_range PackCoord(int coord) const {
118  if (coord < 0)
119  // Effectively pack coord=0;
120  return __OUT_OF_RANGE_BIT_;
121  else if (coord >= mWdim)
122  // Pack max in-range coord value; NB: '& mMask' is not really needed here and below;
123  return (((t_hough_range)mWdim-1) << mShift) | __OUT_OF_RANGE_BIT_;
124  else
125  return ((t_hough_range)coord) << mShift;
126  };
127 
129  if (!offset) return value;
130 
131  t_hough_range coord = (value >> mShift) & mMask;
132  int result = coord + offset;
133 
134  if (result < 0)
135  return 0x0;
136  else if (result >= mWdim)
137  return ((t_hough_range)(mWdim-1)) << mShift;
138  else
139  return ((t_hough_range)result) << mShift;
140  };
141 
142  private:
143  // FIXME: unify with the same code in HoughTree.cxx;
145  // Yes, prefer to avoid pathologic cases; at least 1 bit allocation please;
146  if (value == 1) return 1;
147 
148  unsigned count = 0;
149 
150  // Subtract 1 and shift to the right till get zero value;
151  for(value--; value; count++)
152  value >>= 1;
153 
154  return count;
155  };
156 
157  // Parameters for bit-wise packing operations: field shift, width and
158  // mask once shifted to 0-th position;
159  unsigned mShift, mWidth;
161 
162  double mMin, mGra;
163  // Basically means: expected "strip id" range is [0..mWdim-1];
164  unsigned mWdim;
165 };
166 
168  public:
169  HoughNodeGroup(unsigned id): mId(id), mPhaseSpaceSmearing(0) {};
170 
171  void ConfigureCoordinateDescriptors(unsigned cdim, const double min[], const double max[],
172  const double gra[]) {
173  // FIXME: range check here, please;
174  unsigned accu = 0;
175 
176  for(unsigned iq=0; iq<cdim; iq++) {
177  mCoordDescr.push_back(CoordinateDescriptor(min[iq], max[iq], gra[iq], accu));
178 
179  accu += mCoordDescr[mCoordDescr.size()-1].GetBitWidth();
180  } //for iq
181  };
182  virtual ~HoughNodeGroup() {};
183 
184  int AddMember(const std::pair<void *, void *> &ptr, t_hough_range from, t_hough_range to) {
185  // FIXME; check out-of-range condition;
186 #if _THINK_
187  if (from > to || to > _imax) return -1;
188 #endif
189 
190  mMembers.push_back(GroupMember(ptr, from, to));
191 
192  return 0;
193  };
194 
195  void ResetMemberCounter() { mMembers.clear(); };
196  unsigned GetMemberCount() const { return mMembers.size(); };
197  GroupMember *GetMember(unsigned mm) { return (mm < mMembers.size() ? &mMembers[mm] : 0); };
198 
199  void SetPhaseSpaceSmearing(unsigned smearing) { mPhaseSpaceSmearing = smearing; };
200  unsigned GetPhaseSpaceSmearing() const { return mPhaseSpaceSmearing; };
201 
202  unsigned GetGroupId() const { return mId; };
203 
204  // FIXME: put this XYZ stuff in some other place eventually;
206  if (id >= mCoordDescr.size()) return 0;
207 
208  return mCoordDescr[id].UnpackCoord(value);
209  };
210 
211  const std::vector<CoordinateDescriptor> &GetCoordDescr() { return mCoordDescr; };
212 
213  // Shift all packed components by (possibly negative) offset and pack
214  // back; NB: obey boundary conditions [0..mWdim-1];
216  t_hough_range ret = 0x0;
217 
218  for(unsigned iq=0; iq<mCoordDescr.size(); iq++)
219  ret |= mCoordDescr[iq].OffsetThisValueComponent(value, offset);
220 
221  return ret;
222  };
223 
224  // NB: in generic case need to confirm overlap in all dimensions; FIXME: assume,
225  // that neither of 2x2 t_hough_range values has an __OUT_OF_RANGE_BIT_ bit set;
226  bool Overlap(std::pair<t_hough_range, t_hough_range> r1,
227  std::pair<t_hough_range, t_hough_range> r2) {
228  for(unsigned iq=0; iq<mCoordDescr.size(); iq++) {
229  CoordinateDescriptor *descr = &mCoordDescr[iq];
230 
231  // This pair presently comes from member->From()/To(); ranges here may
232  // be swapped; THINK: may want to swap wrongly ordered components in
233  // AddMember() call?;
234  t_hough_range r1l = descr->UnpackCoord(r1.first);
235  t_hough_range r1r = descr->UnpackCoord(r1.second);
236  if (r1l > r1r) {
237  t_hough_range bff = r1l;
238 
239  r1l = r1r;
240  r1r = bff;
241  } //if
242  //assert(r1l < r1r);
243 
244  // This pair is presently cell->From()/To(); they are guaranteed
245  // to be ordered (although can be equal: the same cell); so leave assert() here;
246  t_hough_range r2l = descr->UnpackCoord(r2.first);
247  t_hough_range r2r = descr->UnpackCoord(r2.second);
248  // FIXME: return the strict check back!;
249  //if (r2l == r2r) printf("%8X %8X\n", r2l, r2r);
250  assert(r2l <= r2r);
251 
252  if (r2l > r1r || r2r < r1l) return false;
253  } //for iq
254 
255  return true;
256  };
257 
258  double GetMin(unsigned iq) const {
259  return iq < mCoordDescr.size() ? mCoordDescr[iq].GetMin() : 0.0;
260  };
261  double GetGra(unsigned iq) const {
262  return iq < mCoordDescr.size() ? mCoordDescr[iq].GetGra() : 0.0;
263  };
264 
265  protected:
266  // Coordinate descriptors (either X or XY or XYZ are packed into
267  // a single t_hough_range variable; pack/unpack operations are needed);
268  std::vector<CoordinateDescriptor> mCoordDescr;
269 
270  t_hough_range HoughPack(const int coord[]) {
271  t_hough_range value = 0x0;
272 
273  for(unsigned iq=0; iq<mCoordDescr.size(); iq++)
274  value |= mCoordDescr[iq].PackCoord(coord[iq]);
275 
276  return value;
277  };
278 
279  private:
280  // Tree search should allow limits on hit count within certain group "types";
281  unsigned mId;
282 
283  // Perhaps add +/- few {strip} units for safety when checking ranges?;
285 
286  // Array of elementary detectors to be OR'ed during calculations; these
287  // are *hits* of a given plane, in the track finder context;
288 #if _LATER_
289  // they can be split into a few "neighboring" entries with different weights;
290 #endif
291  std::vector<GroupMember> mMembers;
292 };
293 
294 #endif