#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 982 of file aligner.h.
virtual EMData* EMAN::Refine3DAlignerQuaternion::align | ( | EMData * | this_img, | |
EMData * | to_img | |||
) | const [inline, virtual] |
Implements EMAN::Aligner.
Definition at line 988 of file aligner.h.
References align().
00989 { 00990 return align(this_img, to_img, "sqeuclidean", Dict()); 00991 }
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 1575 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().
01577 { 01578 01579 if (!to || !this_img) throw NullPointerException("Input image is null"); // not sure if this is necessary, it was there before I started 01580 01581 if (to->get_ndim() != 3 || this_img->get_ndim() != 3) throw ImageDimensionException("The Refine3D aligner only works for 3D images"); 01582 01583 #ifdef EMAN2_USING_CUDA 01584 if(EMData::usecuda == 1) { 01585 if(!this_img->getcudarwdata()) this_img->copy_to_cuda(); 01586 if(!to->getcudarwdata()) to->copy_to_cuda(); 01587 } 01588 #endif 01589 01590 float sdi = 0.0; 01591 float sdj = 0.0; 01592 float sdk = 0.0; 01593 float sdx = 0.0; 01594 float sdy = 0.0; 01595 float sdz = 0.0; 01596 bool mirror = false; 01597 01598 Transform* t; 01599 if (params.has_key("xform.align3d") ) { 01600 // Unlike the 2d refine aligner, this class doesn't require the starting transform's 01601 // parameters to form the starting guess. Instead the Transform itself 01602 // is perturbed carefully (using quaternion rotation) to overcome problems that arise 01603 // when you use orthogonally-based Euler angles 01604 t = params["xform.align3d"]; 01605 }else { 01606 t = new Transform(); // is the identity 01607 } 01608 01609 float spincoeff = params.set_default("spin_coeff",10.0f); // spin coefficient, controls speed of convergence (sort of) 01610 01611 int np = 6; // the number of dimensions 01612 Dict gsl_params; 01613 gsl_params["this"] = this_img; 01614 gsl_params["with"] = to; 01615 gsl_params["snr"] = params["snr"]; 01616 gsl_params["mirror"] = mirror; 01617 gsl_params["transform"] = t; 01618 gsl_params["spincoeff"] = spincoeff; 01619 Dict altered_cmp_params(cmp_params); 01620 01621 const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; 01622 gsl_vector *ss = gsl_vector_alloc(np); 01623 01624 float stepi = params.set_default("stepi",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway 01625 float stepj = params.set_default("stepj",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway 01626 float stepk = params.set_default("stepk",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway 01627 float stepx = params.set_default("stepx",1.0f); 01628 float stepy = params.set_default("stepy",1.0f); 01629 float stepz = params.set_default("stepz",1.0f); 01630 01631 //gsl_vector_set(ss, 0, stepw); 01632 gsl_vector_set(ss, 0, stepi); 01633 gsl_vector_set(ss, 1, stepj); 01634 gsl_vector_set(ss, 2, stepk); 01635 gsl_vector_set(ss, 3, stepx); 01636 gsl_vector_set(ss, 4, stepy); 01637 gsl_vector_set(ss, 5, stepz); 01638 01639 gsl_vector *x = gsl_vector_alloc(np); 01640 gsl_vector_set(x, 0, sdi); 01641 gsl_vector_set(x, 1, sdj); 01642 gsl_vector_set(x, 2, sdk); 01643 gsl_vector_set(x, 3, sdx); 01644 gsl_vector_set(x, 4, sdy); 01645 gsl_vector_set(x, 5, sdz); 01646 01647 gsl_multimin_function minex_func; 01648 Cmp *c = Factory < Cmp >::get(cmp_name, altered_cmp_params); 01649 01650 gsl_params["cmp"] = (void *) c; 01651 minex_func.f = &refalifn3dquat; 01652 01653 minex_func.n = np; 01654 minex_func.params = (void *) &gsl_params; 01655 01656 gsl_multimin_fminimizer *s = gsl_multimin_fminimizer_alloc(T, np); 01657 gsl_multimin_fminimizer_set(s, &minex_func, x, ss); 01658 01659 int rval = GSL_CONTINUE; 01660 int status = GSL_SUCCESS; 01661 int iter = 1; 01662 01663 float precision = params.set_default("precision",0.01f); 01664 int maxiter = params.set_default("maxiter",100); 01665 while (rval == GSL_CONTINUE && iter < maxiter) { 01666 iter++; 01667 status = gsl_multimin_fminimizer_iterate(s); 01668 if (status) { 01669 break; 01670 } 01671 rval = gsl_multimin_test_size(gsl_multimin_fminimizer_size(s), precision); 01672 } 01673 01674 int maxshift = params.set_default("maxshift",-1); 01675 01676 if (maxshift <= 0) { 01677 maxshift = this_img->get_xsize() / 4; 01678 } 01679 float fmaxshift = static_cast<float>(maxshift); 01680 01681 EMData *result; 01682 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)) 01683 { 01684 float n0 = (float)gsl_vector_get(s->x, 0); 01685 float n1 = (float)gsl_vector_get(s->x, 1); 01686 float n2 = (float)gsl_vector_get(s->x, 2); 01687 float x = (float)gsl_vector_get(s->x, 3); 01688 float y = (float)gsl_vector_get(s->x, 4); 01689 float z = (float)gsl_vector_get(s->x, 5); 01690 01691 Transform tsoln = refalin3d_perturbquat(t,spincoeff,n0,n1,n2,x,y,z); 01692 01693 result = this_img->process("xform",Dict("transform",&tsoln)); 01694 result->set_attr("xform.align3d",&tsoln); 01695 result->set_attr("score", result->cmp(cmp_name,to,cmp_params)); 01696 01697 //coda goes here 01698 } else { // The refine aligner failed - this shift went beyond the max shift 01699 result = this_img->process("xform",Dict("transform",t)); 01700 result->set_attr("xform.align3d",t); 01701 } 01702 01703 //EMData *result = this_img->process("xform",Dict("transform",t)); 01704 delete t; 01705 t = 0; 01706 gsl_vector_free(x); 01707 gsl_vector_free(ss); 01708 gsl_multimin_fminimizer_free(s); 01709 01710 if ( c != 0 ) delete c; 01711 return result; 01712 }
virtual string EMAN::Refine3DAlignerQuaternion::get_desc | ( | ) | const [inline, virtual] |
Implements EMAN::Aligner.
Definition at line 998 of file aligner.h.
00999 { 01000 return "Refines a preliminary 3D alignment using a simplex algorithm. Subpixel precision."; 01001 }
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 1008 of file aligner.h.
References EMAN::EMObject::FLOAT, EMAN::EMObject::INT, EMAN::TypeDict::put(), and EMAN::EMObject::TRANSFORM.
01009 { 01010 TypeDict d; 01011 d.put("xform.align3d", EMObject::TRANSFORM,"The Transform storing the starting guess. If unspecified the identity matrix is used"); 01012 d.put("stepx", EMObject::FLOAT, "The initial simplex step size in x. Default is 1"); 01013 d.put("stepy", EMObject::FLOAT, "The initial simplex step size in y. Default is 1"); 01014 d.put("stepz", EMObject::FLOAT, "The initial simplex step size in z. Default is 1." ); 01015 d.put("stepn0", EMObject::FLOAT, "The initial simplex step size in the first quaternion vecotr component. Default is 1." ); 01016 d.put("stepn1", EMObject::FLOAT, "The initial simplex step size in the second quaternion vecotr component. Default is 1." ); 01017 d.put("stepn2", EMObject::FLOAT, "The initial simplex step size in the third quaternion vecotr component. Default is 1." ); 01018 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."); 01019 d.put("precision", EMObject::FLOAT, "The precision which, if achieved, can stop the iterative refinement before reaching the maximum iterations. Default is 0.01." ); 01020 d.put("maxiter", EMObject::INT, "The maximum number of iterations that can be performed by the Simplex minimizer. Default is 100."); 01021 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."); 01022 return d; 01023 }
static Aligner* EMAN::Refine3DAlignerQuaternion::NEW | ( | ) | [inline, static] |
const string Refine3DAlignerQuaternion::NAME = "refine_3d" [static] |