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

static AlignerNEW ()

Static Public Attributes

static 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 1536 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 1545 of file aligner.h.

References align().

01546                         {
01547                                 return align(this_img, to_img, "sqeuclidean", Dict());
01548                         }

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 2433 of file aligner.cpp.

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

Referenced by align().

02434 {
02435 
02436         vector<Dict> alis = xform_align_nbest(this_img,to,1,cmp_name,cmp_params);
02437 
02438         Dict t;
02439         Transform* tr = (Transform*) alis[0]["xform.align3d"];
02440         t["transform"] = tr;
02441         EMData* soln = this_img->process("xform",t);
02442         soln->set_attr("xform.align3d",tr);
02443         delete tr; tr = 0;
02444 
02445         return soln;
02446 
02447 }

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

Implements EMAN::Aligner.

Definition at line 1560 of file aligner.h.

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

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 1555 of file aligner.h.

References NAME.

01556                         {
01557                                 return NAME;
01558                         }

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

Implements EMAN::Aligner.

Definition at line 1570 of file aligner.h.

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

01571                         {
01572                                 TypeDict d;
01573                                 d.put("sym", EMObject::STRING,"The symmtery to use as the basis of the spherical sampling. Default is c1 (asymmetry).");
01574                                 d.put("orientgen", EMObject::STRING,"Advanced. The orientation generation strategy. Default is eman");
01575                                 d.put("delta", EMObject::FLOAT,"Angle the separates points on the sphere. This is exclusive of the \'n\' paramater. Default is 10");
01576                                 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");
01577                                 d.put("dphi", EMObject::FLOAT,"The angle increment in the phi direction. Default is 10");
01578                                 d.put("phi0", EMObject::FLOAT,"Lower bound for phi. Default it 0");
01579                                 d.put("phi1", EMObject::FLOAT,"Upper bound for phi. Default it 360");
01580                                 d.put("dotrans", EMObject::BOOL,"Do a translational search. Default is True(1)");
01581                                 d.put("fsrotate", EMObject::BOOL,"Do rotations in Fourier space");
01582                                 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.");
01583                                 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.");
01584                                 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.");
01585                                 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");
01586                                 d.put("verbose", EMObject::BOOL,"Turn this on to have useful information printed to standard out.");
01587                                 return d;
01588                         }

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

Definition at line 1565 of file aligner.h.

01566                         {
01567                                 return new RT3DSphereAligner();
01568                         }

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 2449 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::Symmetry3D::gen_orientations(), 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::Aligner::params, phi, EMAN::EMData::process(), EMAN::EMData::process_inplace(), EMAN::Dict::set_default(), EMAN::Transform::set_trans(), sqrt(), and t.

Referenced by align().

