Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

EMAN::RT3DSphereAligner Class Reference
[a function or class that is CUDA enabled]

3D rotational and translational alignment using spherical sampling, can reduce the search space based on symmetry. More...

#include <aligner.h>

Inheritance diagram for EMAN::RT3DSphereAligner:

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

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
 See Aligner comments for more details.
virtual EMDataalign (EMData *this_img, EMData *to_img) const
 See Aligner comments for more details.
virtual vector< Dictxform_align_nbest (EMData *this_img, EMData *to_img, const unsigned int nsoln, const string &cmp_name, const Dict &cmp_params) const
 See Aligner comments for more details.
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

AlignerNEW ()

Static Public Attributes

const string NAME = "rotate_translate_3d"

Detailed Description

3D rotational and translational alignment using spherical sampling, can reduce the search space based on symmetry.

can also make use of different OrientationGenerators (random, for example) 2X more efficient than the RT3DGridAligner The aligner actually aligns the reference to the 'moving' and then takes the inverse of the resulting transform. This is necessary because, in the case of symmetry (i.e. not c1), the reference symmetry axis must be aligned to the EMAN2 symmetry axis, restricting the search space to the asymmetrical points on a sphere. We note that if the reference symmetry axis is not aligned to the EMAN2 symmetry axis, the best thing is to do a full search (i.e. specify sym='c1') unless you really know what you are doing!

Parameters:
sym The symmtery to use as the basis of the spherical sampling
orietgen Advanced. The orientation generation strategy
delta Angle the separates points on the sphere. This is exclusive of the 'n' paramater
n An alternative to the delta argument, this is the number of points you want generated on the sphere
dphi The angle increment in the phi direction
lphi Lower bound for the phi direction
uphi Upper bound for the phi direction
dotrans Do a translational search
search The maximum length of the detectable translational shift - if you supply this parameter you can not supply the maxshiftx, maxshifty or maxshiftz parameters. Each approach is mutually exclusive
searchx The maximum length of the detectable translational shift in the x direction- if you supply this parameter you can not supply the maxshift parameters
searchy The maximum length of the detectable translational shift in the y direction- if you supply this parameter you can not supply the maxshift parameters
searchz The maximum length of the detectable translational shift in the z direction- if you supply this parameter you can not supply the maxshift parameters
verbose Turn this on to have useful information printed to standard out
Author:
John Flanagan and David Woolford
Date:
Feb 2011

Definition at line 1608 of file aligner.h.


Member Function Documentation

virtual EMData* EMAN::RT3DSphereAligner::align EMData this_img,
EMData to_img
const [inline, virtual]
 

See Aligner comments for more details.

Implements EMAN::Aligner.

Definition at line 1617 of file aligner.h.

References align().

01618                         {
01619                                 return align(this_img, to_img, "sqeuclidean", Dict());
01620                         }

EMData * RT3DSphereAligner::align EMData this_img,
EMData to_img,
const string &  cmp_name = "sqeuclidean",
const Dict cmp_params = Dict()
const [virtual]
 

See Aligner comments for more details.

Implements EMAN::Aligner.

Definition at line 2607 of file aligner.cpp.

References EMAN::EMData::process(), EMAN::EMData::set_attr(), t, and xform_align_nbest().

02608 {
02609 
02610         vector<Dict> alis = xform_align_nbest(this_img,to,1,cmp_name,cmp_params);
02611 
02612         Dict t;
02613         Transform* tr = (Transform*) alis[0]["xform.align3d"];
02614         t["transform"] = tr;
02615         EMData* soln = this_img->process("xform",t);
02616         soln->set_attr("xform.align3d",tr);
02617         delete tr; tr = 0;
02618 
02619         return soln;
02620 
02621 }

virtual string EMAN::RT3DSphereAligner::get_desc  )  const [inline, virtual]
 

Implements EMAN::Aligner.

Definition at line 1632 of file aligner.h.

01633                         {
01634                                 return "3D rotational and translational alignment using spherical sampling. Can reduce the search space if symmetry is supplied";
01635                         }

virtual string EMAN::RT3DSphereAligner::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 1627 of file aligner.h.

01628                         {
01629                                 return NAME;
01630                         }

virtual TypeDict EMAN::RT3DSphereAligner::get_param_types  )  const [inline, virtual]
 

Implements EMAN::Aligner.

Definition at line 1642 of file aligner.h.

References EMAN::TypeDict::put().

