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 "TrackingUserHL/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 
246    HepVector w = trk->par();
247    HepSymMatrix m = trk->getHelixFit().getErrorMatrix();
248    if ( _extrapolateTrackErrors ) {
249      // This will move the reference point

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

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

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

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

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

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

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

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

285 
286 /*=======================================================================

287                          VertexFit::addTrack

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

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

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

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

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

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

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

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

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

342                          VertexFit::vertexPoint_2d

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

348 // that the vertices are unique.

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

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

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

361                          VertexFit::vertexPoint_3d

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

367 // that the vertices are distinct.

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

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

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

379                          VertexFit::vertexPoint_1track

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

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

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

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

396                          VertexFit::vertexPoint_0track

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

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

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

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

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

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

409   // this case)

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

412   // of subroutines: ctvmft and ctvmfa

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

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

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

422 
423    return true;
424 }//vertexPoint_0track

425 
426 /*=======================================================================

427                          VertexFit::conversion_2d

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

440                          VertexFit::conversion_3d

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

453                          VertexFit::massConstrain

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

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

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

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

499 // list of tracks.

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

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

518                      VertexFit::beamlineConstraint

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

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

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

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

524 // just one track in input.

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

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

527 // Enable beamlineConstraint by setting the pointing constraint variable

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

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

530 // Provide the beamline parameters:

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

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

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

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

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

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

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

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

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

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

541 //      All other elements should be 0

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

543 //                 Franco Bedeschi bed@fnal.gov 

544 // See more information in the ctvmft.f

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

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

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

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

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

578                          VertexFit::setPrimaryVertex

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

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

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

604                          VertexFit::setPrimaryVertexError

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

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

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

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

632                          VertexFit::fit

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

638 //are positive.

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

643       if(_trkprm.trem[trk][j][j] < 0.) {
644         mstat = false;
645 // Record offending track

646         _ctvmq.ijkerr[2] = trk + 1;
647       }
648     }
649   }
650   if(!mstat) {
651 // Tell user that the covariance matrix could not be inverted.

652     _ctvmq.ijkerr[0] = 3;
653     _ctvmq.ijkerr[1] = 2;
654     stat = 1;
655     return false;
656   }
657 
658 // First copy information into CTVMFT common blocks

659    *_ctvmq_com=_ctvmq;
660    *_ctvmfr_com=_ctvmfr;
661    *_fiddle_com=_fiddle;
662    *_trkprm_com=_trkprm;
663 // Do the vertex fit.

664    int print=0;
665    int level=0;
666    ctvmft_(print,level,stat);
667 // Now copy information from CTVMFT common blocks to local storage

668    _ctvmq=*_ctvmq_com;
669    _ctvmfr=*_ctvmfr_com;
670    _fiddle=*_fiddle_com;
671    _trkprm=*_trkprm_com;
672    
673    return stat==0;
674 }
675 
676 /*=======================================================================

677                          VertexFit::print

678   =======================================================================*/
679 
680 void VertexFit::print() const
681 {
682    print(std::cout);
683 }
684 
685 void VertexFit::print(std::ostream& os) const
686 {
687    os << "****************************** VertexFit "
688       << "******************************" << std::endl;
689    os << "Number of tracks: " << _ctvmq.ntrack << std::endl;
690    os << "   Tracks: ";
691    for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
692       if(jt != 0) os << ",  ";
693       CdfTrack::Id trkId(_ctvmq.list[jt]);
694       os << trkId;
695    }
696    os << std::endl;
697    os << "Number of vertices: " << _ctvmq.nvertx << std::endl;
698    for(int jv=0; jv<_ctvmq.nvertx; ++jv) {
699       os << "   Vertex " << jv+1 << " tracks: ";
700       for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
701          if(_ctvmq.trkvtx[jv][jt]) {
702             os << " " << _ctvmq.list[jt];
703          }
704       }
705       os << std::endl;
706    }
707    for(int jv=0; jv<_ctvmq.nvertx; ++jv) {
708       if(_ctvmq.vtxpnt[0][jv]==0) {
709          os << "   Vertex " << jv+1 << " points to the primary vertex ";
710       }
711       else if(_ctvmq.vtxpnt[0][jv]>0) {
712          os << "   Vertex " << jv+1 << " points to vertex "
713               << _ctvmq.vtxpnt[0][jv];
714       }
715       if(_ctvmq.vtxpnt[1][jv]==1) {
716          os << " in 2 dimensions" << std::endl;
717       }
718       else if(_ctvmq.vtxpnt[1][jv]==2) {
719          os << " in 3 dimensions" << std::endl;
720       }
721       else if(_ctvmq.vtxpnt[1][jv]==3) {
722          os << ", a single track vertex" << std::endl;
723       }
724       if(_ctvmq.cvtx[jv]>0) {
725          os << "   Vertex " << jv+1 << " is a conversion" << std::endl;
726       }
727    }
728    os << "Number of mass constraints: " << _ctvmq.nmassc << std::endl;
729    for(int jmc=0; jmc<_ctvmq.nmassc; ++jmc) {
730       os << "   Tracks ";
731       for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
732          if(_ctvmq.trkmcn[jmc][jt]) {
733             os << " " << _ctvmq.list[jt];
734          }
735       }
736       os << " constrained to mass " << _ctvmq.cmass[jmc]
737          << " Gev/c^2" << std::endl;
738    }
739    if(stat==-999) {
740       os << "No fit has been done." << std::endl;
741    }
742    else {
743       os << "***** Results of Fit *****" << std::endl;
744       printErr(os);
745       os << "   Status = " << stat << std::endl;
746       os << "   Chi-square = " << _ctvmq.chisqr[0]
747          << " for " << _ctvmq.ndof << " degrees of freedom." << std::endl;
748       os << "   => probability = " << prob() << std::endl;
749       for(int jv=0; jv<_ctvmq.nvertx; ++jv) {
750          os << "Vertex " << jv+1 << " position: "
751             << _ctvmq.xyzvrt[jv+1][0] << " "
752             << _ctvmq.xyzvrt[jv+1][1] << " "
753             << _ctvmq.xyzvrt[jv+1][2] << std::endl;
754       }
755       for(int jt=0; jt<_ctvmq.ntrack; ++jt) {
756          os << "Track " << _ctvmq.list[jt] << " P4: " 
757             << _ctvmq.trkp4[0][jt] << " "
758             << _ctvmq.trkp4[1][jt] << " "
759             << _ctvmq.trkp4[2][jt] << " "
760             << _ctvmq.trkp4[3][jt] << " " << std::endl;
761       }
762    }
763    os << "****************************************"
764       << "**************************" << std::endl;
765 
766    return;
767 }
768 
769 /*=======================================================================

770                          VertexFit::printErr

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

1008                          VertexFit::getIJKErr

1009   =======================================================================*/
1010 
1011 void VertexFit::getIJKErr(int& err0, int& err1, int& err2) const
1012 {
1013   err0 = _ctvmq.ijkerr[0];
1014   err1 = _ctvmq.ijkerr[1];
1015   err2 = _ctvmq.ijkerr[2];
1016   return;
1017 }
1018 
1019 int VertexFit::getIJKErr0() const
1020 {
1021   return _ctvmq.ijkerr[0];
1022 }
1023 int VertexFit::getIJKErr1() const
1024 {
1025   return _ctvmq.ijkerr[1];
1026 }
1027 int VertexFit::getIJKErr2() const
1028 {
1029   return _ctvmq.ijkerr[2];
1030 }
1031 
1032 /*=======================================================================

1033                        VertexFit::getErrTrackId()

1034   =======================================================================*/
1035 
1036 int VertexFit::getErrTrackId() const
1037  {
1038    if (status() == 0) return 0;
1039    int trkId = 0;
1040    // Problems with track in CTVM01 or track has negative id in CTVM00

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

1042    if ((_ctvmq.ijkerr[0] == 2 && _ctvmq.ijkerr[1] == 20) ||
1043        _ctvmq.ijkerr[0] == 3) {
1044      trkId = _ctvmq.list[_ctvmq.ijkerr[2]-1];
1045    }
1046    
1047    return trkId;
1048  }
1049 
1050 /*=======================================================================

1051                          VertexFit::expert

1052   =======================================================================*/
1053 
1054 string VertexFit::expert() const
1055 {
1056    return _expert;
1057 }
1058 
1059 /*=======================================================================

1060                          VertexFit::status

1061   =======================================================================*/
1062 
1063 int VertexFit::status() const
1064 {
1065 
1066    return stat;
1067 }
1068 
1069 /*=======================================================================

1070                          VertexFit::chisq

1071   =======================================================================*/
1072 
1073 float VertexFit::chisq() const
1074 {
1075 // Chi-square of fit

1076       return _ctvmq.chisqr[0];
1077 }
1078 
1079 /*=======================================================================

1080                          VertexFit::ndof

1081   =======================================================================*/
1082 
1083 int VertexFit::ndof() const
1084 {
1085 // Number of degrees of freedom of fit.

1086    if(_ctvmq.chisqr[0] >= 0) {
1087       return _ctvmq.ndof; }
1088    else {
1089       return 0;}
1090 }
1091 
1092 /*=======================================================================

1093                          VertexFit::prob

1094   =======================================================================*/
1095 
1096 float VertexFit::prob() const
1097 {
1098 // Probability of chi-square of fit

1099    if(_ctvmq.chisqr[0]>=0.) {
1100       float chisq=_ctvmq.chisqr[0];
1101       int nd=_ctvmq.ndof;
1102       return prob_(chisq,nd);
1103    }
1104    else {
1105       return -999.;
1106    }
1107 }
1108 
1109 /*=======================================================================

1110                          VertexFit::chisq(CdfTrack*)

1111   =======================================================================*/
1112 
1113 float VertexFit::chisq(const CdfTrack* trk) const
1114 {
1115 // This method returns the chisquare contribution for one track 

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

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

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

1122        return _ctvmq.chit[jt];
1123      }
1124    }
1125 // If track is not in list, return -1.

