BOSS 8.0.0
BESIII Offline Software System
Loading...
Searching...
No Matches
TrkPocaBase.cxx
Go to the documentation of this file.
1//--------------------------------------------------------------------------
2// File and Version Information:
3// $Id: TrkPocaBase.cxx,v 1.4 2006/03/28 01:02:36 zhangy Exp $
4//
5// Description:
6//
7// Environment:
8// Software developed for the BaBar Detector at the SLAC B-Factory.
9//
10// Author(s): Steve Schaffner
11//
12// Modifications:
13// - Jan 2003 (WDH)
14//------------------------------------------------------------------------
15#include "TrkBase/TrkPocaBase.h"
16#include "CLHEP/Geometry/Point3D.h"
17#include "CLHEP/Vector/ThreeVector.h"
18#include "MdcGeom/Trajectory.h"
19#include "TrkBase/TrkPoca.h"
20#include <algorithm>
21#include <assert.h>
22#include <iomanip>
23#include <math.h>
24
25TrkPocaBase::TrkPocaBase( double f1, double f2, double prec )
26 : _precision( prec ), _flt1( f1 ), _flt2( f2 ), _status( TrkErrCode::fail ) {
27 assert( prec > 0. );
28}
29
30void TrkPocaBase::minimize( const Trajectory& traj1, double f1, const Trajectory& traj2,
31 double f2 ) {
32 // Last revision: Jan 2003, WDH
33 const int maxnOscillStep = 5;
34 const int maxnDivergingStep = 5;
35
36 // initialize
38 _flt1 = f1;
39 _flt2 = f2;
40
41 static HepPoint3D newPos1, newPos2;
42 double delta( 0 ), prevdelta( 0 );
43 int nOscillStep( 0 );
44 int nDivergingStep( 0 );
45 bool finished = false;
46 int istep( 0 );
47
48 for ( istep = 0; istep < _maxTry && !finished; ++istep )
49 {
50 double prevflt1 = flt1();
51 double prevflt2 = flt2();
52 double prevprevdelta = prevdelta;
53 prevdelta = delta;
54
55 stepTowardPoca( traj1, traj2 );
56 if ( status().failure() )
57 {
58 // failure in stepTowardPoca
59 finished = true;
60 }
61 else
62 {
63 newPos1 = traj1.position( flt1() );
64 newPos2 = traj2.position( flt2() );
65 delta = ( newPos1 - newPos2 ).mag();
66 double step1 = flt1() - prevflt1;
67 double step2 = flt2() - prevflt2;
68 int pathDir1 = ( step1 > 0. ) ? 1 : -1;
69 int pathDir2 = ( step2 > 0. ) ? 1 : -1;
70
71 // Can we stop stepping?
72 double distToErr1 = traj1.distTo1stError( prevflt1, precision(), pathDir1 );
73 double distToErr2 = traj2.distTo1stError( prevflt2, precision(), pathDir2 );
74
75 // converged if very small steps, or if parallel
76 finished = ( fabs( step1 ) < distToErr1 && fabs( step2 ) < distToErr2 ) ||
77 ( status().success() == 3 );
78
79 // we have to catch some problematic cases
80 if ( !finished && istep > 2 && delta > prevdelta )
81 {
82 if ( prevdelta > prevprevdelta )
83 {
84 // diverging
85 if ( ++nDivergingStep > maxnDivergingStep )
86 {
87 _status.setFailure( 2 ); // code for `Failed to converge'
88 finished = true;
89 }
90 }
91 else
92 {
93 nDivergingStep = 0;
94 // oscillating
95 if ( ++nOscillStep > maxnOscillStep )
96 {
97 // bail out of oscillation. since the previous step was
98 // better, use that one.
99 _flt1 = prevflt1;
100 _flt2 = prevflt2;
101 _status.setSuccess( 21, "Oscillating poca." );
102 finished = true;
103 }
104 else
105 {
106 // we might be oscillating, but we could also just have
107 // stepped over the minimum. choose a solution `in
108 // between'.
109 _flt1 = prevflt1 + 0.5 * step1;
110 _flt2 = prevflt2 + 0.5 * step2;
111 newPos1 = traj1.position( _flt1 );
112 newPos2 = traj2.position( _flt2 );
113 delta = ( newPos1 - newPos2 ).mag();
114 }
115 }
116 }
117 }
118 }
119 if ( !finished ) _status.setSuccess( 2 ); // code for 'not converged' (yet)
120}
121
122TrkPocaBase::TrkPocaBase( double f1, double prec )
123 : _precision( prec ), _flt1( f1 ), _flt2( 0 ), _status( TrkErrCode::fail ) {}
124
125void TrkPocaBase::minimize( const Trajectory& traj, double f1, const HepPoint3D& pt ) {
127 _flt1 = f1;
128 int pathDir = 1; // which way are we stepping (+/- 1)
129
130 int nTinyStep = 0; // number of consecutive tiny steps -- oscillation test
131 int nOscills = 0;
132 double fltLast = 0., fltBeforeLast = 0.; // another check for oscillation
133 for ( int i = 0; i < _maxTry; i++ )
134 {
135 fltLast = flt1();
136 stepToPointPoca( traj, pt );
137 if ( status().failure() ) return;
138 double step = flt1() - fltLast;
139 pathDir = ( step > 0. ) ? 1 : -1;
140 // Can we stop stepping?
141 double distToErr = traj.distTo1stError( fltLast, precision(), pathDir );
142 bool mustStep = ( fabs( step ) > distToErr && step != 0. );
143 // Crude test for oscillation (around cusp point of piecewise traj, I hope)
144 if ( fabs( step ) < 0.5 * precision() ) { nTinyStep++; }
145 else
146 {
147 nTinyStep = 0;
148 if ( i > 1 )
149 {
150 if ( fabs( step ) >= fabs( fltBeforeLast - fltLast ) &&
151 fabs( fltBeforeLast - flt1() ) <= fabs( step ) )
152 {
153 nOscills++;
154 double halfway = ( fltBeforeLast + fltLast ) / 2.;
155 if ( ( traj.position( flt1() ) - pt ).mag() >
156 ( traj.position( halfway ) - pt ).mag() )
157 _flt1 = halfway;
158 }
159 }
160 }
161 if ( nTinyStep > 3 ) mustStep = false;
162 if ( nOscills > 2 )
163 {
164 mustStep = false;
165#ifdef MDCPATREC_WARNING
166 std::cout << " ErrMsg(warning) "
167 << "Alleged oscillation detected. " << step << " " << fltLast - fltBeforeLast
168 << " " << i << " " << std::endl;
169#endif
170 }
171 if ( !mustStep ) return;
172 fltBeforeLast = fltLast;
173 }
174 // Ran off the end of the loop
175 _status.setFailure( 2 );
176}
177
179
180void TrkPocaBase::stepTowardPoca( const Trajectory& traj1, const Trajectory& traj2 ) {
181 // Last revision: Jan 2003, WDH
182
183 // A bunch of unsightly uninitialized variables:
184 static Hep3Vector dir1, dir2;
185 static Hep3Vector delDir1, delDir2;
186 static HepPoint3D pos1, pos2;
187
188 traj1.getInfo( flt1(), pos1, dir1, delDir1 );
189 traj2.getInfo( flt2(), pos2, dir2, delDir2 );
190 Hep3Vector delta = ( (CLHEP::Hep3Vector)pos1 ) - ( (CLHEP::Hep3Vector)pos2 );
191 double ua = -delta.dot( dir1 );
192 double ub = delta.dot( dir2 );
193 double caa = dir1.mag2() + delta.dot( delDir1 );
194 double cbb = dir2.mag2() - delta.dot( delDir2 );
195 double cab = -dir1.dot( dir2 );
196 double det = caa * cbb - cab * cab;
197
198 if ( det < 0 )
199 {
200 // get rid of second order terms
201 caa = dir1.mag2();
202 cbb = dir2.mag2();
203 det = caa * cbb - cab * cab;
204 }
205
206 if ( det < 1.e-8 )
207 {
208 // If they are parallel (in quadratic approximation) give up
209 _status.setSuccess( 3 );
210 return;
211 }
212
213 double df1 = ( ua * cbb - ub * cab ) / det;
214 int pathDir1 = ( df1 > 0 ) ? 1 : -1;
215 double df2 = ( ub * caa - ua * cab ) / det;
216 int pathDir2 = ( df2 > 0 ) ? 1 : -1;
217
218 // Don't try going farther than worst parabolic approximation will
219 // allow: Since ` _extrapToler' is large, this cut effectively only
220 // takes care that we don't make large jumps past the kink in a
221 // piecewise trajectory.
222
223 double distToErr1 = traj1.distTo2ndError( flt1(), _extrapToler, pathDir1 );
224 double distToErr2 = traj2.distTo2ndError( flt2(), _extrapToler, pathDir2 );
225
226 // Factor to push just over border of piecewise traj (essential!)
227 const double smudge = 1.01;
228 if ( fabs( df1 ) > smudge * distToErr1 )
229 {
230 // choose solution for which df1 steps just over border
231 df1 = smudge * distToErr1 * pathDir1;
232 // now recalculate df2, given df1:
233 df2 = ( ub - df1 * cab ) / cbb;
234 }
235
236 if ( fabs( df2 ) > smudge * distToErr2 )
237 {
238 // choose solution for which df2 steps just over border
239 df2 = smudge * distToErr2 * pathDir2;
240 // now recalculate df1, given df2:
241 df1 = ( ua - df2 * cab ) / cbb;
242 // if still not okay,
243 if ( fabs( df1 ) > smudge * distToErr1 ) { df1 = smudge * distToErr1 * pathDir1; }
244 }
245
246 _flt1 += df1;
247 _flt2 += df2;
248
249 // another check for parallel trajectories
250 if ( fabs( flt1() ) > _maxDist && fabs( flt2() ) > _maxDist ) _status.setSuccess( 3 );
251}
252
253void TrkPocaBase::stepToPointPoca( const Trajectory& traj, const HepPoint3D& pt ) {
254 // Unsightly uninitialized variables:
255 static Hep3Vector dir, delDir;
256 static HepPoint3D trajPos;
257
258 traj.getInfo( flt1(), trajPos, dir, delDir );
259 Hep3Vector delta = ( (CLHEP::Hep3Vector)trajPos ) - ( (CLHEP::Hep3Vector)pt );
260 double denom = 1. + delta.dot( delDir );
261 if ( fabs( denom ) * _maxDist < 1. )
262 {
263 _status.setFailure( 11, "TrkPoca::ambiguous tight looper." );
264 return;
265 }
266 double df = -delta.dot( dir ) / fabs( denom );
267 int pathDir = ( df > 0. ) ? 1 : -1;
268
269 // Don't try going farther than worst parabolic approximation will allow:
270 double distToErr = traj.distTo2ndError( flt1(), _extrapToler, pathDir );
271 if ( fabs( df ) > distToErr ) df = ( df > 0 ? distToErr : -distToErr );
272 // Make the step slightly longer -- prevents quitting at kinks
273 df += 0.001 * pathDir * precision();
274 _flt1 += df;
275}
276
277double TrkPocaBase::_maxDist = 1.e7;
278
279int TrkPocaBase::_maxTry = 500;
280
281double TrkPocaBase::_extrapToler = 2.;
TFile * f1
virtual HepPoint3D position(double) const =0
virtual double distTo2ndError(double s, double tol, int pathDir) const =0
virtual void getInfo(double fltLen, HepPoint3D &pos, Hep3Vector &direction) const =0
virtual double distTo1stError(double s, double tol, int pathDir) const =0
void stepToPointPoca(const Trajectory &traj, const HepPoint3D &pt)
TrkPocaBase(double flt1, double flt2, double precision)
void minimize(const Trajectory &traj1, double f1, const Trajectory &traj2, double f2)
virtual ~TrkPocaBase()
void stepTowardPoca(const Trajectory &traj1, const Trajectory &traj2)