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/>.
20
#include "Recon/Global/MinuitTrackFitter.hh"
30
#include "json/json.h"
32
#include "CLHEP/Units/PhysicalConstants.h"
33
#include "DataStructure/Global/Track.hh"
34
#include "DataStructure/Global/TrackPoint.hh"
35
#include "Utils/Exception.hh"
36
#include "src/common_cpp/Optics/CovarianceMatrix.hh"
37
#include "src/common_cpp/Optics/OpticsModel.hh"
38
#include "src/common_cpp/Optics/PhaseSpaceVector.hh"
39
#include "src/common_cpp/Optics/TransferMap.hh"
40
#include "src/common_cpp/Simulation/MAUSGeant4Manager.hh"
41
#include "src/common_cpp/Simulation/MAUSPrimaryGeneratorAction.hh"
42
#include "Recon/Global/DataStructureHelper.hh"
43
#include "Recon/Global/Particle.hh"
44
#include "Recon/Global/ParticleOpticalVector.hh"
45
#include "src/common_cpp/Utils/JsonWrapper.hh"
51
using MAUS::DataStructure::Global::Track;
52
using MAUS::DataStructure::Global::TrackPoint;
53
namespace GlobalDS = MAUS::DataStructure::Global;
55
void common_cpp_optics_recon_minuit_track_fitter_score_function(
56
Int_t & number_of_parameters,
59
Double_t * phase_space_coordinate_values,
60
Int_t execution_stage_flag) {
61
for (size_t index = 0; index < 6; ++index) {
62
std::cout << "DEBUG common_..._score_function: coordinate[" << index << "] = "
63
<< phase_space_coordinate_values[index] << std::endl;
65
// common_cpp_optics_recon_minuit_track_fitter_minuit is defined
66
// globally in the header file
68
= common_cpp_optics_recon_minuit_track_fitter_minuit;
70
MinuitTrackFitter * track_fitter
71
= static_cast<MinuitTrackFitter *>(minuit->GetObjectFit());
73
score = MinuitTrackFitter::ScoreTrack(
74
phase_space_coordinate_values,
75
*track_fitter->optics_model_,
76
Particle::GetInstance().GetMass(track_fitter->particle_id_),
77
track_fitter->detector_events_);
80
MinuitTrackFitter::MinuitTrackFitter(
81
OpticsModel const * optics_model,
82
const double start_plane)
83
: TrackFitter(optics_model, start_plane), rounds_(0) {
84
// Setup *global* scope Minuit object
85
common_cpp_optics_recon_minuit_track_fitter_minuit
86
= new TMinuit(kPhaseSpaceDimension);
88
= common_cpp_optics_recon_minuit_track_fitter_minuit;
90
minimizer->SetObjectFit(this);
93
common_cpp_optics_recon_minuit_track_fitter_score_function);
98
MinuitTrackFitter::~MinuitTrackFitter() {
99
delete common_cpp_optics_recon_minuit_track_fitter_minuit;
102
void MinuitTrackFitter::ResetParameters() {
104
= common_cpp_optics_recon_minuit_track_fitter_minuit;
106
// setup the index, name, init value, step size, min, and max value for each
107
// phase space variable (mins and maxes calculated from 800MeV/c ISIS beam)
109
Json::Value const * configuration = optics_model_->configuration();
110
if (configuration == NULL) {
111
throw(Exception(Exception::nonRecoverable,
112
"Initialized with a null configuration.",
113
"MAUS::MinuitTrackFitter::ResetParameters()"));
115
const Json::Value parameters = JsonWrapper::GetProperty(
116
*configuration, "global_recon_minuit_parameters",
117
JsonWrapper::arrayValue);
118
const Json::Value::UInt parameter_count = parameters.size();
119
if (parameter_count != 6) {
120
std::stringstream message;
121
message << "Expected 6 elements in \"global_recon_minuit_parameters\""
122
<< " but found " << parameter_count << "." << std::endl;
123
throw(Exception(Exception::nonRecoverable,
125
"MAUS::MinuitTrackFitter::ResetParameters()"));
127
for (Json::Value::UInt index = 0; index < parameter_count; ++index) {
128
const Json::Value parameter = parameters[index];
129
const std::string name = JsonWrapper::GetProperty(
130
parameter, "name", JsonWrapper::stringValue).asString();
131
const bool fixed = JsonWrapper::GetProperty(
132
parameter, "fixed", JsonWrapper::booleanValue).asBool();
133
const double initial_value = JsonWrapper::GetProperty(
134
parameter, "initial_value", JsonWrapper::realValue).asDouble();
135
const double value_step = JsonWrapper::GetProperty(
136
parameter, "value_step", JsonWrapper::realValue).asDouble();
137
const double min_value = JsonWrapper::GetProperty(
138
parameter, "min_value", JsonWrapper::realValue).asDouble();
139
const double max_value = JsonWrapper::GetProperty(
140
parameter, "max_value", JsonWrapper::realValue).asDouble();
142
minimizer->mnparm(index, name, initial_value, value_step,
143
min_value, max_value, error_flag);
145
minimizer->FixParameter(index);
150
void MinuitTrackFitter::Fit(Track const * const raw_track, Track * const track,
151
const std::string mapper_name) {
152
std::cout << "CHECKPOINT Fit(): BEGIN" << std::endl;
154
detector_events_ = raw_track->GetTrackPoints();
155
std::cout << "DEBUG MinuitTrackFitter::Fit(): CHECKPOINT 0" << std::endl;
156
std::cout << "DEBUG MinuitTrackFitter::Fit(): Fitting track with "
157
<< detector_events_.size() << " track points." << std::endl;
158
std::cout << "DEBUG MinuitTrackFitter::Fit(): CHECKPOINT 0.5" << std::endl;
159
particle_id_ = raw_track->get_pid();
160
std::cout << "DEBUG MinuitTrackFitter::Fit(): particle ID: "
161
<< particle_id_ << std::endl;
163
std::cout << "DEBUG MinuitTrackFitter::Fit(): CHECKPOINT 1" << std::endl;
164
if (detector_events_.size() < 2) {
165
throw(Exception(Exception::recoverable,
166
"Not enough track points to fit track (need at least two).",
167
"MAUS::MinuitTrackFitter::Fit()"));
169
std::cout << "DEBUG MinuitTrackFitter::Fit(): CHECKPOINT 2" << std::endl;
174
= common_cpp_optics_recon_minuit_track_fitter_minuit;
176
// Find the start plane coordinates that minimize the score for the calculated
177
// track based off of this track point (i.e. best fits the measured track
178
// points from the detectors).
179
Json::Value const * const configuration = optics_model_->configuration();
180
if (configuration == NULL) {
181
throw(Exception(Exception::nonRecoverable,
182
"Initialized with a null configuration.",
183
"MAUS::MinuitTrackFitter::Fit()"));
185
const std::string method = JsonWrapper::GetProperty(
186
*configuration, "global_recon_minuit_minimizer",
187
JsonWrapper::stringValue).asString();
188
const double max_iterations = JsonWrapper::GetProperty(
189
*configuration, "global_recon_minuit_max_iterations",
190
JsonWrapper::intValue).asInt();
191
const double max_EDM = JsonWrapper::GetProperty(
192
*configuration, "global_recon_minuit_max_edm",
193
JsonWrapper::realValue).asDouble();
196
Double_t args[2] = {max_iterations, max_EDM};
197
minimizer->mnexcm(method.c_str(), args, 2, err);
199
// Get the particle event for this track
200
GlobalDS::TrackPointCPArray raw_points = raw_track->GetTrackPoints();
201
size_t particle_event = raw_points[0]->get_particle_event();
203
DataStructureHelper helper = DataStructureHelper::GetInstance();
205
// Add a TrackPoint to the recon track for the fit primary
206
PhaseSpaceVector fit_primary;
207
for (size_t index = 0; index < kPhaseSpaceDimension; ++index) {
208
Double_t value, error;
209
minimizer->GetParameter(index, value, error);
210
fit_primary[index] = value;
212
std::cout << "DEBUG MinuitTrackFitter::Fit: Fit Primary: " << fit_primary
215
TrackPoint track_point = helper.PhaseSpaceVector2TrackPoint(
217
optics_model_->primary_plane(),
219
track_point.set_mapper_name(mapper_name);
220
track_point.set_detector(MAUS::DataStructure::Global::kUndefined);
221
track_point.set_particle_event(particle_event);
222
track->AddTrackPoint(new TrackPoint(track_point));
223
} catch (Exception exc) {
224
std::cerr << "DEBUG MinuitTrackFitter::ScoreTrack: "
225
<< "something bad happened during track fitting: "
226
<< exc.what() << std::endl;
227
// FIXME(Lane) handle better by reporting horrible score or something
231
// Add the fit points to the recon track by transporting the fit primary
232
GlobalDS::TrackPointCPArray::const_iterator raw_point = raw_points.begin();
233
for (; raw_point != raw_points.end(); ++raw_point) {
234
// transport the fit primary to the desired z-position
235
const double z = (*raw_point)->get_position().Z();
236
const PhaseSpaceVector point = optics_model_->Transport(fit_primary, z);
237
std::cout << "DEBUG MinuitTrackFitter::Fit: track point: " << point << std::endl;
239
TrackPoint track_point;
241
track_point = helper.PhaseSpaceVector2TrackPoint(point, z, particle_id_);
242
} catch (Exception exc) {
243
std::cerr << "DEBUG MinuitTrackFitter::ScoreTrack: "
244
<< "something bad happened during track fitting: "
245
<< exc.what() << std::endl;
246
// FIXME(Lane) handle better by reporting horrible score or something
249
track_point.set_particle_event(particle_event);
250
track_point.set_mapper_name(mapper_name);
251
track_point.set_detector((*raw_point)->get_detector());
252
track->AddTrackPoint(new TrackPoint(track_point));
254
track->set_pid(raw_track->get_pid());
257
Double_t MinuitTrackFitter::ScoreTrack(
258
Double_t const * const start_plane_track_coordinates,
259
const MAUS::OpticsModel & optics_model,
261
const std::vector<const GlobalDS::TrackPoint *> & detector_events) {
262
DataStructureHelper helper = DataStructureHelper::GetInstance();
264
// Setup the start plane track point based on the Minuit initial conditions
265
CovarianceMatrix null_uncertainties;
266
const PhaseSpaceVector guess(start_plane_track_coordinates[0],
267
start_plane_track_coordinates[1],
268
start_plane_track_coordinates[2],
269
start_plane_track_coordinates[3],
270
start_plane_track_coordinates[4],
271
start_plane_track_coordinates[5]);
272
// If the guess is not physical then return a horrible score
273
if (!MinuitTrackFitter::ValidVector(guess, mass)) {
277
std::vector<const TrackPoint*>::const_iterator event
278
= detector_events.begin();
281
Double_t chi_squared = 0.0;
283
for (std::vector<const TrackPoint*>::const_iterator event
284
= detector_events.begin();
285
event != detector_events.end();
287
std::cout << "DEBUG MinuitTrackFitter::ScoreTrack(): Guess: "
288
<< guess << std::endl;
289
std::cout << "DEBUG MinuitTrackFitter::ScoreTrack(): Measured: "
290
<< *event << std::endl;
291
// calculate the next guess
292
const double end_plane = (*event)->get_position().Z();
293
PhaseSpaceVector point =
294
optics_model.Transport(guess, end_plane);
295
std::cout << "DEBUG MinuitTrackFitter::ScoreTrack(): Calculated: "
296
<< point << std::endl;
298
TLorentzVector position_error = (*event)->get_position_error();
299
TLorentzVector momentum_error = (*event)->get_momentum_error();
300
const double errors[36] = {
301
position_error.T(), 0., 0., 0., 0., 0.,
302
0., momentum_error.E(), 0., 0., 0., 0.,
303
0., 0., position_error.X(), 0., 0., 0.,
304
0., 0., 0., momentum_error.Px(), 0., 0.,
305
0., 0., 0., 0., position_error.Y(), 0.,
306
0., 0., 0., 0., 0., momentum_error.Py(),
308
const Matrix<double> error_matrix(6, 6, errors);
309
const CovarianceMatrix uncertainties(error_matrix*error_matrix);
311
const double weights[36] = {
312
1., 0., 0., 0., 0., 0.,
313
0., 1., 0., 0., 0., 0.,
314
0., 0., 1., 0., 0., 0.,
315
0., 0., 0., 1., 0., 0.,
316
0., 0., 0., 0., 1., 0.,
317
0., 0., 0., 0., 0., 1.,
319
Matrix<double> weight_matrix(6, 6, weights);
321
// Sum the squares of the differences between the calculated phase space
322
// coordinates (point) and the measured coordinates (event).
323
PhaseSpaceVector event_point = helper.TrackPoint2PhaseSpaceVector(**event);
324
PhaseSpaceVector residual = PhaseSpaceVector(
325
weight_matrix * (event_point - point));
326
const double residual_squared = (transpose(residual)
327
* inverse(uncertainties)
329
std::cout << "DEBUG MinuitTrackFitter::ScoreTrack(): Residual Squared: "
330
<< residual_squared << std::endl;
331
chi_squared += residual_squared;
332
std::cerr << residual << std::endl
333
<< " = " << event_point << std::endl
334
<< " - " << point << std::endl
335
<< " -- chi2: " << chi_squared << std::endl;
338
std::cerr << std::endl;
343
bool MinuitTrackFitter::ValidVector(const PhaseSpaceVector & guess,
345
const double E = guess.E();
346
const double px = guess.Px();
347
const double py = guess.Py();
351
if (guess != guess) {
354
} else if (::sqrt(px*px + py*py + mass*mass) > E) {
355
// Energy cannot be greater than the sum of the squares of the transverse
363
const size_t MinuitTrackFitter::kPhaseSpaceDimension = 6;
364
} // namespace global