02449                                                                                                                                                                  {
02450 
02451         if ( this_img->get_ndim() != 3 || to->get_ndim() != 3 ) {
02452                 throw ImageDimensionException("This aligner only works for 3D images");
02453         }
02454 
02455         int searchx = 0;
02456         int searchy = 0;
02457         int searchz = 0;
02458          
02459         bool dotrans = params.set_default("dotrans",1);
02460         bool fsrotate = params.set_default("fsrotate",0);
02461         if (params.has_key("search")) {
02462                 vector<string> check;
02463                 check.push_back("searchx");
02464                 check.push_back("searchy");
02465                 check.push_back("searchz");
02466                 for(vector<string>::const_iterator cit = check.begin(); cit != check.end(); ++cit) {
02467                         if (params.has_key(*cit)) throw InvalidParameterException("The search parameter is mutually exclusive of the searchx, searchy, and searchz parameters");
02468                 }
02469                 int search  = params["search"];
02470                 searchx = search;
02471                 searchy = search;
02472                 searchz = search;
02473         } else {
02474                 searchx = params.set_default("searchx",3);
02475                 searchy = params.set_default("searchy",3);
02476                 searchz = params.set_default("searchz",3);
02477         }
02478 
02479         float lphi = params.set_default("phi0",0.0f);
02480         float uphi = params.set_default("phi1",360.0f);
02481         float dphi = params.set_default("dphi",10.f);
02482         float threshold = params.set_default("threshold",0.f);
02483         if (threshold < 0.0f) throw InvalidParameterException("The threshold parameter must be greater than or equal to zero");
02484         bool verbose = params.set_default("verbose",false);
02485         
02486         //in case we arre aligning tomos
02487         Dict altered_cmp_params(cmp_params);
02488         if (cmp_name == "ccc.tomo") {
02489                 altered_cmp_params.set_default("searchx", searchx);
02490                 altered_cmp_params.set_default("searchy", searchy);
02491                 altered_cmp_params.set_default("searchz", searchz);
02492                 altered_cmp_params.set_default("norm", true);
02493         }
02494 
02495         vector<Dict> solns;
02496         if (nsoln == 0) return solns; // What was the user thinking?
02497         for (unsigned int i = 0; i < nsoln; ++i ) {
02498                 Dict d;
02499                 d["score"] = 1.e24;
02500                 Transform t; // identity by default
02501                 d["xform.align3d"] = &t; // deep copy is going on here
02502                 solns.push_back(d);
02503         }
02504 
02505         Dict d;
02506         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
02507         if ( params.has_key("delta") && params.has_key("n") ) {
02508                 throw InvalidParameterException("The delta and n parameters are mutually exclusive in the RT3DSphereAligner aligner");
02509         } else if ( params.has_key("n") ) {
02510                 d["n"] = params["n"];
02511         } else {
02512                 // If they didn't specify either then grab the default delta - if they did supply delta we're still safe doing this
02513                 d["delta"] = params.set_default("delta",10.f);
02514         }
02515 
02516         if ((string)params.set_default("orientgen","eman")=="eman") d["perturb"]=0;
02517         Symmetry3D* sym = Factory<Symmetry3D>::get((string)params.set_default("sym","c1"));
02518         vector<Transform> transforms = sym->gen_orientations((string)params.set_default("orientgen","eman"),d);
02519 
02520         bool tomography = (cmp_name == "ccc.tomo") ? 1 : 0;
02521         
02522         //precompute fixed FT, saves a LOT of time!!!
02523         EMData * this_imgfft = 0;
02524         if(dotrans || tomography){
02525                 this_imgfft = this_img->do_fft();
02526         }
02527         EMData * to_fft = 0;
02528         if(fsrotate){
02529                 to_fft = to->do_fft();
02530         }
02531         
02532         
02533 #ifdef EMAN2_USING_CUDA 
02534         if(EMData::usecuda == 1) {
02535                 cout << "Using CUDA for 3D alignment" << endl;
02536                 if(!to->getcudarodata()) to->copy_to_cudaro(); // Safer call
02537                 if(!this_img->getcudarwdata()) this_img->copy_to_cuda();
02538                 if(this_imgfft) this_imgfft->copy_to_cuda();
02539         }
02540 #endif
02541 
02542         Transform trans = Transform();
02543         Cmp* c = Factory <Cmp>::get(cmp_name, cmp_params);
02544         
02545         bool use_cpu = true;
02546         for(vector<Transform>::const_iterator trans_it = transforms.begin(); trans_it != transforms.end(); trans_it++) {
02547                 Dict params = trans_it->get_params("eman");
02548                 
02549                 if (verbose) {
02550                         float alt = params["alt"];
02551                         float az = params["az"];
02552                         cout << "Trying angle alt: " << alt << " az: " << az << endl;
02553                 }
02554 
02555                 for( float phi = lphi; phi < uphi; phi += dphi ) { 
02556                         params["phi"] = phi;
02557                         Transform t(params);
02558                         
02559                         EMData* transformed;
02560                         if(fsrotate){
02561                                 transformed = to_fft->process("rotateinfs",Dict("transform",&t));
02562                         } else {
02563                                 transformed = to->process("xform",Dict("transform",&t));
02564                         }
02565                                 
02566                         //need to do things a bit diffrent if we want to compare two tomos
02567                         float best_score = 0.0f;
02568                         // Dotrans is effectievly ignored for tomography
02569                         if(dotrans || tomography){
02570                                 EMData* ccf = transformed->calc_ccf(this_imgfft);
02571 #ifdef EMAN2_USING_CUDA 
02572                                 if(EMData::usecuda == 1){
02573                                         // I use the following code rather than ccc.tomo to avoid doing two CCCs
02574                                         use_cpu = false;
02575                                         CudaPeakInfo* data = calc_max_location_wrap_cuda(ccf->getcudarwdata(), ccf->get_xsize(), ccf->get_ysize(), ccf->get_zsize(), searchx, searchy, searchz);
02576                                         trans.set_trans((float)-data->px, (float)-data->py, (float)-data->pz);
02577                                         t = trans*t;    //composite transform to reflect the fact that we have done a rotation first and THEN a transformation
02578                                         if (tomography) {
02579                                                 float2 stats = get_stats_cuda(ccf->getcudarwdata(), ccf->get_xsize(), ccf->get_ysize(), ccf->get_zsize());
02580                                                 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
02581                                         } else {
02582                                                 best_score = -data->peak;
02583                                         }
02584                                         delete data;
02585                                 }
02586 #endif
02587                                 if(use_cpu){
02588                                         // I use the following code rather than ccc.tomo to avoid doing two CCCs
02589                                         if(tomography) ccf->process_inplace("normalize");
02590                                         IntPoint point = ccf->calc_max_location_wrap(searchx,searchy,searchz);
02591                                         trans.set_trans((float)-point[0], (float)-point[1], (float)-point[2]);
02592                                         t = trans*t;    //composite transform to reflect the fact that we have done a rotation first and THEN a transformation
02593                                         best_score = -ccf->get_value_at_wrap(point[0], point[1], point[2]);
02594                                 }
02595                                 delete ccf; ccf =0;
02596                                 delete transformed; transformed = 0;// this is to stop a mem leak
02597                         }
02598 
02599                         if(!tomography){
02600                                 if(!transformed) transformed = to->process("xform",Dict("transform",&t));
02601                                 best_score = c->cmp(this_img,transformed);
02602                                 delete transformed; transformed = 0;
02603                         }
02604 
02605                         unsigned int j = 0;
02606                         //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;
02607                         for ( vector<Dict>::iterator it = solns.begin(); it != solns.end(); ++it, ++j ) {
02608                                 if ( (float)(*it)["score"] > best_score ) { // Note greater than - EMAN2 preferes minimums as a matter of policy
02609                                         vector<Dict>::reverse_iterator rit = solns.rbegin();
02610                                         copy(rit+1,solns.rend()-j,rit);
02611                                         Dict& d = (*it);
02612                                         d["score"] = best_score;
02613                                         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)
02614                                         d["xform.align3d"] = &t; // deep copy is going on here
02615                                         break;
02616                                 }
02617                         }
02618 
02619                 }
02620         }
02621         
02622         if(this_imgfft) {delete this_imgfft; this_imgfft = 0;}
02623         if(fsrotate){delete to_fft;}
02624         if(sym!=0) delete sym;
02625         if (c != 0) delete c;
02626         
02627         return solns;
02628 
02629 }


Member Data Documentation

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

Definition at line 1590 of file aligner.h.

Referenced by get_name().


The documentation for this class was generated from the following files:
Generated on Thu May 3 10:08:51 2012 for EMAN2 by  doxygen 1.4.7