CppEllipse CppEllipse::fromMatrix(const tmv::Matrix<double>& m, Angle& rotation, bool& parityFlip) { dbg<<"ellipse from matrix "<<m<<'\n'; assert(m.nrows()==2 && m.ncols()==2); double det = m(0,0)*m(1,1) - m(0,1)*m(1,0); parityFlip = false; double scale; if (det < 0) { parityFlip = true; scale = -det; } else if (det==0.) { // Degenerate transformation. Return some junk return CppEllipse(CppShear(0.0, 0.0), -std::numeric_limits<double>::max()); } else { scale = det; } // Determine and remove the dilation double mu = 0.5*std::log(scale); // Now make m m^T matrix, which is symmetric // a & b are diagonal elements here double a = m(0,1)*m(0,1) + m(0,0)*m(0,0); double b = m(1,1)*m(1,1) + m(1,0)*m(1,0); double c = m(1,1)*m(0,1) + m(1,0)*m(0,0); double eta = acosh(std::max(1.,0.5*(a+b)/scale)); Angle beta = 0.5*std::atan2(2.*c, a-b) * radians; CppShear s; s.setEtaBeta(eta,beta); s.getMatrix(a,b,c); // Now look for the rotation rotation = std::atan2(-c*m(0,0)+a*m(1,0), b*m(0,0)-c*m(1,0)) * radians; return CppEllipse(s,mu, Position<double>(0.,0.)); }
static void wrap() { static char const * doc = "SBTransform is an affine transformation of another SBProfile.\n" "Origin of original shape will now appear at x0.\n" "Flux is NOT conserved in transformation - SB is preserved." ; bp::class_< SBTransform, bp::bases<SBProfile> >("SBTransform", doc, bp::no_init) .def(bp::init<const SBProfile &, double, double, double, double, Position<double>, double >( (bp::args("sbin", "mA", "mB", "mC", "mD"), bp::arg("x0")=Position<double>(0.,0.), bp::arg("fluxScaling")=1.) )) .def(bp::init<const SBProfile &, const CppEllipse &, double>( (bp::arg("sbin"), bp::arg("e")=CppEllipse(), bp::arg("fluxScaling")=1.) )) .def(bp::init<const SBTransform &>()) ; }
// CppEllipses share the ordering conventions: e1 + e2 is transform // e1 followed by transform e2. Transform objects, not coords. CppEllipse CppEllipse::operator-() const { Position<double> x3(-x0); x3 /= expmu; return CppEllipse(-s, -mu, s.inv(x3)); }