#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 1602 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 2591 of file aligner.cpp.
References EMAN::EMData::process(), EMAN::EMData::set_attr(), t, and xform_align_nbest().
Referenced by align().
02592 { 02593 02594 vector<Dict> alis = xform_align_nbest(this_img,to,1,cmp_name,cmp_params); 02595 02596 Dict t; 02597 Transform* tr = (Transform*) alis[0]["xform.align3d"]; 02598 t["transform"] = tr; 02599 EMData* soln = this_img->process("xform",t); 02600 soln->set_attr("xform.align3d",tr); 02601 delete tr; tr = 0; 02602 02603 return soln; 02604 02605 }
virtual string EMAN::RT3DSphereAligner::get_desc | ( | ) | const [inline, virtual] |
Implements EMAN::Aligner.
Definition at line 1626 of file aligner.h.
01627 { 01628 return "3D rotational and translational alignment using spherical sampling. Can reduce the search space if symmetry is supplied"; 01629 }
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 1636 of file aligner.h.
References EMAN::EMObject::BOOL, EMAN::EMObject::FLOAT, EMAN::EMObject::INT, EMAN::TypeDict::put(), EMAN::EMObject::STRING, and EMAN::EMObject::TRANSFORM.
01637 { 01638 TypeDict d; 01639 d.put("sym", EMObject::STRING,"The symmtery to use as the basis of the spherical sampling. Default is c1 (asymmetry)."); 01640 d.put("orientgen", EMObject::STRING,"Advanced. The orientation generation strategy. Default is eman"); 01641 d.put("delta", EMObject::FLOAT,"Angle the separates points on the sphere. This is exclusive of the \'n\' paramater. Default is 10"); 01642 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"); 01643 d.put("dphi", EMObject::FLOAT,"The angle increment in the phi direction. Default is 10"); 01644 d.put("phi0", EMObject::FLOAT,"Lower bound for phi. Default it 0"); 01645 d.put("phi1", EMObject::FLOAT,"Upper bound for phi. Default it 360"); 01646 d.put("dotrans", EMObject::BOOL,"Do a translational search. Default is True(1)"); 01647 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."); 01648 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."); 01649 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."); 01650 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"); 01651 d.put("initxform", EMObject::TRANSFORM,"The Transform storing the starting position. If unspecified the identity matrix is used"); 01652 d.put("verbose", EMObject::BOOL,"Turn this on to have useful information printed to standard out."); 01653 return d; 01654 }
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 2607 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().
02607 { 02608 02609 if ( this_img->get_ndim() != 3 || to->get_ndim() != 3 ) { 02610 throw ImageDimensionException("This aligner only works for 3D images"); 02611 } 02612 02613 int searchx = 0; 02614 int searchy = 0; 02615 int searchz = 0; 02616 02617 bool dotrans = params.set_default("dotrans",1); 02618 if (params.has_key("search")) { 02619 vector<string> check; 02620 check.push_back("searchx"); 02621 check.push_back("searchy"); 02622 check.push_back("searchz"); 02623 for(vector<string>::const_iterator cit = check.begin(); cit != check.end(); ++cit) { 02624 if (params.has_key(*cit)) throw InvalidParameterException("The search parameter is mutually exclusive of the searchx, searchy, and searchz parameters"); 02625 } 02626 int search = params["search"]; 02627 searchx = search; 02628 searchy = search; 02629 searchz = search; 02630 } else { 02631 searchx = params.set_default("searchx",3); 02632 searchy = params.set_default("searchy",3); 02633 searchz = params.set_default("searchz",3); 02634 } 02635 02636 Transform* initxform; 02637 if (params.has_key("initxform") ) { 02638 // Unlike the 2d refine aligner, this class doesn't require the starting transform's 02639 // parameters to form the starting guess. Instead the Transform itself 02640 // is perturbed carefully (using quaternion rotation) to overcome problems that arise 02641 // when you use orthogonally-based Euler angles 02642 initxform = params["initxform"]; 02643 }else { 02644 initxform = new Transform(); // is the identity 02645 } 02646 02647 float lphi = params.set_default("phi0",0.0f); 02648 float uphi = params.set_default("phi1",360.0f); 02649 float dphi = params.set_default("dphi",10.f); 02650 float threshold = params.set_default("threshold",0.f); 02651 if (threshold < 0.0f) throw InvalidParameterException("The threshold parameter must be greater than or equal to zero"); 02652 bool verbose = params.set_default("verbose",false); 02653 02654 //in case we arre aligning tomos 02655 Dict altered_cmp_params(cmp_params); 02656 if (cmp_name == "ccc.tomo") { 02657 altered_cmp_params.set_default("searchx", searchx); 02658 altered_cmp_params.set_default("searchy", searchy); 02659 altered_cmp_params.set_default("searchz", searchz); 02660 altered_cmp_params.set_default("norm", true); 02661 } 02662 02663 vector<Dict> solns; 02664 if (nsoln == 0) return solns; // What was the user thinking? 02665 for (unsigned int i = 0; i < nsoln; ++i ) { 02666 Dict d; 02667 d["score"] = 1.e24; 02668 Transform t; // identity by default 02669 d["xform.align3d"] = &t; // deep copy is going on here 02670 solns.push_back(d); 02671 } 02672 02673 Dict d; 02674 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 02675 if ( params.has_key("delta") && params.has_key("n") ) { 02676 throw InvalidParameterException("The delta and n parameters are mutually exclusive in the RT3DSphereAligner aligner"); 02677 } else if ( params.has_key("n") ) { 02678 d["n"] = params["n"]; 02679 } else { 02680 // If they didn't specify either then grab the default delta - if they did supply delta we're still safe doing this 02681 d["delta"] = params.set_default("delta",10.f); 02682 } 02683 02684 if ((string)params.set_default("orientgen","eman")=="eman") d["perturb"]=0; 02685 Symmetry3D* sym = Factory<Symmetry3D>::get((string)params.set_default("sym","c1")); 02686 vector<Transform> transforms = sym->gen_orientations((string)params.set_default("orientgen","eman"),d); 02687 02688 bool tomography = (cmp_name == "ccc.tomo") ? 1 : 0; 02689 02690 //precompute fixed FT, saves a LOT of time!!! 02691 EMData * this_imgfft = 0; 02692 if(dotrans || tomography){ 02693 this_imgfft = this_img->do_fft(); 02694 } 02695 02696 #ifdef EMAN2_USING_CUDA 02697 if(EMData::usecuda == 1) { 02698 cout << "Using CUDA for 3D alignment" << endl; 02699 if(!to->getcudarodata()) to->copy_to_cudaro(); // Safer call 02700 if(!this_img->getcudarwdata()) this_img->copy_to_cuda(); 02701 if(this_imgfft) this_imgfft->copy_to_cuda(); 02702 } 02703 #endif 02704 02705 Transform trans = Transform(); 02706 Cmp* c = Factory <Cmp>::get(cmp_name, cmp_params); 02707 02708 bool use_cpu = true; 02709 for(vector<Transform>::const_iterator trans_it = transforms.begin(); trans_it != transforms.end(); trans_it++) { 02710 Dict params = trans_it->get_params("eman"); 02711 02712 if (verbose) { 02713 float alt = params["alt"]; 02714 float az = params["az"]; 02715 cout << "Trying angle alt: " << alt << " az: " << az << endl; 02716 } 02717 02718 for( float phi = lphi; phi < uphi; phi += dphi ) { 02719 params["phi"] = phi; 02720 Transform t(params); 02721 t = t*(*initxform); 02722 02723 EMData* transformed; 02724 transformed = to->process("xform",Dict("transform",&t)); 02725 02726 //need to do things a bit diffrent if we want to compare two tomos 02727 float best_score = 0.0f; 02728 // Dotrans is effectievly ignored for tomography 02729 if(dotrans || tomography){ 02730 EMData* ccf = transformed->calc_ccf(this_imgfft); 02731 #ifdef EMAN2_USING_CUDA 02732 if(EMData::usecuda == 1){ 02733 // I use the following code rather than ccc.tomo to avoid doing two CCCs 02734 use_cpu = false; 02735 CudaPeakInfo* data = calc_max_location_wrap_cuda(ccf->getcudarwdata(), ccf->get_xsize(), ccf->get_ysize(), ccf->get_zsize(), searchx, searchy, searchz); 02736 trans.set_trans((float)-data->px, (float)-data->py, (float)-data->pz); 02737 t = trans*t; //composite transform to reflect the fact that we have done a rotation first and THEN a transformation 02738 if (tomography) { 02739 float2 stats = get_stats_cuda(ccf->getcudarwdata(), ccf->get_xsize(), ccf->get_ysize(), ccf->get_zsize()); 02740 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 02741 } else { 02742 best_score = -data->peak; 02743 } 02744 delete data; 02745 } 02746 #endif 02747 if(use_cpu){ 02748 // I use the following code rather than ccc.tomo to avoid doing two CCCs 02749 if(tomography) ccf->process_inplace("normalize"); 02750 IntPoint point = ccf->calc_max_location_wrap(searchx,searchy,searchz); 02751 trans.set_trans((float)-point[0], (float)-point[1], (float)-point[2]); 02752 t = trans*t; //composite transform to reflect the fact that we have done a rotation first and THEN a transformation 02753 best_score = -ccf->get_value_at_wrap(point[0], point[1], point[2]); 02754 } 02755 delete ccf; ccf =0; 02756 delete transformed; transformed = 0;// this is to stop a mem leak 02757 } 02758 02759 if(!tomography){ 02760 if(!transformed) transformed = to->process("xform",Dict("transform",&t)); 02761 best_score = c->cmp(this_img,transformed); 02762 delete transformed; transformed = 0; 02763 } 02764 02765 unsigned int j = 0; 02766 //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; 02767 for ( vector<Dict>::iterator it = solns.begin(); it != solns.end(); ++it, ++j ) { 02768 if ( (float)(*it)["score"] > best_score ) { // Note greater than - EMAN2 preferes minimums as a matter of policy 02769 vector<Dict>::reverse_iterator rit = solns.rbegin(); 02770 copy(rit+1,solns.rend()-j,rit); 02771 Dict& d = (*it); 02772 d["score"] = best_score; 02773 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) 02774 d["xform.align3d"] = &t; // deep copy is going on here 02775 break; 02776 } 02777 } 02778 02779 } 02780 } 02781 02782 if(this_imgfft) {delete this_imgfft; this_imgfft = 0;} 02783 if(sym!=0) delete sym; 02784 if (c != 0) delete c; 02785 02786 return solns; 02787 02788 }
const string RT3DSphereAligner::NAME = "rotate_translate_3d" [static] |