#include <aligner.h>
Inheritance diagram for EMAN::Refine3DAlignerQuaternion:
Public Member Functions | |
virtual EMData * | align (EMData *this_img, EMData *to_img, const string &cmp_name="sqeuclidean", const Dict &cmp_params=Dict()) const |
To align 'this_img' with another image passed in through its parameters. | |
virtual EMData * | align (EMData *this_img, EMData *to_img) const |
virtual string | get_name () const |
Get the Aligner's name. | |
virtual string | get_desc () const |
virtual TypeDict | get_param_types () const |
Static Public Member Functions | |
static Aligner * | NEW () |
Static Public Attributes | |
static const string | NAME = "refine_3d" |
Refines a preliminary 3D alignment using a simplex algorithm. Subpixel precision. Target function for the simplex algorithm is a rotation along an arbitrary axis defined by a quaternion, whose rotation magnitude is defined by the vector length (hence the simplex varies the vecotr component of the quaternion). In addition the simplex varies translation. Using quaternions avoids gimbal lock. The simplex algorithm moves the function downhill in a ameboa like fasion, hence it may get stuck in a local minima if the two 3D models are already roughly aligned.
xform.align3d | The Transform storing the starting guess. If unspecified the identity matrix is used | |
stepx | The initial simplex step size in x | |
stepy | The initial simplex step size in y | |
stepz | The initial simplex step size in z | |
stepn0 | The initial simplex step size in the first quaternion vecotr component | |
stepn1 | The initial simplex step size in the second quaternion vecotr component | |
stepn2 | The initial simplex step size in the third quaternion vecotr component | |
spin_coeff | The multiplier appied to the spin (if it is too small or too large the simplex will not converge) | |
precision | The precision which, if achieved, can stop the iterative refinement before reaching the maximum iterations | |
maxiter | The maximum number of iterations that can be performed by the Simplex minimizer | |
maxshift | Maximum translation in pixels in any direction. |
Definition at line 1384 of file aligner.h.
virtual EMData* EMAN::Refine3DAlignerQuaternion::align | ( | EMData * | this_img, | |
EMData * | to_img | |||
) | const [inline, virtual] |
Implements EMAN::Aligner.
Definition at line 1390 of file aligner.h.
References align().
01391 { 01392 return align(this_img, to_img, "sqeuclidean", Dict()); 01393 }
EMData * Refine3DAlignerQuaternion::align | ( | EMData * | this_img, | |
EMData * | to_img, | |||
const string & | cmp_name = "sqeuclidean" , |
|||
const Dict & | cmp_params = Dict() | |||
) | const [virtual] |
To align 'this_img' with another image passed in through its parameters.
The alignment uses a user-given comparison method to compare the two images. If none is given, a default one is used.
this_img | The image to be compared. | |
to_img | 'this_img" is aligned with 'to_img'. | |
cmp_name | The comparison method to compare the two images. | |
cmp_params | The parameter dictionary for comparison method. |
Implements EMAN::Aligner.
Definition at line 1969 of file aligner.cpp.
References EMAN::EMData::get_ndim(), EMAN::EMData::get_xsize(), EMAN::Dict::has_key(), ImageDimensionException, NullPointerException, EMAN::Aligner::params, EMAN::EMData::process(), refalifn3dquat(), refalin3d_perturbquat(), EMAN::EMData::set_attr(), EMAN::Dict::set_default(), status, t, x, and y.
Referenced by align().
01971 { 01972 01973 if (!to || !this_img) throw NullPointerException("Input image is null"); // not sure if this is necessary, it was there before I started 01974 01975 if (to->get_ndim() != 3 || this_img->get_ndim() != 3) throw ImageDimensionException("The Refine3D aligner only works for 3D images"); 01976 01977 #ifdef EMAN2_USING_CUDA 01978 if(EMData::usecuda == 1) { 01979 if(!this_img->getcudarwdata()) this_img->copy_to_cuda(); 01980 if(!to->getcudarwdata()) to->copy_to_cuda(); 01981 } 01982 #endif 01983 01984 float sdi = 0.0; 01985 float sdj = 0.0; 01986 float sdk = 0.0; 01987 float sdx = 0.0; 01988 float sdy = 0.0; 01989 float sdz = 0.0; 01990 bool mirror = false; 01991 01992 Transform* t; 01993 if (params.has_key("xform.align3d") ) { 01994 // Unlike the 2d refine aligner, this class doesn't require the starting transform's 01995 // parameters to form the starting guess. Instead the Transform itself 01996 // is perturbed carefully (using quaternion rotation) to overcome problems that arise 01997 // when you use orthogonally-based Euler angles 01998 t = params["xform.align3d"]; 01999 }else { 02000 t = new Transform(); // is the identity 02001 } 02002 02003 float spincoeff = params.set_default("spin_coeff",10.0f); // spin coefficient, controls speed of convergence (sort of) 02004 02005 int np = 6; // the number of dimensions 02006 Dict gsl_params; 02007 gsl_params["this"] = this_img; 02008 gsl_params["with"] = to; 02009 gsl_params["snr"] = params["snr"]; 02010 gsl_params["mirror"] = mirror; 02011 gsl_params["transform"] = t; 02012 gsl_params["spincoeff"] = spincoeff; 02013 Dict altered_cmp_params(cmp_params); 02014 02015 const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; 02016 gsl_vector *ss = gsl_vector_alloc(np); 02017 02018 float stepi = params.set_default("stepn0",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway 02019 float stepj = params.set_default("stepn1",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway 02020 float stepk = params.set_default("stepn2",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway 02021 float stepx = params.set_default("stepx",1.0f); 02022 float stepy = params.set_default("stepy",1.0f); 02023 float stepz = params.set_default("stepz",1.0f); 02024 02025 //gsl_vector_set(ss, 0, stepw); 02026 gsl_vector_set(ss, 0, stepi); 02027 gsl_vector_set(ss, 1, stepj); 02028 gsl_vector_set(ss, 2, stepk); 02029 gsl_vector_set(ss, 3, stepx); 02030 gsl_vector_set(ss, 4, stepy); 02031 gsl_vector_set(ss, 5, stepz); 02032 02033 gsl_vector *x = gsl_vector_alloc(np); 02034 gsl_vector_set(x, 0, sdi); 02035 gsl_vector_set(x, 1, sdj); 02036 gsl_vector_set(x, 2, sdk); 02037 gsl_vector_set(x, 3, sdx); 02038 gsl_vector_set(x, 4, sdy); 02039 gsl_vector_set(x, 5, sdz); 02040 02041 gsl_multimin_function minex_func; 02042 Cmp *c = Factory < Cmp >::get(cmp_name, altered_cmp_params); 02043 02044 gsl_params["cmp"] = (void *) c; 02045 minex_func.f = &refalifn3dquat; 02046 02047 minex_func.n = np; 02048 minex_func.params = (void *) &gsl_params; 02049 02050 gsl_multimin_fminimizer *s = gsl_multimin_fminimizer_alloc(T, np); 02051 gsl_multimin_fminimizer_set(s, &minex_func, x, ss); 02052 02053 int rval = GSL_CONTINUE; 02054 int status = GSL_SUCCESS; 02055 int iter = 1; 02056 02057 float precision = params.set_default("precision",0.01f); 02058 int maxiter = params.set_default("maxiter",100); 02059 while (rval == GSL_CONTINUE && iter < maxiter) { 02060 iter++; 02061 status = gsl_multimin_fminimizer_iterate(s); 02062 if (status) { 02063 break; 02064 } 02065 rval = gsl_multimin_test_size(gsl_multimin_fminimizer_size(s), precision); 02066 } 02067 02068 int maxshift = params.set_default("maxshift",-1); 02069 02070 if (maxshift <= 0) { 02071 maxshift = this_img->get_xsize() / 4; 02072 } 02073 float fmaxshift = static_cast<float>(maxshift); 02074 02075 EMData *result; 02076 if ( fmaxshift >= (float)gsl_vector_get(s->x, 0) && fmaxshift >= (float)gsl_vector_get(s->x, 1) && fmaxshift >= (float)gsl_vector_get(s->x, 2)) 02077 { 02078 float n0 = (float)gsl_vector_get(s->x, 0); 02079 float n1 = (float)gsl_vector_get(s->x, 1); 02080 float n2 = (float)gsl_vector_get(s->x, 2); 02081 float x = (float)gsl_vector_get(s->x, 3); 02082 float y = (float)gsl_vector_get(s->x, 4); 02083 float z = (float)gsl_vector_get(s->x, 5); 02084 02085 Transform tsoln = refalin3d_perturbquat(t,spincoeff,n0,n1,n2,x,y,z); 02086 02087 result = this_img->process("xform",Dict("transform",&tsoln)); 02088 result->set_attr("xform.align3d",&tsoln); 02089 result->set_attr("score", result->cmp(cmp_name,to,cmp_params)); 02090 02091 //coda goes here 02092 } else { // The refine aligner failed - this shift went beyond the max shift 02093 result = this_img->process("xform",Dict("transform",t)); 02094 result->set_attr("xform.align3d",t); 02095 result->set_attr("score",0.0); 02096 } 02097 02098 //EMData *result = this_img->process("xform",Dict("transform",t)); 02099 delete t; 02100 gsl_vector_free(x); 02101 gsl_vector_free(ss); 02102 gsl_multimin_fminimizer_free(s); 02103 02104 if (c != 0) delete c; 02105 02106 return result; 02107 }
virtual string EMAN::Refine3DAlignerQuaternion::get_desc | ( | ) | const [inline, virtual] |
Implements EMAN::Aligner.
Definition at line 1400 of file aligner.h.
01401 { 01402 return "Refines a preliminary 3D alignment using a simplex algorithm. Subpixel precision."; 01403 }
virtual string EMAN::Refine3DAlignerQuaternion::get_name | ( | ) | const [inline, virtual] |
virtual TypeDict EMAN::Refine3DAlignerQuaternion::get_param_types | ( | ) | const [inline, virtual] |
Implements EMAN::Aligner.
Definition at line 1410 of file aligner.h.
References EMAN::EMObject::FLOAT, EMAN::EMObject::INT, EMAN::TypeDict::put(), and EMAN::EMObject::TRANSFORM.
01411 { 01412 TypeDict d; 01413 d.put("xform.align3d", EMObject::TRANSFORM,"The Transform storing the starting guess. If unspecified the identity matrix is used"); 01414 d.put("stepx", EMObject::FLOAT, "The initial simplex step size in x. Default is 1"); 01415 d.put("stepy", EMObject::FLOAT, "The initial simplex step size in y. Default is 1"); 01416 d.put("stepz", EMObject::FLOAT, "The initial simplex step size in z. Default is 1." ); 01417 d.put("stepn0", EMObject::FLOAT, "The initial simplex step size in the first quaternion vecotr component. Default is 1." ); 01418 d.put("stepn1", EMObject::FLOAT, "The initial simplex step size in the second quaternion vecotr component. Default is 1." ); 01419 d.put("stepn2", EMObject::FLOAT, "The initial simplex step size in the third quaternion vecotr component. Default is 1." ); 01420 d.put("spin_coeff", EMObject::FLOAT,"The multiplier appied to the spin (if it is too small or too large the simplex will not converge). Default is 10."); 01421 d.put("precision", EMObject::FLOAT, "The precision which, if achieved, can stop the iterative refinement before reaching the maximum iterations. Default is 0.01." ); 01422 d.put("maxiter", EMObject::INT, "The maximum number of iterations that can be performed by the Simplex minimizer. Default is 100."); 01423 d.put("maxshift", EMObject::INT,"Maximum translation in pixels in any direction. If the solution yields a shift beyond this value in any direction, then the refinement is judged a failure and the original alignment is used as the solution."); 01424 return d; 01425 }
static Aligner* EMAN::Refine3DAlignerQuaternion::NEW | ( | ) | [inline, static] |
const string Refine3DAlignerQuaternion::NAME = "refine_3d" [static] |