
Paul Avery 
This document describes the third version of the kinematic fitting library that has been used since 1992 for CLEO data analysis. Kwfit has a number of powerful features that together provide a complete framework for data analysis (the user interface routines are documented elsewhere):
Note: kwfit currently has 5000 tracks defined. The number may have to be increased if analyses with large combinatorics are attempted. Please let me know if the dimensions are adequate.
This web document and its links serve as the documentation for kwfit. It is mirrored at Florida and Cornell for greater access speed for users at these different locations:



There are over 100 routines in the kwfit user interface. The file locations for the sources and libraries are shown in the table below. No include files except for the one listed in the table below should be used directly in your code. There are access routines to return any information you will need.

Library 
$C_LIB/libkwfit.a 
Remember that the kwfit library is completely double precision. You must take care not to call kwfit routines with single precision arguments such as BMPOS or BFIE.
Many of you are familiar with knlib (which in turn replaced an older version called ftknlib) which has seen increasing use in CLEO because of the advent of silicon tracking and improved Kalman fitting of charged tracks. Kwfit has several improvements over knlib:
ktrk_move_arc(ktrk, arc, error)
moves the parameters and covariance matrix of track "ktrk" by the distance "arc", returning a nonzero error code if there is a problem.
This information is probably already familiar to you if you have used knlib previously. Track information is stored in a 10 dimensional format known as the "W representation", obtained through by calling

