/* 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/common_cpp/Recon/Kalman/MAUSTrackWrapper.hh" #include #include "TMatrixD.h" namespace MAUS { template bool SortByZ(const ELEMENT *a, const ELEMENT *b) { return (a->get_position().z() > b->get_position().z()); } Kalman::Track BuildTrack(SciFiClusterPArray cluster_array, const SciFiGeometryHelper* geom) { Kalman::Track new_track(1); size_t numbclusters = cluster_array.size(); if (numbclusters < 1) return new_track; int tracker = cluster_array[0]->get_tracker(); const SciFiPlaneMap& geom_map = geom->GeometryMap().find(tracker)->second.Planes; int tracker_const = (tracker == 0 ? -1 : 1); for (SciFiPlaneMap::const_iterator iter = geom_map.begin(); iter != geom_map.end(); ++iter) { int id = iter->first * tracker_const; Kalman::State new_state = Kalman::State(1, iter->second.Position.z()); new_state.SetId(id); new_track.Append(new_state); } for (size_t j = 0; j < numbclusters; ++j) { SciFiCluster* cluster = cluster_array[j]; int id = (cluster->get_station() - 1)*3 + cluster->get_plane(); // Actually (id - 1) // TODO : // - APPLY GEOMETRY CORRECTIONS! // - Fill covariance matrix correctly! TMatrixD state_vector(1, 1); TMatrixD covariance(1, 1); state_vector(0, 0) = cluster->get_alpha(); covariance(0, 0) = 0.0; new_track[id].SetVector(state_vector); new_track[id].SetCovariance(covariance); } return new_track; } Kalman::State ComputeSeed(SciFiHelicalPRTrack* h_track, const SciFiGeometryHelper* geom, bool correct_energy_loss, double seed_cov) { TMatrixD vector(5, 1); TMatrixD covariance(5, 5); int tracker = h_track->get_tracker(); int seed_id = (tracker == 0 ? -15 : 15); double seed_pos = geom->GetPlanePosition(tracker, 5, 2); double length = seed_pos; double c = CLHEP::c_light; double particle_charge = h_track->get_charge(); double Bz = geom->GetFieldValue(tracker); // Get h_track values. double r = h_track->get_R(); double pt = - c*Bz*r*particle_charge; double dsdz = - h_track->get_dsdz(); double x0 = h_track->get_circle_x0(); // Circle Center x double y0 = h_track->get_circle_y0(); // Circle Center y double s = (h_track->get_line_sz_c() - length*dsdz); // Path length at start plane double phi_0 = s / r; // Phi at start plane double phi = phi_0 + TMath::PiOver2(); // Direction of momentum // TODO: Actually propagate the track parrameters and covariance matrix back to start plane. // This is an approximation. ThreeVector patrec_momentum(-pt*sin(phi_0), pt*cos(phi_0), - pt/dsdz); if (correct_energy_loss) { double P = patrec_momentum.mag(); double patrec_bias; // Account for two planes of energy loss if (tracker == 0) { patrec_bias = (P + 1.4) / P; } else { patrec_bias = (P + 1.4) / P; } patrec_momentum = patrec_bias * patrec_momentum; } double x = x0 + r*cos(phi_0); double px = patrec_momentum.x(); double y = y0 + r*sin(phi_0); double py = patrec_momentum.y(); double kappa = particle_charge / patrec_momentum.z(); vector(0, 0) = x; vector(1, 0) = px; vector(2, 0) = y; vector(3, 0) = py; vector(4, 0) = kappa; // // METHOD = ED SANTOS // if (seed_cov > 0.0) { covariance.Zero(); for (int i = 0; i < 5; ++i) { covariance(i, i) = seed_cov; } } else { // // METHOD = CHRISTOPHER HUNT // std::vector cov = h_track->get_covariance(); TMatrixD patrec_covariance(5, 5); if (cov.size() != 25) { throw MAUS::Exception(MAUS::Exception::recoverable, "Dimension of covariance matrix does not match the state vector", "KalmanSeed::ComputeInitalCovariance(Helical)"); } double mc = particle_charge*c*Bz; // Magnetic constant double sin = std::sin(phi_0); double cos = std::cos(phi_0); double sin_plus = std::sin(phi); double cos_plus = std::cos(phi); TMatrixD jacobian(5, 5); jacobian(0, 0) = 1.0; jacobian(0, 2) = cos + phi*sin; jacobian(0, 3) = -sin; jacobian(1, 2) = mc*cos_plus + mc*phi*sin_plus; jacobian(1, 3) = -mc*sin_plus; jacobian(2, 1) = 1.0; jacobian(2, 2) = sin - phi*cos; jacobian(2, 3) = cos; jacobian(3, 2) = mc*sin_plus - mc*phi*cos_plus; jacobian(1, 3) = mc*cos_plus; jacobian(4, 3) = -dsdz / (mc*r*r); jacobian(4, 4) = 1.0 / (mc*r); TMatrixD jacobianT(5, 5); jacobianT.Transpose(jacobian); for (int i = 0; i < 5; ++i) { for (int j = 0; j < 5; ++j) { patrec_covariance(i, j) = cov.at(i*5 + j); } } covariance = jacobian*patrec_covariance*jacobianT; } Kalman::State seed_state(vector, covariance, seed_pos); seed_state.SetId(seed_id); return seed_state; } Kalman::State ComputeSeed(SciFiStraightPRTrack* s_track, const SciFiGeometryHelper* geom, double seed_cov) { TMatrixD vector(4, 1); TMatrixD covariance(4, 4); int tracker = s_track->get_tracker(); double seed_pos = geom->GetPlanePosition(tracker, 5, 2); double length = seed_pos; int seed_id = (tracker == 0 ? -15 : 15); double x0 = s_track->get_x0(); double y0 = s_track->get_y0(); double mx = s_track->get_mx(); double my = s_track->get_my(); // Get position at the starting end of tracker double x = x0 + mx*length; double y = y0 + my*length; vector(0, 0) = x; vector(1, 0) = mx; vector(2, 0) = y; vector(3, 0) = my; // // METHOD = ED SANTOS // if (seed_cov > 0.0) { covariance.Zero(); for (int i = 0; i < 4; ++i) { covariance(i, i) = seed_cov; } } else { // // METHOD = CHRISTOPHER HUNT // std::vector cov = s_track->get_covariance(); TMatrixD patrec_covariance(4, 4); if (cov.size() != (unsigned int)16) { throw MAUS::Exception(MAUS::Exception::recoverable, "Dimension of covariance matrix does not match the state vector", "KalmanSeed::ComputeInitalCovariance(Straight)"); } TMatrixD jacobian(4, 4); jacobian(0, 0) = 1.0; jacobian(1, 1) = 1.0; jacobian(2, 2) = 1.0; jacobian(3, 3) = 1.0; jacobian(0, 1) = length; jacobian(2, 3) = length; TMatrixD jacobianT(4, 4); jacobianT.Transpose(jacobian); for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { patrec_covariance(i, j) = cov.at(i*4 + j); } } covariance = jacobian*patrec_covariance*jacobianT; } Kalman::State seed_state(vector, covariance, seed_pos); seed_state.SetId(seed_id); return seed_state; } SciFiTrack* ConvertToSciFiTrack(const Kalman::TrackFit* fitter, const SciFiGeometryHelper* geom) { SciFiTrack* new_track = new SciFiTrack(); const Kalman::Track& smoothed = fitter->Smoothed(); // const Kalman::Track& smoothed = fitter->Filtered(); // const Kalman::Track& filtered = fitter->Filtered(); // const Kalman::Track& predicted = fitter->Predicted(); const Kalman::Track& data = fitter->Data(); Kalman::State seed = fitter->GetSeed(); double default_mom = geom->GetDefaultMomentum(); if (smoothed.GetLength() < 1) throw MAUS::Exception(MAUS::Exception::recoverable, "Not enough points in Kalman Track", "ConvertToSciFiTrack()"); double chi_squared = fitter->CalculateChiSquared(smoothed); int NDF = fitter->GetNDF(); double p_value = TMath::Prob(chi_squared, NDF); int tracker; if (smoothed[0].GetId() > 0) { tracker = 1; } else { tracker = 0; } new_track->set_tracker(tracker); int dimension = smoothed.GetDimension(); if (dimension == 4) { new_track->SetAlgorithmUsed(SciFiTrack::kalman_straight); } else if (dimension == 5) { new_track->SetAlgorithmUsed(SciFiTrack::kalman_helical); } else { throw MAUS::Exception(MAUS::Exception::recoverable, "Unexpected dimension of Kalman::Track", "ConvertToSciFiTrack()"); } // const SciFiGeometryMap& geom_map = geom->GeometryMap(); ThreeVector reference_pos = geom->GetReferencePosition(tracker); HepRotation reference_rot = geom->GetReferenceRotation(tracker); int charge = 0; for (unsigned int i = 0; i < smoothed.GetLength(); ++i) { const Kalman::State& smoothed_state = smoothed[i]; // const Kalman::State& filtered_state = filtered[i]; // const Kalman::State& predicted_state = predicted[i]; const Kalman::State& data_state = data[i]; SciFiTrackPoint* new_point = new SciFiTrackPoint(); new_point->set_tracker(tracker); int id = abs(smoothed_state.GetId()); new_point->set_station(((id-1)/3)+1); new_point->set_plane((id-1)%3); ThreeVector pos; ThreeVector mom; TMatrixD state_vector = smoothed_state.GetVector(); if (dimension == 4) { pos.setZ(smoothed_state.GetPosition()); pos.setX(state_vector(0, 0)); mom.setX(state_vector(1, 0)*default_mom); pos.setY(state_vector(2, 0)); mom.setY(state_vector(3, 0)*default_mom); pos *= reference_rot; pos += reference_pos; mom *= reference_rot; if (tracker == 0) mom *= -1.0; mom.setZ(default_mom); // MeV/c } else if (dimension == 5) { pos.setX(state_vector(0, 0)); mom.setX(state_vector(1, 0)); pos.setY(state_vector(2, 0)); mom.setY(state_vector(3, 0)); pos.setZ(smoothed_state.GetPosition()); pos *= reference_rot; pos += reference_pos; mom *= reference_rot; if (mom.z() < 0.0) { charge = -1; } else { charge = 1; } mom.setZ(fabs(1.0/state_vector(4, 0))); } // if (mom.z() < 0.0) { // mom.setZ(- mom.z()); // } // if (tracker == 0) { // mom.setZ(fabs(mom.z())); // mom.setY(-1.0*mom.y()); // } new_point->set_pos(pos); new_point->set_mom(mom); // TODO // _pull = kalman_site->residual(KalmanState::Projected)(0, 0); // _residual = kalman_site->residual(KalmanState::Filtered)(0, 0); // _smoothed_residual = kalman_site->residual(KalmanState::Smoothed)(0, 0); // AND CHARGE! if (data_state) { // new_point->set_pull(sqrt(fitter->CalculatePredictedResidual(i).GetVector().E2Norm())); // new_point->set_residual(sqrt(fitter->CalculateFilteredResidual(i).GetVector().E2Norm())); // new_point->set_smoothed_residual( // sqrt(fitter->CalculateSmoothedResidual(i).GetVector().E2Norm())); new_point->set_pull(fitter->CalculatePredictedResidual(i).GetVector()(0, 0)); new_point->set_residual(fitter->CalculateFilteredResidual(i).GetVector()(0, 0)); new_point->set_smoothed_residual(fitter->CalculateSmoothedResidual(i).GetVector()(0, 0)); } else { new_point->set_pull(0.0); new_point->set_residual(0.0); new_point->set_smoothed_residual(0.0); } TMatrixD C = smoothed_state.GetCovariance(); int size = C.GetNrows(); int num_elements = size*size; double* matrix_elements = C.GetMatrixArray(); std::vector covariance(num_elements); for (int i = 0; i < num_elements; ++i) { covariance[i] = matrix_elements[i]; } new_point->set_covariance(covariance); std::vector errors(size); for (int i = 0; i < size; ++i) { errors[i] = std::sqrt(fabs(C(i, i))); } new_point->set_errors(errors); // TODO // _cluster = new TRef(kalman_site->cluster()); new_point->set_cluster(new TRef()); new_track->add_scifitrackpoint(new_point); } new_track->set_charge(charge); new_track->set_chi2(chi_squared); new_track->set_ndf(NDF); new_track->set_P_value(p_value); TMatrixD seed_vector = seed.GetVector(); ThreeVector seed_pos; ThreeVector seed_mom; if (dimension == 4) { seed_pos.setZ(seed.GetPosition()); seed_pos.setX(seed_vector(0, 0)); seed_mom.setX(seed_vector(1, 0)*default_mom); seed_pos.setY(seed_vector(2, 0)); seed_mom.setY(seed_vector(3, 0)*default_mom); } else if (dimension == 5) { seed_pos.setX(seed_vector(0, 0)); seed_mom.setX(seed_vector(1, 0)); seed_pos.setY(seed_vector(2, 0)); seed_mom.setY(seed_vector(3, 0)); seed_pos.setZ(seed.GetPosition()); } seed_pos *= reference_rot; seed_pos += reference_pos; seed_mom *= reference_rot; if (dimension == 4) { seed_mom.setZ(default_mom); } else if (dimension == 5) { seed_mom.setZ(fabs(1.0/seed_vector(4, 0))); } new_track->SetSeedPosition(seed_pos); new_track->SetSeedMomentum(seed_mom); new_track->SetSeedCovariance(seed.GetCovariance().GetMatrixArray(), dimension*dimension); // TODO: // - Set Cluster // - Calculate p-value // - Set Algorithm used // - Set Seed Info // - Init track before the fit? return new_track; } Kalman::Track BuildSpacepointTrack(SciFiSpacePointPArray spacepoints, const SciFiGeometryHelper* geom, int plane_num, double smear) { // TRandom3 rand; Kalman::Track new_track(2); int tracker = (*spacepoints.begin())->get_tracker(); for (unsigned int i = 0; i < 5; ++i) { Kalman::State new_state(2, geom->GetPlanePosition(tracker, i+1, plane_num)); new_state.SetId((1 + i*3 + plane_num)*(tracker == 0 ? -1 : 1)); new_track.Append(new_state); } for (SciFiSpacePointPArray::iterator it = spacepoints.begin(); it != spacepoints.end(); ++it) { int station = (*it)->get_station(); TMatrixD vec(2, 1); TMatrixD cov(2, 2); cov.Zero(); vec(0, 0) = (*it)->get_position().x();// * (1.0 + rand.Gaus(0.0, smear)); vec(1, 0) = (*it)->get_position().y();// * (1.0 + rand.Gaus(0.0, smear)); cov(0, 0) = 0.0; cov(1, 1) = 0.0; new_track[station-1].SetVector(vec); new_track[station-1].SetCovariance(cov); new_track[station-1].SetPosition((*it)->get_position().z()); } return new_track; } }