CDF II
CDF KITS
source navigation ]
diff markup ]
identifier search ]
freetext search ]
file search ]
 
Architecture: i386 ]
Version: 4.10.4 ] [ 4.10.5 ] [ 4.8.4 ] [ 4.8.4l3s ] [ 4.8.5 ] [ 4.9.0 ] [ 4.9.1 ] [ 4.9.1.hpt3 ] [ 4.9.1hpt3 ] [ 4.9.1top1 ] [ 5.0.0 ] [ 5.1.0 ] [ 5.1.0beamonly ] [ 5.1.1 ] [ 5.2.0 ] [ 5.3.0 ] [ 5.3.1 ] [ 5.3.1dsp ] [ 5.3.3 ] [ 5.3.3_nt ] [ 5.3.4 ] [ 6.1.1 ] [ 6.1.1b ] [ 6.1.2 ] [ 6.1.3 ] [ 6.1.4 ] [ 6.1.4int3 ] [ 6.1.4mc ] [ 6.1.4mc_a ] [ 6.1.6 ] [ development ]

001  /************************************************************************

002  * VertexFit class implementation file                                   *

003  *                                                                       *

004  *                                                                       *

005  * Author: Craig Blocker, CDF Group                                      *

006  *         Phone 781-736-2920                                            *

007  *                                                                       *

008  * Description: Routines to implement VertexFit class                    *

009  *                                                                       *

010  * See VertexFit.hh in the VertexAlg/ area and                           *

011  * the file VertexFit.txt in the /doc area of VertexAlg for              *

012  * documentation.                                                        *

013  *                                                                       *

014  * Revision History:                                                     *

015  *    May 27, 1999   Craig Blocker   Initial creation                    * 

016  *    June 22, 2001  Craig Blocker   Fix a few bugs in checking on       *

017  *                                     vertices (such as pointing to     *

018  *                                     primary vertex wasn't allowed)    *

019  *                                                                       *

020  *    Sept 07, 2002 Joao Guimaraes   Added accessors for ijk errors and  *

021  *                                   track-id of tracks that produce     *

022  *                                   some of those errors                *

023  *                                   These methods are:                  *

024  *                                      getIJKErr(int&,int&,int&) const  *

025  *                                      getIJKErr0() const               *

026  *                                      getIJKErr1() const               *

027  *                                      getIJKErr2() const               *

028  *                                      getErrTrackId() const            *

029  *                                                                       *

030  *    Feb 10, 2002 Joao Guimaraes    Added two methods to allow for a    *

031  *                                   beam constrained fit with CTVMFT.   *

032  *                                   This only makes sense when fitting  *

033  *                                   a primary vertex and should not be  *

034  *                                   used for fitting secondary vertices *

035  *    Oct 15 2003 Sal Rappoccio (rappocc@fnal.gov)                       *

036  *                  Added accessor to add tracks to ctvmft via a track   *

037  *                  id and the track parameters and covariance           *

038  *                                                                       *

039  *  December 2 2003 Sal Rappoccio (rappocc@fnal.gov)                     *

040  *                  Added an interface to use extrapolated track errors  *

041  *                  in a "transparent" way. The new interface is used as:*

042  *                        VertexFit fit;                                 *

043  *                        fit.init();                                    *

044  *                        fit.setPrimaryVertex ( p1 ); // Note the order *

045  *                                                     // matters        *

046  *                        fit.setReferencePoint( p2 );                   *

047  *                        fit.addTrack( trk1, M_PION, 1 );               *

048  *                        fit.addTrack( trk2, M_PION, 1 );               *

049  *                        fit.fit();                                     *

050  *                        Hep3Vector & pos = fit.getVertex( 1 );         *

051  *                  "pos" will now hold the new vertex in CDF coordinates*

052  *                  constructed from tracks with errors referenced at the*

053  *                  new reference point "p2".                            *

054  *                  This track extrapolation code is OFF by default. It  *

055  *                  is turned ON by:   fit.setReferencePoint( p2 );      * 

056  *                  AddTrack was modified to use this feature.           *

057  *  Dec 2 2003 Joao Guimaraes                                            *

058  *                  Updated VertexFit::beamlineConstraint to use new     *

059  *                  reference point (see entry above).                   *

060  *                                                                       *

061  *************************************************************************/
062 
063 
064 #ifndef VERTEXFIT_CC
065 #define VERTEXFIT_CC
066 
067 //-----------------------

068 // This Class's Header --

069 //-----------------------

070 #include "VertexAlg/VertexFit.hh"
071 
072 extern "C" void ctvmft_(int&,int&,int&);
073 extern "C" float prob_(float&,int&);
074 extern "C" bool mcalc_(int&,int*,float&,float&,double*);
075 extern "C" void dcalc_(int&,int&,float*,float&,float&,float*);
076 
077 // C++ Headers --

078 //---------------

079 #if defined(DEFECT_OLD_IOSTREAM_HEADERS)
080 #include <iostream>
081 #else // Standard C++

082 #include <iostream>
083 #endif
084 
085 #if defined(DEFECT_NO_STDLIB_NAMESPACES)
086 // Do nothing

087 #else // Standard C++

088 using std::cerr ;
089 using std::cout ;
090 using std::endl ;
091 #endif
092 
093 #include <algorithm>
094 #include <math.h>
095 
096 //-------------------------------

097 // Collaborating Class Headers --

098 //-------------------------------

099 #include "TrackingObjects/Tracks/CdfTrack.hh"
100 #include "CLHEP/Matrix/Matrix.h"
101 #include "TrackingHL/Utility/TrackExtrapolator.hh"
102 
103 //for floating point exception handling Joe and Farrukh

104 #include <csignal>
105 #include <csetjmp>
106 
107 /******************************************************************************

108  * Default constructor                                                        *

109  *                                                                            *

110  *                                                                            *

111  *****************************************************************************/
112 
113 //the following will have scope throughout.

114 
115  jmp_buf env;
116  extern "C" void VertexFitSetStatus(int i) { 
117    std::cout << "Warning, you are handling a severe error in VertexFit" << std::endl;
118    longjmp(env,-66);
119  }
120 
121 VertexFit::VertexFit() :
122   _currentAllocatedVertexNumber(0),   // facilitates CandNode recursion

123   _referencePoint( 0,0,0 ), // Set Reference Point to (0,0,0) initially

124   _primaryVertex( 0,0,0 ), // Set primary vertex to (0,0,0) initially

125   _cdfPrimaryVertex( 0,0,0 ) // Set p.v. in CDF coords to (0,0,0) initially

126 {
127 // Set name and email of VertexFit expert.

128    _expert="Craig Blocker (blocker@fnal.gov)";
129 // First get pointers to various FORTAN common blocks.

130    _ctvmq_com = (CTVMQ*) ctvmq_address_();
131    _ctvmfr_com = (CTVMFR*) ctvmfr_address_();
132    _fiddle_com = (FIDDLE*) fiddle_address_();
133    _trkprm_com = (TRKPRM*) trkprm_address_();
134 // Initialize various arrays

135    init();
136 // Don't bomb program on error.

137    _fiddle.excuse=1;
138 // Don't extrapolate track errors by default

139    _extrapolateTrackErrors = false;
140 }
141 
142 /******************************************************************************

143  * Destructor                                                                 *

144  *        Use default, i.e. do nothing                                        *

145  *****************************************************************************/
146 
147 VertexFit::~VertexFit(){ }
148 
149 
150 
151 // Particle masses

152 const float VertexFit::EL_MASS = 0.000510998902;
153 const float VertexFit::MU_MASS = 0.105658357;
154 const float VertexFit::PI_MASS = 0.13957018;
155 const float VertexFit::K_MASS = 0.493677;
156 const float VertexFit::PROTON_MASS = 0.938272;
157 
158 /*=======================================================================

159                          VertexFit::init

160   =======================================================================*/
161 
162 void VertexFit::init()
163 {
164   double bmag = 1.4116; // Magnetic field in Tesla

165    init(bmag);
166 }
167 
168 void VertexFit::init(double bmag)
169 {
170 // Now initialize CTVMQ common.  Run and trigger numbers are

171 // dummies - they are not used.

172    _ctvmq.runnum=1;
173    _ctvmq.trgnum=100;
174 // Eventually, we have to get the magnetic field from the right place.

175 // Origignal with      bmag = 14.116:

176 // _ctvmq.pscale=0.000149896*bmag;

177 // New bfield in Tesla bmag = 1.4116 [T]:

178    _ctvmq.pscale=0.00149896*bmag;
179 // Set the default maximum chi-square per dof.

180    _fiddle.chisqmax = 225.;
181 // We also need to get the primary vertex from the right place,

182 // but for now we put in (0,0,0).

183    setPrimaryVertex(0.,0.,0.);
184    float xverr[3][3];
185    for(int j = 0; j<3; j++) {
186       for(int k = 0; k<3; k++) {
187          xverr[j][k] = 0.;
188       }
189    }
190    xverr[0][0]=.005;
191    xverr[1][1]=.005;
192    xverr[2][2]=1.;
193    setPrimaryVertexError(xverr);
194 // Zero number of tracks, vertices and mass constraints.

195    _ctvmq.ntrack=0;
196    _ctvmq.nvertx=0;
197    _ctvmq.nmassc=0;
198 // Zero track list and arrays containing the vertex and

199 // mass constraint configuration.

200    for(int j=0; j<_maxtrk; ++j) {
201       _ctvmq.list[j]=0;
202       for(int jv=0; jv<_maxvtx; ++jv) {
203          _ctvmq.trkvtx[jv][j]=false;
204       }
205       for(int jmc=0; jmc<_maxmcn; ++jmc) {
206          _ctvmq.trkmcn[jmc][j]=false;
207       }
208    }
209 // Initialize the conversion and vertex pointing arrays.

210    for(int jv=0; jv<_maxvtx; ++jv) {
211       _ctvmq.cvtx[jv]=0;
212       _ctvmq.vtxpnt[0][jv]=-1;
213       _ctvmq.vtxpnt[1][jv]=0;
214    }
215    _ctvmq.drmax=2.;
216    _ctvmq.dzmax=20.;
217    _ctvmq.rvmax=70.;
218    _ctvmq.trnmax=0.5;
219    _ctvmq.dsmin=-2.;   
220 // Set stat to -999  and chisqq to -1 to symbolize that no fit has yet been done.

221    stat=-999;
222    _ctvmq.chisqr[0]=-1.;
223 
224    _primaryVertex = Hep3Vector(0,0,0);
225    _cdfPrimaryVertex = Hep3Vector(0,0,0);
226    _referencePoint = Hep3Vector(0,0,0);
227 }
228 
229 /*=======================================================================

230                          VertexFit::addTrack

231   =======================================================================*/
232 
233 bool VertexFit::addTrack(const CdfTrack* trk, float mass,
234                          vertexNumber jv)
235 {
236 // Check that this vertex number is within the allowed range.

237    if(jv<VERTEX_1 || jv>_maxvtx) return false;
238    _ctvmq.nvertx = jv>_ctvmq.nvertx ? jv : _ctvmq.nvertx;
239 
240 // Check that we have not exceeded the maximum number of tracks.

241    if(_ctvmq.ntrack>=_maxtrk) return false;
242 
243 
244 // Sal Rappoccio: Add track extrapolation, if the user set it

245    HepVector w = trk->par();
246    HepSymMatrix m = trk->getHelixFit().getErrorMatrix();
247    if ( _extrapolateTrackErrors ) {
248      // This will move the reference point

249      moveReferencePoint( w, m );
250    }
251 
252 // Add this track.

253    _ctvmq.list[_ctvmq.ntrack]=trk->id().value();
254    _ctvmq.tkbank[_ctvmq.ntrack][0]='Q';
255    _ctvmq.tkbank[_ctvmq.ntrack][1]='T';
256    _ctvmq.tkbank[_ctvmq.ntrack][2]='R';
257    _ctvmq.tkbank[_ctvmq.ntrack][3]='K';
258    _ctvmq.tmass[_ctvmq.ntrack]=mass;
259    _ctvmq.trkvtx[jv-1][_ctvmq.ntrack]=true;
260 
261 // Put this track's helix parameters and error matrix into

262 // a fortran common block so that they can  be accessed

263 // by gettrk.  This is a dummy for now.

264    _trkprm.trhelix[_ctvmq.ntrack][0]=w[0];
265    _trkprm.trhelix[_ctvmq.ntrack][1]=w[1];
266    _trkprm.trhelix[_ctvmq.ntrack][2]=w[2];
267    _trkprm.trhelix[_ctvmq.ntrack][3]=w[3];
268    _trkprm.trhelix[_ctvmq.ntrack][4]=w[4];
269 
270    for(int j=0; j<5; ++j) {
271       for(int k=0; k<5; ++k) {
272          _trkprm.trem[_ctvmq.ntrack][j][k]=m[j][k];
273       }
274    }
275    _ctvmq.ntrack++;
276 
277    return true;
278 }
279 
280 // Sal Rappoccio: 11/04/03: Added this method to add track using

