#include "Reconstructor.h" #include "MassLookup.h" #include namespace SabreRecon { constexpr double Reconstructor::s_phiDet[5]; //C++11 weirdness with static constexpr Reconstructor::Reconstructor() { } Reconstructor::Reconstructor(const Target& target, double spsTheta, double spsB, const std::vector& spsCal) { Init(target, spsTheta, spsB, spsCal); } Reconstructor::~Reconstructor() {} void Reconstructor::Init(const Target& target, double spsTheta, double spsB, const std::vector& spsCal) { m_target = target; m_focalPlane.Init({spsB, spsTheta, spsCal}); for(int i=0; i<5; i++) m_sabreArray.emplace_back(SabreDetector::Parameters(s_phiDet[i], s_tiltAngle, s_zOffset, false, i)); //Setup intermediate energy loss layers m_sabreDeadLayer.SetParameters({28}, {14}, {1}, s_sabreDeadlayerThickness); } void Reconstructor::AddEnergyLossTable(const std::string& filename) { m_elossTables.emplace_back(filename); } void Reconstructor::AddPunchThruTable(const std::string& filename) { m_punchTables.emplace_back(filename); } PunchTable::ElossTable* Reconstructor::GetElossTable(const NucID& projectile, const NucID& material) { MassLookup& masses = MassLookup::GetInstance(); std::string projString = masses.FindSymbol(projectile.Z, projectile.A); std::string matString = masses.FindSymbol(material.Z, material.A) + "1"; //temp for(auto& table : m_elossTables) { if(table.GetProjectile() == projString && table.GetMaterial() == matString) return &table; } return nullptr; } PunchTable::PunchTable* Reconstructor::GetPunchThruTable(const NucID& projectile, const NucID& material) { MassLookup& masses = MassLookup::GetInstance(); std::string projString = masses.FindSymbol(projectile.Z, projectile.A); std::string matString = masses.FindSymbol(material.Z, material.A) + "1"; //temp for(auto& table : m_punchTables) { if(table.GetProjectile() == projString && table.GetMaterial() == matString) return &table; } return nullptr; } TLorentzVector Reconstructor::GetSabre4Vector(const SabrePair& pair, double mass) { TVector3 coords; TLorentzVector result; double p, E, theta, phi; //if(pair.detID == 4) // coords = m_sabreArray[4].GetHitCoordinates(15-pair.local_ring, pair.local_wedge); //else coords = m_sabreArray[pair.detID].GetHitCoordinates(pair.local_ring, pair.local_wedge); p = std::sqrt(pair.ringE*(pair.ringE + 2.0*mass)); E = pair.ringE + mass; theta = coords.Theta(); phi = coords.Phi(); result.SetPxPyPzE(p*std::sin(theta)*std::cos(phi), p*std::sin(theta)*std::sin(phi), p*std::cos(theta), E); return result; } TLorentzVector Reconstructor::GetSabre4VectorEloss(const SabrePair& pair, double mass, const NucID& id) { TVector3 coords, sabreNorm; TLorentzVector result; double incidentAngle, p, E, rxnKE, theta, phi; //if(pair.detID == 4) // coords = m_sabreArray[4].GetHitCoordinates(15-pair.local_ring, pair.local_wedge); //else coords = m_sabreArray[pair.detID].GetHitCoordinates(pair.local_ring, pair.local_wedge); sabreNorm = m_sabreArray[pair.detID].GetNormTilted(); incidentAngle = std::acos(sabreNorm.Dot(coords)/(sabreNorm.Mag()*coords.Mag())); rxnKE = pair.ringE + m_sabreDeadLayer.GetReverseEnergyLossTotal(id.Z, id.A, pair.ringE, incidentAngle); rxnKE += m_target.GetReverseEnergyLossFractionalDepth(id.Z, id.A, rxnKE, coords.Theta(), 0.5); p = std::sqrt(rxnKE*(rxnKE + 2.0*mass)); E = rxnKE + mass; theta = coords.Theta(); phi = coords.Phi(); result.SetPxPyPzE(p*std::sin(theta)*std::cos(phi), p*std::sin(theta)*std::sin(phi), p*std::cos(theta), E); return result; } TLorentzVector Reconstructor::GetSabre4VectorElossPunchThru(const SabrePair& pair, double mass, const NucID& id) { TVector3 coords, sabreNorm; TLorentzVector result; double incidentAngle, p, E, rxnKE, theta, phi; PunchTable::PunchTable* table = GetPunchThruTable(id, {14, 28}); if(table == nullptr) return result; //if(pair.detID == 4) // coords = m_sabreArray[4].GetHitCoordinates(15-pair.local_ring, pair.local_wedge); //else coords = m_sabreArray[pair.detID].GetHitCoordinates(pair.local_ring, pair.local_wedge); sabreNorm = m_sabreArray[pair.detID].GetNormTilted(); incidentAngle = std::acos(sabreNorm.Dot(coords)/(sabreNorm.Mag()*coords.Mag())); if(incidentAngle > M_PI/2.0) incidentAngle = M_PI - incidentAngle; rxnKE = table->GetInitialKineticEnergy(incidentAngle, pair.ringE); if(rxnKE == 0.0) return result; rxnKE += m_target.GetReverseEnergyLossFractionalDepth(id.Z, id.A, rxnKE, coords.Theta(), 0.5); p = std::sqrt(rxnKE*(rxnKE + 2.0*mass)); E = rxnKE + mass; theta = coords.Theta(); phi = coords.Phi(); result.SetPxPyPzE(p*std::sin(theta)*std::cos(phi), p*std::sin(theta)*std::sin(phi), p*std::cos(theta), E); return result; } TLorentzVector Reconstructor::GetSabre4VectorElossPunchThruDegraded(const SabrePair& pair, double mass, const NucID& id) { TVector3 coords, sabreNorm; TLorentzVector result; double incidentAngle, p, E, rxnKE, theta, phi; PunchTable::PunchTable* ptable = GetPunchThruTable(id, {14, 28}); PunchTable::ElossTable* etable = GetElossTable(id, {73, 181}); if(ptable == nullptr || etable == nullptr) return result; //if(pair.detID == 4) // coords = m_sabreArray[4].GetHitCoordinates(15-pair.local_ring, pair.local_wedge); //else coords = m_sabreArray[pair.detID].GetHitCoordinates(pair.local_ring, pair.local_wedge); sabreNorm = m_sabreArray[pair.detID].GetNormTilted(); incidentAngle = std::acos(sabreNorm.Dot(coords)/(sabreNorm.Mag()*coords.Mag())); if(incidentAngle > M_PI/2.0) incidentAngle = M_PI - incidentAngle; rxnKE = ptable->GetInitialKineticEnergy(incidentAngle, pair.ringE); if(rxnKE == pair.ringE) return result; rxnKE += etable->GetEnergyLoss(incidentAngle, rxnKE); if(rxnKE == 0.0) return result; rxnKE += m_target.GetReverseEnergyLossFractionalDepth(id.Z, id.A, rxnKE, coords.Theta(), 0.5); p = std::sqrt(rxnKE*(rxnKE + 2.0*mass)); E = rxnKE + mass; theta = coords.Theta(); phi = coords.Phi(); result.SetPxPyPzE(p*std::sin(theta)*std::cos(phi), p*std::sin(theta)*std::sin(phi), p*std::cos(theta), E); return result; } TLorentzVector Reconstructor::GetFP4VectorEloss(double xavg, double mass, const NucID& id) { TLorentzVector result; double p = m_focalPlane.GetP(xavg, id.Z); double theta = m_focalPlane.GetFPTheta(); double KE = std::sqrt(p*p + mass*mass) - mass; double rxnKE = KE + m_target.GetReverseEnergyLossFractionalDepth(id.Z, id.A, KE, theta, 0.5); double rxnP = sqrt(rxnKE*(rxnKE + 2.0*mass)); double rxnE = rxnKE + mass; result.SetPxPyPzE(rxnP*std::sin(theta), 0.0, rxnP*std::cos(theta), rxnE); return result; } TLorentzVector Reconstructor::GetProj4VectorEloss(double beamKE, double mass, const NucID& id) { TLorentzVector result; double rxnKE = beamKE + m_target.GetReverseEnergyLossFractionalDepth(id.Z, id.A, beamKE, 0.0, 0.5); result.SetPxPyPzE(0.0,0.0,std::sqrt(rxnKE*(rxnKE+2.0*mass)),rxnKE+mass); return result; } ReconResult Reconstructor::RunThreeParticleExcitation(const SabrePair& p1, const SabrePair& p2, const SabrePair& p3, const std::vector& nuclei) { ReconResult result; NucID parent; parent.Z = nuclei[0].Z + nuclei[1].Z + nuclei[2].Z; parent.A = nuclei[0].A + nuclei[1].A + nuclei[2].A; if(parent.Z > parent.A || parent.A <= 0 || parent.Z < 0) { std::cerr<<"Invalid parent nucleus at Reconstructor::RunThreeParticleExcitation with Z: "<& nuclei) { ReconResult result; NucID parent; parent.Z = nuclei[0].Z + nuclei[1].Z; parent.A = nuclei[0].A + nuclei[1].A; if(parent.Z > parent.A || parent.A <= 0 || parent.Z < 0) { std::cerr<<"Invalid parent nucleus at Reconstructor::RunTwoParticleExcitation with Z: "<& nuclei) { ReconResult result; NucID resid; resid.Z = nuclei[0].Z + nuclei[1].Z - nuclei[2].Z; resid.A = nuclei[0].A + nuclei[1].A - nuclei[2].A; if(resid.Z > resid.A || resid.A <= 0 || resid.Z < 0) { std::cerr<<"Invalid reisdual nucleus at Reconstructor::RunFPResidExcitation with Z: "<& nuclei) { ReconResult result; NucID resid; resid.Z = nuclei[0].Z + nuclei[1].Z - nuclei[2].Z; resid.A = nuclei[0].A + nuclei[1].A - nuclei[2].A; if(resid.Z > resid.A || resid.A <= 0 || resid.Z < 0) { std::cerr<<"Invalid reisdual nucleus at Reconstructor::RunFPResidExcitation with Z: "<& nuclei) { ReconResult result; NucID decayFrag; decayFrag.Z = nuclei[0].Z + nuclei[1].Z - nuclei[2].Z - nuclei[3].Z; decayFrag.A = nuclei[0].A + nuclei[1].A - nuclei[2].A - nuclei[3].A; if(decayFrag.Z > decayFrag.A || decayFrag.A <= 0 || decayFrag.Z < 0) { std::cerr<<"Invalid reisdual nucleus at Reconstructor::RunSabreExcitation with Z: "<& nuclei) { ReconResult result; NucID decayFrag; decayFrag.Z = nuclei[0].Z + nuclei[1].Z - nuclei[2].Z - nuclei[3].Z; decayFrag.A = nuclei[0].A + nuclei[1].A - nuclei[2].A - nuclei[3].A; if(decayFrag.Z > decayFrag.A || decayFrag.A <= 0 || decayFrag.Z < 0) { std::cerr<<"Invalid reisdual nucleus at Reconstructor::RunSabreExcitation with Z: "<& nuclei) { ReconResult result; NucID decayFrag; decayFrag.Z = nuclei[0].Z + nuclei[1].Z - nuclei[2].Z - nuclei[3].Z; decayFrag.A = nuclei[0].A + nuclei[1].A - nuclei[2].A - nuclei[3].A; if(decayFrag.Z > decayFrag.A || decayFrag.A <= 0 || decayFrag.Z < 0) { std::cerr<<"Invalid reisdual nucleus at Reconstructor::RunSabreExcitation with Z: "<& nuclei) { ReconResult result; NucID decayFrag; decayFrag.Z = nuclei[0].Z + nuclei[1].Z - nuclei[2].Z - nuclei[3].Z; decayFrag.A = nuclei[0].A + nuclei[1].A - nuclei[2].A - nuclei[3].A; if(decayFrag.Z > decayFrag.A || decayFrag.A <= 0 || decayFrag.Z < 0) { std::cerr<<"Invalid reisdual nucleus at Reconstructor::RunSabreExcitation with Z: "<