1126    return -1.;
1127 }
1128 
1129 /*=======================================================================

1130                          VertexFit::chisq_rphi()

1131   =======================================================================*/
1132 
1133 float VertexFit::chisq_rphi() const
1134 {
1135 // This method returns the chisquare contribution in the r-phi plane.

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

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

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

1143      for(int k1=0; k1<3; ++k1) {
1144        for(int k2=0; k2<3; ++k2) {
1145 // Add contribution to chisquare.

1146          chisq += _ctvmq.pardif[jt][index[k1]] *
1147                   _ctvmq.g[jt][index[k1]][index[k2]] *
1148                   _ctvmq.pardif[jt][index[k2]];
1149        }
1150      }
1151    }
1152 // Return the chisquare.

1153    return chisq;
1154 }
1155 
1156 
1157 /*=======================================================================

1158                          VertexFit::chisq_z()

1159   =======================================================================*/
1160 
1161 float VertexFit::chisq_z() const
1162 {
1163 // This method returns the chisquare contribution in the z direction.

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

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

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

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

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

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

1186                          VertexFit::chisq_rphiz()

1187   =======================================================================*/
1188 
1189 float VertexFit::chisq_rphiz() const
1190 {
1191 // This method returns the chisquare contribution of the cross

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

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

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

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

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

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

1211    return 2.*chisq;
1212 }
1213 
1214 /*=======================================================================

1215                          VertexFit::chisq_rphi(CdfTrack*)

1216   =======================================================================*/
1217 
1218 float VertexFit::chisq_rphi(const CdfTrack* trk) const
1219 {
1220 // This method returns the chisquare contribution in the r-phi plane.

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

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

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

1228        float chisq = 0.;
1229 // Double loop over the relevant parameter indices.

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

1233            chisq += _ctvmq.pardif[jt][index[k1]] *
1234                     _ctvmq.g[jt][index[k1]][index[k2]] *
1235                     _ctvmq.pardif[jt][index[k2]];
1236          }
1237        }
1238        return chisq;
1239      }
1240    }
1241 // Track not found, return -1.