281 // their track id and the explicit helix parameters.

282 // This is useful when for adding tracks with helical parameters relative 

283 // to a point other than (0,0)

284 
285 /*=======================================================================

286                          VertexFit::addTrack

287   =======================================================================*/
288 
289 bool VertexFit::addTrack( const HepVector & v,
290                           const HepSymMatrix & cov,
291                           int trackId,
292                           float mass,
293                           vertexNumber jv)
294 {
295 // Check that this vertex number is within the allowed range.

296    if(jv<VERTEX_1 || jv>_maxvtx) return false;
297    _ctvmq.nvertx = jv>_ctvmq.nvertx ? jv : _ctvmq.nvertx;
298 
299 // Sal Rappoccio: Add track extrapolation, if the user set it

300 
301    HepVector w = v;
302    HepSymMatrix m = cov;
303    if ( _extrapolateTrackErrors ) {
304      // This will move the reference point

305      moveReferencePoint( w, m );
306    }
307 
308 // Check that we have not exceeded the maximum number of tracks.

309    if(_ctvmq.ntrack>=_maxtrk) return false;
310 
311 // Add this track.

312    _ctvmq.list[_ctvmq.ntrack]=trackId;
313    _ctvmq.tkbank[_ctvmq.ntrack][0]='Q';
314    _ctvmq.tkbank[_ctvmq.ntrack][1]='T';
315    _ctvmq.tkbank[_ctvmq.ntrack][2]='R';
316    _ctvmq.tkbank[_ctvmq.ntrack][3]='K';
317    _ctvmq.tmass[_ctvmq.ntrack]=mass;
318    _ctvmq.trkvtx[jv-1][_ctvmq.ntrack]=true;
319 
320 // Put this track's helix parameters and error matrix into

321 // a fortran common block so that they can  be accessed

322 // by gettrk.  This is a dummy for now.

323    _trkprm.trhelix[_ctvmq.ntrack][0]=w[0];
324    _trkprm.trhelix[_ctvmq.ntrack][1]=w[1];
325    _trkprm.trhelix[_ctvmq.ntrack][2]=w[2];
326    _trkprm.trhelix[_ctvmq.ntrack][3]=w[3];
327    _trkprm.trhelix[_ctvmq.ntrack][4]=w[4];
328 
329    for(int j=0; j<5; ++j) {
330       for(int k=0; k<5; ++k) {
331          _trkprm.trem[_ctvmq.ntrack][j][k]=m[j][k];
332 
333       }
334    }
335    _ctvmq.ntrack++;
336 
337    return true;
338 }
339 
340 /*=======================================================================

341                          VertexFit::vertexPoint_2d

342   =======================================================================*/
343   
344 bool VertexFit::vertexPoint_2d(vertexNumber jv1, vertexNumber jv2)
345 {
346 // Check that these vertex numbers are within allowed range and

347 // that the vertices are unique.

348    if(jv1>_maxvtx || jv1<VERTEX_1) return false;
349    if(jv2>_maxvtx || jv2<PRIMARY_VERTEX) return false;
350    if(jv1 <= jv2) return false;
351 
352 // Setup vertex pointing.

353    _ctvmq.vtxpnt[0][jv1-1]=jv2;
354    _ctvmq.vtxpnt[1][jv1-1]=1;           // 2d pointing.

355 
356    return true;
357 }
358 
359 /*=======================================================================

360                          VertexFit::vertexPoint_3d

361   =======================================================================*/
362 
363 bool VertexFit::vertexPoint_3d(vertexNumber jv1, vertexNumber jv2)
364 {
365 // Check that these vertex numbers are within allowed range and

366 // that the vertices are distinct.

367    if(jv1>_maxvtx || jv1<VERTEX_1) return false;
368    if(jv2>_maxvtx || jv2<PRIMARY_VERTEX) return false;
369    if(jv1 <= jv2) return false;
370 // Setup vertex pointing.

371    _ctvmq.vtxpnt[0][jv1-1]=jv2;
372    _ctvmq.vtxpnt[1][jv1-1]=2;           // 3d pointing.

373 
374    return true;
375 }
376 
377 /*=======================================================================

378                          VertexFit::vertexPoint_1track

379   =======================================================================*/
380 
381 bool VertexFit::vertexPoint_1track(vertexNumber jv1, vertexNumber jv2)
382 {
383 // Check that these vertex numbers are within allowed range and are distinct.

384    if(jv1>_maxvtx || jv1<VERTEX_1) return false;
385    if(jv2>_maxvtx || jv2<PRIMARY_VERTEX) return false;
386    if(jv1 <= jv2) return false;
387 
388 // Setup vertex pointing.

389    _ctvmq.vtxpnt[0][jv1-1]=jv2;
390    _ctvmq.vtxpnt[1][jv1-1]=3;           // Point to 1 track vertex.

391 
392    return true;
393 }
394 /*=======================================================================

395                          VertexFit::vertexPoint_0track

396   =======================================================================*/
397 
398 bool VertexFit::vertexPoint_0track(vertexNumber jv1, vertexNumber jv2)
399 {
400 
401   // jv2 is the zero track vertex. jv1 is the multi track vertex which points to jv2

402 
403   // Note: You must call this routine at least twice in order for ctvmft_zerotrackvtx to work

404   // ie there must be at least 2 vertices pointed at a zero track vertex. ctvmft

405   // for this, but the error message may not make it to your log file (look at the local

406   // variables in the stack frame especially IJKERR(2). The significance of this

407   // error code is documented at the top of whatever routine chucked you out (ctvmf00 in

408   // this case)

409 
410   // see ctvmft.f source file for discussion. See especially comments at the top

411   // of subroutines: ctvmft and ctvmfa

412 
413 // Check that these vertex numbers are within allowed range and are distinct.

414    if(jv1>_maxvtx || jv1<VERTEX_1) return false;
415    if(jv2>_maxvtx || jv2<PRIMARY_VERTEX) return false;
416    if(jv1 <= jv2) return false;
417 
418 // Setup vertex pointing.

419    _ctvmq.vtxpnt[0][jv1-1]=jv2;
420    _ctvmq.vtxpnt[1][jv1-1]=4;           // Point to 0 track vertex.

421 
422    return true;
423 }//vertexPoint_0track

424 
425 /*=======================================================================

426                          VertexFit::conversion_2d

427   =======================================================================*/
428 
429 bool VertexFit::conversion_2d(vertexNumber jv)
430 {
431    if(jv<VERTEX_1 || jv>_ctvmq.nvertx) {
432       return false;
433    }
434    _ctvmq.cvtx[jv-1]=1;
435    return true;
436 }
437 
438 /*=======================================================================

439                          VertexFit::conversion_3d

440   =======================================================================*/
441 
442 bool VertexFit::conversion_3d(vertexNumber jv)
443 {
444    if(jv<VERTEX_1 || jv>_ctvmq.nvertx) {
445       return false;
446    }
447    _ctvmq.cvtx[jv-1]=2;
448    return true;
449 }
450 
451 /*=======================================================================

452                          VertexFit::massConstrain

453   =======================================================================*/
454 
455 bool VertexFit::massConstrain(const CdfTrack* trk1,
456                               const CdfTrack* trk2, float mass)
457 {
458    int ntrk=2;
459    const CdfTrack* tracks[2];
460    tracks[0]=trk1;
461    tracks[1]=trk2;
462    return massConstrain(ntrk,tracks,mass);
463 }
464 
465 bool VertexFit::massConstrain(const CdfTrack* trk1, const CdfTrack* trk2,
466                                 const CdfTrack* trk3, float mass)
467 {
468    int ntrk=3;
469    const CdfTrack* tracks[3];
470    tracks[0]=trk1;
471    tracks[1]=trk2;
472    tracks[2]=trk3;
473    return massConstrain(ntrk,tracks,mass);
474 }
475 
476 bool VertexFit::massConstrain(const CdfTrack* trk1, const CdfTrack* trk2,
477                     const CdfTrack* trk3, const CdfTrack* trk4,float mass)
478 {
479    int ntrk=4;
480    const CdfTrack* tracks[4];
481    tracks[0]=trk1;
482    tracks[1]=trk2;
483    tracks[2]=trk3;
484    tracks[3]=trk4;
485    return massConstrain(ntrk,tracks,mass);
486 }
487 
488 bool VertexFit::massConstrain(int ntrk, const CdfTrack* tracks[], float mass)
489 {
490 // Check that we have not exceeded the allowed number of mass constraints.

491    if(_ctvmq.nmassc>=_maxmcn) return false;
492 
493 // Set constraint mass

494    _ctvmq.cmass[_ctvmq.nmassc]=mass;
495      
496 // For each track in contraint, set trkmcn true.  Since the number in

497 // tracks[] is the track number, we have to find each track in the

498 // list of tracks.

499    for(int jt=0; jt<ntrk; ++jt) {
500       bool found=false;
501       for(int kt=0; kt<_ctvmq.ntrack; ++kt) {
502          if(tracks[jt]->id().value()==_ctvmq.list[kt]) {
503             _ctvmq.trkmcn[_ctvmq.nmassc][kt]=true;
504             found=true;
505          }
506       }
507       if(!found) return false;
508    }
509 // Increment number of mass constraints.   

510    _ctvmq.nmassc++;
511 
512    return true;
513 }
514 
515 
516 /*=======================================================================

517                      VertexFit::beamlineConstraint

518   =======================================================================*/
519 //  Turn ON this option only when fitting the primary with no additional 

