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

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

Generated on Thu Dec 9 13:45:44 2010 for EMAN2 by  doxygen 1.3.9.1