/* 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/MapCppTrackerTOFReFit/MapCppTrackerTOFReFit.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_MapCppTrackerTOFReFit(void) { PyWrapMapBase::PyWrapMapBaseModInit ("MapCppTrackerTOFReFit", "", "", "", ""); } MapCppTrackerTOFReFit::MapCppTrackerTOFReFit() : MapBase("MapCppTrackerTOFReFit"), _helical_track_fitter(NULL), _radius_cut(10.0), _has_tof(false) { } MapCppTrackerTOFReFit::~MapCppTrackerTOFReFit() { } void MapCppTrackerTOFReFit::_birth(const std::string& argJsonConfigDocument) { // Pull out the global settings if (!Globals::HasInstance()) { GlobalsManager::InitialiseGlobals(argJsonConfigDocument); } Json::Value* json = Globals::GetConfigurationCards(); std::vector tof_modules = Globals::GetReconstructionMiceModules()-> findModulesByPropertyString("SensitiveDetector", "TOF"); _radius_cut = (*json)["SciFiHelicalRadiusLimit"].asDouble(); _has_tof = ( tof_modules.size() > 0 ? true : false ); // Values used to set the track rating: if (!_has_tof) { Squeak::mout(Squeak::warning) << "Tracker-TOF Refit Mapper is initialised but there is no TOF" << "in the reconstruction geometry"; } _tof1_z = 0.0; bool found = false; for (std::vector::const_iterator it = tof_modules.begin(); it != tof_modules.end(); ++it) { const MiceModule* parent = (*it)->mother(); if (parent->propertyInt("Station") == 1) { _tof1_z = parent->globalPosition().z(); found = true; break; } } if (!found) { throw Exceptions::Exception(Exceptions::nonRecoverable, "MapCppTrackerTOFReFit::_birth()", "Could not locate the TOF1 Detetector"); } double lower, upper; MaterialModelAxialLookup::GetBounds(_tof1_z, lower, upper); _tof1_z = lower; // Find the start of the TOF detector. SciFiTrackerMap& geo_map = Globals::GetSciFiGeometryHelper()->GeometryMap(); // Set up final track fit (Kalman filter) 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); // Each measurement plane has a unique alignment and rotation => they all need their own // measurement object. 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) { _tracker_z = plane_it->second.GlobalPosition.Z(); } } } } void MapCppTrackerTOFReFit::_death() { if (_helical_track_fitter) { delete _helical_track_fitter; _helical_track_fitter = NULL; } } void MapCppTrackerTOFReFit::_process(Data* data) const { if (!_has_tof) { return; } 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; } TOFEvent *tof_event = spill.GetReconEvents()->at(k)->GetTOFEvent(); if (!tof_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() ) { if ( calculate_pz_seed(seed, tof_event) ) { 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() == 0 ) { if ( calculate_straight_pz_seed(seed, tof_event) ) { 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* MapCppTrackerTOFReFit::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 MapCppTrackerTOFReFit::needs_refitting(MAUS::SciFiSeed* seed) const { if ( seed->getTracker() != 0 ) { return false; } else if ( static_cast(seed->getPRTrackTobject())->get_R() > this->_radius_cut ) { return false; } return true; } bool MapCppTrackerTOFReFit::calculate_pz_seed(MAUS::SciFiSeed* seed, TOFEvent* tof_event) const { TOFEventSpacePoint* spacepoints = tof_event->GetTOFEventSpacePointPtr(); if (spacepoints->GetTOF0SpacePointArraySize() != 1 ) return false; if (spacepoints->GetTOF1SpacePointArraySize() != 1 ) return false; TOFSpacePoint tof0 = spacepoints->GetTOF0SpacePointArrayElement(0); TOFSpacePoint tof1 = spacepoints->GetTOF1SpacePointArrayElement(0); double delta_T = tof1.GetTime() - tof0.GetTime(); double delta_Z = tof1.GetGlobalPosZ() - tof0.GetGlobalPosZ(); double beta = delta_Z / ( delta_T * CLHEP::c_light); double gamma = 1.0 / sqrt(1.0 - beta*beta); double pz = gamma*beta*Recon::Constants::MuonMass; // Propagate from TOF to tracker pz = calculate_new_pz(pz); 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 MapCppTrackerTOFReFit::calculate_straight_pz_seed(MAUS::SciFiSeed* seed, TOFEvent* tof_event) const { TOFEventSpacePoint* spacepoints = tof_event->GetTOFEventSpacePointPtr(); if (spacepoints->GetTOF0SpacePointArraySize() != 1 ) return false; if (spacepoints->GetTOF1SpacePointArraySize() != 1 ) return false; TOFSpacePoint tof0 = spacepoints->GetTOF0SpacePointArrayElement(0); TOFSpacePoint tof1 = spacepoints->GetTOF1SpacePointArrayElement(0); double delta_T = tof1.GetTime() - tof0.GetTime(); double delta_Z = tof1.GetGlobalPosZ() - tof0.GetGlobalPosZ(); double beta = delta_Z / (delta_T * CLHEP::c_light); double gamma = 1.0 / sqrt(1.0 - beta*beta); double pz = gamma*beta*Recon::Constants::MuonMass; // Propagate from TOF to tracker pz = calculate_new_pz(pz); 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 MapCppTrackerTOFReFit::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 = _tof1_z; double position = _tof1_z; MaterialModelAxialLookup lookup(0, 0, position); do { lookup.SetMaterial(0, 0, position); MaterialModelAxialLookup::GetBounds(position, lower, upper); if (lower < _tof1_z) { start_position = _tof1_z; } else { start_position = lower; } if (upper > _tracker_z) { position = _tracker_z; } else { position = upper; } double dEdx = lookup.dEdx(energy, Recon::Constants::MuonMass, +1); energy += dEdx*(position-start_position); position += MaterialModelAxialLookup::GetZTolerance(); } while (position < _tracker_z); return std::sqrt( energy*energy - Recon::Constants::MuonMass*Recon::Constants::MuonMass); } } // ~namespace MAUS