520 // constraints. The routine is protected and will not function

521 // if those options are selected as well as the beamline constraint.

522 // In case this option is chosen the fit will calculate a result also with

523 // just one track in input.

524 // In order to enable this option the user must do the following:

525 // Fit the primary vertex as VERTEX_1 (without any other vertices).

526 // Enable beamlineConstraint by setting the pointing constraint variable

527 // vtxpnt[0][0] to -100 (no pointing constraints when <0)

528 // Note that index 0,0 corresponds to index 1,1 in fortran

529 // Provide the beamline parameters:

530 //  --> assume xv = xb + xzbslope*z, 

531 //             yv = yb + yzbslope*z, where (xv, yv) is the transverse

532 //      beam position at z, (xb, yb) is the transverse beam position at z = 0 

533 //      and (xzbslope, yzbslope) are the slopes of the beamline

534 //  --> set primary vertex at z=0 (xb, yb, 0)

535 //  --> set the diagonal elements of the primary vertex error matrix to the

536 //      sigma**2 of beam spread in x, y and z:

537 //      xverr[1][1] =  (~30 - 50 um)**2

538 //      xverr[2][2] =  (~30 - 50 um)**2

539 //      xverr[3][3] =  (~30 cm) **2

540 //      All other elements should be 0

541 // For help email: Joao Guimaraes  guima@huhepl.harvard.edu

542 //                 Franco Bedeschi bed@fnal.gov 

543 // See more information in the ctvmft.f

