FairRoot
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FairGeanePro.cxx
Go to the documentation of this file.
1 /********************************************************************************
2  * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
3  * *
4  * This software is distributed under the terms of the *
5  * GNU Lesser General Public Licence (LGPL) version 3, *
6  * copied verbatim in the file "LICENSE" *
7  ********************************************************************************/
8 // Class for the interface to propagate track parameters with GEANE
9 //
10 // Authors: M. Al-Turany, A. Fontana, L. Lavezzi and A. Rotondi
11 //
12 #include "FairGeanePro.h"
13 
14 #include "FairGeaneApplication.h" // for FairGeaneApplication
15 #include "FairGeaneUtil.h" // for FairGeaneUtil
16 #include "FairLogger.h"
17 #include "FairTrackPar.h" // for FairTrackPar
18 #include "FairTrackParH.h" // for FairTrackParH
19 #include "FairTrackParP.h" // for FairTrackParP
20 
21 #include <TDatabasePDG.h> // for TDatabasePDG
22 #include <TGeoTorus.h> // for TGeoTorus
23 #include <TMath.h> // for pow, ACos, Cos, sqrt
24 #include <TMathBase.h> // for Abs
25 #include <TVector3.h> // for TVector3, operator-, etc
26 #include <TVirtualMC.h> // for gMC
27 #include <cmath> // IWYU pragma: keep for fabs
28 #include <iostream> // for operator<<, basic_ostream, etc
29 // IWYU pragma: no_include <architecture/i386/math.h>
30 
31 // ----- Default constructor -------------------------------------------
33  : FairPropagator("Geane", "Propagate Tracks")
34  , gMC3(static_cast<TGeant3*>(TVirtualMC::GetMC()))
35  , fPropOption("")
36  , nepred(1)
37  , fdbPDG(TDatabasePDG::Instance())
38  , afErtrio(nullptr)
39  , GeantCode(0)
40  , ProMode(0)
41  , VName("")
42  , VCopyNo(0)
43  , VEnter(kTRUE)
44  , fpoint(TVector3(0., 0., 0.))
45  , fwire1(TVector3(0., 0., 0.))
46  , fwire2(TVector3(0., 0., 0.))
47  , fPCA(0)
48  , fRad(0.)
49  , fDi(0.)
50  , fvpf(TVector3(0., 0., 0.))
51  , fvwi(TVector3(0., 0., 0.))
52  , ftrklength(0.)
53  , ftrktime(0.)
54  , flag(0)
55  , fApp(FairGeaneApplication::Instance())
56  , fPrintErrors(kTRUE)
57 {
58  if (gMC3 == NULL) {
59  LOG(fatal) << "FairGeanePro::TGeant3 has not been initialized! ABORTING!";
60  throw;
61  }
62  afErtrio = gMC3->fErtrio;
63 
64  // nepred=1;
65  xlf[0] = 0.;
66  // fdbPDG= TDatabasePDG::Instance();
67  // fErrorMat= new TArrayD(15);
68  // afErtrio=gMC3->fErtrio;
69  // Pos=TVector3(0, 0 , 0);
70  // PosErr = TVector3(0,0,0);
71  // Mom=TVector3(0,0,0);
72  // fTrkPar= new FairTrackPar();
73  // ProMode=0;
74  // FairRunAna *fRun= FairRunAna::Instance();
75  // fField= fRun->GetField();
76 
77  // PCA stuff
78  // fPCA = 0;
79  /*
80  fpoint = TVector3(0., 0., 0.);
81  fwire1 = TVector3(0., 0., 0.);
82  fwire2 = TVector3(0., 0., 0.);
83  */
84 
85  for (int i = 0; i < 5; i++)
86  for (int j = 0; j < 5; j++) {
87  trpmat[i][j] = 0.;
88  }
89 
90  // fApp = FairGeaneApplication::Instance();
91 
92  // fPropOption = "";
93  for (int i = 0; i < 15; i++) {
94  ein[i] = 0.;
95  if (i < 3) {
96  x2[i] = 0;
97  p2[i] = 0;
98  x1[i] = 0;
99  p1[i] = 0;
100  }
101  }
102 
103  pli[0] = 1.;
104  pli[1] = 0.;
105  pli[2] = 0.;
106  pli[3] = 0.;
107  pli[4] = 1.;
108  pli[5] = 0.;
109 
110  plo[0] = 0.;
111  plo[1] = 0.;
112  plo[2] = 0.;
113  plo[3] = 1.;
114  plo[4] = 0.;
115  plo[5] = 0.;
116  plo[6] = 0.;
117  plo[7] = 1.;
118  plo[8] = 0.;
119  plo[9] = 0.;
120  plo[10] = 0.;
121  plo[11] = 1.;
122 
123  // GeantCode = 0;
124  /*
125  VName = "";
126  VCopyNo = 0;
127  VEnter = kTRUE;
128  */
129 }
130 
132 
134 {
135  // Propagate a helix track and return a helix (SC system)
136 
137  // bool NeedSDSC=kFALSE;
138  int ch = 1; // CHARGE OF PARTICLE
139 
140  double fCov[15], fCovOut[15];
141  TParam->GetCovQ(fCov);
142 
143  Init(TParam);
144  double Q = TParam->GetQ();
145  if (fabs(Q) > 1.E-8) {
146  ch = int(Q / TMath::Abs(Q));
147  }
148  if (ProMode == 1) { // Propagate to Volume
149  //***** We have the right representation go further
150  for (int i = 0; i < 15; i++) {
151  ein[i] = fCov[i];
152  }
153  if (fPropOption.Contains("V")) {
154  // LOG(debug) << "Propagate Helix to Volume";
155  int option;
156  if (VEnter) {
157  option = 1;
158  } else {
159  option = 2;
160  }
161  gMC3->Eufilv(1, ein, const_cast<char*>(VName.Data()), &VCopyNo, &option);
162  } else if (fPropOption.Contains("L")) {
163  if (fPCA == 0) {
164  gMC3->Eufill(nepred, ein, xlf);
165  } else if (fPCA != 0) {
166 
167  // max length estimate:
168  // we calculate the geometrical distance of the start point
169  // from the point/wire extremity and multiply it * 2
170  TVector3 start = TVector3(TParam->GetX(), TParam->GetY(), TParam->GetZ());
171  double maxdistance = 0;
172  if (fPCA == 1) {
173  maxdistance = (fpoint - start).Mag();
174  } else if (fPCA == 2) {
175  double distance1, distance2;
176  distance1 = (fwire1 - start).Mag();
177  distance2 = (fwire2 - start).Mag();
178  if (distance1 < distance2) {
179  maxdistance = distance2;
180  } else {
181  maxdistance = distance1;
182  }
183  }
184  maxdistance *= 2.;
185 
186  // output
187  PCAOutputStruct pcaoutput = FindPCA(fPCA, PDG, fpoint, fwire1, fwire2, maxdistance);
188  fRad = pcaoutput.Radius;
189  fvpf = pcaoutput.OnTrackPCA;
190  fvwi = pcaoutput.OnWirePCA;
191  fDi = pcaoutput.Distance;
192  ftrklength = pcaoutput.TrackLength;
193  int findpca = pcaoutput.PCAStatusFlag;
194  if (findpca != 0) {
195  return kFALSE;
196  }
197 
198  // reset parameters
199  Init(TParam);
200  gMC3->Eufill(nepred, ein, &ftrklength);
201  }
202  }
203  } else if (ProMode == 3) {
204  LOG(warning) << "Propagate Helix parameter to Plane is not implimented yet";
205  return kFALSE;
206  }
207  // Propagate
208  if (Propagate(PDG) == kFALSE) {
209  return kFALSE;
210  }
211 
212  for (int i = 0; i < 15; i++) {
213  fCovOut[i] = afErtrio->errout[i];
214  if (i == 0) {
215  fCovOut[i] = fCovOut[i] * ch * ch;
216  }
217  if (i > 0 && i < 5) {
218  fCovOut[i] = fCovOut[i] * ch;
219  }
220  }
221 
222  // do not remove (useful for debug)
223  if (fabs(p2[0]) < 1e-9 && fabs(p2[1]) < 1e-9 && fabs(p2[2]) < 1e-9) {
224  return kFALSE;
225  }
226  TEnd->SetTrackPar(x2[0], x2[1], x2[2], p2[0], p2[1], p2[2], ch, fCovOut);
227  return kTRUE;
228 }
229 
230 bool FairGeanePro::Propagate(FairTrackParP* /*TStart*/, FairTrackParH* /*TEnd*/, int /*PDG*/)
231 {
232  // Propagate a parabola track (SD system) and return a helix (SC system) (not used nor implemented)
233  LOG(warning)
234  << "FairGeanePro::Propagate(FairTrackParP *TParam, FairTrackParH &TEnd, int PDG) : (not used nor implemented)";
235  return kFALSE;
236 }
237 
239 {
240  // Propagate a parabola track (SD system) and return a parabola (SD system) (not used nor implemented)
241  int ch = 1; // CHARGE OF PARTICLE
242  double fCov[15], fCovOut[15];
243  TStart->GetCovQ(fCov);
244 
245  Init(TStart);
246  double Q = TStart->GetQ();
247  if (Q != 0) {
248  ch = int(Q / TMath::Abs(Q));
249  }
250 
251  if (ProMode == 1) { // Propagate to Volume
252  LOG(warning) << "Propagate Parabola parameter to Volume is not implimented yet";
253  return kFALSE;
254  } else if (ProMode == 3) {
256  for (int i = 0; i < 15; i++) {
257  ein[i] = fCov[i];
258  }
259 
260  if (fPropOption.Contains("P")) {
261  gMC3->Eufilp(nepred, ein, pli, plo);
262  } else if (fPropOption.Contains("L")) {
263  if (fPCA == 0) {
264  LOG(warning) << "Propagate Parabola to Parabola in Length not yet implemented";
265  } else if (fPCA != 0) {
266 
267  // max length estimate:
268  // we calculate the geometrical distance of the start point
269  // from the point/wire extremity and multiply it * 2
270  TVector3 start = TVector3(TStart->GetX(), TStart->GetY(), TStart->GetZ());
271  double maxdistance = 0;
272  if (fPCA == 1) {
273  maxdistance = (fpoint - start).Mag();
274  } else if (fPCA == 2) {
275  double distance1, distance2;
276  distance1 = (fwire1 - start).Mag();
277  distance2 = (fwire2 - start).Mag();
278  if (distance1 < distance2) {
279  maxdistance = distance2;
280  } else {
281  maxdistance = distance1;
282  }
283  }
284  maxdistance *= 2.;
285 
286  // output
287  PCAOutputStruct pcaoutput = FindPCA(fPCA, PDG, fpoint, fwire1, fwire2, maxdistance);
288  fRad = pcaoutput.Radius;
289  fvpf = pcaoutput.OnTrackPCA;
290  fvwi = pcaoutput.OnWirePCA;
291  fDi = pcaoutput.Distance;
292  ftrklength = pcaoutput.TrackLength;
293  int findpca = pcaoutput.PCAStatusFlag;
294  // LOG(info)<<" FairGeanePro::ftrklength="<<ftrklength;
295  if (findpca != 0) {
296  return kFALSE;
297  }
298 
299  // reset parameters
300  Init(TStart);
301 
302  // find plane
303  // unitary vector along distance
304  // fvpf on track, fvwi on wire
305  TVector3 fromwiretoextr = fvpf - fvwi;
306  fromwiretoextr.SetMag(1.);
307  if (fabs(fromwiretoextr.Mag() - 1) > 1E-4) {
308  LOG(fatal) << "fromwire.Mag()!=1";
309  return kFALSE;
310  }
311 
312  // for wires:
313  // unitary vector along the wire
314  TVector3 wiredirection = fwire2 - fwire1;
315  if (fPCA == 1) { // point
316  TVector3 mom(TStart->GetPx(), TStart->GetPy(), TStart->GetPz());
317  wiredirection = mom.Cross(fromwiretoextr);
318  }
319  wiredirection.SetMag(1.);
320  // check orthogonality
321  if (fabs(fromwiretoextr * wiredirection) > 1e-3) {
322  return kFALSE; // throw away the event
323  // wiredirection = (fromwiretoextr.Cross(wiredirection)).Cross(fromwiretoextr);
324  // wiredirection.SetMag(1.);
325  }
326 
327  TVector3 jver = TStart->GetJVer();
328  ;
329  TVector3 kver = TStart->GetKVer();
330  bool backtracking = kFALSE;
331  if (fPropOption.Contains("B")) {
332  backtracking = kTRUE;
333  }
334  SetOriginPlane(jver, kver);
335  SetDestinationPlane(fvwi, fromwiretoextr, wiredirection);
336  if (backtracking == kTRUE) {
337  fPropOption = "BPE";
338  }
339 
340  gMC3->Eufilp(nepred, ein, pli, plo);
341  }
342  }
343  }
344  // Propagate
345  if (Propagate(PDG) == kFALSE) {
346  return kFALSE;
347  }
348 
349  for (int i = 0; i < 15; i++) {
350  fCovOut[i] = afErtrio->errout[i];
351  if (i == 0) {
352  fCovOut[i] = fCovOut[i] * ch * ch;
353  }
354  if (i > 0 && i < 5) {
355  fCovOut[i] = fCovOut[i] * ch;
356  }
357  }
358 
359  // plane
360  TVector3 origin(plo[6], plo[7], plo[8]);
361  TVector3 dj(plo[0], plo[1], plo[2]);
362  TVector3 dk(plo[3], plo[4], plo[5]);
363  TVector3 di(plo[9], plo[10], plo[11]); // = dj.Cross(dk);
364 
365  if (fabs(p2[0]) < 1e-9 && fabs(p2[1]) < 1e-9 && fabs(p2[2]) < 1e-9) {
366  return kFALSE;
367  }
368 
369  TEnd->SetTrackPar(x2[0], x2[1], x2[2], p2[0], p2[1], p2[2], ch, fCovOut, origin, di, dj, dk);
370 
371  return kTRUE;
372 }
373 
374 bool FairGeanePro::Propagate(FairTrackParH* /*TStart*/, FairTrackParP* /*TEnd*/, int /*PDG*/)
375 {
376  // Propagate a helix track (SC system) and return a parabola (SD system) (not used nor implemented)
377  LOG(warning) << "FairGeanePro::Propagate(FairTrackParH *TParam, FairTrackParP &TEnd, int PDG) not implemented";
378  return kFALSE;
379 }
380 
381 bool FairGeanePro::Propagate(float* X1, float* P1, float* X2, float* P2, int PDG)
382 {
383  // fApp->GeanePreTrack(X1, P1, PDG);
384  GeantCode = fdbPDG->ConvertPdgToGeant3(PDG);
385  xlf[0] = 1000;
386  gMC3->Eufill(1, ein, xlf);
387  gMC3->Ertrak(X1, P1, X2, P2, GeantCode, "L");
388  if (X2[0] < -1.E29) {
389  return kFALSE;
390  }
391  if (gMC3->IsTrackOut()) {
392  return kFALSE;
393  }
394  return kTRUE;
395 }
396 
398 {
399  // main propagate call to fortran ERTRAK
400 
401  GeantCode = fdbPDG->ConvertPdgToGeant3(PDG);
402  // LOG(info) << " FairGeanePro::Propagate ---------------------------"<< " " << x1[0]<< " "<< x1[1]<< " "<<
403  // x1[2]; fApp->GeanePreTrack(x1, p1, PDG);
404  gMC3->Ertrak(x1, p1, x2, p2, GeantCode, fPropOption.Data());
405  if (x2[0] < -1.E29) {
406  return kFALSE;
407  }
408  if (gMC3->IsTrackOut()) {
409  return kFALSE;
410  }
411 
412  ftrklength = gMC3->TrackLength();
413 
414  ftrktime = gMC3->TrackTime();
415 
416  double trasp[25];
417  for (int i = 0; i < 25; i++) {
418  // trasp[i] = afErtrio->ertrsp[i]; // single precision tr. mat.
419  trasp[i] = afErtrio->erdtrp[i]; // double precision tr. mat.
420  }
421  FairGeaneUtil fUtil;
422  fUtil.FromVecToMat(trpmat, trasp);
423  return kTRUE;
424 }
425 
427 {
428  // starting and ending point initialization
429  x1[0] = TParam->GetX();
430  x1[1] = TParam->GetY();
431  x1[2] = TParam->GetZ();
432  p1[0] = TParam->GetPx();
433  p1[1] = TParam->GetPy();
434  p1[2] = TParam->GetPz();
435 
436  x2[0] = 0;
437  x2[1] = 0;
438  x2[2] = 0;
439  p2[0] = 0;
440  p2[1] = 0;
441  p2[2] = 0;
442 }
443 
444 bool FairGeanePro::SetOriginPlane(const TVector3& v1, const TVector3& v2)
445 {
446  // define initial plane (option "P")
447  TVector3 v1u = v1.Unit();
448  TVector3 v2u = v2.Unit();
449  pli[0] = v1u.X();
450  pli[1] = v1u.Y();
451  pli[2] = v1u.Z();
452  pli[3] = v2u.X();
453  pli[4] = v2u.Y();
454  pli[5] = v2u.Z();
455  return kTRUE;
456 }
457 
458 bool FairGeanePro::SetDestinationPlane(const TVector3& v0, const TVector3& v1, const TVector3& v2)
459 {
460  // define final plane (option "P")
461  // uncomment to set the initial error to zero
462  // for(int i=0;i<15;i++) ein[i]=0.00;
463  TVector3 v1u = v1.Unit();
464  TVector3 v2u = v2.Unit();
465 
466  plo[0] = v1u.X();
467  plo[1] = v1u.Y();
468  plo[2] = v1u.Z();
469  plo[3] = v2u.X();
470  plo[4] = v2u.Y();
471  plo[5] = v2u.Z();
472 
473  plo[6] = v0.X();
474  plo[7] = v0.Y();
475  plo[8] = v0.Z();
476 
477  TVector3 v3 = v1u.Cross(v2u);
478 
479  plo[9] = v3(0);
480  plo[10] = v3(1);
481  plo[11] = v3(2);
482 
483  fPropOption = "PE";
484  ProMode = 3; // need errors in representation 3 (SD)(see Geane doc)
485  // gMC3->Eufilp(nepred, ein, pli, plo);
486  return kTRUE;
487 }
488 
489 bool FairGeanePro::SetDestinationVolume(std::string VolName, int CopyNo, int option)
490 {
491  // define final volume (option "V")
492  for (int i = 0; i < 15; i++) {
493  ein[i] = 0.00;
494  }
495  VName = VolName;
496  VCopyNo = CopyNo;
497  if (option == 1) {
498  VEnter = kTRUE;
499  } else {
500  VEnter = kFALSE;
501  }
502  fPropOption = "VE";
503  ProMode = 1; // need errors in representation 1 (SC) (see Geane doc)
504  return kTRUE;
505 }
506 
508 {
509  // define final length (option "L")
510  if (length < 0) {
511  xlf[0] = -length;
512  fPropOption = "BLE";
513  } else {
514  xlf[0] = length;
515  fPropOption = "LE";
516  }
517  ProMode = 1; // need errors in representation 1 (SC)(see Geane doc)
518  return kTRUE;
519 }
520 
522 {
523  int index = fPropOption.Index("E");
524  if (index == -1) {
525  fPropOption.Append("O");
526  } else {
527  fPropOption.Replace(index, 1, "O");
528  }
529  return kTRUE;
530 }
531 
532 bool FairGeanePro::PropagateFromPlane(const TVector3& v1, const TVector3& v2)
533 {
534  return SetOriginPlane(v1, v2);
535 }
536 
537 bool FairGeanePro::PropagateToPlane(const TVector3& v0, const TVector3& v1, const TVector3& v2)
538 {
539  return SetDestinationPlane(v0, v1, v2);
540 }
541 
542 bool FairGeanePro::PropagateToVolume(TString VolName, int CopyNo, int option)
543 {
544  return SetDestinationVolume(VolName.Data(), CopyNo, option);
545 }
546 
547 bool FairGeanePro::PropagateToLength(float length)
548 {
549  return SetDestinationLength(length);
550 }
551 
552 bool FairGeanePro::PropagateOnlyParameters()
553 {
555 }
556 
557 bool FairGeanePro::SetWire(TVector3 extremity1, TVector3 extremity2)
558 {
559  fwire1 = extremity1;
560  fwire2 = extremity2;
561  return true;
562 }
563 
564 bool FairGeanePro::SetPoint(TVector3 pnt)
565 {
566  fpoint = pnt;
567  return true;
568 }
569 
571 {
572  if (par) {
573  Init(par);
574  for (int i = 0; i < 15; i++) {
575  ein[i] = 0.00;
576  }
577  }
578  // through track length
579  if (dir > 0) {
580  fPropOption = "LE";
581  } else if (dir < 0) {
582  fPropOption = "BLE";
583  } else {
584  LOG(warning) << "FairGeanePro::SetPCAPropagation ERROR: no direction set";
585  }
586  ProMode = 1; // need errors in representation 1 (SC)(see Geane doc)
587  fPCA = pca;
588  // initialization
589  fRad = 0.;
590  fDi = 0.;
591  fvpf = TVector3(0., 0., 0.);
592  fvwi = TVector3(0., 0., 0.);
593  ftrklength = 0;
594  ftrktime = 0;
595  return kTRUE;
596 }
597 
598 bool FairGeanePro::PropagateToPCA(int pca)
599 {
600  return SetPCAPropagation(pca);
601 }
602 
603 bool FairGeanePro::PropagateToPCA(int pca, int dir)
604 {
605  return SetPCAPropagation(pca, dir);
606 }
607 
608 bool FairGeanePro::ActualFindPCA(int pca, FairTrackParP* par, int dir)
609 {
610  return SetPCAPropagation(pca, dir, par);
611 }
612 
613 bool FairGeanePro::BackTrackToVertex()
614 {
615  // through track length
616  fPropOption = "BLE";
617  ProMode = 1; // need errors in representation 1 (SC)(see Geane doc)
618  fPCA = 1; // to point
619  // initialization (forse non necessario) CHECK!!!!
620  fRad = 0.;
621  fDi = 0.;
622  fvpf = TVector3(0., 0., 0.);
623  fvwi = TVector3(0., 0., 0.);
624  ftrklength = 0;
625  ftrktime = 0;
626  return kTRUE;
627 }
628 
629 bool FairGeanePro::PropagateToVirtualPlaneAtPCA(int pca)
630 {
631  // through track length
632  fPropOption = "LE";
633  ProMode = 3; // need errors in representation 3 (SD)(see Geane doc)
634  fPCA = pca;
635  // initialization
636  fRad = 0.;
637  fDi = 0.;
638  fvpf = TVector3(0., 0., 0.);
639  fvwi = TVector3(0., 0., 0.);
640  ftrklength = 0;
641  ftrktime = 0;
642  return kTRUE;
643 }
644 
645 bool FairGeanePro::BackTrackToVirtualPlaneAtPCA(int pca)
646 {
647  // through track length
648  fPropOption = "BLE";
649  ProMode = 3; // need errors in representation 3 (SD)(see Geane doc)
650  fPCA = pca;
651  // initialization
652  fRad = 0.;
653  fDi = 0.;
654  fvpf = TVector3(0., 0., 0.);
655  fvwi = TVector3(0., 0., 0.);
656  ftrklength = 0;
657  ftrktime = 0;
658  return kTRUE;
659 }
660 
661 //=====================
662 
664  int PDGCode,
665  TVector3 point,
666  TVector3 wire1,
667  TVector3 wire2,
668  double maxdistance,
669  double& Rad,
670  TVector3& vpf,
671  TVector3& vwi,
672  double& Di,
673  float& trklength)
674 {
675  PCAOutputStruct pcaoutput = FindPCA(pca, PDGCode, point, wire1, wire2, maxdistance);
676  Rad = pcaoutput.Radius;
677  vpf = pcaoutput.OnTrackPCA;
678  vwi = pcaoutput.OnWirePCA;
679  Di = pcaoutput.Distance;
680  trklength = pcaoutput.TrackLength;
681  return pcaoutput.PCAStatusFlag;
682 }
683 
685  int PDGCode,
686  TVector3 Point,
687  TVector3 Wire1,
688  TVector3 Wire2,
689  double MaxDistance)
690 {
691  // find the point of closest approach of the track to a point(measured position) or to a line(wire)
692 
693  // INPUT ----------------------------------------
694  // .. pca = ic = 1 closest approach to point
695  // = 2 closest approach to wire
696  // = 0 no closest approach
697  // .. PDGCode = pdg code of the particle
698  // .. point point with respect to which calculate the closest approach
699  // .. wire, wire2 line with respect to which calculate the closest approach
700  // .. maxdistance = geometrical distance[start - point/wire extr] * 2
701  // OUTPUT STRUCT ----------------------------------------
702  // .. PCAStatusFlag 0 by success, else otherwise
703  // .. Radius : radius if the found circle
704  // .. OnTrackPCA : point of closest approach on track
705  // .. OnWirePCA : point of closest approach on wire
706  // .. Distance : distance between track and wire in the PCA
707  // .. TrackLength : track length to add to the GEANE one
708 
709  PCAOutputStruct pcastruct = PCAOutputStruct();
710 
711  float pf[3] = {static_cast<float>(Point.X()), static_cast<float>(Point.Y()), static_cast<float>(Point.Z())};
712  float w1[3] = {static_cast<float>(Wire1.X()), static_cast<float>(Wire1.Y()), static_cast<float>(Wire1.Z())};
713  float w2[3] = {static_cast<float>(Wire2.X()), static_cast<float>(Wire2.Y()), static_cast<float>(Wire2.Z())};
714 
715  GeantCode = fdbPDG->ConvertPdgToGeant3(PDGCode);
716 
717  // flags Rotondi's function
718  int flg = 0;
719 
720  // cl track length to the three last points of closest approach
721  // dst assigned distance between initial point in ERTRAK and PFINAL along straight line (currently noy used)
722  float cl[3], dst;
723 
724  // GEANE filled points
725  float po1[3], po2[3], po3[3];
726 
727  // cl track length to the three last points of closest approach
728  float clen[3];
729 
730  // track length to add to GEANE computed one
731  double Le = 0.0;
732  double dist1, dist2;
733 
734  // initialization of some variables
735  dst = 999.;
736  cl[0] = 0;
737  cl[1] = 0;
738  cl[2] = 0;
739 
740  // GEANE filled points
741  po1[0] = 0;
742  po1[1] = 0;
743  po1[2] = 0;
744  po2[0] = 0;
745  po2[1] = 0;
746  po2[2] = 0;
747  po3[0] = 0;
748  po3[1] = 0;
749  po3[2] = 0;
750 
751  gMC3->SetClose(PCA, pf, dst, w1, w2, po1, po2, po3, cl);
752 
753  // maximum distance calculated 2 * geometric distance
754  // start point - end point (the point to which we want
755  // to find the PCA)
756  float stdlength[1] = {static_cast<float>(MaxDistance)};
757 
758  gMC3->Eufill(1, ein, stdlength);
759 
760  // check needed for low momentum tracks
761  gMC3->Ertrak(x1, p1, x2, p2, GeantCode, fPropOption.Data());
762  if (x2[0] < -1.E29) {
763  return pcastruct;
764  }
765  if (gMC3->IsTrackOut()) {
766  return pcastruct;
767  }
768  gMC3->GetClose(po1, po2, po3, clen);
769 
770  // check on cases when only two steps are performed!
771  // in these cases po1[i] = 0 ==> let' s copy po2 into
772  // po1 in order to use only the two actually extrapolated
773  // points po2 and po3 to complete the PCA calculation
774  if (clen[0] == 0 && clen[1] == 0) {
775  po1[0] = po2[0];
776  po1[1] = po2[1];
777  po1[2] = po2[2];
778  }
779 
780  if (PCA == 1) {
781  if ((po1[0] == po2[0] && po1[1] == po2[1] && po1[2] == po2[2])
782  || (po2[0] == po3[0] && po2[1] == po3[1] && po2[2] == po3[2])) {
783  int quitFlag = 0;
784  Track2ToPoint(
785  TVector3(po1), TVector3(po3), TVector3(pf), pcastruct.OnTrackPCA, pcastruct.Distance, Le, quitFlag);
786  if (quitFlag != 0) {
787  if (fPrintErrors) {
788  LOG(warning) << "FairGeanePro:FindPCA: Track2ToPoint quitFlag " << quitFlag << " ABORT";
789  }
790  return pcastruct;
791  } // abort
792  } else {
793  Track3ToPoint(TVector3(po1),
794  TVector3(po2),
795  TVector3(po3),
796  TVector3(pf),
797  pcastruct.OnTrackPCA,
798  flg,
799  pcastruct.Distance,
800  Le,
801  pcastruct.Radius);
802  if (flg == 1) {
803  int quitFlag = 0;
804  Track2ToPoint(
805  TVector3(po1), TVector3(po3), TVector3(pf), pcastruct.OnTrackPCA, pcastruct.Distance, Le, quitFlag);
806  if (quitFlag != 0) {
807  if (fPrintErrors) {
808  LOG(warning) << "FairGeanePro:FindPCA: Track2ToPoint quitFlag " << quitFlag << " ABORT";
809  }
810  return pcastruct;
811  } // abort
812  } else if (flg == 2) {
813  if (fPrintErrors) {
814  LOG(warning) << "FairGeanePro:FindPCA: Track3ToPoint flg " << flg << " ABORT";
815  }
816  return pcastruct;
817  } // abort
818  }
819  // if the propagation to closest approach to a POINT is performed
820  // vwi is the point itself (with respect to which the PCA is calculated)
821  pcastruct.OnWirePCA = Point;
822  } else if (PCA == 2) {
823  if ((po1[0] == po2[0] && po1[1] == po2[1] && po1[2] == po2[2])
824  || (po2[0] == po3[0] && po2[1] == po3[1] && po2[2] == po3[2])) {
825  Track2ToLine(TVector3(po1),
826  TVector3(po3),
827  TVector3(w1),
828  TVector3(w2),
829  pcastruct.OnTrackPCA,
830  pcastruct.OnWirePCA,
831  flg,
832  pcastruct.Distance,
833  Le);
834  if (flg == 1) {
835  dist1 = (pcastruct.OnWirePCA - TVector3(w1)).Mag();
836  dist2 = (pcastruct.OnWirePCA - TVector3(w2)).Mag();
837  int quitFlag = 0;
838  dist1 < dist2 ? Track2ToPoint(
839  TVector3(po1), TVector3(po3), TVector3(w1), pcastruct.OnTrackPCA, pcastruct.Distance, Le, quitFlag)
840  : Track2ToPoint(TVector3(po1),
841  TVector3(po3),
842  TVector3(w2),
843  pcastruct.OnTrackPCA,
844  pcastruct.Distance,
845  Le,
846  quitFlag);
847  if (quitFlag != 0) {
848  if (fPrintErrors) {
849  LOG(warning) << "FairGeanePro:FindPCA: Track2ToPoint quitFlag " << quitFlag << " ABORT";
850  }
851  return pcastruct;
852  } // abort
853  } else if (flg == 2) {
854  if (fPrintErrors) {
855  LOG(warning) << "FairGeanePro:FindPCA: Track2ToLine flg " << flg << " ABORT";
856  }
857  return pcastruct;
858  }
859  } else {
860  Track3ToLine(TVector3(po1),
861  TVector3(po2),
862  TVector3(po3),
863  TVector3(w1),
864  TVector3(w2),
865  pcastruct.OnTrackPCA,
866  pcastruct.OnWirePCA,
867  flg,
868  pcastruct.Distance,
869  Le,
870  pcastruct.Radius);
871  if (flg == 1) {
872  Track2ToLine(TVector3(po1),
873  TVector3(po3),
874  TVector3(w1),
875  TVector3(w2),
876  pcastruct.OnTrackPCA,
877  pcastruct.OnWirePCA,
878  flg,
879  pcastruct.Distance,
880  Le);
881  if (flg == 1) {
882  dist1 = (pcastruct.OnWirePCA - TVector3(w1)).Mag();
883  dist2 = (pcastruct.OnWirePCA - TVector3(w2)).Mag();
884  int quitFlag = 0;
885  dist1 < dist2 ? Track2ToPoint(TVector3(po1),
886  TVector3(po3),
887  TVector3(w1),
888  pcastruct.OnTrackPCA,
889  pcastruct.Distance,
890  Le,
891  quitFlag)
892  : Track2ToPoint(TVector3(po1),
893  TVector3(po3),
894  TVector3(w2),
895  pcastruct.OnTrackPCA,
896  pcastruct.Distance,
897  Le,
898  quitFlag);
899  if (quitFlag != 0) {
900  if (fPrintErrors) {
901  LOG(warning) << "FairGeanePro:FindPCA: Track2ToPoint quitFlag " << quitFlag << " ABORT";
902  }
903  return pcastruct;
904  } // abort
905  } else if (flg == 2) {
906  if (fPrintErrors) {
907  LOG(warning) << "FairGeanePro:FindPCA: Track2ToLine flg " << flg << " ABORT";
908  }
909  return pcastruct;
910  }
911  } else if (flg == 2) {
912  dist1 = (pcastruct.OnWirePCA - TVector3(w1)).Mag();
913  dist2 = (pcastruct.OnWirePCA - TVector3(w2)).Mag();
914 
915  dist1 < dist2 ? Track3ToPoint(TVector3(po1),
916  TVector3(po2),
917  TVector3(po3),
918  TVector3(w1),
919  pcastruct.OnTrackPCA,
920  flg,
921  pcastruct.Distance,
922  Le,
923  pcastruct.Radius)
924  : Track3ToPoint(TVector3(po1),
925  TVector3(po2),
926  TVector3(po3),
927  TVector3(w2),
928  pcastruct.OnTrackPCA,
929  flg,
930  pcastruct.Distance,
931  Le,
932  pcastruct.Radius);
933  if (flg == 2) {
934  if (fPrintErrors) {
935  LOG(warning) << "FairGeanePro:FindPCA: Track3ToLine flg " << flg << " ABORT";
936  }
937  return pcastruct;
938  } // abort
939  } else if (flg == 3) {
940  dist1 = (pcastruct.OnWirePCA - TVector3(w1)).Mag();
941  dist2 = (pcastruct.OnWirePCA - TVector3(w2)).Mag();
942  int quitFlag = 0;
943  dist1 < dist2 ? Track2ToPoint(
944  TVector3(po1), TVector3(po3), TVector3(w1), pcastruct.OnTrackPCA, pcastruct.Distance, Le, quitFlag)
945  : Track2ToPoint(TVector3(po1),
946  TVector3(po3),
947  TVector3(w2),
948  pcastruct.OnTrackPCA,
949  pcastruct.Distance,
950  Le,
951  quitFlag);
952  if (quitFlag != 0) {
953  if (fPrintErrors) {
954  LOG(warning) << "FairGeanePro:FindPCA: Track2ToPoint quitFlag " << quitFlag << " ABORT";
955  }
956  return pcastruct;
957  } // abort
958  } else if (flg == 4) {
959  Track2ToLine(TVector3(po1),
960  TVector3(po3),
961  TVector3(w1),
962  TVector3(w2),
963  pcastruct.OnTrackPCA,
964  pcastruct.OnWirePCA,
965  flg,
966  pcastruct.Distance,
967  Le);
968  if (flg == 2) {
969  if (fPrintErrors) {
970  LOG(warning) << "FairGeanePro:FindPCA: Track2ToLine flg " << flg << " ABORT";
971  }
972  return pcastruct;
973  }
974  }
975  }
976  }
977 
978  // calculated track length corresponding
979  // to the point of closest approach
980  pcastruct.TrackLength = clen[0] + Le;
981 
982  // PCA before starting point
983  if (pcastruct.TrackLength < 0) {
984  return pcastruct;
985  }
986  flag = flg;
987 
988  pcastruct.PCAStatusFlag = 0;
989  return pcastruct;
990 }
991 
992 void FairGeanePro::Track2ToLine(TVector3 X1,
993  TVector3 X2,
994  TVector3 w1,
995  TVector3 w2,
996  TVector3& Pfinal,
997  TVector3& Pwire,
998  int& Iflag,
999  double& Dist,
1000  double& Length)
1001 {
1002  // Closest approach to a line from 2 GEANE points
1003  //
1004  // METHOD: the nearest points on the two lines
1005  // x1,x2 and w1,w2 is found.
1006  // The method is described in:
1007  // http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
1008  // http://www.geometrictools.com/Documentation/DistanceLine3Line3.pdf.
1009  //
1010  // INPUT: x1, x2 closest appoach GEANE points
1011  // w1, w2 points of the line (wire) to approach
1012  //
1013  // OUTPUT: Pfinal point of closest approach on the track
1014  // Pwire point of closest approach on the wire
1015  // Dist distance between Pfian and w1
1016  // Length arc length to add to the GEANE length of x1
1017  // Iflag =1 when Pwire is outside [w1,w2]
1018  // In this case, when w1 and w2 are the extremes
1019  // of the wire, the user could remake the procedure
1020  // by calling Track3ToPoint or Track2ToPoint, where the
1021  // Point is w1 or w2;
1022  // = 2 when the two lines are parallel and the solution
1023  // does not exists.
1024  //
1025  // Authors: Andrea Fontana and Alberto Rotondi 20 MAy 2007
1026  //
1027 
1028  TVector3 x21, x32, w21;
1029  TVector3 xw1, xw2;
1030 
1031  double a1, b1, c1, d1, e1;
1032  double Delta1;
1033 
1034  double Eps = 1.E-08;
1035 
1036  Iflag = 0;
1037 
1038  // line-line distance
1039  x21 = X2 - X1;
1040  w21 = w2 - w1;
1041 
1042  xw1 = X1 - w1;
1043  xw2 = X2 - w1;
1044 
1045  a1 = x21.Mag2();
1046  b1 = x21.Dot(w21);
1047  c1 = w21.Mag2();
1048  d1 = xw1.Dot(x21);
1049  e1 = xw1.Dot(w21);
1050 
1051  Delta1 = a1 * c1 - b1 * b1;
1052 
1053  if (Delta1 > Eps) {
1054  double t1 = (a1 * e1 - b1 * d1) / Delta1;
1055  double s1 = (b1 * e1 - c1 * d1) / Delta1;
1056 
1057  Pfinal = (X1 + x21 * s1);
1058  Pwire = (w1 + w21 * t1);
1059  Length = s1 * x21.Mag();
1060  Dist = (Pfinal - Pwire).Mag();
1061 
1062  } else {
1063  // lines are paralllel, no solution does exist
1064  Pfinal.SetXYZ(0., 0., 0.);
1065  Pwire.SetXYZ(0., 0., 0.);
1066  Dist = 0.;
1067  Length = 0.;
1068  Iflag = 2;
1069  return;
1070  }
1071  // flag when the point on the wire is outside (w1,w2)
1072  if ((((Pwire[0] < w1[0] && Pwire[0] < w2[0]) || (w2[0] < Pwire[0] && w1[0] < Pwire[0]))
1073  && (fabs(Pwire[0] - w1[0]) > 1e-11 && fabs(Pwire[0] - w2[0]) > 1e-11))
1074  || (((Pwire[1] < w1[1] && Pwire[1] < w2[1]) || (w2[1] < Pwire[1] && w1[1] < Pwire[1]))
1075  && (fabs(Pwire[1] - w1[1]) > 1e-11 && fabs(Pwire[1] - w2[1]) > 1e-11))
1076  || (((Pwire[2] < w1[2] && Pwire[2] < w2[2]) || (w2[2] < Pwire[2] && w1[2] < Pwire[2]))
1077  && (fabs(Pwire[2] - w1[2]) > 1e-11 && fabs(Pwire[2] - w2[2]) > 1e-11))) {
1078  Iflag = 1;
1079  }
1080 }
1081 
1082 void FairGeanePro::Track2ToPoint(TVector3 X1,
1083  TVector3 X2,
1084  TVector3 w1,
1085  TVector3& Pfinal,
1086  double& Dist,
1087  double& Length,
1088  int& quitFlag)
1089 {
1090  //
1091  // Closest approach to a point from 2 GEANE points
1092  //
1093  // METHOD: the nearest point to w1 on the line x1,x2
1094  // is found. Elementary vector calculus is used!
1095  //
1096  // INPUT: x1, x2 closest appoach GEANE points
1097  // w1 point to approach w1
1098  //
1099  // OUTPUT: Pfinal point of closest approach
1100  // Dist distance between Pfinal and w1
1101  // Length arc length to add to the GEANE length of x1
1102  // quitFlag error flag which will be set to 1 if points dont form line
1103  // Authors: Andrea Fontana and Alberto Rotondi May 2007
1104  //
1105 
1106  quitFlag = 0;
1107 
1108  TVector3 u21;
1109 
1110  double a, t1;
1111 
1112  // w-point - x-line distance
1113  double d = (X2 - X1).Mag();
1114  if (fabs(d) < 1.E-8) {
1115  quitFlag = 1;
1116  return;
1117  }
1118  a = 1. / d;
1119 
1120  u21 = (X2 - X1).Unit();
1121 
1122  // output
1123  Dist = ((w1 - X1).Cross(u21)).Mag();
1124  t1 = a * (w1 - X1).Dot(u21);
1125  Pfinal = (X2 - X1) * t1 + X1;
1126  Length = (X2 - X1).Mag() * t1;
1127 }
1128 
1129 void FairGeanePro::Track3ToLine(TVector3 X1,
1130  TVector3 X2,
1131  TVector3 X3,
1132  TVector3 w1,
1133  TVector3 w2,
1134  // output
1135  TVector3& Pfinal,
1136  TVector3& Wire,
1137  int& Iflag,
1138  double& Dist,
1139  double& Length,
1140  double& Radius)
1141 {
1142  // Find the closest approach points between a curve (helix)
1143  // and a line (wire)
1144  //
1145  // METHOD:the classical Eberly method is used: see
1146  // http://www.geometrictools.com/Documentation/DistanceLine3Circle.pdf.
1147  // (see also www.geometrictools.com for the other formulae used
1148  // in this interface).
1149  // The 4-degree polynomial resulting for the line parameter t is
1150  // solved with the efficient SolveQuartic Root routine.
1151  // The minimal distance solution is found by using our Track3ToPoint
1152  // routine
1153  //
1154  // INPUT: x1, x2, x3 closest appoach GEANE points
1155  // w1, w2 points of the line (wire) to approach
1156  //
1157  // OUTPUT: Pfinal track point of closest approach
1158  // Wire line point of closest approach
1159  // Iflag = 1, the points are on a straight line
1160  // within the precision of the method (20 micron).
1161  // In this case the user should recall Track2ToPoint
1162  // = 2, Pwire is outside [w1,w2]
1163  // In this case, when w1 and w2 are the extremes
1164  // of the wire, the user could remake the procedure
1165  // by calling Track3ToPoint, where the Point is w1 or w2.
1166  // = 3 both conditions 1 and 2 are encountered
1167  // = 4, the method failed for mathematical reasons.
1168  // In this case the user should use Track2ToLine where
1169  // x1=x1 and x2=x3.
1170  // Dist distance between Pfinal and Wire
1171  // Length arc length to add to the GEANE length of x1
1172  // Radius radius of the found circle
1173  //
1174  // Authors: Andrea Fontana and Alberto Rotondi 20 June 2007
1175  //
1176 
1177  TVector3 xp1, xp2, xp3, xp32;
1178  TVector3 x21, x31;
1179  TVector3 e1, e2, e3, aperp;
1180  TVector3 Ppfinal, Pwire;
1181  TVector3 wp1, wp2, wpt, xR, xpR;
1182  TVector3 xw1, xw2;
1183  TVector3 px;
1184 
1185  double T[3][3], TM1[3][3];
1186 
1187  TVector3 N, M, D, B, Pointw;
1188  double a0, a1, b0, b1, c0, c1, c2;
1189  double d0, d1, d2, d3, d4, sol4[4], dmin;
1190  double Angle;
1191  double dx;
1192  int it, imin;
1193 
1194  Iflag = 0;
1195 
1196  // go to the circle plane: matrix of director cosines
1197 
1198  x21 = X2 - X1;
1199  e1 = x21.Unit();
1200  T[0][0] = e1.X();
1201  T[0][1] = e1.Y();
1202  T[0][2] = e1.Z();
1203 
1204  x31 = X3 - X1;
1205  e3 = e1.Cross(x31);
1206  // if the points are on the same line
1207  if (e3.Mag() < 1e-8) {
1208  Iflag = 1;
1209  return;
1210  }
1211  e3 = e3.Unit();
1212 
1213  T[2][0] = e3.X();
1214  T[2][1] = e3.Y();
1215  T[2][2] = e3.Z();
1216 
1217  e2 = e3.Cross(e1);
1218  T[1][0] = e2.X();
1219  T[1][1] = e2.Y();
1220  T[1][2] = e2.Z();
1221 
1222  // new coordinates
1223  for (int i = 0; i < 3; i++) {
1224  xp1[i] = 0.;
1225  xp2[i] = 0.;
1226  xp3[i] = 0.;
1227  wp1[i] = 0.;
1228  wp2[i] = 0.;
1229  }
1230  for (int i = 0; i < 3; i++) {
1231  xp1[i] = 0.;
1232  for (int j = 0; j < 3; j++) {
1233  TM1[i][j] = T[j][i];
1234  xp2[i] += T[i][j] * (X2[j] - X1[j]);
1235  xp3[i] += T[i][j] * (X3[j] - X1[j]);
1236  wp1[i] += T[i][j] * (w1[j] - X1[j]);
1237  wp2[i] += T[i][j] * (w2[j] - X1[j]);
1238  }
1239  }
1240 
1241  // radius and center
1242 
1243  xp32 = xp3 - xp2;
1244  xpR[0] = 0.5 * xp2[0];
1245  if (fabs(xp3[1]) < 1.E-8) {
1246  Iflag = 4;
1247  return;
1248  }
1249  xpR[1] = 0.5 * (xp32[0] * xp3[0] / xp3[1] + xp3[1]);
1250  xpR[2] = 0.;
1251  Radius = sqrt(pow(xpR[0] - xp1[0], 2) + pow(xpR[1] - xp1[1], 2));
1252 
1253  // Eberly's method
1254 
1255  B = wp1;
1256  M = wp2 - wp1;
1257  D = wp1 - xpR;
1258  N.SetXYZ(0., 0., 1.);
1259 
1260  a0 = M.Dot(D);
1261  a1 = M.Dot(M);
1262  b0 = M.Dot(D) - (N.Dot(M)) * (N.Dot(D));
1263  b1 = M.Dot(M) - (N.Dot(M)) * (N.Dot(M));
1264  c0 = D.Dot(D) - (N.Dot(D)) * (N.Dot(D));
1265  c1 = b0;
1266  c2 = b1;
1267 
1268  d0 = a0 * a0 * c0 - b0 * b0 * Radius * Radius;
1269  d1 = 2. * (a0 * a1 * c0 + a0 * a0 * c1 - b0 * b1 * Radius * Radius);
1270  d2 = a1 * a1 * c0 + 4. * a0 * a1 * c1 + a0 * a0 * c2 - b1 * b1 * Radius * Radius;
1271  d3 = 2. * (a1 * a1 * c1 + a0 * a1 * c2);
1272  d4 = a1 * a1 * c2;
1273 
1274  // solve the quartic equation
1275  for (int k = 0; k < 4; k++) {
1276  sol4[k] = 0.;
1277  }
1278  if (fabs(d4) < 1.E-12) {
1279  Iflag = 4;
1280  return;
1281  }
1282 
1283  TGeoTorus t;
1284  it = t.SolveQuartic(d3 / d4, d2 / d4, d1 / d4, d0 / d4, sol4);
1285 
1286  if (it == 0) {
1287  Iflag = 4;
1288  return;
1289  }
1290 
1291  // select the right solution
1292  dmin = 1.e+08;
1293  imin = 0; // This was set to -1 which could make problem if the indx is negative!! (MT)
1294 
1295  for (int j = 0; j < it; j++) {
1296  Pointw[0] = B[0] + sol4[j] * M[0];
1297  Pointw[1] = B[1] + sol4[j] * M[1];
1298  Pointw[2] = B[2] + sol4[j] * M[2];
1299  Track3ToPoint(xp1, xp2, xp3, Pointw, px, Iflag, dx, Length, Radius);
1300  if (Iflag == 2) {
1301  Iflag = 4;
1302  return;
1303  }
1304  if (dx < dmin) {
1305  dmin = dx;
1306  imin = j;
1307  }
1308  }
1309 
1310  // final solution
1311  Pwire[0] = B[0] + sol4[imin] * M[0];
1312  Pwire[1] = B[1] + sol4[imin] * M[1];
1313  Pwire[2] = B[2] + sol4[imin] * M[2];
1314  Track3ToPoint(xp1, xp2, xp3, Pwire, px, Iflag, dx, Length, Radius);
1315  if (Iflag == 2) {
1316  Iflag = 4;
1317  return;
1318  }
1319 
1320  // output: distance and points in the circle plane reference
1321 
1322  Dist = dx;
1323  Ppfinal = px;
1324 
1325  //
1326  // back to lab coordinates
1327  //
1328 
1329  xR[0] = 0.;
1330  xR[1] = 0.;
1331  xR[2] = 0.;
1332  Pfinal[0] = 0.;
1333  Pfinal[1] = 0.;
1334  Pfinal[2] = 0.;
1335  Wire[0] = 0.;
1336  Wire[1] = 0.;
1337  Wire[2] = 0.;
1338 
1339  for (int i = 0; i < 3; i++) {
1340  for (int j = 0; j < 3; j++) {
1341  Pfinal[i] += TM1[i][j] * Ppfinal[j];
1342  Wire[i] += TM1[i][j] * Pwire[j];
1343  xR[i] += TM1[i][j] * xpR[j];
1344  }
1345  }
1346  Pfinal = Pfinal + X1;
1347  Wire = Wire + X1;
1348  xR = xR + X1;
1349 
1350  double dx1 = (X1 - xR).Mag();
1351  double dx2 = (Pfinal - xR).Mag();
1352  double dx12 = dx1 * dx2;
1353  if (fabs(dx12) < 1.E-8) {
1354  Iflag = 4;
1355  return;
1356  }
1357 
1358  // now find the length
1359  Angle = TMath::ACos((X1 - xR).Dot(Pfinal - xR) / (dx12));
1360  Length = Radius * Angle;
1361  if ((X2 - X1).Dot(Pfinal - X1) < 0.) {
1362  Length = -Length;
1363  }
1364 
1365  // flag straight points within 20 microns
1366  double epsi = 0;
1367  if (Radius > 1E-8) {
1368  epsi = Radius * (1. - TMath::Cos(0.5 * (X3 - X1).Mag() / Radius));
1369  }
1370  if (epsi < 0.0020) {
1371  Iflag = 1;
1372  }
1373 
1374  // flag when the point on the wire is outside (w1,w2)
1375  if ((((Wire[0] < w1[0] && Wire[0] < w2[0]) || (w2[0] < Wire[0] && w1[0] < Wire[0]))
1376  && (fabs(Wire[0] - w1[0]) > 1e-11 && fabs(Wire[0] - w2[0]) > 1e-11))
1377  || (((Wire[1] < w1[1] && Wire[1] < w2[1]) || (w2[1] < Wire[1] && w1[1] < Wire[1]))
1378  && (fabs(Wire[1] - w1[1]) > 1e-11 && fabs(Wire[1] - w2[1]) > 1e-11))
1379  || (((Wire[2] < w1[2] && Wire[2] < w2[2]) || (w2[2] < Wire[2] && w1[2] < Wire[2]))
1380  && (fabs(Wire[2] - w1[2]) > 1e-11 && fabs(Wire[2] - w2[2]) > 1e-11))) {
1381  Iflag = 2;
1382  }
1383 }
1384 
1385 void FairGeanePro::Track3ToPoint(TVector3 X1,
1386  TVector3 X2,
1387  TVector3 X3,
1388  TVector3 w1,
1389  // output
1390  TVector3& Pfinal,
1391  int& Iflag,
1392  double& Dist,
1393  double& Length,
1394  double& Radius)
1395 {
1396  // Closest approach to a point from 3 GEANE points
1397  //
1398  // METHOD: first, we go on the circle plane to have
1399  // x1=(0,0), x2=(x2,0), x3=(x3,y3).
1400  // Then, the point on the circle is found as the
1401  // intersection between the circle and the line
1402  // joining the circle center and the projection of
1403  // the point on the circle plane.
1404  // The 3D distance is found between w1 and this
1405  // point on the circle.
1406  //
1407  // INPUT: x1, x2, x3 closest appoach GEANE points
1408  // w1 point to approach
1409  //
1410  // OUTPUT: Pfinal point of closest approach on the track
1411  // Dist distance between Pfinal and w1
1412  // Length arc length to add to the GEANE length of x1
1413  // Iflag when =1 the points are on a straight line
1414  // within the precision of the method (20 micron).
1415  // In this case the user should recall Track2ToPoint
1416  // if =2 mathematical errors
1417  // Authors: Andrea Fontana and Alberto Rotondi 20 May 2007
1418  //
1419 
1420  TVector3 xp1, xp2, xp3, xp32;
1421  TVector3 x21, x31;
1422  TVector3 e1, e2, e3;
1423  TVector3 Ppfinal, x32;
1424  TVector3 wp1, wpt, xR, xpR;
1425  TVector3 xw1, xw2;
1426 
1427  TVector3 xc1, xc2, xc3, wc1;
1428 
1429  double m1, m3, Rt;
1430  double T[3][3], TM1[3][3];
1431 
1432  double Angle;
1433 
1434  Iflag = 0;
1435 
1436  // go to the circle plane with origin in x1 prime (xp1):
1437  // matrix of director cosines
1438 
1439  x21 = X2 - X1;
1440 
1441  double x21mag = x21.Mag();
1442  if (x21mag < 1.E-8) {
1443  Iflag = 2;
1444  return;
1445  }
1446 
1447  m1 = 1. / x21mag;
1448  e1 = m1 * x21;
1449  T[0][0] = e1.X();
1450  T[0][1] = e1.Y();
1451  T[0][2] = e1.Z();
1452 
1453  x31 = X3 - X1;
1454  e3 = e1.Cross(x31);
1455 
1456  // if the points are on the same line
1457  if (e3.Mag() < 1e-8) {
1458  Iflag = 1;
1459  return;
1460  }
1461 
1462  m3 = 1. / e3.Mag();
1463  e3 = m3 * e3;
1464  T[2][0] = e3.X();
1465  T[2][1] = e3.Y();
1466  T[2][2] = e3.Z();
1467 
1468  e2 = e3.Cross(e1);
1469  T[1][0] = e2.X();
1470  T[1][1] = e2.Y();
1471  T[1][2] = e2.Z();
1472 
1473  // new coordinates
1474  for (int i = 0; i < 3; i++) {
1475  xp1[i] = 0.;
1476  xp2[i] = 0.;
1477  xp3[i] = 0.;
1478  wp1[i] = 0.;
1479  }
1480  for (int i = 0; i < 3; i++) {
1481  for (int j = 0; j < 3; j++) {
1482  TM1[i][j] = T[j][i];
1483  xp1[i] += 0.;
1484  xp2[i] += T[i][j] * (X2[j] - X1[j]);
1485  xp3[i] += T[i][j] * (X3[j] - X1[j]);
1486  wp1[i] += T[i][j] * (w1[j] - X1[j]);
1487  }
1488  }
1489 
1490  // radius Radius and center xpR
1491 
1492  xp32 = xp3 - xp2;
1493  xpR[0] = 0.5 * xp2[0];
1494  if (fabs(xp3[1]) < 1.E-8) {
1495  Iflag = 2;
1496  return;
1497  }
1498  xpR[1] = 0.5 * (xp32[0] * xp3[0] / xp3[1] + xp3[1]);
1499  xpR[2] = 0.;
1500 
1501  Radius = sqrt(pow(xpR[0] - xp1[0], 2) + pow(xpR[1] - xp1[1], 2));
1502 
1503  // distance and points
1504  wpt = wp1;
1505  wpt[2] = 0.; // point projection on the circle plane
1506 
1507  double dwp = (wpt - xpR).Mag();
1508  if (fabs(dwp) < 1.E-8) {
1509  Iflag = 2;
1510  return;
1511  }
1512  Rt = Radius / dwp;
1513  Ppfinal = (wpt - xpR) * Rt + xpR;
1514  Dist = (wp1 - Ppfinal).Mag();
1515 
1516  // back to lab coordinates:
1517  // from Ppfinal to Pfinal and from xpR to xR
1518 
1519  xR[0] = 0.;
1520  xR[1] = 0.;
1521  xR[2] = 0.;
1522  Pfinal[0] = 0.;
1523  Pfinal[1] = 0.;
1524  Pfinal[2] = 0.;
1525  for (int i = 0; i < 3; i++) {
1526  for (int j = 0; j < 3; j++) {
1527  Pfinal[i] += TM1[i][j] * Ppfinal[j];
1528  xR[i] += TM1[i][j] * xpR[j];
1529  }
1530  }
1531  Pfinal = Pfinal + X1;
1532  xR = xR + X1;
1533 
1534  // now find the length
1535  double dx1 = (X1 - xR).Mag();
1536  double dx2 = (Pfinal - xR).Mag();
1537  double dx12 = dx1 * dx2;
1538  if (fabs(dx12) < 1.E-8) {
1539  Iflag = 2;
1540  return;
1541  }
1542  // now find the length
1543  Angle = TMath::ACos((X1 - xR).Dot(Pfinal - xR) / (dx12));
1544  Length = Radius * Angle;
1545 
1546  // flag straight points within 20 microns
1547  double epsi = 0;
1548  if (Radius > 1E-8) {
1549  epsi = Radius * (1. - TMath::Cos(0.5 * (X3 - X1).Mag() / Radius));
1550  }
1551  if (epsi < 0.0020) {
1552  Iflag = 1;
1553  }
1554 }
1555 
1556 void FairGeanePro::GetTransportMatrix(double trm[5][5])
1557 {
1558  for (int i = 0; i < 5; i++)
1559  for (int j = 0; j < 5; j++) {
1560  trm[i][j] = trpmat[i][j];
1561  }
1562 }
1563 
virtual PCAOutputStruct FindPCA(int PCA, int PDGCode, TVector3 Point, TVector3 Wire1, TVector3 Wire2, double MaxDistance)
virtual Double_t GetPz() const
Definition: FairTrackPar.h:62
void GetCovQ(Double_t *CovQ)
virtual bool SetDestinationLength(float length)
Double_t GetY()
ClassImp(FairEventBuilder)
void SetTrackPar(Double_t X, Double_t Y, Double_t Z, Double_t Px, Double_t Py, Double_t Pz, Int_t Q, Double_t CovMatrix[15], TVector3 o, TVector3 di, TVector3 dj, TVector3 dk)
virtual bool SetDestinationPlane(const TVector3 &v0, const TVector3 &v1, const TVector3 &v2)
virtual bool SetPCAPropagation(int pca, int dir=1, FairTrackParP *par=nullptr)
virtual Double_t GetZ()
Definition: FairTrackPar.h:51
Double_t GetX()
virtual Double_t GetPx() const
Definition: FairTrackPar.h:60
TVector3 GetJVer()
virtual bool SetDestinationVolume(std::string volName, int copyNo, int option)
Double_t GetZ()
void Init(FairTrackPar *TParam)
TVector3 OnTrackPCA
TVector3 contact FairRoot group if you need it return fvwi
Definition: FairGeanePro.h:160
TVector3 OnWirePCA
FairMQExParamsParOne * par
virtual bool SetOriginPlane(const TVector3 &v0, const TVector3 &v1)
Int_t GetQ() const
Definition: FairTrackPar.h:52
void FromVecToMat(fiveMat &A, Double_t V[25])
virtual Double_t GetPy() const
Definition: FairTrackPar.h:61
TVector3 contact FairRoot group if you need it
Definition: FairGeanePro.h:164
virtual Double_t GetY()
Definition: FairTrackPar.h:50
void GetTransportMatrix(double trm[5][5])
int int option
Definition: FairGeanePro.h:78
TVector3 extremity2
Definition: FairGeanePro.h:144
virtual Double_t GetX()
Definition: FairTrackPar.h:49
void SetTrackPar(Double_t x, Double_t y, Double_t z, Double_t Px, Double_t Py, Double_t Pz, Int_t Q, Double_t CovMatrix[15])
virtual bool Propagate(FairTrackParH *TStart, FairTrackParH *TEnd, int PDG)
int TVector3 TVector3 TVector3 double maxdistance
Definition: FairGeanePro.h:131
virtual bool SetPropagateOnlyParameters()
TVector3 GetKVer()
void GetCovQ(Double_t *CovQ)