#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 1077 of file aligner.h.
virtual EMData* EMAN::Refine3DAlignerQuaternion::align | ( | EMData * | this_img, | |
EMData * | to_img | |||
) | const [inline, virtual] |
Implements EMAN::Aligner.
Definition at line 1083 of file aligner.h.
References align().
01084 { 01085 return align(this_img, to_img, "sqeuclidean", Dict()); 01086 }
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 1785 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().
01787 { 01788 01789 if (!to || !this_img) throw NullPointerException("Input image is null"); // not sure if this is necessary, it was there before I started 01790 01791 if (to->get_ndim() != 3 || this_img->get_ndim() != 3) throw ImageDimensionException("The Refine3D aligner only works for 3D images"); 01792 01793 #ifdef EMAN2_USING_CUDA 01794 if(EMData::usecuda == 1) { 01795 if(!this_img->getcudarwdata()) this_img->copy_to_cuda(); 01796 if(!to->getcudarwdata()) to->copy_to_cuda(); 01797 } 01798 #endif 01799 01800 float sdi = 0.0; 01801 float sdj = 0.0; 01802 float sdk = 0.0; 01803 float sdx = 0.0; 01804 float sdy = 0.0; 01805 float sdz = 0.0; 01806 bool mirror = false; 01807 01808 Transform* t; 01809 if (params.has_key("xform.align3d") ) { 01810 // Unlike the 2d refine aligner, this class doesn't require the starting transform's 01811 // parameters to form the starting guess. Instead the Transform itself 01812 // is perturbed carefully (using quaternion rotation) to overcome problems that arise 01813 // when you use orthogonally-based Euler angles 01814 t = params["xform.align3d"]; 01815 }else { 01816 t = new Transform(); // is the identity 01817 } 01818 01819 float spincoeff = params.set_default("spin_coeff",10.0f); // spin coefficient, controls speed of convergence (sort of) 01820 01821 int np = 6; // the number of dimensions 01822 Dict gsl_params; 01823 gsl_params["this"] = this_img; 01824 gsl_params["with"] = to; 01825 gsl_params["snr"] = params["snr"]; 01826 gsl_params["mirror"] = mirror; 01827 gsl_params["transform"] = t; 01828 gsl_params["spincoeff"] = spincoeff; 01829 Dict altered_cmp_params(cmp_params); 01830 01831 const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; 01832 gsl_vector *ss = gsl_vector_alloc(np); 01833 01834 float stepi = params.set_default("stepn0",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway 01835 float stepj = params.set_default("stepn1",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway 01836 float stepk = params.set_default("stepn2",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway 01837 float stepx = params.set_default("stepx",1.0f); 01838 float stepy = params.set_default("stepy",1.0f); 01839 float stepz = params.set_default("stepz",1.0f); 01840 01841 //gsl_vector_set(ss, 0, stepw); 01842 gsl_vector_set(ss, 0, stepi); 01843 gsl_vector_set(ss, 1, stepj); 01844 gsl_vector_set(ss, 2, stepk); 01845 gsl_vector_set(ss, 3, stepx); 01846 gsl_vector_set(ss, 4, stepy); 01847 gsl_vector_set(ss, 5, stepz); 01848 01849 gsl_vector *x = gsl_vector_alloc(np); 01850 gsl_vector_set(x, 0, sdi); 01851 gsl_vector_set(x, 1, sdj); 01852 gsl_vector_set(x, 2, sdk); 01853 gsl_vector_set(x, 3, sdx); 01854 gsl_vector_set(x, 4, sdy); 01855 gsl_vector_set(x, 5, sdz); 01856 01857 gsl_multimin_function minex_func; 01858 Cmp *c = Factory < Cmp >::get(cmp_name, altered_cmp_params); 01859 01860 gsl_params["cmp"] = (void *) c; 01861 minex_func.f = &refalifn3dquat; 01862 01863 minex_func.n = np; 01864 minex_func.params = (void *) &gsl_params; 01865 01866 gsl_multimin_fminimizer *s = gsl_multimin_fminimizer_alloc(T, np); 01867 gsl_multimin_fminimizer_set(s, &minex_func, x, ss); 01868 01869 int rval = GSL_CONTINUE; 01870 int status = GSL_SUCCESS; 01871 int iter = 1; 01872 01873 float precision = params.set_default("precision",0.01f); 01874 int maxiter = params.set_default("maxiter",100); 01875 while (rval == GSL_CONTINUE && iter < maxiter) { 01876 iter++; 01877 status = gsl_multimin_fminimizer_iterate(s); 01878 if (status) { 01879 break; 01880 } 01881 rval = gsl_multimin_test_size(gsl_multimin_fminimizer_size(s), precision); 01882 } 01883 01884 int maxshift = params.set_default("maxshift",-1); 01885 01886 if (maxshift <= 0) { 01887 maxshift = this_img->get_xsize() / 4; 01888 } 01889 float fmaxshift = static_cast<float>(maxshift); 01890 01891 EMData *result; 01892 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)) 01893 { 01894 float n0 = (float)gsl_vector_get(s->x, 0); 01895 float n1 = (float)gsl_vector_get(s->x, 1); 01896 float n2 = (float)gsl_vector_get(s->x, 2); 01897 float x = (float)gsl_vector_get(s->x, 3); 01898 float y = (float)gsl_vector_get(s->x, 4); 01899 float z = (float)gsl_vector_get(s->x, 5); 01900 01901 Transform tsoln = refalin3d_perturbquat(t,spincoeff,n0,n1,n2,x,y,z); 01902 01903 result = this_img->process("xform",Dict("transform",&tsoln)); 01904 result->set_attr("xform.align3d",&tsoln); 01905 result->set_attr("score", result->cmp(cmp_name,to,cmp_params)); 01906 01907 //coda goes here 01908 } else { // The refine aligner failed - this shift went beyond the max shift 01909 result = this_img->process("xform",Dict("transform",t)); 01910 result->set_attr("xform.align3d",t); 01911 result->set_attr("score",0.0); 01912 } 01913 01914 //EMData *result = this_img->process("xform",Dict("transform",t)); 01915 delete t; 01916 gsl_vector_free(x); 01917 gsl_vector_free(ss); 01918 gsl_multimin_fminimizer_free(s); 01919 01920 if ( c != 0 ) delete c; 01921 01922 //Free up resources (for an expensive opperation like this move data to and from device is a small % of time) 01923 #ifdef EMAN2_USING_CUDA 01924 to->copy_from_device(); 01925 this_img->ro_free(); 01926 #endif 01927 01928 return result; 01929 }
virtual string EMAN::Refine3DAlignerQuaternion::get_desc | ( | ) | const [inline, virtual] |
Implements EMAN::Aligner.
Definition at line 1093 of file aligner.h.
01094 { 01095 return "Refines a preliminary 3D alignment using a simplex algorithm. Subpixel precision."; 01096 }
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 1103 of file aligner.h.
References EMAN::EMObject::FLOAT, EMAN::EMObject::INT, EMAN::TypeDict::put(), and EMAN::EMObject::TRANSFORM.
01104 { 01105 TypeDict d; 01106 d.put("xform.align3d", EMObject::TRANSFORM,"The Transform storing the starting guess. If unspecified the identity matrix is used"); 01107 d.put("stepx", EMObject::FLOAT, "The initial simplex step size in x. Default is 1"); 01108 d.put("stepy", EMObject::FLOAT, "The initial simplex step size in y. Default is 1"); 01109 d.put("stepz", EMObject::FLOAT, "The initial simplex step size in z. Default is 1." ); 01110 d.put("stepn0", EMObject::FLOAT, "The initial simplex step size in the first quaternion vecotr component. Default is 1." ); 01111 d.put("stepn1", EMObject::FLOAT, "The initial simplex step size in the second quaternion vecotr component. Default is 1." ); 01112 d.put("stepn2", EMObject::FLOAT, "The initial simplex step size in the third quaternion vecotr component. Default is 1." ); 01113 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."); 01114 d.put("precision", EMObject::FLOAT, "The precision which, if achieved, can stop the iterative refinement before reaching the maximum iterations. Default is 0.01." ); 01115 d.put("maxiter", EMObject::INT, "The maximum number of iterations that can be performed by the Simplex minimizer. Default is 100."); 01116 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."); 01117 return d; 01118 }
static Aligner* EMAN::Refine3DAlignerQuaternion::NEW | ( | ) | [inline, static] |
const string Refine3DAlignerQuaternion::NAME = "refine_3d" [static] |