#include <aligner.h>
Inheritance diagram for EMAN::RT3DSphereAligner:
Public Member Functions | |
virtual EMData * | align (EMData *this_img, EMData *to_img, const string &cmp_name="sqeuclidean", const Dict &cmp_params=Dict()) const |
See Aligner comments for more details. | |
virtual EMData * | align (EMData *this_img, EMData *to_img) const |
See Aligner comments for more details. | |
virtual vector< Dict > | xform_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 Aligner * | NEW () |
Static Public Attributes | |
static const string | NAME = "rotate_translate_3d" |
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!
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 |
Definition at line 1608 of file aligner.h.
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().
Referenced by align().
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] |
virtual TypeDict EMAN::RT3DSphereAligner::get_param_types | ( | ) | const [inline, virtual] |
Implements EMAN::Aligner.
Definition at line 1642 of file aligner.h.
References EMAN::EMObject::BOOL, EMAN::EMObject::FLOAT, EMAN::EMObject::INT, EMAN::TypeDict::put(), EMAN::EMObject::STRING, and EMAN::EMObject::TRANSFORM.
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 }
static Aligner* EMAN::RT3DSphereAligner::NEW | ( | ) | [inline, static] |
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::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().
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 }
const string RT3DSphereAligner::NAME = "rotate_translate_3d" [static] |