/* 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/MapCppTrackerDownstreamReFit/MapCppTrackerDownstreamReFit.hh" #include #include "src/common_cpp/API/PyWrapMapBase.hh" #include "src/common_cpp/Recon/Kalman/MAUSTrackWrapper.hh" #include "src/common_cpp/Recon/Global/MaterialModelAxialLookup.hh" #include "TMatrixD.h" #include "Geant4/G4Material.hh" namespace MAUS { PyMODINIT_FUNC init_MapCppTrackerDownstreamReFit(void) { PyWrapMapBase::PyWrapMapBaseModInit ("MapCppTrackerDownstreamReFit", "", "", "", ""); } MapCppTrackerDownstreamReFit::MapCppTrackerDownstreamReFit() : MapBase("MapCppTrackerDownstreamReFit"), _helical_track_fitter(NULL), _radius_cut(10.0) { } MapCppTrackerDownstreamReFit::~MapCppTrackerDownstreamReFit() { } void MapCppTrackerDownstreamReFit::_birth(const std::string& argJsonConfigDocument) { // Pull out the global settings if (!Globals::HasInstance()) { GlobalsManager::InitialiseGlobals(argJsonConfigDocument); } Json::Value* json = Globals::GetConfigurationCards(); _radius_cut = (*json)["SciFiHelicalRadiusLimit"].asDouble(); _tracker_z = 0.0; _downstream_tracker_z = 0.0; HelicalPropagator* helical_prop = new HelicalPropagator(Globals::GetSciFiGeometryHelper()); helical_prop->SetCorrectPz(true); helical_prop->SetIncludeMCS(true); helical_prop->SetSubtractELoss(true); _helical_track_fitter = new Kalman::TrackFit(helical_prop); // Find trackers and initialise measurement objects. // Each measurement plane has a unique alignment and rotation => they all need their own // measurement object. SciFiTrackerMap& geo_map = Globals::GetSciFiGeometryHelper()->GeometryMap(); for (SciFiTrackerMap::iterator track_it = geo_map.begin(); track_it != geo_map.end(); ++track_it) { int tracker_const = (track_it->first == 0 ? -1 : 1); for (SciFiPlaneMap::iterator plane_it = track_it->second.Planes.begin(); plane_it != track_it->second.Planes.end(); ++plane_it) { int id = plane_it->first * tracker_const; _helical_track_fitter->AddMeasurement(id, new MAUS::SciFiHelicalMeasurements(plane_it->second)); if (id == 15) { _downstream_tracker_z = plane_it->second.GlobalPosition.Z(); } if (id == -1) { _tracker_z = plane_it->second.GlobalPosition.Z(); } } } } void MapCppTrackerDownstreamReFit::_death() { if (_helical_track_fitter) { delete _helical_track_fitter; _helical_track_fitter = NULL; } } void MapCppTrackerDownstreamReFit::_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; } SciFiTrackPArray tracks = event->scifitracks(); SciFiTrackPArray new_tracks; for (SciFiTrackPArray::iterator it = tracks.begin(); it != tracks.end(); ++it) { try { SciFiSeed* seed = (*it)->scifi_seed(); switch (seed->getAlgorithm()) { case 1 : if (needs_refitting(seed) || (*it)->is_dud()) { std::cerr << "Found 1 needs refitting" << std::endl; if (calculate_pz_seed(seed, event)) { std::cerr << "Calculated new pz" << std::endl; SciFiTrack* new_track = track_fit_helix(seed); new_track->SetWasRefit(1); new_tracks.push_back(new_track); delete *it; continue; } } new_tracks.push_back((*it)); break; case 0 : if ((*it)->tracker() == 1) { std::cerr << "Found 0 needs reffiting" << std::endl; if (calculate_straight_pz_seed(seed, event)) { std::cerr << "Calculated new pz" << std::endl; SciFiTrack* new_track = track_fit_helix(seed); new_track->SetWasRefit(2); new_tracks.push_back(new_track); delete *it; continue; } } new_tracks.push_back((*it)); break; default: break; } } catch (Exceptions::Exception& e) { std::cerr << "Track Fit Failed: " << e.what(); } } event->set_scifitracks(new_tracks); } } else { std::cout << "No recon events found\n"; } } SciFiTrack* MapCppTrackerDownstreamReFit::track_fit_helix(SciFiSeed* seed) const { SciFiHelicalPRTrack* helical = static_cast(seed->getPRTrackTobject()); Kalman::Track data_track = BuildTrack(helical, Globals::GetSciFiGeometryHelper(), 5); Kalman::State kalman_seed(seed->getStateVector(), seed->getCovariance()); _helical_track_fitter->SetTrack(data_track); _helical_track_fitter->SetSeed(kalman_seed); _helical_track_fitter->Filter(false); _helical_track_fitter->Smooth(false); SciFiTrack* track = ConvertToSciFiTrack(_helical_track_fitter, Globals::GetSciFiGeometryHelper(), helical); track->set_scifi_seed_tobject(seed); ThreeVector seed_pos = track->GetSeedPosition(); ThreeVector seed_mom = track->GetSeedMomentum(); return track; } bool MapCppTrackerDownstreamReFit::needs_refitting(MAUS::SciFiSeed* seed) const { if (seed->getTracker() != 1) { // Dowmnstream Tracker return false; } else if (static_cast(seed->getPRTrackTobject())->get_R() > this->_radius_cut) { return false; // With a small radius } return true; // Then refit it. } bool MapCppTrackerDownstreamReFit::calculate_pz_seed(MAUS::SciFiSeed* seed, SciFiEvent* scifi_event) const { std::vector found_tracks; SciFiTrackPArray tracks = scifi_event->scifitracks(); // std::cerr << tracks.size() << " Tracks" << std::endl; for (SciFiTrackPArray::iterator it = tracks.begin(); it != tracks.end(); ++it) { if ((*it)->tracker() == 0) { found_tracks.push_back((*it)); } } if (found_tracks.size() != 1) { return false; } if (found_tracks[0]->GetAlgorithmUsed() != 1) { return false; } double pz = 0.0; SciFiTrackPointPArray trackpoints = found_tracks[0]->scifitrackpoints(); for (SciFiTrackPointPArray::iterator it = trackpoints.begin(); it != trackpoints.end(); ++it) { if ((*it)->station() == 1 && (*it)->plane() == 0) { pz = (*it)->mom().z(); break; } } if (std::fabs(pz) < 0.001) { return false; } // Propagate from Upstream to downstream tracker pz = calculate_new_pz(pz); std::cerr << " -> " << pz << std::endl; TMatrixD vector = seed->getStateVector(); if (vector(4, 0) >= 0.0) { vector(4, 0) = 1.0 / pz; } else { vector(4, 0) = -1.0 / pz; } seed->setStateVector(vector); return true; } bool MapCppTrackerDownstreamReFit::calculate_straight_pz_seed(MAUS::SciFiSeed* seed, SciFiEvent* scifi_event) const { std::vector found_tracks; SciFiTrackPArray tracks = scifi_event->scifitracks(); for (SciFiTrackPArray::iterator it = tracks.begin(); it != tracks.end(); ++it) { if ((*it)->tracker() == 0) { found_tracks.push_back((*it)); } } if (found_tracks.size() != 1) { return false; } if (found_tracks[0]->GetAlgorithmUsed() != 1) { return false; } double pz = 0.0; SciFiTrackPointPArray trackpoints = found_tracks[0]->scifitrackpoints(); for (SciFiTrackPointPArray::iterator it = trackpoints.begin(); it != trackpoints.end(); ++it) { if ((*it)->station() == 1 && (*it)->plane() == 0) { pz = (*it)->mom().z(); } } if (std::fabs(pz) < 0.001) { return false; } // Propagate from upstream to downstream tracker pz = calculate_new_pz(pz); std::cerr << " -> " << pz << std::endl; TMatrixD vector = seed->getStateVector(); TMatrixD new_vector(5, 1); new_vector(0, 0) = vector(0, 0); new_vector(1, 0) = 0.0; new_vector(2, 0) = vector(2, 0); new_vector(3, 0) = 0.0; if (seed->getTracker() == 0) { new_vector(4, 0) = 1.0 / pz; } else { new_vector(4, 0) = -1.0 / pz; } seed->setStateVector(new_vector); TMatrixD covariance = seed->getCovariance(); TMatrixD new_covariance(5, 5); for (unsigned int i = 0; i < 5; ++i) { for (unsigned int j = 0; j < 5; ++j) { new_covariance(i, j) = 0.0; } } new_covariance(0, 0) = 100.0; new_covariance(1, 1) = 100.0; new_covariance(2, 2) = 100.0; new_covariance(3, 3) = 100.0; new_covariance(4, 4) = 2.5e-7; seed->setCovariance(new_covariance); return true; } double MapCppTrackerDownstreamReFit::calculate_new_pz(double pz) const { double energy = std::sqrt(Recon::Constants::MuonMass*Recon::Constants::MuonMass + pz*pz); double lower; double upper; double start_position = _tracker_z; double position = _tracker_z; MaterialModelAxialLookup lookup(0, 0, position); do { lookup.SetMaterial(0, 0, position); MaterialModelAxialLookup::GetBounds(position, lower, upper); if (lower < _tracker_z) { start_position = _tracker_z; } else { start_position = lower; } if (upper > _downstream_tracker_z) { position = _downstream_tracker_z; } else { position = upper; } double dEdx = lookup.dEdx(energy, Recon::Constants::MuonMass, +1); energy += dEdx*(position-start_position); position += MaterialModelAxialLookup::GetZTolerance(); } while (position < _downstream_tracker_z); return std::sqrt( energy*energy - Recon::Constants::MuonMass*Recon::Constants::MuonMass); } } // ~namespace MAUS