Пример #1
0
	static void create_bone_model_(float radius, float ratio, float length, vtx::fvtxs& vs, vtx::fvtxs& ns)
	{
		static vtx::fvtx rig[4];
		float r = radius * 0.707f;
		float w = length * ratio;
		rig[0].set( r,  r,  w);
		rig[1].set( r, -r,  w);
		rig[2].set(-r, -r,  w);
		rig[3].set(-r,  r,  w);
		vtx::fvtx end(0.0f, 0.0f, length);
		for(int i = 0; i < 4; ++i) {
			vs.push_back(vtx::fvtx(0.0f));
			vs.push_back(rig[i]);
			vs.push_back(rig[(i + 1) & 3]);
			{
				vtx::fvtx n;
				outer_product(rig[i], rig[(i + 1) & 3], n);
				ns.push_back(n);
				ns.push_back(n);
				ns.push_back(n);
			}
			vs.push_back(rig[(i + 1) & 3]);
			vs.push_back(rig[i]);
			vs.push_back(end);
			{
				vtx::fvtx n;
				outer_product(rig[i + 1] - end, rig[i] - end, n);
				ns.push_back(n);
				ns.push_back(n);
				ns.push_back(n);
			}
		}
	}
Пример #2
0
void Puckering::CalculateGradZ(const vector<double> &X)
{
    /* Calculate puckering variable z_j */
    this->CalculateZ(X);

    int iN, jN, iD;

    fill(_dR1.begin(), _dR1.end(), 0.0);
    fill(_dR2.begin(), _dR2.end(), 0.0);

    /* Calculate derivatives of R' and R'' */
    for ( iN = 0; iN < _nAtoms; ++iN )
        for ( jN = 0; jN < _nAtoms; ++jN )
        {
            _dR1.at(iN) += _Delta.at(iN*_nAtoms+jN)*_sinx.at(jN);
            _dR2.at(iN) += _Delta.at(iN*_nAtoms+jN)*_cosx.at(jN);
        }

    /* Calculate some dot products */
    _R1R1 = inner_product(_R1.begin(), _R1.end(), _R1.begin(), 0.0);
    _R2R2 = inner_product(_R2.begin(), _R2.end(), _R2.begin(), 0.0);
    _R1R2 = inner_product(_R1.begin(), _R1.end(), _R2.begin(), 0.0);

    /* Calculate some cross products */
    _R1R1 = inner_product(_R1.begin(), _R1.end(), _R1.begin(), 0.0);
    int jj = 0;
    for ( jN = 0; jN < _nAtoms; ++jN )
    {
        jj = jN*_sdim;
        outer_product(_R2.begin()   , _R .begin()+jj, _R2xRj.begin()+jj);
        outer_product(_R .begin()+jj, _R1.begin()   , _RjxR1.begin()+jj);
    }

    /* Calculate derivativs of z_j */
    double norm2Inv = 0.5/(_norm*_norm);
    double normInv  = 1.0/_norm;
    for ( iD = 0; iD < _sdim; ++iD )
        for ( iN = 0; iN < _nAtoms; ++iN )
        {
            _temp1 = 2.0 * (  _dR1.at(iN)*( _R1.at(iD)*_R2R2 - _R2.at(iD)*_R1R2 )
                                     +_dR2.at(iN)*( _R2.at(iD)*_R1R1 - _R1.at(iD)*_R1R2 ) );

            for ( jN = 0; jN < _nAtoms; ++jN )
            {
                _temp2 = _Delta.at(iN*_nAtoms+jN) *_R1xR2.at(iD)
                        + _dR1.at(iN)*_R2xRj.at(jN*_sdim+iD)
                        + _dR2.at(iN)*_RjxR1.at(jN*_sdim+iD);
                // effective computation of grad_i z_j
                _dz.at(iN*_hdim+jN*_sdim+iD) = _temp2*normInv -_z.at(jN)*_temp1*norm2Inv ;
            }
        }
}
Пример #3
0
// sample user nodes hyperprior
// according to equation A.4 in Xiong paper
void sample_V(){

  vec Vmean = zeros(D);
  mat VVT = calc_MMT(M, M+N, Vmean);   

  double beta0_ = beta0[0] + N;
  vec mu0_ = (N*Vmean)/beta0_;
  double nu0_ = nu0 +N;
  vec dMu = - Vmean;
  if (debug)
    std::cout<<"dMu:"<<dMu<<"beta0: "<<beta0[0]<<" beta0_ "<<beta0_<<" nu0_ " <<nu0_<<endl;
  mat VmeanT = N*outer_product(Vmean, Vmean); 
  assert(VmeanT.rows() == D && VmeanT.cols() == D);
  mat dMuT =  (beta0[0]/beta0_)*VmeanT;
  mat iW0_ = iW0 + VVT - VmeanT + dMuT;
  mat W0_;
  bool ret = inv(iW0_, W0_);
  assert(ret);
  mat tmp = (W0_+transpose(W0_))*0.5;
  if (debug)
    std::cout<<"iW0: "<<iW0<<" VVT: "<<VVT<<" VmeanT: "<<VmeanT<<" dMuT: " <<dMuT<<"W0_"<< W0_<<" tmp: " << tmp<<" nu0_: "<<nu0_<<endl;
  A_V = wishrnd(tmp, nu0_);
  mat tmp2; 
  ret = inv(beta0_*A_V, tmp2);
  assert(ret);
  mu_V = mvnrndex(mu0_, tmp2, D, 0);
  if (debug)
    std::cout<<"Sampling from V: A_V" <<A_V<<" mu_V: "<<mu_V<<" Vmean: "<<Vmean<<" W0_: "<<W0_<<" tmp: "<<tmp<<endl;
}
Пример #4
0
// sample movie nodes hyperprior
// according to equation A.3 in Xiong paper.
void sample_U(){

  vec Umean = zeros(D);
  mat UUT = calc_MMT(0,M,Umean);
  
  double beta0_ = beta0[0] + M;
  vec mu0_ = (M*Umean)/beta0_;
  double nu0_ = nu0 +M;
  vec dMu = - Umean;
  if (debug)
    std::cout<<"dMu:"<<dMu<<"beta0: "<<beta0[0]<<" beta0_ "<<beta0_<<" nu0_ " <<nu0_<<" mu0_ " << mu0_<<endl;

  mat UmeanT = M*outer_product(Umean, Umean); 
  assert(UmeanT.rows() == D && UmeanT.cols() == D);
  mat dMuT = (beta0[0]/beta0_)*UmeanT;
  mat iW0_ = iW0 + UUT - UmeanT + dMuT;
  mat W0_; 
  bool ret =inv(iW0_, W0_);
  assert(ret);
  mat tmp = (W0_+transpose(W0_))*0.5;
  if (debug)
    std::cout<<iW0<<UUT<<UmeanT<<dMuT<<W0_<<tmp<<nu0_<<endl;
  A_U = wishrnd(tmp, nu0_);
  mat tmp2;  
  ret =  inv(beta0_ * A_U, tmp2);
  assert(ret);
  mu_U = mvnrndex(mu0_, tmp2, D, 0);
  if (debug)
    std::cout<<"Sampling from U" <<A_U<<" "<<mu_U<<" "<<Umean<<" "<<W0_<<tmp<<endl;
}
Пример #5
0
void Puckering::CalculateZ(const vector<double> &X)
{
    int jN, iN, iD;
    /* Coordinates of ring elements with respect to the geometrical center */
    fill(_R.begin(), _R.end(), 0.0);
    for ( jN = 0; jN < _nAtoms; ++jN)
        for (iD = 0; iD < _sdim; ++iD)
            for ( iN = 0; iN < _nAtoms; ++iN)
                _R.at(jN*_sdim+iD) += X.at(iN*_sdim+iD)*_Delta.at(iN*_nAtoms+jN);


    fill(_R1.begin(), _R1.end(), 0.0);
    fill(_R2.begin(), _R2.end(), 0.0);

    /* R1 = sinx*R  and  R2 = sinx*R */
    for (iD = 0; iD < _sdim; ++iD)
        for ( jN = 0; jN < _nAtoms; ++jN)
        {
            _R1.at(iD) += _sinx.at(jN)*_R.at(jN*_sdim+iD);
            _R2.at(iD) += _cosx.at(jN)*_R.at(jN*_sdim+iD);
        }

    /* R1xR2 : Cross product of R1 and R2  */
    outer_product(_R1.begin(), _R2.begin(), _R1xR2.begin());

    /* |R1xR2| : L2 norm of cross product of R1 and R2  */
    _norm = sqrt( _R1xR2.at(0)*_R1xR2.at(0) + _R1xR2.at(1)*_R1xR2.at(1) + _R1xR2.at(2)*_R1xR2.at(2));

    /* Normal vector to the mean plane is n = R1xR2/|R1xR2|,
     * so z = R.n */
    for ( jN = 0; jN < _nAtoms; ++jN)
        _z.at(jN) = inner_product( _R1xR2.begin(), _R1xR2.end(), _R.begin()+jN*_sdim, 0.0) / _norm;
}
Пример #6
0
template<class TV> static Matrix<T,TV::m+1> affine_register_helper(RawArray<const TV> X0, RawArray<const TV> X1, RawArray<const T> mass) {
  typedef typename TV::Scalar T;
  static const int d = TV::m;
  const int n = X0.size();
  GEODE_ASSERT(n==X1.size() && (mass.size()==0 || mass.size()==n));
  const bool weighted = mass.size() == n;
  const T total = weighted ? mass.sum() : n;
  if (!total)
    return Matrix<T,d+1>::identity_matrix();

  // Compute centers of mass
  TV c0, c1;
  if (weighted) {
    for (int i=0;i<n;i++) {
      c0 += mass[i]*X0[i];
      c1 += mass[i]*X1[i];
    }
  } else {
    c0 = X0.sum();
    c1 = X1.sum();
  }
  c0 /= total;
  c1 /= total;

  // Compute covariances
  SymmetricMatrix<T,d> cov00 = scaled_outer_product(-total,c0);
  Matrix<T,d> cov01 = outer_product(-total*c1,c0);
  if (weighted)
    for(int i=0;i<n;i++) {
      cov00 += scaled_outer_product(mass[i],X0[i]);
      cov01 += outer_product(mass[i]*X1[i],X0[i]);
    }
  else
    for (int i=0;i<n;i++) {
      cov00 += outer_product(X0[i]);
      cov01 += outer_product(X1[i],X0[i]);
    }

  // Compute transform
  const Matrix<T,d> A = cov01*cov00.inverse();
  const TV t = c1-A*c0;
  auto tA = Matrix<T,d+1>::from_linear(A);
  tA.set_translation(t);
  return tA;
}
void UnconstrainedLocalSearch::update_B_SR1(Matrix& Bk, const Vector& sk, const Vector& gk, const Vector& gk1) {
	Vector r = gk1-gk-Bk*sk;
	double tmp = r*sk;
	// if tmp=0 => sk =0 and gk=gk1. That means that we have converge
	// but due to rounding error in the computation of the stopping criteria,
	// we cannot detect it.
	// If the norm of the correction is too large we skip the correction
	//  cout << " [update_B_SR1] r*r/r*sk = "<< (r*r)/tmp<<endl;
	if ((tmp!=0)&&( fabs((r*r)/tmp)<=1.e8)) Bk += (1/tmp)*outer_product(r,r);
}
Пример #8
0
void hyperbolic_reflection(r3vector a, r3transform *out) {
  matrix_el_t denom = minkowski_self_inner_product(a);

  matrix_el_t s = 2.0 / denom;

  r3vector swapped = {a[0]*s, a[1]*s, a[2]*-1*s};

  outer_product(a, swapped, out);

  *out *= -1;
  *out += identity_transform;
}
Пример #9
0
void 
rich_cell::
update_eccentricity_and_radius()
{
  //Step1: project the points to the x-y plane
  std::vector<vnl_vector_fixed<double, 2> > points_2d;
  std::vector<bool> checked(all_points_.size(), false);
  
  for (unsigned int i = 0; i<all_points_.size(); i++) {
    if (!checked[i]) {
      //record the x-y position
      vnl_vector_fixed<double, 2> pt(all_points_[i][0],all_points_[i][1]);
      points_2d.push_back( pt );
      checked[i] = true;

      //scan through the list to see if other points in the remaining
      //list contains the same x-y position
      for (unsigned int j = i+1; j<all_points_.size(); j++) {
        if (all_points_[j][0] == all_points_[i][0] 
            && all_points_[j][1] == all_points_[i][1]) 
          checked[j] = true;
      }
    }
  }
  
  //Step2: compute the scatter matrix
  //
  // compute the center
  vnl_vector_fixed<double, 2> center(0.0,0.0);
  for (unsigned int i = 0; i<points_2d.size(); i++) {
    center += points_2d[i];
  }
  center /= (double)points_2d.size();

  vnl_matrix<double> cov_matrix(2,2,0.0);
  std::cout<<"points_2d.size = "<<points_2d.size()<<std::endl;
  for (unsigned int i = 0; i<points_2d.size(); i++) {
    cov_matrix += outer_product(points_2d[i]-center, points_2d[i]-center);
  }
  cov_matrix /= (double)points_2d.size();

  //perform eigen-value decomposition to get the semi-major (a) and minor (b) 
  vnl_svd<double> svd_from( cov_matrix );
  
  //eccentricity=sqrt( 1-(b^2/a^2) ). If the shape is close to
  //circular, the value is 0. 
  //eccentricity_ =vcl_sqrt( 1- (svd_from.W(1)*svd_from.W(1))/(svd_from.W(0)*svd_from.W(0)) );
  eccentricity_ =vcl_sqrt( 1- vnl_math_abs(svd_from.W(1)/svd_from.W(0)) );
  float long_axis_mag = vcl_sqrt(vnl_math_abs(svd_from.W(0)));
  float short_axis_mag = vcl_sqrt(vnl_math_abs(svd_from.W(1)));
  average_radius_ = 0.5*(long_axis_mag + short_axis_mag);
}
Пример #10
0
template<class TV> static Frame<TV> rigid_register_helper(RawArray<const TV> X0, RawArray<const TV> X1, RawArray<const T> mass) {
  typedef typename TV::Scalar T;
  static const int d = TV::m;
  const int n = X0.size();
  GEODE_ASSERT(n==X1.size() && (mass.size()==0 || mass.size()==n));
  const bool weighted = mass.size() == n;
  const T total = weighted ? mass.sum() : n;
  if (!total)
    return Frame<TV>();

  // Compute centers of mass
  TV c0, c1;
  if (weighted) {
    for (int i=0;i<n;i++) {
      c0 += mass[i]*X0[i];
      c1 += mass[i]*X1[i];
    }
  } else {
    c0 = X0.sum();
    c1 = X1.sum();
  }
  c0 /= total;
  c1 /= total;

  // Compute covariance
  Matrix<T,d> cov = outer_product(-total*c1,c0);
  if (weighted)
    for(int i=0;i<n;i++)
      cov += outer_product(mass[i]*X1[i],X0[i]);
  else
    for (int i=0;i<n;i++)
      cov += outer_product(X1[i],X0[i]);

  // Compute frame from covariance
  Matrix<T,d> U,V;DiagonalMatrix<T,d> D;
  cov.fast_singular_value_decomposition(U,D,V);
  Rotation<TV> q(U.times_transpose(V));
  return Frame<TV>(c1-q*c0,q);
}
Пример #11
0
vnlMatrixType calcCov(const vnlMatrixType& X,
                                const vnlMatrixType& Y,
                                const vnlVectorType& mu_x,
                                const vnlVectorType& mu_y)
{

    vnlMatrixType Sigma_xy(X.rows(), X.rows(), 0.0);
    for (unsigned j = 0; j < X.cols(); j++) {
        Sigma_xy += outer_product(Y.get_column(j) - mu_y, X.get_column(j) - mu_x);
    }
    Sigma_xy /= X.cols();
    return Sigma_xy;
}
Пример #12
0
const Matrix rotation( const Vector& axis, const double angle )
{
   const double cosa = cos(angle);
   const double sina = sin(angle);
   Vector ax = axis / sqrt( axis*axis ); 
   Matrix op;
   outer_product( ax, ax, op );
   Matrix result = unitMatrix() * cosa 
                 + op * ( 1.0 - cosa )
                 + PauliMatrix[0]*axis[0] * sina 
                 + PauliMatrix[1]*axis[1] * sina 
                 + PauliMatrix[2]*axis[2] * sina;
   return result;
}
Пример #13
0
	int power_eigensolution(const MT& Ap, MT& Q, MT& L, int max_sol)
	{
		typedef typename MT::VectorType VT;
		MT A = Ap;
		int n = min(MT::get_v_dim(), max_sol);

		for(int i=0;i<n;++i)
			{
				// Seed the eigenvector estimate
				VT q(1);
				float l,l_old;

				// As long as we haven't reached the max iterations and the
				// eigenvalue has not converged, do
				int k=0;
				for(; k<2 || k<KMAX && (l-l_old > EV_THRESH * l) ; ++k)
					{
						// Multiply the eigenvector estimate onto A
						const VT z = A * q;

						// Check that we did not get the null vector.
						float z_len = z.length();
						if(z_len < EV_THRESH)
							return i;

						// Normalize to get the new eigenvector
						q = z/z_len;

						// Record the old eigenvalue estimate and get a new estimate.
						l_old = l;
						l = dot(q, A * q);
					}
				// If we hit the max iterations, we also don't trust the eigensolution
				if(k==KMAX)
					return i;
				
				// Update the solution by adding the eigenvector to Q and
				// the eigenvalue to the diagonal of L.
				Q[i] = q;
				L[i][i] = l;

				// Update A by subtracting the subspace represented by the 
				// eigensolution just found. This is called the method of 
				// deflation.
				MT B;
				outer_product(q,q,B);
				A = A - l * B;
			}
		return n;
	}