1242    return -1.;
1243 }
1244 
1245 
1246 /*=======================================================================

1247                          VertexFit::chisq_z(CdfTrack*)

1248   =======================================================================*/
1249 
1250 float VertexFit::chisq_z(const CdfTrack* trk) const
1251 {
1252 // This method returns the chisquare contribution in the z direction.

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

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

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

1260        float chisq = 0.;
1261 // Double loop over the relevant parameter indices.

1262        for(int k1=0; k1<2; ++k1) {
1263          for(int k2=0; k2<2; ++k2) {
1264 // Add contribution to chisquare.

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

1274    return -1.;
1275 }
1276 
1277 
1278 /*=======================================================================

1279                          VertexFit::chisq_rphiz(CdfTrack*)

1280   =======================================================================*/
1281 
1282 float VertexFit::chisq_rphiz(const CdfTrack* trk) const
1283 {
1284 // This method returns the chisquare contribution of the cross

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

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

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

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

1294        float chisq = 0.;
1295 // Double loop over the relevant parameter indices.

1296        for(int k1=0; k1<2; ++k1) {
1297          for(int k2=0; k2<3; ++k2) {
1298 // Add contribution to chisquare.

1299            chisq += _ctvmq.pardif[jt][index1[k1]] *
1300                     _ctvmq.g[jt][index1[k1]][index2[k2]] *
1301                     _ctvmq.pardif[jt][index2[k2]];
1302          }
1303        }
1304        return 2.*chisq;
1305      }
1306    }
1307 // Track not found so return -1.

1308    return -1.;
1309 }
1310 
1311 /*=======================================================================

1312                          VertexFit::getTrackP4

1313   =======================================================================*/
1314 
1315 HepLorentzVector VertexFit::getTrackP4(const CdfTrack* trk) const
1316 {
1317    if(stat != 0) return HepLorentzVector(0,0,0,0);
1318 // return four momentum of fit track 

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

1321       if(trk->id().value()==_ctvmq.list[jt]) {
1322          HepLorentzVector p4((double)_ctvmq.trkp4[0][jt],
1323                              (double)_ctvmq.trkp4[1][jt],
1324                              (double)_ctvmq.trkp4[2][jt],
1325                              (double)_ctvmq.trkp4[3][jt]);
1326          return p4;
1327       }
1328    }
1329    return HepLorentzVector(0,0,0,0);
1330 }
1331 
1332 /*=======================================================================

1333                          VertexFit::getHelix

1334   =======================================================================*/
1335 
1336 Helix VertexFit::getHelix(const CdfTrack* trk) const
1337 {
1338    if(stat != 0) return Helix(0,0,0,0,0);
1339 // return helix parameters of fit track 

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

1342       if(trk->id().value()==_ctvmq.list[jt]) {
1343          Helix trhelix((double)_ctvmq.par[jt][2],
1344                        (double)_ctvmq.par[jt][0],
1345                        (double)_ctvmq.par[jt][4],
1346                        (double)_ctvmq.par[jt][3],
1347                        (double)_ctvmq.par[jt][1]);
1348          return trhelix;
1349       }
1350    }
1351    return Helix(0,0,0,0,0);
1352 }
1353 
1354 /*=======================================================================

1355                          VertexFit::getMass

1356   =======================================================================*/
1357 
1358 float VertexFit::getMass(const CdfTrack* trk1,
1359                          const CdfTrack* trk2, float& dmass) const
1360 {
1361 
1362 //

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

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

1365 //

1366 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1367   struct sigaction myaction = {VertexFitSetStatus, 0, 0, 0}, oldaction;
1368   sigaction(SIGFPE, &myaction, &oldaction);
1369   if (setjmp(env)!=0) {
1370     sigaction(SIGFPE, &oldaction,0);
1371     return -999;
1372   }
1373 #endif
1374 
1375    dmass=-999.;
1376    if(stat!=0) return -999.;
1377 // Get the fit invariant mass of tracks trk1 and trk2.

1378 // dmass is the error on the mass.

1379    int ntrk=2;
1380    const CdfTrack* trks[2];
1381    trks[0]=trk1;
1382    trks[1]=trk2;
1383 
1384   double result = getMass(ntrk,trks,dmass);
1385    //return something for FPE Protection-> Joe and Farrukh

1386 
1387 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1388   sigaction(SIGFPE, &oldaction,0);
1389 #endif
1390 
1391   return result;
1392 }
1393 
1394 float VertexFit::getMass(const CdfTrack* trk1, const CdfTrack* trk2,
1395                                 const CdfTrack* trk3,float& dmass) const
1396 {
1397 
1398 //

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

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

1401 //

1402 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1403   struct sigaction myaction = {VertexFitSetStatus, 0, 0, 0}, oldaction;
1404   sigaction(SIGFPE, &myaction, &oldaction);
1405   if (setjmp(env)!=0) {
1406     sigaction(SIGFPE, &oldaction,0);
1407     return -999;
1408   }
1409 #endif
1410 
1411 
1412 
1413    dmass=-999.;
1414    if(stat!=0) return -999.;
1415 // Get the fit invariant mass of tracks trk1, trk2, and trk3.

1416 // dmass is the error on the mass.

1417    int ntrk=3;
1418    const CdfTrack* trks[3];
1419    trks[0]=trk1;
1420    trks[1]=trk2;
1421    trks[2]=trk3;
1422 
1423 
1424    double result = getMass(ntrk,trks,dmass);
1425 
1426 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1427   sigaction(SIGFPE, &oldaction,0);
1428 #endif
1429 
1430   return result;
1431 }
1432 
1433 float VertexFit::getMass(const CdfTrack* trk1, const CdfTrack* trk2,
1434      const CdfTrack* trk3, const CdfTrack* trk4, float& dmass) const
1435 {
1436    dmass=-999.;
1437    if(stat!=0) return -999.;
1438 // Get the fit invariant mass of tracks trk1, trk2, trk3, and trk4.

1439 // dmass is the error on the mass.

1440    int ntrk=4;
1441    const CdfTrack* trks[4];
1442    trks[0]=trk1;
1443    trks[1]=trk2;
1444    trks[2]=trk3;
1445    trks[3]=trk4;
1446 //

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

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

1449 //

1450 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1451   struct sigaction myaction = {VertexFitSetStatus, 0, 0, 0}, oldaction;
1452   sigaction(SIGFPE, &myaction, &oldaction);
1453   if (setjmp(env)!=0) {
1454     sigaction(SIGFPE, &oldaction,0);
1455     return -999;
1456   }
1457 #endif
1458 
1459   double result = getMass(ntrk,trks,dmass);
1460 
1461    //return something for FPE Protection-> Joe and Farrukh

1462 
1463 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1464   sigaction(SIGFPE, &oldaction,0);
1465 #endif
1466 
1467   return result;
1468 }
1469 
1470 float VertexFit::getMass(int ntrk, const CdfTrack* tracks[],
1471                                                 float& dmass) const
1472 {
1473 
1474 // Vertex Fitting is prone to floating point errors.  Here, we

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

1476 //

1477 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1478   struct sigaction myaction = {VertexFitSetStatus, 0, 0, 0}, oldaction;
1479   sigaction(SIGFPE, &myaction, &oldaction);
1480   if (setjmp(env)!=0) {
1481     sigaction(SIGFPE, &oldaction,0);
1482     return -999;
1483   }
1484 #endif
1485 
1486    dmass=-999.;
1487    if(stat!=0) return -999.;
1488 // Get fit invariant mass of ntrk tracks listed in array tracks.

1489 // dmass is the error on the mass.

1490    dmass=-999.;
1491    if(ntrk <= 0) return 0;
1492    int jtrks[_maxtrk];
1493    for(int jt=0; jt<ntrk; ++jt) {
1494       bool found=false;
1495       for(int kt=0; kt<_ctvmq.ntrack; ++kt) {
1496          if(tracks[jt]->id().value()==_ctvmq.list[kt]) {
1497             found=true;
1498             jtrks[jt]=kt+1;
1499          }
1500       }
1501       if(!found) return 0;
1502    }
1503 // Copy information into CTVMFT common blocks

1504    *_ctvmq_com=_ctvmq;
1505    *_ctvmfr_com=_ctvmfr;
1506    int ntr=ntrk;
1507    float mass;
1508    double p4[4];
1509    mcalc_(ntr, jtrks, mass, dmass, p4);
1510 
1511    //return something for FPE-> Joe and Farrukh

1512 #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
1513   sigaction(SIGFPE, &oldaction,0);
1514 #endif
1515 
1516    return mass;
1517 }
1518 
1519 /*=======================================================================

1520                          VertexFit::getDecayLength

1521   =======================================================================*/
1522 
1523 float VertexFit::getDecayLength(vertexNumber nv, vertexNumber mv, 
1524                                 const Hep3Vector& dir, float& dlerr) const
1525 {
1526    dlerr=-999.;
1527    if(stat!=0) return -999.;
1528 // Get the signed decay length from vertex nv to vertex mv

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

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

1531 // full error matrix.

1532 // Check that vertices are within range.

1533    if(nv<0 || nv>=_ctvmq.nvertx) return -999.;
1534    if(mv<1 || mv>_ctvmq.nvertx) return -999.;
1535    if(nv>=mv) return -999.;
1536    float dir_t=sqrt(dir.x()*dir.x()+dir.y()*dir.y());
1537    if(dir_t <= 0.) return -999.;
1538    Hep3Vector dv=getVertex(mv)-getVertex(nv);
1539    float dl=(dv.x()*dir.x()+dv.y()*dir.y())/dir_t;
1540 // Set up the column matrix of derivatives

1541    HepMatrix A(4,1);
1542    A(1,1)=dir.x()/dir_t;
1543    A(2,1)=dir.y()/dir_t;
1544    A(3,1)=-dir.x()/dir_t;
1545    A(4,1)=-dir.y()/dir_t;
1546 // Check if first vertex (nv) is primary vertex.  If it is,

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

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

1549 // supplied for the primary vertex.

1550    int nvf=0;
1551    if(nv==0) {
1552       nvf=-1;
1553       for(int jv=0; jv<_ctvmq.nvertx; ++jv) {
1554          if(_ctvmq.vtxpnt[0][jv]==0) nvf=0;
1555       }
1556    }
1557 // Get the relevant submatrix of the full error matrix.

1558    HepMatrix V(4,4,0);
1559    if(nvf < 0) {
1560       V(1,1)=getErrorMatrix(_ctvmq.voff[mv-1]+1,_ctvmq.voff[mv-1]+1);
1561       V(1,2)=getErrorMatrix(_ctvmq.voff[mv-1]+1,_ctvmq.voff[mv-1]+2);
1562       V(2,1)=getErrorMatrix(_ctvmq.voff[mv-1]+2,_ctvmq.voff[mv-1]+1);
1563       V(2,2)=getErrorMatrix(_ctvmq.voff[mv-1]+2,_ctvmq.voff[mv-1]+2);
1564       V(3,3)=_ctvmq.exyzpv[0][0];
1565       V(3,4)=_ctvmq.exyzpv[0][1];
1566       V(4,3)=_ctvmq.exyzpv[1][0];
1567       V(4,4)=_ctvmq.exyzpv[1][1];
1568    }
1569    else {
1570 //    Get the indices into the error matrix vmat

1571       int index[4]={_ctvmq.voff[mv-1]+1,_ctvmq.voff[mv-1]+2,0,0};
1572       if(nv==0) {
1573          index[2]=1;
1574          index[3]=2;
1575       }
1576       else {
1577         index[2] = _ctvmq.voff[nv-1]+1;
1578         index[3] = _ctvmq.voff[nv-1]+2;
1579       }
1580       for(int j=0; j<4; ++j) {
1581          for(int k=0; k<4; ++k) {
1582             V[j][k]=getErrorMatrix(index[j],index[k]);
1583          }
1584       }
1585    }
1586 // Calculate square of dlerr

1587    dlerr=(A.T()*V*A)(1,1);
1588    if(dlerr >= 0.) {
1589       dlerr=sqrt(dlerr);
1590    }
1591    else {
1592       dlerr=-sqrt(-dlerr);
1593    }
1594 
1595    return dl;
1596 }
1597 
1598 /*=======================================================================

1599                          VertexFit::get_dr

1600   =======================================================================*/
1601 
1602 float VertexFit::get_dr(vertexNumber nv, vertexNumber mv,
1603                                            float& drerr) const
1604 {
1605    drerr=-999.;
1606    if(stat!=0) return -999.;
1607 // Get the transvese distance between vertices nv and mv

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

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

1610 // full error matrix including correlations.

1611    float dxyz[3];
1612    float dr;
1613    float dz;
1614    float dl[3];
1615 
1616    int mvert=mv;
1617    int nvert=nv;
1618 // Copy information into CTVMFT common blocks

1619    *_ctvmq_com=_ctvmq;
1620    *_ctvmfr_com=_ctvmfr;
1621 // Do calculation

1622    dcalc_(mvert,nvert,dxyz,dr,dz,dl);
1623    drerr=dl[0];
1624    return dr;
1625 }
1626 
1627 /*=======================================================================

1628                          VertexFit::get_dz

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

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

1638 // uncertainty on the longitudinal 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    dzerr=dl[1];
1653    return dz;
1654 }
1655 
1656 /*=======================================================================

1657                          VertexFit::getVertex

1658   =======================================================================*/
1659 
1660 Hep3Vector VertexFit::getVertex(vertexNumber nv) const
1661 {
1662    if(stat!=0) return -999.;
1663 // Return x,y,z position of vertex nv.

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

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

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

1668 // supplied for the primary vertex.

1669    int nvf=0;
1670    if(nv==0) {
1671       nvf=-1;
1672       for(int jv=0; jv<_ctvmq.nvertx; ++jv) {
1673          if(_ctvmq.vtxpnt[0][jv]==0) nvf=0;
1674       }
1675    }
1676    Hep3Vector vertex;
1677 // If primary vertex was not part of fit, take vertex

1678 // location as supplied.

1679    if(nvf < 0) {
1680       vertex.setX(_ctvmq.xyzpv0[0]);
1681       vertex.setY(_ctvmq.xyzpv0[1]);
1682       vertex.setZ(_ctvmq.xyzpv0[2]);
1683    }
1684    else{
1685       vertex.setX(_ctvmq.xyzvrt[nv][0]);
1686       vertex.setY(_ctvmq.xyzvrt[nv][1]);
1687       vertex.setZ(_ctvmq.xyzvrt[nv][2]);
1688    }
1689 // If we have a different reference point, need to add it back in

1690    vertex += _referencePoint;
1691    return vertex;
1692 }
1693 
1694 /*=======================================================================

1695                          VertexFit::getErrorMatrix

1696   =======================================================================*/
1697 
1698 double VertexFit::getErrorMatrix(int j, int k) const
1699 {
1700    if(stat!=0) return -999.;
1701 // Return the j,k element of the full error matrix VMAT.

1702 // Since the CTVMFT documentation assumes the indices

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

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

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

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

1707    if(j<1 || k<1 || j>_maxdim+1 || k>_maxdim) {
1708       return -999.;
1709    }
1710    return _ctvmfr.vmat[k-1][j-1];
1711 }
1712 
1713 HepSymMatrix VertexFit::getErrorMatrix(VertexFit::vertexNumber nv) const 
1714 {  
1715 // Return errors for vertex nv.

1716 
1717   HepSymMatrix cov(3,0);
1718   
1719 // If this is the primary vertex, return the error matrix the

1720 // user supplied.

1721   if(nv==PRIMARY_VERTEX) {
1722     for(int j=0; j<3; j++)
1723       for(int k=0; k<3; k++) 
1724         cov[j][k] = _ctvmq.exyzpv[j][k];
1725     return cov;
1726   }
1727   
1728   if(stat!=0) return cov;
1729 // Return x,y,z position of vertex nv.

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

1732   int voff = _ctvmq.voff[nv-1];
1733 // fill matrix

1734   for(int i = 0 ; i < 3 ; ++i)
1735     for(int j = i ; j < 3 ; ++j)
1736       cov[i][j] = _ctvmfr.vmat[voff+i][voff+j];
1737   return cov;
1738 }
1739 
1740 HepSymMatrix VertexFit::getErrorMatrix(const CdfTrack* trk) const 
1741 {
1742   HepSymMatrix cov(3,0);
1743   if (stat != 0) return cov;
1744 
1745   for (int nt=0; nt<_ctvmq.ntrack; ++nt) {
1746 
1747     // Find which track matches this Id

1748     if (trk->id().value() == _ctvmq.list[nt]) {
1749 
1750       // Position of track nt get offset for track nt

1751       int toff = _ctvmq.toff[nt];
1752 
1753       // Fill matrix -- Crv,Phi,Ctg

1754       for(int i = 0 ; i < 3 ; ++i)
1755         for(int j = i ; j < 3 ; ++j)
1756           cov[i][j] = _ctvmfr.vmat[toff+i][toff+j];
1757     }
1758   }
1759   return cov;
1760 }
1761 
1762 float VertexFit::getPtError(const CdfTrack* trk) const
1763 {  
1764   if (stat != 0) return 0;
1765   
1766   int   toff;
1767   float pt,curv,curvErr,ptErr;
1768 
1769   for (int nt=0; nt<_ctvmq.ntrack; ++nt) {
1770 
1771     // Find which track matches this Id

1772     if (trk->id().value() == _ctvmq.list[nt]) {
1773 
1774       // Position of track nt get offset for track nt

1775       toff = _ctvmq.toff[nt];
1776 
1777       // Curvature error

1778       pt      = sqrt(_ctvmq.trkp4[0][nt]*_ctvmq.trkp4[0][nt] +
1779                      _ctvmq.trkp4[1][nt]*_ctvmq.trkp4[1][nt]);
1780       curv    = _ctvmq.pscale/pt;
1781       curvErr = sqrt(_ctvmfr.vmat[toff+0][toff+0]);
1782       ptErr   = _ctvmq.pscale/curv/curv*curvErr;
1783       return ptErr;
1784     }
1785   }
1786 
1787   return 0;
1788 }
1789 
1790 /*=======================================================================

1791                          VertexFit::getPosMomErr

1792   =======================================================================*/
1793 void VertexFit::getPosMomErr(HepMatrix& errors) const
1794 {
1795   // A c++ rewrite of the FORTRAN MASSAG function

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

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

1798 
1799   double cosph[_maxtrk];
1800   double sinph[_maxtrk];
1801   double cosdph[_maxtrk];
1802   double sindph[_maxtrk];
1803   Hep3Vector mom3[_maxtrk];
1804   HepLorentzVector pmom[_maxtrk];
1805   HepLorentzVector total_mom;
1806 
1807   for(int lvtx = 0; lvtx < _ctvmq.nvertx; lvtx++){
1808     for(int ltrk = 0; ltrk < _ctvmq.ntrack; ltrk++){
1809       if(!_ctvmq.trkvtx[lvtx][ltrk]) continue;
1810       cosph[ltrk] = cos(_ctvmq.par[ltrk][1]);
1811       sinph[ltrk] = sin(_ctvmq.par[ltrk][1]);
1812       double dphi = 0;
1813       sindph[ltrk] = 2 * _ctvmq.par[ltrk][0] * 
1814        (_ctvmq.xyzvrt[lvtx + 1][0] * cosph[ltrk] + 
1815         _ctvmq.xyzvrt[lvtx + 1][1] * sinph[ltrk]);
1816       cosdph[ltrk] = sqrt(1.0 - sindph[ltrk] * sindph[ltrk]);
1817       if(fabs(sindph[ltrk]) <= 1.0){
1818         dphi = asin(sindph[ltrk]);
1819       }
1820       double pt = _ctvmq.pscale * fabs(1./_ctvmq.par[ltrk][0]);
1821       mom3[ltrk].setX(pt * cos(_ctvmq.par[ltrk][1] + dphi));
1822       mom3[ltrk].setY(pt * sin(_ctvmq.par[ltrk][1] + dphi));
1823       mom3[ltrk].setZ(pt * _ctvmq.par[ltrk][2]);
1824       double e  = sqrt(_ctvmq.tmass[ltrk] * _ctvmq.tmass[ltrk] 
1825                        + mom3[ltrk].mag2());
1826       pmom[ltrk].setVect(mom3[ltrk]);
1827       pmom[ltrk].setE(e);
1828 
1829       total_mom += pmom[ltrk];
1830     }
1831   }
1832 
1833 // Easy so far, but now it gets ugly.

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

1835 // to the parameters.

1836 
1837   int ctvmft_dim = 3 * (_ctvmq.nvertx + _ctvmq.ntrack);
1838   HepMatrix deriv(ctvmft_dim, 7, 0);
1839   HepMatrix dp_dpar[_maxvtx] = {deriv, deriv, deriv};
1840 
1841 // Fill the x, y, z rows: 

1842 
1843   for(int nvtx = 0; nvtx < _ctvmq.nvertx; nvtx++){
1844     for(int lcomp = 0; lcomp < 3; lcomp++){
1845       dp_dpar[nvtx][(3 * nvtx) + lcomp][lcomp] = 1.0;
1846     }
1847 
1848 // Fill the px, py, pz, e rows:

1849 
1850     for(int lvtx = 0; lvtx < _ctvmq.nvertx; lvtx++){
1851       for(int ltrk = 0; ltrk < _ctvmq.ntrack; ltrk++){
1852         if(!_ctvmq.trkvtx[lvtx][ltrk]) continue;
1853 
1854 // Find the derivatives of dphi with respect to x, y, curvature, and phi0:

1855 
1856         double dphi_dx = 2.0 * _ctvmq.par[ltrk][0] * cosph[ltrk]/cosdph[ltrk];
1857         double dphi_dy = 2.0 * _ctvmq.par[ltrk][0] * sinph[ltrk]/cosdph[ltrk];
1858         double dphi_dc = 2.0 * 
1859           (_ctvmq.xyzvrt[lvtx + 1][0] * cosph[ltrk] + 
1860            _ctvmq.xyzvrt[lvtx + 1][1] * sinph[ltrk])/cosdph[ltrk];
1861         double dphi_dp = 2.0 * _ctvmq.par[ltrk][0] *
1862           (-_ctvmq.xyzvrt[lvtx + 1][0] * sinph[ltrk] + 
1863             _ctvmq.xyzvrt[lvtx + 1][1] * cosph[ltrk])/cosdph[ltrk];
1864 
1865 // Now load the derivative matrix

1866 
1867         int lvele = 3 * lvtx;
1868 // dPx/dx:

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

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

1873         dp_dpar[nvtx][lvele][5]  = 0.; 
1874 // dPy/dx:

1875         dp_dpar[nvtx][lvele][6]  = 0.; 
1876 
1877         lvele++;
1878 // dPx/dy:

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

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

1883         dp_dpar[nvtx][lvele][5]  = 0.; 
1884 // dE/dy:

1885         dp_dpar[nvtx][lvele][6]  = 0.; 
1886 
1887         lvele++;
1888 // dPx/dz:

1889         dp_dpar[nvtx][lvele][3]  = 0.;
1890 // dPy/dz:

1891         dp_dpar[nvtx][lvele][4]  = 0.;
1892 // dPz/dz:

1893         dp_dpar[nvtx][lvele][5]  = 0.; 
1894 // dE/dz:

1895         dp_dpar[nvtx][lvele][6]  = 0.; 
1896 
1897         lvele = 3 * (ltrk + _ctvmq.nvertx);
1898 // dPx/dcurv[ltrk]:

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

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

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

1907         dp_dpar[nvtx][lvele][6]  = 
1908           -mom3[ltrk].mag2()/(_ctvmq.par[ltrk][0] * pmom[ltrk].e()); 
1909 
1910         lvele++;
1911 // dPx/dphi[ltrk]:

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

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

1916         dp_dpar[nvtx][lvele][5]  = 0.;
1917 // dE/dphi[ltrk]:

1918         dp_dpar[nvtx][lvele][6]  = 0.;
1919 
1920         lvele++;
1921 // dPx/dcot[ltrk]:

1922         dp_dpar[nvtx][lvele][3]  = 0;
1923 // dPy/dcot[ltrk]:

1924         dp_dpar[nvtx][lvele][4]  = 0;
1925 // dPz/dcot[ltrk]:

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

1928         dp_dpar[nvtx][lvele][6]  = 
1929          pmom[ltrk].perp2() * _ctvmq.par[ltrk][2] / pmom[ltrk].e();
1930       }
1931     }
1932   }
1933 // Now calculate the new error matrix

1934 
1935   // Extract the interesting bits from VMAT.

1936 
1937   HepMatrix vmat(ctvmft_dim,ctvmft_dim,0);
1938   for(int lpar = 0; lpar < ctvmft_dim; lpar++){
1939     int l = lpar%3;
1940     int lvele = 0;
1941     if(lpar < 3  * _ctvmq.nvertx){
1942       int lvtx = lpar/3;
1943       lvele = _ctvmq.voff[lvtx] + l;
1944     }
1945     else{
1946       int ltrk = (lpar - 3 * _ctvmq.nvertx)/3;
1947       lvele = _ctvmq.toff[ltrk] + l;
1948     }
1949     for(int kpar = 0; kpar < ctvmft_dim; kpar++){ 
1950       int k = kpar%3;
1951       int kvele = 0;
1952       if(kpar < 3  * _ctvmq.nvertx){
1953         int kvtx = kpar/3;
1954         kvele = _ctvmq.voff[kvtx] + k;
1955       }
1956       else{
1957         int ktrk = (kpar - 3 * _ctvmq.nvertx)/3;
1958         kvele = _ctvmq.toff[ktrk] + k;
1959       }
1960       vmat[kpar][lpar] = _ctvmfr.vmat[kvele][lvele];
1961     }
1962   }
1963   //  Just about done

1964   HepMatrix ans(7,7,0);
1965   HepMatrix answer[_maxvtx] = {ans, ans, ans};
1966   for(int nvtx = 0; nvtx < _ctvmq.nvertx; nvtx++){
1967     answer[nvtx] = (dp_dpar[nvtx].T() * vmat) * dp_dpar[nvtx];
1968   }
1969   errors = answer[0];
1970 }
1971 
1972 /*=======================================================================

1973                          VertexFit::vOff

1974   =======================================================================*/
1975 int VertexFit::vOff(vertexNumber jv) const
1976 { if(jv < VERTEX_1 || jv > _maxvtx) {return -999;}
1977   else {return _ctvmq.voff[jv-1];}
1978 }
1979 
1980 /*=======================================================================

1981                          VertexFit::tOff

1982   =======================================================================*/
1983 int VertexFit::tOff(const CdfTrack* trk) const
1984 { for(int kt=0; kt<_ctvmq.ntrack; ++kt) {
1985     if(trk->id().value()==_ctvmq.list[kt]) return _ctvmq.toff[kt];
1986   }
1987   return -999;
1988 }
1989 
1990 /*=======================================================================

1991                          VertexFit::pOff

1992   =======================================================================*/
1993 int VertexFit::pOff(int lp) const
1994 { if(lp < 1) {
1995     return -999;
1996   }
1997   else return _ctvmq.poff[lp-1];
1998 }
1999 
2000 /*=======================================================================

2001                          VertexFit::cOff

2002   =======================================================================*/
2003 int VertexFit::cOff(int lc) const
2004 { if(lc < 1) {
2005     return -999;
2006   }
2007   else return _ctvmq.coff[lc-1];
2008 }
2009 
2010 /*=======================================================================

2011                          VertexFit::mOff

2012   =======================================================================*/
2013 int VertexFit::mOff() const
2014 { return _ctvmq.moff; }
2015 
2016 /*=======================================================================

2017                          VertexFit::VMat

2018   =======================================================================*/
2019 double VertexFit::VMat(int i, int j) const
2020 { if(i <0 || j < 0) {return -999.;}
2021   else return _ctvmfr.vmat[i][j];
2022 }
2023 
2024 /*=======================================================================

2025                          VertexFit::allocateVertexNumber

2026   =======================================================================*/
2027 
2028 // Facilitates CandNode recursion.  CandNodes have no way of deciding

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