544 bool VertexFit::beamlineConstraint(float xb, float yb, HepSymMatrix berr,
545                                    float xzbslope, float yzbslope)
546 {
547   // Set beam position at z=0

548   setPrimaryVertex(xb,yb,0);
549   if (_extrapolateTrackErrors) {
550     float newXb = xb - _referencePoint.x() + 
551       _referencePoint.z() * xzbslope;
552     float newYb = yb - _referencePoint.y() + 
553       _referencePoint.z() * yzbslope;
554     setPrimaryVertex( newXb, newYb, 0);
555   }
556 
557   bool success = setPrimaryVertexError(berr);
558   //Set the beamline slope values

559   _ctvmq.xzslope= xzbslope;
560   _ctvmq.yzslope= yzbslope;
561   // Turn ON beamline constraint

562   _ctvmq.vtxpnt[0][0]=-100; 
563 
564   return success;
565 }
566 
567 bool VertexFit::beamlineConstraint(Hep3Vector pv, HepSymMatrix berr,
568                                    float xzbslope, float yzbslope)
569 {
570   // Check if input beam position coordinates are at z=0

571   if (pv.z() != 0) return false;
572 
573   return beamlineConstraint(pv.x(),pv.y(),berr,xzbslope,yzbslope);
574 }
575 
576 /*=======================================================================

577                          VertexFit::setPrimaryVertex

578   =======================================================================*/
579 
580 void VertexFit::setPrimaryVertex(float xv, float yv, float zv)
581 {
582 // Set x,y,z position of the primary vertex.

583    _ctvmq.xyzpv0[0]=xv;
584    _ctvmq.xyzpv0[1]=yv;
585    _ctvmq.xyzpv0[2]=zv;
586 
587    _primaryVertex = Hep3Vector( xv, yv, zv );
588    return;
589 }
590 
591 void VertexFit::setPrimaryVertex(Hep3Vector pv)
592 {
593 // Set x,y,z position of the primary vertex.

594    _ctvmq.xyzpv0[0]=pv.x();
595    _ctvmq.xyzpv0[1]=pv.y();
596    _ctvmq.xyzpv0[2]=pv.z();
597 
598    _primaryVertex = pv;
599    return;
600 }
601 
602 /*=======================================================================

603                          VertexFit::setPrimaryVertexError

604   =======================================================================*/
605 
606 void VertexFit::setPrimaryVertexError(const float xverr[3][3])
607 {
608 // Set the error matrix for the primary vertex.

609    for(int j=0; j<3; ++j) {
610       for(int k=0; k<3; ++k) {
611          _ctvmq.exyzpv[j][k]=xverr[j][k];
612       }
613    }
614    return;
615 }
616 
617 bool VertexFit::setPrimaryVertexError(const HepSymMatrix &xverr)
618 {
619 // Set the error matrix for the primary vertex using a HepSymMatrix.

620 // First check that the matrix is the correct size.

621    if(xverr.num_row() != 3) return false;
622    for(int j=0; j<3; j++) {
623      for(int k=0; k<3; k++) {
624        _ctvmq.exyzpv[j][k]=xverr[j][k];
625      }
626    }
627    return true;
628 }
629 
630 /*=======================================================================

631                          VertexFit::fit

632   =======================================================================*/
633 
634 bool VertexFit::fit()
635 {
636 // Check that the diagonal elements of all the track error matrices

637 //are positive.

638   bool mstat = true;
639   for(int trk=0; trk<_ctvmq.ntrack; ++trk) {
640     for(int j=0; j<5; ++j) {
641 // Check diagonal elements of error matrix.

642       if(_trkprm.trem[trk][j][j] < 0.) {
643 // Tell user that the covariance matrix could not be inverted.

644 // Set the error codes and fail this fit.

645         mstat = false;
646         _ctvmq.ijkerr[0] = 3;
647         _ctvmq.ijkerr[1] = 2;
648         _ctvmq.ijkerr[2] = trk + 1;
649       }
650     }
651 // Check that the curvature of the track is reasonable, that is,

652 // that the Pt is above ~10Mev/c.  If not, set the error codes

653 // and fail this fit.

654     if(fabs(_trkprm.trhelix[trk][1]) > 0.01) {
655       mstat = false;
656       _ctvmq.ijkerr[0] = 3;
657       _ctvmq.ijkerr[1] = 5;
658       _ctvmq.ijkerr[2] = trk + 1;
659     }
660   }
661 // If there was a problem with any track, fail the fit.

662   if(!mstat) {
663     stat = 1;
664     return false;
665   }
666 
667 // First copy information into CTVMFT common blocks

668    *_ctvmq_com=_ctvmq;
669    *_ctvmfr_com=_ctvmfr;
670    *_fiddle_com=_fiddle;
671    *_trkprm_com=_trkprm;
672 // Do the vertex fit.

673    int print=0;
674    int level=0;
675 
676 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
677   struct sigaction myaction = {VertexFitSetStatus, 0, 0, 0}, oldaction;
678   sigaction(SIGFPE, &myaction, &oldaction);
679   if (setjmp(env)!=0) {
680     sigaction(SIGFPE, &oldaction,0);
681     return -999;
682   }
683 #endif
684 
685    ctvmft_(print,level,stat);
686 
687 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
688   sigaction(SIGFPE, &oldaction,0);
689 #endif
690 
691 // Now copy information from CTVMFT common blocks to local storage

692    _ctvmq=*_ctvmq_com;
693    _ctvmfr=*_ctvmfr_com;
694    _fiddle=*_fiddle_com;
695    _trkprm=*_trkprm_com;
696    
697    return stat==0;
698 }
699 
700 /*=======================================================================

701                          VertexFit::print

702   =======================================================================*/
703 
704 void VertexFit::print() const
705 {
706    print(std::cout);
707 }
708 
709 void VertexFit::print(std::ostream& os) const
710 {
711    os << "****************************** VertexFit "
712       << "******************************" << std::endl;
713    os << "Number of tracks: " << _ctvmq.ntrack << std::endl;
714    os << "   Tracks: ";
715    for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
716       if(jt != 0) os << ",  ";
717       CdfTrack::Id trkId(_ctvmq.list[jt]);
718       os << trkId;
719    }
720    os << std::endl;
721    os << "Number of vertices: " << _ctvmq.nvertx << std::endl;
722    for(int jv=0; jv<_ctvmq.nvertx; ++jv) {
723       os << "   Vertex " << jv+1 << " tracks: ";
724       for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
725          if(_ctvmq.trkvtx[jv][jt]) {
726             os << " " << _ctvmq.list[jt];
727          }
728       }
729       os << std::endl;
730    }
731    for(int jv=0; jv<_ctvmq.nvertx; ++jv) {
732       if(_ctvmq.vtxpnt[0][jv]==0) {
733          os << "   Vertex " << jv+1 << " points to the primary vertex ";
734       }
735       else if(_ctvmq.vtxpnt[0][jv]>0) {
736          os << "   Vertex " << jv+1 << " points to vertex "
737               << _ctvmq.vtxpnt[0][jv];
738       }
739       if(_ctvmq.vtxpnt[1][jv]==1) {
740          os << " in 2 dimensions" << std::endl;
741       }
742       else if(_ctvmq.vtxpnt[1][jv]==2) {
743          os << " in 3 dimensions" << std::endl;
744       }
745       else if(_ctvmq.vtxpnt[1][jv]==3) {
746          os << ", a single track vertex" << std::endl;
747       }
748       if(_ctvmq.cvtx[jv]>0) {
749          os << "   Vertex " << jv+1 << " is a conversion" << std::endl;
750       }
751    }
752    os << "Number of mass constraints: " << _ctvmq.nmassc << std::endl;
753    for(int jmc=0; jmc<_ctvmq.nmassc; ++jmc) {
754       os << "   Tracks ";
755       for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
756          if(_ctvmq.trkmcn[jmc][jt]) {
757             os << " " << _ctvmq.list[jt];
758          }
759       }
760       os << " constrained to mass " << _ctvmq.cmass[jmc]
761          << " Gev/c^2" << std::endl;
762    }
763    if(stat==-999) {
764       os << "No fit has been done." << std::endl;
765    }
766    else {
767       os << "***** Results of Fit *****" << std::endl;
768       printErr(os);
769       os << "   Status = " << stat << std::endl;
770       os << "   Chi-square = " << _ctvmq.chisqr[0]
771          << " for " << _ctvmq.ndof << " degrees of freedom." << std::endl;
772       os << "   => probability = " << prob() << std::endl;
773       for(int jv=0; jv<_ctvmq.nvertx; ++jv) {
774          os << "Vertex " << jv+1 << " position: "
775             << _ctvmq.xyzvrt[jv+1][0] << " "
776             << _ctvmq.xyzvrt[jv+1][1] << " "
777             << _ctvmq.xyzvrt[jv+1][2] << std::endl;
778       }
779       for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
780          os << "Track " << _ctvmq.list[jt] << " P4: " 
781             << _ctvmq.trkp4[0][jt] << " "
782             << _ctvmq.trkp4[1][jt] << " "
783             << _ctvmq.trkp4[2][jt] << " "
784             << _ctvmq.trkp4[3][jt] << " " << std::endl;
785       }
786    }
787    os << "****************************************"
788       << "**************************" << std::endl;
789 
790    return;
791 }
792 
793 /*=======================================================================

794                          VertexFit::printErr

795   =======================================================================*/
796 
797 void VertexFit::printErr() const
798 {
799    printErr(std::cout);
800 }
801 
802 void VertexFit::printErr(std::ostream& os) const
803 {
804    os << "VertexFit: IJKERR = " << _ctvmq.ijkerr[0] << ", "
805                         << _ctvmq.ijkerr[1] << ", "
806                         << _ctvmq.ijkerr[2] << std::endl;
807    if(status()==0 && _ctvmq.ijkerr[0]==0) return;
808    if(_ctvmq.ijkerr[0] == -1) {
809       os << "   Problem with GETTRK:  track requested is not in list."
810          << std::endl
811          << "   This should not happen - Contact VertexFit expert "
812          << _expert << "." <<std::endl;
813    }
814    else if(_ctvmq.ijkerr[0]==1) {
815       os << "   Problem in CTVM00:" << std::endl;
816       if(_ctvmq.ijkerr[1]==1) {
817          os << "      Number of tracks is " << _ctvmq.ntrack
818             << "." << std::endl;
819          if(_ctvmq.ntrack < 2) {
820             os << ", which is too few (must be at least 2)." << std::endl;
821          }
822          else if(_ctvmq.ntrack > _maxtrk) {
823             os << ", which is too many (maximum is " << _maxtrk
824                << ")." << std::endl;
825          }
826          else {
827             os << "      Problem with number of tracks"
828                << " for unknown reasons." << std::endl;
829          }
830       }
831       else if(_ctvmq.ijkerr[1]==2) {
832          os << "      Number of vertices is " << _ctvmq.nvertx
833             << "." << std::endl;
834          if(_ctvmq.nvertx < 1) {
835             os << ", which is too few (must be at least 1)." << std::endl;
836          }
837          else if(_ctvmq.nvertx > _maxvtx) {
838             os << ", which is too many (maximum is " << _maxvtx
839                << ")." << std::endl;
840          }
841          else {
842             os << std::endl << "      Problem with number of vertices"
843                << " for unknown reasons." << std::endl;
844          }
845       }
846       else if(_ctvmq.ijkerr[1]==3) {
847          os << "      Number of mass constraints is " << _ctvmq.nmassc
848             << "." << std::endl;
849          if(_ctvmq.nmassc < 0) {
850             os << ", which is negative." << std::endl;
851          }
852          else if(_ctvmq.nmassc > _maxmcn) {
853             os << ", which is too many (maximum is " << _maxmcn
854                << ")." << std::endl;
855          }
856          else {
857             os << std::endl << "      Problem with number of mass"
858                << " constraints for unknown reasons." << std::endl;
859          }
860       }
861       else if(_ctvmq.ijkerr[1]==11) {
862          os << "      Vertex " << _ctvmq.ijkerr[2]
863             << " has less than one track." << std::endl;
864       }
865       else if(_ctvmq.ijkerr[1]==12) {
866          os << "      Vertex " << _ctvmq.ijkerr[2]
867             << " is a conversion vertex with a number of tracks"
868             << " different than two." << std::endl;
869       }
870       else if(_ctvmq.ijkerr[1]==13) {
871          os << "      Vertex " << _ctvmq.ijkerr[2]
872             << " is a one track vertex that has no multi-track"
873             << " descendents." << std::endl;
874       }
875       else if(_ctvmq.ijkerr[1]==14) {
876          os << "      Vertex " << _ctvmq.ijkerr[2]
877             << " does not point at a vertex with a lower number."
878             << std::endl;
879       }
880       else if(_ctvmq.ijkerr[1]==15) {
881          os << "      Vertex " << _ctvmq.ijkerr[2]
882             << " has a parent vertex that is a conversion." << std::endl;
883       }
884       else if(_ctvmq.ijkerr[1]==16) {
885          os << "      Vertex " << _ctvmq.ijkerr[2]
886             << " does 1 track pointing to a vertex with"
887             << " more than 1 track." << std::endl;
888       }
889       else if(_ctvmq.ijkerr[1]==17) {
890          os << "      Vertex " << _ctvmq.ijkerr[2]
891             << " does 0 track pointing to a vertex with"
892             << " more than 0 track (?)." << std::endl;
893       }
894       else if(_ctvmq.ijkerr[1]==19) {
895          os << "      Primary vertex error matrix is singular." << std::endl;
896       }
897       else if(_ctvmq.ijkerr[1]==21) {
898          os << "      Track with Id " << _ctvmq.ijkerr[2]
899             << "is not in any vertex." << std::endl;
900       }
901       else if(_ctvmq.ijkerr[1]==22) {
902          os << "      Track with Id " << _ctvmq.ijkerr[2]
903             << "is in multiple vertices." << std::endl;
904       }
905       else if(_ctvmq.ijkerr[1]==23) {
906          os << "      Track with Id " << _ctvmq.ijkerr[2]
907             << "occurs more than once." << std::endl;
908       }
909       else if(_ctvmq.ijkerr[1]==31) {
910          os << "      A mass constraint has less than 2 tracks." << std::endl;
911       }
912       else if(_ctvmq.ijkerr[1]==32) {
913          os << "      The sum masses of the tracks in a mass constraint"
914             << " exceeds the constraint mass." << std::endl;
915       }
916       else if(_ctvmq.ijkerr[1]==33) {
917          os << "      Beamline constraint. Beam covariance not set properly."
918             << " Negative diagonal elements." << std::endl;
919       }
920       else if(_ctvmq.ijkerr[1]==34) {
921          os << "      Beamline constraint. Beam covariance not set properly."
922             << " Off-diagonal elements not zero." << std::endl;
923       }
924       else if(_ctvmq.ijkerr[1]==36) {
925          os << "      Beamline constraint. Number of vertices = " 
926             << _ctvmq.nvertx << " Should be 1." << std::endl;
927       }
928    }
929    else if(_ctvmq.ijkerr[0] == 2) {
930       if(_ctvmq.ijkerr[1] == 20) {
931          os << "   Problem in CTVM00: " << std::endl;
932          os << "      Track has negative Id = "
933             << _ctvmq.list[_ctvmq.ijkerr[2]-1] << "." << std::endl;
934       }
935       else {
936          os << "   Problem in CTVMFA with vertex "
937             << _ctvmq.ijkerr[2] << ": " << std::endl;
938          os << "      Failure in vertex first approximation." << std::endl;
939          if(_ctvmq.ijkerr[1] == 1) {
940             os << "      Tracks are concentric circles." << std::endl;
941          }
942          if(_ctvmq.ijkerr[1] == 2) {
943             os << "      Conversion vertex has widely separated"
944                << " exterior circles at midpoint." << std::endl;
945          }
946          if(_ctvmq.ijkerr[1] == 3) {
947             os << "      Conversion vertex has widely separated"
948                << " interior circles at midpoint." << std::endl;
949          }
950          if(_ctvmq.ijkerr[1] == 4) {
951             os << "      Vertex has widely separated"
952                << " exterior circles at approximate vertex." << std::endl;
953          }
954          if(_ctvmq.ijkerr[1] == 5) {
955             os << "      Vertex has widely separated"
956                << " interior circles at approximate vertex." << std::endl;
957          }
958          if(_ctvmq.ijkerr[1] == 6) {
959             os << "      Rv is too large at the chosen"
960                << " intersection point." << std::endl;
961          }
962          if(_ctvmq.ijkerr[1] == 7) {
963             os << "      Delta z is too large at the chosen"
964                << " intersection point." << std::endl;
965          }
966          if(_ctvmq.ijkerr[1] == 8) {
967             os << "      A track's turning to the chosen vertex"
968                << " is too large." << std::endl;
969          }
970          if(_ctvmq.ijkerr[1] == 9) {
971             os << "      There is no solution with an adequately"
972                << " positive arc length." << std::endl;
973          }
974          if(_ctvmq.ijkerr[1] == 21) {
975             os << "      zero-track vertexing: either/both vertex "
976                << " momenta are too small (<0.01 MeV)." << std::endl;
977          }
978          if(_ctvmq.ijkerr[1] == 22) {
979             os << "      zero-track vertexing: Two lines (tracks) are "
980                << " parallel/antiparallel." << std::endl;
981          }
982 
983       }
984    }
985    else if(_ctvmq.ijkerr[0] == 3) {
986       os << "   Problem in CTVM01 with track with Id = "
987          << _ctvmq.list[_ctvmq.ijkerr[2]-1] << ": " << std::endl;
988       if(_ctvmq.ijkerr[1] == 1) {
989          os << "      GETTRK cannot find Id in list." << std::endl;
990       }
991       if(_ctvmq.ijkerr[1] == 2) {
992          os << "      Covariance matrix could not be inverted."  << endl 
993             << "      Offending track number (in order addded) is "
994             << _ctvmq.ijkerr[2] << "." << std::endl;
995       }
996       if(_ctvmq.ijkerr[1] == 3) {
997          os << "      Track turns through too large an angle"
998             << " to the vertex." << std::endl;
999       }
1000       if(_ctvmq.ijkerr[1] == 4) {
1001          os << "      Track moves too far backward to vertex." << std::endl;
1002       }
1003       if(_ctvmq.ijkerr[1] == 5) {
1004          os << "      Track with curvature > 0.01." << std::endl
1005             << "      Offending track number is "
1006             << _ctvmq.ijkerr[2] << "." << std::endl;
1007       }
1008    }
1009    else if(status() == 9) {
1010       os << "   General fit problem: " << std::endl;
1011       if(_ctvmq.ijkerr[1] == 1) {
1012          os << "      Singular solution matrix." << std::endl;
1013       }
1014       if(_ctvmq.ijkerr[1] == 2 || _ctvmq.ijkerr[1] == 3) {
1015          os << "      Too many iterations ( "
1016             << _ctvmq.ijkerr[2] << "(." << std::endl;
1017       }
1018       if(_ctvmq.ijkerr[1] == 4) {
1019          os << "      Convergence failure." << std::endl;
1020       }
1021       if(_ctvmq.ijkerr[1] == 5) {
1022          os << "      Bad convergence." << std::endl;
1023       }
1024       if(_ctvmq.ijkerr[1] == 9) {
1025          os << "      Ill-formed  covariance matrix." << std::endl;
1026       }
1027    }
1028    else {
1029       os << "   The error codes above are not recognized." << std::endl
1030          << "   Contact VertexFit expert " << _expert << "." << std::endl;
1031    }
1032    return;
1033 }
1034 
1035 
1036 /*=======================================================================

1037                          VertexFit::getIJKErr

1038   =======================================================================*/
1039 
1040 void VertexFit::getIJKErr(int& err0, int& err1, int& err2) const
1041 {
1042   err0 = _ctvmq.ijkerr[0];
1043   err1 = _ctvmq.ijkerr[1];
1044   err2 = _ctvmq.ijkerr[2];
1045   return;
1046 }
1047 
1048 int VertexFit::getIJKErr0() const
1049 {
1050   return _ctvmq.ijkerr[0];
1051 }
1052 int VertexFit::getIJKErr1() const
1053 {
1054   return _ctvmq.ijkerr[1];
1055 }
1056 int VertexFit::getIJKErr2() const
1057 {
1058   return _ctvmq.ijkerr[2];
1059 }
1060 
1061 /*=======================================================================

1062                        VertexFit::getErrTrackId()

1063   =======================================================================*/
1064 
1065 int VertexFit::getErrTrackId() const
1066  {
1067    if (status() == 0) return 0;
1068    int trkId = 0;
1069    // Problems with track in CTVM01 or track has negative id in CTVM00

1070    // See PrintErr() for a more detailed list of error codes.

1071    if ((_ctvmq.ijkerr[0] == 2 && _ctvmq.ijkerr[1] == 20) ||
1072        _ctvmq.ijkerr[0] == 3) {
1073      trkId = _ctvmq.list[_ctvmq.ijkerr[2]-1];
1074    }
1075    
1076    return trkId;
1077  }
1078 
1079 /*=======================================================================

1080                          VertexFit::expert

1081   =======================================================================*/
1082 
1083 string VertexFit::expert() const
1084 {
1085    return _expert;
1086 }
1087 
1088 /*=======================================================================

1089                          VertexFit::status

1090   =======================================================================*/
1091 
1092 int VertexFit::status() const
1093 {
1094 
1095    return stat;
1096 }
1097 
1098 /*=======================================================================

1099                          VertexFit::chisq

1100   =======================================================================*/
1101 
1102 float VertexFit::chisq() const
1103 {
1104 // Chi-square of fit

1105       return _ctvmq.chisqr[0];
1106 }
1107 
1108 /*=======================================================================

1109                          VertexFit::ndof

1110   =======================================================================*/
1111 
1112 int VertexFit::ndof() const
1113 {
1114 // Number of degrees of freedom of fit.

1115    if(_ctvmq.chisqr[0] >= 0) {
1116       return _ctvmq.ndof; }
1117    else {
1118       return 0;}
1119 }
1120 
1121 /*=======================================================================

1122                          VertexFit::prob

1123   =======================================================================*/
1124 
1125 float VertexFit::prob() const
1126 {
1127 // Probability of chi-square of fit

1128    if(_ctvmq.chisqr[0]>=0.) {
1129       float chisq=_ctvmq.chisqr[0];
1130       int nd=_ctvmq.ndof;
1131       return prob_(chisq,nd);
1132    }
1133    else {
1134       return -999.;
1135    }
1136 }
1137 
1138 /*=======================================================================

1139                          VertexFit::chisq(CdfTrack*)

1140   =======================================================================*/
1141 
1142 float VertexFit::chisq(const CdfTrack* trk) const
1143 {
1144 // This method returns the chisquare contribution for one track 

1145 // If fit not successful or not done yet, return -1.

1146    if(_ctvmq.chisqr[0] < 0) return -1.;
1147 // Look for this track in the list of tracks.

1148    for(int jt = 0; jt < _ctvmq.ntrack; ++jt) {
1149      if(trk->id().value() == _ctvmq.list[jt]) {
1150 // Found the track, so return its chisquare contribution.

1151        return _ctvmq.chit[jt];
1152      }
1153    }
1154 // If track is not in list, return -1.

1155    return -1.;
1156 }
1157 
1158 /*=======================================================================

1159                          VertexFit::chisq_rphi()

1160   =======================================================================*/
1161 
1162 float VertexFit::chisq_rphi() const
1163 {
1164 // This method returns the chisquare contribution in the r-phi plane.

1165    int index[3] = {0,1,3};
1166 // If fit not successful or not done yet, return -1.

1167    if(_ctvmq.chisqr[0] < 0) return -1.;
1168 // Loop over the tracks in the event.

1169    float chisq = 0.;
1170    for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
1171 // Double loop over the relevant parameter indices.

1172      for(int k1=0; k1<3; ++k1) {
1173        for(int k2=0; k2<3; ++k2) {
1174 // Add contribution to chisquare.

1175          chisq += _ctvmq.pardif[jt][index[k1]] *
1176                   _ctvmq.g[jt][index[k1]][index[k2]] *
1177                   _ctvmq.pardif[jt][index[k2]];
1178        }
1179      }
1180    }
1181 // Return the chisquare.