01643                         {
01644                                 TypeDict d;
01645                                 d.put("sym", EMObject::STRING,"The symmtery to use as the basis of the spherical sampling. Default is c1 (asymmetry).");
01646                                 d.put("orientgen", EMObject::STRING,"Advanced. The orientation generation strategy. Default is eman");
01647                                 d.put("delta", EMObject::FLOAT,"Angle the separates points on the sphere. This is exclusive of the \'n\' paramater. Default is 10");
01648                                 d.put("n", EMObject::INT,"An alternative to the delta argument, this is the number of points you want generated on the sphere. Default is OFF");
01649                                 d.put("dphi", EMObject::FLOAT,"The angle increment in the phi direction. Default is 10");
01650                                 d.put("phi0", EMObject::FLOAT,"Lower bound for phi. Default it 0");
01651                                 d.put("phi1", EMObject::FLOAT,"Upper bound for phi. Default it 360");
01652                                 d.put("dotrans", EMObject::BOOL,"Do a translational search. Default is True(1)");
01653                                 d.put("search", EMObject::INT,"The maximum length of the detectable translational shift - if you supply this parameter you can not supply the maxshiftx, maxshifty or maxshiftz parameters. Each approach is mutually exclusive.");
01654                                 d.put("searchx", EMObject::INT,"The maximum length of the detectable translational shift in the x direction- if you supply this parameter you can not supply the maxshift parameters. Default is 3.");
01655                                 d.put("searchy", EMObject::INT,"The maximum length of the detectable translational shift in the y direction- if you supply this parameter you can not supply the maxshift parameters. Default is 3.");
01656                                 d.put("searchz", EMObject::INT,"The maximum length of the detectable translational shift in the z direction- if you supply this parameter you can not supply the maxshift parameters. Default is 3");
01657                                 d.put("initxform", EMObject::TRANSFORM,"The Transform storing the starting position. If unspecified the identity matrix is used");
01658                                 d.put("verbose", EMObject::BOOL,"Turn this on to have useful information printed to standard out.");
01659                                 return d;
01660                         }

Aligner* EMAN::RT3DSphereAligner::NEW  )  [inline, static]
 

Definition at line 1637 of file aligner.h.

01638                         {
01639                                 return new RT3DSphereAligner();
01640                         }

vector< Dict > RT3DSphereAligner::xform_align_nbest EMData this_img,
EMData to_img,
const unsigned int  nsoln,
const string &  cmp_name,
const Dict cmp_params
const [virtual]
 

See Aligner comments for more details.

Reimplemented from EMAN::Aligner.

Definition at line 2623 of file aligner.cpp.

References EMAN::EMData::calc_ccf(), EMAN::EMData::calc_max_location_wrap(), calc_max_location_wrap_cuda(), EMAN::Cmp::cmp(), copy(), data, EMAN::EMData::do_fft(), EMAN::Dict::end(), EMAN::Symmetry3D::gen_orientations(), EMAN::Factory< T >::get(), EMAN::EMData::get_ndim(), get_stats_cuda(), EMAN::EMData::get_value_at_wrap(), EMAN::EMData::get_xsize(), EMAN::EMData::get_ysize(), EMAN::EMData::get_zsize(), EMAN::Dict::has_key(), ImageDimensionException, InvalidParameterException, EMAN::Transform::invert(), CudaPeakInfo::peak, phi, EMAN::EMData::process(), EMAN::EMData::process_inplace(), CudaPeakInfo::px, CudaPeakInfo::py, CudaPeakInfo::pz, EMAN::Dict::set_default(), EMAN::Transform::set_trans(), sqrt(), and t.

Referenced by align().