Пример #14
0
		int power_eigensolution(const MT& Ap, MT& Q, MT& L, unsigned int max_sol)
		{
				L = MT(0);

				typedef typename MT::VectorType VT;
				MT A = Ap;
				unsigned int n = s_min(MT::get_v_dim(), max_sol);

				for(unsigned int i=0;i<n;++i)
				{
						// Seed the eigenvector estimate
						VT q(1);
						q.normalize();
						double l=123,l_old;

						// As long as we haven't reached the max iterations and the
						// eigenvalue has not converged, do
						unsigned int k=0;
						do
						{
							const VT z = A * q;
							double z_len = length(z);
							
							if(z_len < EV_THRESH) return i;
							
							l_old = l;
							l = dot(q, z)>0 ? z_len : -z_len;
							q = z/z_len;
								
							if(++k==KMAX)
								return i;
						}
						while((fabs(l-l_old) > fabs(EV_THRESH * l)) || k<2);
				
						// Update the solution by adding the eigenvector to Q and
						// the eigenvalue to the diagonal of L.
						Q[i] = q;
						L[i][i] = l;

						// Update A by subtracting the subspace represented by the 
						// eigensolution just found. This is called the method of 
						// deflation.
						MT B;
						outer_product(q,q,B);
						A = A - l * B;
				}
				return n;
		}