1182    return chisq;
1183 }
1184 
1185 
1186 /*=======================================================================

1187                          VertexFit::chisq_z()

1188   =======================================================================*/
1189 
1190 float VertexFit::chisq_z() const
1191 {
1192 // This method returns the chisquare contribution in the z direction.

1193    int index[2] = {2,4};
1194 // If fit not successful or not done yet, return -1.

1195    if(_ctvmq.chisqr[0] < 0) return -1.;
1196 // Loop over the tracks in the event.

1197    float chisq = 0.;
1198    for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
1199 // Double loop over the relevant parameter indices.

1200      for(int k1=0; k1<2; ++k1) {
1201        for(int k2=0; k2<2; ++k2) {
1202 // Add contribution to chisquare.

1203          chisq += _ctvmq.pardif[jt][index[k1]] *
1204                   _ctvmq.g[jt][index[k1]][index[k2]] *
1205                   _ctvmq.pardif[jt][index[k2]];
1206        }
1207      }
1208    }
1209 // Return the chisquare.

1210    return chisq;
1211 }
1212 
1213 
1214 /*=======================================================================

1215                          VertexFit::chisq_rphiz()

1216   =======================================================================*/
1217 
1218 float VertexFit::chisq_rphiz() const
1219 {
1220 // This method returns the chisquare contribution of the cross

1221 // terms in the r-phi and z directions.

1222    int index1[2] = {2,4};
1223    int index2[3] = {0,1,3};
1224 // If fit not successful or not done yet, return -1.

1225    if(_ctvmq.chisqr[0] < 0) return -1.;
1226 // Loop over the tracks in the event.

1227    float chisq = 0.;
1228    for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
1229 // Double loop over the relevant parameter indices.

1230      for(int k1=0; k1<2; ++k1) {
1231        for(int k2=0; k2<3; ++k2) {
1232 // Add contribution to chisquare.

1233          chisq += _ctvmq.pardif[jt][index1[k1]] *
1234                   _ctvmq.g[jt][index1[k1]][index2[k2]] *
1235                   _ctvmq.pardif[jt][index2[k2]];
1236        }
1237      }
1238    }
1239 // Return the chisquare.

1240    return 2.*chisq;
1241 }
1242 
1243 /*=======================================================================

1244                          VertexFit::chisq_rphi(CdfTrack*)

1245   =======================================================================*/
1246 
1247 float VertexFit::chisq_rphi(const CdfTrack* trk) const
1248 {
1249 // This method returns the chisquare contribution in the r-phi plane.

1250    int index[3] = {0,1,3};
1251 // If fit not successful or not done yet, return -1.

1252    if(_ctvmq.chisqr[0] < 0) return -1.;
1253 // Loop over the tracks in the event, looking for the one we want

1254    for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
1255      if(trk->id().value() == _ctvmq.list[jt]) {
1256 // Found the track, so calculate its chisquare contribution.

1257        float chisq = 0.;
1258 // Double loop over the relevant parameter indices.

1259        for(int k1=0; k1<3; ++k1) {
1260          for(int k2=0; k2<3; ++k2) {
1261 // Add contribution to chisquare.

1262            chisq += _ctvmq.pardif[jt][index[k1]] *
1263                     _ctvmq.g[jt][index[k1]][index[k2]] *
1264                     _ctvmq.pardif[jt][index[k2]];
1265          }
1266        }
1267        return chisq;
1268      }
1269    }
1270 // Track not found, return -1.

1271    return -1.;
1272 }
1273 
1274 
1275 /*=======================================================================

1276                          VertexFit::chisq_z(CdfTrack*)

1277   =======================================================================*/
1278 
1279 float VertexFit::chisq_z(const CdfTrack* trk) const
1280 {
1281 // This method returns the chisquare contribution in the z direction.

1282    int index[2] = {2,4};
1283 // If fit not successful or not done yet, return -1.

1284    if(_ctvmq.chisqr[0] < 0) return -1.;
1285 // Loop over the tracks in the event, looking for the one we want.

1286    for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
1287      if(trk->id().value() == _ctvmq.list[jt]) {
1288 // Found the track, so calculate its chisquare contribution.

1289        float chisq = 0.;
1290 // Double loop over the relevant parameter indices.

1291        for(int k1=0; k1<2; ++k1) {
1292          for(int k2=0; k2<2; ++k2) {
1293 // Add contribution to chisquare.

1294            chisq += _ctvmq.pardif[jt][index[k1]] *
1295                     _ctvmq.g[jt][index[k1]][index[k2]] *
1296                     _ctvmq.pardif[jt][index[k2]];
1297          }
1298        }
1299        return chisq;
1300      }
1301    }
1302 // Track not found - return -1.

1303    return -1.;
1304 }
1305 
1306 
1307 /*=======================================================================

1308                          VertexFit::chisq_rphiz(CdfTrack*)

1309   =======================================================================*/
1310 
1311 float VertexFit::chisq_rphiz(const CdfTrack* trk) const
1312 {
1313 // This method returns the chisquare contribution of the cross

1314 // terms in the r-phi and z directions.

1315    int index1[2] = {2,4};
1316    int index2[3] = {0,1,3};
1317 // If fit not successful or not done yet, return -1.

1318    if(_ctvmq.chisqr[0] < 0) return -1.;
1319 // Loop over the tracks in the event.

1320    for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
1321      if(trk->id().value() == _ctvmq.list[jt]) {
1322 // Found the track, so calculate its chisquare contribution.

1323        float chisq = 0.;
1324 // Double loop over the relevant parameter indices.

1325        for(int k1=0; k1<2; ++k1) {
1326          for(int k2=0; k2<3; ++k2) {
1327 // Add contribution to chisquare.

1328            chisq += _ctvmq.pardif[jt][index1[k1]] *
1329                     _ctvmq.g[jt][index1[k1]][index2[k2]] *
1330                     _ctvmq.pardif[jt][index2[k2]];
1331          }
1332        }
1333        return 2.*chisq;
1334      }
1335    }
1336 // Track not found so return -1.

