aligner.cpp

Go to the documentation of this file.
00001 
00005 /*
00006  * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
00007  * Copyright (c) 2000-2006 Baylor College of Medicine
00008  *
00009  * This software is issued under a joint BSD/GNU license. You may use the
00010  * source code in this file under either license. However, note that the
00011  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00012  * so you are responsible for compliance with the licenses of these packages
00013  * if you opt to use BSD licensing. The warranty disclaimer below holds
00014  * in either instance.
00015  *
00016  * This complete copyright notice must be included in any revised version of the
00017  * source code. Additional authorship citations may be added, but existing
00018  * author citations must be preserved.
00019  *
00020  * This program is free software; you can redistribute it and/or modify
00021  * it under the terms of the GNU General Public License as published by
00022  * the Free Software Foundation; either version 2 of the License, or
00023  * (at your option) any later version.
00024  *
00025  * This program is distributed in the hope that it will be useful,
00026  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00028  * GNU General Public License for more details.
00029  *
00030  * You should have received a copy of the GNU General Public License
00031  * along with this program; if not, write to the Free Software
00032  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00033  *
00034  * */
00035 #include "emfft.h"
00036 #include "cmp.h"
00037 #include "aligner.h"
00038 #include "emdata.h"
00039 #include "processor.h"
00040 #include "util.h"
00041 #include "symmetry.h"
00042 #include <gsl/gsl_multimin.h>
00043 #include "plugins/aligner_template.h"
00044 
00045 #ifdef EMAN2_USING_CUDA
00046         #include "cuda/cuda_processor.h"
00047         #include "cuda/cuda_cmp.h"
00048 #endif
00049 
00050 #ifdef SPARX_USING_CUDA
00051         #include <sparx/cuda/cuda_ccf.h>
00052 #endif
00053 
00054 #define EMAN2_ALIGNER_DEBUG 0
00055 
00056 using namespace EMAN;
00057 
00058 const string TranslationalAligner::NAME = "translational";
00059 const string RotationalAligner::NAME = "rotational";
00060 const string RotationalAlignerIterative::NAME = "rotational_iterative";
00061 const string RotatePrecenterAligner::NAME = "rotate_precenter";
00062 const string RotateTranslateAligner::NAME = "rotate_translate";
00063 const string RotateTranslateAlignerIterative::NAME = "rotate_translate_iterative";
00064 const string RotateTranslateAlignerPawel::NAME = "rotate_translate_resample";
00065 const string RotateTranslateBestAligner::NAME = "rotate_translate_best";
00066 const string RotateFlipAligner::NAME = "rotate_flip";
00067 const string RotateFlipAlignerIterative::NAME = "rotate_flip.iterative";
00068 const string RotateTranslateFlipAligner::NAME = "rotate_translate_flip";
00069 const string RotateTranslateFlipAlignerIterative::NAME = "rotate_translate_flip_iterative";
00070 const string RotateTranslateFlipAlignerPawel::NAME = "rotate_translate_flip_resample";
00071 const string RTFExhaustiveAligner::NAME = "rtf_exhaustive";
00072 const string RTFSlowExhaustiveAligner::NAME = "rtf_slow_exhaustive";
00073 const string RefineAligner::NAME = "refine";
00074 const string Refine3DAlignerGrid::NAME = "refine_3d_grid";
00075 const string Refine3DAlignerQuaternion::NAME = "refine_3d";
00076 const string RT3DGridAligner::NAME = "rotate_translate_3d_grid";
00077 const string RT3DSphereAligner::NAME = "rotate_translate_3d";
00078 const string RT3DSymmetryAligner::NAME = "rotate_symmetry_3d";
00079 const string FRM2DAligner::NAME = "frm2d";
00080 
00081 
00082 template <> Factory < Aligner >::Factory()
00083 {
00084         force_add<TranslationalAligner>();
00085         force_add<RotationalAligner>();
00086         force_add<RotationalAlignerIterative>();
00087         force_add<RotatePrecenterAligner>();
00088         force_add<RotateTranslateAligner>();
00089         force_add<RotateTranslateAlignerIterative>();
00090         force_add<RotateTranslateAlignerPawel>();
00091         force_add<RotateFlipAligner>();
00092         force_add<RotateFlipAlignerIterative>();
00093         force_add<RotateTranslateFlipAligner>();
00094         force_add<RotateTranslateFlipAlignerIterative>();
00095         force_add<RotateTranslateFlipAlignerPawel>();
00096         force_add<RTFExhaustiveAligner>();
00097         force_add<RTFSlowExhaustiveAligner>();
00098         force_add<RefineAligner>();
00099         force_add<Refine3DAlignerGrid>();
00100         force_add<Refine3DAlignerQuaternion>();
00101         force_add<RT3DGridAligner>();
00102         force_add<RT3DSphereAligner>();
00103         force_add<RT3DSymmetryAligner>();
00104         force_add<FRM2DAligner>();
00105 //      force_add<XYZAligner>();
00106 }
00107 
00108 vector<Dict> Aligner::xform_align_nbest(EMData *, EMData *, const unsigned int, const string &, const Dict&) const
00109 {
00110         vector<Dict> solns;
00111         return solns;
00112 }
00113 
00114 // Note, the translational aligner assumes that the correlation image
00115 // generated by the calc_ccf function is centered on the bottom left corner
00116 // That is, if you did at calc_cff using identical images, the
00117 // peak would be at 0,0
00118 EMData *TranslationalAligner::align(EMData * this_img, EMData *to,
00119                                         const string&, const Dict&) const
00120 {
00121         if (!this_img) {
00122                 return 0;
00123         }
00124 
00125         if (to && !EMUtil::is_same_size(this_img, to))
00126                 throw ImageDimensionException("Images must be the same size to perform translational alignment");
00127 
00128         EMData *cf = 0;
00129         int nx = this_img->get_xsize();
00130         int ny = this_img->get_ysize();
00131         int nz = this_img->get_zsize();
00132 
00133         int masked = params.set_default("masked",0);
00134         int useflcf = params.set_default("useflcf",0);
00135         bool use_cpu = true;
00136 
00137 #ifdef EMAN2_USING_CUDA
00138         if(EMData::usecuda == 1) {
00139                 if(!this_img->getcudarwdata()) this_img->copy_to_cuda();
00140                 if(to && !to->getcudarwdata()) to->copy_to_cuda();
00141                 if (masked) throw UnexpectedBehaviorException("Masked is not yet supported in CUDA");
00142                 if (useflcf) throw UnexpectedBehaviorException("Useflcf is not yet supported in CUDA");
00143                 //cout << "Translate on GPU" << endl;
00144                 use_cpu = false;
00145                 cf = this_img->calc_ccf(to);
00146         }
00147 #endif // EMAN2_USING_CUDA
00148         
00149         if (use_cpu) {
00150                 if (useflcf) cf = this_img->calc_flcf(to);
00151                 else cf = this_img->calc_ccf(to);
00152         }
00153         //return cf;
00154         // This is too expensive, esp for CUDA(we we can fix later
00155         if (masked) {
00156                 EMData *msk=this_img->process("threshold.notzero");
00157                 EMData *sqr=to->process("math.squared");
00158                 EMData *cfn=msk->calc_ccf(sqr);
00159                 cfn->process_inplace("math.sqrt");
00160                 float *d1=cf->get_data();
00161                 float *d2=cfn->get_data();
00162                 for (size_t i=0; i<(size_t)nx*ny*nz; ++i) {
00163                         if (d2[i]!=0) d1[i]/=d2[i];
00164                 }
00165                 cf->update();
00166                 delete msk;
00167                 delete sqr;
00168                 delete cfn;
00169         }
00170 
00171         int maxshiftx = params.set_default("maxshift",-1);
00172         int maxshifty = params["maxshift"];
00173         int maxshiftz = params["maxshift"];
00174         int nozero = params["nozero"];
00175 
00176         if (maxshiftx <= 0) {
00177                 maxshiftx = nx / 4;
00178                 maxshifty = ny / 4;
00179                 maxshiftz = nz / 4;
00180         }
00181 
00182         if (maxshiftx > nx / 2 - 1) maxshiftx = nx / 2 - 1;
00183         if (maxshifty > ny / 2 - 1)     maxshifty = ny / 2 - 1;
00184         if (maxshiftz > nz / 2 - 1) maxshiftz = nz / 2 - 1;
00185 
00186         if (nx == 1) maxshiftx = 0; // This is justhere for completeness really... plus it saves errors
00187         if (ny == 1) maxshifty = 0;
00188         if (nz == 1) maxshiftz = 0;
00189 
00190         // If nozero the portion of the image in the center (and its 8-connected neighborhood) is zeroed
00191         if (nozero) {
00192                 cf->zero_corner_circulant(1);
00193         }
00194         
00195         IntPoint peak;
00196 #ifdef EMAN2_USING_CUDA
00197         if (!use_cpu) {
00198                 if (nozero) throw UnexpectedBehaviorException("Nozero is not yet supported in CUDA");
00199                 CudaPeakInfo* data = calc_max_location_wrap_cuda(cf->getcudarwdata(), cf->get_xsize(), cf->get_ysize(), cf->get_zsize(), maxshiftx, maxshifty, maxshiftz);
00200                 peak = IntPoint(data->px,data->py,data->pz);
00201                 free(data);
00202         }
00203 #endif // EMAN2_USING_CUDA
00204         
00205         if (use_cpu) {
00206                 peak = cf->calc_max_location_wrap(maxshiftx, maxshifty, maxshiftz);
00207         }
00208         //cout << -peak[0] << " " << -peak[1] << " " << -peak[2] << endl;
00209         Vec3f cur_trans = Vec3f ( (float)-peak[0], (float)-peak[1], (float)-peak[2]);
00210         //cout << peak[0] << " " << peak[1] << endl;
00211 
00212         if (!to) {
00213                 cur_trans /= 2.0f; // If aligning theimage to itself then only go half way -
00214                 int intonly = params.set_default("intonly",false);
00215                 if (intonly) {
00216                         cur_trans[0] = floor(cur_trans[0] + 0.5f);
00217                         cur_trans[1] = floor(cur_trans[1] + 0.5f);
00218                         cur_trans[2] = floor(cur_trans[2] + 0.5f);
00219                 }
00220         }
00221 
00222         if( cf ){
00223                 delete cf;
00224                 cf = 0;
00225         }
00226         
00227         Dict params("trans",static_cast< vector<int> >(cur_trans));
00228         if (use_cpu){
00229                 cf=this_img->process("math.translate.int",params);
00230         }
00231         Transform t;
00232         t.set_trans(cur_trans);
00233         
00234 #ifdef EMAN2_USING_CUDA
00235         if (!use_cpu) {
00236                 //this will work just fine....
00237                 cf = this_img->process("xform",Dict("transform",&t));
00238         }
00239 #endif // EMAN2_USING_CUDA
00240 
00241         if ( nz != 1 ) {
00242 //              Transform* t = get_set_align_attr("xform.align3d",cf,this_img);
00243 //              t->set_trans(cur_trans);
00244                 cf->set_attr("xform.align3d",&t);
00245         } else if ( ny != 1 ) {
00246                 //Transform* t = get_set_align_attr("xform.align2d",cf,this_img);
00247                 cur_trans[2] = 0; // just make sure of it
00248                 t.set_trans(cur_trans);
00249                 cf->set_attr("xform.align2d",&t);
00250         }
00251         return cf;
00252 }
00253 
00254 EMData * RotationalAligner::align_180_ambiguous(EMData * this_img, EMData * to, int rfp_mode) {
00255 
00256         // Make translationally invariant rotational footprints
00257         EMData* this_img_rfp, * to_rfp;
00258         if (rfp_mode == 0) {
00259                 this_img_rfp = this_img->make_rotational_footprint_e1();
00260                 to_rfp = to->make_rotational_footprint_e1();
00261         } else if (rfp_mode == 1) {
00262                 this_img_rfp = this_img->make_rotational_footprint();
00263                 to_rfp = to->make_rotational_footprint();
00264         } else if (rfp_mode == 2) {
00265                 this_img_rfp = this_img->make_rotational_footprint_cmc();
00266                 to_rfp = to->make_rotational_footprint_cmc();
00267         } else {
00268                 throw InvalidParameterException("rfp_mode must be 0,1 or 2");
00269         }
00270         int this_img_rfp_nx = this_img_rfp->get_xsize();
00271 
00272         // Do row-wise correlation, returning a sum.
00273         EMData *cf = this_img_rfp->calc_ccfx(to_rfp, 0, this_img->get_ysize());
00274         
00275         // Delete them, they're no longer needed
00276         delete this_img_rfp; this_img_rfp = 0;
00277         delete to_rfp; to_rfp = 0;
00278 
00279         // Now solve the rotational alignment by finding the max in the column sum
00280         float *data = cf->get_data();
00281         
00282         float peak = 0;
00283         int peak_index = 0;
00284         Util::find_max(data, this_img_rfp_nx, &peak, &peak_index);
00285 
00286         if( cf ) {
00287                 delete cf;
00288                 cf = 0;
00289         }
00290         float rot_angle = (float) (peak_index * 180.0f / this_img_rfp_nx);
00291 
00292         // Return the result
00293         Transform tmp(Dict("type","2d","alpha",rot_angle));
00294         cf=this_img->process("xform",Dict("transform",(Transform*)&tmp));
00295 //      Transform* t = get_set_align_attr("xform.align2d",cf,this_img);
00296 //      Dict d("type","2d","alpha",rot_angle);
00297 //      t->set_rotation(d);
00298         cf->set_attr("xform.align2d",&tmp);
00299         return cf;
00300 }
00301 
00302 EMData *RotationalAligner::align(EMData * this_img, EMData *to,
00303                         const string& cmp_name, const Dict& cmp_params) const
00304 {
00305         if (!to) throw InvalidParameterException("Can not rotational align - the image to align to is NULL");
00306         
00307 #ifdef EMAN2_USING_CUDA
00308         if(EMData::usecuda == 1) {
00309                 if(!this_img->getcudarwdata()) this_img->copy_to_cuda();
00310                 if(!to->getcudarwdata()) to->copy_to_cuda();
00311         }
00312 #endif
00313 
00314         // Perform 180 ambiguous alignment
00315         int rfp_mode = params.set_default("rfp_mode",0);
00316         EMData* rot_aligned = RotationalAligner::align_180_ambiguous(this_img,to,rfp_mode);
00317         Transform * tmp = rot_aligned->get_attr("xform.align2d");
00318         Dict rot = tmp->get_rotation("2d");
00319         float rotate_angle_solution = rot["alpha"];
00320         delete tmp;
00321 
00322         EMData *rot_align_180 = rot_aligned->process("math.rotate.180");
00323 
00324         // Generate the comparison metrics for both rotational candidates
00325         float rot_cmp = rot_aligned->cmp(cmp_name, to, cmp_params);
00326         float rot_180_cmp = rot_align_180->cmp(cmp_name, to, cmp_params);
00327 
00328         // Decide on the result
00329         float score = 0.0;
00330         EMData* result = NULL;
00331         if (rot_cmp < rot_180_cmp){
00332                 result = rot_aligned;
00333                 score = rot_cmp;
00334                 delete rot_align_180; rot_align_180 = 0;
00335         } else {
00336                 result = rot_align_180;
00337                 score = rot_180_cmp;
00338                 delete rot_aligned; rot_aligned = 0;
00339                 rotate_angle_solution = rotate_angle_solution-180.0f;
00340         }
00341 
00342 //      Transform* t = get_align_attr("xform.align2d",result);
00343 //      t->set_rotation(Dict("type","2d","alpha",rotate_angle_solution));
00344         Transform tmp2(Dict("type","2d","alpha",rotate_angle_solution));
00345         result->set_attr("xform.align2d",&tmp2);
00346         return result;
00347 }
00348 
00349 
00350 EMData *RotatePrecenterAligner::align(EMData * this_img, EMData *to,
00351                         const string&, const Dict&) const
00352 {
00353         if (!to) {
00354                 return 0;
00355         }
00356 
00357         int ny = this_img->get_ysize();
00358         int size = Util::calc_best_fft_size((int) (M_PI * ny * 1.5));
00359         EMData *e1 = this_img->unwrap(4, ny * 7 / 16, size, 0, 0, 1);
00360         EMData *e2 = to->unwrap(4, ny * 7 / 16, size, 0, 0, 1);
00361         EMData *cf = e1->calc_ccfx(e2, 0, ny);
00362 
00363         float *data = cf->get_data();
00364 
00365         float peak = 0;
00366         int peak_index = 0;
00367         Util::find_max(data, size, &peak, &peak_index);
00368         float a = (float) ((1.0f - 1.0f * peak_index / size) * 180. * 2);
00369 
00370         Transform rot;
00371         rot.set_rotation(Dict("type","2d","alpha",(float)(a*180./M_PI)));
00372         EMData* rslt = this_img->process("xform",Dict("transform",&rot));
00373         rslt->set_attr("xform.align2d",&rot);
00374 //
00375 //      Transform* t = get_set_align_attr("xform.align2d",rslt,this_img);
00376 //      t->set_rotation(Dict("type","2d","alpha",-a));
00377 //
00378 //      EMData* result this_img->transform(Dict("type","2d","alpha",(float)(a*180./M_PI)));
00379 //
00380 //      cf->set_attr("xform.align2d",t);
00381 //      delete t;
00382 //      cf->update();
00383 
00384         if( e1 )
00385         {
00386                 delete e1;
00387                 e1 = 0;
00388         }
00389 
00390         if( e2 )
00391         {
00392                 delete e2;
00393                 e2 = 0;
00394         }
00395 
00396         if (cf) {
00397                 delete cf;
00398                 cf = 0;
00399         }
00400         return rslt;
00401 }
00402 
00403 EMData *RotationalAlignerIterative::align(EMData * this_img, EMData *to,
00404                         const string &, const Dict&) const
00405 {
00406         int r1 = params.set_default("r1",-1);
00407         int r2 = params.set_default("r2",-1);
00408         //to start lest try the original size image. If needed, we can pad it....
00409         EMData * to_polar = to->unwrap(r1,r2,-1,0,0,true);
00410         EMData * this_img_polar = this_img->unwrap(r1,r2,-1,0,0,true);
00411         int this_img_polar_nx = this_img_polar->get_xsize();
00412         
00413         EMData *cf = this_img_polar->calc_ccfx(to_polar, 0, this_img->get_ysize());
00414         
00415         //take out the garbage
00416         delete to_polar; to_polar = 0;
00417         delete this_img_polar; this_img_polar = 0;
00418         
00419         float *data = cf->get_data();
00420         float peak = 0;
00421         int peak_index = 0;
00422         Util::find_max(data, this_img_polar_nx, &peak, &peak_index);
00423 
00424         delete cf; cf = 0;
00425         float rot_angle = (float) (peak_index * 360.0f / this_img_polar_nx);
00426         
00427         //return the result
00428         //cout << rot_angle << endl;
00429         Transform tmp(Dict("type","2d","alpha",rot_angle));
00430         EMData * rotimg=this_img->process("xform",Dict("transform",(Transform*)&tmp));
00431         rotimg->set_attr("xform.align2d",&tmp);
00432         
00433         return rotimg;
00434         
00435 }
00436 
00437 EMData *RotateTranslateAlignerIterative::align(EMData * this_img, EMData *to,
00438                         const string & cmp_name, const Dict& cmp_params) const
00439 {
00440         int maxiter = params.set_default("maxiter", 3);
00441         
00442         Dict trans_params;
00443         trans_params["intonly"] = 0;
00444         trans_params["maxshift"] = params.set_default("maxshift", -1);
00445         trans_params["useflcf"] = params.set_default("useflcf",0);
00446         trans_params["nozero"] = params.set_default("nozero",false);
00447         
00448         Dict rot_params;
00449         rot_params["r1"] = params.set_default("r1", -1);
00450         rot_params["r2"] = params.set_default("r2", -1);
00451         
00452         Transform t;
00453         EMData * moving_img = this_img;
00454         for(int it = 0; it < maxiter; it++){
00455                 
00456                 // First do a translational alignment
00457                 EMData * trans_align = moving_img->align("translational", to, trans_params, cmp_name, cmp_params);
00458                 Transform * tt = trans_align->get_attr("xform.align2d");
00459                 t = *tt*t;
00460                 delete tt;
00461 
00462                 //now do rotation
00463                 EMData * rottrans_align = trans_align->align("rotational.iterative", to, rot_params, cmp_name, cmp_params);
00464                 Transform * rt = rottrans_align->get_attr("xform.align2d");
00465                 t = *rt*t;
00466                 delete trans_align; trans_align = 0;
00467                 delete rottrans_align; rottrans_align = 0;
00468                 delete rt;
00469                 
00470                 //this minimizes interpolation errors (all images that are futher processed will be interpolated at most twice)
00471                 if(it > 0){delete moving_img;}
00472                 
00473                 moving_img = this_img->process("xform",Dict("transform",&t));  //iterate
00474         }
00475         
00476         //write the total transformation;       
00477         moving_img->set_attr("xform.align2d", &t);
00478         
00479         return moving_img;
00480 }
00481 
00482 EMData *RotateTranslateAlignerPawel::align(EMData * this_img, EMData *to,
00483                         const string & cmp_name, const Dict& cmp_params) const
00484 {
00485         if (cmp_name != "dot" && cmp_name != "ccc") throw InvalidParameterException("Resample aligner only works for dot and ccc");
00486         
00487         int maxtx = params.set_default("tx", 0);
00488         int maxty = params.set_default("ty", 0);
00489         int r1 = params.set_default("r1",-1);
00490         int r2 = params.set_default("r2",-1);
00491         
00492         if(this_img->get_xsize()/2 - 1 - r2 - maxtx <= 0 || (r2 == -1 && maxtx > 0)) throw InvalidParameterException("nx/2 - 1 - r2 - tx must be greater than or = 0");
00493         if(this_img->get_ysize()/2 - 1 - r2 - maxty <= 0 || (r2 == -1 && maxty > 0)) throw InvalidParameterException("ny/2 - 1 - r2 - ty must be greater than or = 0");
00494         
00495         float best_peak = -numeric_limits<float>::infinity();
00496         int best_peak_index = 0;
00497         int best_tx = 0;
00498         int best_ty = 0;
00499         int polarxsize = 0;
00500                 
00501         for(int x = -maxtx; x <= maxtx; x++){
00502                 for(int y = -maxty; y <= maxty; y++){
00503 
00504                         EMData * to_polar = to->unwrap(r1,r2,-1,0,0,true);
00505                         EMData * this_img_polar = this_img->unwrap(r1,r2,-1,x,y,true);
00506                         EMData * cf = this_img_polar->calc_ccfx(to_polar, 0, this_img_polar->get_ysize());
00507                         
00508                         polarxsize = this_img_polar->get_xsize();
00509                         
00510                         //take out the garbage
00511                         delete to_polar; to_polar = 0;
00512                         delete this_img_polar; this_img_polar = 0;
00513         
00514                         float *data = cf->get_data();
00515                         float peak = 0;
00516                         int peak_index = 0;
00517                         Util::find_max(data, polarxsize, &peak, &peak_index);
00518                         delete cf; cf = 0;
00519 
00520                         if(peak > best_peak) {
00521                                 best_peak = peak;
00522                                 best_peak_index = peak_index;
00523                                 best_tx = x;
00524                                 best_ty = y;
00525                         }
00526                 }
00527         }
00528         
00529         float rot_angle = (float) (best_peak_index * 360.0f / polarxsize);
00530                                 
00531         //return the result
00532         Transform tmp(Dict("type","2d","alpha",rot_angle,"tx",best_tx,"ty",best_ty));
00533         EMData* rotimg=this_img->process("xform",Dict("transform",(Transform*)&tmp));
00534         rotimg->set_attr("xform.align2d",&tmp);
00535         
00536         return rotimg;
00537         
00538 }
00539 
00540 EMData *RotateTranslateAligner::align(EMData * this_img, EMData *to,
00541                         const string & cmp_name, const Dict& cmp_params) const
00542 {
00543 
00544 #ifdef EMAN2_USING_CUDA
00545         if(EMData::usecuda == 1) {
00546                 if(!this_img->getcudarwdata()) this_img->copy_to_cuda();
00547                 if(!to->getcudarwdata()) to->copy_to_cuda();
00548         }
00549 #endif
00550 
00551         // Get the 180 degree ambiguously rotationally aligned and its 180 degree rotation counterpart
00552         int rfp_mode = params.set_default("rfp_mode",0);
00553         EMData *rot_align  =  RotationalAligner::align_180_ambiguous(this_img,to,rfp_mode);
00554         Transform * tmp = rot_align->get_attr("xform.align2d");
00555         Dict rot = tmp->get_rotation("2d");
00556         float rotate_angle_solution = rot["alpha"];
00557         delete tmp;
00558 
00559         EMData *rot_align_180 = rot_align->copy();
00560         rot_align_180->process_inplace("math.rotate.180");
00561 
00562         Dict trans_params;
00563         trans_params["intonly"]  = 0;
00564         trans_params["maxshift"] = params.set_default("maxshift", -1);
00565         trans_params["useflcf"]=params.set_default("useflcf",0);
00566 
00567         // Do the first case translational alignment
00568         trans_params["nozero"]   = params.set_default("nozero",false);
00569         EMData* rot_trans = rot_align->align("translational", to, trans_params, cmp_name, cmp_params);
00570         if( rot_align ) { // Clean up
00571                 delete rot_align;
00572                 rot_align = 0;
00573         }
00574 
00575         // Do the second case translational alignment
00576         EMData*  rot_180_trans = rot_align_180->align("translational", to, trans_params, cmp_name, cmp_params);
00577         if( rot_align_180 )     { // Clean up
00578                 delete rot_align_180;
00579                 rot_align_180 = 0;
00580         }
00581 
00582         // Finally decide on the result
00583         float cmp1 = rot_trans->cmp(cmp_name, to, cmp_params);
00584         float cmp2 = rot_180_trans->cmp(cmp_name, to, cmp_params);
00585 
00586         EMData *result = 0;
00587         if (cmp1 < cmp2) { // Assumes smaller is better - thus all comparitors should support "smaller is better"
00588                 if( rot_180_trans )     {
00589                         delete rot_180_trans;
00590                         rot_180_trans = 0;
00591                 }
00592                 result = rot_trans;
00593         }
00594         else {
00595                 if( rot_trans ) {
00596                         delete rot_trans;
00597                         rot_trans = 0;
00598                 }
00599                 result = rot_180_trans;
00600                 rotate_angle_solution -= 180.f;
00601         }
00602 
00603         Transform* t = result->get_attr("xform.align2d");
00604         t->set_rotation(Dict("type","2d","alpha",rotate_angle_solution));
00605         result->set_attr("xform.align2d",t);
00606         delete t;
00607 
00608         return result;
00609 }
00610 
00611 
00612 
00613 
00614 EMData* RotateTranslateFlipAligner::align(EMData * this_img, EMData *to,
00615                                                                                   const string & cmp_name, const Dict& cmp_params) const
00616 {
00617         // Get the non flipped rotational, tranlsationally aligned image
00618         Dict rt_params("maxshift", params["maxshift"], "rfp_mode", params.set_default("rfp_mode",0),"useflcf",params.set_default("useflcf",0));
00619         EMData *rot_trans_align = this_img->align("rotate_translate",to,rt_params,cmp_name, cmp_params);
00620         
00621         // Do the same alignment, but using the flipped version of the image
00622         EMData *flipped = params.set_default("flip", (EMData *) 0);
00623         bool delete_flag = false;
00624         if (flipped == 0) {
00625                 flipped = to->process("xform.flip", Dict("axis", "x"));
00626                 delete_flag = true;
00627         }
00628 
00629         EMData * rot_trans_align_flip = this_img->align("rotate_translate", flipped, rt_params, cmp_name, cmp_params);
00630         Transform* t = rot_trans_align_flip->get_attr("xform.align2d");
00631         t->set_mirror(true);
00632         rot_trans_align_flip->set_attr("xform.align2d",t);
00633         delete t;
00634 
00635         // Now finally decide on what is the best answer
00636         float cmp1 = rot_trans_align->cmp(cmp_name, to, cmp_params);
00637         float cmp2 = rot_trans_align_flip->cmp(cmp_name, flipped, cmp_params);
00638 
00639         if (delete_flag){
00640                 if(flipped) {
00641                         delete flipped;
00642                         flipped = 0;
00643                 }
00644         }
00645 
00646         EMData *result = 0;
00647         if (cmp1 < cmp2 )  {
00648 
00649                 if( rot_trans_align_flip ) {
00650                         delete rot_trans_align_flip;
00651                         rot_trans_align_flip = 0;
00652                 }
00653                 result = rot_trans_align;
00654         }
00655         else {
00656                 if( rot_trans_align ) {
00657                         delete rot_trans_align;
00658                         rot_trans_align = 0;
00659                 }
00660                 result = rot_trans_align_flip;
00661                 result->process_inplace("xform.flip",Dict("axis","x"));
00662         }
00663 
00664         return result;
00665 }
00666 
00667 EMData* RotateTranslateFlipAlignerIterative::align(EMData * this_img, EMData *to,
00668                                                                                   const string & cmp_name, const Dict& cmp_params) const
00669 {
00670         // Get the non flipped rotational, tranlsationally aligned image
00671         Dict rt_params("maxshift", params["maxshift"],"r1",params.set_default("r1",-1),"r2",params.set_default("r2",-1));
00672         EMData *rot_trans_align = this_img->align("rotate_translate.iterative",to,rt_params,cmp_name, cmp_params);
00673 
00674         // Do the same alignment, but using the flipped version of the image
00675         EMData *flipped = params.set_default("flip", (EMData *) 0);
00676         bool delete_flag = false;
00677         if (flipped == 0) {
00678                 flipped = to->process("xform.flip", Dict("axis", "x"));
00679                 delete_flag = true;
00680         }
00681 
00682         EMData * rot_trans_align_flip = this_img->align("rotate_translate.iterative", flipped, rt_params, cmp_name, cmp_params);
00683         Transform* t = rot_trans_align_flip->get_attr("xform.align2d");
00684         t->set_mirror(true);
00685         rot_trans_align_flip->set_attr("xform.align2d",t);
00686         delete t;
00687 
00688         // Now finally decide on what is the best answer
00689         float cmp1 = rot_trans_align->cmp(cmp_name, to, cmp_params);
00690         float cmp2 = rot_trans_align_flip->cmp(cmp_name, flipped, cmp_params);
00691 
00692         if (delete_flag){
00693                 if(flipped) {
00694                         delete flipped;
00695                         flipped = 0;
00696                 }
00697         }
00698 
00699         EMData *result = 0;
00700         if (cmp1 < cmp2 )  {
00701 
00702                 if( rot_trans_align_flip ) {
00703                         delete rot_trans_align_flip;
00704                         rot_trans_align_flip = 0;
00705                 }
00706                 result = rot_trans_align;
00707         }
00708         else {
00709                 if( rot_trans_align ) {
00710                         delete rot_trans_align;
00711                         rot_trans_align = 0;
00712                 }
00713                 result = rot_trans_align_flip;
00714                 result->process_inplace("xform.flip",Dict("axis","x"));
00715         }
00716 
00717         return result;
00718 }
00719 
00720 EMData *RotateTranslateFlipAlignerPawel::align(EMData * this_img, EMData *to,
00721                         const string & cmp_name, const Dict& cmp_params) const
00722 {
00723         if (cmp_name != "dot" && cmp_name != "ccc") throw InvalidParameterException("Resample aligner only works for dot and ccc");
00724         
00725         int maxtx = params.set_default("tx", 0);
00726         int maxty = params.set_default("ty", 0);
00727         int r1 = params.set_default("r1",-1);
00728         int r2 = params.set_default("r2",-1);
00729         
00730         if(this_img->get_xsize()/2 - 1 - r2 - maxtx <= 0 || (r2 == -1 && maxtx > 0)) throw InvalidParameterException("nx/2 - 1 - r2 - tx must be greater than or = 0");
00731         if(this_img->get_ysize()/2 - 1 - r2 - maxty <= 0 || (r2 == -1 && maxty > 0)) throw InvalidParameterException("ny/2 - 1 - r2 - ty must be greater than or = 0");
00732         
00733         float best_peak = -numeric_limits<float>::infinity();
00734         int best_peak_index = 0;
00735         int best_tx = 0;
00736         int best_ty = 0;
00737         int polarxsize = 0;
00738         bool flip = false;
00739         
00740         for(int x = -maxtx; x <= maxtx; x++){
00741                 for(int y = -maxty; y <= maxty; y++){
00742 
00743                         EMData * to_polar = to->unwrap(r1,r2,-1,0,0,true);
00744                         EMData * this_img_polar = this_img->unwrap(r1,r2,-1,x,y,true);
00745                         EMData * cfflip = this_img_polar->calc_ccfx(to_polar, 0, this_img_polar->get_ysize(), false, true);
00746                         EMData * cf = this_img_polar->calc_ccfx(to_polar, 0, this_img_polar->get_ysize());
00747                         
00748                         polarxsize = this_img_polar->get_xsize();
00749                         
00750                         //take out the garbage
00751                         delete to_polar; to_polar = 0;
00752                         delete this_img_polar; this_img_polar = 0;
00753         
00754                         float *data = cf->get_data();
00755                         float peak = 0;
00756                         int peak_index = 0;
00757                         Util::find_max(data, polarxsize, &peak, &peak_index);
00758                         delete cf; cf = 0;
00759 
00760                         if(peak > best_peak) {
00761                                 best_peak = peak;
00762                                 best_peak_index = peak_index;
00763                                 best_tx = x;
00764                                 best_ty = y;
00765                                 flip = false;
00766                         }
00767                         
00768                         data = cfflip->get_data();
00769                         Util::find_max(data, polarxsize, &peak, &peak_index);
00770                         delete cfflip; cfflip = 0;
00771 
00772                         if(peak > best_peak) {
00773                                 best_peak = peak;
00774                                 best_peak_index = peak_index;
00775                                 best_tx = x;
00776                                 best_ty = y;
00777                                 flip = true;
00778                         }
00779                 }
00780         }
00781         
00782         float rot_angle = (float) (best_peak_index * 360.0f / polarxsize);
00783                                 
00784         //return the result
00785         Transform tmp(Dict("type","2d","alpha",rot_angle,"tx",best_tx,"ty",best_ty));
00786         EMData* rotimg=this_img->process("xform",Dict("transform",(Transform*)&tmp));
00787         rotimg->set_attr("xform.align2d",&tmp);
00788         if(flip == true) {
00789                 rotimg->process_inplace("xform.flip",Dict("axis", "x"));
00790         }
00791         
00792         return rotimg;
00793         
00794 }
00795 
00796 EMData *RotateFlipAligner::align(EMData * this_img, EMData *to,
00797                         const string& cmp_name, const Dict& cmp_params) const
00798 {
00799         Dict rot_params("rfp_mode",params.set_default("rfp_mode",0));
00800         EMData *r1 = this_img->align("rotational", to, rot_params,cmp_name, cmp_params);
00801 
00802 
00803         EMData* flipped =to->process("xform.flip", Dict("axis", "x"));
00804         EMData *r2 = this_img->align("rotational", flipped,rot_params, cmp_name, cmp_params);
00805         Transform* t = r2->get_attr("xform.align2d");
00806         t->set_mirror(true);
00807         r2->set_attr("xform.align2d",t);
00808         delete t;
00809 
00810         float cmp1 = r1->cmp(cmp_name, to, cmp_params);
00811         float cmp2 = r2->cmp(cmp_name, flipped, cmp_params);
00812 
00813         delete flipped; flipped = 0;
00814 
00815         EMData *result = 0;
00816 
00817         if (cmp1 < cmp2) {
00818                 if( r2 )
00819                 {
00820                         delete r2;
00821                         r2 = 0;
00822                 }
00823                 result = r1;
00824         }
00825         else {
00826                 if( r1 )
00827                 {
00828                         delete r1;
00829                         r1 = 0;
00830                 }
00831                 result = r2;
00832                 result->process_inplace("xform.flip",Dict("axis","x"));
00833         }
00834 
00835         return result;
00836 }
00837 
00838 EMData *RotateFlipAlignerIterative::align(EMData * this_img, EMData *to,
00839                         const string& cmp_name, const Dict& cmp_params) const
00840 {
00841         Dict rot_params("r1",params.set_default("r1",-1),"r2",params.set_default("r2",-1));
00842         EMData *r1 = this_img->align("rotational.iterative", to, rot_params,cmp_name, cmp_params);
00843 
00844         EMData* flipped =to->process("xform.flip", Dict("axis", "x"));
00845         EMData *r2 = this_img->align("rotational.iterative", flipped,rot_params, cmp_name, cmp_params);
00846         Transform* t = r2->get_attr("xform.align2d");
00847         t->set_mirror(true);
00848         r2->set_attr("xform.align2d",t);
00849         delete t;
00850 
00851         float cmp1 = r1->cmp(cmp_name, to, cmp_params);
00852         float cmp2 = r2->cmp(cmp_name, flipped, cmp_params);
00853 
00854         delete flipped; flipped = 0;
00855 
00856         EMData *result = 0;
00857 
00858         if (cmp1 < cmp2) {
00859                 if( r2 )
00860                 {
00861                         delete r2;
00862                         r2 = 0;
00863                 }
00864                 result = r1;
00865         }
00866         else {
00867                 if( r1 )
00868                 {
00869                         delete r1;
00870                         r1 = 0;
00871                 }
00872                 result = r2;
00873                 result->process_inplace("xform.flip",Dict("axis","x"));
00874         }
00875 
00876         return result;
00877 }
00878 
00879 // David Woolford says FIXME
00880 // You will note the excessive amount of EMData copying that's going in this function
00881 // This is because functions that are operating on the EMData objects are changing them
00882 // and if you do not use copies the whole algorithm breaks. I did not have time to go
00883 // through and rectify this situation.
00884 // David Woolford says - this problem is related to the fact that many functions that
00885 // take EMData pointers as arguments do not take them as constant pointers to constant
00886 // objects, instead they are treated as raw (completely changeable) pointers. This means
00887 // it's hard to track down which functions are changing the EMData objects, because they
00888 // all do (in name). If this behavior is unavoidable then ignore this comment, however if possible it would
00889 // be good to make things const as much as possible. For example in alignment, technically
00890 // the argument EMData objects (raw pointers) should not be altered... should they?
00891 //
00892 // But const can be very annoying sometimes...
00893 EMData *RTFExhaustiveAligner::align(EMData * this_img, EMData *to,
00894                         const string & cmp_name, const Dict& cmp_params) const
00895 {
00896         EMData *flip = params.set_default("flip", (EMData *) 0);
00897         int maxshift = params.set_default("maxshift", this_img->get_xsize()/8);
00898         if (maxshift < 2) throw InvalidParameterException("maxshift must be greater than or equal to 2");
00899 
00900         int ny = this_img->get_ysize();
00901         int xst = (int) floor(2 * M_PI * ny);
00902         xst = Util::calc_best_fft_size(xst);
00903 
00904         Dict d("n",2);
00905         EMData *to_shrunk_unwrapped = to->process("math.medianshrink",d);
00906 
00907         int to_copy_r2 = to_shrunk_unwrapped->get_ysize() / 2 - 2 - maxshift / 2;
00908         EMData *tmp = to_shrunk_unwrapped->unwrap(4, to_copy_r2, xst / 2, 0, 0, true);
00909         if( to_shrunk_unwrapped )
00910         {
00911                 delete to_shrunk_unwrapped;
00912                 to_shrunk_unwrapped = 0;
00913         }
00914         to_shrunk_unwrapped = tmp;
00915 
00916         EMData *to_shrunk_unwrapped_copy = to_shrunk_unwrapped->copy();
00917         EMData* to_unwrapped = to->unwrap(4, to->get_ysize() / 2 - 2 - maxshift, xst, 0, 0, true);
00918         EMData *to_unwrapped_copy = to_unwrapped->copy();
00919 
00920         bool delete_flipped = true;
00921         EMData *flipped = 0;
00922         if (flip) {
00923                 delete_flipped = false;
00924                 flipped = flip;
00925         }
00926         else {
00927                 flipped = to->process("xform.flip", Dict("axis", "x"));
00928         }
00929         EMData *to_shrunk_flipped_unwrapped = flipped->process("math.medianshrink",d);
00930         tmp = to_shrunk_flipped_unwrapped->unwrap(4, to_copy_r2, xst / 2, 0, 0, true);
00931         if( to_shrunk_flipped_unwrapped )
00932         {
00933                 delete to_shrunk_flipped_unwrapped;
00934                 to_shrunk_flipped_unwrapped = 0;
00935         }
00936         to_shrunk_flipped_unwrapped = tmp;
00937         EMData *to_shrunk_flipped_unwrapped_copy = to_shrunk_flipped_unwrapped->copy();
00938         EMData* to_flip_unwrapped = flipped->unwrap(4, to->get_ysize() / 2 - 2 - maxshift, xst, 0, 0, true);
00939         EMData* to_flip_unwrapped_copy = to_flip_unwrapped->copy();
00940 
00941         if (delete_flipped && flipped != 0) {
00942                 delete flipped;
00943                 flipped = 0;
00944         }
00945 
00946         EMData *this_shrunk_2 = this_img->process("math.medianshrink",d);
00947 
00948         float bestval = FLT_MAX;
00949         float bestang = 0;
00950         int bestflip = 0;
00951         float bestdx = 0;
00952         float bestdy = 0;
00953 
00954         int half_maxshift = maxshift / 2;
00955 
00956         int ur2 = this_shrunk_2->get_ysize() / 2 - 2 - half_maxshift;
00957         for (int dy = -half_maxshift; dy <= half_maxshift; dy += 1) {
00958                 for (int dx = -half_maxshift; dx <= half_maxshift; dx += 1) {
00959 #ifdef  _WIN32
00960                         if (_hypot(dx, dy) <= half_maxshift) {
00961 #else
00962                         if (hypot(dx, dy) <= half_maxshift) {
00963 #endif
00964                                 EMData *uw = this_shrunk_2->unwrap(4, ur2, xst / 2, dx, dy, true);
00965                                 EMData *uwc = uw->copy();
00966                                 EMData *a = uw->calc_ccfx(to_shrunk_unwrapped);
00967 
00968                                 uwc->rotate_x(a->calc_max_index());
00969                                 float cm = uwc->cmp(cmp_name, to_shrunk_unwrapped_copy, cmp_params);
00970                                 if (cm < bestval) {
00971                                         bestval = cm;
00972                                         bestang = (float) (2.0 * M_PI * a->calc_max_index() / a->get_xsize());
00973                                         bestdx = (float)dx;
00974                                         bestdy = (float)dy;
00975                                         bestflip = 0;
00976                                 }
00977 
00978 
00979                                 if( a )
00980                                 {
00981                                         delete a;
00982                                         a = 0;
00983                                 }
00984                                 if( uw )
00985                                 {
00986                                         delete uw;
00987                                         uw = 0;
00988                                 }
00989                                 if( uwc )
00990                                 {
00991                                         delete uwc;
00992                                         uwc = 0;
00993                                 }
00994                                 uw = this_shrunk_2->unwrap(4, ur2, xst / 2, dx, dy, true);
00995                                 uwc = uw->copy();
00996                                 a = uw->calc_ccfx(to_shrunk_flipped_unwrapped);
00997 
00998                                 uwc->rotate_x(a->calc_max_index());
00999                                 cm = uwc->cmp(cmp_name, to_shrunk_flipped_unwrapped_copy, cmp_params);
01000                                 if (cm < bestval) {
01001                                         bestval = cm;
01002                                         bestang = (float) (2.0 * M_PI * a->calc_max_index() / a->get_xsize());
01003                                         bestdx = (float)dx;
01004                                         bestdy = (float)dy;
01005                                         bestflip = 1;
01006                                 }
01007 
01008                                 if( a )
01009                                 {
01010                                         delete a;
01011                                         a = 0;
01012                                 }
01013 
01014                                 if( uw )
01015                                 {
01016                                         delete uw;
01017                                         uw = 0;
01018                                 }
01019                                 if( uwc )
01020                                 {
01021                                         delete uwc;
01022                                         uwc = 0;
01023                                 }
01024                         }
01025                 }
01026         }
01027         if( this_shrunk_2 )
01028         {
01029                 delete this_shrunk_2;
01030                 this_shrunk_2 = 0;
01031         }
01032         if( to_shrunk_unwrapped )
01033         {
01034                 delete to_shrunk_unwrapped;
01035                 to_shrunk_unwrapped = 0;
01036         }
01037         if( to_shrunk_unwrapped_copy )
01038         {
01039                 delete to_shrunk_unwrapped_copy;
01040                 to_shrunk_unwrapped_copy = 0;
01041         }
01042         if( to_shrunk_flipped_unwrapped )
01043         {
01044                 delete to_shrunk_flipped_unwrapped;
01045                 to_shrunk_flipped_unwrapped = 0;
01046         }
01047         if( to_shrunk_flipped_unwrapped_copy )
01048         {
01049                 delete to_shrunk_flipped_unwrapped_copy;
01050                 to_shrunk_flipped_unwrapped_copy = 0;
01051         }
01052         bestdx *= 2;
01053         bestdy *= 2;
01054         bestval = FLT_MAX;
01055 
01056         float bestdx2 = bestdx;
01057         float bestdy2 = bestdy;
01058         // Note I tried steps less than 1.0 (sub pixel precision) and it actually appeared detrimental
01059         // So my advice is to stick with dx += 1.0 etc unless you really are looking to fine tune this
01060         // algorithm
01061         for (float dy = bestdy2 - 3; dy <= bestdy2 + 3; dy += 1.0 ) {
01062                 for (float dx = bestdx2 - 3; dx <= bestdx2 + 3; dx += 1.0 ) {
01063 
01064 #ifdef  _WIN32
01065                         if (_hypot(dx, dy) <= maxshift) {
01066 #else
01067                         if (hypot(dx, dy) <= maxshift) {
01068 #endif
01069                                 EMData *uw = this_img->unwrap(4, this_img->get_ysize() / 2 - 2 - maxshift, xst, (int)dx, (int)dy, true);
01070                                 EMData *uwc = uw->copy();
01071                                 EMData *a = uw->calc_ccfx(to_unwrapped);
01072 
01073                                 uwc->rotate_x(a->calc_max_index());
01074                                 float cm = uwc->cmp(cmp_name, to_unwrapped_copy, cmp_params);
01075 
01076                                 if (cm < bestval) {
01077                                         bestval = cm;
01078                                         bestang = (float)(2.0 * M_PI * a->calc_max_index() / a->get_xsize());
01079                                         bestdx = dx;
01080                                         bestdy = dy;
01081                                         bestflip = 0;
01082                                 }
01083 
01084                                 if( a )
01085                                 {
01086                                         delete a;
01087                                         a = 0;
01088                                 }
01089                                 if( uw )
01090                                 {
01091                                         delete uw;
01092                                         uw = 0;
01093                                 }
01094                                 if( uwc )
01095                                 {
01096                                         delete uwc;
01097                                         uwc = 0;
01098                                 }
01099                                 uw = this_img->unwrap(4, this_img->get_ysize() / 2 - 2 - maxshift, xst, (int)dx, (int)dy, true);
01100                                 uwc = uw->copy();
01101                                 a = uw->calc_ccfx(to_flip_unwrapped);
01102 
01103                                 uwc->rotate_x(a->calc_max_index());
01104                                 cm = uwc->cmp(cmp_name, to_flip_unwrapped_copy, cmp_params);
01105 
01106                                 if (cm < bestval) {
01107                                         bestval = cm;
01108                                         bestang = (float)(2.0 * M_PI * a->calc_max_index() / a->get_xsize());
01109                                         bestdx = dx;
01110                                         bestdy = dy;
01111                                         bestflip = 1;
01112                                 }
01113 
01114                                 if( a )
01115                                 {
01116                                         delete a;
01117                                         a = 0;
01118                                 }
01119                                 if( uw )
01120                                 {
01121                                         delete uw;
01122                                         uw = 0;
01123                                 }
01124                                 if( uwc )
01125                                 {
01126                                         delete uwc;
01127                                         uwc = 0;
01128                                 }
01129                         }
01130                 }
01131         }
01132         if( to_unwrapped ) {delete to_unwrapped;to_unwrapped = 0;}
01133         if( to_shrunk_unwrapped ) {     delete to_shrunk_unwrapped;     to_shrunk_unwrapped = 0;}
01134         if (to_unwrapped_copy) { delete to_unwrapped_copy; to_unwrapped_copy = 0; }
01135         if (to_flip_unwrapped) { delete to_flip_unwrapped; to_flip_unwrapped = 0; }
01136         if (to_flip_unwrapped_copy) { delete to_flip_unwrapped_copy; to_flip_unwrapped_copy = 0;}
01137 
01138         bestang *= (float)EMConsts::rad2deg;
01139         Transform t(Dict("type","2d","alpha",(float)bestang));
01140         t.set_pre_trans(Vec2f(-bestdx,-bestdy));
01141         if (bestflip) {
01142                 t.set_mirror(true);
01143         }
01144 
01145         EMData* ret = this_img->process("xform",Dict("transform",&t));
01146         ret->set_attr("xform.align2d",&t);
01147 
01148         return ret;
01149 }
01150 
01151 
01152 EMData *RTFSlowExhaustiveAligner::align(EMData * this_img, EMData *to,
01153                         const string & cmp_name, const Dict& cmp_params) const
01154 {
01155 
01156         EMData *flip = params.set_default("flip", (EMData *) 0);
01157         int maxshift = params.set_default("maxshift", -1);
01158 
01159         EMData *flipped = 0;
01160 
01161         bool delete_flipped = true;
01162         if (flip) {
01163                 delete_flipped = false;
01164                 flipped = flip;
01165         }
01166         else {
01167                 flipped = to->process("xform.flip", Dict("axis", "x"));
01168         }
01169 
01170         int nx = this_img->get_xsize();
01171 
01172         if (maxshift < 0) {
01173                 maxshift = nx / 10;
01174         }
01175 
01176         float angle_step =  params.set_default("angstep", 0.0f);
01177         if ( angle_step == 0 ) angle_step = atan2(2.0f, (float)nx);
01178         else {
01179                 angle_step *= (float)EMConsts::deg2rad; //convert to radians
01180         }
01181         float trans_step =  params.set_default("transtep",1.0f);
01182 
01183         if (trans_step <= 0) throw InvalidParameterException("transstep must be greater than 0");
01184         if (angle_step <= 0) throw InvalidParameterException("angstep must be greater than 0");
01185 
01186 
01187         Dict shrinkfactor("n",2);
01188         EMData *this_img_shrink = this_img->process("math.medianshrink",shrinkfactor);
01189         EMData *to_shrunk = to->process("math.medianshrink",shrinkfactor);
01190         EMData *flipped_shrunk = flipped->process("math.medianshrink",shrinkfactor);
01191 
01192         int bestflip = 0;
01193         float bestdx = 0;
01194         float bestdy = 0;
01195 
01196         float bestang = 0;
01197         float bestval = FLT_MAX;
01198 
01199         int half_maxshift = maxshift / 2;
01200 
01201 
01202         for (int dy = -half_maxshift; dy <= half_maxshift; ++dy) {
01203                 for (int dx = -half_maxshift; dx <= half_maxshift; ++dx) {
01204                         if (hypot(dx, dy) <= maxshift) {
01205                                 for (float ang = -angle_step * 2.0f; ang <= (float)2 * M_PI; ang += angle_step * 4.0f) {
01206                                         EMData v(*this_img_shrink);
01207                                         Transform t(Dict("type","2d","alpha",static_cast<float>(ang*EMConsts::rad2deg)));
01208                                         t.set_trans((float)dx,(float)dy);
01209                                         v.transform(t);
01210 //                                      v.rotate_translate(ang*EMConsts::rad2deg, 0.0f, 0.0f, (float)dx, (float)dy, 0.0f);
01211 
01212                                         float lc = v.cmp(cmp_name, to_shrunk, cmp_params);
01213 
01214                                         if (lc < bestval) {
01215                                                 bestval = lc;
01216                                                 bestang = ang;
01217                                                 bestdx = (float)dx;
01218                                                 bestdy = (float)dy;
01219                                                 bestflip = 0;
01220                                         }
01221 
01222                                         lc = v.cmp(cmp_name,flipped_shrunk , cmp_params);
01223                                         if (lc < bestval) {
01224                                                 bestval = lc;
01225                                                 bestang = ang;
01226                                                 bestdx = (float)dx;
01227                                                 bestdy = (float)dy;
01228                                                 bestflip = 1;
01229                                         }
01230                                 }
01231                         }
01232                 }
01233         }
01234 
01235         if( to_shrunk )
01236         {
01237                 delete to_shrunk;
01238                 to_shrunk = 0;
01239         }
01240         if( flipped_shrunk )
01241         {
01242                 delete flipped_shrunk;
01243                 flipped_shrunk = 0;
01244         }
01245         if( this_img_shrink )
01246         {
01247                 delete this_img_shrink;
01248                 this_img_shrink = 0;
01249         }
01250 
01251         bestdx *= 2;
01252         bestdy *= 2;
01253         bestval = FLT_MAX;
01254 
01255         float bestdx2 = bestdx;
01256         float bestdy2 = bestdy;
01257         float bestang2 = bestang;
01258 
01259         for (float dy = bestdy2 - 3; dy <= bestdy2 + 3; dy += trans_step) {
01260                 for (float dx = bestdx2 - 3; dx <= bestdx2 + 3; dx += trans_step) {
01261                         if (hypot(dx, dy) <= maxshift) {
01262                                 for (float ang = bestang2 - angle_step * 6.0f; ang <= bestang2 + angle_step * 6.0f; ang += angle_step) {
01263                                         EMData v(*this_img);
01264                                         Transform t(Dict("type","2d","alpha",static_cast<float>(ang*EMConsts::rad2deg)));
01265                                         t.set_trans(dx,dy);
01266                                         v.transform(t);
01267 //                                      v.rotate_translate(ang*EMConsts::rad2deg, 0.0f, 0.0f, (float)dx, (float)dy, 0.0f);
01268 
01269                                         float lc = v.cmp(cmp_name, to, cmp_params);
01270 
01271                                         if (lc < bestval) {
01272                                                 bestval = lc;
01273                                                 bestang = ang;
01274                                                 bestdx = dx;
01275                                                 bestdy = dy;
01276                                                 bestflip = 0;
01277                                         }
01278 
01279                                         lc = v.cmp(cmp_name, flipped, cmp_params);
01280 
01281                                         if (lc < bestval) {
01282                                                 bestval = lc;
01283                                                 bestang = ang;
01284                                                 bestdx = dx;
01285                                                 bestdy = dy;
01286                                                 bestflip = 1;
01287                                         }
01288                                 }
01289                         }
01290                 }
01291         }
01292 
01293         if (delete_flipped) { delete flipped; flipped = 0; }
01294 
01295         bestang *= (float)EMConsts::rad2deg;
01296         Transform t(Dict("type","2d","alpha",(float)bestang));
01297         t.set_trans(bestdx,bestdy);
01298 
01299         if (bestflip) {
01300                 t.set_mirror(true);
01301         }
01302 
01303         EMData* rslt = this_img->process("xform",Dict("transform",&t));
01304         rslt->set_attr("xform.align2d",&t);
01305 
01306         return rslt;
01307 }
01308 
01309 
01310 
01311 static double refalifn(const gsl_vector * v, void *params)
01312 {
01313         Dict *dict = (Dict *) params;
01314 
01315         double x = gsl_vector_get(v, 0);
01316         double y = gsl_vector_get(v, 1);
01317         double a = gsl_vector_get(v, 2);
01318 
01319         EMData *this_img = (*dict)["this"];
01320         EMData *with = (*dict)["with"];
01321         bool mirror = (*dict)["mirror"];
01322 
01323 //      float mean = (float)this_img->get_attr("mean");
01324 //      if ( Util::goodf(&mean) ) {
01325 //              //cout << "tmps mean is nan even before rotation" << endl;
01326 //      }
01327 
01328         Transform t(Dict("type","2d","alpha",static_cast<float>(a)));
01329 //      Transform3D t3d(Transform3D::EMAN, (float)a, 0.0f, 0.0f);
01330 //      t3d.set_posttrans( (float) x, (float) y);
01331 //      tmp->rotate_translate(t3d);
01332         t.set_trans((float)x,(float)y);
01333         t.set_mirror(mirror);
01334         if (v->size>3) {
01335                 float sca=(float)gsl_vector_get(v, 3);
01336                 if (sca<.7 || sca>1.3) return 1.0e20;
01337                 t.set_scale((float)gsl_vector_get(v, 3));
01338         }
01339         EMData *tmp = this_img->process("xform",Dict("transform",&t));
01340 
01341 //      printf("GSL %f %f %f %d %f\n",x,y,a,mirror,(float)gsl_vector_get(v, 3));
01342         Cmp* c = (Cmp*) ((void*)(*dict)["cmp"]);
01343         double result = c->cmp(tmp,with);
01344 
01345         // DELETE AT SOME STAGE, USEFUL FOR PRERELEASE STUFF
01346         //      float test_result = (float)result;
01347 //      if ( Util::goodf(&test_result) ) {
01348 //              cout << "result " << result << " " << x << " " << y << " " << a << endl;
01349 //              cout << (float)this_img->get_attr("mean") << " " << (float)tmp->get_attr("mean") << " " << (float)with->get_attr("mean") << endl;
01350 //              tmp->write_image("tmp.hdf");
01351 //              with->write_image("with.hdf");
01352 //              this_img->write_image("this_img.hdf");
01353 //              EMData* t = this_img->copy();
01354 //              cout << (float)t->get_attr("mean") << endl;
01355 //              t->rotate_translate( t3d );
01356 //              cout << (float)t->get_attr("mean") << endl;
01357 //              cout << "exit" << endl;
01359 //              cout << (float)t->get_attr("mean") << endl;
01360 //              cout << "now exit" << endl;
01361 //              delete t;
01362 //      }
01363 
01364 
01365         if ( tmp != 0 ) delete tmp;
01366 
01367         return result;
01368 }
01369 
01370 static double refalifnfast(const gsl_vector * v, void *params)
01371 {
01372         Dict *dict = (Dict *) params;
01373         EMData *this_img = (*dict)["this"];
01374         EMData *img_to = (*dict)["with"];
01375         bool mirror = (*dict)["mirror"];
01376 
01377         double x = gsl_vector_get(v, 0);
01378         double y = gsl_vector_get(v, 1);
01379         double a = gsl_vector_get(v, 2);
01380 
01381         double r = this_img->dot_rotate_translate(img_to, (float)x, (float)y, (float)a, mirror);
01382         int nsec = this_img->get_xsize() * this_img->get_ysize();
01383         double result = 1.0 - r / nsec;
01384 
01385 //      cout << result << " x " << x << " y " << y << " az " << a <<  endl;
01386         return result;
01387 }
01388 
01389 
01390 EMData *RefineAligner::align(EMData * this_img, EMData *to,
01391         const string & cmp_name, const Dict& cmp_params) const
01392 {
01393 
01394         if (!to) {
01395                 return 0;
01396         }
01397 
01398         EMData *result;
01399         int mode = params.set_default("mode", 0);
01400         float saz = 0.0;
01401         float sdx = 0.0;
01402         float sdy = 0.0;
01403         float sscale = 1.0;
01404         bool mirror = false;
01405         Transform* t;
01406         if (params.has_key("xform.align2d") ) {
01407                 t = params["xform.align2d"];
01408                 Dict params = t->get_params("2d");
01409                 saz = params["alpha"];
01410                 sdx = params["tx"];
01411                 sdy = params["ty"];
01412                 mirror = params["mirror"];
01413                 sscale = params["scale"];
01414         } else {
01415                 t = new Transform(); // is the identity
01416         }
01417 
01418         // We do this to prevent the GSL routine from crashing on an invalid alignment
01419         if ((float)(this_img->get_attr("sigma"))==0.0 || (float)(to->get_attr("sigma"))==0.0) {
01420                 result = this_img->process("xform",Dict("transform",t));
01421                 result->set_attr("xform.align2d",t);
01422                 delete t;
01423                 return result;
01424         }
01425         
01426         float stepx = params.set_default("stepx",1.0f);
01427         float stepy = params.set_default("stepy",1.0f);
01428         // Default step is 5 degree - note in EMAN1 it was 0.1 radians
01429         float stepaz = params.set_default("stepaz",5.0f);
01430         float stepscale = params.set_default("stepscale",0.0f);
01431 
01432         int np = 3;
01433         if (stepscale!=0.0) np++;
01434         Dict gsl_params;
01435         gsl_params["this"] = this_img;
01436         gsl_params["with"] = to;
01437         gsl_params["snr"]  = params["snr"];
01438         gsl_params["mirror"] = mirror;
01439 
01440         const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
01441         gsl_vector *ss = gsl_vector_alloc(np);
01442 
01443 
01444         gsl_vector_set(ss, 0, stepx);
01445         gsl_vector_set(ss, 1, stepy);
01446         gsl_vector_set(ss, 2, stepaz);
01447         if (stepscale!=0.0) gsl_vector_set(ss,3,stepscale);
01448         
01449         gsl_vector *x = gsl_vector_alloc(np);
01450         gsl_vector_set(x, 0, sdx);
01451         gsl_vector_set(x, 1, sdy);
01452         gsl_vector_set(x, 2, saz);
01453         if (stepscale!=0.0) gsl_vector_set(x,3,1.0);
01454         
01455         Cmp *c = 0;
01456 
01457         gsl_multimin_function minex_func;
01458         if (mode == 2) {
01459                 minex_func.f = &refalifnfast;
01460         }
01461         else {
01462                 c = Factory < Cmp >::get(cmp_name, cmp_params);
01463                 gsl_params["cmp"] = (void *) c;
01464                 minex_func.f = &refalifn;
01465         }
01466 
01467         minex_func.n = np;
01468         minex_func.params = (void *) &gsl_params;
01469 
01470         gsl_multimin_fminimizer *s = gsl_multimin_fminimizer_alloc(T, np);
01471         gsl_multimin_fminimizer_set(s, &minex_func, x, ss);
01472 
01473         int rval = GSL_CONTINUE;
01474         int status = GSL_SUCCESS;
01475         int iter = 1;
01476 
01477         float precision = params.set_default("precision",0.04f);
01478         int maxiter = params.set_default("maxiter",28);
01479 
01480 //      printf("Refine sx=%1.2f sy=%1.2f sa=%1.2f prec=%1.4f maxit=%d\n",stepx,stepy,stepaz,precision,maxiter);
01481 //      printf("%1.2f %1.2f %1.1f  ->",(float)gsl_vector_get(s->x, 0),(float)gsl_vector_get(s->x, 1),(float)gsl_vector_get(s->x, 2));
01482 
01483         while (rval == GSL_CONTINUE && iter < maxiter) {
01484                 iter++;
01485                 status = gsl_multimin_fminimizer_iterate(s);
01486                 if (status) {
01487                         break;
01488                 }
01489                 rval = gsl_multimin_test_size(gsl_multimin_fminimizer_size(s), precision);
01490         }
01491 
01492         int maxshift = params.set_default("maxshift",-1);
01493 
01494         if (maxshift <= 0) {
01495                 maxshift = this_img->get_xsize() / 4;
01496         }
01497         float fmaxshift = static_cast<float>(maxshift);
01498         if ( fmaxshift >= fabs((float)gsl_vector_get(s->x, 0)) && fmaxshift >= fabs((float)gsl_vector_get(s->x, 1)) && (stepscale==0 || (((float)gsl_vector_get(s->x, 3))<1.3 && ((float)gsl_vector_get(s->x, 3))<0.7))  )
01499         {
01500 //              printf(" Refine good %1.2f %1.2f %1.1f\n",(float)gsl_vector_get(s->x, 0),(float)gsl_vector_get(s->x, 1),(float)gsl_vector_get(s->x, 2));
01501                 Transform  tsoln(Dict("type","2d","alpha",(float)gsl_vector_get(s->x, 2)));
01502                 tsoln.set_mirror(mirror);
01503                 tsoln.set_trans((float)gsl_vector_get(s->x, 0),(float)gsl_vector_get(s->x, 1));
01504                 if (stepscale!=0.0) tsoln.set_scale((float)gsl_vector_get(s->x, 3));
01505                 result = this_img->process("xform",Dict("transform",&tsoln));
01506                 result->set_attr("xform.align2d",&tsoln);
01507         } else { // The refine aligner failed - this shift went beyond the max shift
01508 //              printf(" Refine Failed %1.2f %1.2f %1.1f\n",(float)gsl_vector_get(s->x, 0),(float)gsl_vector_get(s->x, 1),(float)gsl_vector_get(s->x, 2));
01509                 result = this_img->process("xform",Dict("transform",t));
01510                 result->set_attr("xform.align2d",t);
01511         }
01512 
01513         delete t;
01514         t = 0;
01515 
01516         gsl_vector_free(x);
01517         gsl_vector_free(ss);
01518         gsl_multimin_fminimizer_free(s);
01519 
01520         if ( c != 0 ) delete c;
01521         return result;
01522 }
01523 
01524 static Transform refalin3d_perturbquat(const Transform*const t, const float& spincoeff, const float& n0, const float& n1, const float& n2, const float& x, const float& y, const float& z)
01525 {
01526         Vec3f normal(n0,n1,n2);
01527         normal.normalize();
01528         
01529         float omega = spincoeff*sqrt(n0*n0 + n1*n1 + n2*n2); // Here we compute the spin by the rotation axis vector length
01530         Dict d;
01531         d["type"] = "spin";
01532         d["Omega"] = omega;
01533         d["n1"] = normal[0];
01534         d["n2"] = normal[1];
01535         d["n3"] = normal[2];
01536         //cout << omega << " " << normal[0] << " " << normal[1] << " " << normal[2] << " " << n0 << " " << n1 << " " << n2 << endl;
01537         
01538         Transform q(d);
01539         q.set_trans((float)x,(float)y,(float)z);
01540         
01541         q = q*(*t); //compose transforms        
01542         
01543         return q;
01544 }
01545 
01546 static double refalifn3dquat(const gsl_vector * v, void *params)
01547 {
01548         Dict *dict = (Dict *) params;
01549 
01550         double n0 = gsl_vector_get(v, 0);
01551         double n1 = gsl_vector_get(v, 1);
01552         double n2 = gsl_vector_get(v, 2);
01553         double x = gsl_vector_get(v, 3);
01554         double y = gsl_vector_get(v, 4);
01555         double z = gsl_vector_get(v, 5);
01556 
01557         EMData *this_img = (*dict)["this"];
01558         EMData *with = (*dict)["with"];
01559 //      bool mirror = (*dict)["mirror"];
01560 
01561         Transform* t = (*dict)["transform"];
01562         float spincoeff = (*dict)["spincoeff"];
01563 
01564         Transform soln = refalin3d_perturbquat(t,spincoeff,(float)n0,(float)n1,(float)n2,(float)x,(float)y,(float)z);
01565 
01566         EMData *tmp = this_img->process("xform",Dict("transform",&soln));
01567         Cmp* c = (Cmp*) ((void*)(*dict)["cmp"]);
01568         double result = c->cmp(tmp,with);
01569         if ( tmp != 0 ) delete tmp;
01570         delete t; t = 0;
01571         //cout << result << endl;
01572         return result;
01573 }
01574 
01575 EMData* Refine3DAlignerQuaternion::align(EMData * this_img, EMData *to,
01576         const string & cmp_name, const Dict& cmp_params) const
01577 {
01578         
01579         if (!to || !this_img) throw NullPointerException("Input image is null"); // not sure if this is necessary, it was there before I started
01580 
01581         if (to->get_ndim() != 3 || this_img->get_ndim() != 3) throw ImageDimensionException("The Refine3D aligner only works for 3D images");
01582 
01583 #ifdef EMAN2_USING_CUDA 
01584         if(EMData::usecuda == 1) {
01585                 if(!this_img->getcudarwdata()) this_img->copy_to_cuda();
01586                 if(!to->getcudarwdata()) to->copy_to_cuda();
01587         }
01588 #endif
01589 
01590         float sdi = 0.0;
01591         float sdj = 0.0;
01592         float sdk = 0.0;
01593         float sdx = 0.0;
01594         float sdy = 0.0;
01595         float sdz = 0.0;
01596         bool mirror = false;
01597         
01598         Transform* t;
01599         if (params.has_key("xform.align3d") ) {
01600                 // Unlike the 2d refine aligner, this class doesn't require the starting transform's
01601                 // parameters to form the starting guess. Instead the Transform itself
01602                 // is perturbed carefully (using quaternion rotation) to overcome problems that arise
01603                 // when you use orthogonally-based Euler angles
01604                 t = params["xform.align3d"];
01605         }else {
01606                 t = new Transform(); // is the identity
01607         }
01608         
01609         float spincoeff =  params.set_default("spin_coeff",10.0f); // spin coefficient, controls speed of convergence (sort of)
01610         
01611         int np = 6; // the number of dimensions
01612         Dict gsl_params;
01613         gsl_params["this"] = this_img;
01614         gsl_params["with"] = to;
01615         gsl_params["snr"]  = params["snr"];
01616         gsl_params["mirror"] = mirror;
01617         gsl_params["transform"] = t;    
01618         gsl_params["spincoeff"] = spincoeff;
01619         Dict altered_cmp_params(cmp_params);
01620         
01621         const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
01622         gsl_vector *ss = gsl_vector_alloc(np);
01623         
01624         float stepi = params.set_default("stepi",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway
01625         float stepj = params.set_default("stepj",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway
01626         float stepk = params.set_default("stepk",1.0f); // doesn't really matter b/c the vecor part will be normalized anyway
01627         float stepx = params.set_default("stepx",1.0f);
01628         float stepy = params.set_default("stepy",1.0f);
01629         float stepz = params.set_default("stepz",1.0f);
01630         
01631         //gsl_vector_set(ss, 0, stepw);
01632         gsl_vector_set(ss, 0, stepi);
01633         gsl_vector_set(ss, 1, stepj);
01634         gsl_vector_set(ss, 2, stepk);
01635         gsl_vector_set(ss, 3, stepx);
01636         gsl_vector_set(ss, 4, stepy);
01637         gsl_vector_set(ss, 5, stepz);
01638         
01639         gsl_vector *x = gsl_vector_alloc(np);
01640         gsl_vector_set(x, 0, sdi);
01641         gsl_vector_set(x, 1, sdj);
01642         gsl_vector_set(x, 2, sdk);
01643         gsl_vector_set(x, 3, sdx);
01644         gsl_vector_set(x, 4, sdy);
01645         gsl_vector_set(x, 5, sdz);
01646         
01647         gsl_multimin_function minex_func;
01648         Cmp *c = Factory < Cmp >::get(cmp_name, altered_cmp_params);
01649                 
01650         gsl_params["cmp"] = (void *) c;
01651         minex_func.f = &refalifn3dquat;
01652 
01653         minex_func.n = np;
01654         minex_func.params = (void *) &gsl_params;
01655         
01656         gsl_multimin_fminimizer *s = gsl_multimin_fminimizer_alloc(T, np);
01657         gsl_multimin_fminimizer_set(s, &minex_func, x, ss);
01658         
01659         int rval = GSL_CONTINUE;
01660         int status = GSL_SUCCESS;
01661         int iter = 1;
01662         
01663         float precision = params.set_default("precision",0.01f);
01664         int maxiter = params.set_default("maxiter",100);
01665         while (rval == GSL_CONTINUE && iter < maxiter) {
01666                 iter++;
01667                 status = gsl_multimin_fminimizer_iterate(s);
01668                 if (status) {
01669                         break;
01670                 }
01671                 rval = gsl_multimin_test_size(gsl_multimin_fminimizer_size(s), precision);
01672         }
01673 
01674         int maxshift = params.set_default("maxshift",-1);
01675 
01676         if (maxshift <= 0) {
01677                 maxshift = this_img->get_xsize() / 4;
01678         }
01679         float fmaxshift = static_cast<float>(maxshift);
01680         
01681         EMData *result;
01682         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))
01683         {
01684                 float n0 = (float)gsl_vector_get(s->x, 0);
01685                 float n1 = (float)gsl_vector_get(s->x, 1);
01686                 float n2 = (float)gsl_vector_get(s->x, 2);
01687                 float x = (float)gsl_vector_get(s->x, 3);
01688                 float y = (float)gsl_vector_get(s->x, 4);
01689                 float z = (float)gsl_vector_get(s->x, 5);
01690                 
01691                 Transform tsoln = refalin3d_perturbquat(t,spincoeff,n0,n1,n2,x,y,z);
01692                         
01693                 result = this_img->process("xform",Dict("transform",&tsoln));
01694                 result->set_attr("xform.align3d",&tsoln);
01695                 result->set_attr("score", result->cmp(cmp_name,to,cmp_params));
01696                 
01697          //coda goes here
01698         } else { // The refine aligner failed - this shift went beyond the max shift
01699                 result = this_img->process("xform",Dict("transform",t));
01700                 result->set_attr("xform.align3d",t);
01701         }
01702         
01703         //EMData *result = this_img->process("xform",Dict("transform",t));
01704         delete t;
01705         t = 0;
01706         gsl_vector_free(x);
01707         gsl_vector_free(ss);
01708         gsl_multimin_fminimizer_free(s);
01709 
01710         if ( c != 0 ) delete c;
01711         return result;
01712 }
01713 
01714 EMData*Refine3DAlignerGrid::align(EMData * this_img, EMData *to,
01715         const string & cmp_name, const Dict& cmp_params) const
01716 {
01717         if ( this_img->get_ndim() != 3 || to->get_ndim() != 3 ) {
01718                 throw ImageDimensionException("This aligner only works for 3D images");
01719         }
01720 
01721         Transform* t;
01722         if (params.has_key("xform.align3d") ) {
01723                 // Unlike the 2d refine aligner, this class doesn't require the starting transform's
01724                 // parameters to form the starting guess. Instead the Transform itself
01725                 // is perturbed carefully (using quaternion rotation) to overcome problems that arise
01726                 // when you use orthogonally-based Euler angles
01727                 t = params["xform.align3d"];
01728         }else {
01729                 t = new Transform(); // is the identity
01730         }
01731         
01732         int searchx = 0;
01733         int searchy = 0;
01734         int searchz = 0;
01735         
01736         bool dotrans = params.set_default("dotrans",1);
01737         if (params.has_key("search")) {
01738                 vector<string> check;
01739                 check.push_back("searchx");
01740                 check.push_back("searchy");
01741                 check.push_back("searchz");
01742                 for(vector<string>::const_iterator cit = check.begin(); cit != check.end(); ++cit) {
01743                         if (params.has_key(*cit)) throw InvalidParameterException("The search parameter is mutually exclusive of the searchx, searchy, and searchz parameters");
01744                 }
01745                 int search  = params["search"];
01746                 searchx = search;
01747                 searchy = search;
01748                 searchz = search;
01749         } else {
01750                 searchx = params.set_default("searchx",3);
01751                 searchy = params.set_default("searchy",3);
01752                 searchz = params.set_default("searchz",3);
01753         }       
01754         
01755         float delta = params.set_default("delta",1.0f);
01756         float range = params.set_default("range",10.0f);
01757         bool verbose = params.set_default("verbose",false);
01758         
01759         bool tomography = (cmp_name == "ccc.tomo") ? 1 : 0;
01760         EMData * tofft = 0;
01761         if(dotrans || tomography){
01762                 tofft = to->do_fft();
01763         }
01764         
01765 #ifdef EMAN2_USING_CUDA 
01766         if(EMData::usecuda == 1) {
01767                 if(!this_img->isrodataongpu()) this_img->copy_to_cudaro();
01768                 if(!to->getcudarwdata()) to->copy_to_cuda();
01769                 if(to->getcudarwdata()){if(tofft) tofft->copy_to_cuda();}
01770         }
01771 #endif
01772 
01773         Dict d;
01774         d["type"] = "eman"; // d is used in the loop below
01775         Dict best;
01776         best["score"] = 0.0f;
01777         bool use_cpu = true;
01778         Transform tran = Transform();
01779         for ( float alt = 0; alt < range; alt += delta) {
01780                 // now compute a sane az step size 
01781                 float saz = 360;
01782                 if(alt != 0) saz = delta/sin(alt*M_PI/180.0f); // This gives consistent az step sizes(arc lengths)
01783                 for ( float az = 0; az < 360; az += saz ){
01784                         if (verbose) {
01785                                 cout << "Trying angle alt " << alt << " az " << az << endl;
01786                         }
01787                         // account for any changes in az
01788                         for( float phi = -range-az; phi < range-az; phi += delta ) {
01789                                 d["alt"] = alt;
01790                                 d["phi"] = phi; 
01791                                 d["az"] = az;
01792                                 Transform tr(d);
01793                                 tr = tr*(*t);   // compose transforms, this moves to the pole (aprox)
01794                                 
01795                                 EMData* transformed = this_img->process("xform",Dict("transform",&tr));
01796                                 
01797                                 //need to do things a bit diffrent if we want to compare two tomos
01798                                 float score = 0.0f;
01799                                 if(dotrans || tomography){
01800                                         EMData* ccf = transformed->calc_ccf(tofft);
01801 #ifdef EMAN2_USING_CUDA 
01802                                         if(to->getcudarwdata()){
01803                                                 use_cpu = false;
01804                                                 CudaPeakInfo* data = calc_max_location_wrap_cuda(ccf->getcudarwdata(), ccf->get_xsize(), ccf->get_ysize(), ccf->get_zsize(), searchx, searchy, searchz);
01805                                                 tran.set_trans((float)-data->px, (float)-data->py, (float)-data->pz);
01806                                                 //CudaPeakInfoFloat* data = calc_max_location_wrap_intp_cuda(ccf->getcudarwdata(), ccf->get_xsize(), ccf->get_ysize(), ccf->get_zsize(), searchx, searchy, searchz);
01807                                                 //tran.set_trans(-data->xintp, -data->yintp, -data->zintp);
01808                                                 tr = tran*tr;
01809                                                 if (tomography) {
01810                                                         float2 stats = get_stats_cuda(ccf->getcudarwdata(), ccf->get_xsize(), ccf->get_ysize(), ccf->get_zsize());
01811                                                         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
01812                                                 } else {
01813                                                         score = -data->peak;
01814                                                 }
01815                                                 delete data;
01816                                         }
01817 #endif
01818                                         if(use_cpu){
01819                                                 if(tomography) ccf->process_inplace("normalize");
01820                                                 //vector<float> fpoint = ccf->calc_max_location_wrap_intp(searchx,searchy,searchz);
01821                                                 //tran.set_trans(-fpoint[0], -fpoint[1], -fpoint[2]);
01822                                                 //score = -fpoint[3];
01823                                                 IntPoint point = ccf->calc_max_location_wrap(searchx,searchy,searchz);
01824                                                 tran.set_trans((float)-point[0], (float)-point[1], (float)-point[2]);
01825                                                 score = -ccf->get_value_at_wrap(point[0], point[1], point[2]);
01826                                                 tr = tran*tr;
01827                                                 
01828                                         }
01829                                         delete ccf; ccf =0;
01830                                         delete transformed; transformed = 0;// this is to stop a mem leak
01831                                 }
01832 
01833                                 if(!tomography){
01834                                         if(!transformed) transformed = this_img->process("xform",Dict("transform",&tr)); // we are returning a map
01835                                         score = transformed->cmp(cmp_name,to,cmp_params); //this is not very efficient as it creates a new cmp object for each iteration
01836                                         delete transformed; transformed = 0;// this is to stop a mem leak
01837                                 }
01838                                 
01839                                 if(score < float(best["score"])) {
01840                                         best["score"] = score;
01841                                         best["xform.align3d"] = &tr; // I wonder if this will cause a mem leak?
01842                                 }       
01843                         }
01844                 }
01845         }
01846 
01847         if(tofft) {delete tofft; tofft = 0;}
01848         
01849         //make aligned map;
01850         EMData* best_match = this_img->process("xform",Dict("transform", best["xform.align3d"])); // we are returning a map
01851         best_match->set_attr("xform.align3d", best["xform.align3d"]);
01852         best_match->set_attr("score", float(best["score"]));
01853         
01854         //debug....
01855         Transform* zz = best_match->get_attr("xform.align3d");
01856         Vec3f zzz = zz->get_trans();
01857         cout << "x " << float(zzz[0]) << " y " << float(zzz[1]) << " z " << float(zzz[2]) << endl;
01858         
01859         return best_match;
01860         
01861 }
01862 
01863 EMData* RT3DGridAligner::align(EMData * this_img, EMData *to, const string & cmp_name, const Dict& cmp_params) const
01864 {
01865 
01866         vector<Dict> alis = xform_align_nbest(this_img,to,1,cmp_name,cmp_params);
01867 
01868         Dict t;
01869         Transform* tr = (Transform*) alis[0]["xform.align3d"];
01870         t["transform"] = tr;
01871         EMData* soln = this_img->process("xform",t);
01872         soln->set_attr("xform.align3d",tr);
01873         delete tr; tr = 0;
01874 
01875         return soln;
01876 
01877 }
01878 
01879 vector<Dict> RT3DGridAligner::xform_align_nbest(EMData * this_img, EMData * to, const unsigned int nsoln, const string & cmp_name, const Dict& cmp_params) const {
01880 
01881         if ( this_img->get_ndim() != 3 || to->get_ndim() != 3 ) {
01882                 throw ImageDimensionException("This aligner only works for 3D images");
01883         }
01884 
01885         int searchx = 0;
01886         int searchy = 0;
01887         int searchz = 0;
01888         
01889         bool dotrans = params.set_default("dotrans",1);
01890         if (params.has_key("search")) {
01891                 vector<string> check;
01892                 check.push_back("searchx");
01893                 check.push_back("searchy");
01894                 check.push_back("searchz");
01895                 for(vector<string>::const_iterator cit = check.begin(); cit != check.end(); ++cit) {
01896                         if (params.has_key(*cit)) throw InvalidParameterException("The search parameter is mutually exclusive of the searchx, searchy, and searchz parameters");
01897                 }
01898                 int search  = params["search"];
01899                 searchx = search;
01900                 searchy = search;
01901                 searchz = search;
01902         } else {
01903                 searchx = params.set_default("searchx",3);
01904                 searchy = params.set_default("searchy",3);
01905                 searchz = params.set_default("searchz",3);
01906         }
01907 
01908         float lalt = params.set_default("alt0",0.0f);
01909         float laz = params.set_default("az0",0.0f);
01910         float lphi = params.set_default("phi0",0.0f);
01911         float ualt = params.set_default("alt1",180.0f); // I am using 179.9 rather than 180 to avoid resampling
01912         float uphi = params.set_default("phi1",360.0f); // I am using 359.9 rather than 180 to avoid resampling 0 = 360 (for perodic functions)
01913         float uaz = params.set_default("az1",360.0f);   // I am using 359.9 rather than 180 to avoid resampling 0 = 360 (for perodic functions)
01914         float dalt = params.set_default("dalt",10.f);
01915         float daz = params.set_default("daz",10.f);
01916         float dphi = params.set_default("dphi",10.f);
01917         bool verbose = params.set_default("verbose",false);
01918         
01919         //in case we arre aligning tomos
01920         Dict altered_cmp_params(cmp_params);
01921         if (cmp_name == "ccc.tomo") {
01922                 altered_cmp_params.set_default("searchx", searchx);
01923                 altered_cmp_params.set_default("searchy", searchy);
01924                 altered_cmp_params.set_default("searchz", searchz);
01925                 altered_cmp_params.set_default("norm", true);
01926         }
01927 
01928         vector<Dict> solns;
01929         if (nsoln == 0) return solns; // What was the user thinking?
01930         for (unsigned int i = 0; i < nsoln; ++i ) {
01931                 Dict d;
01932                 d["score"] = 1.e24;
01933                 Transform t; // identity by default
01934                 d["xform.align3d"] = &t; // deep copy is going on here
01935                 solns.push_back(d);
01936         }
01937         
01938         bool tomography = (cmp_name == "ccc.tomo") ? 1 : 0;
01939         EMData * tofft = 0;
01940         if(dotrans || tomography){
01941                 tofft = to->do_fft();
01942         }
01943         
01944 #ifdef EMAN2_USING_CUDA 
01945         if(EMData::usecuda == 1) {
01946                 if(!this_img->isrodataongpu()) this_img->copy_to_cudaro();
01947                 if(!to->getcudarwdata()) to->copy_to_cuda();
01948                 if(to->getcudarwdata()){if(tofft) tofft->copy_to_cuda();}
01949         }
01950 #endif
01951 
01952         Dict d;
01953         d["type"] = "eman"; // d is used in the loop below
01954         Transform trans = Transform();
01955         bool use_cpu = true;
01956         for ( float alt = lalt; alt <= ualt; alt += dalt) {
01957                 // An optimization for the range of az is made at the top of the sphere
01958                 // If you think about it, this is just a coarse way of making this approach slightly more efficient
01959                 for ( float az = laz; az < uaz; az += daz ){
01960                         if (verbose) {
01961                                 cout << "Trying angle alt " << alt << " az " << az << endl;
01962                         }
01963                         for( float phi = lphi; phi < uphi; phi += dphi ) {
01964                                 d["alt"] = alt;
01965                                 d["phi"] = phi; 
01966                                 d["az"] = az;
01967                                 Transform t(d);
01968                                 EMData* transformed = this_img->process("xform",Dict("transform",&t));
01969                                 
01970                                 //need to do things a bit diffrent if we want to compare two tomos
01971                                 float best_score = 0.0f;
01972                                 if(dotrans || tomography){
01973                                         EMData* ccf = transformed->calc_ccf(tofft);
01974 #ifdef EMAN2_USING_CUDA 
01975                                         if(to->getcudarwdata()){
01976                                                 use_cpu = false;;
01977                                                 CudaPeakInfo* data = calc_max_location_wrap_cuda(ccf->getcudarwdata(), ccf->get_xsize(), ccf->get_ysize(), ccf->get_zsize(), searchx, searchy, searchz);
01978                                                 trans.set_trans((float)-data->px, (float)-data->py, (float)-data->pz);
01979                                                 t = trans*t;    //composite transfrom
01980                                                 if (tomography) {
01981                                                         float2 stats = get_stats_cuda(ccf->getcudarwdata(), ccf->get_xsize(), ccf->get_ysize(), ccf->get_zsize());
01982                                                         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
01983                                                 } else {
01984                                                         best_score = -data->peak;
01985                                                 }
01986                                                 delete data;
01987                                         }
01988 #endif
01989                                         if(use_cpu){
01990                                                 if(tomography) ccf->process_inplace("normalize");       
01991                                                 IntPoint point = ccf->calc_max_location_wrap(searchx,searchy,searchz);
01992                                                 trans.set_trans((float)-point[0], (float)-point[1], (float)-point[2]);
01993                                                 t = trans*t;    //composite transfrom
01994                                                 best_score = -ccf->get_value_at_wrap(point[0], point[1], point[2]);
01995                                         }
01996                                         delete ccf; ccf =0;
01997                                         delete transformed; transformed = 0;
01998                                 }
01999 
02000                                 if(!tomography){
02001                                         if(!transformed) transformed = this_img->process("xform",Dict("transform",&t));
02002                                         best_score = transformed->cmp(cmp_name,to,cmp_params); //this is not very efficient as it creates a new cmp object for each iteration
02003                                         delete transformed; transformed = 0;
02004                                 }
02005                                 
02006                                 unsigned int j = 0;
02007                                 for ( vector<Dict>::iterator it = solns.begin(); it != solns.end(); ++it, ++j ) {
02008                                         if ( (float)(*it)["score"] > best_score ) {  // Note greater than - EMAN2 preferes minimums as a matter of policy
02009                                                 vector<Dict>::reverse_iterator rit = solns.rbegin();
02010                                                 copy(rit+1,solns.rend()-j,rit);
02011                                                 Dict& d = (*it);
02012                                                 d["score"] = best_score;
02013                                                 d["xform.align3d"] = &t;
02014                                                 break;
02015                                         }
02016                                 }
02017                         }
02018                 }
02019         }
02020 
02021         if(tofft) {delete tofft; tofft = 0;}
02022         return solns;
02023 
02024 }
02025 
02026 EMData* RT3DSphereAligner::align(EMData * this_img, EMData *to, const string & cmp_name, const Dict& cmp_params) const
02027 {
02028 
02029         vector<Dict> alis = xform_align_nbest(this_img,to,1,cmp_name,cmp_params);
02030 
02031         Dict t;
02032         Transform* tr = (Transform*) alis[0]["xform.align3d"];
02033         t["transform"] = tr;
02034         EMData* soln = this_img->process("xform",t);
02035         soln->set_attr("xform.align3d",tr);
02036         delete tr; tr = 0;
02037 
02038         return soln;
02039 
02040 }
02041 
02042 vector<Dict> RT3DSphereAligner::xform_align_nbest(EMData * this_img, EMData * to, const unsigned int nsoln, const string & cmp_name, const Dict& cmp_params) const {
02043 
02044         if ( this_img->get_ndim() != 3 || to->get_ndim() != 3 ) {
02045                 throw ImageDimensionException("This aligner only works for 3D images");
02046         }
02047 
02048         int searchx = 0;
02049         int searchy = 0;
02050         int searchz = 0;
02051          
02052         bool dotrans = params.set_default("dotrans",1);
02053         if (params.has_key("search")) {
02054                 vector<string> check;
02055                 check.push_back("searchx");
02056                 check.push_back("searchy");
02057                 check.push_back("searchz");
02058                 for(vector<string>::const_iterator cit = check.begin(); cit != check.end(); ++cit) {
02059                         if (params.has_key(*cit)) throw InvalidParameterException("The search parameter is mutually exclusive of the searchx, searchy, and searchz parameters");
02060                 }
02061                 int search  = params["search"];
02062                 searchx = search;
02063                 searchy = search;
02064                 searchz = search;
02065         } else {
02066                 searchx = params.set_default("searchx",3);
02067                 searchy = params.set_default("searchy",3);
02068                 searchz = params.set_default("searchz",3);
02069         }
02070 
02071         float lphi = params.set_default("phi0",0.0f);
02072         float uphi = params.set_default("phi1",360.0f);
02073         float dphi = params.set_default("dphi",10.f);
02074         float threshold = params.set_default("threshold",0.f);
02075         if (threshold < 0.0f) throw InvalidParameterException("The threshold parameter must be greater than or equal to zero");
02076         bool verbose = params.set_default("verbose",false);
02077         
02078         //in case we arre aligning tomos
02079         Dict altered_cmp_params(cmp_params);
02080         if (cmp_name == "ccc.tomo") {
02081                 altered_cmp_params.set_default("searchx", searchx);
02082                 altered_cmp_params.set_default("searchy", searchy);
02083                 altered_cmp_params.set_default("searchz", searchz);
02084                 altered_cmp_params.set_default("norm", true);
02085         }
02086 
02087         vector<Dict> solns;
02088         if (nsoln == 0) return solns; // What was the user thinking?
02089         for (unsigned int i = 0; i < nsoln; ++i ) {
02090                 Dict d;
02091                 d["score"] = 1.e24;
02092                 Transform t; // identity by default
02093                 d["xform.align3d"] = &t; // deep copy is going on here
02094                 solns.push_back(d);
02095         }
02096 
02097         Dict d;
02098         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
02099         if ( params.has_key("delta") && params.has_key("n") ) {
02100                 throw InvalidParameterException("The delta and n parameters are mutually exclusive in the RT3DSphereAligner aligner");
02101         } else if ( params.has_key("n") ) {
02102                 d["n"] = params["n"];
02103         } else {
02104                 // If they didn't specify either then grab the default delta - if they did supply delta we're still safe doing this
02105                 d["delta"] = params.set_default("delta",10.f);
02106         }
02107 
02108         if ((string)params.set_default("orientgen","eman")=="eman") d["perturb"]=0;
02109         Symmetry3D* sym = Factory<Symmetry3D>::get((string)params.set_default("sym","c1"));
02110         vector<Transform> transforms = sym->gen_orientations((string)params.set_default("orientgen","eman"),d);
02111 
02112         bool tomography = (cmp_name == "ccc.tomo") ? 1 : 0;
02113         
02114         //precompute fixed FT, saves a LOT of time!!!
02115         EMData * this_imgfft = 0;
02116         if(dotrans || tomography){
02117                 this_imgfft = this_img->do_fft();
02118         }
02119         
02120         
02121 #ifdef EMAN2_USING_CUDA 
02122         if(EMData::usecuda == 1) {
02123                 cout << "Using CUDA for 3D alignment" << endl;
02124                 if(!to->isrodataongpu()) to->copy_to_cudaro();
02125                 if(!this_img->getcudarwdata()) this_img->copy_to_cuda();
02126                 if(this_imgfft) this_imgfft->copy_to_cuda();
02127         }
02128 #endif
02129 
02130         Transform trans = Transform();
02131         bool use_cpu = true;
02132         for(vector<Transform>::const_iterator trans_it = transforms.begin(); trans_it != transforms.end(); trans_it++) {
02133                 Dict params = trans_it->get_params("eman");
02134                 
02135                 if (verbose) {
02136                         float alt = params["alt"];
02137                         float az = params["az"];
02138                         cout << "Trying angle alt: " << alt << " az: " << az << endl;
02139                 }
02140 
02141                 for( float phi = lphi; phi < uphi; phi += dphi ) { 
02142                         Transform t(params);
02143                         params["phi"] = phi;
02144                         t.set_rotation(params);
02145                         EMData* transformed = to->process("xform",Dict("transform",&t));
02146                         
02147                         //need to do things a bit diffrent if we want to compare two tomos
02148                         float best_score = 0.0f;
02149                         // Dotrans is effectievly ignored for tomography
02150                         if(dotrans || tomography){
02151                                 EMData* ccf = transformed->calc_ccf(this_imgfft);
02152 #ifdef EMAN2_USING_CUDA 
02153                                 if(this_img->getcudarwdata()){
02154                                         use_cpu = false;
02155                                         CudaPeakInfo* data = calc_max_location_wrap_cuda(ccf->getcudarwdata(), ccf->get_xsize(), ccf->get_ysize(), ccf->get_zsize(), searchx, searchy, searchz);
02156                                         trans.set_trans((float)-data->px, (float)-data->py, (float)-data->pz);
02157                                         t = trans*t;    //composite transform
02158                                         if (tomography) {
02159                                                 float2 stats = get_stats_cuda(ccf->getcudarwdata(), ccf->get_xsize(), ccf->get_ysize(), ccf->get_zsize());
02160                                                 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
02161                                         } else {
02162                                                 best_score = -data->peak;
02163                                         }
02164                                         delete data;
02165                                 }
02166 #endif
02167                                 if(use_cpu){
02168                                         if(tomography) ccf->process_inplace("normalize");
02169                                         IntPoint point = ccf->calc_max_location_wrap(searchx,searchy,searchz);
02170                                         trans.set_trans((float)-point[0], (float)-point[1], (float)-point[2]);
02171                                         t = trans*t;    //composite transform 
02172                                         best_score = -ccf->get_value_at_wrap(point[0], point[1], point[2]);
02173                                 }
02174                                 delete ccf; ccf =0;
02175                                 delete transformed; transformed = 0;// this is to stop a mem leak
02176                         }
02177 
02178                         if(!tomography){
02179                                 if(!transformed) transformed = to->process("xform",Dict("transform",&t));
02180                                 best_score = transformed->cmp(cmp_name,this_img,cmp_params); //this is not very efficient as it creates a new cmp object for each iteration
02181                                 delete transformed; transformed = 0;
02182                         }
02183 
02184                         unsigned int j = 0;
02185                         //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;
02186                         for ( vector<Dict>::iterator it = solns.begin(); it != solns.end(); ++it, ++j ) {
02187                                 if ( (float)(*it)["score"] > best_score ) { // Note greater than - EMAN2 preferes minimums as a matter of policy
02188                                         vector<Dict>::reverse_iterator rit = solns.rbegin();
02189                                         copy(rit+1,solns.rend()-j,rit);
02190                                         Dict& d = (*it);
02191                                         d["score"] = best_score;
02192                                         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)
02193                                         d["xform.align3d"] = &t; // deep copy is going on here
02194                                         break;
02195                                 }
02196                         }
02197 
02198                 }
02199         }
02200         delete sym; sym = 0;
02201         if(this_imgfft) {delete this_imgfft; this_imgfft = 0;}
02202         return solns;
02203 
02204 }
02205 
02206 //Could refactor the code here......(But not really woth it)
02207 EMData* RT3DSymmetryAligner::align(EMData * this_img, EMData *to, const string & cmp_name, const Dict& cmp_params) const
02208 {
02209 
02210         vector<Dict> alis = xform_align_nbest(this_img,to,1,cmp_name,cmp_params);
02211 
02212         Dict t;
02213         Transform* tr = (Transform*) alis[0]["xform.align3d"];
02214         t["transform"] = tr;
02215         EMData* soln = this_img->process("xform",t);
02216         soln->set_attr("xform.align3d",tr);
02217         delete tr; tr = 0;
02218 
02219         return soln;
02220 
02221 }
02222 
02223 vector<Dict> RT3DSymmetryAligner::xform_align_nbest(EMData * this_img, EMData * to, const unsigned int nsoln, const string & cmp_name, const Dict& cmp_params) const 
02224 {
02225         
02226         bool verbose = params.set_default("verbose",false);
02227         //Initialize a soln dict
02228         vector<Dict> solns;
02229         if (nsoln == 0) return solns; // What was the user thinking?
02230         for (unsigned int i = 0; i < nsoln; ++i ) {
02231                 Dict d;
02232                 d["score"] = 1.e24;
02233                 Transform t; // identity by default
02234                 d["xform.align3d"] = &t; // deep copy is going on here
02235                 solns.push_back(d);
02236         }
02237         
02238         //Genrate symmetry related orritenations
02239         vector<Transform> syms = Symmetry3D::get_symmetries((string)params.set_default("sym","icos"));
02240         
02241         float score = 0.0f;
02242         for ( vector<Transform>::const_iterator symit = syms.begin(); symit != syms.end(); ++symit ) {
02243                 Transform sympos = *symit; //stupidly this is necessary!!!
02244                 //Here move to sym position and compute the score
02245                 EMData* transformed = this_img->process("xform",Dict("transform",&sympos));
02246                 score = transformed->cmp(cmp_name,this_img,cmp_params);
02247                 delete transformed; transformed = 0;
02248                 
02249                 if (verbose) {
02250                         Dict rots = sympos.get_rotation("eman");
02251                         cout <<"Score is: " << score << " az " << float(rots["az"]) << " alt " << float(rots["alt"]) << " phi " << float(rots["phi"]) << endl;
02252                 }
02253                 
02254                 unsigned int j = 0;
02255                 for ( vector<Dict>::iterator it = solns.begin(); it != solns.end(); ++it, ++j ) {
02256                         if ( (float)(*it)["score"] > score ) { // Note greater than - EMAN2 preferes minimums as a matter of policy
02257                                 vector<Dict>::reverse_iterator rit = solns.rbegin();
02258                                 copy(rit+1,solns.rend()-j,rit);
02259                                 Dict& d = (*it);
02260                                 d["score"] = score;
02261                                 d["xform.align3d"] = &sympos; // deep copy is going on here
02262                                 break;
02263                         }
02264                 }
02265         }
02266         return solns;
02267 }
02268 
02269 namespace {
02270 float frm_2d_Align(EMData *this_img, EMData *to, float *frm2dhhat, EMData* selfpcsfft, int p_max_input,int rsize, float &com_this_x, float &com_this_y, float &com_with_x, float &com_with_y,const string & cmp_name, const Dict& cmp_params)
02271 {
02272         int size=rsize;
02273         float dx,dy;
02274         int bw=size/2;
02275         int MAXR=this_img->get_ysize()/2;
02276         //int MAXR=size;
02277         unsigned long tsize=2*size;
02278         unsigned long ind1=0, ind2=0, ind3=0, ind4=0, ind41=0;
02279         unsigned long index0=0;
02280         int i=0, j=0, m=0, n=0, r=0;
02281         int loop_rho=0, rho_best=0;
02282 
02283         float* gnr2   = new float[size*2];
02284         float* maxcor = new float[size+1];                  // MAXR need change
02285 
02286         int p_max=p_max_input;
02287         float* result = new float[5*(p_max+1)];
02288         float* cr=new float[size*(bw+1)];
02289         float* ci=new float[size*(bw+1)];
02290         EMData *data_in=new EMData;
02291         data_in->set_complex(true);
02292         data_in->set_fftodd(false);
02293         data_in->set_ri(true);
02294         data_in->set_size(size+2,size,1);
02295         float *in=data_in->get_data();
02296 
02297         float *self_sampl_fft = selfpcsfft->get_data(); // ming f(r)
02298 
02299         float maxcor_sofar=0.0f;
02300         int p=0;
02301 
02302         for(p=0; p<=p_max; ++p){
02303                 ind1=p*size*bw;
02304                 for (i=0;i<size;++i)
02305                         for (j=0;j<bw+1;++j){
02306                                 cr[i*(bw+1)+j]=0.0;
02307                                 ci[i*(bw+1)+j]=0.0;
02308                         }
02309         for(n=0;n<bw;++n){                                // loop for n
02310                 ind2=(ind1+n);
02311                 index0=n*(bw+1);
02312                         for(r=0;r<=MAXR;++r) {
02313                         ind3=(ind2+r*bw)*size;
02314                         for(m=0;m<size;m++){              // take back hat{h(n,r,p)}(m)
02315                                 ind4=(ind3+m)*2;
02316                                     ind41=ind4+1;
02317                                     gnr2[2*m]=frm2dhhat[ind4];
02318                                     gnr2[2*m+1]=frm2dhhat[ind41];
02319                                 }
02320                         for(m=0;m<bw;++m){
02321                                         float tempr=self_sampl_fft[2*m+r*(size+2)]*r;
02322                                 float tempi=self_sampl_fft[2*m+1+r*(size+2)]*r;
02323                                 float gnr2_r=gnr2[2*m];
02324                                 float gnr2_i=gnr2[2*m+1];
02325                                 cr[n*(bw+1)+m]+=gnr2_r*tempr+gnr2_i*tempi;
02326                                         ci[n*(bw+1)+m]+=gnr2_i*tempr-gnr2_r*tempi;
02327                                         if(n!=0){                                       // m,-n
02328                                         if(m!= 0){
02329                                                 int ssize=tsize-2*m;    // ssize = 2*size-2m
02330                                                 int ssize1=ssize+1;
02331                                                 float gnr2_r=gnr2[ssize];
02332                                                 float gnr2_i=gnr2[ssize1];
02333                                                         cr[(size-n)*(bw+1)+m]+=gnr2_r*tempr-gnr2_i*tempi;
02334                                                 ci[(size-n)*(bw+1)+m]-=gnr2_i*tempr+gnr2_r*tempi;
02335                                         }
02336                                                 else{
02337                                                         cr[(size-n)*(bw+1)+m]+=*(gnr2)*tempr-*(gnr2+1)*tempi;
02338                                                         ci[(size-n)*(bw+1)+m]-=*(gnr2+1)*tempr+*(gnr2)*tempi;
02339                                                 }
02340                                 }
02341                                 }
02342                         }
02343         }
02344         for (int cii=0; cii<size*(bw+1);++cii){
02345                         in[2*cii]=cr[cii];
02346                         in[2*cii+1]=ci[cii];
02347                         //printf("cii=%d,in[2i+1]=%f\n",cii, cr[cii]);
02348         }
02349 
02350         EMData *data_out;
02351                 data_out=data_in->do_ift();
02352                 float *c=data_out->get_data();
02353                 float tempr=0.0f, corre_fcs=999.0f;
02354 
02355             int n_best=0, m_best=0;
02356         float temp=-100.0f;
02357                 for(n=0;n<size;++n){// move Tri_2D to Tri = c(phi,phi';rho)
02358                         for(m=0;m<size;++m){
02359                                 temp=c[n*size+m];
02360                                 if(temp>tempr) {
02361                                         tempr=temp;
02362                                         n_best=n;
02363                                         m_best=m;
02364                                 }
02365                         }
02366                 }
02367                 delete data_out;
02368 
02369                 float corre,Phi2,Phi,Tx,Ty,Vx, Vy;
02370 
02371                 //for (n_best=0;n_best<bw;n_best++)
02372                   //  for (m_best=0;m_best<2*bw;m_best++){
02373                 //n_best=0;
02374                 //m_best=70;
02375                 Phi2=n_best*M_PI/bw;  // ming this is reference image rotation angle
02376                 Phi=m_best*M_PI/bw;   // ming this is particle image rotation angle
02377                 Vx=p*cos(Phi);//should use the angle of the centered one
02378                 Vy=-p*sin(Phi);
02379                 Tx=Vx+(floor(com_this_x+0.5f)-floor(com_with_x+0.5f));
02380                 Ty=Vy+(floor(com_this_y+0.5f)-floor(com_with_y+0.5f));
02381 
02382                 dx=-Tx; // the Rota & Trans value (Tx,Ty, ang_keep) are for the projection image,
02383                 dy=-Ty; // need to convert to raw image
02384 
02385                 EMData *this_tmp=this_img->copy();//ming change to to
02386                 this_tmp->rotate(-(Phi2-Phi)*180.0f,0.0f,0.0f);
02387                 this_tmp->translate(dx,dy,0.0);
02388 
02389                 corre=this_tmp->cmp(cmp_name,to,cmp_params);
02390                 //printf("corre=%f\n",corre);
02391                 delete this_tmp;
02392                 if(corre<=corre_fcs) { //ming, cmp use smaller value stands for more similarity
02393                         corre_fcs=corre;
02394                         result[0+5*p] = float(p);       // rho
02395                         result[1+5*p] = corre;          // correlation_fcs
02396                         result[2+5*p] = (Phi2-Phi)*180.0f;      // rotation angle
02397                         result[3+5*p] = Tx;             // Translation_x
02398                         result[4+5*p] = Ty;             // Translation_y
02399                 }
02400                 maxcor[p]=corre_fcs;                            //  maximum correlation for current rho
02401                 if(corre_fcs<maxcor_sofar) {
02402                         maxcor_sofar=corre_fcs;                 // max correlation up to current rho
02403                     rho_best=p;                         // the rho value with maxinum correlation value
02404                 }
02405                 if(p>=4){
02406                         if(maxcor[p] < maxcor[p-1] && maxcor[p-1] < maxcor[p-2]&& maxcor[p-2] < maxcor[p-3] && maxcor[p-3] < maxcor[p-4]){
02407                                 loop_rho=1;
02408                                 break; //exit p loop
02409                         }
02410                 }
02411         } // end for p
02412         //}//test my method
02413         if(loop_rho == 1)
02414                 p=p+1;
02415         int rb5=5*rho_best;
02416         float fsc      = result[1+rb5];
02417         float ang_keep = result[2+rb5];
02418         float Tx       = result[3+rb5];
02419         float Ty       = result[4+rb5];
02420         delete[] gnr2;
02421         delete[] maxcor;
02422         delete[] result;
02423         delete cr;
02424         cr=0;
02425         delete ci;
02426         ci=0;
02427         delete data_in; // ming add
02428         dx = -Tx;               // the Rota & Trans value (Tx,Ty, ang_keep) are for the projection image,
02429         dy = -Ty;               // need to convert to raw image
02430         this_img->rotate(-ang_keep,0,0); // ming change this to this_img??
02431         this_img->translate(dx,dy,0.0); // ming change this to this_img
02432 
02433 
02434         Transform  tsoln(Dict("type","2d","alpha",ang_keep));
02435         tsoln.set_trans(dx,dy);
02436         this_img->set_attr("xform.align2d",&tsoln);
02437 #ifdef DEBUG
02438         float fsc_best=this_img->cmp(cmp_name,to,cmp_params);
02439         printf("rho_best=%d fsc=%f fsc_best=%f dx=%f dy=%f ang_keep=%f com_withx=%f com_selfx=%f com_selfy=%f\n",rho_best,fsc,fsc_best,dx,dy,ang_keep,com_with_x,com_this_x,com_this_y);
02440 #endif
02441         return fsc;     // return the fsc coefficients
02442 } // FRM2D aligner sub_class
02443 } // end namespace
02444 
02445 
02446 EMData *FRM2DAligner::align(EMData * this_img, EMData * to,
02447                         const string & cmp_name, const Dict& cmp_params) const
02448 {
02449         if (!this_img) {
02450                 return 0;
02451         }
02452         if (to && !EMUtil::is_same_size(this_img, to))
02453                 throw ImageDimensionException("Images must be the same size to perform translational alignment");
02454 
02455         int nx=this_img->get_xsize();
02456         int ny=this_img->get_ysize();
02457         int size =(int)floor(M_PI*ny/4.0);
02458         size =Util::calc_best_fft_size(size);//ming   bestfftsize(size);
02459         int MAXR=ny/2;
02460         //int MAXR=size;
02461         EMData *this_temp=this_img->copy(); // ming change avg to to
02462         FloatPoint com_test,com_test1;
02463         com_test=this_temp->calc_center_of_mass();//ming add
02464         float com_this_x=com_test[0];
02465         float com_this_y=com_test[1];
02466         delete this_temp;
02467 
02468 
02469         EMData *that_temp=to->copy();
02470         com_test1=that_temp->calc_center_of_mass();
02471         float com_with_x=com_test1[0];
02472         float com_with_y=com_test1[1];
02473         delete that_temp;
02474 
02475         EMData *avg_frm=to->copy();
02476         float dx,dy;
02477         //float dx=-(com_with_x-nx/2); //ming
02478         //float dy=-(com_with_y-ny/2); //ming
02479         //avg_frm->translate(dx,dy,0.0);
02480         EMData *withpcs=avg_frm->unwrap_largerR(0,MAXR,size,float(MAXR)); // ming, something wrong inside this subroutine
02481         //EMData *withpcs=avg_frm->unwrap(-1,-1,-1,0,0,1);
02482         EMData *withpcsfft=withpcs->oneDfftPolar(size, float(MAXR), float(MAXR));
02483 
02484         float *sampl_fft=withpcsfft->get_data(); //
02485         delete avg_frm;
02486         delete withpcs;
02487 
02488         int bw=size/2;
02489         unsigned long ind1=0, ind2=0, ind3=0, ind4=0, ind41=0;
02490         float pi2=2.0*M_PI, r2;
02491 
02492         EMData *data_in=new EMData;
02493         data_in->set_complex(true);
02494         data_in->set_ri(1);
02495         data_in->set_size(2*size,1,1);
02496         float * comp_in=data_in->get_data();
02497 
02498         int p_max=3;
02499         float *frm2dhhat=0;
02500 
02501         if( (frm2dhhat=(float *)malloc((p_max+1)*(size+2)*bw*size*2* sizeof(float)))==NULL){
02502                 cout <<"Error in allocating memory 13. \n";
02503                 exit(1);
02504         }
02505         //printf("p_max=%d\n",p_max);
02506         float *sb=0, *cb=0;             // sin(beta) and cos(beta) for get h_hat, 300>size
02507         if((sb=new float[size])==NULL||(cb=new float[size])==NULL) {
02508                 cout <<"can't allocate more memory, terminating. \n";
02509                 exit(1);
02510         }
02511         for(int i=0;i<size;++i) {        // beta sampling, to calculate beta' and r'
02512                 float beta=i*M_PI/bw;
02513                 sb[i]=sin(beta);
02514                 cb[i]=cos(beta);
02515         }
02516 
02517         for(int p=0; p<=p_max; ++p){
02518                 ind1=p*size*bw;
02519         float pp2=(float)(p*p);
02520                 for(int n=0;n<bw;++n){         /* loop for n */
02521                 ind2=ind1+n;
02522                 for(int r=0;r<=MAXR;++r) {
02523                                 ind3=(ind2+r*bw)*size;
02524                         float rr2=(float)(r*r);
02525                                 float rp2=(float)(r*p);
02526                         for(int i=0;i<size;++i){                            // beta sampling, to get beta' and r'
02527                                 r2=std::sqrt((float)(rr2+pp2-2.0*rp2*cb[i]));   // r2->r'
02528                                 int r1=(int)floor(r2+0.5f);                        // for computing gn(r')
02529                                 if(r1>MAXR){
02530                                         comp_in[2*i]=0.0f;
02531                                         comp_in[2*i+1]=0.0f;
02532                                 }
02533                                 else{
02534                                         float gn_r=sampl_fft[2*n+r1*(size+2)];           // real part of gn(r')
02535                                         float gn_i=sampl_fft[2*n+1+r1*(size+2)];           // imaginary part of gn(r')
02536                                                 float sb2, cb2, cn, sn;
02537                                                 if(n!=0){
02538                                                         if(r2 != 0.0){
02539                                                                 sb2=r*sb[i]/r2;
02540                                                                 cb2=(r*cb[i]-p)/r2;
02541                                                         }
02542                                                 else{
02543                                                                 sb2=0.0;
02544                                                                 cb2=1.0;
02545                                                         }
02546                                                 if(sb2>1.0) sb2= 1.0f;
02547                                                 if(sb2<-1.0)sb2=-1.0f;
02548                                                 if(cb2>1.0) cb2= 1.0f;
02549                                                 if(cb2<-1.0)cb2=-1.0f;
02550                                                 float beta2=atan2(sb2,cb2);
02551                                                 if(beta2<0.0) beta2+=pi2;
02552                                                 float nb2=n*beta2;
02553                                                 cn=cos(nb2);
02554                                                         sn=sin(nb2);
02555                                                 }
02556                                         else{
02557                                                         cn=1.0f; sn=0.0f;
02558                                                 }
02559                                                 comp_in[2*i]=cn*gn_r-sn*gn_i;
02560                                                 comp_in[2*i+1]=-(cn*gn_i+sn*gn_r);
02561                                 }
02562                         }
02563                         EMData *data_out;
02564                         data_out=data_in->do_fft();
02565                         float * comp_out=data_out->get_data();
02566                         for(int m=0;m<size;m++){                                     // store hat{h(n,r,p)}(m)
02567                                         ind4=(ind3+m)*2;
02568                                         ind41=ind4+1;
02569                                         frm2dhhat[ind4]=comp_out[2*m];
02570                                         frm2dhhat[ind41]=comp_out[2*m+1];
02571                                 }
02572                         delete data_out;
02573                         }
02574                 }
02575         }
02576 
02577         delete[] sb;
02578         delete[] cb;
02579         delete data_in;
02580         delete withpcsfft;
02581 
02582         float dot_frm0=0.0f, dot_frm1=0.0f;
02583         EMData *da_nFlip=0, *da_yFlip=0, *dr_frm=0;
02584         //dr_frm=this_img->copy();
02585         for (int iFlip=0;iFlip<=1;++iFlip){
02586                 if (iFlip==0){dr_frm=this_img->copy();  da_nFlip=this_img->copy();}
02587                 else {dr_frm=this_img->copy(); da_yFlip=this_img->copy();}
02588                 if(iFlip==1) {com_this_x=nx-com_this_x; } //ming   // image mirror about Y axis, so y keeps the same
02589 
02590                 dx=-(com_this_x-nx/2); //ming
02591                 dy=-(com_this_y-ny/2); //ming
02592                 dr_frm->translate(dx,dy,0.0); // this
02593                 EMData *selfpcs = dr_frm->unwrap_largerR(0,MAXR,size, (float)MAXR);
02594                 //EMData *selfpcs=dr_frm->unwrap(-1,-1,-1,0,0,1);
02595                 EMData *selfpcsfft = selfpcs->oneDfftPolar(size, (float)MAXR, (float)MAXR);
02596                 delete selfpcs;
02597                 delete dr_frm;
02598                 if(iFlip==0)
02599                         dot_frm0=frm_2d_Align(da_nFlip,to, frm2dhhat, selfpcsfft, p_max, size, com_this_x, com_this_y, com_with_x, com_with_y,cmp_name,cmp_params);
02600                 else
02601                         dot_frm1=frm_2d_Align(da_yFlip,to, frm2dhhat, selfpcsfft, p_max, size, com_this_x, com_this_y, com_with_x, com_with_y,cmp_name,cmp_params);
02602                 delete selfpcsfft;
02603         }
02604 
02605         delete[] frm2dhhat;
02606         if(dot_frm0 <=dot_frm1) {
02607 #ifdef DEBUG
02608                 printf("best_corre=%f, no flip\n",dot_frm0);
02609 #endif
02610                 delete da_yFlip;
02611                 return da_nFlip;
02612         }
02613         else {
02614 #ifdef DEBUG
02615                 printf("best_corre=%f, flipped\n",dot_frm1);
02616 #endif
02617                 delete da_nFlip;
02618                 return da_yFlip;
02619         }
02620 }
02621 
02622 #ifdef SPARX_USING_CUDA
02623 
02624 CUDA_Aligner::CUDA_Aligner(int id) {
02625         image_stack = NULL;
02626         image_stack_filtered = NULL;
02627         ccf = NULL;
02628         if (id != -1) cudasetup(id);
02629 }
02630 
02631 void CUDA_Aligner::finish() {
02632         if (image_stack) free(image_stack);
02633         if (image_stack_filtered) free(image_stack_filtered);
02634         if (ccf) free(ccf);
02635         image_stack = NULL;
02636         image_stack_filtered = NULL;
02637         ccf = NULL;
02638 }
02639 
02640 void CUDA_Aligner::setup(int nima, int nx, int ny, int ring_length, int nring, int ou, float step, int kx, int ky, bool ctf) {
02641 
02642         NIMA = nima;
02643         NX = nx;
02644         NY = ny;
02645         RING_LENGTH = ring_length;
02646         NRING = nring;
02647         STEP = step;
02648         KX = kx;
02649         KY = ky;
02650         OU = ou;
02651         CTF = ctf;
02652         
02653         image_stack = (float *)malloc(NIMA*NX*NY*sizeof(float));
02654         if (CTF == 1) image_stack_filtered = (float *)malloc(NIMA*NX*NY*sizeof(float));
02655         ccf = (float *)malloc(2*(2*KX+1)*(2*KY+1)*NIMA*(RING_LENGTH+2)*sizeof(float));
02656 }
02657 
02658 void CUDA_Aligner::insert_image(EMData *image, int num) {
02659 
02660         int base_address = num*NX*NY;
02661 
02662         for (int y=0; y<NY; y++)
02663                 for (int x=0; x<NX; x++)
02664                         image_stack[base_address+y*NX+x] = (*image)(x, y);
02665 }
02666 
02667 void CUDA_Aligner::filter_stack(vector<float> ctf_params) {
02668         
02669         float *params;
02670         
02671         params = (float *)malloc(NIMA*6*sizeof(float)); 
02672         
02673         for (int i=0; i<NIMA*6; i++) params[i] = ctf_params[i];
02674 
02675         filter_image(image_stack, image_stack_filtered, NIMA, NX, NY, params);
02676 
02677         free(params);
02678 }
02679 
02680 void CUDA_Aligner::sum_oe(vector<float> ctf_params, vector<float> ali_params, EMData *ave1, EMData *ave2) {
02681         
02682         float *ctf_p, *ali_p, *av1, *av2;
02683         
02684         ctf_p = (float *)malloc(NIMA*6*sizeof(float));
02685         ali_p = (float *)malloc(NIMA*4*sizeof(float));
02686         
02687         if (CTF == 1) {
02688                 for (int i=0; i<NIMA*6; i++)  ctf_p[i] = ctf_params[i];
02689         }
02690         for (int i=0; i<NIMA*4; i++)   ali_p[i] = ali_params[i];
02691         
02692         av1 = ave1->get_data();
02693         av2 = ave2->get_data();
02694         
02695         rot_filt_sum(image_stack, NIMA, NX, NY, CTF, ctf_p, ali_p, av1, av2);
02696         
02697         free(ctf_p);
02698         free(ali_p);
02699 }
02700 
02701 vector<float> CUDA_Aligner::alignment_2d(EMData *ref_image_em, vector<float> sx_list, vector<float> sy_list, int silent) {
02702 
02703         float *ref_image, max_ccf;
02704         int base_address, ccf_offset;
02705         float ts, tm;
02706         float ang, sx = 0, sy = 0, mirror, co, so, sxs, sys;
02707         float *sx2, *sy2;
02708         vector<float> align_result;
02709 
02710         sx2 = (float *)malloc(NIMA*sizeof(float));
02711         sy2 = (float *)malloc(NIMA*sizeof(float));
02712 
02713         ref_image = ref_image_em->get_data();
02714         
02715         for (int i=0; i<NIMA; i++) {
02716                 sx2[i] = sx_list[i];
02717                 sy2[i] = sy_list[i];
02718         }
02719         
02720         if (CTF == 1) {
02721                 calculate_ccf(image_stack_filtered, ref_image, ccf, NIMA, NX, NY, RING_LENGTH, NRING, OU, STEP, KX, KY, sx2, sy2, silent);
02722         } else {
02723                 calculate_ccf(image_stack, ref_image, ccf, NIMA, NX, NY, RING_LENGTH, NRING, OU, STEP, KX, KY, sx2, sy2, silent);
02724         }
02725 
02726         ccf_offset = NIMA*(RING_LENGTH+2)*(2*KX+1)*(2*KY+1);
02727 
02728         for (int im=0; im<NIMA; im++) {
02729                 max_ccf = -1.0e22;
02730                 for (int kx=-KX; kx<=KX; kx++) {
02731                         for (int ky=-KY; ky<=KY; ky++) {
02732                                 base_address = (((ky+KY)*(2*KX+1)+(kx+KX))*NIMA+im)*(RING_LENGTH+2);
02733                                 for (int l=0; l<RING_LENGTH; l++) {
02734                                         ts = ccf[base_address+l];
02735                                         tm = ccf[base_address+l+ccf_offset];
02736                                         if (ts > max_ccf) {
02737                                                 ang = float(l)/RING_LENGTH*360.0;
02738                                                 sx = -kx*STEP;
02739                                                 sy = -ky*STEP;
02740                                                 mirror = 0;
02741                                                 max_ccf = ts;
02742                                         }
02743                                         if (tm > max_ccf) {
02744                                                 ang = float(l)/RING_LENGTH*360.0; 
02745                                                 sx = -kx*STEP;
02746                                                 sy = -ky*STEP;
02747                                                 mirror = 1;
02748                                                 max_ccf = tm;
02749                                         }
02750                                 }
02751                         }
02752                 }
02753                 co =  cos(ang*M_PI/180.0);
02754                 so = -sin(ang*M_PI/180.0);
02755                 sxs = sx*co - sy*so;
02756                 sys = sx*so + sy*co;
02757 
02758                 align_result.push_back(ang);
02759                 align_result.push_back(sxs);
02760                 align_result.push_back(sys);
02761                 align_result.push_back(mirror);
02762         }
02763         
02764         free(sx2);
02765         free(sy2);
02766         
02767         return align_result;
02768 }
02769 
02770 
02771 vector<float> CUDA_Aligner::ali2d_single_iter(EMData *ref_image_em, vector<float> ali_params, float csx, float csy, int silent, float delta) {
02772 
02773         float *ref_image, max_ccf;
02774         int base_address, ccf_offset;
02775         float ts, tm;
02776         float ang = 0.0, sx = 0.0, sy = 0.0, co, so, sxs, sys;
02777         int mirror;
02778         float *sx2, *sy2;
02779         vector<float> align_result;
02780 
02781         sx2 = (float *)malloc(NIMA*sizeof(float));
02782         sy2 = (float *)malloc(NIMA*sizeof(float));
02783 
02784         ref_image = ref_image_em->get_data();
02785         
02786         for (int i=0; i<NIMA; i++) {
02787                 ang = ali_params[i*4]/180.0*M_PI;
02788                 sx = (ali_params[i*4+3] < 0.5)?(ali_params[i*4+1]-csx):(ali_params[i*4+1]+csx);
02789                 sy = ali_params[i*4+2]-csy;
02790                 co = cos(ang);
02791                 so = sin(ang);
02792                 sx2[i] = -(sx*co-sy*so);
02793                 sy2[i] = -(sx*so+sy*co);
02794         }
02795         
02796         if (CTF == 1) {
02797                 calculate_ccf(image_stack_filtered, ref_image, ccf, NIMA, NX, NY, RING_LENGTH, NRING, OU, STEP, KX, KY, sx2, sy2, silent);
02798         } else {
02799                 calculate_ccf(image_stack, ref_image, ccf, NIMA, NX, NY, RING_LENGTH, NRING, OU, STEP, KX, KY, sx2, sy2, silent);
02800         }
02801 
02802         ccf_offset = NIMA*(RING_LENGTH+2)*(2*KX+1)*(2*KY+1);
02803 
02804         float sx_sum = 0.0f;
02805         float sy_sum = 0.0f;
02806 
02807         int dl;
02808         dl = static_cast<int>(delta/360.0*RING_LENGTH);
02809         if (dl<1) { dl = 1; }   
02810         
02811         for (int im=0; im<NIMA; im++) {
02812                 max_ccf = -1.0e22;
02813                 for (int kx=-KX; kx<=KX; kx++) {
02814                         for (int ky=-KY; ky<=KY; ky++) {
02815                                 base_address = (((ky+KY)*(2*KX+1)+(kx+KX))*NIMA+im)*(RING_LENGTH+2);
02816                                 for (int l=0; l<RING_LENGTH; l+=dl) {
02817                                         ts = ccf[base_address+l];
02818                                         tm = ccf[base_address+l+ccf_offset];
02819                                         if (ts > max_ccf) {
02820                                                 ang = float(l)/RING_LENGTH*360.0;
02821                                                 sx = -kx*STEP;
02822                                                 sy = -ky*STEP;
02823                                                 mirror = 0;
02824                                                 max_ccf = ts;
02825                                         }
02826                                         if (tm > max_ccf) {
02827                                                 ang = float(l)/RING_LENGTH*360.0; 
02828                                                 sx = -kx*STEP;
02829                                                 sy = -ky*STEP;
02830                                                 mirror = 1;
02831                                                 max_ccf = tm;
02832                                         }
02833                                 }
02834                         }
02835                 }
02836                 co =  cos(ang*M_PI/180.0);
02837                 so = -sin(ang*M_PI/180.0);
02838                 
02839                 sxs = (sx-sx2[im])*co-(sy-sy2[im])*so;
02840                 sys = (sx-sx2[im])*so+(sy-sy2[im])*co;
02841 
02842                 //if (sxs*sxs+sys*sys >= 7*7) { sxs=0; sys=0; }
02843 
02844                 align_result.push_back(ang);
02845                 align_result.push_back(sxs);
02846                 align_result.push_back(sys);
02847                 align_result.push_back(mirror);
02848                 
02849                 if (mirror == 0)  { sx_sum += sxs; }  else { sx_sum -= sxs; }
02850                 sy_sum += sys;
02851         }
02852         
02853         align_result.push_back(sx_sum);
02854         align_result.push_back(sy_sum);
02855         
02856         free(sx2);
02857         free(sy2);
02858         
02859         return align_result;
02860 }
02861 
02862 
02863 CUDA_multiref_aligner::CUDA_multiref_aligner(int id) {
02864         image_stack = NULL;
02865         ref_image_stack = NULL;
02866         ref_image_stack_filtered = NULL;
02867         ccf = NULL;
02868         ctf_params = NULL;
02869         ali_params = NULL;
02870         cudasetup(id);
02871 }
02872 
02873 
02874 void CUDA_multiref_aligner::finish() {
02875         if (image_stack) free(image_stack);
02876         if (ref_image_stack) free(ref_image_stack);
02877         if (ref_image_stack_filtered) free(ref_image_stack_filtered);
02878         if (ccf) free(ccf);
02879         if (ctf_params) free(ctf_params);
02880         if (ali_params) free(ali_params);
02881         image_stack = NULL;
02882         ref_image_stack = NULL;
02883         ref_image_stack_filtered = NULL;
02884         ccf = NULL;
02885         ctf_params = NULL;
02886         ali_params = NULL;
02887 }       
02888 
02889 void CUDA_multiref_aligner::setup(int nima, int nref, int nx, int ny, int ring_length, int nring, int ou, float step, int kx, int ky, bool ctf) {
02890 
02891         NIMA = nima;
02892         NREF = nref;
02893         NX = nx;
02894         NY = ny;
02895         RING_LENGTH = ring_length;
02896         NRING = nring;
02897         STEP = step;
02898         KX = kx;
02899         KY = ky;
02900         OU = ou;
02901         CTF = ctf;
02902         // This number can be increased according to the GPU memory. But my tests has shown the speedup 
02903         // is limited (~5%) even if I increased the size 10 times, so it's better to be on the safe side.
02904         MAX_IMAGE_BATCH = 10;
02905         
02906         image_stack = (float *)malloc(NIMA*NX*NY*sizeof(float));
02907         ref_image_stack = (float *)malloc(NREF*NX*NY*sizeof(float));
02908         if (CTF == 1) ref_image_stack_filtered = (float *)malloc(NREF*NX*NY*sizeof(float));
02909         ccf = (float *)malloc(2*(2*KX+1)*(2*KY+1)*NREF*(RING_LENGTH+2)*MAX_IMAGE_BATCH*sizeof(float));
02910 }
02911 
02912 void CUDA_multiref_aligner::setup_params(vector<float> all_ali_params, vector<float> all_ctf_params) {
02913         
02914         ali_params = (float *)malloc(NIMA*4*sizeof(float));
02915         for (int i=0; i<NIMA*4; i++)   ali_params[i] = all_ali_params[i];
02916         if (CTF == 1) {
02917                 ctf_params = (float *)malloc(NIMA*6*sizeof(float));
02918                 for (int i=0; i<NIMA*6; i++)  ctf_params[i] = all_ctf_params[i];
02919         }
02920 }
02921 
02922 void CUDA_multiref_aligner::insert_image(EMData *image, int num) {
02923 
02924         int base_address = num*NX*NY;
02925 
02926         for (int y=0; y<NY; y++)
02927                 for (int x=0; x<NX; x++)
02928                         image_stack[base_address+y*NX+x] = (*image)(x, y);
02929 }
02930 
02931 void CUDA_multiref_aligner::insert_ref_image(EMData *image, int num) {
02932 
02933         int base_address = num*NX*NY;
02934 
02935         for (int y=0; y<NY; y++)
02936                 for (int x=0; x<NX; x++)
02937                         ref_image_stack[base_address+y*NX+x] = (*image)(x, y);
02938 }
02939 
02940 vector<float> CUDA_multiref_aligner::multiref_ali2d(int silent) {
02941 
02942         float *ctf_params_ref = (float *)malloc(NREF*6*sizeof(float));  
02943         float *sx2 = (float *)malloc(NIMA*sizeof(float));
02944         float *sy2 = (float *)malloc(NIMA*sizeof(float));
02945         vector<float> align_results;
02946         int ccf_offset = NREF*(RING_LENGTH+2)*(2*KX+1)*(2*KY+1);
02947 
02948         vector<int> batch_size;
02949         vector<int> batch_begin;
02950         
02951         if (CTF == 1) {
02952                 float previous_defocus = ctf_params[0];
02953                 int current_size = 1;
02954                 for (int i=1; i<NIMA; i++) {
02955                         if (ctf_params[i*6] != previous_defocus || current_size >= MAX_IMAGE_BATCH) {
02956                                 batch_size.push_back(current_size);
02957                                 current_size = 1;
02958                                 previous_defocus = ctf_params[i*6];
02959                         } else current_size++;                  
02960                 }
02961                 batch_size.push_back(current_size);
02962         } else {
02963                 batch_size.resize(NIMA/MAX_IMAGE_BATCH, MAX_IMAGE_BATCH);
02964                 if (NIMA%MAX_IMAGE_BATCH != 0)  batch_size.push_back(NIMA%MAX_IMAGE_BATCH);
02965         }
02966         int num_batch = batch_size.size();
02967         batch_begin.resize(num_batch, 0);
02968         for (int i=1; i<num_batch; i++) batch_begin[i] = batch_size[i-1]+batch_begin[i-1];
02969         assert(batch_begin[num_batch-1]+batch_size[num_batch-1] == NIMA-1);
02970 
02971         for (int i=0; i<NIMA; i++) {
02972                 float ang = ali_params[i*4]/180.0*M_PI;
02973                 float sx = ali_params[i*4+1];
02974                 float sy = ali_params[i*4+2];
02975                 float co = cos(ang);
02976                 float so = sin(ang);
02977                 sx2[i] = -(sx*co-sy*so);
02978                 sy2[i] = -(sx*so+sy*co);
02979         }
02980 
02981         for (int i=0; i<num_batch; i++) {
02982                 if (CTF == 1) {
02983                         for (int p=0; p<NREF; p++)
02984                                 for (int q=0; q<6; q++)
02985                                         ctf_params_ref[p*6+q] = ctf_params[batch_begin[i]*6+q];
02986                         filter_image(ref_image_stack, ref_image_stack_filtered, NREF, NX, NY, ctf_params_ref);
02987                         calculate_multiref_ccf(image_stack+batch_begin[i]*NX*NY, ref_image_stack_filtered, ccf, batch_size[i], NREF, NX, NY, RING_LENGTH, NRING, OU, STEP, KX, KY,
02988                                 sx2+batch_begin[i], sy2+batch_begin[i], silent);
02989                 } else {
02990                         calculate_multiref_ccf(image_stack+batch_begin[i]*NX*NY, ref_image_stack, ccf, batch_size[i], NREF, NX, NY, RING_LENGTH, NRING, OU, STEP, KX, KY,
02991                                 sx2+batch_begin[i], sy2+batch_begin[i], silent);
02992                 }
02993 
02994                 for (int j=0; j<batch_size[i]; j++) {
02995                         for (int im=0; im<NREF; im++) {
02996                                 float max_ccf = -1.0e22;
02997                                 float ang = 0.0, sx = 0.0, sy = 0.0;
02998                                 int mirror = 0;
02999                                 for (int kx=-KX; kx<=KX; kx++) {
03000                                         for (int ky=-KY; ky<=KY; ky++) {
03001                                                 int base_address = (((ky+KY)*(2*KX+1)+(kx+KX))*NREF+im)*(RING_LENGTH+2)+ccf_offset*2*j;                 
03002                                                 for (int l=0; l<RING_LENGTH; l++) {
03003                                                         float ts = ccf[base_address+l];
03004                                                         float tm = ccf[base_address+l+ccf_offset];
03005                                                         if (ts > max_ccf) {
03006                                                                 ang = 360.0-float(l)/RING_LENGTH*360.0;
03007                                                                 sx = -kx*STEP;
03008                                                                 sy = -ky*STEP;
03009                                                                 mirror = 0;
03010                                                                 max_ccf = ts;
03011                                                         }
03012                                                         if (tm > max_ccf) {
03013                                                                 ang = float(l)/RING_LENGTH*360.0; 
03014                                                                 sx = -kx*STEP;
03015                                                                 sy = -ky*STEP;
03016                                                                 mirror = 1;
03017                                                                 max_ccf = tm;
03018                                                         }
03019                                                 }
03020                                         }
03021                                 }
03022                                 float co =  cos(ang*M_PI/180.0);
03023                                 float so = -sin(ang*M_PI/180.0);
03024                 
03025                                 int img_num = batch_begin[i]+j;
03026                                 float sxs = (sx-sx2[img_num])*co-(sy-sy2[img_num])*so;
03027                                 float sys = (sx-sx2[img_num])*so+(sy-sy2[img_num])*co;
03028 
03029                                 align_results.push_back(max_ccf);
03030                                 align_results.push_back(ang);
03031                                 align_results.push_back(sxs);
03032                                 align_results.push_back(sys);
03033                                 align_results.push_back(mirror);
03034                         }
03035                 }
03036         }
03037         
03038         free(ctf_params_ref);
03039         free(sx2);
03040         free(sy2);
03041         
03042         return align_results;
03043 }
03044 
03045 #endif
03046 
03047 
03048 void EMAN::dump_aligners()
03049 {
03050         dump_factory < Aligner > ();
03051 }
03052 
03053 map<string, vector<string> > EMAN::dump_aligners_list()
03054 {
03055         return dump_factory_list < Aligner > ();
03056 }

Generated on Mon May 2 13:26:50 2011 for EMAN2 by  doxygen 1.4.7