as discussed in the next section. The quantities w(110) are described below
W track representation
px 
x momentum 
py 
y momentum 
pz 
y momentum 
E 
Energy 
x 
x position 
y 
y position 
z 
z position 
Pt 
sqrt(px^2 + py^2) 
Ptot 
Total momentum 
Q 
Charge 
The momentum is evaluated at the (x, y, z) position. When a CLEO track is converted to the W representation, the track is created at the point of closest approach to the beam spot for that run (BMPOS). Note that only the first 7 components of a W are used in fits. Thus the covariance matrix corresponding to a W track is a 7 x 7 matrix.
Routines exist in kwfit to transform the standard CLEO helix track parameters (socalled "C representation) to and from the W representation. The C format is described in the following table.
C track representation
cu 
1/(2*radius of curvature) 
phi0 
Phi angle of momentum at PCA to reference point 
d0 
Signed distance to reference point in xy plane 
ct 
cot(theta) = pz / pt 
z0 
Z position at PCA to reference point 
cos(phi0) 

sin(phi0) 

Pt 
sqrt(px^2 + py^2) 
Ptot 
Total momentum 
Q 
Charge 
ref_x 
x position of reference point 
ref_y 
y position of reference point 
ref_z 
z position of reference point 
The helix is described by the first 5 parameters, defined relative to a reference point. In CLEO the reference point is always the origin of the coordinate system, but when moving helices to, say, a drift chamber wire or to a point in space, it is much more natural to have the reference point be at the place where you want to move the track. The parameters have a 5 x 5 covariance matrix which is converted to the 7 x 7 version when building the W track in kwfit.
The number of tracks in the kwfit system is obtained from kget_track_number. Individual kwfit tracks are accessed straightforwardly by track index. The following list shows what information is stored, along with the name of the corresponding access routine.
New entries in the kwfit track list can be created only by calling one of the kfil_track_xxxx routines. Each routine creates a track slot and copies over information from the corresponding track list, e.g. CD, CC, XBAL, etc. These routines are the only connection between CLEO and kwfit.
All fits in kwfit are performed with the lagrange multiplier method, described in other references [1,2]. The track parameters relevant to the fit are the current values w, unconstrained values w0, and a covariance matrix V0 associated with w0. These quantities are obtained by calling kget_track_param, kget_track_param0, and kget_track_covar, respectively. Normally w is the same as w0 unless a previous fit has updated it. The fit always starts with the unconstrained parameters w0 and recomputes the current parameters w.
The fitting algorithm proceeds as follows. First, the constraint equations are linearized by expanding around the current track parameters w (w is used for the center of the expansion because the current parameters are regarded by kwfit as being closer to their "true" values. This choice of expansion point has nothing to do with the fit itself). Second, the constraint and chisquare equations are solved simultaneously using matrix algebra (see the references for details) to calculate the new parameters w and the chisquare. The constraints can be thought of as "pulling" the track parameters from their unconstrained values w0. These two steps are repeated until the change in chisquare falls below a cutoff value (default = 0.001) or the maximum number of iterations (default = 10) has been reached. Both of these conditions can be specified by the user (kset_fit_criteria).
At the end of the fit the updated track parameters are stored in a temporary area, but they are updated only if the user has set the update flag in the call to the fitting routine. The update flag can take on three values:
Update 
Meaning 
0 
Compute chisquare, do not update input track parameters 
1 
Compute chisquare, update input track parameters 
2 
Compute chisquare, update input track parameters, 
Note that the update=2 option resets the track irreversibly. This option should be used with great care because it can give erroneous results when multiple tracks are used in a fit (most vertex fits fall into this category, for example). The reason is that when update=2 is specified for a fit involving multiple tracks, kwfit updates the parameters and covariance matrix of each individual track correctly, but it does not keep track of the intertrack correlations. If two or more of these tracks are used in a subsequent fit the loss of these correlations will lead to incorrect results. Note that there is no problem if a single track is used in a fit, e.g., kfit_mass or kfit_energy. For example, to build a virtual particle like a D^{0} with the correct mass, the following code fragment will work:

c Create new track entry and fill it with a D0 > K pi combination c which has been vertex constrained to a common, but unknown, point c Do not update the input tracks list_d0(1) = ktrk_K list_d0(2) = ktrk_pi option_d0(1) = 2 option_d0(2) = 2 update = 0 lvtx = .FALSE. call kfil_track_create(kd0) call kvir_vertex_unknown(2, list_d0, option_d0, update, lvtx, vtx, * chisq_d0, kd0, error) c Apply the mass constraint and update D0 parameters & error matrix c The D0 track now has the correct parameters and error matrix and c can be used in subsequent fits. mass_d0 = kget_track_mass(kd0) if(abs(mass_d0  1.8654) .lt. 0.010) then update = 2 call kfit_mass(kd0, 1.865, update, chisq_mass, error) endif 
With the advent of silicon tracking in CLEO, vertex fitting has become extremely important to physics analyses. However, there is no single vertex constraint method which is adequate to cover all desired cases. The mathematics for constraining tracks to a common vertex is worked out in refs. [2,3]. Kwfit distinguishes three kinds of vertex constraints when the number of tracks is n:
The routines which carry out the vertex constraints are described in the user interface. Note that kwfit actually treats the first vertex algorithm as a special case of the second by setting the diagonal elements of the prior covariance matrix to huge values, effectively nullifying knowledge of the initial position.
All vertex routines have the prefix "kvtx_".
One of the most powerful features of kwfit is its ability to build a new particle from a set of particles using a vertex constraint. I like to call the new entity a "virtual particle". The virtual particle is created at the fitted vertex position and has the correct 4momentum and 7x7 covariance matrix so that it can participate in future fits. Moreover, I have implemented a very flexible scheme  proven mathematically correct in ref. [3]  in which each input track can contribute to the vertex in a different way. This flexibility is necessary when handling very soft tracks and particles such as pizeros and gammas which have no position information.
There is a virtual particle creation routine corresponding to each of the vertex algorithms described in the previous section. If, in addition, you want to force the new particle to have a well defined mass, you merely impose the new constraint after the particle has been created. This two step procedure is equivalent to a simultaneous mass + vertex constraint (see ref. [1] if your masochistic urges compel you to see a proof of this assertion) and has the added advantage that the chisquares for the vertex and the mass constraints can be tested separately to help you decide if you want to keep the particle. An short example of how this is done is shown in Section 7 above.
All the virtual particle routines have the prefix "kvir_" and can only fill an existing particle slot (created by a "kfil_track_xxxx" routine).