#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 1449 of file aligner.h.
virtual EMData* EMAN::Refine3DAlignerQuaternion::align | ( | EMData * | this_img, | |
EMData * | to_img | |||
) | const [inline, virtual] |
Implements EMAN::Aligner.
Definition at line 1455 of file aligner.h.
References align().
01456 { 01457 return align(this_img, to_img, "sqeuclidean", Dict()); 01458 }
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 2123 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().
02125 { 02126 02127 if (!to || !this_img) throw NullPointerException("Input image is null"); // not sure if this is necessary, it was there before I started 02128 02129 if (to->get_ndim() != 3 || this_img->get_ndim() != 3) throw ImageDimensionException("The Refine3D aligner only works for 3D images"); 02130 02131 #ifdef EMAN2_USING_CUDA 02132 if(EMData::usecuda == 1) { 02133 if(!this_img->getcudarwdata()) this_img->copy_to_cuda(); 02134 if(!to->getcudarwdata()) to->copy_to_cuda(); 02135 } 02136 #endif 02137 02138 float sdi = 0.0; 02139 float sdj = 0.0; 02140 float sdk = 0.0; 02141 float sdx = 0.0; 02142 float sdy = 0.0; 02143 float sdz = 0.0; 02144 bool mirror = false; 02145 02146 Transform* t; 02147 if (params.has_key("xform.align3d") ) { 02148 // Unlike the 2d refine aligner, this class doesn't require the starting transform's 02149 // parameters to form the starting guess. Instead the Transform itself 02150 // is perturbed carefully (using quaternion rotation) to overcome problems that arise 02151 // when you use orthogonally-based Euler angles 02152 t = params["xform.align3d"]; 02153 }else { 02154 t = new Transform(); // is the identity 02155 } 02156 02157 float spincoeff = params.set_default("spin_coeff",10.0f); // spin coefficient, controls speed of convergence (sort of) 02158 02159 int np = 6; // the number of dimensions 02160 Dict gsl_params; 02161 gsl_params["this"] = this_img; 02162 gsl_params["with"] = to; 02163 gsl_params["snr"] = params["snr"]; 02164 gsl_params["mirror"] = mirror; 02165 gsl_params["transform"] = t; 02166 gsl_params["spincoeff"] = spincoeff; 02167 Dict altered_cmp_params(cmp_params); 02168 02169 const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; 02170 gsl_vector *ss = gsl_vector_alloc(np); 02171 02172 float stepi = params.set_default("stepn0",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway 02173 float stepj = params.set_default("stepn1",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway 02174 float stepk = params.set_default("stepn2",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway 02175 float stepx = params.set_default("stepx",1.0f); 02176 float stepy = params.set_default("stepy",1.0f); 02177 float stepz = params.set_default("stepz",1.0f); 02178 02179 //gsl_vector_set(ss, 0, stepw); 02180 gsl_vector_set(ss, 0, stepi); 02181 gsl_vector_set(ss, 1, stepj); 02182 gsl_vector_set(ss, 2, stepk); 02183 gsl_vector_set(ss, 3, stepx); 02184 gsl_vector_set(ss, 4, stepy); 02185 gsl_vector_set(ss, 5, stepz); 02186 02187 gsl_vector *x = gsl_vector_alloc(np); 02188 gsl_vector_set(x, 0, sdi); 02189 gsl_vector_set(x, 1, sdj); 02190 gsl_vector_set(x, 2, sdk); 02191 gsl_vector_set(x, 3, sdx); 02192 gsl_vector_set(x, 4, sdy); 02193 gsl_vector_set(x, 5, sdz); 02194 02195 gsl_multimin_function minex_func; 02196 Cmp *c = Factory < Cmp >::get(cmp_name, altered_cmp_params); 02197 02198 gsl_params["cmp"] = (void *) c; 02199 minex_func.f = &refalifn3dquat; 02200 02201 minex_func.n = np; 02202 minex_func.params = (void *) &gsl_params; 02203 02204 gsl_multimin_fminimizer *s = gsl_multimin_fminimizer_alloc(T, np); 02205 gsl_multimin_fminimizer_set(s, &minex_func, x, ss); 02206 02207 int rval = GSL_CONTINUE; 02208 int status = GSL_SUCCESS; 02209 int iter = 1; 02210 02211 float precision = params.set_default("precision",0.01f); 02212 int maxiter = params.set_default("maxiter",100); 02213 while (rval == GSL_CONTINUE && iter < maxiter) { 02214 iter++; 02215 status = gsl_multimin_fminimizer_iterate(s); 02216 if (status) { 02217 break; 02218 } 02219 rval = gsl_multimin_test_size(gsl_multimin_fminimizer_size(s), precision); 02220 } 02221 02222 int maxshift = params.set_default("maxshift",-1); 02223 02224 if (maxshift <= 0) { 02225 maxshift = this_img->get_xsize() / 4; 02226 } 02227 float fmaxshift = static_cast<float>(maxshift); 02228 02229 EMData *result; 02230 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)) 02231 { 02232 float n0 = (float)gsl_vector_get(s->x, 0); 02233 float n1 = (float)gsl_vector_get(s->x, 1); 02234 float n2 = (float)gsl_vector_get(s->x, 2); 02235 float x = (float)gsl_vector_get(s->x, 3); 02236 float y = (float)gsl_vector_get(s->x, 4); 02237 float z = (float)gsl_vector_get(s->x, 5); 02238 02239 Transform tsoln = refalin3d_perturbquat(t,spincoeff,n0,n1,n2,x,y,z); 02240 02241 result = this_img->process("xform",Dict("transform",&tsoln)); 02242 result->set_attr("xform.align3d",&tsoln); 02243 result->set_attr("score", result->cmp(cmp_name,to,cmp_params)); 02244 02245 //coda goes here 02246 } else { // The refine aligner failed - this shift went beyond the max shift 02247 result = this_img->process("xform",Dict("transform",t)); 02248 result->set_attr("xform.align3d",t); 02249 result->set_attr("score",0.0); 02250 } 02251 02252 //EMData *result = this_img->process("xform",Dict("transform",t)); 02253 delete t; 02254 gsl_vector_free(x); 02255 gsl_vector_free(ss); 02256 gsl_multimin_fminimizer_free(s); 02257 02258 if (c != 0) delete c; 02259 02260 return result; 02261 }
virtual string EMAN::Refine3DAlignerQuaternion::get_desc | ( | ) | const [inline, virtual] |
Implements EMAN::Aligner.
Definition at line 1465 of file aligner.h.
01466 { 01467 return "Refines a preliminary 3D alignment using a simplex algorithm. Subpixel precision."; 01468 }
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 1475 of file aligner.h.
References EMAN::EMObject::FLOAT, EMAN::EMObject::INT, EMAN::TypeDict::put(), and EMAN::EMObject::TRANSFORM.
01476 { 01477 TypeDict d; 01478 d.put("xform.align3d", EMObject::TRANSFORM,"The Transform storing the starting guess. If unspecified the identity matrix is used"); 01479 d.put("stepx", EMObject::FLOAT, "The initial simplex step size in x. Default is 1"); 01480 d.put("stepy", EMObject::FLOAT, "The initial simplex step size in y. Default is 1"); 01481 d.put("stepz", EMObject::FLOAT, "The initial simplex step size in z. Default is 1." ); 01482 d.put("stepn0", EMObject::FLOAT, "The initial simplex step size in the first quaternion vecotr component. Default is 1." ); 01483 d.put("stepn1", EMObject::FLOAT, "The initial simplex step size in the second quaternion vecotr component. Default is 1." ); 01484 d.put("stepn2", EMObject::FLOAT, "The initial simplex step size in the third quaternion vecotr component. Default is 1." ); 01485 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."); 01486 d.put("precision", EMObject::FLOAT, "The precision which, if achieved, can stop the iterative refinement before reaching the maximum iterations. Default is 0.01." ); 01487 d.put("maxiter", EMObject::INT, "The maximum number of iterations that can be performed by the Simplex minimizer. Default is 100."); 01488 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."); 01489 return d; 01490 }
static Aligner* EMAN::Refine3DAlignerQuaternion::NEW | ( | ) | [inline, static] |
const string Refine3DAlignerQuaternion::NAME = "refine_3d" [static] |