1
/* This file is part of MAUS: http://micewww.pp.rl.ac.uk:8080/projects/maus
3
* MAUS is free software: you can redistribute it and/or modify
4
* it under the terms of the GNU General Public License as published by
5
* the Free Software Foundation, either version 3 of the License, or
6
* (at your option) any later version.
8
* MAUS is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with MAUS. If not, see <http://www.gnu.org/licenses/>.
18
#include "src/common_cpp/Recon/Kalman/MAUSTrackWrapper.hh"
26
template<class ELEMENT>
27
bool SortByZ(const ELEMENT *a, const ELEMENT *b) {
28
return (a->get_position().z() > b->get_position().z());
33
Kalman::Track BuildTrack(SciFiClusterPArray cluster_array, const SciFiGeometryHelper* geom) {
34
Kalman::Track new_track(1);
35
size_t numbclusters = cluster_array.size();
37
if (numbclusters < 1) return new_track;
38
int tracker = cluster_array[0]->get_tracker();
40
const SciFiPlaneMap& geom_map = geom->GeometryMap().find(tracker)->second.Planes;
41
int tracker_const = (tracker == 0 ? -1 : 1);
43
for (SciFiPlaneMap::const_iterator iter = geom_map.begin(); iter != geom_map.end(); ++iter) {
44
int id = iter->first * tracker_const;
45
Kalman::State new_state = Kalman::State(1, iter->second.Position.z());
47
new_track.Append(new_state);
50
for (size_t j = 0; j < numbclusters; ++j) {
51
SciFiCluster* cluster = cluster_array[j];
53
int id = (cluster->get_station() - 1)*3 + cluster->get_plane(); // Actually (id - 1)
56
// - APPLY GEOMETRY CORRECTIONS!
57
// - Fill covariance matrix correctly!
58
TMatrixD state_vector(1, 1);
59
TMatrixD covariance(1, 1);
61
state_vector(0, 0) = cluster->get_alpha();
62
covariance(0, 0) = 0.0;
64
new_track[id].SetVector(state_vector);
65
new_track[id].SetCovariance(covariance);
73
Kalman::State ComputeSeed(SciFiHelicalPRTrack* h_track, const SciFiGeometryHelper* geom,
74
bool correct_energy_loss, double seed_cov) {
75
TMatrixD vector(5, 1);
76
TMatrixD covariance(5, 5);
78
int tracker = h_track->get_tracker();
79
int seed_id = (tracker == 0 ? -15 : 15);
80
double seed_pos = geom->GetPlanePosition(tracker, 5, 2);
81
double length = seed_pos;
82
double c = CLHEP::c_light;
83
double particle_charge = h_track->get_charge();
84
double Bz = geom->GetFieldValue(tracker);
86
// Get h_track values.
87
double r = h_track->get_R();
88
double pt = - c*Bz*r*particle_charge;
89
double dsdz = - h_track->get_dsdz();
90
double x0 = h_track->get_circle_x0(); // Circle Center x
91
double y0 = h_track->get_circle_y0(); // Circle Center y
92
double s = (h_track->get_line_sz_c() - length*dsdz); // Path length at start plane
93
double phi_0 = s / r; // Phi at start plane
94
double phi = phi_0 + TMath::PiOver2(); // Direction of momentum
96
// TODO: Actually propagate the track parrameters and covariance matrix back to start plane.
97
// This is an approximation.
98
ThreeVector patrec_momentum(-pt*sin(phi_0), pt*cos(phi_0), - pt/dsdz);
100
if (correct_energy_loss) {
101
double P = patrec_momentum.mag();
102
double patrec_bias; // Account for two planes of energy loss
104
patrec_bias = (P + 1.4) / P;
106
patrec_bias = (P + 1.4) / P;
108
patrec_momentum = patrec_bias * patrec_momentum;
111
double x = x0 + r*cos(phi_0);
112
double px = patrec_momentum.x();
113
double y = y0 + r*sin(phi_0);
114
double py = patrec_momentum.y();
115
double kappa = particle_charge / patrec_momentum.z();
121
vector(4, 0) = kappa;
124
// METHOD = ED SANTOS
126
if (seed_cov > 0.0) {
128
for (int i = 0; i < 5; ++i) {
129
covariance(i, i) = seed_cov;
133
// METHOD = CHRISTOPHER HUNT
135
std::vector<double> cov = h_track->get_covariance();
136
TMatrixD patrec_covariance(5, 5);
137
if (cov.size() != 25) {
138
throw MAUS::Exception(MAUS::Exception::recoverable,
139
"Dimension of covariance matrix does not match the state vector",
140
"KalmanSeed::ComputeInitalCovariance(Helical)");
143
double mc = particle_charge*c*Bz; // Magnetic constant
144
double sin = std::sin(phi_0);
145
double cos = std::cos(phi_0);
146
double sin_plus = std::sin(phi);
147
double cos_plus = std::cos(phi);
149
TMatrixD jacobian(5, 5);
150
jacobian(0, 0) = 1.0;
151
jacobian(0, 2) = cos + phi*sin;
152
jacobian(0, 3) = -sin;
154
jacobian(1, 2) = mc*cos_plus + mc*phi*sin_plus;
155
jacobian(1, 3) = -mc*sin_plus;
157
jacobian(2, 1) = 1.0;
158
jacobian(2, 2) = sin - phi*cos;
159
jacobian(2, 3) = cos;
161
jacobian(3, 2) = mc*sin_plus - mc*phi*cos_plus;
162
jacobian(1, 3) = mc*cos_plus;
164
jacobian(4, 3) = -dsdz / (mc*r*r);
165
jacobian(4, 4) = 1.0 / (mc*r);
167
TMatrixD jacobianT(5, 5);
168
jacobianT.Transpose(jacobian);
170
for (int i = 0; i < 5; ++i) {
171
for (int j = 0; j < 5; ++j) {
172
patrec_covariance(i, j) = cov.at(i*5 + j);
175
covariance = jacobian*patrec_covariance*jacobianT;
178
Kalman::State seed_state(vector, covariance, seed_pos);
179
seed_state.SetId(seed_id);
185
Kalman::State ComputeSeed(SciFiStraightPRTrack* s_track, const SciFiGeometryHelper* geom,
187
TMatrixD vector(4, 1);
188
TMatrixD covariance(4, 4);
190
int tracker = s_track->get_tracker();
191
double seed_pos = geom->GetPlanePosition(tracker, 5, 2);
192
double length = seed_pos;
193
int seed_id = (tracker == 0 ? -15 : 15);
195
double x0 = s_track->get_x0();
196
double y0 = s_track->get_y0();
197
double mx = s_track->get_mx();
198
double my = s_track->get_my();
200
// Get position at the starting end of tracker
201
double x = x0 + mx*length;
202
double y = y0 + my*length;
210
// METHOD = ED SANTOS
212
if (seed_cov > 0.0) {
214
for (int i = 0; i < 4; ++i) {
215
covariance(i, i) = seed_cov;
219
// METHOD = CHRISTOPHER HUNT
221
std::vector<double> cov = s_track->get_covariance();
222
TMatrixD patrec_covariance(4, 4);
224
if (cov.size() != (unsigned int)16) {
225
throw MAUS::Exception(MAUS::Exception::recoverable,
226
"Dimension of covariance matrix does not match the state vector",
227
"KalmanSeed::ComputeInitalCovariance(Straight)");
230
TMatrixD jacobian(4, 4);
231
jacobian(0, 0) = 1.0;
232
jacobian(1, 1) = 1.0;
233
jacobian(2, 2) = 1.0;
234
jacobian(3, 3) = 1.0;
235
jacobian(0, 1) = length;
236
jacobian(2, 3) = length;
238
TMatrixD jacobianT(4, 4);
239
jacobianT.Transpose(jacobian);
241
for (int i = 0; i < 4; ++i) {
242
for (int j = 0; j < 4; ++j) {
243
patrec_covariance(i, j) = cov.at(i*4 + j);
247
covariance = jacobian*patrec_covariance*jacobianT;
250
Kalman::State seed_state(vector, covariance, seed_pos);
251
seed_state.SetId(seed_id);
256
SciFiTrack* ConvertToSciFiTrack(const Kalman::TrackFit* fitter,
257
const SciFiGeometryHelper* geom) {
258
SciFiTrack* new_track = new SciFiTrack();
259
const Kalman::Track& smoothed = fitter->Smoothed();
260
// const Kalman::Track& smoothed = fitter->Filtered();
261
// const Kalman::Track& filtered = fitter->Filtered();
262
// const Kalman::Track& predicted = fitter->Predicted();
263
const Kalman::Track& data = fitter->Data();
264
Kalman::State seed = fitter->GetSeed();
265
double default_mom = geom->GetDefaultMomentum();
267
if (smoothed.GetLength() < 1)
268
throw MAUS::Exception(MAUS::Exception::recoverable,
269
"Not enough points in Kalman Track",
270
"ConvertToSciFiTrack()");
272
double chi_squared = fitter->CalculateChiSquared(smoothed);
273
int NDF = fitter->GetNDF();
274
double p_value = TMath::Prob(chi_squared, NDF);
277
if (smoothed[0].GetId() > 0) {
282
new_track->set_tracker(tracker);
284
int dimension = smoothed.GetDimension();
285
if (dimension == 4) {
286
new_track->SetAlgorithmUsed(SciFiTrack::kalman_straight);
287
} else if (dimension == 5) {
288
new_track->SetAlgorithmUsed(SciFiTrack::kalman_helical);
290
throw MAUS::Exception(MAUS::Exception::recoverable,
291
"Unexpected dimension of Kalman::Track",
292
"ConvertToSciFiTrack()");
295
// const SciFiGeometryMap& geom_map = geom->GeometryMap();
297
ThreeVector reference_pos = geom->GetReferencePosition(tracker);
298
HepRotation reference_rot = geom->GetReferenceRotation(tracker);
301
for (unsigned int i = 0; i < smoothed.GetLength(); ++i) {
302
const Kalman::State& smoothed_state = smoothed[i];
303
// const Kalman::State& filtered_state = filtered[i];
304
// const Kalman::State& predicted_state = predicted[i];
305
const Kalman::State& data_state = data[i];
307
SciFiTrackPoint* new_point = new SciFiTrackPoint();
309
new_point->set_tracker(tracker);
311
int id = abs(smoothed_state.GetId());
312
new_point->set_station(((id-1)/3)+1);
313
new_point->set_plane((id-1)%3);
318
TMatrixD state_vector = smoothed_state.GetVector();
320
if (dimension == 4) {
321
pos.setZ(smoothed_state.GetPosition());
322
pos.setX(state_vector(0, 0));
323
mom.setX(state_vector(1, 0)*default_mom);
324
pos.setY(state_vector(2, 0));
325
mom.setY(state_vector(3, 0)*default_mom);
327
pos *= reference_rot;
328
pos += reference_pos;
330
mom *= reference_rot;
331
if (tracker == 0) mom *= -1.0;
332
mom.setZ(default_mom); // MeV/c
333
} else if (dimension == 5) {
334
pos.setX(state_vector(0, 0));
335
mom.setX(state_vector(1, 0));
336
pos.setY(state_vector(2, 0));
337
mom.setY(state_vector(3, 0));
338
pos.setZ(smoothed_state.GetPosition());
340
pos *= reference_rot;
341
pos += reference_pos;
343
mom *= reference_rot;
349
mom.setZ(fabs(1.0/state_vector(4, 0)));
352
// if (mom.z() < 0.0) {
353
// mom.setZ(- mom.z());
355
// if (tracker == 0) {
356
// mom.setZ(fabs(mom.z()));
357
// mom.setY(-1.0*mom.y());
360
new_point->set_pos(pos);
361
new_point->set_mom(mom);
364
// _pull = kalman_site->residual(KalmanState::Projected)(0, 0);
365
// _residual = kalman_site->residual(KalmanState::Filtered)(0, 0);
366
// _smoothed_residual = kalman_site->residual(KalmanState::Smoothed)(0, 0);
369
// new_point->set_pull(sqrt(fitter->CalculatePredictedResidual(i).GetVector().E2Norm()));
370
// new_point->set_residual(sqrt(fitter->CalculateFilteredResidual(i).GetVector().E2Norm()));
371
// new_point->set_smoothed_residual(
372
// sqrt(fitter->CalculateSmoothedResidual(i).GetVector().E2Norm()));
373
new_point->set_pull(fitter->CalculatePredictedResidual(i).GetVector()(0, 0));
374
new_point->set_residual(fitter->CalculateFilteredResidual(i).GetVector()(0, 0));
375
new_point->set_smoothed_residual(fitter->CalculateSmoothedResidual(i).GetVector()(0, 0));
377
new_point->set_pull(0.0);
378
new_point->set_residual(0.0);
379
new_point->set_smoothed_residual(0.0);
383
TMatrixD C = smoothed_state.GetCovariance();
384
int size = C.GetNrows();
385
int num_elements = size*size;
387
double* matrix_elements = C.GetMatrixArray();
388
std::vector<double> covariance(num_elements);
389
for (int i = 0; i < num_elements; ++i) {
390
covariance[i] = matrix_elements[i];
392
new_point->set_covariance(covariance);
393
std::vector<double> errors(size);
394
for (int i = 0; i < size; ++i) {
395
errors[i] = std::sqrt(fabs(C(i, i)));
397
new_point->set_errors(errors);
400
// _cluster = new TRef(kalman_site->cluster());
401
new_point->set_cluster(new TRef());
402
new_track->add_scifitrackpoint(new_point);
405
new_track->set_charge(charge);
406
new_track->set_chi2(chi_squared);
407
new_track->set_ndf(NDF);
408
new_track->set_P_value(p_value);
410
TMatrixD seed_vector = seed.GetVector();
411
ThreeVector seed_pos;
412
ThreeVector seed_mom;
413
if (dimension == 4) {
414
seed_pos.setZ(seed.GetPosition());
415
seed_pos.setX(seed_vector(0, 0));
416
seed_mom.setX(seed_vector(1, 0)*default_mom);
417
seed_pos.setY(seed_vector(2, 0));
418
seed_mom.setY(seed_vector(3, 0)*default_mom);
419
} else if (dimension == 5) {
420
seed_pos.setX(seed_vector(0, 0));
421
seed_mom.setX(seed_vector(1, 0));
422
seed_pos.setY(seed_vector(2, 0));
423
seed_mom.setY(seed_vector(3, 0));
424
seed_pos.setZ(seed.GetPosition());
426
seed_pos *= reference_rot;
427
seed_pos += reference_pos;
429
seed_mom *= reference_rot;
431
if (dimension == 4) {
432
seed_mom.setZ(default_mom);
433
} else if (dimension == 5) {
434
seed_mom.setZ(fabs(1.0/seed_vector(4, 0)));
437
new_track->SetSeedPosition(seed_pos);
438
new_track->SetSeedMomentum(seed_mom);
439
new_track->SetSeedCovariance(seed.GetCovariance().GetMatrixArray(), dimension*dimension);
443
// - Calculate p-value
444
// - Set Algorithm used
446
// - Init track before the fit?
452
Kalman::Track BuildSpacepointTrack(SciFiSpacePointPArray spacepoints,
453
const SciFiGeometryHelper* geom, int plane_num, double smear) {
456
Kalman::Track new_track(2);
457
int tracker = (*spacepoints.begin())->get_tracker();
459
for (unsigned int i = 0; i < 5; ++i) {
460
Kalman::State new_state(2, geom->GetPlanePosition(tracker, i+1, plane_num));
461
new_state.SetId((1 + i*3 + plane_num)*(tracker == 0 ? -1 : 1));
462
new_track.Append(new_state);
465
for (SciFiSpacePointPArray::iterator it = spacepoints.begin(); it != spacepoints.end(); ++it) {
466
int station = (*it)->get_station();
470
vec(0, 0) = (*it)->get_position().x();// * (1.0 + rand.Gaus(0.0, smear));
471
vec(1, 0) = (*it)->get_position().y();// * (1.0 + rand.Gaus(0.0, smear));
474
new_track[station-1].SetVector(vec);
475
new_track[station-1].SetCovariance(cov);
476
new_track[station-1].SetPosition((*it)->get_position().z());