1337    return -1.;
1338 }
1339 
1340 /*=======================================================================

1341                          VertexFit::getTrackP4

1342   =======================================================================*/
1343 
1344 HepLorentzVector VertexFit::getTrackP4(const CdfTrack* trk) const
1345 {
1346    if(stat != 0) return HepLorentzVector(0,0,0,0);
1347 // return four momentum of fit track 

1348    for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
1349 //   Find which track matches this Id.

1350       if(trk->id().value()==_ctvmq.list[jt]) {
1351          HepLorentzVector p4((double)_ctvmq.trkp4[0][jt],
1352                              (double)_ctvmq.trkp4[1][jt],
1353                              (double)_ctvmq.trkp4[2][jt],
1354                              (double)_ctvmq.trkp4[3][jt]);
1355          return p4;
1356       }
1357    }
1358    return HepLorentzVector(0,0,0,0);
1359 }
1360 
1361 /*=======================================================================

1362                          VertexFit::getHelix

1363   =======================================================================*/
1364 
1365 Helix VertexFit::getHelix(const CdfTrack* trk) const
1366 {
1367    if(stat != 0) return Helix(0,0,0,0,0);
1368 // return helix parameters of fit track 

1369    for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
1370 //   Find which track matches this Id.

1371       if(trk->id().value()==_ctvmq.list[jt]) {
1372          Helix trhelix((double)_ctvmq.par[jt][2],
1373                        (double)_ctvmq.par[jt][0],
1374                        (double)_ctvmq.par[jt][4],
1375                        (double)_ctvmq.par[jt][3],
1376                        (double)_ctvmq.par[jt][1]);
1377          return trhelix;
1378       }
1379    }
1380    return Helix(0,0,0,0,0);
1381 }
1382 
1383 /*=======================================================================

1384                          VertexFit::getMass

1385   =======================================================================*/
1386 
1387 float VertexFit::getMass(const CdfTrack* trk1,
1388                          const CdfTrack* trk2, float& dmass) const
1389 {
1390 
1391 //

1392 // Vertex Fitting is prone to floating point errors.  Here, we

1393 // turn those off during the duration of this routine: Joe and Farrukh

1394 //

1395 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1396   struct sigaction myaction = {VertexFitSetStatus, 0, 0, 0}, oldaction;
1397   sigaction(SIGFPE, &myaction, &oldaction);
1398   if (setjmp(env)!=0) {
1399     sigaction(SIGFPE, &oldaction,0);
1400     return -999;
1401   }
1402 #endif
1403 
1404    dmass=-999.;
1405    if(stat!=0) return -999.;
1406 // Get the fit invariant mass of tracks trk1 and trk2.

1407 // dmass is the error on the mass.

1408    int ntrk=2;
1409    const CdfTrack* trks[2];
1410    trks[0]=trk1;
1411    trks[1]=trk2;
1412 
1413   double result = getMass(ntrk,trks,dmass);
1414    //return something for FPE Protection-> Joe and Farrukh

1415 
1416 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1417   sigaction(SIGFPE, &oldaction,0);
1418 #endif
1419 
1420   return result;
1421 }
1422 
1423 float VertexFit::getMass(const CdfTrack* trk1, const CdfTrack* trk2,
1424                                 const CdfTrack* trk3,float& dmass) const
1425 {
1426 
1427 //

1428 // Vertex Fitting is prone to floating point errors.  Here, we

1429 // turn those off during the duration of this routine: Joe and Farrukh

1430 //

1431 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1432   struct sigaction myaction = {VertexFitSetStatus, 0, 0, 0}, oldaction;
1433   sigaction(SIGFPE, &myaction, &oldaction);
1434   if (setjmp(env)!=0) {
1435     sigaction(SIGFPE, &oldaction,0);
1436     return -999;
1437   }
1438 #endif
1439 
1440 
1441 
1442    dmass=-999.;
1443    if(stat!=0) return -999.;
1444 // Get the fit invariant mass of tracks trk1, trk2, and trk3.

1445 // dmass is the error on the mass.

1446    int ntrk=3;
1447    const CdfTrack* trks[3];
1448    trks[0]=trk1;
1449    trks[1]=trk2;
1450    trks[2]=trk3;
1451 
1452 
1453    double result = getMass(ntrk,trks,dmass);
1454 
1455 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1456   sigaction(SIGFPE, &oldaction,0);
1457 #endif
1458 
1459   return result;
1460 }
1461 
1462 float VertexFit::getMass(const CdfTrack* trk1, const CdfTrack* trk2,
1463      const CdfTrack* trk3, const CdfTrack* trk4, float& dmass) const
1464 {
1465    dmass=-999.;
1466    if(stat!=0) return -999.;
1467 // Get the fit invariant mass of tracks trk1, trk2, trk3, and trk4.

1468 // dmass is the error on the mass.

1469    int ntrk=4;
1470    const CdfTrack* trks[4];
1471    trks[0]=trk1;
1472    trks[1]=trk2;
1473    trks[2]=trk3;
1474    trks[3]=trk4;
1475 //

1476 // Vertex Fitting is prone to floating point errors.  Here, we

1477 // turn those off during the duration of this routine: Joe and Farrukh

1478 //

1479 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1480   struct sigaction myaction = {VertexFitSetStatus, 0, 0, 0}, oldaction;
1481   sigaction(SIGFPE, &myaction, &oldaction);
1482   if (setjmp(env)!=0) {
1483     sigaction(SIGFPE, &oldaction,0);
1484     return -999;
1485   }
1486 #endif
1487 
1488   double result = getMass(ntrk,trks,dmass);
1489 
1490    //return something for FPE Protection-> Joe and Farrukh

1491 
1492 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1493   sigaction(SIGFPE, &oldaction,0);
1494 #endif
1495 
1496   return result;
1497 }
1498 
1499 float VertexFit::getMass(int ntrk, const CdfTrack* tracks[],
1500                                                 float& dmass) const
1501 {
1502 
1503 // Vertex Fitting is prone to floating point errors.  Here, we

1504 // turn those off during the duration of this routine: Joe and Farrukh

1505 //

1506 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1507   struct sigaction myaction = {VertexFitSetStatus, 0, 0, 0}, oldaction;
1508   sigaction(SIGFPE, &myaction, &oldaction);
1509   if (setjmp(env)!=0) {
1510     sigaction(SIGFPE, &oldaction,0);
1511     return -999;
1512   }
1513 #endif
1514 
1515    dmass=-999.;
1516    if(stat!=0) return -999.;
1517 // Get fit invariant mass of ntrk tracks listed in array tracks.

1518 // dmass is the error on the mass.

1519    dmass=-999.;
1520    if(ntrk <= 0) return 0;
1521    int jtrks[_maxtrk];
1522    for(int jt=0; jt<ntrk; ++jt) {
1523       bool found=false;
1524       for(int kt=0; kt<_ctvmq.ntrack; ++kt) {
1525          if(tracks[jt]->id().value()==_ctvmq.list[kt]) {
1526             found=true;
1527             jtrks[jt]=kt+1;
1528          }
1529       }
1530       if(!found) return 0;
1531    }
1532 // Copy information into CTVMFT common blocks

1533    *_ctvmq_com=_ctvmq;
1534    *_ctvmfr_com=_ctvmfr;
1535    int ntr=ntrk;
1536    float mass;
1537    double p4[4];
1538    mcalc_(ntr, jtrks, mass, dmass, p4);
1539 
1540    //return something for FPE-> Joe and Farrukh

1541 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1542   sigaction(SIGFPE, &oldaction,0);
1543 #endif
1544 
1545    return mass;
1546 }
1547 
1548 /*=======================================================================

1549                          VertexFit::getDecayLength

1550   =======================================================================*/
1551 
1552 float VertexFit::getDecayLength(vertexNumber nv, vertexNumber mv, 
1553                                 const Hep3Vector& dir, float& dlerr) const
1554 {
1555    dlerr=-999.;
1556    if(stat!=0) return -999.;
1557 // Get the signed decay length from vertex nv to vertex mv

1558 // along the x-y direction defined by the 3 vector dir.

1559 // dlerr is the error on the decay length including the

1560 // full error matrix.

1561 // Check that vertices are within range.

1562    if(nv<0 || nv>=_ctvmq.nvertx) return -999.;
1563    if(mv<1 || mv>_ctvmq.nvertx) return -999.;
1564    if(nv>=mv) return -999.;
1565    float dir_t=sqrt(dir.x()*dir.x()+dir.y()*dir.y());
1566    if(dir_t <= 0.) return -999.;
1567    Hep3Vector dv=getVertex(mv)-getVertex(nv);
1568    float dl=(dv.x()*dir.x()+dv.y()*dir.y())/dir_t;
1569 // Set up the column matrix of derivatives

1570    HepMatrix A(4,1);
1571    A(1,1)=dir.x()/dir_t;
1572    A(2,1)=dir.y()/dir_t;
1573    A(3,1)=-dir.x()/dir_t;
1574    A(4,1)=-dir.y()/dir_t;
1575 // Check if first vertex (nv) is primary vertex.  If it is,

1576 // check if it was used in the primary vertex.  If not,

1577 // all of the corresponding error matrix elements are those

1578 // supplied for the primary vertex.

1579    int nvf=0;
1580    if(nv==0) {
1581       nvf=-1;
1582       for(int jv=0; jv<_ctvmq.nvertx; ++jv) {
1583          if(_ctvmq.vtxpnt[0][jv]==0) nvf=0;
1584       }
1585    }
1586 // Get the relevant submatrix of the full error matrix.

1587    HepMatrix V(4,4,0);
1588    if(nvf < 0) {
1589       V(1,1)=getErrorMatrix(_ctvmq.voff[mv-1]+1,_ctvmq.voff[mv-1]+1);
1590       V(1,2)=getErrorMatrix(_ctvmq.voff[mv-1]+1,_ctvmq.voff[mv-1]+2);
1591       V(2,1)=getErrorMatrix(_ctvmq.voff[mv-1]+2,_ctvmq.voff[mv-1]+1);
1592       V(2,2)=getErrorMatrix(_ctvmq.voff[mv-1]+2,_ctvmq.voff[mv-1]+2);
1593       V(3,3)=_ctvmq.exyzpv[0][0];
1594       V(3,4)=_ctvmq.exyzpv[0][1];
1595       V(4,3)=_ctvmq.exyzpv[1][0];
1596       V(4,4)=_ctvmq.exyzpv[1][1];
1597    }
1598    else {
1599 //    Get the indices into the error matrix vmat

1600       int index[4]={_ctvmq.voff[mv-1]+1,_ctvmq.voff[mv-1]+2,0,0};
1601       if(nv==0) {
1602          index[2]=1;
1603          index[3]=2;
1604       }
1605       else {
1606         index[2] = _ctvmq.voff[nv-1]+1;
1607         index[3] = _ctvmq.voff[nv-1]+2;
1608       }
1609       for(int j=0; j<4; ++j) {
1610          for(int k=0; k<4; ++k) {
1611             V[j][k]=getErrorMatrix(index[j],index[k]);
1612          }
1613       }
1614    }
1615 // Calculate square of dlerr

1616    dlerr=(A.T()*V*A)(1,1);
1617    if(dlerr >= 0.) {
1618       dlerr=sqrt(dlerr);
1619    }
1620    else {
1621       dlerr=-sqrt(-dlerr);
1622    }
1623 
1624    return dl;
1625 }
1626 
1627 /*=======================================================================

1628                          VertexFit::get_dr

1629   =======================================================================*/
1630 
1631 float VertexFit::get_dr(vertexNumber nv, vertexNumber mv,
1632                                            float& drerr) const
1633 {
1634    drerr=-999.;
1635    if(stat!=0) return -999.;
1636 // Get the transvese distance between vertices nv and mv

1637 // and return it as the function value.  drerr is the

1638 // uncertainty on the transverse distance, calculated from the

1639 // full error matrix including correlations.

1640    float dxyz[3];
1641    float dr;
1642    float dz;
1643    float dl[3];
1644 
1645    int mvert=mv;
1646    int nvert=nv;
1647 // Copy information into CTVMFT common blocks

1648    *_ctvmq_com=_ctvmq;
1649    *_ctvmfr_com=_ctvmfr;
1650 // Do calculation

1651    dcalc_(mvert,nvert,dxyz,dr,dz,dl);
1652    drerr=dl[0];
1653    return dr;
1654 }
1655 
1656 /*=======================================================================

1657                          VertexFit::get_dz

1658   =======================================================================*/
1659 
1660 float VertexFit::get_dz(vertexNumber nv, vertexNumber mv,
1661                                              float& dzerr) const
1662 {
1663    dzerr=-999.;
1664    if(stat!=0) return -999.;
1665 // Get the longitudinal distance between vertices nv and mv

1666 // and return it as the function value.  dzerr is the

1667 // uncertainty on the longitudinal distance, calculated from the

1668 // full error matrix including correlations.

1669    float dxyz[3];
1670    float dr;
1671    float dz;
1672    float dl[3];
1673 
1674    int mvert=mv;
1675    int nvert=nv;
1676 // Copy information into CTVMFT common blocks

1677    *_ctvmq_com=_ctvmq;
1678    *_ctvmfr_com=_ctvmfr;
1679 // Do calculation

1680    dcalc_(mvert,nvert,dxyz,dr,dz,dl);
1681    dzerr=dl[1];
1682    return dz;
1683 }
1684 
1685 /*=======================================================================

1686                          VertexFit::getVertex

1687   =======================================================================*/
1688 
1689 Hep3Vector VertexFit::getVertex(vertexNumber nv) const
1690 {
1691    if(stat!=0) return -999.;
1692 // Return x,y,z position of vertex nv.

1693    if(nv<0 || nv>_ctvmq.nvertx) return Hep3Vector(0,0,0);
1694 // Check if first vertex (nv) is primary vertex.  If it is,

1695 // check if it was used in the primary vertex.  If not,

1696 // all of the corresponding error matrix elements are those

1697 // supplied for the primary vertex.

1698    int nvf=0;
1699    if(nv==0) {
1700       nvf=-1;
1701       for(int jv=0; jv<_ctvmq.nvertx; ++jv) {
1702          if(_ctvmq.vtxpnt[0][jv]==0) nvf=0;
1703       }
1704    }
1705    Hep3Vector vertex;
1706 // If primary vertex was not part of fit, take vertex

1707 // location as supplied.

1708    if(nvf < 0) {
1709       vertex.setX(_ctvmq.xyzpv0[0]);
1710       vertex.setY(_ctvmq.xyzpv0[1]);
1711       vertex.setZ(_ctvmq.xyzpv0[2]);
1712    }
1713    else{
1714       vertex.setX(_ctvmq.xyzvrt[nv][0]);
1715       vertex.setY(_ctvmq.xyzvrt[nv][1]);
1716       vertex.setZ(_ctvmq.xyzvrt[nv][2]);
1717    }
1718 // If we have a different reference point, need to add it back in

1719    vertex += _referencePoint;
1720    return vertex;
1721 }
1722 
1723 /*=======================================================================

1724                          VertexFit::getErrorMatrix

1725   =======================================================================*/
1726 
1727 double VertexFit::getErrorMatrix(int j, int k) const
1728 {
1729    if(stat!=0) return -999.;
1730 // Return the j,k element of the full error matrix VMAT.

1731 // Since the CTVMFT documentation assumes the indices

1732 // start from 1 (ala Fortran), we will also assume this

1733 // and convert the C++ indices.  Note also the that order of

1734 // Fortran and C++ indices is different.  We assume that

1735 // j and k are in the Fortran order.

1736    if(j<1 || k<1 || j>_maxdim+1 || k>_maxdim) {
1737       return -999.;
1738    }
1739    return _ctvmfr.vmat[k-1][j-1];
1740 }
1741 
1742 HepSymMatrix VertexFit::getErrorMatrix(VertexFit::vertexNumber nv) const 
1743 {  
1744 // Return errors for vertex nv.

1745 
1746   HepSymMatrix cov(3,0);
1747   
1748 // If this is the primary vertex, return the error matrix the

1749 // user supplied.

1750   if(nv==PRIMARY_VERTEX) {
1751     for(int j=0; j<3; j++)
1752       for(int k=0; k<3; k++) 
1753         cov[j][k] = _ctvmq.exyzpv[j][k];
1754     return cov;
1755   }
1756   
1757   if(stat!=0) return cov;
1758 // Return x,y,z position of vertex nv.

1759   if(nv<VERTEX_1 || nv>_ctvmq.nvertx) return cov;
1760 // get offset for vertex nv

1761   int voff = _ctvmq.voff[nv-1];
1762 // fill matrix

1763   for(int i = 0 ; i < 3 ; ++i)
1764     for(int j = i ; j < 3 ; ++j)
1765       cov[i][j] = _ctvmfr.vmat[voff+i][voff+j];
1766   return cov;
1767 }
1768 
1769 HepSymMatrix VertexFit::getErrorMatrix(const CdfTrack* trk) const 
1770 {
1771   HepSymMatrix cov(3,0);
1772   if (stat != 0) return cov;
1773 
1774   for (int nt=0; nt<_ctvmq.ntrack; ++nt) {
1775 
1776     // Find which track matches this Id

1777     if (trk->id().value() == _ctvmq.list[nt]) {
1778 
1779       // Position of track nt get offset for track nt

1780       int toff = _ctvmq.toff[nt];
1781 
1782       // Fill matrix -- Crv,Phi,Ctg

1783       for(int i = 0 ; i < 3 ; ++i)
1784         for(int j = i ; j < 3 ; ++j)
1785           cov[i][j] = _ctvmfr.vmat[toff+i][toff+j];
1786     }
1787   }
1788   return cov;
1789 }
1790 
1791 float VertexFit::getPtError(const CdfTrack* trk) const
1792 {  
1793   if (stat != 0) return 0;
1794   
1795   int   toff;
1796   float pt,curv,curvErr,ptErr;
1797 
1798   for (int nt=0; nt<_ctvmq.ntrack; ++nt) {
1799 
1800     // Find which track matches this Id

1801     if (trk->id().value() == _ctvmq.list[nt]) {
1802 
1803       // Position of track nt get offset for track nt

1804       toff = _ctvmq.toff[nt];
1805 
1806       // Curvature error

1807       pt      = sqrt(_ctvmq.trkp4[0][nt]*_ctvmq.trkp4[0][nt] +
1808                      _ctvmq.trkp4[1][nt]*_ctvmq.trkp4[1][nt]);
1809       curv    = _ctvmq.pscale/pt;
1810       curvErr = sqrt(_ctvmfr.vmat[toff+0][toff+0]);
1811       ptErr   = _ctvmq.pscale/curv/curv*curvErr;
1812       return ptErr;
1813     }
1814   }
1815 
1816   return 0;
1817 }
1818 
1819 /*=======================================================================

1820                          VertexFit::getPosMomErr

1821   =======================================================================*/
1822 void VertexFit::getPosMomErr(HepMatrix& errors) const
1823 {
1824   // A c++ rewrite of the FORTRAN MASSAG function

1825   // The result of this function is an error matrix in position-momentum basis.

1826   // A 7x7 matrix of errors where the rows/columns are x, y, z, px, py, pz, e.

1827 
1828   double cosph[_maxtrk];
1829   double sinph[_maxtrk];
1830   double cosdph[_maxtrk];
1831   double sindph[_maxtrk];
1832   Hep3Vector mom3[_maxtrk];
1833   HepLorentzVector pmom[_maxtrk];
1834   HepLorentzVector total_mom;
1835 
1836   for(int lvtx = 0; lvtx < _ctvmq.nvertx; lvtx++){
1837     for(int ltrk = 0; ltrk < _ctvmq.ntrack; ltrk++){
1838       if(!_ctvmq.trkvtx[lvtx][ltrk]) continue;
1839       cosph[ltrk] = cos(_ctvmq.par[ltrk][1]);
1840       sinph[ltrk] = sin(_ctvmq.par[ltrk][1]);
1841       double dphi = 0;
1842       sindph[ltrk] = 2 * _ctvmq.par[ltrk][0] * 
1843        (_ctvmq.xyzvrt[lvtx + 1][0] * cosph[ltrk] + 
1844         _ctvmq.xyzvrt[lvtx + 1][1] * sinph[ltrk]);
1845       cosdph[ltrk] = sqrt(1.0 - sindph[ltrk] * sindph[ltrk]);
1846       if(fabs(sindph[ltrk]) <= 1.0){
1847         dphi = asin(sindph[ltrk]);
1848       }
1849       double pt = _ctvmq.pscale * fabs(1./_ctvmq.par[ltrk][0]);
1850       mom3[ltrk].setX(pt * cos(_ctvmq.par[ltrk][1] + dphi));
1851       mom3[ltrk].setY(pt * sin(_ctvmq.par[ltrk][1] + dphi));
1852       mom3[ltrk].setZ(pt * _ctvmq.par[ltrk][2]);
1853       double e  = sqrt(_ctvmq.tmass[ltrk] * _ctvmq.tmass[ltrk] 
1854                        + mom3[ltrk].mag2());
1855       pmom[ltrk].setVect(mom3[ltrk]);
1856       pmom[ltrk].setE(e);
1857 
1858       total_mom += pmom[ltrk];
1859     }
1860   }
1861 
1862 // Easy so far, but now it gets ugly.

1863 // Fill dp_dpar with the derivatives of the position and momentum with respect

1864 // to the parameters.

1865 
1866   int ctvmft_dim = 3 * (_ctvmq.nvertx + _ctvmq.ntrack);
1867   HepMatrix deriv(ctvmft_dim, 7, 0);
1868   HepMatrix dp_dpar[_maxvtx] = {deriv, deriv, deriv};
1869 
1870 // Fill the x, y, z rows: 

1871 
1872   for(int nvtx = 0; nvtx < _ctvmq.nvertx; nvtx++){
1873     for(int lcomp = 0; lcomp < 3; lcomp++){
1874       dp_dpar[nvtx][(3 * nvtx) + lcomp][lcomp] = 1.0;
1875     }
1876 
1877 // Fill the px, py, pz, e rows:

1878 
1879     for(int lvtx = 0; lvtx < _ctvmq.nvertx; lvtx++){
1880       for(int ltrk = 0; ltrk < _ctvmq.ntrack; ltrk++){
1881         if(!_ctvmq.trkvtx[lvtx][ltrk]) continue;
1882 
1883 // Find the derivatives of dphi with respect to x, y, curvature, and phi0:

1884 
1885         double dphi_dx = 2.0 * _ctvmq.par[ltrk][0] * cosph[ltrk]/cosdph[ltrk];
1886         double dphi_dy = 2.0 * _ctvmq.par[ltrk][0] * sinph[ltrk]/cosdph[ltrk];
1887         double dphi_dc = 2.0 * 
1888           (_ctvmq.xyzvrt[lvtx + 1][0] * cosph[ltrk] + 
1889            _ctvmq.xyzvrt[lvtx + 1][1] * sinph[ltrk])/cosdph[ltrk];
1890         double dphi_dp = 2.0 * _ctvmq.par[ltrk][0] *
1891           (-_ctvmq.xyzvrt[lvtx + 1][0] * sinph[ltrk] + 
1892             _ctvmq.xyzvrt[lvtx + 1][1] * cosph[ltrk])/cosdph[ltrk];
1893 
1894 // Now load the derivative matrix

1895 
1896         int lvele = 3 * lvtx;
1897 // dPx/dx:

1898         dp_dpar[nvtx][lvele][3] += -pmom[ltrk].y() * dphi_dx;
1899 // dPy/dx:

1900         dp_dpar[nvtx][lvele][4] +=  pmom[ltrk].x() * dphi_dx;
1901 // dPz/dx:

1902         dp_dpar[nvtx][lvele][5]  = 0.; 
1903 // dPy/dx:

1904         dp_dpar[nvtx][lvele][6]  = 0.; 
1905 
1906         lvele++;
1907 // dPx/dy:

1908         dp_dpar[nvtx][lvele][3] += -pmom[ltrk].y() * dphi_dy;
1909 // dPy/dy:

1910         dp_dpar[nvtx][lvele][4] +=  pmom[ltrk].x() * dphi_dy;
1911 // dPz/dy:

1912         dp_dpar[nvtx][lvele][5]  = 0.; 
1913 // dE/dy:

1914         dp_dpar[nvtx][lvele][6]  = 0.; 
1915 
1916         lvele++;
1917 // dPx/dz:

1918         dp_dpar[nvtx][lvele][3]  = 0.;
1919 // dPy/dz:

1920         dp_dpar[nvtx][lvele][4]  = 0.;
1921 // dPz/dz:

1922         dp_dpar[nvtx][lvele][5]  = 0.; 
1923 // dE/dz:

1924         dp_dpar[nvtx][lvele][6]  = 0.; 
1925 
1926         lvele = 3 * (ltrk + _ctvmq.nvertx);
1927 // dPx/dcurv[ltrk]:

1928         dp_dpar[nvtx][lvele][3]  = -(pmom[ltrk].x()/_ctvmq.par[ltrk][0])
1929                                    - pmom[ltrk].y() * dphi_dc;
1930 // dPy/dcurv[ltrk]:

1931         dp_dpar[nvtx][lvele][4]  = -(pmom[ltrk].y()/_ctvmq.par[ltrk][0])
1932                                    + pmom[ltrk].x() * dphi_dc;
1933 // dPz/dcurv[ltrk]:

1934         dp_dpar[nvtx][lvele][5]  = -(pmom[ltrk].z()/_ctvmq.par[ltrk][0]); 
1935 // dE/dcurv[ltrk]:

1936         dp_dpar[nvtx][lvele][6]  = 
1937           -mom3[ltrk].mag2()/(_ctvmq.par[ltrk][0] * pmom[ltrk].e()); 
1938 
1939         lvele++;
1940 // dPx/dphi[ltrk]:

1941         dp_dpar[nvtx][lvele][3]  = -pmom[ltrk].y() * (1.0 + dphi_dp);
1942 // dPy/dphi[ltrk]:

1943         dp_dpar[nvtx][lvele][4]  =  pmom[ltrk].x() * (1.0 + dphi_dp);
1944 // dPz/dphi[ltrk]:

1945         dp_dpar[nvtx][lvele][5]  = 0.;
1946 // dE/dphi[ltrk]:

1947         dp_dpar[nvtx][lvele][6]  = 0.;
1948 
1949         lvele++;
1950 // dPx/dcot[ltrk]:

1951         dp_dpar[nvtx][lvele][3]  = 0;
1952 // dPy/dcot[ltrk]:

1953         dp_dpar[nvtx][lvele][4]  = 0;
1954 // dPz/dcot[ltrk]:

1955         dp_dpar[nvtx][lvele][5]  = pmom[ltrk].perp();
1956 // dE/dcot[ltrk]:

1957         dp_dpar[nvtx][lvele][6]  = 
1958          pmom[ltrk].perp2() * _ctvmq.par[ltrk][2] / pmom[ltrk].e();
1959       }
1960     }
1961   }
1962 // Now calculate the new error matrix

1963 
1964   // Extract the interesting bits from VMAT.

1965 
1966   HepMatrix vmat(ctvmft_dim,ctvmft_dim,0);
1967   for(int lpar = 0; lpar < ctvmft_dim; lpar++){
1968     int l = lpar%3;
1969     int lvele = 0;
1970     if(lpar < 3  * _ctvmq.nvertx){
1971       int lvtx = lpar/3;
1972       lvele = _ctvmq.voff[lvtx] + l;
1973     }
1974     else{
1975       int ltrk = (lpar - 3 * _ctvmq.nvertx)/3;
1976       lvele = _ctvmq.toff[ltrk] + l;
1977     }
1978     for(int kpar = 0; kpar < ctvmft_dim; kpar++){ 
1979       int k = kpar%3;
1980       int kvele = 0;
1981       if(kpar < 3  * _ctvmq.nvertx){
1982         int kvtx = kpar/3;
1983         kvele = _ctvmq.voff[kvtx] + k;
1984       }
1985       else{
1986         int ktrk = (kpar - 3 * _ctvmq.nvertx)/3;
1987         kvele = _ctvmq.toff[ktrk] + k;
1988       }
1989       vmat[kpar][lpar] = _ctvmfr.vmat[kvele][lvele];
1990     }
1991   }
1992   //  Just about done

1993   HepMatrix ans(7,7,0);
1994   HepMatrix answer[_maxvtx] = {ans, ans, ans};
1995   for(int nvtx = 0; nvtx < _ctvmq.nvertx; nvtx++){
1996     answer[nvtx] = (dp_dpar[nvtx].T() * vmat) * dp_dpar[nvtx];
1997   }
1998   errors = answer[0];
1999 }
2000 
2001 /*=======================================================================

2002                          VertexFit::vOff

2003   =======================================================================*/
2004 int VertexFit::vOff(vertexNumber jv) const
2005 { if(jv < VERTEX_1 || jv > _maxvtx) {return -999;}
2006   else {return _ctvmq.voff[jv-1];}
2007 }
2008 
2009 /*=======================================================================

2010                          VertexFit::tOff

2011   =======================================================================*/
2012 int VertexFit::tOff(const CdfTrack* trk) const
2013 { for(int kt=0; kt<_ctvmq.ntrack; ++kt) {
2014     if(trk->id().value()==_ctvmq.list[kt]) return _ctvmq.toff[kt];
2015   }
2016   return -999;
2017 }
2018 
2019 /*=======================================================================

2020                          VertexFit::pOff

2021   =======================================================================*/
2022 int VertexFit::pOff(int lp) const
2023 { if(lp < 1) {
2024     return -999;
2025   }
2026   else return _ctvmq.poff[lp-1];
2027 }
2028 
2029 /*=======================================================================

2030                          VertexFit::cOff

2031   =======================================================================*/
2032 int VertexFit::cOff(int lc) const
2033 { if(lc < 1) {
2034     return -999;
2035   }
2036   else return _ctvmq.coff[lc-1];
2037 }
2038 
2039 /*=======================================================================

2040                          VertexFit::mOff

2041   =======================================================================*/
2042 int VertexFit::mOff() const
2043 { return _ctvmq.moff; }
2044 
2045 /*=======================================================================

2046                          VertexFit::VMat

2047   =======================================================================*/
2048 double VertexFit::VMat(int i, int j) const
2049 { if(i <0 || j < 0) {return -999.;}
2050   else return _ctvmfr.vmat[i][j];
2051 }
2052 
2053 /*=======================================================================

2054                          VertexFit::allocateVertexNumber

2055   =======================================================================*/
2056 
2057 // Facilitates CandNode recursion.  CandNodes have no way of deciding

