1 |
loizides |
1.2 |
// $Id: MultiVertexFitterD.cc,v 1.1 2008/11/13 16:34:29 paus Exp $
|
2 |
paus |
1.1 |
|
3 |
|
|
#include "MitCommon/VertexFit/interface/MultiVertexFitterD.h"
|
4 |
|
|
#include <algorithm>
|
5 |
|
|
#include <math.h>
|
6 |
|
|
#include <iostream>
|
7 |
|
|
#include <csignal>
|
8 |
|
|
#include <csetjmp>
|
9 |
|
|
#include <TMath.h>
|
10 |
|
|
#include <CLHEP/Matrix/Matrix.h>
|
11 |
|
|
|
12 |
|
|
extern "C" void dctvmft_(int&, int&, int&);
|
13 |
|
|
extern "C" bool dmcalc_ (int&, int*, float&, float&, double*);
|
14 |
|
|
extern "C" void ddcalc_ (int&, int&, float*, float&, float&, float*);
|
15 |
|
|
|
16 |
|
|
using namespace std;
|
17 |
|
|
using namespace mithep;
|
18 |
|
|
|
19 |
|
|
jmp_buf denv;
|
20 |
loizides |
1.2 |
|
21 |
|
|
//--------------------------------------------------------------------------------------------------
|
22 |
paus |
1.1 |
extern "C" void MultiVertexFitterDSetStatus(int i) {
|
23 |
|
|
cout << "Warning, you are handling a severe error in MultiVertexFitterD" << endl;
|
24 |
|
|
longjmp(denv,-66);
|
25 |
|
|
}
|
26 |
|
|
|
27 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
28 |
paus |
1.1 |
MultiVertexFitterD::MultiVertexFitterD() :
|
29 |
|
|
_bField (3.8), // default B field for running
|
30 |
|
|
_currentAllocatedVertexNumber(0), // facilitates CandNode recursion
|
31 |
|
|
_referencePoint (0,0,0), // set reference point to (0,0,0) initially
|
32 |
|
|
_primaryVertex (0,0,0), // set primary vertex to (0,0,0) initially
|
33 |
|
|
_cdfPrimaryVertex (0,0,0) // set pv in CMS coords to (0,0,0) initially
|
34 |
|
|
{
|
35 |
|
|
// Set name and email of MultiVertexFitterD expert
|
36 |
|
|
_expert="Christoph Paus (paus@mit.edu)";
|
37 |
|
|
|
38 |
|
|
// First get pointers to various FORTAN common blocks
|
39 |
|
|
_ctvmq_com = (CTVMQ*) dctvmq_address_(); //printf(" Common: _ctvmq_com %p\n", _ctvmq_com );
|
40 |
|
|
_ctvmfr_com = (CTVMFR*) dctvmfr_address_(); //printf(" Common: _ctvmfr_com %p\n", _ctvmfr_com);
|
41 |
|
|
_fiddle_com = (FIDDLE*) dfiddle_address_(); //printf(" Common: _fiddle_com %p\n", _fiddle_com);
|
42 |
|
|
_trkprm_com = (TRKPRM*) dtrkprm_address_(); //printf(" Common: _trkprm_com %p\n", _trkprm_com);
|
43 |
|
|
|
44 |
|
|
// Initialize various arrays
|
45 |
|
|
init();
|
46 |
|
|
// Don't bomb program on error.
|
47 |
|
|
_fiddle.excuse = 1;
|
48 |
|
|
// Don't extrapolate track errors by default
|
49 |
|
|
_extrapolateTrackErrors = false;
|
50 |
|
|
}
|
51 |
|
|
|
52 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
53 |
paus |
1.1 |
void MultiVertexFitterD::init(double bField)
|
54 |
|
|
{
|
55 |
|
|
// Set internal variable which keeps track of the b field
|
56 |
|
|
_bField = bField;
|
57 |
|
|
|
58 |
|
|
// Now initialize CTVMQ common. Run and trigger numbers are dummies - they are not used.
|
59 |
|
|
_ctvmq.runnum = 1;
|
60 |
|
|
_ctvmq.trgnum = 100;
|
61 |
|
|
// Eventually, we have to get the magnetic field from the right place.
|
62 |
|
|
// Origignal with bmag = 14.116 [kGauss]:
|
63 |
|
|
// _ctvmq.pscale = 0.000149896 * bmag;
|
64 |
|
|
// New bfield in Tesla bmag = 1.4116 [T]:
|
65 |
|
|
_ctvmq.pscale = 0.00149896 * bField;
|
66 |
|
|
// Set the default maximum chi-square per dof.
|
67 |
|
|
_fiddle.chisqmax = 225.0;
|
68 |
|
|
// We also need to get the primary vertex from the right place, but for now we put in (0,0,0).
|
69 |
|
|
setPrimaryVertex(0.0,0.0,0.0);
|
70 |
|
|
float xverr[3][3];
|
71 |
|
|
for (int j = 0; j<3; j++) {
|
72 |
|
|
for (int k = 0; k<3; k++) {
|
73 |
|
|
xverr[j][k] = 0.;
|
74 |
|
|
}
|
75 |
|
|
}
|
76 |
|
|
xverr[0][0] = 0.005;
|
77 |
|
|
xverr[1][1] = 0.005;
|
78 |
|
|
xverr[2][2] = 1.0;
|
79 |
|
|
setPrimaryVertexError(xverr);
|
80 |
|
|
// Zero number of tracks, vertices and mass constraints
|
81 |
|
|
_ctvmq.ntrack = 0;
|
82 |
|
|
_ctvmq.nvertx = 0;
|
83 |
|
|
_ctvmq.nmassc = 0;
|
84 |
|
|
// Zero track list and arrays containing the vertex and mass constraint configuration
|
85 |
|
|
for (int j=0; j<_maxtrk; ++j) {
|
86 |
|
|
_ctvmq.list[j]=0;
|
87 |
|
|
for (int jv=0; jv<_maxvtx; ++jv)
|
88 |
|
|
_ctvmq.trkvtx[jv][j] = false;
|
89 |
|
|
for (int jmc=0; jmc<_maxmcn; ++jmc)
|
90 |
|
|
_ctvmq.trkmcn[jmc][j] = false;
|
91 |
|
|
}
|
92 |
|
|
// Initialize the conversion and vertex pointing arrays
|
93 |
|
|
for (int jv=0; jv<_maxvtx; ++jv) {
|
94 |
|
|
_ctvmq.cvtx[jv] = 0;
|
95 |
|
|
_ctvmq.vtxpnt[0][jv] = -1;
|
96 |
|
|
_ctvmq.vtxpnt[1][jv] = 0;
|
97 |
|
|
}
|
98 |
|
|
_ctvmq.drmax = 2.0;
|
99 |
|
|
_ctvmq.dzmax = 20.0;
|
100 |
|
|
_ctvmq.rvmax = 70.0;
|
101 |
|
|
_ctvmq.trnmax = 0.5;
|
102 |
|
|
_ctvmq.dsmin = -100.0; // for CDF used -2, for CMS fuzzing around.
|
103 |
|
|
// Set _stat to -999 and chisqq to -1 to symbolize that no fit has yet been done.
|
104 |
|
|
_stat = -999;
|
105 |
|
|
_ctvmq.chisqr[0] = -1.0;
|
106 |
|
|
|
107 |
|
|
_primaryVertex = Hep3Vector(0,0,0);
|
108 |
|
|
_cdfPrimaryVertex = Hep3Vector(0,0,0);
|
109 |
|
|
_referencePoint = ThreeVector(0,0,0);
|
110 |
|
|
}
|
111 |
|
|
|
112 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
113 |
paus |
1.1 |
bool MultiVertexFitterD::addTrack(const HepVector &v, const HepSymMatrix &cov,
|
114 |
|
|
int trackId, float mass, vertexNumber jv)
|
115 |
|
|
{
|
116 |
|
|
// Check that this vertex number is within the allowed range.
|
117 |
|
|
if (jv<VERTEX_1 || jv>_maxvtx)
|
118 |
|
|
return false;
|
119 |
|
|
_ctvmq.nvertx = jv>_ctvmq.nvertx ? jv : _ctvmq.nvertx;
|
120 |
|
|
|
121 |
|
|
// Add track extrapolation, if the user set it
|
122 |
|
|
HepVector w = v;
|
123 |
|
|
HepSymMatrix m = cov;
|
124 |
|
|
//if (_extrapolateTrackErrors)
|
125 |
|
|
// // This will move the reference point
|
126 |
|
|
// moveReferencePoint(w, m);
|
127 |
|
|
|
128 |
|
|
// Check that we have not exceeded the maximum number of tracks.
|
129 |
|
|
if (_ctvmq.ntrack>=_maxtrk)
|
130 |
|
|
return false;
|
131 |
|
|
|
132 |
|
|
// Add this track
|
133 |
|
|
_ctvmq.list [_ctvmq.ntrack] = trackId;
|
134 |
|
|
_ctvmq.tkbank[_ctvmq.ntrack][0] = 'Q';
|
135 |
|
|
_ctvmq.tkbank[_ctvmq.ntrack][1] = 'T';
|
136 |
|
|
_ctvmq.tkbank[_ctvmq.ntrack][2] = 'R';
|
137 |
|
|
_ctvmq.tkbank[_ctvmq.ntrack][3] = 'K';
|
138 |
|
|
_ctvmq.tmass [_ctvmq.ntrack] = mass;
|
139 |
|
|
_ctvmq.trkvtx[jv-1][_ctvmq.ntrack] = true;
|
140 |
|
|
|
141 |
|
|
// Put this track's helix parameters and error matrix into a fortran common block so that they
|
142 |
|
|
// can be accessed by gettrk. This is a dummy for now.
|
143 |
|
|
_trkprm.trhelix[_ctvmq.ntrack][0] = w[0];
|
144 |
|
|
_trkprm.trhelix[_ctvmq.ntrack][1] = w[1];
|
145 |
|
|
_trkprm.trhelix[_ctvmq.ntrack][2] = w[2];
|
146 |
|
|
_trkprm.trhelix[_ctvmq.ntrack][3] = w[3];
|
147 |
|
|
_trkprm.trhelix[_ctvmq.ntrack][4] = w[4];
|
148 |
|
|
|
149 |
|
|
for (int j=0; j<5; ++j) {
|
150 |
|
|
for (int k=0; k<5; ++k)
|
151 |
|
|
_trkprm.trem[_ctvmq.ntrack][j][k]=m[j][k];
|
152 |
|
|
}
|
153 |
|
|
_ctvmq.ntrack++;
|
154 |
|
|
|
155 |
|
|
return true;
|
156 |
|
|
}
|
157 |
|
|
|
158 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
159 |
paus |
1.1 |
bool MultiVertexFitterD::addTrack(const TVectorD &v, const TMatrixDSym &cov,
|
160 |
|
|
int trackId, double mass, vertexNumber jv)
|
161 |
|
|
{
|
162 |
|
|
// Check that this vertex number is within the allowed range.
|
163 |
|
|
if (jv<VERTEX_1 || jv>_maxvtx)
|
164 |
|
|
return false;
|
165 |
|
|
_ctvmq.nvertx = jv>_ctvmq.nvertx ? jv : _ctvmq.nvertx;
|
166 |
|
|
|
167 |
|
|
//// Add track extrapolation, if the user set it
|
168 |
|
|
//HepVector w = v;
|
169 |
|
|
//HepSymMatrix m = cov;
|
170 |
|
|
TVectorD w(v);
|
171 |
|
|
TMatrixDSym m(cov);
|
172 |
|
|
////if (_extrapolateTrackErrors)
|
173 |
|
|
//// // This will move the reference point
|
174 |
|
|
//// moveReferencePoint(w, m);
|
175 |
|
|
|
176 |
|
|
// Check that we have not exceeded the maximum number of tracks.
|
177 |
|
|
if (_ctvmq.ntrack>=_maxtrk)
|
178 |
|
|
return false;
|
179 |
|
|
|
180 |
|
|
// Add this track
|
181 |
|
|
_ctvmq.list [_ctvmq.ntrack] = trackId;
|
182 |
|
|
_ctvmq.tkbank[_ctvmq.ntrack][0] = 'Q';
|
183 |
|
|
_ctvmq.tkbank[_ctvmq.ntrack][1] = 'T';
|
184 |
|
|
_ctvmq.tkbank[_ctvmq.ntrack][2] = 'R';
|
185 |
|
|
_ctvmq.tkbank[_ctvmq.ntrack][3] = 'K';
|
186 |
|
|
_ctvmq.tmass [_ctvmq.ntrack] = mass;
|
187 |
|
|
_ctvmq.trkvtx[jv-1][_ctvmq.ntrack] = true;
|
188 |
|
|
|
189 |
|
|
// Put this track's helix parameters and error matrix into a fortran common block so that they
|
190 |
|
|
// can be accessed by gettrk. This is a dummy for now.
|
191 |
|
|
_trkprm.trhelix[_ctvmq.ntrack][0] = w[0];
|
192 |
|
|
_trkprm.trhelix[_ctvmq.ntrack][1] = w[1];
|
193 |
|
|
_trkprm.trhelix[_ctvmq.ntrack][2] = w[2];
|
194 |
|
|
_trkprm.trhelix[_ctvmq.ntrack][3] = w[3];
|
195 |
|
|
_trkprm.trhelix[_ctvmq.ntrack][4] = w[4];
|
196 |
|
|
|
197 |
|
|
for (int j=0; j<5; ++j) {
|
198 |
|
|
for (int k=0; k<5; ++k)
|
199 |
|
|
_trkprm.trem[_ctvmq.ntrack][j][k]=m[j][k];
|
200 |
|
|
}
|
201 |
|
|
_ctvmq.ntrack++;
|
202 |
|
|
|
203 |
|
|
return true;
|
204 |
|
|
}
|
205 |
|
|
|
206 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
207 |
paus |
1.1 |
bool MultiVertexFitterD::vertexPoint_2d(vertexNumber jv1, vertexNumber jv2)
|
208 |
|
|
{
|
209 |
|
|
// Check that these vertex numbers are within allowed range and that the vertices are unique.
|
210 |
|
|
if (jv1>_maxvtx || jv1<VERTEX_1)
|
211 |
|
|
return false;
|
212 |
|
|
if (jv2>_maxvtx || jv2<PRIMARY_VERTEX)
|
213 |
|
|
return false;
|
214 |
|
|
if (jv1 <= jv2)
|
215 |
|
|
return false;
|
216 |
|
|
|
217 |
|
|
// Setup vertex pointing.
|
218 |
|
|
_ctvmq.vtxpnt[0][jv1-1] = jv2;
|
219 |
|
|
_ctvmq.vtxpnt[1][jv1-1] = 1; // 2d pointing.
|
220 |
|
|
|
221 |
|
|
return true;
|
222 |
|
|
}
|
223 |
|
|
|
224 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
225 |
paus |
1.1 |
bool MultiVertexFitterD::vertexPoint_3d(vertexNumber jv1, vertexNumber jv2)
|
226 |
|
|
{
|
227 |
|
|
// Check that these vertex numbers are within allowed range and that the vertices are distinct
|
228 |
|
|
if (jv1>_maxvtx || jv1<VERTEX_1)
|
229 |
|
|
return false;
|
230 |
|
|
if (jv2>_maxvtx || jv2<PRIMARY_VERTEX)
|
231 |
|
|
return false;
|
232 |
|
|
if (jv1 <= jv2)
|
233 |
|
|
return false;
|
234 |
|
|
|
235 |
|
|
// Setup vertex pointing
|
236 |
|
|
_ctvmq.vtxpnt[0][jv1-1] = jv2;
|
237 |
|
|
_ctvmq.vtxpnt[1][jv1-1] = 2; // 3d pointing
|
238 |
|
|
|
239 |
|
|
return true;
|
240 |
|
|
}
|
241 |
|
|
|
242 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
243 |
paus |
1.1 |
bool MultiVertexFitterD::vertexPoint_1track(vertexNumber jv1, vertexNumber jv2)
|
244 |
|
|
{
|
245 |
|
|
// Check that these vertex numbers are within allowed range and are distinct
|
246 |
|
|
if (jv1>_maxvtx || jv1<VERTEX_1)
|
247 |
|
|
return false;
|
248 |
|
|
if (jv2>_maxvtx || jv2<PRIMARY_VERTEX)
|
249 |
|
|
return false;
|
250 |
|
|
if (jv1 <= jv2)
|
251 |
|
|
return false;
|
252 |
|
|
|
253 |
|
|
// Setup vertex pointing
|
254 |
|
|
_ctvmq.vtxpnt[0][jv1-1] = jv2;
|
255 |
|
|
_ctvmq.vtxpnt[1][jv1-1] = 3; // Point to 1 track vertex
|
256 |
|
|
|
257 |
|
|
return true;
|
258 |
|
|
}
|
259 |
|
|
|
260 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
261 |
paus |
1.1 |
bool MultiVertexFitterD::vertexPoint_0track(vertexNumber jv1, vertexNumber jv2)
|
262 |
|
|
{
|
263 |
|
|
// jv2 is the zero track vertex. jv1 is the multi track vertex which points to jv2
|
264 |
|
|
|
265 |
|
|
// Note: You must call this routine at least twice in order for ctvmft_zerotrackvtx to work ie
|
266 |
|
|
// there must be at least 2 vertices pointed at a zero track vertex. ctvmft for this, but the
|
267 |
|
|
// error message may not make it to your log file (look at the local variables in the stack frame
|
268 |
|
|
// especially IJKERR(2). The significance of this error code is documented at the top of whatever
|
269 |
|
|
// routine chucked you out (ctvmf00 in this case)
|
270 |
|
|
|
271 |
|
|
// see ctvmft.f source file for discussion. See especially comments at the top of subroutines:
|
272 |
|
|
// ctvmft and ctvmfa
|
273 |
|
|
|
274 |
|
|
// Check that these vertex numbers are within allowed range and are distinct.
|
275 |
|
|
if (jv1>_maxvtx || jv1<VERTEX_1)
|
276 |
|
|
return false;
|
277 |
|
|
if (jv2>_maxvtx || jv2<PRIMARY_VERTEX)
|
278 |
|
|
return false;
|
279 |
|
|
if (jv1 <= jv2)
|
280 |
|
|
return false;
|
281 |
|
|
|
282 |
|
|
// Setup vertex pointing.
|
283 |
|
|
_ctvmq.vtxpnt[0][jv1-1] = jv2;
|
284 |
|
|
_ctvmq.vtxpnt[1][jv1-1] = 4; // Point to 0 track vertex.
|
285 |
|
|
|
286 |
|
|
return true;
|
287 |
|
|
}
|
288 |
|
|
|
289 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
290 |
paus |
1.1 |
bool MultiVertexFitterD::conversion_2d(vertexNumber jv)
|
291 |
|
|
{
|
292 |
|
|
if (jv<VERTEX_1 || jv>_ctvmq.nvertx)
|
293 |
|
|
return false;
|
294 |
|
|
|
295 |
|
|
_ctvmq.cvtx[jv-1] = 1;
|
296 |
|
|
|
297 |
|
|
return true;
|
298 |
|
|
}
|
299 |
|
|
|
300 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
301 |
paus |
1.1 |
bool MultiVertexFitterD::conversion_3d(vertexNumber jv)
|
302 |
|
|
{
|
303 |
|
|
if (jv<VERTEX_1 || jv>_ctvmq.nvertx)
|
304 |
|
|
return false;
|
305 |
|
|
|
306 |
|
|
_ctvmq.cvtx[jv-1] = 2;
|
307 |
|
|
|
308 |
|
|
return true;
|
309 |
|
|
}
|
310 |
|
|
|
311 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
312 |
paus |
1.1 |
bool MultiVertexFitterD::massConstrain(int ntrk, const int trkIds[], float mass)
|
313 |
|
|
{
|
314 |
|
|
// Check that we have not exceeded the allowed number of mass constraints.
|
315 |
|
|
if (_ctvmq.nmassc>=_maxmcn)
|
316 |
|
|
return false;
|
317 |
|
|
|
318 |
|
|
// Set constraint mass
|
319 |
|
|
_ctvmq.cmass[_ctvmq.nmassc]=mass;
|
320 |
|
|
|
321 |
|
|
// For each track in contraint, set trkmcn true. Since the number in tracks[] is the track
|
322 |
|
|
// number, we have to find each track in the list of tracks.
|
323 |
|
|
for (int jt=0; jt<ntrk; ++jt) {
|
324 |
|
|
bool found=false;
|
325 |
|
|
for (int kt=0; kt<_ctvmq.ntrack; ++kt) {
|
326 |
|
|
if (trkIds[jt] == _ctvmq.list[kt]) {
|
327 |
|
|
_ctvmq.trkmcn[_ctvmq.nmassc][kt]=true;
|
328 |
|
|
found=true;
|
329 |
|
|
}
|
330 |
|
|
}
|
331 |
|
|
if (!found)
|
332 |
|
|
return false;
|
333 |
|
|
}
|
334 |
|
|
|
335 |
|
|
// Increment number of mass constraints.
|
336 |
|
|
_ctvmq.nmassc++;
|
337 |
|
|
|
338 |
|
|
return true;
|
339 |
|
|
}
|
340 |
|
|
|
341 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
342 |
paus |
1.1 |
bool MultiVertexFitterD::beamlineConstraint(float xb, float yb, HepSymMatrix berr,
|
343 |
|
|
float xzbslope, float yzbslope)
|
344 |
|
|
{
|
345 |
|
|
// Set beam position at z=0
|
346 |
|
|
setPrimaryVertex(xb,yb,0);
|
347 |
|
|
//if (_extrapolateTrackErrors) {
|
348 |
|
|
// float newXb = xb - _referencePoint.x() + _referencePoint.z() * xzbslope;
|
349 |
|
|
// float newYb = yb - _referencePoint.y() + _referencePoint.z() * yzbslope;
|
350 |
|
|
// setPrimaryVertex(newXb, newYb, 0);
|
351 |
|
|
//}
|
352 |
|
|
|
353 |
|
|
bool success = setPrimaryVertexError(berr);
|
354 |
|
|
|
355 |
|
|
// Set the beamline slope values
|
356 |
|
|
_ctvmq.xzslope = xzbslope;
|
357 |
|
|
_ctvmq.yzslope = yzbslope;
|
358 |
|
|
|
359 |
|
|
// Turn ON beamline constraint
|
360 |
|
|
_ctvmq.vtxpnt[0][0] = -100;
|
361 |
|
|
|
362 |
|
|
return success;
|
363 |
|
|
}
|
364 |
|
|
|
365 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
366 |
paus |
1.1 |
bool MultiVertexFitterD::beamlineConstraint(Hep3Vector pv, HepSymMatrix berr, float xzbslope,
|
367 |
|
|
float yzbslope)
|
368 |
|
|
{
|
369 |
|
|
// Check if input beam position coordinates are at z=0
|
370 |
|
|
if (pv.z() != 0)
|
371 |
|
|
return false;
|
372 |
|
|
|
373 |
|
|
return beamlineConstraint(pv.x(),pv.y(),berr,xzbslope,yzbslope);
|
374 |
|
|
}
|
375 |
|
|
|
376 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
377 |
paus |
1.1 |
void MultiVertexFitterD::setPrimaryVertex(float xv, float yv, float zv)
|
378 |
|
|
{
|
379 |
|
|
// Set x,y,z position of the primary vertex.
|
380 |
|
|
_ctvmq.xyzpv0[0] = xv;
|
381 |
|
|
_ctvmq.xyzpv0[1] = yv;
|
382 |
|
|
_ctvmq.xyzpv0[2] = zv;
|
383 |
|
|
|
384 |
|
|
_primaryVertex = Hep3Vector( xv, yv, zv );
|
385 |
|
|
}
|
386 |
|
|
|
387 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
388 |
paus |
1.1 |
void MultiVertexFitterD::setPrimaryVertex(Hep3Vector pv)
|
389 |
|
|
{
|
390 |
|
|
// Set x,y,z position of the primary vertex.
|
391 |
|
|
_ctvmq.xyzpv0[0] = pv.x();
|
392 |
|
|
_ctvmq.xyzpv0[1] = pv.y();
|
393 |
|
|
_ctvmq.xyzpv0[2] = pv.z();
|
394 |
|
|
|
395 |
|
|
_primaryVertex = pv;
|
396 |
|
|
}
|
397 |
|
|
|
398 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
399 |
paus |
1.1 |
void MultiVertexFitterD::setPrimaryVertexError(const float xverr[3][3])
|
400 |
|
|
{
|
401 |
|
|
// Set the error matrix for the primary vertex.
|
402 |
|
|
for (int j=0; j<3; ++j) {
|
403 |
|
|
for (int k=0; k<3; ++k)
|
404 |
|
|
_ctvmq.exyzpv[j][k]=xverr[j][k];
|
405 |
|
|
}
|
406 |
|
|
}
|
407 |
|
|
|
408 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
409 |
paus |
1.1 |
bool MultiVertexFitterD::setPrimaryVertexError(const HepSymMatrix &xverr)
|
410 |
|
|
{
|
411 |
|
|
// Set the error matrix for the primary vertex using a HepSymMatrix. First check that the matrix
|
412 |
|
|
// is the correct size.
|
413 |
|
|
if (xverr.num_row() != 3)
|
414 |
|
|
return false;
|
415 |
|
|
for (int j=0; j<3; j++) {
|
416 |
|
|
for (int k=0; k<3; k++)
|
417 |
|
|
_ctvmq.exyzpv[j][k]=xverr[j][k];
|
418 |
|
|
}
|
419 |
|
|
return true;
|
420 |
|
|
}
|
421 |
|
|
|
422 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
423 |
paus |
1.1 |
bool MultiVertexFitterD::fit()
|
424 |
|
|
{
|
425 |
|
|
// Check that the diagonal elements of all the track error matrices are positive
|
426 |
|
|
bool mstat = true;
|
427 |
|
|
for (int trk=0; trk<_ctvmq.ntrack; ++trk) {
|
428 |
|
|
for (int j=0; j<5; ++j) {
|
429 |
|
|
// Check diagonal elements of error matrix.
|
430 |
|
|
if (_trkprm.trem[trk][j][j] < 0.) {
|
431 |
|
|
// The covariance matrix could not be inverted: Set the error codes and fail this fit
|
432 |
|
|
mstat = false;
|
433 |
|
|
_ctvmq.ijkerr[0] = 3;
|
434 |
|
|
_ctvmq.ijkerr[1] = 2;
|
435 |
|
|
_ctvmq.ijkerr[2] = trk + 1;
|
436 |
|
|
}
|
437 |
|
|
}
|
438 |
|
|
// Check that curvature of track is reasonable: Pt is above ~10MeV/c. If not, set the error
|
439 |
|
|
// codes and fail this fit
|
440 |
|
|
if (fabs(_trkprm.trhelix[trk][1]) > 0.1) {
|
441 |
|
|
//if (fabs(_trkprm.trhelix[trk][1]) > 0.01) {
|
442 |
|
|
mstat = false;
|
443 |
|
|
_ctvmq.ijkerr[0] = 3;
|
444 |
|
|
_ctvmq.ijkerr[1] = 5;
|
445 |
|
|
_ctvmq.ijkerr[2] = trk + 1;
|
446 |
|
|
}
|
447 |
|
|
}
|
448 |
|
|
// If there was a problem with any track, fail the fit
|
449 |
|
|
if (!mstat) {
|
450 |
|
|
_stat = 1;
|
451 |
|
|
return false;
|
452 |
|
|
}
|
453 |
|
|
|
454 |
|
|
// First copy information into CTVMFT common blocks
|
455 |
|
|
*_ctvmq_com = _ctvmq;
|
456 |
|
|
*_ctvmfr_com = _ctvmfr;
|
457 |
|
|
*_fiddle_com = _fiddle;
|
458 |
|
|
*_trkprm_com = _trkprm;
|
459 |
|
|
// Do the vertex fit.
|
460 |
|
|
int print = 0;
|
461 |
|
|
int level = 0;
|
462 |
|
|
|
463 |
|
|
// #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
|
464 |
|
|
// struct sigaction myaction = {MultiVertexFitterDSetStatus, 0, 0, 0}, oldaction;
|
465 |
|
|
// sigaction(SIGFPE, &myaction, &oldaction);
|
466 |
|
|
// if (setjmp(denv)!=0) {
|
467 |
|
|
// sigaction(SIGFPE, &oldaction,0);
|
468 |
|
|
// return -999;
|
469 |
|
|
// }
|
470 |
|
|
// #endif
|
471 |
|
|
|
472 |
|
|
dctvmft_(print,level,_stat);
|
473 |
|
|
|
474 |
|
|
// #if ( defined(LINUX) && defined(__USE_BSD) ) || defined(OSF1)
|
475 |
|
|
// sigaction(SIGFPE, &oldaction,0);
|
476 |
|
|
// #endif
|
477 |
|
|
|
478 |
|
|
// Now copy information from CTVMFT common blocks to local storage
|
479 |
|
|
_ctvmq = *_ctvmq_com;
|
480 |
|
|
_ctvmfr = *_ctvmfr_com;
|
481 |
|
|
_fiddle = *_fiddle_com;
|
482 |
|
|
_trkprm = *_trkprm_com;
|
483 |
|
|
|
484 |
|
|
return (_stat == 0);
|
485 |
|
|
}
|
486 |
|
|
|
487 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
488 |
paus |
1.1 |
void MultiVertexFitterD::print() const
|
489 |
|
|
{
|
490 |
|
|
print(cout);
|
491 |
|
|
}
|
492 |
|
|
|
493 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
494 |
paus |
1.1 |
void MultiVertexFitterD::print(ostream& os) const
|
495 |
|
|
{
|
496 |
|
|
os << "****************************** MultiVertexFitterD "
|
497 |
|
|
<< "******************************" << endl;
|
498 |
|
|
os << "Number of tracks: " << _ctvmq.ntrack << endl;
|
499 |
|
|
os << " Tracks: ";
|
500 |
|
|
for (int jt=0; jt<_ctvmq.ntrack; ++jt) {
|
501 |
|
|
if (jt != 0) os << ", ";
|
502 |
|
|
os << _ctvmq.list[jt];
|
503 |
|
|
}
|
504 |
|
|
os << endl;
|
505 |
|
|
os << "Number of vertices: " << _ctvmq.nvertx << endl;
|
506 |
|
|
for (int jv=0; jv<_ctvmq.nvertx; ++jv) {
|
507 |
|
|
os << " Vertex " << jv+1 << " tracks: ";
|
508 |
|
|
for (int jt=0; jt<_ctvmq.ntrack; ++jt) {
|
509 |
|
|
if (_ctvmq.trkvtx[jv][jt]) {
|
510 |
|
|
os << " " << _ctvmq.list[jt];
|
511 |
|
|
}
|
512 |
|
|
}
|
513 |
|
|
os << endl;
|
514 |
|
|
}
|
515 |
|
|
for (int jv=0; jv<_ctvmq.nvertx; ++jv) {
|
516 |
|
|
if (_ctvmq.vtxpnt[0][jv]==0) {
|
517 |
|
|
os << " Vertex " << jv+1 << " points to the primary vertex ";
|
518 |
|
|
}
|
519 |
|
|
else if (_ctvmq.vtxpnt[0][jv]>0) {
|
520 |
|
|
os << " Vertex " << jv+1 << " points to vertex "
|
521 |
|
|
<< _ctvmq.vtxpnt[0][jv];
|
522 |
|
|
}
|
523 |
|
|
if (_ctvmq.vtxpnt[1][jv]==1) {
|
524 |
|
|
os << " in 2 dimensions" << endl;
|
525 |
|
|
}
|
526 |
|
|
else if (_ctvmq.vtxpnt[1][jv]==2) {
|
527 |
|
|
os << " in 3 dimensions" << endl;
|
528 |
|
|
}
|
529 |
|
|
else if (_ctvmq.vtxpnt[1][jv]==3) {
|
530 |
|
|
os << ", a single track vertex" << endl;
|
531 |
|
|
}
|
532 |
|
|
if (_ctvmq.cvtx[jv]>0) {
|
533 |
|
|
os << " Vertex " << jv+1 << " is a conversion" << endl;
|
534 |
|
|
}
|
535 |
|
|
}
|
536 |
|
|
os << "Number of mass constraints: " << _ctvmq.nmassc << endl;
|
537 |
|
|
for (int jmc=0; jmc<_ctvmq.nmassc; ++jmc) {
|
538 |
|
|
os << " Tracks ";
|
539 |
|
|
for (int jt=0; jt<_ctvmq.ntrack; ++jt) {
|
540 |
|
|
if (_ctvmq.trkmcn[jmc][jt]) {
|
541 |
|
|
os << " " << _ctvmq.list[jt];
|
542 |
|
|
}
|
543 |
|
|
}
|
544 |
|
|
os << " constrained to mass " << _ctvmq.cmass[jmc]
|
545 |
|
|
<< " Gev/c^2" << endl;
|
546 |
|
|
}
|
547 |
|
|
if (_stat==-999) {
|
548 |
|
|
os << "No fit has been done." << endl;
|
549 |
|
|
}
|
550 |
|
|
else {
|
551 |
|
|
os << "***** Results of Fit *****" << endl;
|
552 |
|
|
printErr(os);
|
553 |
|
|
os << " Status = " << _stat << endl;
|
554 |
|
|
os.precision(7);
|
555 |
|
|
os << " Chi-square = " << scientific << _ctvmq.chisqr[0]
|
556 |
|
|
<< " for " << _ctvmq.ndof << " degrees of freedom." << endl;
|
557 |
|
|
os << " => probability = " << prob() << endl;
|
558 |
|
|
for (int jv=0; jv<_ctvmq.nvertx; ++jv) {
|
559 |
|
|
os << "Vertex " << jv+1
|
560 |
|
|
<< " position: " << scientific
|
561 |
|
|
<< _ctvmq.xyzvrt[jv+1][0] << " "
|
562 |
|
|
<< _ctvmq.xyzvrt[jv+1][1] << " "
|
563 |
|
|
<< _ctvmq.xyzvrt[jv+1][2] << endl;
|
564 |
|
|
}
|
565 |
|
|
for (int jt=0; jt<_ctvmq.ntrack; ++jt) {
|
566 |
|
|
os << "Track " << _ctvmq.list[jt]
|
567 |
|
|
<< " - P4: " << scientific
|
568 |
|
|
<< _ctvmq.trkp4[0][jt] << " "
|
569 |
|
|
<< _ctvmq.trkp4[1][jt] << " "
|
570 |
|
|
<< _ctvmq.trkp4[2][jt] << " "
|
571 |
|
|
<< _ctvmq.trkp4[3][jt] << " "
|
572 |
|
|
<< " - PT: " << scientific
|
573 |
|
|
<< sqrt(_ctvmq.trkp4[0][jt]*_ctvmq.trkp4[0][jt]+
|
574 |
|
|
_ctvmq.trkp4[1][jt]*_ctvmq.trkp4[1][jt]) << endl;
|
575 |
|
|
}
|
576 |
|
|
}
|
577 |
|
|
os << "****************************************"
|
578 |
|
|
<< "**************************" << endl;
|
579 |
|
|
|
580 |
|
|
return;
|
581 |
|
|
}
|
582 |
|
|
|
583 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
584 |
paus |
1.1 |
void MultiVertexFitterD::printErr() const
|
585 |
|
|
{
|
586 |
|
|
printErr(cout);
|
587 |
|
|
}
|
588 |
|
|
|
589 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
590 |
paus |
1.1 |
void MultiVertexFitterD::printErr(ostream& os) const
|
591 |
|
|
{
|
592 |
|
|
os << "MultiVertexFitterD: IJKERR = " << _ctvmq.ijkerr[0] << ", "
|
593 |
|
|
<< _ctvmq.ijkerr[1] << ", "
|
594 |
|
|
<< _ctvmq.ijkerr[2] << endl;
|
595 |
|
|
if (status()==0 && _ctvmq.ijkerr[0]==0) return;
|
596 |
|
|
if (_ctvmq.ijkerr[0] == -1) {
|
597 |
|
|
os << " Problem with GETTRK: track requested is not in list."
|
598 |
|
|
<< endl
|
599 |
|
|
<< " This should not happen - Contact MultiVertexFitterD expert "
|
600 |
|
|
<< _expert << "." <<endl;
|
601 |
|
|
}
|
602 |
|
|
else if (_ctvmq.ijkerr[0]==1) {
|
603 |
|
|
os << " Problem in CTVM00:" << endl;
|
604 |
|
|
if (_ctvmq.ijkerr[1]==1) {
|
605 |
|
|
os << " Number of tracks is " << _ctvmq.ntrack
|
606 |
|
|
<< "." << endl;
|
607 |
|
|
if (_ctvmq.ntrack < 2) {
|
608 |
|
|
os << ", which is too few (must be at least 2)." << endl;
|
609 |
|
|
}
|
610 |
|
|
else if (_ctvmq.ntrack > _maxtrk) {
|
611 |
|
|
os << ", which is too many (maximum is " << _maxtrk
|
612 |
|
|
<< ")." << endl;
|
613 |
|
|
}
|
614 |
|
|
else {
|
615 |
|
|
os << " Problem with number of tracks"
|
616 |
|
|
<< " for unknown reasons." << endl;
|
617 |
|
|
}
|
618 |
|
|
}
|
619 |
|
|
else if (_ctvmq.ijkerr[1]==2) {
|
620 |
|
|
os << " Number of vertices is " << _ctvmq.nvertx
|
621 |
|
|
<< "." << endl;
|
622 |
|
|
if (_ctvmq.nvertx < 1) {
|
623 |
|
|
os << ", which is too few (must be at least 1)." << endl;
|
624 |
|
|
}
|
625 |
|
|
else if (_ctvmq.nvertx > _maxvtx) {
|
626 |
|
|
os << ", which is too many (maximum is " << _maxvtx
|
627 |
|
|
<< ")." << endl;
|
628 |
|
|
}
|
629 |
|
|
else {
|
630 |
|
|
os << endl << " Problem with number of vertices"
|
631 |
|
|
<< " for unknown reasons." << endl;
|
632 |
|
|
}
|
633 |
|
|
}
|
634 |
|
|
else if (_ctvmq.ijkerr[1]==3) {
|
635 |
|
|
os << " Number of mass constraints is " << _ctvmq.nmassc
|
636 |
|
|
<< "." << endl;
|
637 |
|
|
if (_ctvmq.nmassc < 0) {
|
638 |
|
|
os << ", which is negative." << endl;
|
639 |
|
|
}
|
640 |
|
|
else if (_ctvmq.nmassc > _maxmcn) {
|
641 |
|
|
os << ", which is too many (maximum is " << _maxmcn
|
642 |
|
|
<< ")." << endl;
|
643 |
|
|
}
|
644 |
|
|
else {
|
645 |
|
|
os << endl << " Problem with number of mass"
|
646 |
|
|
<< " constraints for unknown reasons." << endl;
|
647 |
|
|
}
|
648 |
|
|
}
|
649 |
|
|
else if (_ctvmq.ijkerr[1]==11) {
|
650 |
|
|
os << " Vertex " << _ctvmq.ijkerr[2]
|
651 |
|
|
<< " has less than one track." << endl;
|
652 |
|
|
}
|
653 |
|
|
else if (_ctvmq.ijkerr[1]==12) {
|
654 |
|
|
os << " Vertex " << _ctvmq.ijkerr[2]
|
655 |
|
|
<< " is a conversion vertex with a number of tracks"
|
656 |
|
|
<< " different than two." << endl;
|
657 |
|
|
}
|
658 |
|
|
else if (_ctvmq.ijkerr[1]==13) {
|
659 |
|
|
os << " Vertex " << _ctvmq.ijkerr[2]
|
660 |
|
|
<< " is a one track vertex that has no multi-track"
|
661 |
|
|
<< " descendents." << endl;
|
662 |
|
|
}
|
663 |
|
|
else if (_ctvmq.ijkerr[1]==14) {
|
664 |
|
|
os << " Vertex " << _ctvmq.ijkerr[2]
|
665 |
|
|
<< " does not point at a vertex with a lower number."
|
666 |
|
|
<< endl;
|
667 |
|
|
}
|
668 |
|
|
else if (_ctvmq.ijkerr[1]==15) {
|
669 |
|
|
os << " Vertex " << _ctvmq.ijkerr[2]
|
670 |
|
|
<< " has a parent vertex that is a conversion." << endl;
|
671 |
|
|
}
|
672 |
|
|
else if (_ctvmq.ijkerr[1]==16) {
|
673 |
|
|
os << " Vertex " << _ctvmq.ijkerr[2]
|
674 |
|
|
<< " does 1 track pointing to a vertex with"
|
675 |
|
|
<< " more than 1 track." << endl;
|
676 |
|
|
}
|
677 |
|
|
else if (_ctvmq.ijkerr[1]==17) {
|
678 |
|
|
os << " Vertex " << _ctvmq.ijkerr[2]
|
679 |
|
|
<< " does 0 track pointing to a vertex with"
|
680 |
|
|
<< " more than 0 track (?)." << endl;
|
681 |
|
|
}
|
682 |
|
|
else if (_ctvmq.ijkerr[1]==19) {
|
683 |
|
|
os << " Primary vertex error matrix is singular." << endl;
|
684 |
|
|
}
|
685 |
|
|
else if (_ctvmq.ijkerr[1]==21) {
|
686 |
|
|
os << " Track with Id " << _ctvmq.ijkerr[2]
|
687 |
|
|
<< "is not in any vertex." << endl;
|
688 |
|
|
}
|
689 |
|
|
else if (_ctvmq.ijkerr[1]==22) {
|
690 |
|
|
os << " Track with Id " << _ctvmq.ijkerr[2]
|
691 |
|
|
<< "is in multiple vertices." << endl;
|
692 |
|
|
}
|
693 |
|
|
else if (_ctvmq.ijkerr[1]==23) {
|
694 |
|
|
os << " Track with Id " << _ctvmq.ijkerr[2]
|
695 |
|
|
<< "occurs more than once." << endl;
|
696 |
|
|
}
|
697 |
|
|
else if (_ctvmq.ijkerr[1]==31) {
|
698 |
|
|
os << " A mass constraint has less than 2 tracks." << endl;
|
699 |
|
|
}
|
700 |
|
|
else if (_ctvmq.ijkerr[1]==32) {
|
701 |
|
|
os << " The sum masses of the tracks in a mass constraint"
|
702 |
|
|
<< " exceeds the constraint mass." << endl;
|
703 |
|
|
}
|
704 |
|
|
else if (_ctvmq.ijkerr[1]==33) {
|
705 |
|
|
os << " Beamline constraint. Beam covariance not set properly."
|
706 |
|
|
<< " Negative diagonal elements." << endl;
|
707 |
|
|
}
|
708 |
|
|
else if (_ctvmq.ijkerr[1]==34) {
|
709 |
|
|
os << " Beamline constraint. Beam covariance not set properly."
|
710 |
|
|
<< " Off-diagonal elements not zero." << endl;
|
711 |
|
|
}
|
712 |
|
|
else if (_ctvmq.ijkerr[1]==36) {
|
713 |
|
|
os << " Beamline constraint. Number of vertices = "
|
714 |
|
|
<< _ctvmq.nvertx << " Should be 1." << endl;
|
715 |
|
|
}
|
716 |
|
|
}
|
717 |
|
|
else if (_ctvmq.ijkerr[0] == 2) {
|
718 |
|
|
if (_ctvmq.ijkerr[1] == 20) {
|
719 |
|
|
os << " Problem in CTVM00: " << endl;
|
720 |
|
|
os << " Track has negative Id = "
|
721 |
|
|
<< _ctvmq.list[_ctvmq.ijkerr[2]-1] << "." << endl;
|
722 |
|
|
}
|
723 |
|
|
else {
|
724 |
|
|
os << " Problem in CTVMFA with vertex "
|
725 |
|
|
<< _ctvmq.ijkerr[2] << ": " << endl;
|
726 |
|
|
os << " Failure in vertex first approximation." << endl;
|
727 |
|
|
if (_ctvmq.ijkerr[1] == 1) {
|
728 |
|
|
os << " Tracks are concentric circles." << endl;
|
729 |
|
|
}
|
730 |
|
|
if (_ctvmq.ijkerr[1] == 2) {
|
731 |
|
|
os << " Conversion vertex has widely separated"
|
732 |
|
|
<< " exterior circles at midpoint." << endl;
|
733 |
|
|
}
|
734 |
|
|
if (_ctvmq.ijkerr[1] == 3) {
|
735 |
|
|
os << " Conversion vertex has widely separated"
|
736 |
|
|
<< " interior circles at midpoint." << endl;
|
737 |
|
|
}
|
738 |
|
|
if (_ctvmq.ijkerr[1] == 4) {
|
739 |
|
|
os << " Vertex has widely separated"
|
740 |
|
|
<< " exterior circles at approximate vertex." << endl;
|
741 |
|
|
}
|
742 |
|
|
if (_ctvmq.ijkerr[1] == 5) {
|
743 |
|
|
os << " Vertex has widely separated"
|
744 |
|
|
<< " interior circles at approximate vertex." << endl;
|
745 |
|
|
}
|
746 |
|
|
if (_ctvmq.ijkerr[1] == 6) {
|
747 |
|
|
os << " Rv is too large at the chosen"
|
748 |
|
|
<< " intersection point." << endl;
|
749 |
|
|
}
|
750 |
|
|
if (_ctvmq.ijkerr[1] == 7) {
|
751 |
|
|
os << " Delta z is too large at the chosen"
|
752 |
|
|
<< " intersection point." << endl;
|
753 |
|
|
}
|
754 |
|
|
if (_ctvmq.ijkerr[1] == 8) {
|
755 |
|
|
os << " A track's turning to the chosen vertex"
|
756 |
|
|
<< " is too large." << endl;
|
757 |
|
|
}
|
758 |
|
|
if (_ctvmq.ijkerr[1] == 9) {
|
759 |
|
|
os << " There is no solution with an adequately"
|
760 |
|
|
<< " positive arc length." << endl;
|
761 |
|
|
}
|
762 |
|
|
if (_ctvmq.ijkerr[1] == 21) {
|
763 |
|
|
os << " zero-track vertexing: either/both vertex "
|
764 |
|
|
<< " momenta are too small (<0.01 MeV)." << endl;
|
765 |
|
|
}
|
766 |
|
|
if (_ctvmq.ijkerr[1] == 22) {
|
767 |
|
|
os << " zero-track vertexing: Two lines (tracks) are "
|
768 |
|
|
<< " parallel/antiparallel." << endl;
|
769 |
|
|
}
|
770 |
|
|
}
|
771 |
|
|
}
|
772 |
|
|
else if (_ctvmq.ijkerr[0] == 3) {
|
773 |
|
|
os << " Problem in CTVM01 with track with Id = "
|
774 |
|
|
<< _ctvmq.list[_ctvmq.ijkerr[2]-1] << ": " << endl;
|
775 |
|
|
if (_ctvmq.ijkerr[1] == 1) {
|
776 |
|
|
os << " GETTRK cannot find Id in list." << endl;
|
777 |
|
|
}
|
778 |
|
|
if (_ctvmq.ijkerr[1] == 2) {
|
779 |
|
|
os << " Covariance matrix could not be inverted." << endl
|
780 |
|
|
<< " Offending track number (in order addded) is "
|
781 |
|
|
<< _ctvmq.ijkerr[2] << "." << endl;
|
782 |
|
|
}
|
783 |
|
|
if (_ctvmq.ijkerr[1] == 3) {
|
784 |
|
|
os << " Track turns through too large an angle"
|
785 |
|
|
<< " to the vertex." << endl;
|
786 |
|
|
}
|
787 |
|
|
if (_ctvmq.ijkerr[1] == 4) {
|
788 |
|
|
os << " Track moves too far backward to vertex." << endl;
|
789 |
|
|
}
|
790 |
|
|
if (_ctvmq.ijkerr[1] == 5) {
|
791 |
|
|
os << " Track with curvature > 0.01." << endl
|
792 |
|
|
<< " Offending track number is "
|
793 |
|
|
<< _ctvmq.ijkerr[2] << "." << endl;
|
794 |
|
|
}
|
795 |
|
|
}
|
796 |
|
|
else if (status() == 9) {
|
797 |
|
|
os << " General fit problem: " << endl;
|
798 |
|
|
if (_ctvmq.ijkerr[1] == 1) {
|
799 |
|
|
os << " Singular solution matrix." << endl;
|
800 |
|
|
}
|
801 |
|
|
if (_ctvmq.ijkerr[1] == 2 || _ctvmq.ijkerr[1] == 3) {
|
802 |
|
|
os << " Too many iterations ( "
|
803 |
|
|
<< _ctvmq.ijkerr[2] << "(." << endl;
|
804 |
|
|
}
|
805 |
|
|
if (_ctvmq.ijkerr[1] == 4) {
|
806 |
|
|
os << " Convergence failure." << endl;
|
807 |
|
|
}
|
808 |
|
|
if (_ctvmq.ijkerr[1] == 5) {
|
809 |
|
|
os << " Bad convergence." << endl;
|
810 |
|
|
}
|
811 |
|
|
if (_ctvmq.ijkerr[1] == 9) {
|
812 |
|
|
os << " Ill-formed covariance matrix." << endl;
|
813 |
|
|
}
|
814 |
|
|
}
|
815 |
|
|
else {
|
816 |
|
|
os << " The error codes above are not recognized." << endl
|
817 |
|
|
<< " Contact MultiVertexFitterD expert " << _expert << "." << endl;
|
818 |
|
|
}
|
819 |
|
|
return;
|
820 |
|
|
}
|
821 |
|
|
|
822 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
823 |
paus |
1.1 |
void MultiVertexFitterD::getIJKErr(int& err0, int& err1, int& err2) const
|
824 |
|
|
{
|
825 |
|
|
err0 = _ctvmq.ijkerr[0];
|
826 |
|
|
err1 = _ctvmq.ijkerr[1];
|
827 |
|
|
err2 = _ctvmq.ijkerr[2];
|
828 |
|
|
return;
|
829 |
|
|
}
|
830 |
|
|
|
831 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
832 |
paus |
1.1 |
int MultiVertexFitterD::getIJKErr0() const
|
833 |
|
|
{
|
834 |
|
|
return _ctvmq.ijkerr[0];
|
835 |
|
|
}
|
836 |
loizides |
1.2 |
|
837 |
|
|
//--------------------------------------------------------------------------------------------------
|
838 |
paus |
1.1 |
int MultiVertexFitterD::getIJKErr1() const
|
839 |
|
|
{
|
840 |
|
|
return _ctvmq.ijkerr[1];
|
841 |
|
|
}
|
842 |
loizides |
1.2 |
|
843 |
|
|
//--------------------------------------------------------------------------------------------------
|
844 |
paus |
1.1 |
int MultiVertexFitterD::getIJKErr2() const
|
845 |
|
|
{
|
846 |
|
|
return _ctvmq.ijkerr[2];
|
847 |
|
|
}
|
848 |
|
|
|
849 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
850 |
paus |
1.1 |
int MultiVertexFitterD::getErrTrackId() const
|
851 |
|
|
{
|
852 |
|
|
if (status() == 0) return 0;
|
853 |
|
|
int trkId = 0;
|
854 |
|
|
// Problems with track in CTVM01 or track has negative id in CTVM00 See PrintErr() for a more
|
855 |
|
|
// detailed list of error codes.
|
856 |
|
|
if ((_ctvmq.ijkerr[0] == 2 && _ctvmq.ijkerr[1] == 20) ||
|
857 |
|
|
_ctvmq.ijkerr[0] == 3) {
|
858 |
|
|
trkId = _ctvmq.list[_ctvmq.ijkerr[2]-1];
|
859 |
|
|
}
|
860 |
|
|
|
861 |
|
|
return trkId;
|
862 |
|
|
}
|
863 |
|
|
|
864 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
865 |
paus |
1.1 |
string MultiVertexFitterD::expert() const
|
866 |
|
|
{
|
867 |
|
|
return _expert;
|
868 |
|
|
}
|
869 |
|
|
|
870 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
871 |
paus |
1.1 |
int MultiVertexFitterD::status() const
|
872 |
|
|
{
|
873 |
|
|
return _stat;
|
874 |
|
|
}
|
875 |
|
|
|
876 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
877 |
paus |
1.1 |
float MultiVertexFitterD::chisq() const
|
878 |
|
|
{
|
879 |
|
|
// Chi-square of fit
|
880 |
|
|
return _ctvmq.chisqr[0];
|
881 |
|
|
}
|
882 |
|
|
|
883 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
884 |
paus |
1.1 |
int MultiVertexFitterD::ndof() const
|
885 |
|
|
{
|
886 |
|
|
// Number of degrees of freedom of fit.
|
887 |
|
|
if (_ctvmq.chisqr[0] >= 0)
|
888 |
|
|
return _ctvmq.ndof;
|
889 |
|
|
else
|
890 |
|
|
return 0;
|
891 |
|
|
}
|
892 |
|
|
|
893 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
894 |
paus |
1.1 |
float MultiVertexFitterD::prob() const
|
895 |
|
|
{
|
896 |
|
|
// Probability of chi-square of fit
|
897 |
|
|
if (_ctvmq.chisqr[0]>=0.) {
|
898 |
|
|
float chisq = _ctvmq.chisqr[0];
|
899 |
|
|
int nd = _ctvmq.ndof;
|
900 |
|
|
return TMath::Prob(chisq,nd);
|
901 |
|
|
}
|
902 |
|
|
else
|
903 |
|
|
return -999.;
|
904 |
|
|
}
|
905 |
|
|
|
906 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
907 |
paus |
1.1 |
float MultiVertexFitterD::chisq(const int trkId) const
|
908 |
|
|
{
|
909 |
|
|
// This method returns the chisquare contribution for one track If fit not successful or not done
|
910 |
|
|
// yet, return -1.
|
911 |
|
|
if (_ctvmq.chisqr[0] < 0)
|
912 |
|
|
return -1.;
|
913 |
|
|
// Look for this track in the list of tracks.
|
914 |
|
|
for (int jt = 0; jt < _ctvmq.ntrack; ++jt) {
|
915 |
|
|
if (trkId == _ctvmq.list[jt]) {
|
916 |
|
|
// Found the track, so return its chisquare contribution.
|
917 |
|
|
return _ctvmq.chit[jt];
|
918 |
|
|
}
|
919 |
|
|
}
|
920 |
|
|
// If track is not in list, return -1.
|
921 |
|
|
return -1.;
|
922 |
|
|
}
|
923 |
|
|
|
924 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
925 |
paus |
1.1 |
float MultiVertexFitterD::chisq_rphi() const
|
926 |
|
|
{
|
927 |
|
|
// This method returns the chisquare contribution in the r-phi plane.
|
928 |
|
|
int index[3] = {0,1,3};
|
929 |
|
|
// If fit not successful or not done yet, return -1.
|
930 |
|
|
if (_ctvmq.chisqr[0] < 0)
|
931 |
|
|
return -1.;
|
932 |
|
|
// Loop over the tracks in the event.
|
933 |
|
|
float chisq = 0.;
|
934 |
|
|
for (int jt=0; jt<_ctvmq.ntrack; ++jt) {
|
935 |
|
|
// Double loop over the relevant parameter indices.
|
936 |
|
|
for (int k1=0; k1<3; ++k1) {
|
937 |
|
|
for (int k2=0; k2<3; ++k2)
|
938 |
|
|
// Add contribution to chisquare.
|
939 |
|
|
chisq += _ctvmq.pardif[jt][index[k1]] *
|
940 |
|
|
_ctvmq.g[jt][index[k1]][index[k2]] *
|
941 |
|
|
_ctvmq.pardif[jt][index[k2]];
|
942 |
|
|
}
|
943 |
|
|
}
|
944 |
|
|
// Return the chisquare.
|
945 |
|
|
return chisq;
|
946 |
|
|
}
|
947 |
|
|
|
948 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
949 |
paus |
1.1 |
float MultiVertexFitterD::chisq_z() const
|
950 |
|
|
{
|
951 |
|
|
// This method returns the chisquare contribution in the z direction.
|
952 |
|
|
int index[2] = {2,4};
|
953 |
|
|
// If fit not successful or not done yet, return -1.
|
954 |
|
|
if (_ctvmq.chisqr[0] < 0)
|
955 |
|
|
return -1.;
|
956 |
|
|
// Loop over the tracks in the event.
|
957 |
|
|
float chisq = 0.;
|
958 |
|
|
for (int jt=0; jt<_ctvmq.ntrack; ++jt) {
|
959 |
|
|
// Double loop over the relevant parameter indices.
|
960 |
|
|
for (int k1=0; k1<2; ++k1) {
|
961 |
|
|
for (int k2=0; k2<2; ++k2)
|
962 |
|
|
// Add contribution to chisquare.
|
963 |
|
|
chisq += _ctvmq.pardif[jt][index[k1]] *
|
964 |
|
|
_ctvmq.g[jt][index[k1]][index[k2]] *
|
965 |
|
|
_ctvmq.pardif[jt][index[k2]];
|
966 |
|
|
}
|
967 |
|
|
}
|
968 |
|
|
// Return the chisquare.
|
969 |
|
|
return chisq;
|
970 |
|
|
}
|
971 |
|
|
|
972 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
973 |
paus |
1.1 |
float MultiVertexFitterD::chisq_rphiz() const
|
974 |
|
|
{
|
975 |
|
|
// This method returns the chisquare contribution of the cross
|
976 |
|
|
// terms in the r-phi and z directions.
|
977 |
|
|
int index1[2] = {2,4};
|
978 |
|
|
int index2[3] = {0,1,3};
|
979 |
|
|
// If fit not successful or not done yet, return -1.
|
980 |
|
|
if (_ctvmq.chisqr[0] < 0)
|
981 |
|
|
return -1.;
|
982 |
|
|
// Loop over the tracks in the event.
|
983 |
|
|
float chisq = 0.;
|
984 |
|
|
for (int jt=0; jt<_ctvmq.ntrack; ++jt) {
|
985 |
|
|
// Double loop over the relevant parameter indices.
|
986 |
|
|
for (int k1=0; k1<2; ++k1) {
|
987 |
|
|
for (int k2=0; k2<3; ++k2)
|
988 |
|
|
// Add contribution to chisquare.
|
989 |
|
|
chisq += _ctvmq.pardif[jt][index1[k1]] *
|
990 |
|
|
_ctvmq.g[jt][index1[k1]][index2[k2]] *
|
991 |
|
|
_ctvmq.pardif[jt][index2[k2]];
|
992 |
|
|
}
|
993 |
|
|
}
|
994 |
|
|
|
995 |
|
|
// Return the chisquare.
|
996 |
|
|
return 2.0 * chisq;
|
997 |
|
|
}
|
998 |
|
|
|
999 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1000 |
paus |
1.1 |
float MultiVertexFitterD::chisq_rphi(const int trkId) const
|
1001 |
|
|
{
|
1002 |
|
|
// This method returns the chisquare contribution in the r-phi plane.
|
1003 |
|
|
int index[3] = {0,1,3};
|
1004 |
|
|
// If fit not successful or not done yet, return -1.
|
1005 |
|
|
if (_ctvmq.chisqr[0] < 0)
|
1006 |
|
|
return -1.;
|
1007 |
|
|
// Loop over the tracks in the event, looking for the one we want
|
1008 |
|
|
for (int jt=0; jt<_ctvmq.ntrack; ++jt) {
|
1009 |
|
|
if (trkId == _ctvmq.list[jt]) {
|
1010 |
|
|
// Found the track, so calculate its chisquare contribution.
|
1011 |
|
|
float chisq = 0.;
|
1012 |
|
|
// Double loop over the relevant parameter indices.
|
1013 |
|
|
for (int k1=0; k1<3; ++k1) {
|
1014 |
|
|
for (int k2=0; k2<3; ++k2) {
|
1015 |
|
|
// Add contribution to chisquare.
|
1016 |
|
|
chisq += _ctvmq.pardif[jt][index[k1]] *
|
1017 |
|
|
_ctvmq.g[jt][index[k1]][index[k2]] *
|
1018 |
|
|
_ctvmq.pardif[jt][index[k2]];
|
1019 |
|
|
}
|
1020 |
|
|
}
|
1021 |
|
|
return chisq;
|
1022 |
|
|
}
|
1023 |
|
|
}
|
1024 |
|
|
|
1025 |
|
|
// Track not found, return -1.
|
1026 |
|
|
return -1.;
|
1027 |
|
|
}
|
1028 |
|
|
|
1029 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1030 |
paus |
1.1 |
float MultiVertexFitterD::chisq_z(const int trkId) const
|
1031 |
|
|
{
|
1032 |
|
|
// This method returns the chisquare contribution in the z direction.
|
1033 |
|
|
int index[2] = {2,4};
|
1034 |
|
|
// If fit not successful or not done yet, return -1.
|
1035 |
|
|
if (_ctvmq.chisqr[0] < 0)
|
1036 |
|
|
return -1.;
|
1037 |
|
|
// Loop over the tracks in the event, looking for the one we want.
|
1038 |
|
|
for (int jt=0; jt<_ctvmq.ntrack; ++jt) {
|
1039 |
|
|
if (trkId == _ctvmq.list[jt]) {
|
1040 |
|
|
// Found the track, so calculate its chisquare contribution.
|
1041 |
|
|
float chisq = 0.;
|
1042 |
|
|
// Double loop over the relevant parameter indices.
|
1043 |
|
|
for (int k1=0; k1<2; ++k1) {
|
1044 |
|
|
for (int k2=0; k2<2; ++k2)
|
1045 |
|
|
// Add contribution to chisquare.
|
1046 |
|
|
chisq += _ctvmq.pardif[jt][index[k1]] *
|
1047 |
|
|
_ctvmq.g[jt][index[k1]][index[k2]] *
|
1048 |
|
|
_ctvmq.pardif[jt][index[k2]];
|
1049 |
|
|
}
|
1050 |
|
|
return chisq;
|
1051 |
|
|
}
|
1052 |
|
|
}
|
1053 |
|
|
|
1054 |
|
|
// Track not found - return -1.
|
1055 |
|
|
return -1.;
|
1056 |
|
|
}
|
1057 |
|
|
|
1058 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1059 |
paus |
1.1 |
float MultiVertexFitterD::chisq_rphiz(const int trkId) const
|
1060 |
|
|
{
|
1061 |
|
|
// This method returns the chisquare contribution of the cross terms in the r-phi and z
|
1062 |
|
|
// directions
|
1063 |
|
|
int index1[2] = { 2,4 };
|
1064 |
|
|
int index2[3] = { 0,1,3 };
|
1065 |
|
|
// If fit not successful or not done yet, return -1
|
1066 |
|
|
if (_ctvmq.chisqr[0] < 0)
|
1067 |
|
|
return -1.;
|
1068 |
|
|
// Loop over the tracks in the event
|
1069 |
|
|
for (int jt=0; jt<_ctvmq.ntrack; ++jt) {
|
1070 |
|
|
if (trkId == _ctvmq.list[jt]) {
|
1071 |
|
|
// Found the track, so calculate its chisquare contribution
|
1072 |
|
|
float chisq = 0.;
|
1073 |
|
|
// Double loop over the relevant parameter indices
|
1074 |
|
|
for (int k1=0; k1<2; ++k1) {
|
1075 |
|
|
for (int k2=0; k2<3; ++k2)
|
1076 |
|
|
// Add contribution to chisquare
|
1077 |
|
|
chisq += _ctvmq.pardif[jt][index1[k1]] *
|
1078 |
|
|
_ctvmq.g[jt][index1[k1]][index2[k2]] *
|
1079 |
|
|
_ctvmq.pardif[jt][index2[k2]];
|
1080 |
|
|
}
|
1081 |
|
|
return 2.0 * chisq;
|
1082 |
|
|
}
|
1083 |
|
|
}
|
1084 |
|
|
// Track not found so return -1.
|
1085 |
|
|
return -1.;
|
1086 |
|
|
}
|
1087 |
|
|
|
1088 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1089 |
paus |
1.1 |
FourVector MultiVertexFitterD::getTrackP4(const int trkId) const
|
1090 |
|
|
{
|
1091 |
|
|
if (_stat != 0)
|
1092 |
|
|
return FourVector(0,0,0,0);
|
1093 |
|
|
// return four momentum of fit track
|
1094 |
|
|
for (int jt=0; jt<_ctvmq.ntrack; ++jt) {
|
1095 |
|
|
// Find which track matches this Id.
|
1096 |
|
|
if (trkId == _ctvmq.list[jt]) {
|
1097 |
|
|
FourVector p4((double)_ctvmq.trkp4[0][jt], (double)_ctvmq.trkp4[1][jt],
|
1098 |
|
|
(double)_ctvmq.trkp4[2][jt], (double)_ctvmq.trkp4[3][jt]);
|
1099 |
|
|
return p4;
|
1100 |
|
|
}
|
1101 |
|
|
}
|
1102 |
|
|
return FourVector(0,0,0,0);
|
1103 |
|
|
}
|
1104 |
|
|
|
1105 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1106 |
paus |
1.1 |
float MultiVertexFitterD::getMass(int ntrk, const int trkIds[], float &dmass) const
|
1107 |
|
|
{
|
1108 |
|
|
// #if (defined(LINUX) && defined(__USE_BSD)) || defined(OSF1)
|
1109 |
|
|
// struct sigaction myaction = {MultiVertexFitterDSetStatus, 0, 0, 0}, oldaction;
|
1110 |
|
|
// sigaction(SIGFPE, &myaction, &oldaction);
|
1111 |
|
|
// if (setjmp(denv)!=0) {
|
1112 |
|
|
// sigaction(SIGFPE, &oldaction,0);
|
1113 |
|
|
// return -999;
|
1114 |
|
|
// }
|
1115 |
|
|
// #endif
|
1116 |
|
|
|
1117 |
|
|
dmass = -999.;
|
1118 |
|
|
if (_stat!=0)
|
1119 |
|
|
return -999.;
|
1120 |
|
|
// Get fit invariant mass of ntrk tracks listed in array tracks. dmass is the error on the mass.
|
1121 |
|
|
dmass=-999.;
|
1122 |
|
|
if (ntrk <= 0)
|
1123 |
|
|
return 0;
|
1124 |
|
|
int jtrks[_maxtrk];
|
1125 |
|
|
for (int jt=0; jt<ntrk; ++jt) {
|
1126 |
|
|
bool found = false;
|
1127 |
|
|
for (int kt=0; kt<_ctvmq.ntrack; ++kt) {
|
1128 |
|
|
if (trkIds[jt] == _ctvmq.list[kt]) {
|
1129 |
|
|
found = true;
|
1130 |
|
|
jtrks[jt]=kt+1;
|
1131 |
|
|
}
|
1132 |
|
|
}
|
1133 |
|
|
if (!found)
|
1134 |
|
|
return 0;
|
1135 |
|
|
}
|
1136 |
|
|
// Copy information into CTVMFT common blocks
|
1137 |
|
|
*_ctvmq_com = _ctvmq;
|
1138 |
|
|
*_ctvmfr_com = _ctvmfr;
|
1139 |
|
|
int ntr = ntrk;
|
1140 |
|
|
float mass;
|
1141 |
|
|
double p4[4];
|
1142 |
|
|
dmcalc_(ntr, jtrks, mass, dmass, p4);
|
1143 |
|
|
|
1144 |
|
|
// #if (defined(LINUX) && defined(__USE_BSD)) || defined(OSF1)
|
1145 |
|
|
// sigaction(SIGFPE, &oldaction,0);
|
1146 |
|
|
// #endif
|
1147 |
|
|
|
1148 |
|
|
return mass;
|
1149 |
|
|
}
|
1150 |
|
|
|
1151 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1152 |
paus |
1.1 |
float MultiVertexFitterD::getDecayLength(vertexNumber nv, vertexNumber mv,
|
1153 |
|
|
const Hep3Vector& dir, float& dlerr) const
|
1154 |
|
|
{
|
1155 |
|
|
dlerr = -999.;
|
1156 |
|
|
if (_stat!=0)
|
1157 |
|
|
return -999.;
|
1158 |
|
|
|
1159 |
|
|
// Get the signed decay length from vertex nv to vertex mv along the x-y direction defined by the
|
1160 |
|
|
// 3 vector dir. dlerr is the error on the decay length including the full error matrix. Check
|
1161 |
|
|
// that vertices are within range.
|
1162 |
|
|
if (nv<0 || nv>=_ctvmq.nvertx)
|
1163 |
|
|
return -999.;
|
1164 |
|
|
if (mv<1 || mv>_ctvmq.nvertx)
|
1165 |
|
|
return -999.;
|
1166 |
|
|
if (nv>=mv)
|
1167 |
|
|
return -999.;
|
1168 |
|
|
|
1169 |
|
|
float dir_t = sqrt(dir.x()*dir.x()+dir.y()*dir.y());
|
1170 |
|
|
if (dir_t <= 0.)
|
1171 |
|
|
return -999.;
|
1172 |
|
|
|
1173 |
|
|
Hep3Vector dv = getVertexHep(mv)-getVertexHep(nv);
|
1174 |
|
|
float dl = (dv.x()*dir.x()+dv.y()*dir.y())/dir_t;
|
1175 |
|
|
// Set up the column matrix of derivatives
|
1176 |
|
|
HepMatrix A(4,1);
|
1177 |
|
|
A(1,1) = dir.x()/dir_t;
|
1178 |
|
|
A(2,1) = dir.y()/dir_t;
|
1179 |
|
|
A(3,1) = -dir.x()/dir_t;
|
1180 |
|
|
A(4,1) = -dir.y()/dir_t;
|
1181 |
|
|
// Check if first vertex (nv) is primary vertex. If it is, check if it was used in the primary
|
1182 |
|
|
// vertex. If not, all of the corresponding error matrix elements are those supplied for the
|
1183 |
|
|
// primary vertex.
|
1184 |
|
|
int nvf = 0;
|
1185 |
|
|
if (nv==0) {
|
1186 |
|
|
nvf=-1;
|
1187 |
|
|
for (int jv=0; jv<_ctvmq.nvertx; ++jv) {
|
1188 |
|
|
if (_ctvmq.vtxpnt[0][jv]==0)
|
1189 |
|
|
nvf=0;
|
1190 |
|
|
}
|
1191 |
|
|
}
|
1192 |
|
|
// Get the relevant submatrix of the full error matrix.
|
1193 |
|
|
HepMatrix V(4,4,0);
|
1194 |
|
|
if (nvf < 0) {
|
1195 |
|
|
V(1,1) = getErrorMatrixHep(_ctvmq.voff[mv-1]+1,_ctvmq.voff[mv-1]+1);
|
1196 |
|
|
V(1,2) = getErrorMatrixHep(_ctvmq.voff[mv-1]+1,_ctvmq.voff[mv-1]+2);
|
1197 |
|
|
V(2,1) = getErrorMatrixHep(_ctvmq.voff[mv-1]+2,_ctvmq.voff[mv-1]+1);
|
1198 |
|
|
V(2,2) = getErrorMatrixHep(_ctvmq.voff[mv-1]+2,_ctvmq.voff[mv-1]+2);
|
1199 |
|
|
V(3,3) = _ctvmq.exyzpv[0][0];
|
1200 |
|
|
V(3,4) = _ctvmq.exyzpv[0][1];
|
1201 |
|
|
V(4,3) = _ctvmq.exyzpv[1][0];
|
1202 |
|
|
V(4,4) = _ctvmq.exyzpv[1][1];
|
1203 |
|
|
}
|
1204 |
|
|
else {
|
1205 |
|
|
// Get the indices into the error matrix vmat
|
1206 |
|
|
int index[4] = { _ctvmq.voff[mv-1]+1,_ctvmq.voff[mv-1]+2,0,0 };
|
1207 |
|
|
if (nv==0) {
|
1208 |
|
|
index[2] = 1;
|
1209 |
|
|
index[3] = 2;
|
1210 |
|
|
}
|
1211 |
|
|
else {
|
1212 |
|
|
index[2] = _ctvmq.voff[nv-1]+1;
|
1213 |
|
|
index[3] = _ctvmq.voff[nv-1]+2;
|
1214 |
|
|
}
|
1215 |
|
|
for (int j=0; j<4; ++j) {
|
1216 |
|
|
for (int k=0; k<4; ++k) {
|
1217 |
|
|
V[j][k] = getErrorMatrixHep(index[j],index[k]);
|
1218 |
|
|
}
|
1219 |
|
|
}
|
1220 |
|
|
}
|
1221 |
|
|
|
1222 |
|
|
// Calculate square of dlerr
|
1223 |
|
|
dlerr = (A.T()*V*A)(1,1);
|
1224 |
|
|
if (dlerr >= 0.)
|
1225 |
|
|
dlerr = sqrt(dlerr);
|
1226 |
|
|
else
|
1227 |
|
|
dlerr = -sqrt(-dlerr);
|
1228 |
|
|
|
1229 |
|
|
return dl;
|
1230 |
|
|
}
|
1231 |
|
|
|
1232 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1233 |
paus |
1.1 |
float MultiVertexFitterD::getDecayLength(vertexNumber nv, vertexNumber mv,
|
1234 |
|
|
const ThreeVector& dir, float& dlerr) const
|
1235 |
|
|
{
|
1236 |
|
|
Hep3Vector dirHep(dir.x(),dir.y(),dir.z());
|
1237 |
|
|
return getDecayLength(nv, mv, dirHep, dlerr);
|
1238 |
|
|
}
|
1239 |
|
|
|
1240 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1241 |
paus |
1.1 |
float MultiVertexFitterD::getZDecayLength(vertexNumber nv, vertexNumber mv,
|
1242 |
|
|
const Hep3Vector& mom, float& dlerr) const
|
1243 |
|
|
{
|
1244 |
|
|
//----------------------------------------------------------------------------
|
1245 |
|
|
// Get the signed decay length from vertex nv to vertex mv along the
|
1246 |
|
|
// z direction of the momentum vector, mom.
|
1247 |
|
|
// dlerr is the error on the decay length including the full error
|
1248 |
|
|
// matrix.
|
1249 |
|
|
//----------------------------------------------------------------------------
|
1250 |
|
|
// Start with good initialization
|
1251 |
|
|
dlerr = -999.;
|
1252 |
|
|
|
1253 |
|
|
// Check that the fit worked
|
1254 |
|
|
if (_stat != 0)
|
1255 |
|
|
return -999.;
|
1256 |
|
|
|
1257 |
|
|
// Check that vertices are within range.
|
1258 |
|
|
if (nv<0 || nv>=_ctvmq.nvertx)
|
1259 |
|
|
return -999.;
|
1260 |
|
|
if (mv<1 || mv> _ctvmq.nvertx)
|
1261 |
|
|
return -999.;
|
1262 |
|
|
if (nv >= mv)
|
1263 |
|
|
return -999.;
|
1264 |
|
|
|
1265 |
|
|
// Calculate the vector length
|
1266 |
|
|
float length = fabs(mom.z());
|
1267 |
|
|
if (length <= 0.)
|
1268 |
|
|
return -999.;
|
1269 |
|
|
|
1270 |
|
|
// Get the vector pointing from first vertex (nv) to second vertex (mv)
|
1271 |
|
|
Hep3Vector dv = getVertexHep(mv) - getVertexHep(nv);
|
1272 |
|
|
|
1273 |
|
|
//----------------------------------------------------------------------------
|
1274 |
|
|
// Calculate the "decay distance"
|
1275 |
|
|
//----------------------------------------------------------------------------
|
1276 |
|
|
// Project the vertex vector onto the momentum vector direction
|
1277 |
|
|
float dl = (dv.z()*mom.z())/length;
|
1278 |
|
|
|
1279 |
|
|
//----------------------------------------------------------------------------
|
1280 |
|
|
// Calculate the error on that distance
|
1281 |
|
|
//----------------------------------------------------------------------------
|
1282 |
|
|
// Set up the column matrix of derivatives
|
1283 |
|
|
HepMatrix A(2,1);
|
1284 |
|
|
A(1,1) = mom.z()/length;
|
1285 |
|
|
A(2,1) = -mom.z()/length;
|
1286 |
|
|
|
1287 |
|
|
// Need to catch the special case if the first vertex is the primary
|
1288 |
|
|
int nvf = 0;
|
1289 |
|
|
if (nv == 0) {
|
1290 |
|
|
nvf = -1;
|
1291 |
|
|
for (int jv=0; jv<_ctvmq.nvertx; ++jv) {
|
1292 |
|
|
if (_ctvmq.vtxpnt[0][jv] == 0)
|
1293 |
|
|
nvf = 0;
|
1294 |
|
|
}
|
1295 |
|
|
}
|
1296 |
|
|
// Get the relevant submatrix of the full error matrix.
|
1297 |
|
|
HepMatrix V(2,2,0);
|
1298 |
|
|
if (nvf < 0) {
|
1299 |
|
|
// Geometric uncertainties (positions second vertex)
|
1300 |
|
|
V(1,1) = getErrorMatrixHep(_ctvmq.voff[mv-1]+3,_ctvmq.voff[mv-1]+3);
|
1301 |
|
|
// Geometric uncertainties (positions first vertex)
|
1302 |
|
|
V(2,2) = _ctvmq.exyzpv[2][2];
|
1303 |
|
|
}
|
1304 |
|
|
else {
|
1305 |
|
|
// Get the indices into the error matrix vmat
|
1306 |
|
|
int index[2] = { _ctvmq.voff[mv-1]+3,_ctvmq.voff[nv-1]+3 };
|
1307 |
|
|
// Handeling the case of the primary vertex
|
1308 |
|
|
if (nv == 0)
|
1309 |
|
|
index[1] = 3;
|
1310 |
|
|
// All right... copy
|
1311 |
|
|
for(int j=0; j<2; ++j)
|
1312 |
|
|
for(int k=0; k<2; ++k)
|
1313 |
|
|
V[j][k] = getErrorMatrixHep(index[j],index[k]);
|
1314 |
|
|
}
|
1315 |
|
|
// Calculate square of dlerr
|
1316 |
|
|
dlerr = (A.T() * V * A )(1,1);
|
1317 |
|
|
if (dlerr >= 0.)
|
1318 |
|
|
dlerr = sqrt(dlerr);
|
1319 |
|
|
else
|
1320 |
|
|
dlerr = -sqrt(-dlerr);
|
1321 |
|
|
|
1322 |
|
|
return dl;
|
1323 |
|
|
}
|
1324 |
|
|
|
1325 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1326 |
paus |
1.1 |
float MultiVertexFitterD::getZDecayLength(vertexNumber nv, vertexNumber mv,
|
1327 |
|
|
const ThreeVector& mom, float& dlerr) const
|
1328 |
|
|
{
|
1329 |
|
|
Hep3Vector momHep(mom.x(),mom.y(),mom.z());
|
1330 |
|
|
return getZDecayLength(nv, mv, momHep, dlerr);
|
1331 |
|
|
}
|
1332 |
|
|
|
1333 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1334 |
paus |
1.1 |
float MultiVertexFitterD::getImpactPar(vertexNumber prdV, vertexNumber dcyV,
|
1335 |
|
|
const Hep3Vector &v, float &dxyerr) const
|
1336 |
|
|
{
|
1337 |
|
|
Hep3Vector PVtx = getVertexHep (prdV);
|
1338 |
|
|
Hep3Vector DVtx = getVertexHep (dcyV);
|
1339 |
|
|
HepSymMatrix PVtxCv = getErrorMatrixHep(prdV);
|
1340 |
|
|
HepSymMatrix DVtxCv = getErrorMatrixHep(dcyV);
|
1341 |
|
|
|
1342 |
|
|
double norma = v.perp();
|
1343 |
|
|
if (norma <= 0) {
|
1344 |
|
|
dxyerr = -999.;
|
1345 |
|
|
return -999.0;
|
1346 |
|
|
}
|
1347 |
|
|
double dxy = ((v.cross(DVtx-PVtx)).z())/norma;
|
1348 |
|
|
|
1349 |
|
|
// Calculate error on B impact parameter:
|
1350 |
|
|
double cosPhi = cos(v.phi());
|
1351 |
|
|
double sinPhi = sin(v.phi());
|
1352 |
|
|
dxyerr = cosPhi * cosPhi * (DVtxCv[1][1] + PVtxCv[1][1])
|
1353 |
|
|
+ sinPhi * sinPhi * (DVtxCv[0][0] + PVtxCv[0][0])
|
1354 |
|
|
- 2.0 * cosPhi * sinPhi * (DVtxCv[0][1] + PVtxCv[0][1]);
|
1355 |
|
|
dxyerr = (dxyerr>0.0) ? sqrt(dxyerr) : -999.;
|
1356 |
|
|
|
1357 |
|
|
return dxy;
|
1358 |
|
|
}
|
1359 |
|
|
|
1360 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1361 |
paus |
1.1 |
float MultiVertexFitterD::getImpactPar(vertexNumber prdV, vertexNumber dcyV,
|
1362 |
|
|
const ThreeVector &v, float &dxyerr) const
|
1363 |
|
|
{
|
1364 |
|
|
Hep3Vector vHep(v.x(),v.y(),v.z());
|
1365 |
|
|
return getImpactPar(prdV, dcyV, vHep, dxyerr);
|
1366 |
|
|
}
|
1367 |
|
|
|
1368 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1369 |
paus |
1.1 |
float MultiVertexFitterD::get_dr(vertexNumber nv, vertexNumber mv, float& drerr) const
|
1370 |
|
|
{
|
1371 |
|
|
drerr = -999.;
|
1372 |
|
|
if (_stat!=0)
|
1373 |
|
|
return -999.;
|
1374 |
|
|
// Get the transvese distance between vertices nv and mv and return it as the function value.
|
1375 |
|
|
// drerr is the uncertainty on the transverse distance, calculated from the full error matrix
|
1376 |
|
|
// including correlations.
|
1377 |
|
|
float dxyz[3];
|
1378 |
|
|
float dr;
|
1379 |
|
|
float dz;
|
1380 |
|
|
float dl[3];
|
1381 |
|
|
|
1382 |
|
|
int mvert = mv;
|
1383 |
|
|
int nvert = nv;
|
1384 |
|
|
// Copy information into CTVMFT common blocks
|
1385 |
|
|
*_ctvmq_com = _ctvmq;
|
1386 |
|
|
*_ctvmfr_com = _ctvmfr;
|
1387 |
|
|
// Do calculation
|
1388 |
|
|
ddcalc_(mvert,nvert,dxyz,dr,dz,dl);
|
1389 |
|
|
drerr = dl[0];
|
1390 |
|
|
return dr;
|
1391 |
|
|
}
|
1392 |
|
|
|
1393 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1394 |
paus |
1.1 |
float MultiVertexFitterD::get_dz(vertexNumber nv, vertexNumber mv, float& dzerr) const
|
1395 |
|
|
{
|
1396 |
|
|
dzerr = -999.;
|
1397 |
|
|
if (_stat!=0)
|
1398 |
|
|
return -999.;
|
1399 |
|
|
// Get the longitudinal distance between vertices nv and mv and return it as the function value.
|
1400 |
|
|
// dzerr is the uncertainty on the longitudinal distance, calculated from the full error matrix
|
1401 |
|
|
// including correlations.
|
1402 |
|
|
float dxyz[3];
|
1403 |
|
|
float dr;
|
1404 |
|
|
float dz;
|
1405 |
|
|
float dl[3];
|
1406 |
|
|
|
1407 |
|
|
int mvert = mv;
|
1408 |
|
|
int nvert = nv;
|
1409 |
|
|
// Copy information into CTVMFT common blocks
|
1410 |
|
|
*_ctvmq_com = _ctvmq;
|
1411 |
|
|
*_ctvmfr_com = _ctvmfr;
|
1412 |
|
|
|
1413 |
|
|
// Do calculation
|
1414 |
|
|
ddcalc_(mvert,nvert,dxyz,dr,dz,dl);
|
1415 |
|
|
dzerr = dl[1];
|
1416 |
|
|
return dz;
|
1417 |
|
|
}
|
1418 |
|
|
|
1419 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1420 |
paus |
1.1 |
Hep3Vector MultiVertexFitterD::getVertexHep(vertexNumber nv) const
|
1421 |
|
|
{
|
1422 |
|
|
if (_stat!=0)
|
1423 |
|
|
return Hep3Vector(-999,-999,-999);
|
1424 |
|
|
// Return x,y,z position of vertex nv.
|
1425 |
|
|
if (nv<0 || nv>_ctvmq.nvertx)
|
1426 |
|
|
return Hep3Vector(0,0,0);
|
1427 |
|
|
// Check if first vertex (nv) is primary vertex. If it is, check if it was used in the primary
|
1428 |
|
|
// vertex. If not, all of the corresponding error matrix elements are those supplied for the
|
1429 |
|
|
// primary vertex.
|
1430 |
|
|
int nvf=0;
|
1431 |
|
|
if (nv==0) {
|
1432 |
|
|
nvf=-1;
|
1433 |
|
|
for (int jv=0; jv<_ctvmq.nvertx; ++jv) {
|
1434 |
|
|
if (_ctvmq.vtxpnt[0][jv]==0)
|
1435 |
|
|
nvf=0;
|
1436 |
|
|
}
|
1437 |
|
|
}
|
1438 |
|
|
Hep3Vector vertex;
|
1439 |
|
|
// If primary vertex was not part of fit, take vertex location as supplied.
|
1440 |
|
|
if (nvf < 0) {
|
1441 |
|
|
vertex.setX(_ctvmq.xyzpv0[0]);
|
1442 |
|
|
vertex.setY(_ctvmq.xyzpv0[1]);
|
1443 |
|
|
vertex.setZ(_ctvmq.xyzpv0[2]);
|
1444 |
|
|
}
|
1445 |
|
|
else {
|
1446 |
|
|
vertex.setX(_ctvmq.xyzvrt[nv][0]);
|
1447 |
|
|
vertex.setY(_ctvmq.xyzvrt[nv][1]);
|
1448 |
|
|
vertex.setZ(_ctvmq.xyzvrt[nv][2]);
|
1449 |
|
|
}
|
1450 |
|
|
//// If we have a different reference point, need to add it back in
|
1451 |
|
|
//vertex += _referencePoint;
|
1452 |
|
|
return vertex;
|
1453 |
|
|
}
|
1454 |
|
|
|
1455 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1456 |
paus |
1.1 |
ThreeVector MultiVertexFitterD::getVertex(vertexNumber nv) const
|
1457 |
|
|
{
|
1458 |
|
|
if (_stat!=0)
|
1459 |
|
|
return ThreeVector(-999,-999,-999);
|
1460 |
|
|
// Return x,y,z position of vertex nv.
|
1461 |
|
|
if (nv<0 || nv>_ctvmq.nvertx)
|
1462 |
|
|
return ThreeVector(0,0,0);
|
1463 |
|
|
// Check if first vertex (nv) is primary vertex. If it is, check if it was used in the primary
|
1464 |
|
|
// vertex. If not, all of the corresponding error matrix elements are those supplied for the
|
1465 |
|
|
// primary vertex.
|
1466 |
|
|
int nvf=0;
|
1467 |
|
|
if (nv==0) {
|
1468 |
|
|
nvf=-1;
|
1469 |
|
|
for (int jv=0; jv<_ctvmq.nvertx; ++jv) {
|
1470 |
|
|
if (_ctvmq.vtxpnt[0][jv]==0)
|
1471 |
|
|
nvf=0;
|
1472 |
|
|
}
|
1473 |
|
|
}
|
1474 |
|
|
ThreeVector vertex;
|
1475 |
|
|
// If primary vertex was not part of fit, take vertex location as supplied.
|
1476 |
|
|
if (nvf < 0) {
|
1477 |
|
|
vertex.SetX(_ctvmq.xyzpv0[0]);
|
1478 |
|
|
vertex.SetY(_ctvmq.xyzpv0[1]);
|
1479 |
|
|
vertex.SetZ(_ctvmq.xyzpv0[2]);
|
1480 |
|
|
}
|
1481 |
|
|
else {
|
1482 |
|
|
vertex.SetX(_ctvmq.xyzvrt[nv][0]);
|
1483 |
|
|
vertex.SetY(_ctvmq.xyzvrt[nv][1]);
|
1484 |
|
|
vertex.SetZ(_ctvmq.xyzvrt[nv][2]);
|
1485 |
|
|
}
|
1486 |
|
|
// If we have a different reference point, need to add it back in
|
1487 |
|
|
vertex += _referencePoint;
|
1488 |
|
|
return vertex;
|
1489 |
|
|
}
|
1490 |
|
|
|
1491 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1492 |
paus |
1.1 |
ThreeSymMatrix MultiVertexFitterD::getErrorMatrix(MultiVertexFitterD::vertexNumber nv) const
|
1493 |
|
|
{
|
1494 |
|
|
// return errors for vertex nv
|
1495 |
|
|
ThreeSymMatrix cov;
|
1496 |
|
|
|
1497 |
|
|
// if this is the primary vertex, return the error matrix the user supplied
|
1498 |
|
|
if (nv==PRIMARY_VERTEX) {
|
1499 |
|
|
for (int j=0; j<3; j++)
|
1500 |
|
|
for (int k=0; k<3; k++)
|
1501 |
|
|
cov(j,k) = _ctvmq.exyzpv[j][k];
|
1502 |
|
|
return cov;
|
1503 |
|
|
}
|
1504 |
|
|
|
1505 |
|
|
if (_stat!=0)
|
1506 |
|
|
return cov;
|
1507 |
|
|
// return x,y,z position of vertex nv
|
1508 |
|
|
if (nv<VERTEX_1 || nv>_ctvmq.nvertx)
|
1509 |
|
|
return cov;
|
1510 |
|
|
// get offset for vertex nv
|
1511 |
|
|
int voff = _ctvmq.voff[nv-1];
|
1512 |
|
|
// fill matrix
|
1513 |
|
|
for (int i=0; i<3; ++i)
|
1514 |
|
|
for (int j=i; j<3; ++j)
|
1515 |
|
|
cov(i,j) = _ctvmfr.vmat[voff+i][voff+j];
|
1516 |
|
|
return cov;
|
1517 |
|
|
}
|
1518 |
|
|
|
1519 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1520 |
paus |
1.1 |
double MultiVertexFitterD::getErrorMatrixHep(int j, int k) const
|
1521 |
|
|
{
|
1522 |
|
|
if (_stat!=0)
|
1523 |
|
|
return -999.;
|
1524 |
|
|
// Return the j,k element of the full error matrix VMAT. Since the CTVMFT documentation assumes
|
1525 |
|
|
// the indices start from 1 (ala Fortran), we will also assume this and convert the C++ indices.
|
1526 |
|
|
// Note also the that order of Fortran and C++ indices is different. We assume that j and k are
|
1527 |
|
|
// in the Fortran order.
|
1528 |
|
|
if (j<1 || k<1 || j>_maxdim+1 || k>_maxdim)
|
1529 |
|
|
return -999.;
|
1530 |
|
|
|
1531 |
|
|
return _ctvmfr.vmat[k-1][j-1];
|
1532 |
|
|
}
|
1533 |
|
|
|
1534 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1535 |
paus |
1.1 |
HepSymMatrix MultiVertexFitterD::getErrorMatrixHep(MultiVertexFitterD::vertexNumber nv) const
|
1536 |
|
|
{
|
1537 |
|
|
// return errors for vertex nv
|
1538 |
|
|
HepSymMatrix cov(3,0);
|
1539 |
|
|
|
1540 |
|
|
// if this is the primary vertex, return the error matrix the user supplied
|
1541 |
|
|
if (nv==PRIMARY_VERTEX) {
|
1542 |
|
|
for (int j=0; j<3; j++)
|
1543 |
|
|
for (int k=0; k<3; k++)
|
1544 |
|
|
cov[j][k] = _ctvmq.exyzpv[j][k];
|
1545 |
|
|
return cov;
|
1546 |
|
|
}
|
1547 |
|
|
|
1548 |
|
|
if (_stat!=0)
|
1549 |
|
|
return cov;
|
1550 |
|
|
// return x,y,z position of vertex nv
|
1551 |
|
|
if (nv<VERTEX_1 || nv>_ctvmq.nvertx)
|
1552 |
|
|
return cov;
|
1553 |
|
|
// get offset for vertex nv
|
1554 |
|
|
int voff = _ctvmq.voff[nv-1];
|
1555 |
|
|
// fill matrix
|
1556 |
|
|
for (int i=0; i<3; ++i)
|
1557 |
|
|
for (int j=i; j<3; ++j)
|
1558 |
|
|
cov[i][j] = _ctvmfr.vmat[voff+i][voff+j];
|
1559 |
|
|
return cov;
|
1560 |
|
|
}
|
1561 |
|
|
|
1562 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1563 |
paus |
1.1 |
HepSymMatrix MultiVertexFitterD::getErrorMatrixHep(const int trkId) const
|
1564 |
|
|
{
|
1565 |
|
|
HepSymMatrix cov(3,0);
|
1566 |
|
|
if (_stat != 0)
|
1567 |
|
|
return cov;
|
1568 |
|
|
|
1569 |
|
|
for (int nt=0; nt<_ctvmq.ntrack; ++nt) {
|
1570 |
|
|
|
1571 |
|
|
// Find which track matches this Id
|
1572 |
|
|
if (trkId == _ctvmq.list[nt]) {
|
1573 |
|
|
|
1574 |
|
|
// Position of track nt get offset for track nt
|
1575 |
|
|
int toff = _ctvmq.toff[nt];
|
1576 |
|
|
|
1577 |
|
|
// Fill matrix -- Crv,Phi,Ctg
|
1578 |
|
|
for (int i=0; i<3; ++i)
|
1579 |
|
|
for (int j=i; j<3; ++j)
|
1580 |
|
|
cov[i][j] = _ctvmfr.vmat[toff+i][toff+j];
|
1581 |
|
|
}
|
1582 |
|
|
}
|
1583 |
|
|
return cov;
|
1584 |
|
|
}
|
1585 |
|
|
|
1586 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1587 |
paus |
1.1 |
float MultiVertexFitterD::getPtError(const int trkId) const
|
1588 |
|
|
{
|
1589 |
|
|
if (_stat != 0)
|
1590 |
|
|
return 0;
|
1591 |
|
|
|
1592 |
|
|
int toff;
|
1593 |
|
|
float pt,curv,curvErr,ptErr;
|
1594 |
|
|
|
1595 |
|
|
for (int nt=0; nt<_ctvmq.ntrack; ++nt) {
|
1596 |
|
|
|
1597 |
|
|
// Find which track matches this Id
|
1598 |
|
|
if (trkId == _ctvmq.list[nt]) {
|
1599 |
|
|
|
1600 |
|
|
// Position of track nt get offset for track nt
|
1601 |
|
|
toff = _ctvmq.toff[nt];
|
1602 |
|
|
|
1603 |
|
|
// Curvature error
|
1604 |
|
|
pt = sqrt(_ctvmq.trkp4[0][nt]*_ctvmq.trkp4[0][nt] +
|
1605 |
|
|
_ctvmq.trkp4[1][nt]*_ctvmq.trkp4[1][nt]);
|
1606 |
|
|
curv = _ctvmq.pscale/pt;
|
1607 |
|
|
curvErr = sqrt(_ctvmfr.vmat[toff+0][toff+0]);
|
1608 |
|
|
ptErr = _ctvmq.pscale/curv/curv*curvErr;
|
1609 |
|
|
return ptErr;
|
1610 |
|
|
}
|
1611 |
|
|
}
|
1612 |
|
|
|
1613 |
|
|
return 0;
|
1614 |
|
|
}
|
1615 |
|
|
|
1616 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1617 |
paus |
1.1 |
void MultiVertexFitterD::getPosMomErr(HepMatrix& errors) const
|
1618 |
|
|
{
|
1619 |
|
|
// A c++ rewrite of the FORTRAN MASSAG function The result of this function is an error matrix in
|
1620 |
|
|
// position-momentum basis. A 7x7 matrix of errors where the rows/columns are x, y, z, px, py,
|
1621 |
|
|
// pz, e.
|
1622 |
|
|
|
1623 |
|
|
double cosph [_maxtrk];
|
1624 |
|
|
double sinph [_maxtrk];
|
1625 |
|
|
double cosdph[_maxtrk];
|
1626 |
|
|
double sindph[_maxtrk];
|
1627 |
|
|
Hep3Vector mom3 [_maxtrk];
|
1628 |
|
|
HepLorentzVector pmom [_maxtrk];
|
1629 |
|
|
HepLorentzVector total_mom;
|
1630 |
|
|
|
1631 |
|
|
for (int lvtx = 0; lvtx < _ctvmq.nvertx; lvtx++) {
|
1632 |
|
|
for (int ltrk = 0; ltrk < _ctvmq.ntrack; ltrk++) {
|
1633 |
|
|
if (!_ctvmq.trkvtx[lvtx][ltrk])
|
1634 |
|
|
continue;
|
1635 |
|
|
cosph[ltrk] = cos(_ctvmq.par[ltrk][1]);
|
1636 |
|
|
sinph[ltrk] = sin(_ctvmq.par[ltrk][1]);
|
1637 |
|
|
double dphi = 0;
|
1638 |
|
|
sindph[ltrk] = 2 * _ctvmq.par[ltrk][0] *
|
1639 |
|
|
(_ctvmq.xyzvrt[lvtx + 1][0] * cosph[ltrk] +
|
1640 |
|
|
_ctvmq.xyzvrt[lvtx + 1][1] * sinph[ltrk]);
|
1641 |
|
|
cosdph[ltrk] = sqrt(1.0 - sindph[ltrk] * sindph[ltrk]);
|
1642 |
|
|
if (fabs(sindph[ltrk]) <= 1.0){
|
1643 |
|
|
dphi = asin(sindph[ltrk]);
|
1644 |
|
|
}
|
1645 |
|
|
double pt = _ctvmq.pscale * fabs(1./_ctvmq.par[ltrk][0]);
|
1646 |
|
|
mom3[ltrk].setX(pt * cos(_ctvmq.par[ltrk][1] + dphi));
|
1647 |
|
|
mom3[ltrk].setY(pt * sin(_ctvmq.par[ltrk][1] + dphi));
|
1648 |
|
|
mom3[ltrk].setZ(pt * _ctvmq.par[ltrk][2]);
|
1649 |
|
|
double e = sqrt(_ctvmq.tmass[ltrk] * _ctvmq.tmass[ltrk]
|
1650 |
|
|
+ mom3[ltrk].mag2());
|
1651 |
|
|
pmom[ltrk].setVect(mom3[ltrk]);
|
1652 |
|
|
pmom[ltrk].setE(e);
|
1653 |
|
|
|
1654 |
|
|
total_mom += pmom[ltrk];
|
1655 |
|
|
}
|
1656 |
|
|
}
|
1657 |
|
|
|
1658 |
|
|
// Easy so far, but now it gets ugly: fill dp_dpar with the derivatives of the position and
|
1659 |
|
|
// momentum with respect to the parameters
|
1660 |
|
|
|
1661 |
|
|
int ctvmft_dim = 3 * (_ctvmq.nvertx + _ctvmq.ntrack);
|
1662 |
|
|
HepMatrix deriv(ctvmft_dim, 7, 0);
|
1663 |
|
|
//HepMatrix dp_dpar[_maxvtx] = { deriv, deriv, deriv };
|
1664 |
|
|
HepMatrix dp_dpar[_maxvtx] = { deriv };
|
1665 |
|
|
|
1666 |
|
|
// Fill the x, y, z rows:
|
1667 |
|
|
for (int nvtx = 0; nvtx < _ctvmq.nvertx; nvtx++) {
|
1668 |
|
|
for (int lcomp = 0; lcomp < 3; lcomp++){
|
1669 |
|
|
dp_dpar[nvtx][(3 * nvtx) + lcomp][lcomp] = 1.0;
|
1670 |
|
|
}
|
1671 |
|
|
|
1672 |
|
|
// Fill the px, py, pz, e rows:
|
1673 |
|
|
for (int lvtx = 0; lvtx < _ctvmq.nvertx; lvtx++){
|
1674 |
|
|
for (int ltrk = 0; ltrk < _ctvmq.ntrack; ltrk++){
|
1675 |
|
|
if (!_ctvmq.trkvtx[lvtx][ltrk])
|
1676 |
|
|
continue;
|
1677 |
|
|
|
1678 |
|
|
// Find the derivatives of dphi with respect to x, y, curvature, and phi0:
|
1679 |
|
|
double dphi_dx = 2.0 * _ctvmq.par[ltrk][0] * cosph[ltrk]/cosdph[ltrk];
|
1680 |
|
|
double dphi_dy = 2.0 * _ctvmq.par[ltrk][0] * sinph[ltrk]/cosdph[ltrk];
|
1681 |
|
|
double dphi_dc = 2.0 *
|
1682 |
|
|
(_ctvmq.xyzvrt[lvtx + 1][0] * cosph[ltrk] +
|
1683 |
|
|
_ctvmq.xyzvrt[lvtx + 1][1] * sinph[ltrk])/cosdph[ltrk];
|
1684 |
|
|
double dphi_dp = 2.0 * _ctvmq.par[ltrk][0] *
|
1685 |
|
|
(-_ctvmq.xyzvrt[lvtx + 1][0] * sinph[ltrk] +
|
1686 |
|
|
_ctvmq.xyzvrt[lvtx + 1][1] * cosph[ltrk])/cosdph[ltrk];
|
1687 |
|
|
|
1688 |
|
|
// Now load the derivative matrix
|
1689 |
|
|
int lvele = 3 * lvtx;
|
1690 |
|
|
// dPx/dx:
|
1691 |
|
|
dp_dpar[nvtx][lvele][3] += -pmom[ltrk].y() * dphi_dx;
|
1692 |
|
|
// dPy/dx:
|
1693 |
|
|
dp_dpar[nvtx][lvele][4] += pmom[ltrk].x() * dphi_dx;
|
1694 |
|
|
// dPz/dx:
|
1695 |
|
|
dp_dpar[nvtx][lvele][5] = 0.;
|
1696 |
|
|
// dPy/dx:
|
1697 |
|
|
dp_dpar[nvtx][lvele][6] = 0.;
|
1698 |
|
|
|
1699 |
|
|
lvele++;
|
1700 |
|
|
// dPx/dy:
|
1701 |
|
|
dp_dpar[nvtx][lvele][3] += -pmom[ltrk].y() * dphi_dy;
|
1702 |
|
|
// dPy/dy:
|
1703 |
|
|
dp_dpar[nvtx][lvele][4] += pmom[ltrk].x() * dphi_dy;
|
1704 |
|
|
// dPz/dy:
|
1705 |
|
|
dp_dpar[nvtx][lvele][5] = 0.;
|
1706 |
|
|
// dE/dy:
|
1707 |
|
|
dp_dpar[nvtx][lvele][6] = 0.;
|
1708 |
|
|
|
1709 |
|
|
lvele++;
|
1710 |
|
|
// dPx/dz:
|
1711 |
|
|
dp_dpar[nvtx][lvele][3] = 0.;
|
1712 |
|
|
// dPy/dz:
|
1713 |
|
|
dp_dpar[nvtx][lvele][4] = 0.;
|
1714 |
|
|
// dPz/dz:
|
1715 |
|
|
dp_dpar[nvtx][lvele][5] = 0.;
|
1716 |
|
|
// dE/dz:
|
1717 |
|
|
dp_dpar[nvtx][lvele][6] = 0.;
|
1718 |
|
|
|
1719 |
|
|
lvele = 3 * (ltrk + _ctvmq.nvertx);
|
1720 |
|
|
// dPx/dcurv[ltrk]:
|
1721 |
|
|
dp_dpar[nvtx][lvele][3] = -(pmom[ltrk].x()/_ctvmq.par[ltrk][0])
|
1722 |
|
|
- pmom[ltrk].y() * dphi_dc;
|
1723 |
|
|
// dPy/dcurv[ltrk]:
|
1724 |
|
|
dp_dpar[nvtx][lvele][4] = -(pmom[ltrk].y()/_ctvmq.par[ltrk][0])
|
1725 |
|
|
+ pmom[ltrk].x() * dphi_dc;
|
1726 |
|
|
// dPz/dcurv[ltrk]:
|
1727 |
|
|
dp_dpar[nvtx][lvele][5] = -(pmom[ltrk].z()/_ctvmq.par[ltrk][0]);
|
1728 |
|
|
// dE/dcurv[ltrk]:
|
1729 |
|
|
dp_dpar[nvtx][lvele][6] =
|
1730 |
|
|
-mom3[ltrk].mag2()/(_ctvmq.par[ltrk][0] * pmom[ltrk].e());
|
1731 |
|
|
|
1732 |
|
|
lvele++;
|
1733 |
|
|
// dPx/dphi[ltrk]:
|
1734 |
|
|
dp_dpar[nvtx][lvele][3] = -pmom[ltrk].y() * (1.0 + dphi_dp);
|
1735 |
|
|
// dPy/dphi[ltrk]:
|
1736 |
|
|
dp_dpar[nvtx][lvele][4] = pmom[ltrk].x() * (1.0 + dphi_dp);
|
1737 |
|
|
// dPz/dphi[ltrk]:
|
1738 |
|
|
dp_dpar[nvtx][lvele][5] = 0.;
|
1739 |
|
|
// dE/dphi[ltrk]:
|
1740 |
|
|
dp_dpar[nvtx][lvele][6] = 0.;
|
1741 |
|
|
|
1742 |
|
|
lvele++;
|
1743 |
|
|
// dPx/dcot[ltrk]:
|
1744 |
|
|
dp_dpar[nvtx][lvele][3] = 0;
|
1745 |
|
|
// dPy/dcot[ltrk]:
|
1746 |
|
|
dp_dpar[nvtx][lvele][4] = 0;
|
1747 |
|
|
// dPz/dcot[ltrk]:
|
1748 |
|
|
dp_dpar[nvtx][lvele][5] = pmom[ltrk].perp();
|
1749 |
|
|
// dE/dcot[ltrk]:
|
1750 |
|
|
dp_dpar[nvtx][lvele][6] =
|
1751 |
|
|
pmom[ltrk].perp2() * _ctvmq.par[ltrk][2] / pmom[ltrk].e();
|
1752 |
|
|
}
|
1753 |
|
|
}
|
1754 |
|
|
}
|
1755 |
|
|
|
1756 |
|
|
// -----------------------------------------------------------------------------------------------
|
1757 |
|
|
// Now calculate the new error matrix
|
1758 |
|
|
// -----------------------------------------------------------------------------------------------
|
1759 |
|
|
// Extract the interesting bits from VMAT
|
1760 |
|
|
HepMatrix vmat(ctvmft_dim,ctvmft_dim,0);
|
1761 |
|
|
for (int lpar = 0; lpar < ctvmft_dim; lpar++){
|
1762 |
|
|
int l = lpar%3;
|
1763 |
|
|
int lvele = 0;
|
1764 |
|
|
if (lpar < 3 * _ctvmq.nvertx){
|
1765 |
|
|
int lvtx = lpar/3;
|
1766 |
|
|
lvele = _ctvmq.voff[lvtx] + l;
|
1767 |
|
|
}
|
1768 |
|
|
else {
|
1769 |
|
|
int ltrk = (lpar - 3 * _ctvmq.nvertx)/3;
|
1770 |
|
|
lvele = _ctvmq.toff[ltrk] + l;
|
1771 |
|
|
}
|
1772 |
|
|
for (int kpar = 0; kpar < ctvmft_dim; kpar++) {
|
1773 |
|
|
int k = kpar%3;
|
1774 |
|
|
int kvele = 0;
|
1775 |
|
|
if (kpar < 3 * _ctvmq.nvertx) {
|
1776 |
|
|
int kvtx = kpar/3;
|
1777 |
|
|
kvele = _ctvmq.voff[kvtx] + k;
|
1778 |
|
|
}
|
1779 |
|
|
else{
|
1780 |
|
|
int ktrk = (kpar - 3 * _ctvmq.nvertx)/3;
|
1781 |
|
|
kvele = _ctvmq.toff[ktrk] + k;
|
1782 |
|
|
}
|
1783 |
|
|
vmat[kpar][lpar] = _ctvmfr.vmat[kvele][lvele];
|
1784 |
|
|
}
|
1785 |
|
|
}
|
1786 |
|
|
|
1787 |
|
|
// Just about done
|
1788 |
|
|
HepMatrix ans(7,7,0);
|
1789 |
|
|
//HepMatrix answer[_maxvtx] = { ans, ans, ans };
|
1790 |
|
|
HepMatrix answer[_maxvtx] = { ans };
|
1791 |
|
|
for (int nvtx = 0; nvtx < _ctvmq.nvertx; nvtx++)
|
1792 |
|
|
answer[nvtx] = (dp_dpar[nvtx].T() * vmat) * dp_dpar[nvtx];
|
1793 |
|
|
errors = answer[0];
|
1794 |
|
|
}
|
1795 |
|
|
|
1796 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1797 |
paus |
1.1 |
int MultiVertexFitterD::vOff(vertexNumber jv) const
|
1798 |
|
|
{
|
1799 |
|
|
if (jv < VERTEX_1 || jv > _maxvtx)
|
1800 |
|
|
return -999;
|
1801 |
|
|
else
|
1802 |
|
|
return _ctvmq.voff[jv-1];
|
1803 |
|
|
}
|
1804 |
|
|
|
1805 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1806 |
paus |
1.1 |
int MultiVertexFitterD::tOff(const int trkId) const
|
1807 |
|
|
{
|
1808 |
|
|
for (int kt=0; kt<_ctvmq.ntrack; ++kt) {
|
1809 |
|
|
if (trkId == _ctvmq.list[kt])
|
1810 |
|
|
return _ctvmq.toff[kt];
|
1811 |
|
|
}
|
1812 |
|
|
return -999;
|
1813 |
|
|
}
|
1814 |
|
|
|
1815 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1816 |
paus |
1.1 |
int MultiVertexFitterD::pOff(int lp) const
|
1817 |
|
|
{
|
1818 |
|
|
if (lp < 1)
|
1819 |
|
|
return -999;
|
1820 |
|
|
else
|
1821 |
|
|
return _ctvmq.poff[lp-1];
|
1822 |
|
|
}
|
1823 |
|
|
|
1824 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1825 |
paus |
1.1 |
int MultiVertexFitterD::cOff(int lc) const
|
1826 |
|
|
{
|
1827 |
|
|
if (lc < 1)
|
1828 |
|
|
return -999;
|
1829 |
|
|
else
|
1830 |
|
|
return _ctvmq.coff[lc-1];
|
1831 |
|
|
}
|
1832 |
|
|
|
1833 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1834 |
paus |
1.1 |
int MultiVertexFitterD::mOff() const
|
1835 |
|
|
{
|
1836 |
|
|
return _ctvmq.moff;
|
1837 |
|
|
}
|
1838 |
|
|
|
1839 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1840 |
paus |
1.1 |
double MultiVertexFitterD::VMat(int i, int j) const
|
1841 |
|
|
{
|
1842 |
|
|
if (i <0 || j < 0)
|
1843 |
|
|
return -999.;
|
1844 |
|
|
else
|
1845 |
|
|
return _ctvmfr.vmat[i][j];
|
1846 |
|
|
}
|
1847 |
|
|
|
1848 |
|
|
// Facilitates CandNode recursion. CandNodes have no way of deciding which vertex they are, and
|
1849 |
|
|
// these trivial functions help them do that.
|
1850 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1851 |
paus |
1.1 |
MultiVertexFitterD::vertexNumber MultiVertexFitterD::allocateVertexNumber()
|
1852 |
|
|
{
|
1853 |
|
|
if ((_currentAllocatedVertexNumber < PRIMARY_VERTEX) ||
|
1854 |
|
|
(_currentAllocatedVertexNumber > _maxvtx)) {
|
1855 |
|
|
cout << "MultiVertexFitterD::allocateVertexNumber: out of range!" << endl;
|
1856 |
|
|
return PRIMARY_VERTEX;
|
1857 |
|
|
}
|
1858 |
|
|
return vertexNumber(++_currentAllocatedVertexNumber);
|
1859 |
|
|
}
|
1860 |
|
|
|
1861 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1862 |
paus |
1.1 |
void MultiVertexFitterD::resetAllocatedVertexNumber()
|
1863 |
|
|
{
|
1864 |
|
|
_currentAllocatedVertexNumber = 0;
|
1865 |
|
|
}
|
1866 |
|
|
|
1867 |
loizides |
1.2 |
//--------------------------------------------------------------------------------------------------
|
1868 |
paus |
1.1 |
void MultiVertexFitterD::restoreFromCommons()
|
1869 |
|
|
{
|
1870 |
|
|
_stat = 0;
|
1871 |
|
|
_ctvmq_com = (CTVMQ*) dctvmq_address_();
|
1872 |
|
|
_ctvmfr_com = (CTVMFR*) dctvmfr_address_();
|
1873 |
|
|
_fiddle_com = (FIDDLE*) dfiddle_address_();
|
1874 |
|
|
_trkprm_com = (TRKPRM*) dtrkprm_address_();
|
1875 |
|
|
_ctvmq = *_ctvmq_com;
|
1876 |
|
|
_ctvmfr = *_ctvmfr_com;
|
1877 |
|
|
_fiddle = *_fiddle_com;
|
1878 |
|
|
_trkprm = *_trkprm_com;
|
1879 |
|
|
}
|