02623                                                                                                                                                                  {
02624 
02625         if ( this_img->get_ndim() != 3 || to->get_ndim() != 3 ) {
02626                 throw ImageDimensionException("This aligner only works for 3D images");
02627         }
02628 
02629         int searchx = 0;
02630         int searchy = 0;
02631         int searchz = 0;
02632          
02633         bool dotrans = params.set_default("dotrans",1);
02634         if (params.has_key("search")) {
02635                 vector<string> check;
02636                 check.push_back("searchx");
02637                 check.push_back("searchy");
02638                 check.push_back("searchz");
02639                 for(vector<string>::const_iterator cit = check.begin(); cit != check.end(); ++cit) {
02640                         if (params.has_key(*cit)) throw InvalidParameterException("The search parameter is mutually exclusive of the searchx, searchy, and searchz parameters");
02641                 }
02642                 int search  = params["search"];
02643                 searchx = search;
02644                 searchy = search;
02645                 searchz = search;
02646         } else {
02647                 searchx = params.set_default("searchx",3);
02648                 searchy = params.set_default("searchy",3);
02649                 searchz = params.set_default("searchz",3);
02650         }
02651 
02652         Transform* initxform;
02653         if (params.has_key("initxform") ) {
02654                 // Unlike the 2d refine aligner, this class doesn't require the starting transform's
02655                 // parameters to form the starting guess. Instead the Transform itself
02656                 // is perturbed carefully (using quaternion rotation) to overcome problems that arise
02657                 // when you use orthogonally-based Euler angles
02658                 initxform = params["initxform"];
02659         }else {
02660                 initxform = new Transform(); // is the identity
02661         }
02662         
02663         float lphi = params.set_default("phi0",0.0f);
02664         float uphi = params.set_default("phi1",360.0f);
02665         float dphi = params.set_default("dphi",10.f);
02666         float threshold = params.set_default("threshold",0.f);
02667         if (threshold < 0.0f) throw InvalidParameterException("The threshold parameter must be greater than or equal to zero");
02668         bool verbose = params.set_default("verbose",false);
02669         
02670         //in case we arre aligning tomos
02671         Dict altered_cmp_params(cmp_params);
02672         if (cmp_name == "ccc.tomo") {
02673                 altered_cmp_params.set_default("searchx", searchx);
02674                 altered_cmp_params.set_default("searchy", searchy);
02675                 altered_cmp_params.set_default("searchz", searchz);
02676                 altered_cmp_params.set_default("norm", true);
02677         }
02678 
02679         vector<Dict> solns;
02680         if (nsoln == 0) return solns; // What was the user thinking?
02681         for (unsigned int i = 0; i < nsoln; ++i ) {
02682                 Dict d;
02683                 d["score"] = 1.e24;
02684                 Transform t; // identity by default
02685                 d["xform.align3d"] = &t; // deep copy is going on here
02686                 solns.push_back(d);
02687         }
02688 
02689         Dict d;
02690         d["inc_mirror"] = true; // This should probably always be true for 3D case. If it ever changes we might have to make inc_mirror a parameter
02691         if ( params.has_key("delta") && params.has_key("n") ) {
02692                 throw InvalidParameterException("The delta and n parameters are mutually exclusive in the RT3DSphereAligner aligner");
02693         } else if ( params.has_key("n") ) {
02694                 d["n"] = params["n"];
02695         } else {
02696                 // If they didn't specify either then grab the default delta - if they did supply delta we're still safe doing this
02697                 d["delta"] = params.set_default("delta",10.f);
02698         }
02699 
02700         if ((string)params.set_default("orientgen","eman")=="eman") d["perturb"]=0;
02701         Symmetry3D* sym = Factory<Symmetry3D>::get((string)params.set_default("sym","c1"));
02702         vector<Transform> transforms = sym->gen_orientations((string)params.set_default("orientgen","eman"),d);
02703 
02704         bool tomography = (cmp_name == "ccc.tomo") ? 1 : 0;
02705         
02706         //precompute fixed FT, saves a LOT of time!!!
02707         EMData * this_imgfft = 0;
02708         if(dotrans || tomography){
02709                 this_imgfft = this_img->do_fft();
02710         }
02711         
02712 #ifdef EMAN2_USING_CUDA 
02713         if(EMData::usecuda == 1) {
02714                 cout << "Using CUDA for 3D alignment" << endl;
02715                 if(!to->getcudarodata()) to->copy_to_cudaro(); // Safer call
02716                 if(!this_img->getcudarwdata()) this_img->copy_to_cuda();
02717                 if(this_imgfft) this_imgfft->copy_to_cuda();
02718         }
02719 #endif
02720 
02721         Transform trans = Transform();
02722         Cmp* c = Factory <Cmp>::get(cmp_name, cmp_params);
02723         
02724         bool use_cpu = true;
02725         for(vector<Transform>::const_iterator trans_it = transforms.begin(); trans_it != transforms.end(); trans_it++) {
02726                 Dict params = trans_it->get_params("eman");
02727                 
02728                 if (verbose) {
02729                         float alt = params["alt"];
02730                         float az = params["az"];
02731                         cout << "Trying angle alt: " << alt << " az: " << az << endl;
02732                 }
02733 
02734                 for( float phi = lphi; phi < uphi; phi += dphi ) { 
02735                         params["phi"] = phi;
02736                         Transform t(params);
02737                         t = t*(*initxform);
02738                         
02739                         EMData* transformed;
02740                         transformed = to->process("xform",Dict("transform",&t));
02741                                 
02742                         //need to do things a bit diffrent if we want to compare two tomos
02743                         float best_score = 0.0f;
02744                         // Dotrans is effectievly ignored for tomography
02745                         if(dotrans || tomography){
02746                                 EMData* ccf = transformed->calc_ccf(this_imgfft);
02747 #ifdef EMAN2_USING_CUDA 
02748                                 if(EMData::usecuda == 1){
02749                                         // I use the following code rather than ccc.tomo to avoid doing two CCCs
02750                                         use_cpu = false;
02751                                         CudaPeakInfo* data = calc_max_location_wrap_cuda(ccf->getcudarwdata(), ccf->get_xsize(), ccf->get_ysize(), ccf->get_zsize(), searchx, searchy, searchz);
02752                                         trans.set_trans((float)-data->px, (float)-data->py, (float)-data->pz);
02753                                         t = trans*t;    //composite transform to reflect the fact that we have done a rotation first and THEN a transformation
02754                                         if (tomography) {
02755                                                 float2 stats = get_stats_cuda(ccf->getcudarwdata(), ccf->get_xsize(), ccf->get_ysize(), ccf->get_zsize());
02756                                                 best_score = -(data->peak - stats.x)/sqrt(stats.y); // Normalize, this is better than calling the norm processor since we only need to normalize one point
02757                                         } else {
02758                                                 best_score = -data->peak;
02759                                         }
02760                                         delete data;
02761                                 }
02762 #endif
02763                                 if(use_cpu){
02764                                         // I use the following code rather than ccc.tomo to avoid doing two CCCs
02765                                         if(tomography) ccf->process_inplace("normalize");
02766                                         IntPoint point = ccf->calc_max_location_wrap(searchx,searchy,searchz);
02767                                         trans.set_trans((float)-point[0], (float)-point[1], (float)-point[2]);
02768                                         t = trans*t;    //composite transform to reflect the fact that we have done a rotation first and THEN a transformation
02769                                         best_score = -ccf->get_value_at_wrap(point[0], point[1], point[2]);
02770                                 }
02771                                 delete ccf; ccf =0;
02772                                 delete transformed; transformed = 0;// this is to stop a mem leak
02773                         }
02774 
02775                         if(!tomography){
02776                                 if(!transformed) transformed = to->process("xform",Dict("transform",&t));
02777                                 best_score = c->cmp(this_img,transformed);
02778                                 delete transformed; transformed = 0;
02779                         }
02780 
02781                         unsigned int j = 0;
02782                         //cout << "alt " <<float(t.get_rotation("eman").get("alt")) << " az " << float(t.get_rotation("eman").get("az")) << " phi " << float(t.get_rotation("eman").get("phi")) << endl;
02783                         for ( vector<Dict>::iterator it = solns.begin(); it != solns.end(); ++it, ++j ) {
02784                                 if ( (float)(*it)["score"] > best_score ) { // Note greater than - EMAN2 preferes minimums as a matter of policy
02785                                         vector<Dict>::reverse_iterator rit = solns.rbegin();
02786                                         copy(rit+1,solns.rend()-j,rit);
02787                                         Dict& d = (*it);
02788                                         d["score"] = best_score;
02789                                         t.invert(); //We actually moved the ref onto the moving, so we need to invert to do the opposite(this is done b/c the ref is aligned to the sym axis, whereas the mvoing is not)
02790                                         d["xform.align3d"] = &t; // deep copy is going on here
02791                                         break;
02792                                 }
02793                         }
02794 
02795                 }
02796         }
02797         
02798         if(this_imgfft) {delete this_imgfft; this_imgfft = 0;}
02799         if(sym!=0) delete sym;
02800         if (c != 0) delete c;
02801         
02802         return solns;
02803 
02804 }


Member Data Documentation

const string RT3DSphereAligner::NAME = "rotate_translate_3d" [static]
 

Definition at line 85 of file aligner.cpp.


The documentation for this class was generated from the following files:
Generated on Tue Jun 11 13:47:49 2013 for EMAN2 by  doxygen 1.3.9.1