2058 // which vertex they are, and these trivial functions help them do that.

2059 VertexFit::vertexNumber VertexFit::allocateVertexNumber()
2060 {
2061   if ((_currentAllocatedVertexNumber < PRIMARY_VERTEX) ||
2062       (_currentAllocatedVertexNumber > _maxvtx)) {
2063     std::cout << "VertexFit::allocateVertexNumber: out of range!" << std::endl;
2064     return PRIMARY_VERTEX;
2065   }
2066   return vertexNumber(++_currentAllocatedVertexNumber);
2067 }
2068 
2069 void VertexFit::resetAllocatedVertexNumber()
2070 {
2071   _currentAllocatedVertexNumber = 0;
2072 }
2073 
2074 /*=======================================================================

2075                          VertexFit::restoreFromCommons()

2076   =======================================================================*/
2077 
2078 void VertexFit::restoreFromCommons() {
2079         stat=0;
2080         _ctvmq_com  = (CTVMQ*) ctvmq_address_();
2081         _ctvmfr_com = (CTVMFR*) ctvmfr_address_();
2082         _fiddle_com = (FIDDLE*) fiddle_address_();
2083         _trkprm_com = (TRKPRM*) trkprm_address_();
2084         _ctvmq  = *_ctvmq_com;
2085         _ctvmfr = *_ctvmfr_com;
2086         _fiddle = *_fiddle_com;
2087         _trkprm = *_trkprm_com;
2088 }
2089 
2090 
2091 /*=======================================================================

2092                          VertexFit::setTrackReferencePoint

2093   =======================================================================*/
2094 void VertexFit::setTrackReferencePoint( const Hep3Vector & ref )
2095 {
2096   // Set extrapolation flag

2097   _extrapolateTrackErrors = true; 
2098   // Keep new reference point

2099   _referencePoint = ref;
2100   // Keep track of old primary vertex in CDF coordinates

2101   _cdfPrimaryVertex = _primaryVertex;
2102   // Set new primary vertex relative to new reference point

2103   setPrimaryVertex( _cdfPrimaryVertex - _referencePoint);
2104 }
2105 
2106 /*=======================================================================

2107                          VertexFit::moveReferencePoint()

2108   =======================================================================*/
2109 
2110 void VertexFit::moveReferencePoint( HepVector & v,
2111                                     HepSymMatrix & m ) {
2112 
2113   // Move the reference point of the track to _referencePoint

2114   if ( !_extrapolateTrackErrors ) 
2115     return;
2116   
2117   TrackExtrapolator e;
2118 
2119   // Modifies v and m

2120   e.moveReferencePoint( v, m, _referencePoint );
2121 }
2122 
2123 
2124 #endif  /* VERTEXFIT_CC */
2125 
2126 

source navigation ] diff markup ] identifier search ] freetext search ] file search ]

This page was automatically generated by the LXR engine.
The LXR team
Valid HTML 4.01!

Send problems or questions to cdfcode@fnal.gov