EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FwdTrackFinder.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file FwdTrackFinder.cxx
1 
2 #include <cassert>
3 
4 #include <FairPrimaryGenerator.h>
5 #include <FairBaseParSet.h>
6 
7 #include <ayk.h>
8 #include <3d.h>
9 #include <htclib.h>
10 
11 #include <MediaBank.h>
12 #include <FwdTrackFinder.h>
13 #include <EicTrackingDigiHit.h>
14 #include <EicRunAna.h>
15 
16 // ---------------------------------------------------------------------------------------
17 
19 {
20  // No length limit; KF axis off (0,0,Z-vtx) along (0,0,1); so assume head node
21  // to sit right in Z-vertex as given in event generator;
22  t_3d_line zaxis(TVector3(0.0, 0.0, mEicBoxGenerator->GetVz()), TVector3(0.0, 0.0, 1.0));
23  MediaBank *mbank = new MediaBank(zaxis, 0.0);
24 
25  // Also start off (0,0,Z-vtx); FIXME: perhaps unify with HTC routine?;
26  t_3d_line saxis(TVector3(0.0, 0.0, mEicBoxGenerator->GetVz()), GetMediaScanDirection());
27  mbank->SetScanLine(saxis);
28 
29  return mbank;
30 } // FwdTrackFinder::ConfigureMediaBank()
31 
32 // ---------------------------------------------------------------------------------------
33 
34 // FIXME: unify these calls;
35 
36 int FwdTrackFinder::DefinePhiRange(double min, double max, double gra)
37 {
38  if (mPhiId != -1 || min > max) return -1;
39 
41  mPhaseSpaceVariables.push_back(PhaseSpaceVariable(min, max, gra));
42 
43  //mPhiId = mCurrentId++;
44  mFwdHoughTree->AddDimension("FI", min, max);
45 
46  return 0;
47 } // FwdTrackFinder::DefinePhiRange()
48 
49 int FwdTrackFinder::DefineInversedMomentumRange(double min, double max, double gra)
50 {
51  if (mInvMomentumId != -1 || mInvPtId != -1 || min > max) return -1;
52 
54  mPhaseSpaceVariables.push_back(PhaseSpaceVariable(min, max, gra));
55 
56  //mInvMomentumId = mCurrentId++;
57  mFwdHoughTree->AddDimension("PP", min, max);
58 
59  return 0;
60 } // FwdTrackFinder::DefineInversedMomentumRange()
61 
62 int FwdTrackFinder::DefineInversedPtRange(double min, double max, double gra)
63 {
64  if (mInvMomentumId != -1 || mInvPtId != -1 || min > max) return -1;
65 
67  mPhaseSpaceVariables.push_back(PhaseSpaceVariable(min, max, gra));
68 
69  //mInvPtId = mCurrentId++;
70  mFwdHoughTree->AddDimension("Pt", min, max);
71 
72  return 0;
73 } // FwdTrackFinder::DefineInversedPtRange()
74 
75 int FwdTrackFinder::DefineThetaRange(double min, double max, double gra)
76 {
77  if (mThetaId != -1 || min > max) return -1;
78 
79  mThetaId = mPhaseSpaceVariables.size();//mCurrentId++;
80  mPhaseSpaceVariables.push_back(PhaseSpaceVariable(min, max, gra));
81 
82  //mThetaId = mPhaseSpaceVariables.size();//mCurrentId++;
83  mFwdHoughTree->AddDimension("TH", min, max);
84 
85  return 0;
86 } // FwdTrackFinder::DefineThetaRange()
87 
88 // ---------------------------------------------------------------------------------------
89 
90 int FwdTrackFinder::ConfigureResolutionLevels(/*const PhaseSpaceVariable *psvar*/unsigned id)
91 {
92  const PhaseSpaceVariable *psvar = &mPhaseSpaceVariables[id];
93 
94  double range = psvar->GetRange(), gra = psvar->GetGra();
95  unsigned div[3] = {1, 1, 1};
96 
97  div[id] = 2;
98 
99  for( ; ; ) {
100  if (range < gra) break;
101 
102  if (mFwdHoughTree->AddResolutionLevel(div)) return kERROR;
103 
104  range /= 2;
105  } //for inf
106 
107  return 0;
108 } // FwdTrackFinder::ConfigureResolutionLevels()
109 
110 // ---------------------------------------------------------------------------------------
111 
113 {
115 
116  // Get access to the box generator parameters; FIXME: assert() calls;
117  {
118  FairBaseParSet *bpset;
119 
120  fManager->GetInFile()->GetObject("FairBaseParSet", bpset);
121  assert(bpset);
122 
123  FairPrimaryGenerator *pgen = bpset->GetPriGen();
124  TObjArray *fGenList = pgen->GetListOfGenerators();
125  TIterator *fListIter = fGenList->MakeIterator();
126 
127  {
128  TObject *obj;
129  unsigned gCounter = 0;
130 
131  while( (obj = fListIter->Next()) ) {
132  gCounter++;
133  mEicBoxGenerator = dynamic_cast<EicBoxGenerator*> (obj);
134  } //while
135 
136  assert(gCounter == 1 && mEicBoxGenerator);
137  }
138 
139  //printf("--> %f\n", mEicBoxGenerator->GetVxSmearing()); exit(0);
140  }
141 
142  // Allocate fake IP Kalman filter node;
143  {
144  // FIXME: will not work in magnetic field;
145  bool nonLinFlags[2] = {WithMagneticField(), WithMagneticField()};
146 
147  mVtxKfNode = dynamic_cast<TrKalmanNode*>
148  (GetKalmanFilter()->AddNode("VTX", mEicBoxGenerator->GetVz(), 2, nonLinFlags/*, 0*/));
149  }
150  //printf("%f\n", mVtxKfNode->GetZ()); exit(0);
151 
152  if (EicHtcTask::Init()) return kERROR;
153  //exit(0);
154 
155  //
156  // NB: by this point FwdHoughTree is allocated already and AddDimension()
157  // are presumably called from reconstruction.C script;
158  //
159 
160  assert(GetThetaId() != -1 && GetPhiId() != -1);
161  {
162  assert(mPhaseSpaceVariables.size() <= 3);
163 
164  // Start with phi division pattern;
166 
167  if (WithMagneticField() &&
170  }
171 
172  // Guess on zero-approximation slope and inv.p(pt) cov.matrix; assume user
173  // sort of knows, that it does not make sense to push resolution beyond the
174  // "natural" limit; so just take highest resolution cell size as an estimate;
175  // NB: this value will be blown up in the preliminary KF pass anyway and it
176  // will be taken from CS[][] at vtx node for th efinal pass (and again blown up);
177  {
179 
180  // Assume theta cell width is directly related to {sx,sy};
181  double thetaSize = RADIANS(high->GetCellSize(GetThetaId()));
182  // Here consider larger value; tan() or sin()? well, does not matter I guess;
183  double phiSize = RADIANS(high->GetCellSize(GetPhiId()))*
184  tan(RADIANS(mPhaseSpaceVariables[GetThetaId()].GetMax()));
185  //printf("%f %f\n", thetaSize, phiSize);
186 
187  mAngularCovMtxEstimate = thetaSize > phiSize ? SQR(thetaSize) : SQR(phiSize);
188 
189  if (WithMagneticField()) {
190  // NB: inversed units here (either invp or invpt);
191  double pSize = high->GetCellSize(GetMomentumRelatedId());
192 
193  // In this case have to rescale; take larger angle;
194  if (GetInvPtId() != -1)
195  pSize *= sin(RADIANS(mPhaseSpaceVariables[GetThetaId()].GetMax()));
196  //printf("%f\n", pSize);
197 
199  } //if
200  //exit(0);
201  }
202 
204 
205  // Loop through all locations; pick up those which have sensitive volumes defined;
206  for(TrKalmanNodeLocation *location=GetKalmanFilter()->GetLocationHead(); location;
207  location=location->GetNext(KalmanFilter::Forward)) {
208 
209  if (!location->HasSensitiveVolumes()) continue;
210  printf("%7.2f\n", location->GetZ());
211 
212  // NB: clearly Hough node groups will have different min/max limits depending
213  // on local template orientations inside respective sensitive volume;
214  for(unsigned tmpl=0; tmpl<location->GetSensitiveVolumeNodeWrapperCount(); tmpl++) {
215  // Templates will choose min[]/max[] definitions out of the suggested options and
216  // should distinguish between XY- and RF-cases; assume rmin=0 is fine as well as
217  // [0..2pi] for angular range;
218  std::set<double> xMin, yMin, xMax, yMax, rMin, rMax;
219 
220  //printf(" %2d -> cyl=%d\n", tmpl, location->GetCylindricalPreference(tmpl));
221 
222  for(unsigned kfnd=0; kfnd<location->GetNodeCount(); kfnd++) {
223  TrKalmanNode *node = location->GetNode(kfnd);
224 
225  SensitiveVolume *sv = node->GetSensitiveVolume();
226  if (!sv) continue;
227 
228  //printf(" %s -> xmin=%7.2f, xmax =%7.2f, ymin=%7.2f, ymax=%7.2f\n",
229  // node->GetName(), sv->GetXmin(), sv->GetXmax(), sv->GetYmin(), sv->GetYmax());
230 
231  double xmin = sv->GetXmin(), xmax = sv->GetXmax(), ymin = sv->GetYmin(), ymax = sv->GetYmax();
232  TVector3 vvLc[4] = {TVector3(xmin, ymin, 0.0), TVector3(xmin, ymax, 0.0),
233  TVector3(xmax, ymax, 0.0), TVector3(xmax, ymin, 0.0)};
234 
235  for(unsigned iq=0; iq<4; iq++) {
236  TVector3 vvGl = LocalToMaster(sv->GetLogicalNode()->mGeoMtx, vvLc[iq]);
237  TVector3 vvNd = MasterToLocal(location->GetNodeToMaster(tmpl), vvGl);
238  double xx = vvNd[0], yy = vvNd[1];
239 
240  xMin.insert(xx);
241  xMax.insert(xx);
242  yMin.insert(yy);
243  yMax.insert(yy);
244 
245  rMax.insert(sqrt(xx*xx+yy*yy));
246  } //for iq
247  } //for kfnd
248 
249  // Don't want to do more here; give {location,templates} combination all
250  // the info concerning min/max values and let it decide how to configure itself;
251  FwdHoughNodeGroup *ngroup =
253  xMin, xMax, yMin, yMax, rMin, rMax);
254  if (!ngroup) return kERROR;
255 
256  // Loop through all sensitive volumes associated with this location and assign
257  // back-door node group pointers;
258  for(std::set<SensitiveVolume*>::iterator it=location->GetSensitiveVolumes().begin();
259  it != location->GetSensitiveVolumes().end(); it++)
260  (*it)->SetNodeGroup(tmpl, ngroup);
261  } //for tmpl
262  } //for location
263  //exit(0);
264 
265  // The rest of configuration parameters; unless specifically booked in
266  // reconstruction.C script, default values will be used;
267  {
269 
270  unsigned maxHitCount = GetMaxPossibleHitCount();
271  assert(!mFwdHoughTree->SetOkHitCounterLimits(maxHitCount-mMissingHitCounterMax, maxHitCount));
272 
275  }
276 
277  FairRootManager::Instance()->Register("FwdTrack", "FwdTrackFinder", mTracks, kTRUE);
278 
279  return kSUCCESS;
280 } // FwdTrackFinder::Init()
281 
282 // ---------------------------------------------------------------------------------------
283 
284 // THINK: do I need these to be configurable?;
285 #define _COVARIANCE_FIRST_BLOWUP_CFF_ (1000)
286 #define _COVARIANCE_FINAL_BLOWUP_CFF_ (1000)
287 
289 {
291  // FIXME: find a better way to figure this out?;
292  unsigned sdim = kf->GetFieldMode() == NoField ? 4 : 5;
293 
294  // Figure out 0-th track approximation based on the track finder guess;
295  // NB: I guess tricks like building linear track approximation will not
296  // improve angular part and will be hopeless for momentum determination
297  // anyway -> stick to this procedure; NB: assume FwdHoughTree knows
298  // parameter meaning better that FwdTrackFinder (after all, MappingCall()
299  // is in this class) -> decrypt [theta,phi,1/p(t)] triplet first;
300  double par[mFwdHoughTree->GetDdim()];
301 
302  // FIXME: may want to pack this into a separate call later;
304  const unsigned *id = match->GetIdPtr();
305  for(unsigned iq=0; iq<mFwdHoughTree->GetDdim(); iq++) {
306  const HoughDimension *dimension = mFwdHoughTree->GetDimension(iq);
307 
308  par[iq] = dimension->GetMin() + high->GetCellSize(iq)*(id[iq] + 0.5);
309  } //for iq
310 
311  double rtheta = RADIANS(par[GetThetaId()]), rphi = RADIANS(par[GetPhiId()]);
312  //printf("%f %f\n", par[0], par[1]); exit(0);
313  if (sdim == 5 && GetMomentumRelatedId() != -1) {
314  double pvar = par[GetMomentumRelatedId()], p, pt;
315 
316  assert(pvar);
317  if (GetInvMomentumId() != -1)
318  p = 1./pvar;
319  else
320  p = 1.0/(sin(rtheta)*pvar);
321 
322  //printf("--> %f\n", p); fflush(stdout);
324  } else {
325  assert(mParticleMomentumSeed);
327  } //if
328 
329  // KFV() and KFM() encapsulated operations are used -> just get pointers and use them;
330  {
331  KfVector *x0 = mVtxKfNode->GetX0();
332 
333  // Use generated info here (see simulation.C);
334  x0->KFV(0) = mEicBoxGenerator->GetVx();
335  x0->KFV(1) = mEicBoxGenerator->GetVy();
336 
337  double nn[3] = {sin(rtheta)*cos(rphi), sin(rtheta)*sin(rphi), cos(rtheta)};
338 
339  assert(nn[2]);
340  x0->KFV(2) = nn[0]/nn[2];
341  x0->KFV(3) = nn[1]/nn[2];
342  }
343 
344  // Yes, predicted state vector at start of chain is set to 0.0;
345  {
346  KfVector *x0 = mVtxKfNode->GetX0(), *xp = mVtxKfNode->GetXp();
347 
348  for(int ip=_X_; ip<sdim; ip++)
349  xp->KFV(ip) = 0.;
350  }
351 
352  // Cook dummy (diagonal) covariance matrix;
353  {
354  KfMatrix *CP = mVtxKfNode->GetCP();
355 
356  CP->Reset();
357  // NB: this constraint comes in sync with the generator setting in simulation.C;
358  CP->KFM(0,0) = SQR(mEicBoxGenerator->GetVxSmearing());
359  CP->KFM(1,1) = SQR(mEicBoxGenerator->GetVySmearing());
360 
361  // Just [2..3] components (slopes) here;
362  for(int ip=_SX_; ip<=_SY_; ip++)
364 
365  // Momentum component;
366  if (sdim == 5)
368  }
369 } // FwdTrackFinder::ResetVtxNode()
370 
372 {
374  // FIXME: find a better way to figure this out?;
375  unsigned sdim = kf->GetFieldMode() == NoField ? 4 : 5;
376 
377  {
378  // KFV() and KFM() encapsulated operations are used -> just get pointers and use them;
379  KfVector *x0 = mVtxKfNode->GetX0();
380 
381  // NB: also use generated info here (see simulation.C); indeed this stuff should
382  // be consistent (use both coordinates and cov.matrix estimate for XY-vertex);
383  x0->KFV(0) = mEicBoxGenerator->GetVx();
384  x0->KFV(1) = mEicBoxGenerator->GetVy();
385 
386  // Otherwise a normal Kalman filter iterative update for slopes;
387  for(int ip=_SX_; ip<=_SY_; ip++)
388  x0->KFV(ip) += mVtxKfNode->GetXs()->KFV(ip);
389  }
390 
391  // Momentum expansion point; NB: head->x0[_QP_] will remain 0. in all cases!;
392  if (sdim == 5) mVtxKfNode->UpdateInversedMomentum(mVtxKfNode->GetXs()->KFV(_QP_));
393 
394  // Yes, predicted state vector at start of chain is set to 0.0;
395  {
396  KfVector *xp = mVtxKfNode->GetXp();
397 
398  for(int ip=_X_; ip<sdim; ip++)
399  xp->KFV(ip) = 0.;
400  }
401 
402  // Cook dummy (diagonal) covariance matrix;
403  {
404  KfMatrix *CP = mVtxKfNode->GetCP(), *CS = mVtxKfNode->GetCS();
405 
406  CP->Reset();
407  // NB: this constraint will be here for the final pass as well;
408  CP->KFM(0,0) = SQR(mEicBoxGenerator->GetVxSmearing());
409  CP->KFM(1,1) = SQR(mEicBoxGenerator->GetVySmearing());
410 
411  // Here assume, that CS[][] at the head node was estimated good enough
412  // in the last smoother pass -> use it as a reference and just blow up;
413  for(int ip=_SX_; ip<=(sdim == 4 ? _SY_ : _QP_); ip++)
414  CP->KFM(ip,ip) = CS->KFM(ip,ip)*_COVARIANCE_FINAL_BLOWUP_CFF_;
415  }
416 } // FwdTrackFinder::UpdateVtxNode()
417 
418 // ---------------------------------------------------------------------------------------
419 
420 void FwdTrackFinder::Exec(Option_t* opt)
421 {
422  {
423  static unsigned evCounter;
424  printf("\n\n FwdTrackFinder::Exec() ... Ev#%03d\n", evCounter++);
425  }
426  //EicHtcTask::Exec(opt);
427  //return;
428 
429  mTracks->Clear();
430 
431  // Reset internal node-group-related hit counters;
432  for(unsigned gr=0; gr<mFwdHoughTree->GetGroupCount(); gr++)
434 
435  // Populate node group hit arrays ("members");
436  for(unsigned gr=0; gr<mIdealTrCode->fGroups.size(); gr++) {
437  EicDetectorGroup *dgroup = &mIdealTrCode->fGroups[gr];
438 
439  if (!dgroup->_fHits) continue;
440  unsigned hnum = dgroup->_fHits->GetEntriesFast();
441 
442  for(unsigned ih=0; ih<hnum; ih++) {
443  EicTrackingDigiHit *hit = (EicTrackingDigiHit*)dgroup->_fHits->At(ih);
444  //assert(hit);
445 
446  // Part of the sensitive volumes may be of no interest -> just skip;
447  SensitiveVolume *sv = dgroup->GetSensitiveVolume(hit);
448  if (!sv) continue;
449 
450  FwdHoughNodeGroup *ngroup = sv->GetNodeGroup(hit->GetKfNodeID());
451 
452  KalmanNodeWrapper *kfwrapper = sv->GetKfNodeWrapper(hit->GetKfNodeID());
453  t_hough_range from = ngroup->PackFrom(hit, mRelativeHitSmearing, mAbsoluteSpatialSmearing, kfwrapper);
454  t_hough_range to = ngroup->PackTo (hit, mRelativeHitSmearing, mAbsoluteSpatialSmearing, kfwrapper);
455 
456  // THINK: return code here (indicate some error)?;
457  assert(!ngroup->AddMember(std::pair<void *, void *>(dgroup, hit), from, to));
458  } //for ih
459  } //for gr
460 
461  //return;
462  // Launch track finder;
464 
465  //return;
466  // Fill out output track arrays;
467  for(unsigned tc=0; tc<mFwdHoughTree->GetLinearMatchCandidateCount(); tc++) {
468  FwdMatchCandidate *match =
470 
471  // Yes, I need only the good ones;
472  if (!match->IsActive()) continue;
473 
474  // FIXME: this copying is not exactly efficient; at some point may want
475  // to unify HoughTree->mMatchCandidates and FwdTrackFinder->mTracks; the
476  // issue however is the 'new []' calls in MatchCandidate constructor which
477  // I do not want to do every time new;
478  new ((*mTracks)[mTracks->GetEntriesFast()]) FwdMatchCandidate(*match);
479  } //for tc
480 } // FwdTrackFinder::Exec()
481 
482 // ---------------------------------------------------------------------------------------
483 
485 {
486  FairRun *fRun = FairRun::Instance();
487 
488  // I hope there is no need to save/restore current directory here?;
489  fRun->GetOutputFile()->cd();
490  ccdf->Write();
491 
493 } // FwdTrackFinder::FinishTask()
494 
495 // ---------------------------------------------------------------------------------------
496