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