#include "src/legacy/Optics/CovarianceMatrix.hh" #include "Tensor.hh" #include "Tensor3.hh" #include "Config/MiceModule.hh" #include "Config/ModuleConverter.hh" #include "Interface/Differentiator.hh" #include "Maths/PolynomialMap.hh" #include "src/legacy/Optics/PhaseSpaceVector.hh" using CLHEP::HepSymMatrix; using CLHEP::HepVector; using CLHEP::c_light; const std::string CovarianceMatrix::_psvVars[5] = {"amplitude_t", "amplitude_x", "amplitude_y", "amplitude_4d", "amplitude_6d"}; const std::string CovarianceMatrix::_bunchVars[23] = {"weight", "emit_6d", "emit_4d", "emit_t", "emit_x", "emit_y", "beta_4d", "beta_t", "beta_x", "beta_y", "alpha_4d", "alpha_t", "alpha_x", "alpha_y", "gamma_4d", "gamma_t", "gamma_x", "gamma_y", "disp_x", "disp_y", "ltwiddle", "lcan", "lkin"}; const std::string CovarianceMatrix::_varTypes[5] = {"Mean", "Covariance", "Standard_Deviation", "Correlation", "Bunch_Parameter"}; const std::string CovarianceMatrix::_phaseSpace[6] = {"t", "E", "x", "px", "y", "py"}; const std::string CovarianceMatrix::_traceSpace[6] = {"t", "t\'", "x", "x\'", "y", "y\'"}; CovarianceMatrix::CovarianceMatrix() : _covNorm(HepSymMatrix(6,1)), _norm(-1), _mean(PhaseSpaceVector()), _weight(1) {} CovarianceMatrix::CovarianceMatrix(HepSymMatrix covariances, PhaseSpaceVector mean, double weight, bool covIsKinetic) : _mean(mean), _weight(weight) { HepSymMatrix cov; if(!covIsKinetic) cov = TransformToKinetic(covariances, mean.Bz(), mean.Ez(), 0.); else cov = covariances; SetCovariances(cov); } CovarianceMatrix::CovarianceMatrix(HepSymMatrix covariances, PhaseSpaceVector mean, double norm, double weight, bool covIsKinetic) : _norm(norm), _mean(mean), _weight(weight) { HepSymMatrix cov; if(!covIsKinetic) cov = TransformToKinetic(covariances, mean.Bz(), mean.Ez(), 0.); else cov = covariances; _covNorm = cov; } CovarianceMatrix::CovarianceMatrix(HepSymMatrix covariances, PhaseSpaceVector mean, bool covIsKinetic) : _mean(mean), _weight(1) { HepSymMatrix cov; if(!covIsKinetic) cov = TransformToKinetic(covariances, mean.Bz(), mean.Ez(), 0.); else cov = covariances; SetCovariances(cov); } CovarianceMatrix::CovarianceMatrix(double emittance_t, double beta_t, double alpha_t, double Ltwiddle_t, double emittance_l, double beta_l, double alpha_l, PhaseSpaceVector mean, double weight) : _covNorm(HepSymMatrix(6,0)), _mean(mean), _weight(weight) { SetCovariances(emittance_t, beta_t, alpha_t, Ltwiddle_t, emittance_l, beta_l, alpha_l); } CovarianceMatrix::CovarianceMatrix(double emittance_x, double beta_x, double alpha_x, double emittance_y, double beta_y, double alpha_y, double emittance_l, double beta_l, double alpha_l, PhaseSpaceVector mean, double weight) : _covNorm(HepSymMatrix(6,0)), _mean(mean), _weight(weight) { SetCovariances(emittance_x, beta_x, alpha_x, emittance_y, beta_y, alpha_y, emittance_l, beta_l, alpha_l); } CovarianceMatrix::CovarianceMatrix(const MiceModule* mod) : _covNorm(HepSymMatrix(6,0)), _norm(1), _mean(PhaseSpaceVector()), _weight(1) { MCHit hit = ModuleConverter::ModuleToHit(mod); CLHEP::HepSymMatrix mat = ModuleConverter::ModuleToBeamEllipse(mod, hit); SetMean(PhaseSpaceVector(&hit)); SetCovariances(mat); } HepSymMatrix CovarianceMatrix::GetCanonicalCovariances() const { double b = _mean.Bz(); double e = _mean.Ez(); return _norm*TransformToCanonical(_covNorm, b, e, 0.); } HepSymMatrix CovarianceMatrix::GetRawNormCanCovariances(PhaseSpaceVector reference) const { HepSymMatrix out = GetNormCanCovariances(); HepVector centre = _mean.getCanonicalSixVector() - reference.getCanonicalSixVector(); //Loop over upper diagonal for(int i=0; i<6; i++) for(int j=i; j<6; j++) out[i][j] += centre[i]*centre[j]/_norm; return out; } HepSymMatrix CovarianceMatrix::GetNormCanCovariances() const { double b = _mean.Bz(); double e = _mean.Ez(); return TransformToCanonical(_covNorm, b, e, 0.); } //use units where the covariances are ~1 to avoid double point precision errors double CovarianceMatrix::GetSixDEmit() const { return pow(GetKineticCovariances().determinant()*c_light, 1./2.) / _mean.m()/ _mean.m()/ _mean.m(); } double CovarianceMatrix::GetTwoDEmit(int axis) const { double determinant = GetNormKinCovariances().sub(axis*2+1,axis*2+2).determinant(); double emittance = _norm*sqrt(determinant)/_mean.m(); return emittance; } double CovarianceMatrix::GetTwoDBeta(int axis) const { double p = _mean.P(); double m = _mean.m(); double em = GetTwoDEmit(axis); if(em<=0) return -1; return _norm*_covNorm[axis*2][axis*2]*p/(m*em); } double CovarianceMatrix::GetTwoDAlpha(int axis) const { double m = _mean.m(); double em = GetTwoDEmit(axis); if(em<=0) return -1; return -_norm*_covNorm[axis*2][axis*2+1] / (m*em); } double CovarianceMatrix::GetTwoDGamma(int axis) const { double p = _mean.P(); double m = _mean.m(); double em = GetTwoDEmit(axis); if(em<=0) return -1; return _norm*_covNorm[axis*2+1][axis*2+1] / (m*p*em); } double CovarianceMatrix::GetBetaTrans() const { double em = GetEmitTrans(); double p = _mean.P(); double m = _mean.m(); if(em<=0) return -1; return _norm*(_covNorm(3,3)+_covNorm(5,5))*p/(2*m*em); } double CovarianceMatrix::GetAlphaTrans() const { double em = GetEmitTrans(); double m = _mean.m(); if(em<=0) return -1; return -_norm*(_covNorm(3,4)+_covNorm(5,6))/(2*m*em); } double CovarianceMatrix::GetGammaTrans() const { double em = GetEmitTrans(); double p = _mean.P(); double m = _mean.m(); return _norm*(_covNorm(3,3)+_covNorm(5,5))/(2*m*p*em); } double CovarianceMatrix::GetEmitTrans() const { HepSymMatrix localCov = GetNormCanCovariances().sub(3,6); double determinant = localCov.determinant(); if(!(determinant>0)) return -1; double em = sqrt(sqrt(determinant))*_norm/_mean.m(); return em; } double CovarianceMatrix::GetLKin() const { return _norm*(_covNorm(3,6) - _covNorm(4,5)); } double CovarianceMatrix::GetLCan() const { /* double m = _mean.m(); double p = _mean.P(); double em = GetEmitTrans(); double b = GetBetaTrans(); double bz = _mean.Bz(); double k = GetKappa(bz,p); */ return -_norm*( (_covNorm[4][3]-_covNorm[4][4]*_mean.Bz()*_mean.q()*c_light/2.) -(_covNorm[2][5]+_covNorm[2][2]*_mean.Bz()*_mean.q()*c_light/2.) ); } double CovarianceMatrix::GetLTwiddle() const { double em = GetEmitTrans(); double m = _mean.m(); return GetLCan()/(m*em); } void CovarianceMatrix::SetCovariances(HepSymMatrix covariances, double determinant) { if(determinant < 0) { _norm = pow(covariances.determinant(),1./6.); if(_norm>1e-9) _covNorm = covariances/_norm; else {_covNorm = HepSymMatrix(6,0); _norm = 1;} } else { _norm = determinant; _covNorm = covariances; } } void CovarianceMatrix::SetCovariances(double emittance_t, double beta_t, double alpha_t, double Ltwiddle_t, double emittance_l, double beta_l, double alpha_l) { double m = _mean.m(); double p = _mean.P(); double k = GetKappa(_mean.Bz(), p); double gamma_t = (1+alpha_t*alpha_t+(beta_t*k - Ltwiddle_t)*(beta_t*k-Ltwiddle_t))/beta_t; double gamma_l = (1+alpha_l*alpha_l)/beta_l; double sigmaxx = emittance_t*m*beta_t/p; double sigmaxpx = -emittance_t*m*alpha_t; double sigmapxpx = emittance_t*m*p*gamma_t; double sigmaxpy = -emittance_t*m*(beta_t*k-Ltwiddle_t)*_mean.q(); _covNorm[0][0] = emittance_l*m*beta_l/p; _covNorm[1][1] = emittance_l*m*gamma_l*p; _covNorm[0][1] = -emittance_l*m*alpha_l; _covNorm[2][2] = _covNorm[4][4] = sigmaxx; _covNorm[3][3] = _covNorm[5][5] = sigmapxpx; _covNorm[2][3] = _covNorm[4][5] = sigmaxpx; _covNorm[3][4] = -sigmaxpy; _covNorm[2][5] = sigmaxpy; _norm = pow(_covNorm.determinant(), 1./6.); _covNorm /= _norm; } void CovarianceMatrix::SetCovariances(double emittance_x, double beta_x, double alpha_x, double emittance_y, double beta_y, double alpha_y, double emittance_l, double beta_l, double alpha_l) { double m = _mean.m(); double p = _mean.P(); double gamma_x = (1+alpha_x*alpha_x)/beta_x; double gamma_y = (1+alpha_y*alpha_y)/beta_y; double gamma_l = (1+alpha_l*alpha_l)/beta_l; _covNorm[0][0] = emittance_l*m*beta_l/p; _covNorm[1][1] = emittance_l*m*gamma_l*p; _covNorm[0][1] = -emittance_l*m*alpha_l; _covNorm[2][2] = emittance_x*m*beta_x/p; _covNorm[3][3] = emittance_x*m*p*gamma_x; _covNorm[2][3] = -emittance_x*m*alpha_x; _covNorm[4][4] = emittance_y*m*beta_y/p; _covNorm[5][5] = emittance_y*m*p*gamma_y; _covNorm[4][5] = -emittance_y*m*alpha_y; _norm = pow(_covNorm.determinant(), 1./6.); _covNorm /= _norm; } void CovarianceMatrix::SetDispersions(double dispersion_x, double dispersion_y) { _covNorm[1][2] = dispersion_x*_covNorm[1][1]/_mean.E(); _covNorm[1][4] = dispersion_y*_covNorm[1][1]/_mean.E(); } void CovarianceMatrix::SetDispersionsPrime(double disp_prime_x, double disp_prime_y) { _covNorm[1][3] = disp_prime_x*_covNorm[1][1]/_mean.E(); _covNorm[1][5] = disp_prime_y*_covNorm[1][1]/_mean.E(); } void CovarianceMatrix::SetRawNormCanCovariances(HepSymMatrix rawCov, double norm, PhaseSpaceVector reference) { HepVector centre = _mean.getCanonicalSixVector() - reference.getCanonicalSixVector(); HepSymMatrix out = rawCov; //Loop over upper diagonal for(int i=0; i<6; i++) for(int j=i; j<6; j++) out[i][j] -= centre[i]*centre[j]/norm; _covNorm = TransformToKinetic(out, reference.Bz(), reference.Ez(),0); //BUG what about quads? _norm = norm; } HepSymMatrix CovarianceMatrix::TransformToCanonical(HepSymMatrix kin, double Bz, double E, double dBdx) const { HepSymMatrix can = kin; double b = 2*GetB0(Bz); can[3][2] = kin[3][2]-kin[4][2]*b/2; can[3][3] = kin[3][3]+kin[4][4]*b*b/4-kin[4][3]*b; can[4][3] = kin[4][3]-kin[4][4]*b/2; can[5][2] = kin[5][2]+kin[2][2]*b/2; can[5][3] = kin[5][3]-kin[4][2]*b*b/4+kin[3][2]*b/2-kin[5][4]*b/2; can[5][4] = kin[5][4]+kin[4][2]*b/2; can[5][5] = kin[5][5]+kin[2][2]*b*b/4+kin[5][2]*b; return can; } HepSymMatrix CovarianceMatrix::TransformToKinetic(HepSymMatrix can, double Bz, double E, double dBdx) const { HepSymMatrix kin = can; double b = 2*GetB0(Bz); kin[3][2] = can[3][2]+can[4][2]*b/2; kin[3][3] = can[3][3]+can[4][4]*b*b/4+can[4][3]*b; kin[4][3] = can[4][3]+can[4][4]*b/2; kin[5][2] = can[5][2]-can[2][2]*b/2; kin[5][3] = can[5][3]-can[4][2]*b*b/4+can[5][4]*b/2-can[3][2]*b/2; kin[5][4] = can[5][4]-can[4][2]*b/2; kin[5][5] = can[5][5]+can[2][2]*b*b/4-can[5][2]*b; return kin; } AnalysisPlaneBank CovarianceMatrix::GetAnalysisPlaneBank() const { AnalysisPlaneBank out; out.CovarianceMatrix = GetKineticCovariances(); out.planeNumber = 0; out.planeType = 7; out.weight = _weight; out.z = _mean.z(); out.t = _mean.t(); out.pz = _mean.Pz(); out.E = _mean.E(); out.beta_p = GetBetaTrans(); out.l_can = GetLCan(); out.em4dXY = GetEmitTrans(); out.em6dTXY = GetSixDEmit(); for(int i=0; i<3; i++) out.beta[i] = GetTwoDBeta(i); for(int i=0; i<3; i++) out.em2d[i] = GetTwoDEmit(i); for(int i=0; i<6; i++) out.sums[i] = _mean.getSixVector()[i]; out.amplitudePzCovariance = 0; return out; } std::ostream& operator<<(std::ostream& out, CovarianceMatrix cov) { cov.Print(out); return out; } double GetTwoDAmp(int axis, PhaseSpaceVector event, CovarianceMatrix Covariance) { int ierr=0; CLHEP::HepSymMatrix matrix = Covariance.GetKineticCovariances().sub(axis+1, axis+2).inverse(ierr); CLHEP::HepVector mean = Covariance.GetMean().getSixVector(); CLHEP::HepVector vector = (event.getSixVector() - mean).sub(axis+1, axis+2); double em2D = Covariance.GetTwoDEmit(axis); return em2D*(vector.T() * matrix * vector)(1,1); } double GetAmpTrans(PhaseSpaceVector event, CovarianceMatrix Covariance) { int ierr=0; CLHEP::HepSymMatrix matrix = Covariance.GetKineticCovariances().sub(3, 6).inverse(ierr); CLHEP::HepVector vector = (event.getSixVector()-Covariance.GetMean().getSixVector()).sub(3,6); double em4D = Covariance.GetEmitTrans(); return em4D*(vector.T()*matrix*vector)(1,1); } double GetSixDAmp(PhaseSpaceVector event, CovarianceMatrix Covariance) { int ierr=0; CLHEP::HepSymMatrix matrix = Covariance.GetKineticCovariances().inverse(ierr); CLHEP::HepVector vector = event.getSixVector()-Covariance.GetMean().getSixVector(); double em6D = Covariance.GetSixDEmit(); return em6D*(vector.T()*matrix*vector)(1,1); } double GetTwoDAmp(int axis, PhaseSpaceVector event, PhaseSpaceVector mean, HepSymMatrix inverseCovariance, double emittance) { CLHEP::HepVector vector = (event.getSixVector()-mean.getSixVector()).sub(axis+1, axis+2); return emittance*(vector.T()*inverseCovariance*vector)(1,1); } double GetAmpTrans(PhaseSpaceVector event, PhaseSpaceVector mean, HepSymMatrix inverseCovariance, double emittance) { CLHEP::HepVector vector = (event.getSixVector()-mean.getSixVector()).sub(3, 6); return emittance*(vector.T()*inverseCovariance*vector)(1,1); } double GetSixDAmp(PhaseSpaceVector event, PhaseSpaceVector mean, HepSymMatrix inverseCovariance, double emittance) { CLHEP::HepVector vector = event.getSixVector()-mean.getSixVector(); return emittance*(vector.T()*inverseCovariance*vector)(1,1); } CovarianceMatrix CovarianceMatrix::Interpolate(std::vector cov, std::string variableName, double variable) { if(cov.size() < 1) throw(MAUS::Exception(MAUS::Exception::recoverable, "Interpolating CovarianceMatrix array with length 0", "CovarianceMatrix::interpolate")); int point = -1; int i = 0; double delta = 0; std::vector mean; for(unsigned int j=0; j0) delta = ( variable - mean[i-1](variableName) )/(mean[i](variableName) - mean[i-1](variableName)); i = mean.size(); //break } else i++; } if(point == -1) return cov.back(); //variable > all of psv if(point == 0) return cov[0]; //variable < all of psv HepSymMatrix covMatrix = (delta*cov[point].GetKineticCovariances() + (1-delta)*cov[point-1].GetKineticCovariances()); HepVector sixVector = delta*(mean[point].getSixVector() - mean[point-1].getSixVector())+mean[point-1].getSixVector(); return CovarianceMatrix(covMatrix, PhaseSpaceVector(sixVector, mean[0].m())); } bool CovarianceMatrix::IsPositiveDefinite(HepSymMatrix mat) { bool posDef = true; for(int i=0; i0 && posDef); //sylvester criterion return posDef; } HepMatrix CovarianceMatrix::Rotation(double angle) { HepMatrix rotation(6,6,1); double fcos = cos(angle); double fsin = sin(angle); rotation *= fcos; rotation[0][0] = 1.; rotation[1][1] = 1.; rotation[4][2] = -fsin; rotation[5][3] = -fsin; rotation[2][4] = fsin; rotation[3][5] = fsin; return rotation; } CovarianceMatrix CovarianceMatrix::Rotate(double angle) const { HepMatrix rotation = Rotation(angle); PhaseSpaceVector rotatedMean = GetMean().Rotate(angle); HepSymMatrix rotatedCovs = GetKineticCovariances().similarity(rotation); return CovarianceMatrix(rotatedCovs, rotatedMean); } double CovarianceMatrix::SingleParticleVariable(PhaseSpaceVector psv, std::string variable) { std::vector list = psvVariables(); int covStart = PhaseSpaceVector::listOfVariables().size(); int var = -1; for(unsigned int i=0; i list = bunchVariables(); int var = -1; for(unsigned int i=0; i list = variableTypes(); std::vector psvList = listOfMyPhaseSpaceVariables(); variable = LowerCase(variable); for(unsigned int i=0; i> variableType >> aux1 >> aux2; for(unsigned int i=0; i CovarianceMatrix::psvVariables() { std::vector bunchList(_psvVars, _psvVars+5); std::vector psvList = PhaseSpaceVector::listOfVariables(); bunchList.insert(bunchList.begin(), psvList.begin(), psvList.end()); return bunchList; } double CovarianceMatrix::FullVariable(std::string variable) const { std::vector list = variableTypes(); std::vector psvList = listOfMyPhaseSpaceVariables(); variable = LowerCase(variable); for(unsigned int i=0; i> variableType >> aux1 >> aux2; for(unsigned int i=0; i CovarianceMatrix::listOfAuxiliaryVariables1(std::string variable) { std::vector list = variableTypes(); for(unsigned int i=0; i CovarianceMatrix::listOfAuxiliaryVariables2(std::string variable) { std::vector list = variableTypes(); for(unsigned int i=0; i(); throw(MAUS::Exception(MAUS::Exception::recoverable, "Unrecognised covariance variable type "+variable, "CovarianceMatrix::listOfAuxiliaryVariables2(std::string)")); } ////////////// MomentHeap ///////////// MomentHeap::MomentHeap(int maxOrder, HepVector mean, double mass) : m_mass(mass), m_mean(mean), m_vars(6,0) { if(maxOrder>2) m_higherMoments = std::vector(maxOrder-2); if(m_higherMoments.size()>0) m_higherMoments[0] = new Tensor3(6,6,6, 0.); for(unsigned int i=1; i higherMoments) : m_mass(covMatrix.GetMean().m()), m_mean(covMatrix.GetMean().getSixVector()), m_vars(covMatrix.GetKineticCovariances()), m_higherMoments(higherMoments) {} MomentHeap::~MomentHeap() { // std::cout << m_higherMoments.size() << " " << << std::endl; // for(unsigned int i=0; iint(m_higherMoments.size()) ) throw(MAUS::Exception(MAUS::Exception::recoverable, "Could not find moment", "MomentHeap::GetTensor")); return m_higherMoments[order-3]; } void MomentHeap::Add(double value, std::vector place) { if(place.size() == 2) m_vars[place[0]][place[1]] += value; else if(int(place.size()) <= MaxOrder()) m_higherMoments[place.size()-3]->Add(place, value); else throw(MAUS::Exception(MAUS::Exception::recoverable, "Add rank > largest rank on heap or <= 1", "MomentHeap::Add")); } double MomentHeap::GetMoment(std::vector position) const { if(position.size()>2 && int(position.size())<=MaxOrder()) { sort(position.begin(), position.end()); //better to design proper symmetric tensor class return GetTensor(position.size())->Get(position); } else if(position.size() == 2) return m_vars[position[0]][position[1]]; else if(position.size() == 1) return m_mean[position[0]]; throw(MAUS::Exception(MAUS::Exception::recoverable, "Index out of range", "MomentHeap::GetMoment")); } std::ostream& MomentHeap::Print(std::ostream& out) const { out << std::scientific << std::setprecision(5) << "MomentHeap order " << MaxOrder() << std::endl; /* out << transpose(m_mean) << "\n ************** " << std::endl; out << m_vars << "\n ************* " << std::endl; for(unsigned int i=0; i kvec = MAUS::PolynomialMap::IndexByVector(j, 6); if(kvec.front() != kvec_front) {std::cout << "\n"; kvec_front = kvec.front();} for(unsigned int k=0; k=0 ) std::cout << " "; std::cout << mom << " "; } std::cout << std::endl; } return out; } std::ostream& operator<<(std::ostream& out, const MomentHeap& heap) { return heap.Print(out); } MAUS::PolynomialMap MomentHeap::Weighting(MomentHeap in, MomentHeap target, int order) { size_t dimension = 6; size_t size = MAUS::PolynomialMap::NumberOfPolynomialCoefficients( dimension, order); MAUS::Vector u(size-1); MAUS::Matrix M(size-1, size-1); for(size_t i=1; i index1 = MAUS::PolynomialMap::IndexByVector(i, dimension); u(i) = target.GetMoment(index1) - in.GetMoment(index1); for(size_t j=1; j index2 = MAUS::PolynomialMap::IndexByVector(j, dimension); std::vector index3 = index2; index3.insert(index3.begin(), index1.begin(), index1.end()); M(j,i) = in.GetMoment(index3) - in.GetMoment(index1)*target.GetMoment(index2); } } MAUS::Vector a = inverse(M) * u; MAUS::Vector a2 = MAUS::Vector(a.size()+1, 1.); for(size_t i=0; i