/* This file is part of MAUS: http://micewww.pp.rl.ac.uk:8080/projects/maus
*
* MAUS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MAUS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MAUS. If not, see .
*
*/
#include "src/map/MapCppTrackerRecon/MapCppTrackerRecon.hh"
#include
#include "src/common_cpp/API/PyWrapMapBase.hh"
#include "src/common_cpp/Recon/Kalman/MAUSTrackWrapper.hh"
namespace MAUS {
PyMODINIT_FUNC init_MapCppTrackerRecon(void) {
PyWrapMapBase::PyWrapMapBaseModInit
("MapCppTrackerRecon", "", "", "", "");
}
MapCppTrackerRecon::MapCppTrackerRecon() : MapBase("MapCppTrackerRecon"),
_clusters_on(true),
_spacepoints_on(true),
_up_straight_pr_on(true),
_down_straight_pr_on(true),
_up_helical_pr_on(true),
_down_helical_pr_on(true),
_kalman_on(true),
_patrec_on(true),
_patrec_debug_on(false),
_helical_track_fitter(NULL),
_straight_track_fitter(NULL) {
}
MapCppTrackerRecon::~MapCppTrackerRecon() {
}
void MapCppTrackerRecon::_birth(const std::string& argJsonConfigDocument) {
// Pull out the global settings
if (!Globals::HasInstance()) {
GlobalsManager::InitialiseGlobals(argJsonConfigDocument);
}
Json::Value* json = Globals::GetConfigurationCards();
int user_up_helical_pr_on = (*json)["SciFiPRHelicalTkUSOn"].asInt();
int user_down_helical_pr_on = (*json)["SciFiPRHelicalTkDSOn"].asInt();
int user_up_straight_pr_on = (*json)["SciFiPRStraightTkUSOn"].asInt();
int user_down_straight_pr_on = (*json)["SciFiPRStraightTkDSOn"].asInt();
_kalman_on = (*json)["SciFiKalmanOn"].asBool();
_clusters_on = (*json)["SciFiClusterReconOn"].asBool();
_spacepoints_on = (*json)["SciFiSpacepointReconOn"].asBool();
_patrec_on = (*json)["SciFiPatRecOn"].asBool();
_patrec_debug_on = (*json)["SciFiPatRecDebugOn"].asBool();
_size_exception = (*json)["SciFiClustExcept"].asInt();
_min_npe = (*json)["SciFiNPECut"].asDouble();
_use_mcs = (*json)["SciFiKalman_use_MCS"].asBool();
_use_eloss = (*json)["SciFiKalman_use_Eloss"].asBool();
_use_patrec_seed = (*json)["SciFiSeedPatRec"].asBool();
_correct_pz = (*json)["SciFiKalmanCorrectPz"].asBool();
// Values used to set the track rating:
_excellent_num_trackpoints = (*json)["SciFiExcellentNumTrackpoints"].asInt();
_good_num_trackpoints = (*json)["SciFiGoodNumTrackpoints"].asInt();
_poor_num_trackpoints = (*json)["SciFiPoorNumTrackpoints"].asInt();
_excellent_p_value = (*json)["SciFiExcellentPValue"].asDouble();
_good_p_value = (*json)["SciFiGoodPValue"].asDouble();
_poor_p_value = (*json)["SciFiPoorPValue"].asDouble();
_excellent_num_spacepoints = (*json)["SciFiExcellentNumSpacepoints"].asInt();
_good_num_spacepoints = (*json)["SciFiGoodNumSpacepoints"].asInt();
_poor_num_spacepoints = (*json)["SciFiPoorNumSpacepoints"].asInt();
ofstream logfile;
std::string root_dir = std::getenv("MAUS_ROOT_DIR");
std::string path = root_dir + "/tmp/digit_exception.log";
logfile.open(path);
logfile.close();
// Build the geometery helper instance
MiceModule* module = Globals::GetReconstructionMiceModules();
std::vector modules =
module->findModulesByPropertyString("SensitiveDetector", "SciFi");
_geometry_helper = SciFiGeometryHelper(modules);
_geometry_helper.Build();
// Set up cluster reconstruction
_cluster_recon = SciFiClusterRec(_size_exception, _min_npe, _geometry_helper.GeometryMap());
// Set up spacepoint reconstruction
_spacepoint_recon = SciFiSpacePointRec();
// Setup Pattern Recognition
double up_field = _geometry_helper.GetFieldValue(0);
double down_field = _geometry_helper.GetFieldValue(1);
if (user_up_helical_pr_on == 2)
_up_helical_pr_on = true;
else if (user_up_helical_pr_on == 1)
_up_helical_pr_on = false;
else if (user_up_helical_pr_on == 0 && fabs(up_field) < 0.00001) // 10 Gaus
_up_helical_pr_on = false;
else if (user_up_helical_pr_on == 0 && fabs(up_field) >= 0.00001)
_up_helical_pr_on = true;
if (user_down_helical_pr_on == 2)
_down_helical_pr_on = true;
else if (user_down_helical_pr_on == 1)
_down_helical_pr_on = false;
else if (user_down_helical_pr_on == 0 && fabs(down_field) < 0.00001)
_down_helical_pr_on = false;
else if (user_down_helical_pr_on == 0 && fabs(down_field) >= 0.00001)
_down_helical_pr_on = true;
if (user_up_straight_pr_on == 2)
_up_straight_pr_on = true;
else if (user_up_straight_pr_on == 1)
_up_straight_pr_on = false;
else if (user_up_straight_pr_on == 0 && fabs(up_field) < 0.00001)
_up_straight_pr_on = true;
else if (user_up_straight_pr_on == 0 && fabs(up_field) >= 0.00001)
_up_straight_pr_on = false;
if (user_down_straight_pr_on == 2)
_down_straight_pr_on = true;
else if (user_down_straight_pr_on == 1)
_down_straight_pr_on = false;
else if (user_down_straight_pr_on == 0 && fabs(down_field) < 0.00001)
_down_straight_pr_on = true;
else if (user_down_straight_pr_on == 0 && fabs(down_field) >= 0.00001)
_down_straight_pr_on = false;
_pattern_recognition = PatternRecognition();
_pattern_recognition.LoadGlobals();
_pattern_recognition.set_up_helical_pr_on(_up_helical_pr_on);
_pattern_recognition.set_down_helical_pr_on(_down_helical_pr_on);
_pattern_recognition.set_up_straight_pr_on(_up_straight_pr_on);
_pattern_recognition.set_down_straight_pr_on(_down_straight_pr_on);
_pattern_recognition.set_bz_t1(up_field);
_pattern_recognition.set_bz_t2(down_field);
if (_patrec_debug_on) _pattern_recognition.setup_debug();
if (_use_patrec_seed) {
_seed_value = -1.0;
} else {
_seed_value = (*json)["SciFiSeedCovariance"].asDouble();
}
// Set up final track fit (Kalman filter)
HelicalPropagator* helical_prop = new HelicalPropagator(&_geometry_helper);
helical_prop->SetCorrectPz(_correct_pz);
helical_prop->SetIncludeMCS(_use_mcs);
helical_prop->SetSubtractELoss(_use_eloss);
_helical_measurement = new SciFiHelicalMeasurements(&_geometry_helper);
_helical_track_fitter = new Kalman::TrackFit(helical_prop, _helical_measurement);
StraightPropagator* straight_prop = new StraightPropagator(&_geometry_helper);
straight_prop->SetIncludeMCS(_use_mcs);
_straight_measurement = new SciFiStraightMeasurements(&_geometry_helper);
_straight_track_fitter = new Kalman::TrackFit(straight_prop, _straight_measurement);
}
void MapCppTrackerRecon::_death() {
if (_helical_track_fitter) {
delete _helical_track_fitter;
_helical_track_fitter = NULL;
}
if (_straight_track_fitter) {
delete _straight_track_fitter;
_straight_track_fitter = NULL;
}
}
void MapCppTrackerRecon::_process(Data* data) const {
Spill& spill = *(data->GetSpill());
/* return if not physics spill */
if (spill.GetDaqEventType() != "physics_event")
return;
if (spill.GetReconEvents()) {
for (unsigned int k = 0; k < spill.GetReconEvents()->size(); k++) {
SciFiEvent *event = spill.GetReconEvents()->at(k)->GetSciFiEvent();
if (!event) {
continue;
}
if ( _clusters_on ) {
// Clear any exising higher level data
event->clear_clusters();
// Build Clusters.
if (event->digits().size()) {
_cluster_recon.process(*event);
}
}
if ( _spacepoints_on ) {
// Build SpacePoints.
event->clear_spacepoints();
if (event->clusters().size()) {
_spacepoint_recon.process(*event);
set_spacepoint_global_output(event->spacepoints());
}
}
// Pattern Recognition.
if (_patrec_on && event->spacepoints().size()) {
event->clear_seeds();
event->clear_stracks();
event->clear_htracks();
_pattern_recognition.process(*event);
set_straight_prtrack_global_output(event->straightprtracks());
extrapolate_helical_reference(*event);
extrapolate_straight_reference(*event);
}
// Kalman Track Fit.
if (_kalman_on) {
event->clear_scifitracks();
track_fit(*event);
}
// print_event_info(*event);
}
} else {
std::cout << "No recon events found\n";
}
}
void MapCppTrackerRecon::track_fit(SciFiEvent &evt) const {
size_t number_helical_tracks = evt.helicalprtracks().size();
size_t number_straight_tracks = evt.straightprtracks().size();
for (size_t track_i = 0; track_i < number_helical_tracks; track_i++) {
SciFiHelicalPRTrack* helical = evt.helicalprtracks().at(track_i);
Kalman::Track data_track = BuildTrack(helical, &_geometry_helper);
Kalman::State seed = ComputeSeed(helical, &_geometry_helper, _use_eloss, _seed_value);
_helical_track_fitter->SetData(data_track);
_helical_track_fitter->SetSeed(seed);
_helical_track_fitter->Filter(false);
_helical_track_fitter->Smooth(false);
SciFiTrack* track = ConvertToSciFiTrack(_helical_track_fitter, &_geometry_helper, helical);
calculate_track_rating(track);
evt.add_scifitrack(track);
}
for (size_t track_i = 0; track_i < number_straight_tracks; track_i++) {
SciFiStraightPRTrack* straight = evt.straightprtracks().at(track_i);
Kalman::Track data_track = BuildTrack(straight, &_geometry_helper);
Kalman::State seed = ComputeSeed(straight, &_geometry_helper, _seed_value);
_straight_track_fitter->SetData(data_track);
_straight_track_fitter->SetSeed(seed);
_straight_track_fitter->Filter(false);
_straight_track_fitter->Smooth(false);
SciFiTrack* track = ConvertToSciFiTrack(_straight_track_fitter, &_geometry_helper, straight);
calculate_track_rating(track);
evt.add_scifitrack(track);
}
}
void MapCppTrackerRecon::extrapolate_helical_reference(SciFiEvent& event) const {
SciFiHelicalPRTrackPArray helicals = event.helicalprtracks();
size_t num_tracks = helicals.size();
for (size_t i = 0; i < num_tracks; ++i) {
SciFiHelicalPRTrack* track = helicals[i];
ThreeVector pos;
ThreeVector mom;
int tracker = track->get_tracker();
ThreeVector reference = _geometry_helper.GetReferencePosition(tracker);
CLHEP::HepRotation rotation = _geometry_helper.GetReferenceRotation(tracker);
double r = track->get_R();
double pt = - track->get_charge()*CLHEP::c_light*_geometry_helper.GetFieldValue(tracker)*r;
double dsdz = - track->get_dsdz();
double x0 = track->get_circle_x0();
double y0 = track->get_circle_y0();
double s = track->get_line_sz_c();
double phi = s / r;
pos.setX(x0 + r*cos(phi));
pos.setY(y0 + r*sin(phi));
pos.setZ(0.0);
pos *= rotation;
pos += reference;
mom.setX(-pt*sin(phi));
mom.setY(pt*cos(phi));
mom.setZ(-pt/dsdz);
mom *= rotation;
track->set_reference_position(pos);
track->set_reference_momentum(mom);
}
}
void MapCppTrackerRecon::extrapolate_straight_reference(SciFiEvent& event) const {
SciFiStraightPRTrackPArray straights = event.straightprtracks();
size_t num_tracks = straights.size();
for (size_t i = 0; i < num_tracks; ++i) {
SciFiStraightPRTrack* track = straights[i];
ThreeVector pos;
ThreeVector mom;
double default_mom = _geometry_helper.GetDefaultMomentum();
int tracker = track->get_tracker();
ThreeVector reference = _geometry_helper.GetReferencePosition(tracker);
CLHEP::HepRotation rotation = _geometry_helper.GetReferenceRotation(tracker);
pos.setX(track->get_x0());
pos.setY(track->get_y0());
pos.setZ(0.0);
pos *= rotation;
pos += reference;
double mx = track->get_mx();
double my = track->get_my();
mom.setX(mx*default_mom);
mom.setY(my*default_mom);
mom *= rotation;
if (tracker == 0) mom *= -1.0;
mom.setZ(default_mom);
track->set_reference_position(pos);
track->set_reference_momentum(mom);
}
}
void MapCppTrackerRecon::set_spacepoint_global_output(const SciFiSpacePointPArray& spoints) const {
for (auto sp : spoints) {
sp->set_global_position(
_geometry_helper.TransformPositionToGlobal(sp->get_position(), sp->get_tracker()));
}
}
void MapCppTrackerRecon::set_straight_prtrack_global_output(
const SciFiStraightPRTrackPArray& trks) const {
for (auto trk : trks) {
ThreeVector pos = trk->get_spacepoints_pointers()[0]->get_position();
std::vector params{ trk->get_x0(), trk->get_mx(), trk->get_y0(), trk->get_my() }; // NOLINT
std::vector global_params =
_geometry_helper.TransformStraightParamsToGlobal(params, trk->get_tracker());
// Update the track
trk->set_global_x0(global_params[0]);
trk->set_global_mx(global_params[1]);
trk->set_global_y0(global_params[2]);
trk->set_global_my(global_params[3]);
}
}
void MapCppTrackerRecon::calculate_track_rating(SciFiTrack* track) const {
SciFiBasePRTrack* pr_track = track->pr_track_pointer();
int number_spacepoints = pr_track->get_num_points();
int number_trackpoints = track->GetNumberDataPoints();
bool excel_numtp = (number_trackpoints >= _excellent_num_trackpoints);
bool good_numtp = (number_trackpoints >= _good_num_trackpoints);
bool poor_numtp = (number_trackpoints >= _poor_num_trackpoints);
bool excel_numsp = (number_spacepoints >= _excellent_num_spacepoints);
bool good_numsp = (number_spacepoints >= _good_num_spacepoints);
bool poor_numsp = (number_spacepoints >= _poor_num_spacepoints);
bool excel_pval = (track->P_value() >= _excellent_p_value);
bool good_pval = (track->P_value() >= _good_p_value);
bool poor_pval = (track->P_value() >= _poor_p_value);
int rating = 0;
if (excel_numtp && excel_numsp && excel_pval) {
rating = 1;
} else if (good_numtp && good_numsp && good_pval) {
rating = 2;
} else if (poor_numtp && poor_numsp && poor_pval) {
rating = 3;
} else {
rating = 5;
}
track->SetRating(rating);
}
void MapCppTrackerRecon::print_event_info(SciFiEvent &event) const {
std::cerr << "\n ###### SciFi Event Details ######\n\n";
std::cerr << "Num Digits : " << event.digits().size() << "\n"
<< "Num Clusters : " << event.clusters().size() << "\n"
<< "Num Spacepoints : " << event.spacepoints().size() << "\n"
<< "Num Straights : " << event.straightprtracks().size() << "\n"
<< "Num Helicals : " << event.helicalprtracks().size() << "\n\n";
SciFiTrackPArray tracks = event.scifitracks();
for (unsigned int i = 0; i < tracks.size(); ++i) {
SciFiTrackPointPArray trackpoints = tracks[i]->scifitrackpoints();
for (unsigned int j = 0; j < trackpoints.size(); ++j) {
std::cerr << "Track Point = " << trackpoints[j]->pos()[0] << ", "
<< trackpoints[j]->pos()[1] << ", "
<< trackpoints[j]->pos()[2] << " | "
<< trackpoints[j]->mom()[0] << ", "
<< trackpoints[j]->mom()[1] << ", "
<< trackpoints[j]->mom()[2] << " | "
// << "DATA = " << (cluster ? cluster->get_alpha() : 0) << '\n
<< "(" << trackpoints[j]->pull() << ", "
<< trackpoints[j]->residual()
<< ", " << trackpoints[j]->smoothed_residual() << ")\n";
}
std::cerr << "Tracker : " << tracks[i]->tracker()
<< ", Chi2 = " << tracks[i]->chi2()
<< ", NDF = " << tracks[i]->ndf()
<< ", P_Value = " << tracks[i]->P_value()
<< ", Charge = " << tracks[i]->charge() << '\n';
ThreeVector seed_pos = tracks[i]->GetSeedPosition();
ThreeVector seed_mom = tracks[i]->GetSeedMomentum();
std::vector seed_cov = tracks[i]->GetSeedCovariance();
std::cerr << "Seed State = (" << seed_pos[0] << ", " << seed_pos[1] << ", " << seed_pos[2]
<< ") (" << seed_mom[0] << ", " << seed_mom[1] << ", " << seed_mom[2] << ")\n";
std::cerr << "Seed Covariance = ";
for (unsigned int j = 0; j < seed_cov.size(); ++j) {
std::cerr << seed_cov[j] << ", ";
}
std::cerr << '\n';
}
std::cerr << std::endl;
}
} // ~namespace MAUS