Пример #15
0
SEXP invariantSimilarityHelper(
  typename itk::Image< float , ImageDimension >::Pointer image1,
  typename itk::Image< float , ImageDimension >::Pointer image2,
  SEXP r_thetas, SEXP r_lsits, SEXP r_WM, SEXP r_scale,
  SEXP r_doreflection, SEXP r_txfn  )
{
  unsigned int mibins = 20;
  unsigned int localSearchIterations =
    Rcpp::as< unsigned int >( r_lsits ) ;
  std::string whichMetric = Rcpp::as< std::string >( r_WM );
  std::string txfn = Rcpp::as< std::string >( r_txfn );
  bool useprincaxis = true;
  typedef typename itk::ImageMaskSpatialObject<ImageDimension>::ImageType
    maskimagetype;
  typename maskimagetype::Pointer mask = ITK_NULLPTR;
  Rcpp::NumericVector thetas( r_thetas );
  Rcpp::NumericVector vector_r( r_thetas ) ;
  Rcpp::IntegerVector dims( 1 );
  Rcpp::IntegerVector doReflection( r_doreflection );
  unsigned int vecsize = thetas.size();
  dims[0]=0;
  typedef float  PixelType;
  typedef double RealType;
  RealType bestscale = Rcpp::as< RealType >( r_scale ) ;
  typedef itk::Image< PixelType , ImageDimension > ImageType;
  if( image1.IsNotNull() & image2.IsNotNull() )
    {
    typedef typename itk::ImageMomentsCalculator<ImageType> ImageCalculatorType;
    typedef itk::AffineTransform<RealType, ImageDimension> AffineType0;
    typedef itk::AffineTransform<RealType, ImageDimension> AffineType;
    typedef typename ImageCalculatorType::MatrixType       MatrixType;
    typedef itk::Vector<float, ImageDimension>  VectorType;
    VectorType ccg1;
    VectorType cpm1;
    MatrixType cpa1;
    VectorType ccg2;
    VectorType cpm2;
    MatrixType cpa2;
    typename ImageCalculatorType::Pointer calculator1 =
      ImageCalculatorType::New();
    typename ImageCalculatorType::Pointer calculator2 =
      ImageCalculatorType::New();
    calculator1->SetImage(  image1 );
    calculator2->SetImage(  image2 );
    typename ImageCalculatorType::VectorType fixed_center;
    fixed_center.Fill(0);
    typename ImageCalculatorType::VectorType moving_center;
    moving_center.Fill(0);
    try
      {
      calculator1->Compute();
      fixed_center = calculator1->GetCenterOfGravity();
      ccg1 = calculator1->GetCenterOfGravity();
      cpm1 = calculator1->GetPrincipalMoments();
      cpa1 = calculator1->GetPrincipalAxes();
      try
        {
        calculator2->Compute();
        moving_center = calculator2->GetCenterOfGravity();
        ccg2 = calculator2->GetCenterOfGravity();
        cpm2 = calculator2->GetPrincipalMoments();
        cpa2 = calculator2->GetPrincipalAxes();
        }
      catch( ... )
        {
        fixed_center.Fill(0);
        }
      }
    catch( ... )
      {
      // Rcpp::Rcerr << " zero image1 error ";
      }
    if ( vnl_math_abs( bestscale - 1.0 ) < 1.e-6 )
      {
      RealType volelt1 = 1;
      RealType volelt2 = 1;
      for ( unsigned int d=0; d<ImageDimension; d++)
        {
        volelt1 *= image1->GetSpacing()[d];
        volelt2 *= image2->GetSpacing()[d];
        }
      bestscale =
        ( calculator2->GetTotalMass() * volelt2 )/
        ( calculator1->GetTotalMass() * volelt1 );
      RealType powlev = 1.0 / static_cast<RealType>(ImageDimension);
      bestscale = vcl_pow( bestscale , powlev );
    }
    unsigned int eigind1 = 1;
    unsigned int eigind2 = 1;
    if( ImageDimension == 3 )
      {
      eigind1 = 2;
      }
    typedef vnl_vector<RealType> EVectorType;
    typedef vnl_matrix<RealType> EMatrixType;
    EVectorType evec1_2ndary = cpa1.GetVnlMatrix().get_row( eigind2 );
    EVectorType evec1_primary = cpa1.GetVnlMatrix().get_row( eigind1 );
    EVectorType evec2_2ndary  = cpa2.GetVnlMatrix().get_row( eigind2 );
    EVectorType evec2_primary = cpa2.GetVnlMatrix().get_row( eigind1 );
    /** Solve Wahba's problem http://en.wikipedia.org/wiki/Wahba%27s_problem */
    EMatrixType B = outer_product( evec2_primary, evec1_primary );
    if( ImageDimension == 3 )
      {
      B = outer_product( evec2_2ndary, evec1_2ndary )
        + outer_product( evec2_primary, evec1_primary );
      }
    vnl_svd<RealType>    wahba( B );
    vnl_matrix<RealType> A_solution = wahba.V() * wahba.U().transpose();
    A_solution = vnl_inverse( A_solution );
    RealType det = vnl_determinant( A_solution  );
    if( ( det < 0 ) )
      {
      vnl_matrix<RealType> id( A_solution );
      id.set_identity();
      for( unsigned int i = 0; i < ImageDimension; i++ )
        {
        if( A_solution( i, i ) < 0 )
          {
          id( i, i ) = -1.0;
          }
        }
      A_solution =  A_solution * id.transpose();
      }
    if ( doReflection[0] == 1 ||  doReflection[0] == 3 )
      {
        vnl_matrix<RealType> id( A_solution );
        id.set_identity();
        id = id - 2.0 * outer_product( evec2_primary , evec2_primary  );
        A_solution = A_solution * id;
      }
    if ( doReflection[0] > 1 )
      {
        vnl_matrix<RealType> id( A_solution );
        id.set_identity();
        id = id - 2.0 * outer_product( evec1_primary , evec1_primary  );
        A_solution = A_solution * id;
      }
    typename AffineType::Pointer affine1 = AffineType::New();
    typename AffineType::OffsetType trans = affine1->GetOffset();
    itk::Point<RealType, ImageDimension> trans2;
    for( unsigned int i = 0; i < ImageDimension; i++ )
      {
      trans[i] = moving_center[i] - fixed_center[i];
      trans2[i] =  fixed_center[i] * ( 1 );
      }
    affine1->SetIdentity();
    affine1->SetOffset( trans );
    if( useprincaxis )
      {
      affine1->SetMatrix( A_solution );
      }
    affine1->SetCenter( trans2 );
    if( ImageDimension > 3  )
      {
      return EXIT_SUCCESS;
      }
    vnl_vector<RealType> evec_tert;
    if( ImageDimension == 3 )
      { // try to rotate around tertiary and secondary axis
      evec_tert = vnl_cross_3d( evec1_primary, evec1_2ndary );
      }
    if( ImageDimension == 2 )
      { // try to rotate around tertiary and secondary axis
      evec_tert = evec1_2ndary;
      evec1_2ndary = evec1_primary;
      }
    itk::Vector<RealType, ImageDimension> axis2;
    itk::Vector<RealType, ImageDimension> axis1;
    for( unsigned int d = 0; d < ImageDimension; d++ )
      {
      axis1[d] = evec_tert[d];
      axis2[d] = evec1_2ndary[d];
      }
    typename AffineType::Pointer simmer = AffineType::New();
    simmer->SetIdentity();
    simmer->SetCenter( trans2 );
    simmer->SetOffset( trans );
    typename AffineType0::Pointer affinesearch = AffineType0::New();
    affinesearch->SetIdentity();
    affinesearch->SetCenter( trans2 );
    typedef  itk::MultiStartOptimizerv4         OptimizerType;
    typename OptimizerType::MetricValuesListType metricvalues;
    typename OptimizerType::Pointer  mstartOptimizer = OptimizerType::New();
    typedef itk::CorrelationImageToImageMetricv4
      <ImageType, ImageType, ImageType> GCMetricType;
    typedef itk::MattesMutualInformationImageToImageMetricv4
      <ImageType, ImageType, ImageType> MetricType;
    typename MetricType::ParametersType newparams(  affine1->GetParameters() );
    typename GCMetricType::Pointer gcmetric = GCMetricType::New();
    gcmetric->SetFixedImage( image1 );
    gcmetric->SetVirtualDomainFromImage( image1 );
    gcmetric->SetMovingImage( image2 );
    gcmetric->SetMovingTransform( simmer );
    gcmetric->SetParameters( newparams );
    typename MetricType::Pointer mimetric = MetricType::New();
    mimetric->SetNumberOfHistogramBins( mibins );
    mimetric->SetFixedImage( image1 );
    mimetric->SetMovingImage( image2 );
    mimetric->SetMovingTransform( simmer );
    mimetric->SetParameters( newparams );
    if( mask.IsNotNull() )
      {
      typename itk::ImageMaskSpatialObject<ImageDimension>::Pointer so =
        itk::ImageMaskSpatialObject<ImageDimension>::New();
      so->SetImage( const_cast<maskimagetype *>( mask.GetPointer() ) );
      mimetric->SetFixedImageMask( so );
      gcmetric->SetFixedImageMask( so );
      }
    typedef  itk::ConjugateGradientLineSearchOptimizerv4 LocalOptimizerType;
    typename LocalOptimizerType::Pointer  localoptimizer =
      LocalOptimizerType::New();
    RealType     localoptimizerlearningrate = 0.1;
    localoptimizer->SetLearningRate( localoptimizerlearningrate );
    localoptimizer->SetMaximumStepSizeInPhysicalUnits(
      localoptimizerlearningrate );
    localoptimizer->SetNumberOfIterations( localSearchIterations );
    localoptimizer->SetLowerLimit( 0 );
    localoptimizer->SetUpperLimit( 2 );
    localoptimizer->SetEpsilon( 0.1 );
    localoptimizer->SetMaximumLineSearchIterations( 50 );
    localoptimizer->SetDoEstimateLearningRateOnce( true );
    localoptimizer->SetMinimumConvergenceValue( 1.e-6 );
    localoptimizer->SetConvergenceWindowSize( 5 );
    if( true )
      {
      typedef typename MetricType::FixedSampledPointSetType PointSetType;
      typedef typename PointSetType::PointType              PointType;
      typename PointSetType::Pointer      pset(PointSetType::New());
      unsigned int ind=0;
      unsigned int ct=0;
      itk::ImageRegionIteratorWithIndex<ImageType> It(image1,
        image1->GetLargestPossibleRegion() );
      for( It.GoToBegin(); !It.IsAtEnd(); ++It )
        {
        // take every N^th point
        if ( ct % 10 == 0  )
          {
          PointType pt;
          image1->TransformIndexToPhysicalPoint( It.GetIndex(), pt);
          pset->SetPoint(ind, pt);
          ind++;
          }
          ct++;
        }
      mimetric->SetFixedSampledPointSet( pset );
      mimetric->SetUseFixedSampledPointSet( true );
      gcmetric->SetFixedSampledPointSet( pset );
      gcmetric->SetUseFixedSampledPointSet( true );
    }
    if ( whichMetric.compare("MI") == 0  ) {
      mimetric->Initialize();
      typedef itk::RegistrationParameterScalesFromPhysicalShift<MetricType>
      RegistrationParameterScalesFromPhysicalShiftType;
      typename RegistrationParameterScalesFromPhysicalShiftType::Pointer
      shiftScaleEstimator =
      RegistrationParameterScalesFromPhysicalShiftType::New();
      shiftScaleEstimator->SetMetric( mimetric );
      shiftScaleEstimator->SetTransformForward( true );
      typename RegistrationParameterScalesFromPhysicalShiftType::ScalesType
      movingScales( simmer->GetNumberOfParameters() );
      shiftScaleEstimator->EstimateScales( movingScales );
      mstartOptimizer->SetScales( movingScales );
      mstartOptimizer->SetMetric( mimetric );
      localoptimizer->SetMetric( mimetric );
      localoptimizer->SetScales( movingScales );
    }
    if ( whichMetric.compare("MI") != 0  ) {
      gcmetric->Initialize();
      typedef itk::RegistrationParameterScalesFromPhysicalShift<GCMetricType>
        RegistrationParameterScalesFromPhysicalShiftType;
      typename RegistrationParameterScalesFromPhysicalShiftType::Pointer
        shiftScaleEstimator =
        RegistrationParameterScalesFromPhysicalShiftType::New();
      shiftScaleEstimator->SetMetric( gcmetric );
      shiftScaleEstimator->SetTransformForward( true );
      typename RegistrationParameterScalesFromPhysicalShiftType::ScalesType
      movingScales( simmer->GetNumberOfParameters() );
      shiftScaleEstimator->EstimateScales( movingScales );
      mstartOptimizer->SetScales( movingScales );
      mstartOptimizer->SetMetric( gcmetric );
      localoptimizer->SetMetric( gcmetric );
      localoptimizer->SetScales( movingScales );
    }
    typename OptimizerType::ParametersListType parametersList =
      mstartOptimizer->GetParametersList();
    affinesearch->SetIdentity();
    affinesearch->SetCenter( trans2 );
    affinesearch->SetOffset( trans );
    for ( unsigned int i = 0; i < vecsize; i++ )
      {
      RealType ang1 = thetas[i];
      RealType ang2 = 0; // FIXME should be psi
      vector_r[ i ]=0;
      if( ImageDimension == 3 )
        {
        for ( unsigned int jj = 0; jj < vecsize; jj++ )
        {
        ang2=thetas[jj];
        affinesearch->SetIdentity();
        affinesearch->SetCenter( trans2 );
        affinesearch->SetOffset( trans );
        if( useprincaxis )
          {
          affinesearch->SetMatrix( A_solution );
          }
        affinesearch->Rotate3D(axis1, ang1, 1);
        affinesearch->Rotate3D(axis2, ang2, 1);
        affinesearch->Scale( bestscale );
        simmer->SetMatrix(  affinesearch->GetMatrix() );
        parametersList.push_back( simmer->GetParameters() );
        }
        }
      if( ImageDimension == 2 )
        {
        affinesearch->SetIdentity();
        affinesearch->SetCenter( trans2 );
        affinesearch->SetOffset( trans );
        if( useprincaxis )
          {
          affinesearch->SetMatrix( A_solution );
          }
        affinesearch->Rotate2D( ang1, 1);
        affinesearch->Scale( bestscale );
        simmer->SetMatrix(  affinesearch->GetMatrix() );
        typename AffineType::ParametersType pp =
          simmer->GetParameters();
        //pp[1]=ang1;
        //pp[0]=bestscale;
        parametersList.push_back( simmer->GetParameters() );
        }
      }
    mstartOptimizer->SetParametersList( parametersList );
    if( localSearchIterations > 0 )
      {
      mstartOptimizer->SetLocalOptimizer( localoptimizer );
      }
    mstartOptimizer->StartOptimization();
    typename AffineType::Pointer bestaffine = AffineType::New();
    bestaffine->SetCenter( trans2 );
    bestaffine->SetParameters( mstartOptimizer->GetBestParameters() );
    if ( txfn.length() > 3 )
      {
      typename AffineType::Pointer bestaffine = AffineType::New();
      bestaffine->SetCenter( trans2 );
      bestaffine->SetParameters( mstartOptimizer->GetBestParameters() );
      typedef itk::TransformFileWriter TransformWriterType;
      typename TransformWriterType::Pointer transformWriter =
        TransformWriterType::New();
      transformWriter->SetInput( bestaffine );
      transformWriter->SetFileName( txfn.c_str() );
      transformWriter->Update();
      }
    metricvalues = mstartOptimizer->GetMetricValuesList();
    for ( unsigned int k = 0; k < metricvalues.size(); k++ )
      {
      vector_r[k] = metricvalues[k];
      }
    dims[0] = vecsize;
    vector_r.attr( "dim" ) = vecsize;
    return Rcpp::wrap( vector_r );
    }
  else
    {
    return Rcpp::wrap( vector_r );
    }
}