EMAN2
Public Member Functions | Static Public Member Functions | Static Public Attributes
EMAN::Refine3DAlignerQuaternion Class Reference

Refine alignment. More...

#include <aligner.h>

Inheritance diagram for EMAN::Refine3DAlignerQuaternion:
Inheritance graph
[legend]
Collaboration diagram for EMAN::Refine3DAlignerQuaternion:
Collaboration graph
[legend]

List of all members.

Public Member Functions

virtual EMDataalign (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 EMDataalign (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 AlignerNEW ()

Static Public Attributes

static const string NAME = "refine_3d"

Detailed Description

Refine alignment.

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.

Parameters:
xform.align3dThe Transform storing the starting guess. If unspecified the identity matrix is used
stepxThe initial simplex step size in x
stepyThe initial simplex step size in y
stepzThe initial simplex step size in z
stepn0The initial simplex step size in the first quaternion vecotr component
stepn1The initial simplex step size in the second quaternion vecotr component
stepn2The initial simplex step size in the third quaternion vecotr component
spin_coeffThe multiplier appied to the spin (if it is too small or too large the simplex will not converge)
precisionThe precision which, if achieved, can stop the iterative refinement before reaching the maximum iterations
maxiterThe maximum number of iterations that can be performed by the Simplex minimizer
maxshiftMaximum translation in pixels in any direction.
Author:
John Flanagan (with code recyled from David Woolford)
Date:
Feb 3rd 2011

Definition at line 1455 of file aligner.h.


Member Function Documentation

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.

Parameters:
this_imgThe image to be compared.
to_img'this_img" is aligned with 'to_img'.
cmp_nameThe comparison method to compare the two images.
cmp_paramsThe parameter dictionary for comparison method.
Returns:
The aligned image.

Implements EMAN::Aligner.

Definition at line 2144 of file aligner.cpp.

References EMAN::EMData::cmp(), 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().

{
        
        if (!to || !this_img) throw NullPointerException("Input image is null"); // not sure if this is necessary, it was there before I started

        if (to->get_ndim() != 3 || this_img->get_ndim() != 3) throw ImageDimensionException("The Refine3D aligner only works for 3D images");

#ifdef EMAN2_USING_CUDA 
        if(EMData::usecuda == 1) {
                if(!this_img->getcudarwdata()) this_img->copy_to_cuda();
                if(!to->getcudarwdata()) to->copy_to_cuda();
        }
#endif

        float sdi = 0.0;
        float sdj = 0.0;
        float sdk = 0.0;
        float sdx = 0.0;
        float sdy = 0.0;
        float sdz = 0.0;
        bool mirror = false;
        
        Transform* t;
        if (params.has_key("xform.align3d") ) {
                // Unlike the 2d refine aligner, this class doesn't require the starting transform's
                // parameters to form the starting guess. Instead the Transform itself
                // is perturbed carefully (using quaternion rotation) to overcome problems that arise
                // when you use orthogonally-based Euler angles
                t = params["xform.align3d"];
        }else {
                t = new Transform(); // is the identity
        }
        
        float spincoeff =  params.set_default("spin_coeff",10.0f); // spin coefficient, controls speed of convergence (sort of)
        
        int np = 6; // the number of dimensions
        Dict gsl_params;
        gsl_params["this"] = this_img;
        gsl_params["with"] = to;
        gsl_params["snr"]  = params["snr"];
        gsl_params["mirror"] = mirror;
        gsl_params["transform"] = t;    
        gsl_params["spincoeff"] = spincoeff;
        Dict altered_cmp_params(cmp_params);
        
        const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
        gsl_vector *ss = gsl_vector_alloc(np);
        
        float stepi = params.set_default("stepn0",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway
        float stepj = params.set_default("stepn1",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway
        float stepk = params.set_default("stepn2",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway
        float stepx = params.set_default("stepx",1.0f);
        float stepy = params.set_default("stepy",1.0f);
        float stepz = params.set_default("stepz",1.0f);
        
        //gsl_vector_set(ss, 0, stepw);
        gsl_vector_set(ss, 0, stepi);
        gsl_vector_set(ss, 1, stepj);
        gsl_vector_set(ss, 2, stepk);
        gsl_vector_set(ss, 3, stepx);
        gsl_vector_set(ss, 4, stepy);
        gsl_vector_set(ss, 5, stepz);
        
        gsl_vector *x = gsl_vector_alloc(np);
        gsl_vector_set(x, 0, sdi);
        gsl_vector_set(x, 1, sdj);
        gsl_vector_set(x, 2, sdk);
        gsl_vector_set(x, 3, sdx);
        gsl_vector_set(x, 4, sdy);
        gsl_vector_set(x, 5, sdz);
        
        gsl_multimin_function minex_func;
        Cmp *c = Factory < Cmp >::get(cmp_name, altered_cmp_params);
                
        gsl_params["cmp"] = (void *) c;
        minex_func.f = &refalifn3dquat;

        minex_func.n = np;
        minex_func.params = (void *) &gsl_params;
        
        gsl_multimin_fminimizer *s = gsl_multimin_fminimizer_alloc(T, np);
        gsl_multimin_fminimizer_set(s, &minex_func, x, ss);
        
        int rval = GSL_CONTINUE;
        int status = GSL_SUCCESS;
        int iter = 1;
        
        float precision = params.set_default("precision",0.01f);
        int maxiter = params.set_default("maxiter",100);
        while (rval == GSL_CONTINUE && iter < maxiter) {
                iter++;
                status = gsl_multimin_fminimizer_iterate(s);
                if (status) {
                        break;
                }
                rval = gsl_multimin_test_size(gsl_multimin_fminimizer_size(s), precision);
        }

        int maxshift = params.set_default("maxshift",-1);

        if (maxshift <= 0) {
                maxshift = this_img->get_xsize() / 4;
        }
        float fmaxshift = static_cast<float>(maxshift);
        
        EMData *result;
        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))
        {
                float n0 = (float)gsl_vector_get(s->x, 0);
                float n1 = (float)gsl_vector_get(s->x, 1);
                float n2 = (float)gsl_vector_get(s->x, 2);
                float x = (float)gsl_vector_get(s->x, 3);
                float y = (float)gsl_vector_get(s->x, 4);
                float z = (float)gsl_vector_get(s->x, 5);
                
                Transform tsoln = refalin3d_perturbquat(t,spincoeff,n0,n1,n2,x,y,z);
                        
                result = this_img->process("xform",Dict("transform",&tsoln));
                result->set_attr("xform.align3d",&tsoln);
                result->set_attr("score", result->cmp(cmp_name,to,cmp_params));
                
         //coda goes here
        } else { // The refine aligner failed - this shift went beyond the max shift
                result = this_img->process("xform",Dict("transform",t));
                result->set_attr("xform.align3d",t);
                result->set_attr("score",0.0);
        }
        
        //EMData *result = this_img->process("xform",Dict("transform",t));
        delete t;
        gsl_vector_free(x);
        gsl_vector_free(ss);
        gsl_multimin_fminimizer_free(s);

        if (c != 0) delete c;
        
        return result;
}
virtual EMData* EMAN::Refine3DAlignerQuaternion::align ( EMData this_img,
EMData to_img 
) const [inline, virtual]

Implements EMAN::Aligner.

Definition at line 1461 of file aligner.h.

References align().

                        {
                                return align(this_img, to_img, "sqeuclidean", Dict());
                        }
virtual string EMAN::Refine3DAlignerQuaternion::get_desc ( ) const [inline, virtual]

Implements EMAN::Aligner.

Definition at line 1471 of file aligner.h.

                        {
                                return "Refines a preliminary 3D alignment using a simplex algorithm. Subpixel precision.";
                        }
virtual string EMAN::Refine3DAlignerQuaternion::get_name ( ) const [inline, virtual]

Get the Aligner's name.

Each Aligner is identified by a unique name.

Returns:
The Aligner's name.

Implements EMAN::Aligner.

Definition at line 1466 of file aligner.h.

References NAME.

                        {
                                return NAME;
                        }
virtual TypeDict EMAN::Refine3DAlignerQuaternion::get_param_types ( ) const [inline, virtual]

Implements EMAN::Aligner.

Definition at line 1481 of file aligner.h.

References EMAN::EMObject::FLOAT, EMAN::EMObject::INT, EMAN::TypeDict::put(), and EMAN::EMObject::TRANSFORM.

                        {
                                TypeDict d;
                                d.put("xform.align3d", EMObject::TRANSFORM,"The Transform storing the starting guess. If unspecified the identity matrix is used");
                                d.put("stepx", EMObject::FLOAT, "The initial simplex step size in x. Default is 1");
                                d.put("stepy", EMObject::FLOAT, "The initial simplex step size in y. Default is 1");
                                d.put("stepz", EMObject::FLOAT, "The initial simplex step size in z. Default is 1." );
                                d.put("stepn0", EMObject::FLOAT, "The initial simplex step size in the first quaternion vecotr component. Default is 1." );
                                d.put("stepn1", EMObject::FLOAT, "The initial simplex step size in the second quaternion vecotr component. Default is 1." );
                                d.put("stepn2", EMObject::FLOAT, "The initial simplex step size in the third quaternion vecotr component. Default is 1." );
                                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.");
                                d.put("precision", EMObject::FLOAT, "The precision which, if achieved, can stop the iterative refinement before reaching the maximum iterations. Default is 0.01." );
                                d.put("maxiter", EMObject::INT, "The maximum number of iterations that can be performed by the Simplex minimizer. Default is 100.");
                                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.");
                                return d;
                        }
static Aligner* EMAN::Refine3DAlignerQuaternion::NEW ( ) [inline, static]

Definition at line 1476 of file aligner.h.

                        {
                                return new Refine3DAlignerQuaternion();
                        }

Member Data Documentation

const string Refine3DAlignerQuaternion::NAME = "refine_3d" [static]

Definition at line 1498 of file aligner.h.

Referenced by get_name().


The documentation for this class was generated from the following files: