00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
00093 }
00094
00095
00096
00097
00098
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
00118
00119
00120
00121
00122
00123
00124 if (use_cpu) {
00125 if (useflcf) cf = this_img->calc_flcf(to);
00126 else cf = this_img->calc_ccf(to);
00127 }
00128
00129
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;
00164 if (ny == 1) maxshifty = 0;
00165 if (nz == 1) maxshiftz = 0;
00166
00167
00168 if (nozero) {
00169 cf->zero_corner_circulant(1);
00170 }
00171
00172 IntPoint peak;
00173
00174
00175
00176
00177
00178
00179
00180
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;
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
00206
00207 cf->set_attr("xform.align3d",&t);
00208 } else if ( ny != 1 ) {
00209
00210 cur_trans[2] = 0;
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
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
00237 EMData *cf = this_img_rfp->calc_ccfx(to_rfp, 0, this_img->get_ysize());
00238
00239
00240 delete this_img_rfp; this_img_rfp = 0;
00241 delete to_rfp; to_rfp = 0;
00242
00243
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
00256 Transform tmp(Dict("type","2d","alpha",rot_angle));
00257 cf=this_img->process("xform",Dict("transform",(Transform*)&tmp));
00258
00259
00260
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
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
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
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
00299
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
00332
00333
00334
00335
00336
00337
00338
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
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
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
00384
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
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
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
00428 if(it > 0){delete moving_img;}
00429
00430 moving_img = this_img->process("xform",Dict("transform",&t));
00431 }
00432
00433
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
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
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 ) {
00462 delete rot_align;
00463 rot_align = 0;
00464 }
00465
00466
00467 EMData* rot_180_trans = rot_align_180->align("translational", to, trans_params, cmp_name, cmp_params);
00468 if( rot_align_180 ) {
00469 delete rot_align_180;
00470 rot_align_180 = 0;
00471 }
00472
00473
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) {
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
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
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
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
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
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
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
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
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
00875
00876
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;
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
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
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
01140
01141
01142
01143
01144 Transform t(Dict("type","2d","alpha",static_cast<float>(a)));
01145
01146
01147
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
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01169
01170
01171
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
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();
01225 }
01226
01227
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
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
01287
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
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 {
01313
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
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
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
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
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
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");
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
01465
01466
01467
01468 t = params["xform.align3d"];
01469 }else {
01470 t = new Transform();
01471 }
01472
01473 int np = 6;
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
01492
01493
01494
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
01503
01504
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
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
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 {
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);
01643 float uphi = params.set_default("uphi",359.9f);
01644 float uaz = params.set_default("uaz",359.9f);
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
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;
01661 for (unsigned int i = 0; i < nsoln; ++i ) {
01662 Dict d;
01663 d["score"] = 1.e24;
01664 Transform t;
01665 d["xform.align3d"] = &t;
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";
01676 for ( float alt = lalt; alt <= ualt; alt += dalt) {
01677
01678
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
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 ) {
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
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;
01790 for (unsigned int i = 0; i < nsoln; ++i ) {
01791 Dict d;
01792 d["score"] = 1.e24;
01793 Transform t;
01794 d["xform.align3d"] = &t;
01795 solns.push_back(d);
01796 }
01797
01798 Dict d;
01799 d["inc_mirror"] = true;
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
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
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
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
01855 for ( vector<Dict>::iterator it = solns.begin(); it != solns.end(); ++it, ++j ) {
01856 if ( (float)(*it)["score"] > best_score ) {
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;
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
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];
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();
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){
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++){
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){
01934 if(m!= 0){
01935 int ssize=tsize-2*m;
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
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){
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
01978
01979
01980
01981 Phi2=n_best*M_PI/bw;
01982 Phi=m_best*M_PI/bw;
01983 Vx=p*cos(Phi);
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;
01989 dy=-Ty;
01990
01991 EMData *this_tmp=this_img->copy();
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
01997 delete this_tmp;
01998 if(corre<=corre_fcs) {
01999 corre_fcs=corre;
02000 result[0+5*p] = float(p);
02001 result[1+5*p] = corre;
02002 result[2+5*p] = (Phi2-Phi)*180.0f;
02003 result[3+5*p] = Tx;
02004 result[4+5*p] = Ty;
02005 }
02006 maxcor[p]=corre_fcs;
02007 if(corre_fcs<maxcor_sofar) {
02008 maxcor_sofar=corre_fcs;
02009 rho_best=p;
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;
02015 }
02016 }
02017 }
02018
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;
02034 dx = -Tx;
02035 dy = -Ty;
02036 this_img->rotate(-ang_keep,0,0);
02037 this_img->translate(dx,dy,0.0);
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;
02048 }
02049 }
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);
02065 int MAXR=ny/2;
02066
02067 EMData *this_temp=this_img->copy();
02068 FloatPoint com_test,com_test1;
02069 com_test=this_temp->calc_center_of_mass();
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
02084
02085
02086 EMData *withpcs=avg_frm->unwrap_largerR(0,MAXR,size,float(MAXR));
02087
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
02112 float *sb=0, *cb=0;
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) {
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){
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){
02133 r2=std::sqrt((float)(rr2+pp2-2.0*rp2*cb[i]));
02134 int r1=(int)floor(r2+0.5f);
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)];
02141 float gn_i=sampl_fft[2*n+1+r1*(size+2)];
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++){
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
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; }
02195
02196 dx=-(com_this_x-nx/2);
02197 dy=-(com_this_y-ny/2);
02198 dr_frm->translate(dx,dy,0.0);
02199 EMData *selfpcs = dr_frm->unwrap_largerR(0,MAXR,size, (float)MAXR);
02200
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
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
02497
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 }