2030 VertexFit::vertexNumber VertexFit::allocateVertexNumber()
2031 {
2032   if ((_currentAllocatedVertexNumber < PRIMARY_VERTEX) ||
2033       (_currentAllocatedVertexNumber > _maxvtx)) {
2034     std::cout << "VertexFit::allocateVertexNumber: out of range!" << std::endl;
2035     return PRIMARY_VERTEX;
2036   }
2037   return vertexNumber(++_currentAllocatedVertexNumber);
2038 }
2039 
2040 void VertexFit::resetAllocatedVertexNumber()
2041 {
2042   _currentAllocatedVertexNumber = 0;
2043 }
2044 
2045 /*=======================================================================

2046                          VertexFit::restoreFromCommons()

2047   =======================================================================*/
2048 
2049 void VertexFit::restoreFromCommons() {
2050         stat=0;
2051         _ctvmq_com  = (CTVMQ*) ctvmq_address_();
2052         _ctvmfr_com = (CTVMFR*) ctvmfr_address_();
2053         _fiddle_com = (FIDDLE*) fiddle_address_();
2054         _trkprm_com = (TRKPRM*) trkprm_address_();
2055         _ctvmq  = *_ctvmq_com;
2056         _ctvmfr = *_ctvmfr_com;
2057         _fiddle = *_fiddle_com;
2058         _trkprm = *_trkprm_com;
2059 }
2060 
2061 
2062 /*=======================================================================

2063                          VertexFit::setTrackReferencePoint

2064   =======================================================================*/
2065 void VertexFit::setTrackReferencePoint( const Hep3Vector & ref )
2066 {
2067   // Set extrapolation flag

2068   _extrapolateTrackErrors = true; 
2069   // Keep new reference point

2070   _referencePoint = ref;
2071   // Keep track of old primary vertex in CDF coordinates

2072   _cdfPrimaryVertex = _primaryVertex;
2073   // Set new primary vertex relative to new reference point

2074   setPrimaryVertex( _cdfPrimaryVertex - _referencePoint);
2075 }
2076 
2077 /*=======================================================================

2078                          VertexFit::moveReferencePoint()

2079   =======================================================================*/
2080 
2081 void VertexFit::moveReferencePoint( HepVector & v,
2082                                     HepSymMatrix & m ) {
2083 
2084   // Move the reference point of the track to _referencePoint

2085   if ( !_extrapolateTrackErrors ) 
2086     return;
2087   
2088   TrackExtrapolator e;
2089 
2090   // Modifies v and m

2091   e.moveReferencePoint( v, m, _referencePoint );
2092 }
2093 
2094 
2095 #endif  /* VERTEXFIT_CC */
2096 
2097 

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