StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StBeamBackMaker.cxx
1 //
2 // Pibero Djawotho <pibero@indiana.edu>
3 // Indiana University
4 // November 17, 2005
5 //
6 
7 // C++ STL
8 #include <vector>
9 #include <set>
10 
11 // STAR
12 #include "StEventTypes.h"
13 
14 // Local
15 #include "Line.hh"
16 #include "Track.hh"
17 #include "TopologyMap.hh"
18 #include "StBeamBackMaker.h"
19 
20 #define MAX_R_DISTANCE 5. // cm
21 #define MAX_Z_DISTANCE 10. // cm
22 #define MIN_TRACK_SEED_HITS 60
23 using namespace std;
24 struct LessHit {
25  bool operator()(const StHit* hit1, const StHit* hit2) const
26  {
27  return hit1->position().z() < hit2->position().z();
28  }
29 };
30 
31 typedef multiset<StHit*, LessHit> HitSet;
32 typedef HitSet::iterator HitSetIter;
33 
34 struct LessTrack {
35  bool operator()(const Track* track1, const Track* track2) const
36  {
37  return track1->size() < track2->size();
38  }
39 };
40 
41 typedef multiset<Track*, LessTrack> TrackSet;
42 typedef TrackSet::iterator TrackSetIter;
43 
44 ClassImp(StBeamBackMaker)
45 
46 Int_t StBeamBackMaker::Make()
47 {
48  info() << "Processing run=" << GetRunNumber()
49  << ", event=" << GetEventNumber() << endm;
50 
51  StEvent* event = (StEvent*)GetInputDS("StEvent");
52  if (!event) {
53  warning("No StEvent");
54  return kStWarn;
55  }
56 
57  StTpcHitCollection* tpc = event->tpcHitCollection();
58  if (!tpc) {
59  info("No TPC hits");
60  return kStOk;
61  }
62 
63  info() << tpc->numberOfHits() << " TPC hits in event" << endm;
64 
65  //
66  // Collect all unused TPC hits, i.e. those that were not assigned to
67  // any track by ITTF, into a set with the hit
68  // with the least z-coordinate at the beginning and the hit with
69  // the highest z-coordinate at the end.
70  //
71  HitSet hits;
72  for (UInt_t sector = 0; sector < tpc->numberOfSectors(); ++sector) {
73  for (UInt_t padrow = 0; padrow < tpc->sector(sector)->numberOfPadrows(); ++padrow) {
74  for (UInt_t i = 0; i < tpc->sector(sector)->padrow(padrow)->hits().size(); ++i) {
75  StHit* hit = tpc->sector(sector)->padrow(padrow)->hits()[i];
76  if (!hit->trackReferenceCount()) {
77  hits.insert(hit);
78  }
79  }
80  }
81  }
82  info() << hits.size() << " unused TPC hits in event" << endm;
83 
84  //
85  // Find track seeds
86  //
87  info("Find track seeds");
88  // Allocate storage, but don't initialize
89  Track* bufBeg = (Track*)malloc(sizeof(Track)*hits.size());
90  Track* bufEnd = bufBeg;
91  TrackSet tracks;
92  while (!hits.empty()) {
93  Track* track = bufEnd++;
94  new (track) Track;
95  StHit* hit = *hits.begin();
96  track->push_back(hit);
97  hits.erase(hits.begin());
98  // Compute initial centroid
99  double sumX = hit->position().x();
100  double sumY = hit->position().y();
101  double meanX = sumX;
102  double meanY = sumY;
103  // Add hits within MAX_R_DISTANCE of centroid to track
104  for (HitSetIter i = hits.begin(); i != hits.end();) {
105  StHit* hit = *i;
106  double dz = hit->position().z() - track->lastHit()->position().z();
107  if (fabs(dz) > MAX_Z_DISTANCE) break;
108  double dx = meanX - hit->position().x();
109  double dy = meanY - hit->position().y();
110  double dr = hypot(dx, dy);
111  if (dr < MAX_R_DISTANCE) {
112  track->push_back(hit);
113  HitSetIter next = i;
114  ++next;
115  hits.erase(i);
116  i = next;
117  // Update centroid
118  sumX += hit->position().x();
119  sumY += hit->position().y();
120  meanX = sumX / track->size();
121  meanY = sumY / track->size();
122  }
123  else {
124  ++i;
125  }
126  }
127  tracks.insert(track);
128  }
129  info() << tracks.size() << " track seeds found" << endm;
130 
131  //
132  // Pick only track seeds with at least MIN_TRACK_SEED_HITS hits.
133  // The others are put back in the set of available hits.
134  //
135  info() << "Removing track seeds with less than "
136  << MIN_TRACK_SEED_HITS << " hits" << endm;
137  for (TrackSetIter i = tracks.begin(); i != tracks.end();) {
138  Track* track = *i;
139  if (track->size() < MIN_TRACK_SEED_HITS) {
140  for (Track::iterator j = track->begin(); j != track->end(); ++j) {
141  StHit* hit = *j;
142  hits.insert(hit);
143  }
144  TrackSetIter next = i;
145  ++next;
146  tracks.erase(i);
147  i = next;
148  }
149  else {
150  ++i;
151  }
152  }
153  info() << tracks.size() << " track seeds left with " << MIN_TRACK_SEED_HITS << " hits or more" << endm;
154 
155  //
156  // Try to fit track seeds to straight tracks by doing
157  // parallel linear regression analyses in xz and yz.
158  //
159  info("Find linear tracks");
160  vector<Track*> linearTracks;
161  for (TrackSetIter i = tracks.begin(); i != tracks.end(); ++i) {
162  Track* track = *i;
163  if (track->fit() && track->ok()) {
164  //
165  // Try to extend the straight track by looking for hits in the
166  // pool of available hits that are within 5 cm of the centroid
167  // of the track in the xy-plane.
168  //
169  for (HitSetIter j = hits.begin(); j != hits.end();) {
170  StHit* hit = *j;
171  if (track->accept(hit)) {
172  track->push_back(hit);
173  // Move added hit to its proper place
174  nth_element(track->begin(), track->rbegin().base(), track->end(), LessHit());
175  track->fit();
176  HitSetIter next = j;
177  ++next;
178  hits.erase(j);
179  j = next;
180  }
181  else {
182  ++j;
183  }
184  }
185  linearTracks.push_back(track);
186  }
187  }
188  info() << linearTracks.size() << " linear tracks found" << endm;
189 
190  //
191  // Merge linear tracks if both end points of the first track
192  // are within 5 cm of the centroid of the track in the xy-plane.
193  //
194  info("Start merging tracks");
195  for (unsigned int i = 0; i < linearTracks.size(); ++i) {
196  if (!linearTracks[i]) continue;
197  for (unsigned int j = i + 1; j < linearTracks.size(); ++j) {
198  if (!linearTracks[j]) continue;
199  if (linearTracks[i]->accept(linearTracks[j]->firstHit()) &&
200  linearTracks[i]->accept(linearTracks[j]->lastHit())) {
201  linearTracks[i]->merge(linearTracks[j]);
202  linearTracks[j] = 0;
203  }
204  }
205  }
206 
207  //
208  // Compress vector of linear tracks (remove null entries)
209  //
210  linearTracks.erase(remove(linearTracks.begin(), linearTracks.end(),
211  (Track*)0), linearTracks.end());
212  info() << linearTracks.size() << " merged tracks" << endm;
213 
214  //
215  // Refit and remove outliers.
216  //
217  info("Refit and remove outliers");
218  for (unsigned int i = 0; i < linearTracks.size(); ++i) {
219  Track* track = linearTracks[i];
220  if (track->fit()) {
221  for (Track::iterator j = track->begin(); j != track->end();) {
222  StHit* hit = *j;
223  if (track->accept(hit)) {
224  ++j;
225  }
226  else {
227  j = track->erase(j);
228  hits.insert(hit);
229  }
230  }
231  }
232  }
233  info() << hits.size() << " unused TPC hits" << endm;
234 
235  //
236  // Number of hits in linear tracks
237  //
238  int nHits = 0;
239  for (unsigned int i = 0; i < linearTracks.size(); ++i)
240  nHits += linearTracks[i]->size();
241  info() << nHits << " TPC hits in linear tracks" << endm;
242 
243  //
244  // Track to StTrack conversion.
245  //
246  // Find the highest track key. Increment successively to assign
247  // to new tracks.
248  //
249  info("Converting Track to StTrack");
250  Int_t key = 0;
251  for (unsigned int i = 0; i < event->trackNodes().size(); ++i) {
252  Int_t key2 = event->trackNodes()[i]->track(global)->key();
253  if (key < key2) key = key2;
254  }
255 
256  Int_t nStTrack = 0;
257  for (unsigned int i = 0; i < linearTracks.size(); ++i) {
258  if (pileup(linearTracks[i])) continue;
259  StTrack* track = createStTrack(linearTracks[i]);
260  StTrackNode* trackNode = new StTrackNode;
261  track->setKey(++key);
262  trackNode->addTrack(track);
263  event->trackNodes().push_back(trackNode);
264  event->trackDetectorInfo().push_back(track->detectorInfo());
265  ++nStTrack;
266  }
267  info() << nStTrack << " StTrack saved" << endm;
268 
269  //
270  // Clean up
271  //
272  for (Track* track = bufBeg; track != bufEnd; ++track) track->~Track();
273  free(bufBeg);
274 
275  return kStOk;
276 }
277 
278 StTrack* StBeamBackMaker::createStTrack(Track* track)
279 {
280  StTrack* gTrack = new StGlobalTrack;
281  gTrack->setLength(track->length());
282  gTrack->setFlag(901);
283  // Inner geometry
284  StThreeVectorF origin(track->x0(), track->y0(), 0);
285  StThreeVectorF momentum(track->dxdz(), track->dydz(), 1);
286  Line line(origin, momentum);
287  momentum.setMag(999); // Bogus
288  double dipAngle = atan2(1, hypot(track->dxdz(), track->dydz()));
289  gTrack->setGeometry(new StHelixModel(-1, // Charge
290  M_PI_2, // Psi
291  0, // Curvature
292  dipAngle, // Dip angle
293  line.perigee(track->firstHit()->position()), // Origin
294  momentum, // Momentum
295  1)); // Helicity
296  gTrack->setEncodedMethod(kLine2StepId);
297  // Outer geometry
298  StTrackGeometry* outerGeometry = gTrack->geometry()->copy();
299  outerGeometry->setOrigin(line.perigee(track->lastHit()->position()));
300  gTrack->setOuterGeometry(outerGeometry);
301 
302  // Detector info
304  detInfo->setFirstPoint(track->firstHit()->position());
305  detInfo->setLastPoint(track->lastHit()->position());
306  for (Track::iterator i = track->begin(); i != track->end(); ++i)
307  detInfo->addHit(*i);
308  // Number of points cannot be larger than 255 (unsigned char)
309  detInfo->setNumberOfPoints(track->size() < 256 ? track->size() : 255, kTpcId);
310  gTrack->setDetectorInfo(detInfo);
311  // Fit traits
312  StTrackFitTraits fitTraits;
313  // Number of fit points cannot be larger than 255 (unsigned char)
314  fitTraits.setNumberOfFitPoints(track->size() < 256 ? track->size() : 255, kTpcId);
315  gTrack->setFitTraits(fitTraits);
316 
317  return gTrack;
318 }
319 
320 inline bool StBeamBackMaker::pileup(Track* track) const
321 {
322  TopologyMap topoMap(track);
323  return (topoMap.nearEast() < 4 || topoMap.farEast() < 4 ||
324  topoMap.nearWest() < 4 || topoMap.farWest() < 4);
325 }
326 
327 inline ostream& StBeamBackMaker::info(const Char_t* message)
328 {
329  if (message)
330  return gMessMgr->Info(Form("%s: %s", GetName(), message));
331  return gMessMgr->Info() << GetName() << ": ";
332 }
333 
334 inline ostream& StBeamBackMaker::warning(const Char_t* message)
335 {
336  if (message)
337  return gMessMgr->Warning(Form("%s: %s", GetName(), message));
338  return gMessMgr->Warning() << GetName() << ": ";
339 }
Number of hits in diffent zones of the TPC for a given track.
Definition: TopologyMap.hh:29
double y0() const
y-intercept at z = 0
Definition: Track.hh:171
STAR includes.
Definition: Line.hh:23
Definition: StHit.h:125
bool fit()
Perform linear fits in zx- and zy-plane.
Definition: Track.cc:26
Beam background tracker in the TPC.
double x0() const
x-intercept at z = 0
Definition: Track.hh:170
bool ok() const
Good track?
Definition: Track.cc:62
double dydz() const
dy/dz slope
Definition: Track.hh:173
bool accept(StHit *hit) const
Is hit close enough to track?
Definition: Track.cc:67
Definition: Stypes.h:42
StHit * firstHit() const
First hit.
Definition: Track.hh:164
StHit * lastHit() const
Last hit.
Definition: Track.hh:165
double dxdz() const
dx/dz slope
Definition: Track.hh:172
C++ STL includes.
Definition: AgUStep.h:47
Definition: Stypes.h:41
double length() const
Track length.
Definition: Track.hh:166