/* 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 "Utils/CppErrorHandler.hh"
#include "Utils/JsonWrapper.hh"
#include "Utils/DAQChannelMap.hh"
#include "Interface/dataCards.hh"
#include "API/PyWrapMapBase.hh"
#include "Converter/DataConverters/CppJsonSpillConverter.hh"
#include "Converter/DataConverters/JsonCppSpillConverter.hh"
#include "src/map/MapCppEMRRecon/MapCppEMRRecon.hh"
namespace MAUS {
PyMODINIT_FUNC init_MapCppEMRRecon(void) {
PyWrapMapBase::PyWrapMapBaseModInit
("MapCppEMRRecon", "", "", "", "");
}
MapCppEMRRecon::MapCppEMRRecon()
: MapBase("MapCppEMRRecon") {
}
void MapCppEMRRecon::_birth(const std::string& argJsonConfigDocument) {
_classname = "MapCppEMRRecon";
char* pMAUS_ROOT_DIR = getenv("MAUS_ROOT_DIR");
if (!pMAUS_ROOT_DIR) {
throw MAUS::Exception(Exception::recoverable,
"Could not resolve ${MAUS_ROOT_DIR} environment variable",
"MapCppEMRRecon::birth");
}
// JsonCpp setup
Json::Value configJSON;
configJSON = JsonWrapper::StringToJson(argJsonConfigDocument);
// Fetch variables
_number_of_planes = configJSON["EMRnumberOfPlanes"].asInt();
_number_of_bars = configJSON["EMRnumberOfBars"].asInt();
_dbb_count = configJSON["EMRdbbCount"].asDouble();
_charge_threshold = configJSON["EMRchargeThreshold"].asDouble();
_polynomial_order = configJSON["EMRpolynomialOrder"].asInt();
_max_time = configJSON["EMRmaxMotherDaughterTime"].asDouble();
_max_distance = configJSON["EMRmaxMotherDaughterDistance"].asDouble();
_hole_fraction = configJSON["EMRholeFraction"].asDouble();
// Load the EMR calibration map
bool loaded = _calibMap.InitializeFromCards(configJSON);
if (!loaded)
throw(Exception(Exception::recoverable,
"Could not find EMR calibration map",
"MapCppEMRRecon::birth"));
// Load the EMR attenuation map
loaded = _attenMap.InitializeFromCards(configJSON);
if (!loaded)
throw(Exception(Exception::recoverable,
"Could not find EMR attenuation map",
"MapCppEMRReccon::birth"));
// Load the EMR geometry map
loaded = _geoMap.InitializeFromCards(configJSON);
if (!loaded)
throw(Exception(Exception::recoverable,
"Could not find EMR geometry map",
"MapCppEMRReccon::birth"));
}
void MapCppEMRRecon::_death() {
}
void MapCppEMRRecon::_process(Data *data) const {
// Routine data checks before processing it
if ( !data )
throw Exception(Exception::recoverable, "Data was NULL",
"MapCppEMRRecon::_process");
Spill* spill = data->GetSpill();
if ( !spill )
throw Exception(Exception::recoverable, "Spill was NULL",
"MapCppEMRRecon::_process");
if ( spill->GetDaqEventType() != "physics_event" )
return;
size_t nPartEvents = spill->GetReconEventSize();
if ( !nPartEvents )
return;
if ( !spill->GetEMRSpillData() )
return;
bool emrData = false;
for (size_t iPe = 0; iPe < nPartEvents; iPe++) {
EMREvent *evt = spill->GetReconEvents()->at(iPe)->GetEMREvent();
if ( evt->GetMotherPtr() ) {
if ( evt->GetMotherPtr()->GetEMRPlaneHitArraySize() ) {
emrData = true;
break;
}
}
}
if ( !emrData )
return;
// Reconstruct the plane density from plane hits
reconstruct_plane_density(spill, nPartEvents);
// Calculate the total corrected charge and the energy loss pattern from space points
reconstruct_event_charge(spill, nPartEvents);
// Fit the space points with an EMRTrack
reconstruct_tracks(spill, nPartEvents);
// Try to match the mother particles with their decay daughter
match_daughters(spill, nPartEvents);
}
void MapCppEMRRecon::reconstruct_plane_density(MAUS::Spill* spill,
size_t nPartEvents) const {
// Loop over mothers and candidates to reconstruct their plane density
size_t nSeconPartEvents = spill->GetEMRSpillData()->GetEMREventTrackArraySize();
for (size_t iPe = 0; iPe < nPartEvents+nSeconPartEvents; iPe++) {
// Skip events without an EventTrack (mother or candidate)
EMREventTrack* evtTrack;
if ( iPe < nPartEvents ) {
evtTrack = spill->GetReconEvents()->at(iPe)->GetEMREvent()->GetMotherPtr();
} else {
evtTrack = spill->GetEMRSpillData()->GetEMREventTrackArray()[iPe-nPartEvents];
}
if ( !evtTrack )
continue;
// Sort the planes by ascending order of plane ID
EMRPlaneHitArray planeHitArray = evtTrack->GetEMRPlaneHitArray();
sort(planeHitArray.begin(), planeHitArray.end(),
[] (const EMRPlaneHit* a, const EMRPlaneHit* b) {
return a->GetPlane() < b->GetPlane();
});
// Find the first, last and total amount of plane hit by the particle
int fPlaneMA(47), lPlaneMA(0), nPlaneMA(0);
int fPlaneSA(47), lPlaneSA(0), nPlaneSA(0);
for (size_t iPlane = 0; iPlane < planeHitArray.size(); iPlane++) {
int xPlane = planeHitArray[iPlane]->GetPlane();
if ( planeHitArray[iPlane]->GetEMRBarHitArraySize() ) {
nPlaneMA++;
if ( xPlane < fPlaneMA )
fPlaneMA = xPlane;
if ( xPlane > lPlaneMA )
lPlaneMA = xPlane;
}
if ( planeHitArray[iPlane]->GetCharge() > _charge_threshold ) {
nPlaneSA++;
if ( xPlane < fPlaneSA )
fPlaneSA = xPlane;
if ( xPlane > lPlaneSA )
lPlaneSA = xPlane;
}
}
// Mothers should alway hit the first plane
if ( iPe < nPartEvents ) {
fPlaneMA = 0;
fPlaneSA = 0;
}
if ( nPlaneMA )
evtTrack->SetPlaneDensityMA(static_cast
(nPlaneMA)/(lPlaneMA-fPlaneMA+1));
if ( iPe < nPartEvents && nPlaneSA )
evtTrack->SetPlaneDensitySA(static_cast
(nPlaneSA)/(lPlaneSA-fPlaneSA+1));
}
}
void MapCppEMRRecon::reconstruct_event_charge(MAUS::Spill* spill,
size_t nPartEvents) const {
// Loop over mothers and candidates to reconstruct their charge
size_t nSeconPartEvents = spill->GetEMRSpillData()->GetEMREventTrackArraySize();
for (size_t iPe = 0; iPe < nPartEvents+nSeconPartEvents; iPe++) {
// Skip events without an EventTrack (mother or candidate)
EMREventTrack* evtTrack;
if ( iPe < nPartEvents ) {
evtTrack = spill->GetReconEvents()->at(iPe)->GetEMREvent()->GetMotherPtr();
} else {
evtTrack = spill->GetEMRSpillData()->GetEMREventTrackArray()[iPe-nPartEvents];
}
if ( !evtTrack )
continue;
if ( !evtTrack->GetEMRSpacePointArraySize() )
continue;
// Add up the charge from all the spacepoints
EMRSpacePointArray spacePointArray = evtTrack->GetEMRSpacePointArray();
double xTotalChargeMA(0.), xTotalChargeSA(0.);
for (size_t iSP = 0; iSP < spacePointArray.size(); iSP++) {
xTotalChargeMA += spacePointArray[iSP]->GetChargeMA();
xTotalChargeSA += spacePointArray[iSP]->GetChargeSA();
}
evtTrack->SetTotalChargeMA(xTotalChargeMA);
evtTrack->SetTotalChargeSA(xTotalChargeSA);
// Only reconstruct the charge ratio for mothers (muon/pion), irrelevant for candidates
if ( iPe < nPartEvents ) {
// Calculate the total charge in the last 1/5th of the track
size_t nSP = spacePointArray.size();
size_t tSP = nSP*4./5; // Threshold space point ID
double xTailChargeMA(0.), xTailChargeSA(0.);
for (size_t iSP = tSP; iSP < nSP; iSP++) {
xTailChargeMA += spacePointArray[iSP]->GetChargeMA();
xTailChargeSA += spacePointArray[iSP]->GetChargeSA();
}
double xFraction = static_cast(nSP-tSP)/nSP; // Actual proportion in the tail
evtTrack->SetChargeRatioMA(xFraction*(xTotalChargeMA-xTailChargeMA)/xTailChargeMA);
evtTrack->SetChargeRatioSA(xFraction*(xTotalChargeSA-xTailChargeSA)/xTailChargeSA);
}
// Reconstruct the global time of the event (end time for mothers, begin time for daughters)
std::vector::iterator minIterator =
min_element(spacePointArray.begin(), spacePointArray.end(),
[] (const EMRSpacePoint* a, const EMRSpacePoint* b) {
return a->GetTime() < b->GetTime();
});
double mTime(0.);
if ( iPe < nPartEvents ) {
mTime = spacePointArray[distance(spacePointArray.begin(), minIterator)]->GetTime();
} else {
mTime = spacePointArray[distance(spacePointArray.begin(), minIterator)]->GetTime();
}
evtTrack->SetTime(mTime*_dbb_count); // [ns]
}
}
void MapCppEMRRecon::reconstruct_tracks(MAUS::Spill* spill,
size_t nPartEvents) const {
// Loop over mothers and candidates to reconstruct their tracks
size_t nSeconPartEvents = spill->GetEMRSpillData()->GetEMREventTrackArraySize();
for (size_t iPe = 0; iPe < nPartEvents+nSeconPartEvents; iPe++) {
// Skip events without an EventTrack (mother or candidate)
EMREventTrack* evtTrack;
if ( iPe < nPartEvents ) {
evtTrack = spill->GetReconEvents()->at(iPe)->GetEMREvent()->GetMotherPtr();
} else {
evtTrack = spill->GetEMRSpillData()->GetEMREventTrackArray()[iPe-nPartEvents];
}
if ( !evtTrack )
continue;
if ( !evtTrack->GetEMRSpacePointArraySize() )
continue;
// Fit the space points with a polynomial of order n=1 and get the fit parameters
EMRSpacePointArray spacePointArray = evtTrack->GetEMRSpacePointArray();
EMRTrack track;
TrackFitter::polynomial_fit(spacePointArray, track, 1);
std::vector ax = track.GetParametersX();
std::vector ay = track.GetParametersY();
std::vector eax = track.GetParametersErrorsX();
std::vector eay = track.GetParametersErrorsY();
// Set the origin, inclination and azimuth of mothers only
if ( iPe < nPartEvents ) {
double z0 = _geoMap.LocalStart().z();
double x0 = TrackFitter::pol(z0, ax);
double y0 = TrackFitter::pol(z0, ay);
ThreeVector xOrigin(x0, y0, z0); // Local origin
track.SetOrigin(_geoMap.MakeGlobal(xOrigin));
// Propagate the error on the origin from the fit parameters
double sigma_x = TrackFitter::pol_error(z0, 0., ax, eax);
double sigma_y = TrackFitter::pol_error(z0, 0., ay, eay);
ThreeVector xOriginErrors(sigma_x, sigma_y, 0.);
track.SetOriginErrors(xOriginErrors);
// Add the origin to the list of trackpoints
EMRTrackPoint trackPoint;
trackPoint.SetPosition(xOrigin);
trackPoint.SetGlobalPosition(_geoMap.MakeGlobal(xOrigin));
trackPoint.SetPositionErrors(xOriginErrors);
trackPoint.SetChannel(-1);
trackPoint.SetResiduals(0., 0.);
trackPoint.SetChi2(0.);
track.AddEMRTrackPoint(trackPoint);
// Reconstruct the inclination and azimuth at the origin
double mx = TrackFitter::dnpol(z0, ax, 1);
double emx = TrackFitter::dnpol_error(z0, 0, ax, eax, 1);
double my = TrackFitter::dnpol(z0, ay, 1);
double emy = TrackFitter::dnpol_error(z0, 0, ay, eay, 1);
track.SetPolar(TrackFitter::polar(mx, my));
track.SetPolarError(TrackFitter::polar_error(mx, my, emx, emy));
track.SetAzimuth(TrackFitter::azimuth(mx, my));
track.SetAzimuthError(TrackFitter::azimuth_error(mx, my, emx, emy));
}
// For each space point, create a track point on the track
for (size_t iSP = 0; iSP < spacePointArray.size(); iSP++) {
// Find the z of the point on the track closest to the spacepoint in the relevant projection
int xPlane = spacePointArray[iSP]->GetChannel()/_number_of_bars;
double zstart(_geoMap.LocalStart().z()), zend(_geoMap.LocalEnd().z());
double z(0.);
double zp = spacePointArray[iSP]->GetPosition().z();
if ( !xPlane ) {
double xp = spacePointArray[iSP]->GetPosition().x();
z = TrackFitter::pol_closest(ax, zp, xp, zstart, zend);
} else {
double yp = spacePointArray[iSP]->GetPosition().y();
z = TrackFitter::pol_closest(ay, zp, yp, zstart, zend);
}
// Evaluate the function in the two projections in the closest z and set the positon
double x = TrackFitter::pol(z, ax);
double y = TrackFitter::pol(z, ay);
ThreeVector xPos(x, y, z);
// Propagate the error on the track point position from the fit parameters
double sigma_x = TrackFitter::pol_error(z, 0., ax, eax);
double sigma_y = TrackFitter::pol_error(z, 0., ay, eay);
ThreeVector xErrors(sigma_x, sigma_y, spacePointArray[iSP]->GetPositionErrors().z());
// Calculate the residuals and chi squared between the corrected and orginial points
double xRes = x - spacePointArray[iSP]->GetPosition().x();
double yRes = y - spacePointArray[iSP]->GetPosition().y();
double xErr = spacePointArray[iSP]->GetPositionErrors().x();
double yErr = spacePointArray[iSP]->GetPositionErrors().y();
double xChi2 = (pow(xRes, 2)+pow(yRes, 2))/(pow(xErr, 2)+pow(yErr, 2));
// Set the track point
EMRTrackPoint trackPoint;
trackPoint.SetPosition(xPos);
trackPoint.SetGlobalPosition(_geoMap.MakeGlobal(xPos));
trackPoint.SetPositionErrors(xErrors);
trackPoint.SetChannel(spacePointArray[iSP]->GetChannel());
trackPoint.SetResiduals(xRes, yRes);
trackPoint.SetChi2(xChi2);
track.AddEMRTrackPoint(trackPoint);
}
// Sort the newly formed track points by ascending order of z
EMRTrackPointArray trackPointArray = track.GetEMRTrackPointArray();
sort(trackPointArray.begin(), trackPointArray.end(),
[] (const EMRTrackPoint& a, const EMRTrackPoint& b) {
return a.GetPosition().z() < b.GetPosition().z();
});
track.SetEMRTrackPointArray(trackPointArray);
// Reconstruct the range of the particle in the EMR
double zstart = track.GetEMRTrackPointArray().front().GetPosition().z();
double ezstart = track.GetEMRTrackPointArray().front().GetPositionErrors().z();
double zend = track.GetEMRTrackPointArray().back().GetPosition().z();
double ezend = track.GetEMRTrackPointArray().back().GetPositionErrors().z();
double xRange = TrackRange::range_integral(ax, ay, zstart, zend);
double xRangeError = TrackRange::range_integral_error(ax, ay, eax, eay,
zstart, zend, ezstart, ezend);
track.SetRange(xRange);
track.SetRangeError(xRangeError);
// Estimate the momentum of the mothers from the CSDA range (default=muon)
if ( iPe < nPartEvents ) {
// Correct the range to account for the holes and gaps (TODO better)
int lPlane = track.GetEMRTrackPointArray().back().GetChannel()/_number_of_bars;
xRange -= lPlane*_geoMap.Gap();
xRange *= (1-_hole_fraction);
double xMomentum = TrackMomentum::csda_momentum(xRange, "muon");
double xMomentumError = TrackMomentum::csda_momentum_error(xMomentum, xRangeError, "muon");
track.SetMomentum(xMomentum);
track.SetMomentumError(xMomentumError);
}
evtTrack->SetEMRTrack(track);
}
}
void MapCppEMRRecon::match_daughters(MAUS::Spill* spill,
size_t nPartEvents) const {
// Retain the index of the last candidate examinated to not go over them twice
size_t cPe = 0;
// Loop over the mothers and try to match them with their daughter
size_t nSeconPartEvents = spill->GetEMRSpillData()->GetEMREventTrackArraySize();
for (size_t aPe = 0; aPe < nPartEvents; aPe++) {
// Skip events that did not reconstruct a track (no trackpoints)
EMREvent* evt = spill->GetReconEvents()->at(aPe)->GetEMREvent();
EMREventTrack* evtTrackM = evt->GetMotherPtr();
if ( !evtTrackM )
continue;
if ( !evtTrackM->GetEMRTrack().GetEMRTrackPointArraySize() )
continue;
// std::cerr << std::endl;
// std::cerr << "Mother in the EMR" << std::endl;
double aTime = evtTrackM->GetEMRSpacePointArray().front()->GetTime();
EMRTrack aTrack = evtTrackM->GetEMRTrack();
ThreeVector xPoint = aTrack.GetEMRTrackPointArray().back().GetPosition();
int xPe(-1);
double xTime(-1.);
double xDist(9999);
for (size_t bPe = cPe; bPe < nSeconPartEvents; bPe++) {
// Skip candidates that did not reconstruct a track (no trackpoints)
EMREventTrack* evtTrackC = spill->GetEMRSpillData()->GetEMREventTrackArray()[bPe];
if ( !evtTrackC->GetEMRTrack().GetEMRTrackPointArraySize() )
continue;
double bTime = evtTrackC->GetEMRSpacePointArray().front()->GetTime();
EMRTrack bTrack = evtTrackC->GetEMRTrack();
if ( bTime < aTime ) // No decay before the mother particle
continue;
if ( (bTime - aTime) > _max_time ) { // Skip unreasonable time difference
cPe = bPe;
break;
}
ThreeVector fPoint = bTrack.GetEMRTrackPointArray().front().GetPosition();
ThreeVector lPoint = bTrack.GetEMRTrackPointArray().back().GetPosition();
double fDist = dist(xPoint, fPoint);
double lDist = dist(xPoint, lPoint);
if ( fDist < xDist || lDist < xDist ) {
xPe = bPe;
xTime = (bTime - aTime)*_dbb_count; // [ns]
xDist = std::min(fDist, lDist); // [mm]
}
}
// If a daughter is found, deep copy the candidate into the EMREvent
if ( xDist < _max_distance ) {
// std::cerr << "Decay found" << std::endl;
// std::cerr << "xPe: " << xPe << std::endl;
// std::cerr << "xTime: " << xTime << " ns" << std::endl;
// std::cerr << "xDist: " << xDist << " mm" << std::endl;
EMREventTrack* evtTrackX = spill->GetEMRSpillData()->GetEMREventTrackArray()[xPe];
EMREventTrack* evtTrackD = new EMREventTrack;
// Deep copy all the plane hits
for (size_t i = 0; i < evtTrackX->GetEMRPlaneHitArraySize(); i++) {
EMRPlaneHit* planeHit = new EMRPlaneHit;
planeHit->SetEMRBarHitArray(evtTrackX->GetEMRPlaneHitArray()[i]->GetEMRBarHitArray());
planeHit->SetPlane(evtTrackX->GetEMRPlaneHitArray()[i]->GetPlane());
planeHit->SetOrientation(evtTrackX->GetEMRPlaneHitArray()[i]->GetOrientation());
planeHit->SetTime(evtTrackX->GetEMRPlaneHitArray()[i]->GetTime());
planeHit->SetDeltaT(evtTrackX->GetEMRPlaneHitArray()[i]->GetDeltaT());
planeHit->SetCharge(evtTrackX->GetEMRPlaneHitArray()[i]->GetCharge());
planeHit->SetPedestalArea(evtTrackX->GetEMRPlaneHitArray()[i]->GetPedestalArea());
planeHit->SetSampleArray(evtTrackX->GetEMRPlaneHitArray()[i]->GetSampleArray());
evtTrackD->AddEMRPlaneHit(planeHit);
}
// Deep copy all the space points
for (size_t i = 0; i < evtTrackX->GetEMRSpacePointArraySize(); i++) {
EMRSpacePoint* spacePoint = new EMRSpacePoint;
spacePoint->SetPosition(evtTrackX->GetEMRSpacePointArray()[i]->GetPosition());
spacePoint->SetGlobalPosition(evtTrackX->GetEMRSpacePointArray()[i]->GetGlobalPosition());
spacePoint->SetPositionErrors(evtTrackX->GetEMRSpacePointArray()[i]->GetPositionErrors());
spacePoint->SetChannel(evtTrackX->GetEMRSpacePointArray()[i]->GetChannel());
spacePoint->SetTime(evtTrackX->GetEMRSpacePointArray()[i]->GetTime());
spacePoint->SetDeltaT(evtTrackX->GetEMRSpacePointArray()[i]->GetDeltaT());
spacePoint->SetChargeMA(evtTrackX->GetEMRSpacePointArray()[i]->GetChargeMA());
spacePoint->SetChargeSA(evtTrackX->GetEMRSpacePointArray()[i]->GetChargeSA());
evtTrackD->AddEMRSpacePoint(spacePoint);
}
// Deep copy all the PID variables
evtTrackD->SetType("daughter");
evtTrackD->SetTrackId(0);
evtTrackD->SetTime(evtTrackX->GetTime());
evtTrackD->SetPlaneDensityMA(evtTrackX->GetPlaneDensityMA());
evtTrackD->SetPlaneDensitySA(evtTrackX->GetPlaneDensitySA());
evtTrackD->SetTotalChargeMA(evtTrackX->GetTotalChargeMA());
evtTrackD->SetTotalChargeSA(evtTrackX->GetTotalChargeSA());
evtTrackD->SetChargeRatioMA(evtTrackX->GetChargeRatioMA());
evtTrackD->SetChargeRatioSA(evtTrackX->GetChargeRatioSA());
// Reconstruct the Michel electron/positron momentum (TODO beam polarity)
EMRTrack track = evtTrackX->GetEMRTrack();
double xMomentum = TrackMomentum::csda_momentum(track.GetRange(), "electron");
double xMomentumError = TrackMomentum::csda_momentum_error(track.GetRange(),
track.GetRangeError(),
"electron");
track.SetMomentum(xMomentum);
track.SetMomentumError(xMomentumError);
evtTrackD->SetEMRTrack(track);
evt->AddEMREventTrack(evtTrackD);
} else {
// std::cerr << "NO DECAY FOUND" << std::endl;
// std::cerr << "Closest candidate" << std::endl;
// std::cerr << "xPe: " << xPe << std::endl;
// std::cerr << "xTime: " << xTime << " ns" << std::endl;
// std::cerr << "xDist: " << xDist << " mm" << std::endl;
}
// If a daughter is found, set the EMREvent parameters
// TODO When the daughter track recon is improved, improve vertex recon
if ( evt->GetDaughterPtr() ) {
EMREventTrack* evtTrackD = evt->GetDaughterPtr();
evt->SetVertex(evtTrackD->GetEMRTrack().GetEMRTrackPointArray().back().GetGlobalPosition());
evt->SetVertexErrors(ThreeVector(0., 0., 0.));
evt->SetDeltaT(evtTrackD->GetTime()-evtTrackM->GetTime());
ThreeVector e1 = evtTrackD->GetEMRTrack().GetEMRTrackPointArray().back().GetPosition();
ThreeVector s2 = evtTrackD->GetEMRTrack().GetEMRTrackPointArray().front().GetPosition();
ThreeVector e2 = evtTrackD->GetEMRTrack().GetEMRTrackPointArray().back().GetPosition();
evt->SetDistance(std::min(dist(e1, s2), dist(e1, s2)));
double mx1 = evtTrackM->GetEMRTrack().GetParametersX()[1];
double my1 = evtTrackM->GetEMRTrack().GetParametersY()[1];
double mx2 = evtTrackM->GetEMRTrack().GetParametersX()[1];
double my2 = evtTrackM->GetEMRTrack().GetParametersY()[1];
double mx = tan(atan(mx2)-atan(mx1));
double my = tan(atan(my2)-atan(my1));
evt->SetPolar(TrackFitter::polar(mx, my));
evt->SetAzimuth(TrackFitter::azimuth(mx, my));
}
}
}
double MapCppEMRRecon::dist(MAUS::ThreeVector p1,
MAUS::ThreeVector p2) const {
return sqrt(pow(p2.x()-p1.x(), 2)+
pow(p2.y()-p1.y(), 2)+
pow(p2.z()-p1.z(), 2));
}
}