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
00036 #include "emdata.h"
00037 #include "all_imageio.h"
00038 #include "ctf.h"
00039 #include "processor.h"
00040 #include "aligner.h"
00041 #include "cmp.h"
00042 #include "emfft.h"
00043 #include "projector.h"
00044 #include "geometry.h"
00045
00046 #include <gsl/gsl_sf_bessel.h>
00047 #include <gsl/gsl_errno.h>
00048
00049 #include <iomanip>
00050 #include <complex>
00051
00052 #include <algorithm>
00053
00054 #ifdef WIN32
00055 #define M_PI 3.14159265358979323846f
00056 #endif //WIN32
00057
00058 #define EMDATA_EMAN2_DEBUG 0
00059
00060 #ifdef EMAN2_USING_CUDA
00061 #include <driver_functions.h>
00062 #include "cuda/cuda_processor.h"
00063 #endif // EMAN2_USING_CUDA
00064
00065 using namespace EMAN;
00066 using namespace std;
00067 using namespace boost;
00068
00069 int EMData::totalalloc=0;
00070
00071 EMData::EMData() :
00072 #ifdef EMAN2_USING_CUDA
00073 cuda_cache_handle(-1),
00074 #endif
00075 attr_dict(), rdata(0), supp(0), flags(0), changecount(0), nx(0), ny(0), nz(0), nxy(0), xoff(0), yoff(0),
00076 zoff(0), all_translation(), path(""), pathnum(0), rot_fp(0)
00077
00078 {
00079 ENTERFUNC;
00080
00081 attr_dict["apix_x"] = 1.0f;
00082 attr_dict["apix_y"] = 1.0f;
00083 attr_dict["apix_z"] = 1.0f;
00084
00085 attr_dict["is_complex"] = int(0);
00086 attr_dict["is_complex_x"] = int(0);
00087 attr_dict["is_complex_ri"] = int(1);
00088
00089 attr_dict["datatype"] = (int)EMUtil::EM_FLOAT;
00090
00091 EMData::totalalloc++;
00092 #ifdef MEMDEBUG
00093 printf("EMDATA+ %4d %p\n",EMData::totalalloc,this);
00094 #endif
00095
00096 }
00097
00098 EMData::EMData(const string& filename, int image_index) :
00099 #ifdef EMAN2_USING_CUDA
00100 cuda_cache_handle(-1),
00101 #endif
00102 attr_dict(), rdata(0), supp(0), flags(0), changecount(0), nx(0), ny(0), nz(0), nxy(0), xoff(0), yoff(0), zoff(0),
00103 all_translation(), path(filename), pathnum(image_index), rot_fp(0)
00104 {
00105 ENTERFUNC;
00106
00107 attr_dict["apix_x"] = 1.0f;
00108 attr_dict["apix_y"] = 1.0f;
00109 attr_dict["apix_z"] = 1.0f;
00110
00111 attr_dict["is_complex"] = int(0);
00112 attr_dict["is_complex_x"] = int(0);
00113 attr_dict["is_complex_ri"] = int(1);
00114
00115 this->read_image(filename, image_index);
00116
00117 update();
00118 EMData::totalalloc++;
00119
00120 EXITFUNC;
00121 }
00122
00123 EMData::EMData(const EMData& that) :
00124 #ifdef EMAN2_USING_CUDA
00125 cuda_cache_handle(-1),
00126 #endif
00127 attr_dict(that.attr_dict), rdata(0), supp(0), flags(that.flags), changecount(that.changecount), nx(that.nx), ny(that.ny), nz(that.nz),
00128 nxy(that.nx*that.ny), xoff(that.xoff), yoff(that.yoff), zoff(that.zoff),all_translation(that.all_translation), path(that.path),
00129 pathnum(that.pathnum), rot_fp(0)
00130 {
00131 ENTERFUNC;
00132
00133 float* data = that.rdata;
00134 size_t num_bytes = nx*ny*nz*sizeof(float);
00135 if (data && num_bytes != 0)
00136 {
00137 rdata = (float*)EMUtil::em_malloc(num_bytes);
00138 EMUtil::em_memcpy(rdata, data, num_bytes);
00139 }
00140 #ifdef EMAN2_USING_CUDA
00141 if (num_bytes != 0 && that.cuda_cache_handle != -1 && that.gpu_rw_is_current()) {
00142 float * cuda_data = that.get_cuda_data();
00143 CudaDataLock lock2(&that);
00144 set_size_cuda(nx,ny,nz);
00145 float *cd = get_cuda_data();
00146 CudaDataLock lock1(this);
00147 cudaError_t error = cudaMemcpy(cd,cuda_data,num_bytes,cudaMemcpyDeviceToDevice);
00148 if ( error != cudaSuccess ) throw UnexpectedBehaviorException("cudaMemcpy failed in EMData copy construction with error: " + string(cudaGetErrorString(error)));
00149 }
00150
00151 flags |= EMDATA_GPU_RO_NEEDS_UPDATE;
00152 #endif //EMAN2_USING_CUDA
00153 if (that.rot_fp != 0) rot_fp = new EMData(*(that.rot_fp));
00154
00155 EMData::totalalloc++;
00156
00157 ENTERFUNC;
00158 }
00159
00160 EMData& EMData::operator=(const EMData& that)
00161 {
00162 ENTERFUNC;
00163
00164 if ( this != &that )
00165 {
00166 free_memory();
00167
00168
00169 float* data = that.rdata;
00170 size_t num_bytes = that.nx*that.ny*that.nz*sizeof(float);
00171 if (data && num_bytes != 0)
00172 {
00173 nx = 1;
00174 set_size(that.nx,that.ny,that.nz);
00175 EMUtil::em_memcpy(rdata, data, num_bytes);
00176 }
00177
00178 flags = that.flags;
00179
00180 all_translation = that.all_translation;
00181
00182 path = that.path;
00183 pathnum = that.pathnum;
00184 attr_dict = that.attr_dict;
00185
00186 xoff = that.xoff;
00187 yoff = that.yoff;
00188 zoff = that.zoff;
00189
00190 #ifdef EMAN2_USING_CUDA
00191 free_cuda_memory();
00192
00193 if (num_bytes != 0 && that.cuda_cache_handle != -1 && that.gpu_rw_is_current()) {
00194 float * cuda_data = that.get_cuda_data();
00195 CudaDataLock lock1(&that);
00196 set_size_cuda(that.nx, that.ny, that.nz);
00197 float *cd = get_cuda_data();
00198 CudaDataLock lock2(this);
00199 cudaError_t error = cudaMemcpy(cd,cuda_data,num_bytes,cudaMemcpyDeviceToDevice);
00200 if ( error != cudaSuccess ) throw UnexpectedBehaviorException("cudaMemcpy failed in operator= with error: " + string(cudaGetErrorString(error)));
00201 }
00202
00203 flags &= EMDATA_GPU_RO_NEEDS_UPDATE;
00204 #endif //EMAN2_USING_CUDA
00205
00206 changecount = that.changecount;
00207
00208 if (that.rot_fp != 0) rot_fp = new EMData(*(that.rot_fp));
00209 else rot_fp = 0;
00210 }
00211 EXITFUNC;
00212 return *this;
00213 }
00214
00215 EMData::EMData(int nx, int ny, int nz, bool is_real) :
00216 #ifdef EMAN2_USING_CUDA
00217 cuda_cache_handle(-1),
00218 #endif
00219 attr_dict(), rdata(0), supp(0), flags(0), changecount(0), nx(0), ny(0), nz(0), nxy(0), xoff(0), yoff(0), zoff(0),
00220 all_translation(), path(""), pathnum(0), rot_fp(0)
00221 {
00222 ENTERFUNC;
00223
00224
00225 attr_dict["apix_x"] = 1.0f;
00226 attr_dict["apix_y"] = 1.0f;
00227 attr_dict["apix_z"] = 1.0f;
00228
00229 if(is_real) {
00230 attr_dict["is_complex"] = int(0);
00231 attr_dict["is_complex_x"] = int(0);
00232 attr_dict["is_complex_ri"] = int(1);
00233 set_size(nx, ny, nz);
00234 }
00235 else {
00236 int new_nx = nx + 2 - nx%2;
00237 set_size(new_nx, ny, nz);
00238
00239 attr_dict["is_complex"] = int(1);
00240
00241 if(ny==1 && nz ==1) {
00242 attr_dict["is_complex_x"] = int(1);
00243 }
00244 else {
00245 attr_dict["is_complex_x"] = int(0);
00246 }
00247
00248 attr_dict["is_complex_ri"] = int(1);
00249 attr_dict["is_fftpad"] = int(1);
00250
00251 if(nx%2 == 1) {
00252 attr_dict["is_fftodd"] = 1;
00253 }
00254 }
00255
00256 this->to_zero();
00257 update();
00258 EMData::totalalloc++;
00259
00260 EXITFUNC;
00261 }
00262
00263
00264 EMData::EMData(float* data, const int x, const int y, const int z, const Dict& attr_dict) :
00265 #ifdef EMAN2_USING_CUDA
00266 cuda_cache_handle(-1),
00267 #endif
00268 attr_dict(attr_dict), rdata(data), supp(0), flags(0), changecount(0), nx(x), ny(y), nz(z), nxy(x*y), xoff(0),
00269 yoff(0), zoff(0), all_translation(), path(""), pathnum(0), rot_fp(0)
00270 {
00271 ENTERFUNC;
00272
00273
00274 attr_dict["apix_x"] = 1.0f;
00275 attr_dict["apix_y"] = 1.0f;
00276 attr_dict["apix_z"] = 1.0f;
00277
00278 EMData::totalalloc++;
00279
00280 update();
00281 EXITFUNC;
00282 }
00283
00284
00285 using std::cout;
00286 using std::endl;
00287 EMData::~EMData()
00288 {
00289 ENTERFUNC;
00290 free_memory();
00291 #ifdef EMAN2_USING_CUDA
00292
00293 free_cuda_memory();
00294 #endif // EMAN2_USING_CUDA
00295 EMData::totalalloc--;
00296 #ifdef MEMDEBUG
00297 printf("EMDATA- %4d %p\n",EMData::totalalloc,this);
00298 #endif
00299 EXITFUNC;
00300 }
00301
00302 void EMData::clip_inplace(const Region & area,const float& fill_value)
00303 {
00304
00305 ENTERFUNC;
00306
00307
00308 int prev_nx = nx, prev_ny = ny, prev_nz = nz;
00309 int prev_size = nx*ny*nz;
00310
00311
00312 int new_nz = ( area.size[2]==0 ? 1 : (int)area.size[2]);
00313 int new_ny = ( area.size[1]==0 ? 1 : (int)area.size[1]);
00314 int new_nx = (int)area.size[0];
00315
00316 if ( new_nz < 0 || new_ny < 0 || new_nx < 0 )
00317 {
00318
00319 throw ImageDimensionException("New image dimensions are negative - this is not supported in the clip_inplace operation");
00320 }
00321
00322 int new_size = new_nz*new_ny*new_nx;
00323
00324
00325 int x0 = (int) area.origin[0];
00326 int y0 = (int) area.origin[1];
00327 int z0 = (int) area.origin[2];
00328
00329
00330 ClipInplaceVariables civ(prev_nx, prev_ny, prev_nz, new_nx, new_ny, new_nz, x0, y0, z0);
00331
00332 get_data();
00333
00334 if ( x0 > prev_nx || y0 > prev_ny || z0 > prev_nz || civ.x_iter == 0 || civ.y_iter == 0 || civ.z_iter == 0)
00335 {
00336
00337
00338
00339
00340 set_size(new_nx, new_ny, new_nz);
00341
00342
00343 EMUtil::em_memset(rdata, 0, new_nx*new_ny*new_nz);
00344
00345 return;
00346 }
00347
00348
00349
00350
00351 if ( new_size > prev_size )
00352 set_size(new_nx, new_ny, new_nz);
00353
00354
00355 size_t clipped_row_size = (civ.x_iter) * sizeof(float);
00356
00357
00358 int new_sec_size = new_nx * new_ny;
00359 int prev_sec_size = prev_nx * prev_ny;
00360
00361
00362
00363 int src_it_begin = civ.prv_z_bottom*prev_sec_size + civ.prv_y_front*prev_nx + civ.prv_x_left;
00364 int dst_it_begin = civ.new_z_bottom*new_sec_size + civ.new_y_front*new_nx + civ.new_x_left;
00365
00366
00367
00368
00369 for (int i = 0; i < civ.z_iter; ++i) {
00370 for (int j = 0; j < civ.y_iter; ++j) {
00371
00372
00373
00374 int dst_inc = dst_it_begin + j*new_nx + i*new_sec_size;
00375 int src_inc = src_it_begin + j*prev_nx + i*prev_sec_size;
00376 float* local_dst = rdata + dst_inc;
00377 float* local_src = rdata + src_inc;
00378
00379 if ( dst_inc >= src_inc )
00380 {
00381
00382
00383
00384 continue;
00385 }
00386
00387
00388
00389 Assert( dst_inc < new_size && src_inc < prev_size && dst_inc >= 0 && src_inc >= 0 );
00390
00391
00392 EMUtil::em_memcpy(local_dst, local_src, clipped_row_size);
00393 }
00394 }
00395
00396
00397
00398 int src_it_end = prev_size - civ.prv_z_top*prev_sec_size - civ.prv_y_back*prev_nx - prev_nx + civ.prv_x_left;
00399 int dst_it_end = new_size - civ.new_z_top*new_sec_size - civ.new_y_back*new_nx - new_nx + civ.new_x_left;
00400
00401
00402
00403
00404 for (int i = 0; i < civ.z_iter; ++i) {
00405 for (int j = 0; j < civ.y_iter; ++j) {
00406
00407
00408 int dst_inc = dst_it_end - j*new_nx - i*new_sec_size;
00409 int src_inc = src_it_end - j*prev_nx - i*prev_sec_size;
00410 float* local_dst = rdata + dst_inc;
00411 float* local_src = rdata + src_inc;
00412
00413 if (dst_inc <= (src_inc + civ.x_iter ))
00414 {
00415
00416 if ( dst_inc > src_inc )
00417 {
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 memmove(local_dst, local_src, clipped_row_size);
00429 }
00430 continue;
00431 }
00432
00433
00434 Assert( dst_inc < new_size && src_inc < prev_size && dst_inc >= 0 && src_inc >= 0 );
00435
00436
00437 EMUtil::em_memcpy(local_dst, local_src, clipped_row_size);
00438 }
00439 }
00440
00441
00442
00443 if ( new_size < prev_size )
00444 set_size(new_nx, new_ny, new_nz);
00445
00446
00447
00448
00449 if ( z0 < 0 )
00450 {
00451
00452 int inc = (-z0)*new_sec_size;
00453 std::fill(rdata,rdata+inc,fill_value);
00454 }
00455
00456
00457 if ( civ.new_z_top > 0 )
00458 {
00459 float* begin_pointer = rdata + (new_nz-civ.new_z_top)*new_sec_size;
00460
00461 float* end_pointer = begin_pointer+(civ.new_z_top)*new_sec_size;
00462 std::fill(begin_pointer,end_pointer,fill_value);
00463 }
00464
00465
00466 for ( int i = civ.new_z_bottom; i < civ.new_z_bottom + civ.z_iter; ++i )
00467 {
00468
00469 if ( y0 < 0 )
00470 {
00471 float* begin_pointer = rdata + i*new_sec_size;
00472
00473 float* end_pointer = begin_pointer+(-y0)*new_nx;
00474 std::fill(begin_pointer,end_pointer,fill_value);
00475 }
00476
00477
00478 if ( civ.new_y_back > 0 )
00479 {
00480 float* begin_pointer = rdata + i*new_sec_size + (new_ny-civ.new_y_back)*new_nx;
00481
00482 float* end_pointer = begin_pointer+(civ.new_y_back)*new_nx;
00483 std::fill(begin_pointer,end_pointer,fill_value);
00484 }
00485
00486
00487 for (int j = civ.new_y_front; j <civ.new_y_front + civ.y_iter; ++j)
00488 {
00489
00490 if ( x0 < 0 )
00491 {
00492 float* begin_pointer = rdata + i*new_sec_size + j*new_nx;
00493
00494 float* end_pointer = begin_pointer+(-x0);
00495 std::fill(begin_pointer,end_pointer,fill_value);
00496 }
00497
00498
00499 if ( civ.new_x_right > 0 )
00500 {
00501 float* begin_pointer = rdata + i*new_sec_size + j*new_nx + (new_nx - civ.new_x_right);
00502
00503 float* end_pointer = begin_pointer+(civ.new_x_right);
00504 std::fill(begin_pointer,end_pointer,fill_value);
00505 }
00506
00507 }
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 if( attr_dict.has_key("origin_x") && attr_dict.has_key("origin_y") &&
00522 attr_dict.has_key("origin_z") )
00523 {
00524 float xorigin = attr_dict["origin_x"];
00525 float yorigin = attr_dict["origin_y"];
00526 float zorigin = attr_dict["origin_z"];
00527
00528 float apix_x = attr_dict["apix_x"];
00529 float apix_y = attr_dict["apix_y"];
00530 float apix_z = attr_dict["apix_z"];
00531
00532 set_xyz_origin(xorigin + apix_x * area.origin[0],
00533 yorigin + apix_y * area.origin[1],
00534 zorigin + apix_z * area.origin[2]);
00535 }
00536
00537
00538 update();
00539
00540 EXITFUNC;
00541 }
00542
00543 EMData *EMData::get_clip(const Region & area, const float fill) const
00544 {
00545 ENTERFUNC;
00546 if (get_ndim() != area.get_ndim()) {
00547 LOGERR("cannot get %dD clip out of %dD image", area.get_ndim(),get_ndim());
00548 return 0;
00549 }
00550
00551 EMData *result = new EMData();
00552
00553
00554
00555
00556 result->attr_dict = this->attr_dict;
00557 int zsize = (int)area.size[2];
00558 if (zsize == 0 && nz <= 1) {
00559 zsize = 1;
00560 }
00561 int ysize = (ny<=1 && (int)area.size[1]==0 ? 1 : (int)area.size[1]);
00562
00563 if ( (int)area.size[0] < 0 || ysize < 0 || zsize < 0 )
00564 {
00565
00566 throw ImageDimensionException("New image dimensions are negative - this is not supported in the the get_clip operation");
00567 }
00568
00569 #ifdef EMAN2_USING_CUDA
00570
00571 bool use_gpu = false;
00572 if ( gpu_operation_preferred() ) {
00573 result->set_size_cuda((int)area.size[0], ysize, zsize);
00574
00575 result->get_cuda_data();
00576
00577 result->to_value(fill);
00578 use_gpu = true;
00579 } else {
00580 result->set_size((int)area.size[0], ysize, zsize);
00581 if (fill != 0.0) { result->to_value(fill); };
00582 }
00583 #else
00584 result->set_size((int)area.size[0], ysize, zsize);
00585 if (fill != 0.0) { result->to_value(fill); };
00586 #endif //EMAN2_USING_CUDA
00587
00588 int x0 = (int) area.origin[0];
00589 x0 = x0 < 0 ? 0 : x0;
00590
00591 int y0 = (int) area.origin[1];
00592 y0 = y0 < 0 ? 0 : y0;
00593
00594 int z0 = (int) area.origin[2];
00595 z0 = z0 < 0 ? 0 : z0;
00596
00597 int x1 = (int) (area.origin[0] + area.size[0]);
00598 x1 = x1 > nx ? nx : x1;
00599
00600 int y1 = (int) (area.origin[1] + area.size[1]);
00601 y1 = y1 > ny ? ny : y1;
00602
00603 int z1 = (int) (area.origin[2] + area.size[2]);
00604 z1 = z1 > nz ? nz : z1;
00605 if (z1 <= 0) {
00606 z1 = 1;
00607 }
00608
00609 result->insert_clip(this,-((IntPoint)area.origin));
00610
00611 if( attr_dict.has_key("apix_x") && attr_dict.has_key("apix_y") &&
00612 attr_dict.has_key("apix_z") )
00613 {
00614 if( attr_dict.has_key("origin_x") && attr_dict.has_key("origin_y") &&
00615 attr_dict.has_key("origin_z") )
00616 {
00617 float xorigin = attr_dict["origin_x"];
00618 float yorigin = attr_dict["origin_y"];
00619 float zorigin = attr_dict["origin_z"];
00620
00621 float apix_x = attr_dict["apix_x"];
00622 float apix_y = attr_dict["apix_y"];
00623 float apix_z = attr_dict["apix_z"];
00624
00625 result->set_xyz_origin(xorigin + apix_x * area.origin[0],
00626 yorigin + apix_y * area.origin[1],
00627 zorigin + apix_z * area.origin[2]);
00628 }
00629 }
00630
00631 #ifdef EMAN2_USING_CUDA
00632 if (use_gpu) result->gpu_update();
00633 else result->update();
00634 #else
00635 result->update();
00636 #endif // EMAN2_USING_CUDA
00637
00638
00639 result->set_path(path);
00640 result->set_pathnum(pathnum);
00641
00642 EXITFUNC;
00643 return result;
00644 }
00645
00646
00647 EMData *EMData::get_top_half() const
00648 {
00649 ENTERFUNC;
00650
00651 if (get_ndim() != 3) {
00652 throw ImageDimensionException("3D only");
00653 }
00654
00655 EMData *half = new EMData();
00656 half->attr_dict = attr_dict;
00657 half->set_size(nx, ny, nz / 2);
00658
00659 float *half_data = half->get_data();
00660 EMUtil::em_memcpy(half_data, &(get_data()[nz / 2 * nx * ny]), sizeof(float) * nx * ny * nz / 2);
00661
00662 float apix_z = attr_dict["apix_z"];
00663 float origin_z = attr_dict["origin_z"];
00664 origin_z += apix_z * nz / 2;
00665 half->attr_dict["origin_z"] = origin_z;
00666 half->update();
00667
00668 EXITFUNC;
00669 return half;
00670 }
00671
00672
00673 EMData *EMData::get_rotated_clip(const Transform &xform,
00674 const IntSize &size, float)
00675 {
00676 EMData *result = new EMData();
00677 result->set_size(size[0],size[1],size[2]);
00678
00679 if (nz==1) {
00680 for (int y=-size[1]/2; y<(size[1]+1)/2; y++) {
00681 for (int x=-size[0]/2; x<(size[0]+1)/2; x++) {
00682 Vec3f xv=xform.transform(Vec3f((float)x,(float)y,0.0f));
00683 float v = 0;
00684
00685 if (xv[0]<0||xv[1]<0||xv[0]>nx-2||xv[1]>ny-2) v=0.;
00686 else v=sget_value_at_interp(xv[0],xv[1]);
00687 result->set_value_at(x+size[0]/2,y+size[1]/2,v);
00688 }
00689 }
00690 }
00691 else {
00692 for (int z=-size[2]/2; z<(size[2]+1)/2; z++) {
00693 for (int y=-size[1]/2; y<(size[1]+1)/2; y++) {
00694 for (int x=-size[0]/2; x<(size[0]+1)/2; x++) {
00695 Vec3f xv=xform.transform(Vec3f((float)x,(float)y,0.0f));
00696 float v = 0;
00697
00698 if (xv[0]<0||xv[1]<0||xv[2]<0||xv[0]>nx-2||xv[1]>ny-2||xv[2]>nz-2) v=0.;
00699 else v=sget_value_at_interp(xv[0],xv[1],xv[2]);
00700 result->set_value_at(x+size[0]/2,y+size[1]/2,z+size[2]/2,v);
00701 }
00702 }
00703 }
00704 }
00705 result->update();
00706
00707 return result;
00708 }
00709
00710
00711 EMData* EMData::window_center(int l) {
00712 ENTERFUNC;
00713
00714 int n = nx;
00715 if (is_complex()) {
00716 LOGERR("Need real-space data for window_center()");
00717 throw ImageFormatException(
00718 "Complex input image; real-space expected.");
00719 }
00720 if (is_fftpadded()) {
00721
00722 n -= (2 - int(is_fftodd()));
00723 }
00724 int corner = n/2 - l/2;
00725 int ndim = get_ndim();
00726 EMData* ret;
00727 switch (ndim) {
00728 case 3:
00729 if ((n != ny) || (n != nz)) {
00730 LOGERR("Need the real-space image to be cubic.");
00731 throw ImageFormatException(
00732 "Need cubic real-space image.");
00733 }
00734 ret = get_clip(Region(corner, corner, corner, l, l, l));
00735 break;
00736 case 2:
00737 if (n != ny) {
00738 LOGERR("Need the real-space image to be square.");
00739 throw ImageFormatException(
00740 "Need square real-space image.");
00741 }
00742
00743 ret = get_clip(Region(corner, corner, l, l));
00744 break;
00745 case 1:
00746 ret = get_clip(Region(corner, l));
00747 break;
00748 default:
00749 throw ImageDimensionException(
00750 "window_center only supports 1-d, 2-d, and 3-d images");
00751 }
00752 return ret;
00753 EXITFUNC;
00754 }
00755
00756
00757 float *EMData::setup4slice(bool redo)
00758 {
00759 ENTERFUNC;
00760
00761 if (!is_complex()) {
00762 throw ImageFormatException("complex image only");
00763 }
00764
00765 if (get_ndim() != 3) {
00766 throw ImageDimensionException("3D only");
00767 }
00768
00769 if (supp) {
00770 if (redo) {
00771 EMUtil::em_free(supp);
00772 supp = 0;
00773 }
00774 else {
00775 EXITFUNC;
00776 return supp;
00777 }
00778 }
00779
00780 const int SUPP_ROW_SIZE = 8;
00781 const int SUPP_ROW_OFFSET = 4;
00782 const int supp_size = SUPP_ROW_SIZE + SUPP_ROW_OFFSET;
00783
00784 supp = (float *) EMUtil::em_calloc(supp_size * ny * nz, sizeof(float));
00785 int nxy = nx * ny;
00786 int supp_xy = supp_size * ny;
00787 float * data = get_data();
00788
00789 for (int z = 0; z < nz; z++) {
00790 size_t cur_z1 = z * nxy;
00791 size_t cur_z2 = z * supp_xy;
00792
00793 for (int y = 0; y < ny; y++) {
00794 size_t cur_y1 = y * nx;
00795 size_t cur_y2 = y * supp_size;
00796
00797 for (int x = 0; x < SUPP_ROW_SIZE; x++) {
00798 size_t k = (x + SUPP_ROW_OFFSET) + cur_y2 + cur_z2;
00799 supp[k] = data[x + cur_y1 + cur_z1];
00800 }
00801 }
00802 }
00803
00804 for (int z = 1, zz = nz - 1; z < nz; z++, zz--) {
00805 size_t cur_z1 = zz * nxy;
00806 size_t cur_z2 = z * supp_xy;
00807
00808 for (int y = 1, yy = ny - 1; y < ny; y++, yy--) {
00809 supp[y * 12 + cur_z2] = data[4 + yy * nx + cur_z1];
00810 supp[1 + y * 12 + cur_z2] = -data[5 + yy * nx + cur_z1];
00811 supp[2 + y * 12 + cur_z2] = data[2 + yy * nx + cur_z1];
00812 supp[3 + y * 12 + cur_z2] = -data[3 + yy * nx + cur_z1];
00813 }
00814 }
00815
00816 EXITFUNC;
00817 return supp;
00818 }
00819
00820
00821 void EMData::scale(float s)
00822 {
00823 ENTERFUNC;
00824 Transform t;
00825 t.set_scale(s);
00826 transform(t);
00827 EXITFUNC;
00828 }
00829
00830
00831 void EMData::translate(int dx, int dy, int dz)
00832 {
00833 ENTERFUNC;
00834 translate(Vec3i(dx, dy, dz));
00835 EXITFUNC;
00836 }
00837
00838
00839 void EMData::translate(float dx, float dy, float dz)
00840 {
00841 ENTERFUNC;
00842 int dx_ = Util::round(dx);
00843 int dy_ = Util::round(dy);
00844 int dz_ = Util::round(dz);
00845 if( ( (dx-dx_) == 0 ) && ( (dy-dy_) == 0 ) && ( (dz-dz_) == 0 )) {
00846 translate(dx_, dy_, dz_);
00847 }
00848 else {
00849 translate(Vec3f(dx, dy, dz));
00850 }
00851 EXITFUNC;
00852 }
00853
00854
00855 void EMData::translate(const Vec3i &translation)
00856 {
00857 ENTERFUNC;
00858
00859
00860 if( translation[0] == 0 && translation[1] == 0 && translation[2] == 0) {
00861 EXITFUNC;
00862 return;
00863 }
00864
00865 Dict params("trans",static_cast< vector<int> >(translation));
00866 process_inplace("math.translate.int",params);
00867
00868
00869 all_translation += translation;
00870
00871 EXITFUNC;
00872 }
00873
00874
00875 void EMData::translate(const Vec3f &translation)
00876 {
00877 ENTERFUNC;
00878
00879 if( translation[0] == 0.0f && translation[1] == 0.0f && translation[2] == 0.0f ) {
00880 EXITFUNC;
00881 return;
00882 }
00883
00884 Transform* t = new Transform();
00885 t->set_trans(translation);
00886 process_inplace("math.transform",Dict("transform",t));
00887 delete t;
00888
00889 all_translation += translation;
00890 EXITFUNC;
00891 }
00892
00893
00894 void EMData::rotate(float az, float alt, float phi)
00895 {
00896 Dict d("type","eman");
00897 d["az"] = az;
00898 d["alt"] = alt;
00899 d["phi"] = phi;
00900 Transform t(d);
00901 transform(t);
00902 }
00903
00904
00905
00906 void EMData::rotate(const Transform3D & t)
00907 {
00908 cout << "Deprecation warning in EMData::rotate. Please consider using EMData::transform() instead " << endl;
00909 rotate_translate(t);
00910 }
00911
00912
00913 void EMData::rotate_translate(float az, float alt, float phi, float dx, float dy, float dz)
00914 {
00915 cout << "Deprecation warning in EMData::rotate_translate. Please consider using EMData::transform() instead " << endl;
00916 Transform3D t( az, alt, phi,Vec3f(dx, dy, dz));
00917 rotate_translate(t);
00918 }
00919
00920
00921 void EMData::rotate_translate(float az, float alt, float phi, float dx, float dy,
00922 float dz, float pdx, float pdy, float pdz)
00923 {
00924 cout << "Deprecation warning in EMData::rotate_translate. Please consider using EMData::transform() instead " << endl;
00925 Transform3D t(Vec3f(dx, dy, dz), az, alt, phi, Vec3f(pdx,pdy,pdz));
00926 rotate_translate(t);
00927 }
00928
00929 void EMData::rotate_translate(const Transform3D & RA)
00930 {
00931 cout << "Deprecation warning in EMData::rotate_translate. Please consider using EMData::transform() instead " << endl;
00932 ENTERFUNC;
00933
00934 #if EMDATA_EMAN2_DEBUG
00935 std::cout << "start rotate_translate..." << std::endl;
00936 #endif
00937
00938 float scale = RA.get_scale();
00939 Vec3f dcenter = RA.get_center();
00940 Vec3f translation = RA.get_posttrans();
00941 Dict rotation = RA.get_rotation(Transform3D::EMAN);
00942
00943 Transform3D RAInv = RA.inverse();
00944
00945 #if EMDATA_EMAN2_DEBUG
00946 vector<string> keys = rotation.keys();
00947 vector<string>::const_iterator it;
00948 for(it=keys.begin(); it!=keys.end(); ++it) {
00949
00950 std::cout << *it << " : " << (float)rotation.get(*it) << std::endl;
00951 }
00952 #endif
00953 float inv_scale = 1.0f;
00954
00955 if (scale != 0) {
00956 inv_scale = 1.0f / scale;
00957 }
00958
00959 float *src_data = 0;
00960 float *des_data = 0;
00961
00962 src_data = get_data();
00963 des_data = (float *) EMUtil::em_malloc(nx * ny * nz * sizeof(float));
00964
00965 if (nz == 1) {
00966 float x2c = nx / 2 - dcenter[0] + RAInv[0][3];
00967 float y2c = ny / 2 - dcenter[1] + RAInv[1][3];
00968 float y = -ny / 2 + dcenter[1];
00969 for (int j = 0; j < ny; j++, y += 1.0f) {
00970 float x = -nx / 2 + dcenter[0];
00971 for (int i = 0; i < nx; i++, x += 1.0f) {
00972 float x2 = RAInv[0][0]*x + RAInv[0][1]*y + x2c;
00973 float y2 = RAInv[1][0]*x + RAInv[1][1]*y + y2c;
00974
00975 if (x2 < 0 || x2 >= nx || y2 < 0 || y2 >= ny ) {
00976 des_data[i + j * nx] = 0;
00977
00978 }
00979 else {
00980 int ii = Util::fast_floor(x2);
00981 int jj = Util::fast_floor(y2);
00982 int k0 = ii + jj * nx;
00983 int k1 = k0 + 1;
00984 int k2 = k0 + nx;
00985 int k3 = k0 + nx + 1;
00986
00987 if (ii == nx - 1) {
00988 k1--;
00989 k3--;
00990 }
00991 if (jj == ny - 1) {
00992 k2 -= nx;
00993 k3 -= nx;
00994 }
00995
00996 float t = x2 - ii;
00997 float u = y2 - jj;
00998
00999 des_data[i + j * nx] = Util::bilinear_interpolate(src_data[k0],src_data[k1], src_data[k2], src_data[k3],t,u);
01000 }
01001 }
01002 }
01003 }
01004 else {
01005 #if EMDATA_EMAN2_DEBUG
01006 std::cout << "This is the 3D case." << std::endl ;
01007 #endif
01008
01009 Transform3D mx = RA;
01010 mx.set_scale(inv_scale);
01011
01012 #if EMDATA_EMAN2_DEBUG
01013
01014
01015 #endif
01016
01017 int nxy = nx * ny;
01018 int l = 0;
01019
01020 float x2c = nx / 2 - dcenter[0] + RAInv[0][3];;
01021 float y2c = ny / 2 - dcenter[1] + RAInv[1][3];;
01022 float z2c = nz / 2 - dcenter[2] + RAInv[2][3];;
01023
01024 float z = -nz / 2 + dcenter[2];
01025
01026 size_t ii, k0, k1, k2, k3, k4, k5, k6, k7;
01027 for (int k = 0; k < nz; k++, z += 1.0f) {
01028 float y = -ny / 2 + dcenter[1];
01029 for (int j = 0; j < ny; j++, y += 1.0f) {
01030 float x = -nx / 2 + dcenter[0];
01031 for (int i = 0; i < nx; i++, l++ , x += 1.0f) {
01032 float x2 = RAInv[0][0] * x + RAInv[0][1] * y + RAInv[0][2] * z + x2c;
01033 float y2 = RAInv[1][0] * x + RAInv[1][1] * y + RAInv[1][2] * z + y2c;
01034 float z2 = RAInv[2][0] * x + RAInv[2][1] * y + RAInv[2][2] * z + z2c;
01035
01036
01037 if (x2 < 0 || y2 < 0 || z2 < 0 ||
01038 x2 >= nx || y2 >= ny || z2>= nz ) {
01039 des_data[l] = 0;
01040 }
01041 else {
01042 int ix = Util::fast_floor(x2);
01043 int iy = Util::fast_floor(y2);
01044 int iz = Util::fast_floor(z2);
01045 float tuvx = x2-ix;
01046 float tuvy = y2-iy;
01047 float tuvz = z2-iz;
01048 ii = ix + iy * nx + iz * nxy;
01049
01050 k0 = ii;
01051 k1 = k0 + 1;
01052 k2 = k0 + nx;
01053 k3 = k0 + nx+1;
01054 k4 = k0 + nxy;
01055 k5 = k1 + nxy;
01056 k6 = k2 + nxy;
01057 k7 = k3 + nxy;
01058
01059 if (ix == nx - 1) {
01060 k1--;
01061 k3--;
01062 k5--;
01063 k7--;
01064 }
01065 if (iy == ny - 1) {
01066 k2 -= nx;
01067 k3 -= nx;
01068 k6 -= nx;
01069 k7 -= nx;
01070 }
01071 if (iz == nz - 1) {
01072 k4 -= nxy;
01073 k5 -= nxy;
01074 k6 -= nxy;
01075 k7 -= nxy;
01076 }
01077
01078 des_data[l] = Util::trilinear_interpolate(src_data[k0],
01079 src_data[k1],
01080 src_data[k2],
01081 src_data[k3],
01082 src_data[k4],
01083 src_data[k5],
01084 src_data[k6],
01085 src_data[k7],
01086 tuvx, tuvy, tuvz);
01087 #if EMDATA_EMAN2_DEBUG
01088 printf(" ix=%d \t iy=%d \t iz=%d \t value=%f \n", ix ,iy, iz, des_data[l] );
01089 std::cout << src_data[ii] << std::endl;
01090 #endif
01091 }
01092 }
01093 }
01094 }
01095 }
01096
01097 if( rdata )
01098 {
01099 EMUtil::em_free(rdata);
01100 rdata = 0;
01101 }
01102 rdata = des_data;
01103
01104 scale_pixel(inv_scale);
01105
01106 attr_dict["origin_x"] = (float) attr_dict["origin_x"] * inv_scale;
01107 attr_dict["origin_y"] = (float) attr_dict["origin_y"] * inv_scale;
01108 attr_dict["origin_z"] = (float) attr_dict["origin_z"] * inv_scale;
01109
01110 update();
01111 all_translation += translation;
01112 EXITFUNC;
01113 }
01114
01115
01116
01117
01118 void EMData::rotate_x(int dx)
01119 {
01120 ENTERFUNC;
01121
01122 if (get_ndim() > 2) {
01123 throw ImageDimensionException("no 3D image");
01124 }
01125
01126
01127 size_t row_size = nx * sizeof(float);
01128 float *tmp = (float*)EMUtil::em_malloc(row_size);
01129 float * data = get_data();
01130
01131 for (int y = 0; y < ny; y++) {
01132 int y_nx = y * nx;
01133 for (int x = 0; x < nx; x++) {
01134 tmp[x] = data[y_nx + (x + dx) % nx];
01135 }
01136 EMUtil::em_memcpy(&data[y_nx], tmp, row_size);
01137 }
01138
01139 update();
01140 if( tmp )
01141 {
01142 delete[]tmp;
01143 tmp = 0;
01144 }
01145 EXITFUNC;
01146 }
01147
01148 double EMData::dot_rotate_translate(EMData * with, float dx, float dy, float da, const bool mirror)
01149 {
01150 ENTERFUNC;
01151
01152 if (!EMUtil::is_same_size(this, with)) {
01153 LOGERR("images not same size");
01154 throw ImageFormatException("images not same size");
01155 }
01156
01157 if (get_ndim() == 3) {
01158 LOGERR("1D/2D Images only");
01159 throw ImageDimensionException("1D/2D only");
01160 }
01161
01162 float *this_data = 0;
01163
01164 this_data = get_data();
01165
01166 float da_rad = da*(float)M_PI/180.0f;
01167
01168 float *with_data = with->get_data();
01169 float mx0 = cos(da_rad);
01170 float mx1 = sin(da_rad);
01171 float y = -ny / 2.0f;
01172 float my0 = mx0 * (-nx / 2.0f - 1.0f) + nx / 2.0f - dx;
01173 float my1 = -mx1 * (-nx / 2.0f - 1.0f) + ny / 2.0f - dy;
01174 double result = 0;
01175
01176 for (int j = 0; j < ny; j++) {
01177 float x2 = my0 + mx1 * y;
01178 float y2 = my1 + mx0 * y;
01179
01180 int ii = Util::fast_floor(x2);
01181 int jj = Util::fast_floor(y2);
01182 float t = x2 - ii;
01183 float u = y2 - jj;
01184
01185 for (int i = 0; i < nx; i++) {
01186 t += mx0;
01187 u -= mx1;
01188
01189 if (t >= 1.0f) {
01190 ii++;
01191 t -= 1.0f;
01192 }
01193
01194 if (u >= 1.0f) {
01195 jj++;
01196 u -= 1.0f;
01197 }
01198
01199 if (t < 0) {
01200 ii--;
01201 t += 1.0f;
01202 }
01203
01204 if (u < 0) {
01205 jj--;
01206 u += 1.0f;
01207 }
01208
01209 if (ii >= 0 && ii <= nx - 2 && jj >= 0 && jj <= ny - 2) {
01210 int k0 = ii + jj * nx;
01211 int k1 = k0 + 1;
01212 int k2 = k0 + nx + 1;
01213 int k3 = k0 + nx;
01214
01215 float tt = 1 - t;
01216 float uu = 1 - u;
01217 int idx = i + j * nx;
01218 if (mirror) idx = nx-1-i+j*nx;
01219 result += (this_data[k0] * tt * uu + this_data[k1] * t * uu +
01220 this_data[k2] * t * u + this_data[k3] * tt * u) * with_data[idx];
01221 }
01222 }
01223 y += 1.0f;
01224 }
01225
01226 EXITFUNC;
01227 return result;
01228 }
01229
01230
01231 EMData *EMData::little_big_dot(EMData * with, bool do_sigma)
01232 {
01233 ENTERFUNC;
01234
01235 if (get_ndim() > 2) {
01236 throw ImageDimensionException("1D/2D only");
01237 }
01238
01239 EMData *ret = copy_head();
01240 ret->set_size(nx,ny,nz);
01241 ret->to_zero();
01242
01243 int nx2 = with->get_xsize();
01244 int ny2 = with->get_ysize();
01245 float em = with->get_edge_mean();
01246
01247 float *data = get_data();
01248 float *with_data = with->get_data();
01249 float *ret_data = ret->get_data();
01250
01251 float sum2 = (Util::square((float)with->get_attr("sigma")) +
01252 Util::square((float)with->get_attr("mean")));
01253 if (do_sigma) {
01254 for (int j = ny2 / 2; j < ny - ny2 / 2; j++) {
01255 for (int i = nx2 / 2; i < nx - nx2 / 2; i++) {
01256 float sum = 0;
01257 float sum1 = 0;
01258 float summ = 0;
01259 int k = 0;
01260
01261 for (int jj = j - ny2 / 2; jj < j + ny2 / 2; jj++) {
01262 for (int ii = i - nx2 / 2; ii < i + nx2 / 2; ii++) {
01263 int l = ii + jj * nx;
01264 sum1 += Util::square(data[l]);
01265 summ += data[l];
01266 sum += data[l] * with_data[k];
01267 k++;
01268 }
01269 }
01270 float tmp_f1 = (sum1 / 2.0f - sum) / (nx2 * ny2);
01271 float tmp_f2 = Util::square((float)with->get_attr("mean") -
01272 summ / (nx2 * ny2));
01273 ret_data[i + j * nx] = sum2 + tmp_f1 - tmp_f2;
01274 }
01275 }
01276 }
01277 else {
01278 for (int j = ny2 / 2; j < ny - ny2 / 2; j++) {
01279 for (int i = nx2 / 2; i < nx - nx2 / 2; i++) {
01280 float eml = 0;
01281 float dot = 0;
01282 float dot2 = 0;
01283
01284 for (int ii = i - nx2 / 2; ii < i + nx2 / 2; ii++) {
01285 eml += data[ii + (j - ny2 / 2) * nx] + data[ii + (j + ny2 / 2 - 1) * nx];
01286 }
01287
01288 for (int jj = j - ny2 / 2; jj < j + ny2 / 2; jj++) {
01289 eml += data[i - nx2 / 2 + jj * nx] + data[i + nx2 / 2 - 1 + jj * nx];
01290 }
01291
01292 eml /= (nx2 + ny2) * 2.0f;
01293 int k = 0;
01294
01295 for (int jj = j - ny2 / 2; jj < j + ny2 / 2; jj++) {
01296 for (int ii = i - nx2 / 2; ii < i + nx2 / 2; ii++) {
01297 dot += (data[ii + jj * nx] - eml) * (with_data[k] - em);
01298 dot2 += Util::square(data[ii + jj * nx] - eml);
01299 k++;
01300 }
01301 }
01302
01303 dot2 = std::sqrt(dot2);
01304
01305 if (dot2 == 0) {
01306 ret_data[i + j * nx] = 0;
01307 }
01308 else {
01309 ret_data[i + j * nx] = dot / (nx2 * ny2 * dot2 * (float)with->get_attr("sigma"));
01310 }
01311 }
01312 }
01313 }
01314
01315 ret->update();
01316
01317 EXITFUNC;
01318 return ret;
01319 }
01320
01321
01322 EMData *EMData::do_radon()
01323 {
01324 ENTERFUNC;
01325
01326 if (get_ndim() != 2) {
01327 throw ImageDimensionException("2D only");
01328 }
01329
01330 if (nx != ny) {
01331 throw ImageFormatException("square image only");
01332 }
01333
01334 EMData *result = new EMData();
01335 result->set_size(nx, ny, 1);
01336 result->to_zero();
01337 float *result_data = result->get_data();
01338
01339 EMData *this_copy = this;
01340 this_copy = copy();
01341
01342 for (int i = 0; i < nx; i++) {
01343 Transform t(Dict("type","2d","alpha",(float) M_PI * 2.0f * i / nx));
01344 this_copy->transform(t);
01345
01346 float *copy_data = this_copy->get_data();
01347
01348 for (int y = 0; y < nx; y++) {
01349 for (int x = 0; x < nx; x++) {
01350 if (Util::square(x - nx / 2) + Util::square(y - nx / 2) <= nx * nx / 4) {
01351 result_data[i + y * nx] += copy_data[x + y * nx];
01352 }
01353 }
01354 }
01355
01356 this_copy->update();
01357 }
01358
01359 result->update();
01360
01361 if( this_copy )
01362 {
01363 delete this_copy;
01364 this_copy = 0;
01365 }
01366
01367 EXITFUNC;
01368 return result;
01369 }
01370
01371 void EMData::zero_corner_circulant(const int radius)
01372 {
01373 if ( nz > 1 && nz < (2*radius+1) ) throw ImageDimensionException("Error: cannot zero corner - nz is too small");
01374 if ( ny > 1 && ny < (2*radius+1) ) throw ImageDimensionException("Error: cannot zero corner - ny is too small");
01375 if ( nx > 1 && nx < (2*radius+1) ) throw ImageDimensionException("Error: cannot zero corner - nx is too small");
01376
01377 int it_z = radius;
01378 int it_y = radius;
01379 int it_x = radius;
01380
01381 if ( nz == 1 ) it_z = 0;
01382 if ( ny == 1 ) it_y = 0;
01383 if ( nx == 1 ) it_z = 0;
01384
01385 if ( nz == 1 && ny == 1 )
01386 {
01387 for ( int x = -it_x; x <= it_x; ++x )
01388 get_value_at_wrap(x) = 0;
01389
01390 }
01391 else if ( nz == 1 )
01392 {
01393 for ( int y = -it_y; y <= it_y; ++y)
01394 for ( int x = -it_x; x <= it_x; ++x )
01395 get_value_at_wrap(x,y) = 0;
01396 }
01397 else
01398 {
01399 for( int z = -it_z; z <= it_z; ++z )
01400 for ( int y = -it_y; y <= it_y; ++y)
01401 for ( int x = -it_x; x < it_x; ++x )
01402 get_value_at_wrap(x,y,z) = 0;
01403
01404 }
01405
01406 }
01407
01408 EMData *EMData::calc_ccf(EMData * with, fp_flag fpflag,bool center)
01409 {
01410 ENTERFUNC;
01411 if( with == 0 ) {
01412 EXITFUNC;
01413 return convolution(this,this,fpflag, center);
01414 }
01415 else if ( with == this ){
01416 EXITFUNC;
01417 return correlation(this, this, fpflag,center);
01418 }
01419 else {
01420
01421 #ifdef EMAN2_USING_CUDA
01422 if (gpu_operation_preferred()) {
01423 EXITFUNC;
01424 return calc_ccf_cuda(with,false,center);
01425 }
01426 #endif
01427
01428
01429 bool undoresize = false;
01430 int wnx = with->get_xsize(); int wny = with->get_ysize(); int wnz = with->get_zsize();
01431 if ( wnx != nx || wny != ny || wnz != nz ) {
01432 Region r((wnx-nx)/2, (wny-ny)/2, (wnz-nz)/2,nx,ny,nz);
01433 with->clip_inplace(r);
01434 undoresize = true;
01435 }
01436
01437 EMData* cor = correlation(this, with, fpflag, center);
01438
01439
01440 if ( undoresize ) {
01441 Region r((nx-wnx)/2, (ny-wny)/2,(nz-wnz)/2,wnx,wny,wnz);
01442 with->clip_inplace(r);
01443 }
01444
01445 EXITFUNC;
01446 return cor;
01447 }
01448 }
01449
01450 EMData *EMData::calc_ccfx( EMData * const with, int y0, int y1, bool no_sum)
01451 {
01452 ENTERFUNC;
01453
01454 #ifdef EMAN2_USING_CUDA
01455 if (gpu_operation_preferred() ) {
01456 EXITFUNC;
01457 return calc_ccfx_cuda(with,y0,y1,no_sum);
01458 }
01459 #endif
01460
01461 if (!with) {
01462 LOGERR("NULL 'with' image. ");
01463 throw NullPointerException("NULL input image");
01464 }
01465
01466 if (!EMUtil::is_same_size(this, with)) {
01467 LOGERR("images not same size: (%d,%d,%d) != (%d,%d,%d)",
01468 nx, ny, nz,
01469 with->get_xsize(), with->get_ysize(), with->get_zsize());
01470 throw ImageFormatException("images not same size");
01471 }
01472 if (get_ndim() > 2) {
01473 LOGERR("2D images only");
01474 throw ImageDimensionException("2D images only");
01475 }
01476
01477 if (y1 <= y0) {
01478 y1 = ny;
01479 }
01480
01481 if (y0 >= y1) {
01482 y0 = 0;
01483 }
01484
01485 if (y0 < 0) {
01486 y0 = 0;
01487 }
01488
01489 if (y1 > ny) {
01490 y1 = ny;
01491 }
01492 if (is_complex_x() || with->is_complex_x() ) throw;
01493
01494 static int nx_fft = 0;
01495 static int ny_fft = 0;
01496 static EMData f1;
01497 static EMData f2;
01498 static EMData rslt;
01499
01500 int height = y1-y0;
01501 int width = (nx+2-(nx%2));
01502 if (width != nx_fft || height != ny_fft ) {
01503 f1.set_size(width,height);
01504 f2.set_size(width,height);
01505 rslt.set_size(nx,height);
01506 nx_fft = width;
01507 ny_fft = height;
01508 }
01509
01510 float *d1 = get_data();
01511 float *d2 = with->get_data();
01512 float *f1d = f1.get_data();
01513 float *f2d = f2.get_data();
01514 for (int j = 0; j < height; j++) {
01515 EMfft::real_to_complex_1d(d1 + j * nx, f1d+j*width, nx);
01516 EMfft::real_to_complex_1d(d2 + j * nx, f2d+j*width, nx);
01517 }
01518
01519 for (int j = 0; j < height; j++) {
01520 float *f1a = f1d + j * width;
01521 float *f2a = f2d + j * width;
01522
01523 for (int i = 0; i < width / 2; i++) {
01524 float re1 = f1a[2*i];
01525 float re2 = f2a[2*i];
01526 float im1 = f1a[2*i+1];
01527 float im2 = f2a[2*i+1];
01528
01529 f1d[j*width+i*2] = re1 * re2 + im1 * im2;
01530 f1d[j*width+i*2+1] = im1 * re2 - re1 * im2;
01531 }
01532 }
01533
01534 float* rd = rslt.get_data();
01535 for (int j = y0; j < y1; j++) {
01536 EMfft::complex_to_real_1d(f1d+j*width, rd+j*nx, nx);
01537 }
01538
01539 if (no_sum) {
01540 rslt.update();
01541 EXITFUNC;
01542 return new EMData(rslt);
01543 } else {
01544 EMData *cf = new EMData(nx,1,1);
01545 cf->to_zero();
01546 float *c = cf->get_data();
01547 for (int j = 0; j < height; j++) {
01548 for(int i = 0; i < nx; ++i) {
01549 c[i] += rd[i+j*nx];
01550 }
01551 }
01552 cf->update();
01553 EXITFUNC;
01554 return cf;
01555 }
01556 }
01557
01558 EMData *EMData::make_rotational_footprint_cmc( bool unwrap) {
01559 ENTERFUNC;
01560 update_stat();
01561
01562
01563
01564
01565
01566
01567 if ( rot_fp != 0 && unwrap == true) {
01568 return new EMData(*rot_fp);
01569 }
01570
01571 static EMData obj_filt;
01572 EMData* filt = &obj_filt;
01573 filt->set_complex(true);
01574
01575
01576
01577
01578
01579
01580 if (filt->get_xsize() != nx+2-(nx%2) || filt->get_ysize() != ny ||
01581 filt->get_zsize() != nz ) {
01582 filt->set_size(nx+2-(nx%2), ny, nz);
01583 filt->to_one();
01584
01585 filt->process_inplace("eman1.filter.highpass.gaussian", Dict("highpass", 1.5f/nx));
01586 }
01587
01588 EMData *ccf = this->calc_mutual_correlation(this, true,filt);
01589 ccf->sub(ccf->get_edge_mean());
01590 EMData *result = ccf->unwrap();
01591 delete ccf; ccf = 0;
01592
01593 EXITFUNC;
01594 if ( unwrap == true)
01595 {
01596
01597
01598
01599
01600
01601
01602
01603
01604 rot_fp = result;
01605 return new EMData(*rot_fp);
01606 }
01607 else return result;
01608 }
01609
01610 EMData *EMData::make_rotational_footprint( bool unwrap) {
01611 ENTERFUNC;
01612 update_stat();
01613
01614
01615
01616
01617
01618
01619 if ( rot_fp != 0 && unwrap == true) {
01620 return new EMData(*rot_fp);
01621 }
01622
01623 EMData* ccf = this->calc_ccf(this,CIRCULANT,true);
01624 ccf->sub(ccf->get_edge_mean());
01625
01626 EMData *result = ccf->unwrap();
01627 delete ccf; ccf = 0;
01628
01629 EXITFUNC;
01630 if ( unwrap == true)
01631 {
01632
01633
01634
01635
01636
01637
01638
01639 rot_fp = result;
01640 return new EMData(*rot_fp);
01641 }
01642 else return result;
01643 }
01644
01645 EMData *EMData::make_rotational_footprint_e1( bool unwrap)
01646 {
01647 ENTERFUNC;
01648 #ifdef EMAN2_USING_CUDA
01649 if (gpu_operation_preferred()) {
01650 EXITFUNC;
01651 return make_rotational_footprint_cuda(unwrap);
01652 }
01653 #endif
01654
01655 update_stat();
01656
01657
01658
01659
01660
01661
01662 if ( rot_fp != 0 && unwrap == true) {
01663 return new EMData(*rot_fp);
01664 }
01665
01666 static EMData obj_filt;
01667 EMData* filt = &obj_filt;
01668 filt->set_complex(true);
01669
01670
01671
01672
01673
01674
01675 int cs = (((nx * 7 / 4) & 0xfffff8) - nx) / 2;
01676
01677 static EMData big_clip;
01678 int big_x = nx+2*cs;
01679 int big_y = ny+2*cs;
01680 int big_z = 1;
01681 if ( nz != 1 ) {
01682 big_z = nz+2*cs;
01683 }
01684
01685
01686 if ( big_clip.get_xsize() != big_x || big_clip.get_ysize() != big_y || big_clip.get_zsize() != big_z ) {
01687 big_clip.set_size(big_x,big_y,big_z);
01688 }
01689
01690
01691
01692 big_clip.to_value(get_edge_mean());
01693
01694 if (nz != 1) {
01695 big_clip.insert_clip(this,IntPoint(cs,cs,cs));
01696 } else {
01697 big_clip.insert_clip(this,IntPoint(cs,cs,0));
01698 }
01699
01700
01701
01702
01703
01704
01705 if (filt->get_xsize() != big_clip.get_xsize() +2-(big_clip.get_xsize()%2) || filt->get_ysize() != big_clip.get_ysize() ||
01706 filt->get_zsize() != big_clip.get_zsize()) {
01707 filt->set_size(big_clip.get_xsize() + 2-(big_clip.get_xsize()%2), big_clip.get_ysize(), big_clip.get_zsize());
01708 filt->to_one();
01709 filt->process_inplace("eman1.filter.highpass.gaussian", Dict("highpass", 1.5f/nx));
01710 }
01711 EMData *mc = big_clip.calc_mutual_correlation(&big_clip, true,filt);
01712 mc->sub(mc->get_edge_mean());
01713
01714 static EMData sml_clip;
01715 int sml_x = nx * 3 / 2;
01716 int sml_y = ny * 3 / 2;
01717 int sml_z = 1;
01718 if ( nz != 1 ) {
01719 sml_z = nz * 3 / 2;
01720 }
01721
01722 if ( sml_clip.get_xsize() != sml_x || sml_clip.get_ysize() != sml_y || sml_clip.get_zsize() != sml_z ) {
01723 sml_clip.set_size(sml_x,sml_y,sml_z); }
01724 if (nz != 1) {
01725 sml_clip.insert_clip(mc,IntPoint(-cs+nx/4,-cs+ny/4,-cs+nz/4));
01726 } else {
01727 sml_clip.insert_clip(mc,IntPoint(-cs+nx/4,-cs+ny/4,0));
01728 }
01729
01730 delete mc; mc = 0;
01731 EMData * result = NULL;
01732
01733 if (nz == 1) {
01734 if (!unwrap) {
01735 result = sml_clip.process("mask.sharp", Dict("outer_radius", -1, "value", 0));
01736
01737 }
01738 else {
01739 result = sml_clip.unwrap();
01740 }
01741 }
01742 else {
01743
01744
01745
01746 result = new EMData(sml_clip);
01747 }
01748
01749 EXITFUNC;
01750 if ( unwrap == true)
01751 {
01752
01753
01754
01755 if ( rot_fp != 0 ) throw UnexpectedBehaviorException("The rotational foot print is only expected to be cached if it is not NULL");
01756
01757
01758
01759 rot_fp = result;
01760 return new EMData(*rot_fp);
01761 }
01762 else return result;
01763 }
01764
01765 EMData *EMData::make_footprint(int type)
01766 {
01767
01768 if (type==0) {
01769 EMData *un=make_rotational_footprint_e1();
01770 if (un->get_ysize() <= 6) {
01771 throw UnexpectedBehaviorException("In EMData::make_footprint. The rotational footprint is too small");
01772 }
01773 EMData *tmp=un->get_clip(Region(0,4,un->get_xsize(),un->get_ysize()-6));
01774 EMData *cx=tmp->calc_ccfx(tmp,0,-1,1);
01775 EMData *fp=cx->get_clip(Region(0,0,cx->get_xsize()/2,cx->get_ysize()));
01776 delete un;
01777 delete tmp;
01778 delete cx;
01779 return fp;
01780 }
01781 else if (type==1 || type==2 ||type==5 || type==6) {
01782 int i,j,kx,ky,lx,ly;
01783
01784 EMData *fft=do_fft();
01785
01786
01787 int rmax=(get_xsize()+1)/2;
01788 float *rmap=(float *)malloc(rmax*rmax*sizeof(float));
01789 for (i=0; i<rmax; i++) {
01790 for (j=0; j<rmax; j++) {
01791 #ifdef _WIN32
01792 rmap[i+j*rmax]=_hypotf((float)i,(float)j);
01793 #else
01794 rmap[i+j*rmax]=hypot((float)i,(float)j);
01795 #endif //_WIN32
01796
01797 }
01798 }
01799
01800 EMData *fp=new EMData(rmax*2+2,rmax*2,1);
01801 fp->set_complex(1);
01802 fp->to_zero();
01803
01804
01805
01806
01807 for (kx=-rmax+1; kx<rmax; kx++) {
01808 for (ky=-rmax+1; ky<rmax; ky++) {
01809 for (lx=-rmax+1; lx<rmax; lx++) {
01810 for (ly=-rmax+1; ly<rmax; ly++) {
01811 int ax=kx+lx;
01812 int ay=ky+ly;
01813 if (abs(ax)>=rmax || abs(ay)>=rmax) continue;
01814 int r1=(int)floor(.5+rmap[abs(kx)+rmax*abs(ky)]);
01815 int r2=(int)floor(.5+rmap[abs(lx)+rmax*abs(ly)]);
01816
01817
01818 if (r1+r2>=rmax) continue;
01819
01820 std::complex<float> p=fft->get_complex_at(kx,ky)*fft->get_complex_at(lx,ly)*conj(fft->get_complex_at(ax,ay));
01821 fp->set_value_at(r1*2,r2,p.real()+fp->get_value_at(r1*2,r2));
01822
01823
01824 fp->set_value_at(r1*2+1,r2,fp->get_value_at(r1*2+1,r2)+1);
01825 }
01826 }
01827 }
01828 }
01829
01830
01831 if (type==5 || type==6) {
01832 for (i=0; i<rmax*2; i+=2) {
01833 for (j=0; j<rmax; j++) {
01834 float norm=fp->get_value_at(i+1,j);
01835 #ifdef _WIN32
01836 fp->set_value_at(i,rmax*2-j-1,pow(fp->get_value_at(i,j)/(norm==0.0f?1.0f:norm), 1.0f/3.0f));
01837 fp->set_value_at(i,j,pow(fp->get_value_at(i,j)/(norm==0.0f?1.0f:norm), 1.0f/3.0f));
01838 #else
01839 fp->set_value_at(i,rmax*2-j-1,cbrt(fp->get_value_at(i,j)/(norm==0?1.0:norm)));
01840 fp->set_value_at(i,j,cbrt(fp->get_value_at(i,j)/(norm==0?1.0:norm)));
01841 #endif //_WIN32
01842 fp->set_value_at(i+1,j,0.0);
01843 }
01844 }
01845 }
01846 else {
01847 for (i=0; i<rmax*2; i+=2) {
01848 for (j=0; j<rmax; j++) {
01849 float norm=fp->get_value_at(i+1,j);
01850 fp->set_value_at(i,rmax*2-j-1,fp->get_value_at(i,j)/(norm==0.0f?1.0f:norm));
01851 fp->set_value_at(i,j,fp->get_value_at(i,j)/(norm==0.0f?1.0f:norm));
01852 fp->set_value_at(i+1,j,0.0);
01853 }
01854 }
01855 }
01856
01857 free(rmap);
01858 if (type==2||type==6) {
01859 EMData *f2=fp->do_ift();
01860 if (f2->get_value_at(0,0)<0) f2->mult(-1.0f);
01861 f2->process_inplace("xform.phaseorigin.tocorner");
01862 delete fp;
01863 return f2;
01864 }
01865 return fp;
01866 }
01867 else if (type==3 || type==4) {
01868 int h,i,j,kx,ky,lx,ly;
01869
01870 EMData *fft=do_fft();
01871
01872
01873 int rmax=(get_xsize()+1)/2;
01874 float *rmap=(float *)malloc(rmax*rmax*sizeof(float));
01875 for (i=0; i<rmax; i++) {
01876 for (j=0; j<rmax; j++) {
01877 #ifdef _WIN32
01878 rmap[i+j*rmax]=_hypotf((float)i,(float)j);
01879 #else
01880 rmap[i+j*rmax]=hypot((float)i,(float)j);
01881 #endif //_WIN32
01882
01883 }
01884 }
01885
01886 EMData *fp=new EMData(rmax*2+2,rmax*2,16);
01887
01888 fp->set_complex(1);
01889 fp->to_zero();
01890
01891
01892
01893
01894 for (kx=-rmax+1; kx<rmax; kx++) {
01895 for (ky=-rmax+1; ky<rmax; ky++) {
01896 for (lx=-rmax+1; lx<rmax; lx++) {
01897 for (ly=-rmax+1; ly<rmax; ly++) {
01898 int ax=kx+lx;
01899 int ay=ky+ly;
01900 if (abs(ax)>=rmax || abs(ay)>=rmax) continue;
01901 float rr1=rmap[abs(kx)+rmax*abs(ky)];
01902 float rr2=rmap[abs(lx)+rmax*abs(ly)];
01903 int r1=(int)floor(.5+rr1);
01904 int r2=(int)floor(.5+rr2);
01905
01906
01907 if (r1+r2>=rmax || rr1==0 ||rr2==0) continue;
01908
01909 std::complex<float> p=fft->get_complex_at(kx,ky)*fft->get_complex_at(lx,ly)*conj(fft->get_complex_at(ax,ay));
01910 int dot=(int)floor((kx*lx+ky*ly)/(rr1*rr2)*7.5);
01911 if (dot<0) dot=16+dot;
01912
01913 fp->set_value_at(r1*2,r2,dot,p.real()+fp->get_value_at(r1*2,r2,dot));
01914
01915
01916 fp->set_value_at(r1*2+1,r2,dot,fp->get_value_at(r1*2+1,r2,dot)+1);
01917 }
01918 }
01919 }
01920 }
01921
01922
01923 for (i=0; i<rmax*2; i+=2) {
01924 for (j=0; j<rmax; j++) {
01925 for (h=0; h<16; h++) {
01926 float norm=fp->get_value_at(i+1,j,h);
01927
01928
01929 fp->set_value_at(i,rmax*2-j-1,h,(fp->get_value_at(i,j,h)/(norm==0.0f?1.0f:norm)));
01930 fp->set_value_at(i,j,h,(fp->get_value_at(i,j,h)/(norm==0.0f?1.0f:norm)));
01931
01932
01933 fp->set_value_at(i+1,j,h,0.0);
01934 }
01935 }
01936 }
01937
01938 free(rmap);
01939 if (type==4) {
01940 EMData *f2=fp->do_ift();
01941 if (f2->get_value_at(0,0,0)<0) f2->mult(-1.0f);
01942 f2->process_inplace("xform.phaseorigin.tocorner");
01943 delete fp;
01944 return f2;
01945 }
01946 return fp;
01947 }
01948 throw UnexpectedBehaviorException("There is not implementation for the parameters you specified");
01949 }
01950
01951
01952 EMData *EMData::calc_mutual_correlation(EMData * with, bool tocenter, EMData * filter)
01953 {
01954 ENTERFUNC;
01955
01956 if (with && !EMUtil::is_same_size(this, with)) {
01957 LOGERR("images not same size");
01958 throw ImageFormatException( "images not same size");
01959 }
01960
01961 EMData *this_fft = 0;
01962 this_fft = do_fft();
01963
01964 if (!this_fft) {
01965
01966 LOGERR("FFT returns NULL image");
01967 throw NullPointerException("FFT returns NULL image");
01968 }
01969
01970 this_fft->ap2ri();
01971 EMData *cf = 0;
01972
01973 if (with && with != this) {
01974 cf = with->do_fft();
01975 if (!cf) {
01976 LOGERR("FFT returns NULL image");
01977 throw NullPointerException("FFT returns NULL image");
01978 }
01979 cf->ap2ri();
01980 }
01981 else {
01982 cf = this_fft->copy();
01983 }
01984
01985 if (filter) {
01986 if (!EMUtil::is_same_size(filter, cf)) {
01987 LOGERR("improperly sized filter");
01988 throw ImageFormatException("improperly sized filter");
01989 }
01990
01991 cf->mult_complex_efficient(*filter,true);
01992 this_fft->mult(*filter,true);
01993
01994
01995 }
01996
01997 float *rdata1 = this_fft->get_data();
01998 float *rdata2 = cf->get_data();
01999 size_t this_fft_size = this_fft->get_xsize() * this_fft->get_ysize() * this_fft->get_zsize();
02000
02001 if (with == this) {
02002 for (size_t i = 0; i < this_fft_size; i += 2) {
02003 rdata2[i] = std::sqrt(rdata1[i] * rdata2[i] + rdata1[i + 1] * rdata2[i + 1]);
02004 rdata2[i + 1] = 0;
02005 }
02006
02007 this_fft->update();
02008 cf->update();
02009 }
02010 else {
02011 for (size_t i = 0; i < this_fft_size; i += 2) {
02012 rdata2[i] = (rdata1[i] * rdata2[i] + rdata1[i + 1] * rdata2[i + 1]);
02013 rdata2[i + 1] = (rdata1[i + 1] * rdata2[i] - rdata1[i] * rdata2[i + 1]);
02014 }
02015
02016 this_fft->update();
02017 cf->update();
02018 rdata1 = cf->get_data();
02019
02020 for (size_t i = 0; i < this_fft_size; i += 2) {
02021 float t = Util::square(rdata1[i]) + Util::square(rdata1[i + 1]);
02022 if (t != 0) {
02023 t = pow(t, (float) 0.25);
02024 rdata1[i] /= t;
02025 rdata1[i + 1] /= t;
02026 }
02027 }
02028 cf->update();
02029 }
02030
02031 EMData *f2 = cf->do_ift();
02032
02033 if (tocenter) {
02034 f2->process_inplace("xform.phaseorigin.tocenter");
02035 }
02036
02037 if( cf )
02038 {
02039 delete cf;
02040 cf = 0;
02041 }
02042
02043 if( this_fft )
02044 {
02045 delete this_fft;
02046 this_fft = 0;
02047 }
02048
02049 f2->set_attr("label", "MCF");
02050 f2->set_path("/tmp/eman.mcf");
02051
02052 EXITFUNC;
02053 return f2;
02054 }
02055
02056
02057 vector < float > EMData::calc_hist(int hist_size, float histmin, float histmax,const float& brt, const float& cont)
02058 {
02059 ENTERFUNC;
02060
02061 static size_t prime[] = { 1, 3, 7, 11, 17, 23, 37, 59, 127, 253, 511 };
02062
02063 if (histmin == histmax) {
02064 histmin = get_attr("minimum");
02065 histmax = get_attr("maximum");
02066 }
02067
02068 vector <float> hist(hist_size, 0.0);
02069
02070 int p0 = 0;
02071 int p1 = 0;
02072 size_t size = nx * ny * nz;
02073 if (size < 300000) {
02074 p0 = 0;
02075 p1 = 0;
02076 }
02077 else if (size < 2000000) {
02078 p0 = 2;
02079 p1 = 3;
02080 }
02081 else if (size < 8000000) {
02082 p0 = 4;
02083 p1 = 6;
02084 }
02085 else {
02086 p0 = 7;
02087 p1 = 9;
02088 }
02089
02090 if (is_complex() && p0 > 0) {
02091 p0++;
02092 p1++;
02093 }
02094
02095 size_t di = 0;
02096
02097 size_t n = hist.size();
02098
02099 float * data = get_data();
02100 for (int k = p0; k <= p1; ++k) {
02101 if (is_complex()) {
02102 di = prime[k] * 2;
02103 }
02104 else {
02105 di = prime[k];
02106 }
02107
02108
02109 float w = (float)n / (histmax - histmin);
02110
02111 for(size_t i=0; i<=size-di; i += di) {
02112 float val;
02113 if (cont != 1.0f || brt != 0)val = cont*(data[i]+brt);
02114 else val = data[i];
02115 int j = Util::round((val - histmin) * w);
02116 if (j >= 0 && j < (int) n) {
02117 hist[j] += 1;
02118 }
02119 }
02120 }
02121
02122
02123
02124
02125
02126
02127
02128 return hist;
02129
02130 EXITFUNC;
02131 }
02132
02133
02134
02135
02136
02137 vector<float> EMData::calc_az_dist(int n, float a0, float da, float rmin, float rmax)
02138 {
02139 ENTERFUNC;
02140
02141 if (get_ndim() > 2) {
02142 throw ImageDimensionException("no 3D image");
02143 }
02144
02145 float *yc = new float[n];
02146
02147 vector<float> vd(n);
02148 for (int i = 0; i < n; i++) {
02149 yc[i] = 0.00001f;
02150 }
02151
02152 float * data = get_data();
02153 if (is_complex()) {
02154 int c = 0;
02155 for (int y = 0; y < ny; y++) {
02156 for (int x = 0; x < nx; x += 2, c += 2) {
02157 float x1 = x / 2.0f;
02158 float y1 = y - ny / 2.0f;
02159 #ifdef _WIN32
02160 float r = (float)_hypot(x1, y1);
02161 #else
02162 float r = (float)hypot(x1, y1);
02163 #endif //_WIN32
02164
02165 if (r >= rmin && r <= rmax) {
02166 float a = 0;
02167
02168 if (y != ny / 2 || x != 0) {
02169 a = (atan2(y1, x1) - a0) / da;
02170 }
02171
02172 int i = static_cast < int >(floor(a));
02173 a -= i;
02174
02175 if (i == 0) {
02176 vd[0] += data[c] * (1.0f - a);
02177 yc[0] += (1.0f - a);
02178 }
02179 else if (i == n - 1) {
02180 vd[n - 1] += data[c] * a;
02181 yc[n - 1] += a;
02182 }
02183 else if (i > 0 && i < (n - 1)) {
02184 float h = 0;
02185 if (is_ri()) {
02186 #ifdef _WIN32
02187 h = (float)_hypot(data[c], data[c + 1]);
02188 #else
02189 h = (float)hypot(data[c], data[c + 1]);
02190 #endif //_WIN32
02191 }
02192 else {
02193 h = data[c];
02194 }
02195
02196 vd[i] += h * (1.0f - a);
02197 yc[i] += (1.0f - a);
02198 vd[i + 1] += h * a;
02199 yc[i + 1] += a;
02200 }
02201 }
02202 }
02203 }
02204 }
02205 else {
02206 int c = 0;
02207 float half_nx = (nx - 1) / 2.0f;
02208 float half_ny = (ny - 1) / 2.0f;
02209
02210 for (int y = 0; y < ny; y++) {
02211 for (int x = 0; x < nx; x++, c++) {
02212 float y1 = y - half_ny;
02213 float x1 = x - half_nx;
02214 #ifdef _WIN32
02215 float r = (float)_hypot(x1, y1);
02216 #else
02217 float r = (float)hypot(x1, y1);
02218 #endif
02219
02220 if (r >= rmin && r <= rmax) {
02221 float a = 0;
02222 if (x1 != 0 || y1 != 0) {
02223 a = atan2(y1, x1);
02224 if (a < 0) {
02225 a += M_PI * 2;
02226 }
02227 }
02228
02229 a = (a - a0) / da;
02230 int i = static_cast < int >(floor(a));
02231 a -= i;
02232
02233 if (i == 0) {
02234 vd[0] += data[c] * (1.0f - a);
02235 yc[0] += (1.0f - a);
02236 }
02237 else if (i == n - 1) {
02238 vd[n - 1] += data[c] * a;
02239 yc[n - 1] += (a);
02240 }
02241 else if (i > 0 && i < (n - 1)) {
02242 vd[i] += data[c] * (1.0f - a);
02243 yc[i] += (1.0f - a);
02244 vd[i + 1] += data[c] * a;
02245 yc[i + 1] += a;
02246 }
02247 }
02248 }
02249 }
02250 }
02251
02252
02253 for (int i = 0; i < n; i++) {
02254 vd[i] /= yc[i];
02255 }
02256
02257 if( yc )
02258 {
02259 delete[]yc;
02260 yc = 0;
02261 }
02262
02263 return vd;
02264
02265 EXITFUNC;
02266 }
02267
02268
02269 EMData *EMData::unwrap(int r1, int r2, int xs, int dx, int dy, bool do360, bool weight_radial) const
02270 {
02271 ENTERFUNC;
02272
02273 if (get_ndim() != 2) {
02274 throw ImageDimensionException("2D image only");
02275 }
02276
02277 int p = 1;
02278 if (do360) {
02279 p = 2;
02280 }
02281
02282 if (xs < 1) {
02283 xs = (int) Util::fast_floor(p * M_PI * ny / 4);
02284 xs -= xs % 8;
02285 if (xs<=8) xs=16;
02286 }
02287
02288 if (r1 < 0) {
02289 r1 = 4;
02290 }
02291
02292 #ifdef _WIN32
02293 int rr = ny / 2 - 2 - (int) Util::fast_floor(static_cast<float>(_hypot(dx, dy)));
02294 #else
02295 int rr = ny / 2 - 2 - (int) Util::fast_floor(static_cast<float>(hypot(dx, dy)));
02296 #endif //_WIN32
02297 rr-=rr%2;
02298 if (r2 <= r1 || r2 > rr) {
02299 r2 = rr;
02300 }
02301
02302 if ( (r2-r1) < 0 ) throw UnexpectedBehaviorException("The combination of function the arguments and the image dimensions causes unexpected behavior internally. Use a larger image, or a smaller value of r1, or a combination of both");
02303
02304 #ifdef EMAN2_USING_CUDA
02305 if ( gpu_operation_preferred() ) {
02306
02307 bind_cuda_texture();
02308 EMData* rslt = new EMData();
02309 rslt->set_size_cuda(xs,r2-r1,1);
02310 EMDataForCuda r = rslt->get_data_struct_for_cuda();
02311
02312 emdata_unwrap(&r,r1,r2,xs,p,dx,dy,weight_radial,nx,ny);
02313 unbind_cuda_texture();
02314
02315
02316
02317 return rslt;
02318 }
02319 #endif
02320
02321 EMData *ret = new EMData();
02322 ret->set_size(xs, r2 - r1, 1);
02323 const float *const d = get_const_data();
02324 float *dd = ret->get_data();
02325 float pfac = (float)p/(float)xs;
02326
02327 int nxon2 = nx/2;
02328 int nyon2 = ny/2;
02329 for (int x = 0; x < xs; x++) {
02330 float ang = x * M_PI * pfac;
02331 float si = sin(ang);
02332 float co = cos(ang);
02333
02334 for (int y = 0; y < r2 - r1; y++) {
02335 float ypr1 = (float)y + r1;
02336 float xx = ypr1 * co + nxon2 + dx;
02337 float yy = ypr1 * si + nyon2 + dy;
02338
02339
02340 float t = xx - (int)xx;
02341 float u = yy - (int)yy;
02342
02343 int k = (int) xx + ((int) yy) * nx;
02344 float val = Util::bilinear_interpolate(d[k], d[k + 1], d[k + nx], d[k + nx+1], t,u);
02345 if (weight_radial) val *= ypr1;
02346 dd[x + y * xs] = val;
02347 }
02348
02349 }
02350 ret->update();
02351
02352 EXITFUNC;
02353 return ret;
02354 }
02355
02356
02357
02358 void EMData::apply_radial_func(float x0, float step, vector < float >array, bool interp)
02359 {
02360 ENTERFUNC;
02361
02362 if (!is_complex()) throw ImageFormatException("apply_radial_func requires a complex image");
02363
02364 int n = static_cast < int >(array.size());
02365
02366 if (n*step>2.0) printf("Warning, apply_radial_func takes x0 and step with respect to Nyquist (0.5)\n");
02367
02368
02369
02370 ap2ri();
02371
02372 size_t ndims = get_ndim();
02373 float * data = get_data();
02374 if (ndims == 2) {
02375 int k = 0;
02376 for (int j = 0; j < ny; j++) {
02377 for (int i = 0; i < nx; i += 2, k += 2) {
02378 float r;
02379 #ifdef _WIN32
02380 if (j<ny/2) r = (float)_hypot(i/(float)(nx*2), j/(float)ny);
02381 else r = (float)_hypot(i/(float)(nx*2), (ny-j)/(float)ny);
02382 #else
02383 if (j<ny/2) r = (float)hypot(i/(float)(nx*2), j/(float)ny);
02384 else r = (float)hypot(i/(float)(nx*2), (ny-j)/(float)ny);
02385 #endif //_WIN32
02386 r = (r - x0) / step;
02387
02388 int l = 0;
02389 if (interp) {
02390 l = (int) floor(r);
02391 }
02392 else {
02393 l = (int) floor(r + 1);
02394 }
02395
02396
02397 float f = 0;
02398 if (l >= n - 2) {
02399 f = array[n - 1];
02400 }
02401 else {
02402 if (interp) {
02403 r -= l;
02404 f = (array[l] * (1.0f - r) + array[l + 1] * r);
02405 }
02406 else {
02407 f = array[l];
02408 }
02409 }
02410
02411 data[k] *= f;
02412 data[k + 1] *= f;
02413 }
02414 }
02415 }
02416 else if (ndims == 3) {
02417 int k = 0;
02418 for (int m = 0; m < nz; m++) {
02419 float mnz;
02420 if (m<nz/2) mnz=m*m/(float)(nz*nz);
02421 else { mnz=(nz-m)/(float)nz; mnz*=mnz; }
02422
02423 for (int j = 0; j < ny; j++) {
02424 float jny;
02425 if (j<ny/2) jny= j*j/(float)(ny*ny);
02426 else { jny=(ny-j)/(float)ny; jny*=jny; }
02427
02428 for (int i = 0; i < nx; i += 2, k += 2) {
02429 float r = std::sqrt((i * i / (nx*nx*4.0f)) + jny + mnz);
02430 r = (r - x0) / step;
02431
02432 int l = 0;
02433 if (interp) {
02434 l = (int) floor(r);
02435 }
02436 else {
02437 l = (int) floor(r + 1);
02438 }
02439
02440
02441 float f = 0;
02442 if (l >= n - 2) {
02443 f = array[n - 1];
02444 }
02445 else {
02446 if (interp) {
02447 r -= l;
02448 f = (array[l] * (1.0f - r) + array[l + 1] * r);
02449 }
02450 else {
02451 f = array[l];
02452 }
02453 }
02454
02455 data[k] *= f;
02456 data[k + 1] *= f;
02457 }
02458 }
02459 }
02460
02461 }
02462
02463 update();
02464 EXITFUNC;
02465 }
02466
02467 vector<float> EMData::calc_radial_dist(int n, float x0, float dx, bool inten)
02468 {
02469 ENTERFUNC;
02470
02471 vector<float>ret(n);
02472 vector<float>norm(n);
02473
02474 int x,y,z,i;
02475 int step=is_complex()?2:1;
02476 int isinten=get_attr_default("is_intensity",0);
02477
02478 if (isinten&&!inten) { throw InvalidParameterException("Must set inten for calc_radial_dist with intensity image"); }
02479
02480 for (i=0; i<n; i++) ret[i]=norm[i]=0.0;
02481 float * data = get_data();
02482
02483
02484 if (nz==1) {
02485 for (y=i=0; y<ny; y++) {
02486 for (x=0; x<nx; x+=step,i+=step) {
02487 float r,v;
02488 if (step==2) {
02489 if (x==0 && y>ny/2) continue;
02490 r=(float)(Util::hypot_fast(x/2,y<ny/2?y:ny-y));
02491 if (!inten) {
02492 #ifdef _WIN32
02493 if (is_ri()) v=static_cast<float>(_hypot(data[i],data[i+1]));
02494 #else
02495 if (is_ri()) v=static_cast<float>(hypot(data[i],data[i+1]));
02496 #endif
02497 else v=data[i];
02498 } else {
02499 if (isinten) v=data[i];
02500 else if (is_ri()) v=data[i]*data[i]+data[i+1]*data[i+1];
02501 else v=data[i]*data[i];
02502 }
02503 }
02504 else {
02505 r=(float)(Util::hypot_fast(x-nx/2,y-ny/2));
02506 if (inten) v=data[i]*data[i];
02507 else v=data[i];
02508 }
02509 r=(r-x0)/dx;
02510 int f=int(r);
02511 r-=float(f);
02512
02513 if (f>=0 && f<n) {
02514 ret[f]+=v*(1.0f-r);
02515 norm[f]+=(1.0f-r);
02516 if (f<n-1) {
02517 ret[f+1]+=v*r;
02518 norm[f+1]+=r;
02519 }
02520 }
02521 }
02522 }
02523 }
02524 else {
02525 size_t i;
02526 for (z=i=0; z<nz; ++z) {
02527 for (y=0; y<ny; ++y) {
02528 for (x=0; x<nx; x+=step,i+=step) {
02529 float r,v;
02530 if (step==2) {
02531 if (x==0 && z<nz/2) continue;
02532 if (x==0 && z==nz/2 && y<ny/2) continue;
02533 r=Util::hypot3(x/2,y<ny/2?y:ny-y,z<nz/2?z:nz-z);
02534 if (!inten) {
02535 #ifdef _WIN32
02536 if (is_ri()) v=static_cast<float>(_hypot(data[i],data[i+1]));
02537 #else
02538 if (is_ri()) v=static_cast<float>(hypot(data[i],data[i+1]));
02539 #endif //_WIN32
02540 else v=data[i];
02541 } else {
02542 if (isinten) v=data[i];
02543 else if (is_ri()) v=data[i]*data[i]+data[i+1]*data[i+1];
02544 else v=data[i]*data[i];
02545 }
02546 }
02547 else {
02548 r=Util::hypot3(x-nx/2,y-ny/2,z-nz/2);
02549 if (inten) v=data[i]*data[i];
02550 else v=data[i];
02551 }
02552 r=(r-x0)/dx;
02553 int f=int(r);
02554 r-=float(f);
02555 if (f>=0 && f<n) {
02556 ret[f]+=v*(1.0f-r);
02557 norm[f]+=(1.0f-r);
02558 if (f<n-1) {
02559 ret[f+1]+=v*r;
02560 norm[f+1]+=r;
02561 }
02562 }
02563 }
02564 }
02565 }
02566 }
02567
02568 for (i=0; i<n; i++) ret[i]/=norm[i]?norm[i]:1.0f;
02569
02570 EXITFUNC;
02571
02572 return ret;
02573 }
02574
02575 vector<float> EMData::calc_radial_dist(int n, float x0, float dx, int nwedge, bool inten)
02576 {
02577 ENTERFUNC;
02578
02579 if (nz > 1) {
02580 LOGERR("2D images only.");
02581 throw ImageDimensionException("2D images only");
02582 }
02583
02584 vector<float>ret(n*nwedge);
02585 vector<float>norm(n*nwedge);
02586
02587 int x,y,i;
02588 int step=is_complex()?2:1;
02589 float astep=static_cast<float>(M_PI*2.0/nwedge);
02590 float* data = get_data();
02591 for (i=0; i<n*nwedge; i++) ret[i]=norm[i]=0.0;
02592
02593
02594 for (y=i=0; y<ny; y++) {
02595 for (x=0; x<nx; x+=step,i+=step) {
02596 float r,v,a;
02597 if (is_complex()) {
02598 #ifdef _WIN32
02599 r=static_cast<float>(_hypot(x/2.0,y<ny/2?y:ny-y));
02600 #else
02601 r=static_cast<float>(hypot(x/2.0,y<ny/2?y:ny-y));
02602 #endif
02603 a=atan2(float(y<ny/2?y:ny-y),x/2.0f);
02604 if (!inten) {
02605 #ifdef _WIN32
02606 if (is_ri()) v=static_cast<float>(_hypot(data[i],data[i+1]));
02607 #else
02608 if (is_ri()) v=static_cast<float>(hypot(data[i],data[i+1]));
02609 #endif //_WIN32
02610 else v=data[i];
02611 } else {
02612 if (is_ri()) v=data[i]*data[i]+data[i+1]*data[i+1];
02613 else v=data[i]*data[i];
02614 }
02615 }
02616 else {
02617 #ifdef _WIN32
02618 r=static_cast<float>(_hypot(x-nx/2,y-ny/2));
02619 #else
02620 r=static_cast<float>(hypot(x-nx/2,y-ny/2));
02621 #endif //_WIN32
02622 a=atan2(float(y-ny/2),float(x-nx/2));
02623 if (inten) v=data[i]*data[i];
02624 else v=data[i];
02625 }
02626 int bin=n*int((a+M_PI)/astep);
02627 if (bin>=nwedge) bin=nwedge-1;
02628 r=(r-x0)/dx;
02629 int f=int(r);
02630 r-=float(f);
02631 if (f>=0 && f<n) {
02632 ret[f+bin]+=v*(1.0f-r);
02633 norm[f+bin]+=(1.0f-r);
02634 if (f<n-1) {
02635 ret[f+1+bin]+=v*r;
02636 norm[f+1+bin]+=r;
02637 }
02638 }
02639 }
02640 }
02641
02642 for (i=0; i<n*nwedge; i++) ret[i]/=norm[i]?norm[i]:1.0f;
02643 EXITFUNC;
02644
02645 return ret;
02646 }
02647
02648 void EMData::cconj() {
02649 ENTERFUNC;
02650 if (!is_complex() || !is_ri())
02651 throw ImageFormatException("EMData::conj requires a complex, ri image");
02652 int nxreal = nx -2 + int(is_fftodd());
02653 int nxhalf = nxreal/2;
02654 for (int iz = 0; iz < nz; iz++)
02655 for (int iy = 0; iy < ny; iy++)
02656 for (int ix = 0; ix <= nxhalf; ix++)
02657 cmplx(ix,iy,iz) = conj(cmplx(ix,iy,iz));
02658 EXITFUNC;
02659 }
02660
02661
02662 void EMData::update_stat() const
02663 {
02664 ENTERFUNC;
02665
02666 if (!(flags & EMDATA_NEEDUPD))
02667 {
02668 EXITFUNC;
02669 return;
02670 }
02671
02672 float* data = get_data();
02673 float max = -FLT_MAX;
02674 float min = -max;
02675
02676 double sum = 0;
02677 double square_sum = 0;
02678
02679 int step = 1;
02680 if (is_complex() && !is_ri()) {
02681 step = 2;
02682 }
02683
02684 int n_nonzero = 0;
02685
02686
02687
02688
02689 size_t size = nx*ny*nz;
02690 for (size_t i = 0; i < size; i += step) {
02691 float v = data[i];
02692 #ifdef _WIN32
02693 max = _cpp_max(max,v);
02694 min = _cpp_min(min,v);
02695 #else
02696 max=std::max<float>(max,v);
02697 min=std::min<float>(min,v);
02698 #endif //_WIN32
02699 sum += v;
02700 square_sum += v * (double)(v);
02701 if (v != 0) n_nonzero++;
02702 }
02703
02704 size_t n = size / step;
02705 double mean = sum / n;
02706
02707 #ifdef _WIN32
02708 float sigma = (float)std::sqrt( _cpp_max(0.0,(square_sum - sum*sum / n)/(n-1)));
02709 n_nonzero = _cpp_max(1,n_nonzero);
02710 double sigma_nonzero = std::sqrt( _cpp_max(0,(square_sum - sum*sum/n_nonzero)/(n_nonzero-1)));
02711 #else
02712 float sigma = (float)std::sqrt(std::max<double>(0.0,(square_sum - sum*sum / n)/(n-1)));
02713 n_nonzero = std::max<int>(1,n_nonzero);
02714 double sigma_nonzero = std::sqrt(std::max<double>(0,(square_sum - sum*sum/n_nonzero)/(n_nonzero-1)));
02715 #endif //_WIN32
02716 double mean_nonzero = sum / n_nonzero;
02717
02718 attr_dict["minimum"] = min;
02719 attr_dict["maximum"] = max;
02720 attr_dict["mean"] = (float)(mean);
02721 attr_dict["sigma"] = (float)(sigma);
02722 attr_dict["square_sum"] = (float)(square_sum);
02723 attr_dict["mean_nonzero"] = (float)(mean_nonzero);
02724 attr_dict["sigma_nonzero"] = (float)(sigma_nonzero);
02725 attr_dict["is_complex"] = (int) is_complex();
02726 attr_dict["is_complex_ri"] = (int) is_ri();
02727
02728 flags &= ~EMDATA_NEEDUPD;
02729
02730 if (rot_fp != 0)
02731 {
02732 delete rot_fp; rot_fp = 0;
02733 }
02734
02735 EXITFUNC;
02736
02737 }
02738
02739 bool EMData::operator==(const EMData& that) const {
02740 if (that.get_xsize() != nx || that.get_ysize() != ny || that.get_zsize() != nz ) return false;
02741
02742 const float* d1 = that.get_const_data();
02743 float* d2 = get_data();
02744
02745 for(size_t i =0; i < get_size(); ++i,++d1,++d2) {
02746 if ((*d1) != (*d2)) return false;
02747 }
02748 return true;
02749
02750 }
02751
02752 EMData * EMAN::operator+(const EMData & em, float n)
02753 {
02754 EMData * r = em.copy();
02755 r->add(n);
02756 return r;
02757 }
02758
02759 EMData * EMAN::operator-(const EMData & em, float n)
02760 {
02761 EMData* r = em.copy();
02762 r->sub(n);
02763 return r;
02764 }
02765
02766 EMData * EMAN::operator*(const EMData & em, float n)
02767 {
02768 EMData* r = em.copy();
02769 r ->mult(n);
02770 return r;
02771 }
02772
02773 EMData * EMAN::operator/(const EMData & em, float n)
02774 {
02775 EMData * r = em.copy();
02776 r->div(n);
02777 return r;
02778 }
02779
02780
02781 EMData * EMAN::operator+(float n, const EMData & em)
02782 {
02783 EMData * r = em.copy();
02784 r->add(n);
02785 return r;
02786 }
02787
02788 EMData * EMAN::operator-(float n, const EMData & em)
02789 {
02790 EMData * r = em.copy();
02791 r->mult(-1.0f);
02792 r->add(n);
02793 return r;
02794 }
02795
02796 EMData * EMAN::operator*(float n, const EMData & em)
02797 {
02798 EMData * r = em.copy();
02799 r->mult(n);
02800 return r;
02801 }
02802
02803 EMData * EMAN::operator/(float n, const EMData & em)
02804 {
02805 EMData * r = em.copy();
02806 r->to_one();
02807 r->mult(n);
02808 r->div(em);
02809
02810 return r;
02811 }
02812
02813 EMData * EMAN::rsub(const EMData & em, float n)
02814 {
02815 return EMAN::operator-(n, em);
02816 }
02817
02818 EMData * EMAN::rdiv(const EMData & em, float n)
02819 {
02820 return EMAN::operator/(n, em);
02821 }
02822
02823 EMData * EMAN::operator+(const EMData & a, const EMData & b)
02824 {
02825 EMData * r = a.copy();
02826 r->add(b);
02827 return r;
02828 }
02829
02830 EMData * EMAN::operator-(const EMData & a, const EMData & b)
02831 {
02832 EMData * r = a.copy();
02833 r->sub(b);
02834 return r;
02835 }
02836
02837 EMData * EMAN::operator*(const EMData & a, const EMData & b)
02838 {
02839 EMData * r = a.copy();
02840 r->mult(b);
02841 return r;
02842 }
02843
02844 EMData * EMAN::operator/(const EMData & a, const EMData & b)
02845 {
02846 EMData * r = a.copy();
02847 r->div(b);
02848 return r;
02849 }
02850
02851 void EMData::set_xyz_origin(float origin_x, float origin_y, float origin_z)
02852 {
02853 attr_dict["origin_x"] = origin_x;
02854 attr_dict["origin_y"] = origin_y;
02855 attr_dict["origin_z"] = origin_z;
02856 }
02857
02858 #if 0
02859 void EMData::calc_rcf(EMData * with, vector < float >&sum_array)
02860 {
02861 ENTERFUNC;
02862
02863 int array_size = sum_array.size();
02864 float da = 2 * M_PI / array_size;
02865 float *dat = new float[array_size + 2];
02866 float *dat2 = new float[array_size + 2];
02867 int nx2 = nx * 9 / 20;
02868
02869 float lim = 0;
02870 if (fabs(translation[0]) < fabs(translation[1])) {
02871 lim = fabs(translation[1]);
02872 }
02873 else {
02874 lim = fabs(translation[0]);
02875 }
02876
02877 nx2 -= static_cast < int >(floor(lim));
02878
02879 for (int i = 0; i < array_size; i++) {
02880 sum_array[i] = 0;
02881 }
02882
02883 float sigma = attr_dict["sigma"];
02884 float with_sigma = with->get_attr_dict().get("sigma");
02885
02886 vector<float> vdata, vdata2;
02887 for (int i = 8; i < nx2; i += 6) {
02888 vdata = calc_az_dist(array_size, 0, da, i, i + 6);
02889 vdata2 = with->calc_az_dist(array_size, 0, da, i, i + 6);
02890 Assert(vdata.size() <= array_size + 2);
02891 Assert(cdata2.size() <= array_size + 2);
02892 std::copy(vdata.begin(), vdata.end(), dat);
02893 std::copy(vdata2.begin(), vdata2.end(), dat2);
02894
02895 EMfft::real_to_complex_1d(dat, dat, array_size);
02896 EMfft::real_to_complex_1d(dat2, dat2, array_size);
02897
02898 for (int j = 0; j < array_size + 2; j += 2) {
02899 float max = dat[j] * dat2[j] + dat[j + 1] * dat2[j + 1];
02900 float max2 = dat[j + 1] * dat2[j] - dat2[j + 1] * dat[j];
02901 dat[j] = max;
02902 dat[j + 1] = max2;
02903 }
02904
02905 EMfft::complex_to_real_1d(dat, dat, array_size);
02906 float norm = array_size * array_size * (4.0f * sigma) * (4.0f * with_sigma);
02907
02908 for (int j = 0; j < array_size; j++) {
02909 sum_array[j] += dat[j] * (float) i / norm;
02910 }
02911 }
02912
02913 if( dat )
02914 {
02915 delete[]dat;
02916 dat = 0;
02917 }
02918
02919 if( dat2 )
02920 {
02921 delete[]dat2;
02922 dat2 = 0;
02923 }
02924 EXITFUNC;
02925 }
02926
02927 #endif
02928
02929 void EMData::add_incoherent(EMData * obj)
02930 {
02931 ENTERFUNC;
02932
02933 if (!obj) {
02934 LOGERR("NULL image");
02935 throw NullPointerException("NULL image");
02936 }
02937
02938 if (!obj->is_complex() || !is_complex()) {
02939 throw ImageFormatException("complex images only");
02940 }
02941
02942 if (!EMUtil::is_same_size(this, obj)) {
02943 throw ImageFormatException("images not same size");
02944 }
02945
02946 ri2ap();
02947 obj->ri2ap();
02948
02949 float *dest = get_data();
02950 float *src = obj->get_data();
02951 size_t size = nx * ny * nz;
02952 for (size_t j = 0; j < size; j += 2) {
02953 #ifdef _WIN32
02954 dest[j] = (float) _hypot(src[j], dest[j]);
02955 #else
02956 dest[j] = (float) hypot(src[j], dest[j]);
02957 #endif //_WIN32
02958 dest[j + 1] = 0;
02959 }
02960
02961 obj->update();
02962 update();
02963 EXITFUNC;
02964 }
02965
02966
02967 float EMData::calc_dist(EMData * second_img, int y_index) const
02968 {
02969 ENTERFUNC;
02970
02971 if (get_ndim() != 1) {
02972 throw ImageDimensionException("'this' image is 1D only");
02973 }
02974
02975 if (second_img->get_xsize() != nx || ny != 1) {
02976 throw ImageFormatException("image xsize not same");
02977 }
02978
02979 if (y_index > second_img->get_ysize() || y_index < 0) {
02980 return -1;
02981 }
02982
02983 float ret = 0;
02984 float *d1 = get_data();
02985 float *d2 = second_img->get_data() + second_img->get_xsize() * y_index;
02986
02987 for (int i = 0; i < nx; i++) {
02988 ret += Util::square(d1[i] - d2[i]);
02989 }
02990 EXITFUNC;
02991 return std::sqrt(ret);
02992 }
02993
02994
02995 EMData * EMData::calc_fast_sigma_image( EMData* mask)
02996 {
02997 ENTERFUNC;
02998
02999 bool maskflag = false;
03000 if (mask == 0) {
03001 mask = new EMData(nx,ny,nz);
03002 mask->process_inplace("testimage.circlesphere");
03003 maskflag = true;
03004 }
03005
03006 if (get_ndim() != mask->get_ndim() ) throw ImageDimensionException("The dimensions do not match");
03007
03008 int mnx = mask->get_xsize(); int mny = mask->get_ysize(); int mnz = mask->get_zsize();
03009
03010 if ( mnx > nx || mny > ny || mnz > nz)
03011 throw ImageDimensionException("Can not calculate variance map using an image that is larger than this image");
03012
03013 size_t P = 0;
03014 for(size_t i = 0; i < mask->get_size(); ++i){
03015 if (mask->get_value_at(i) != 0){
03016 ++P;
03017 }
03018 }
03019 float normfac = 1.0f/(float)P;
03020
03021
03022
03023 int nxc = nx+mnx; int nyc = ny+mny; int nzc = nz+mnz;
03024
03025 Region r;
03026 if (ny == 1) r = Region((mnx-nxc)/2,nxc);
03027 else if (nz == 1) r = Region((mnx-nxc)/2, (mny-nyc)/2,nxc,nyc);
03028 else r = Region((mnx-nxc)/2, (mny-nyc)/2,(mnz-nzc)/2,nxc,nyc,nzc);
03029 mask->clip_inplace(r,0);
03030
03031
03032
03033
03034
03035
03036
03037 Region r2;
03038 if (ny == 1) r2 = Region((nx-nxc)/2,nxc);
03039 else if (nz == 1) r2 = Region((nx-nxc)/2, (ny-nyc)/2,nxc,nyc);
03040 else r2 = Region((nx-nxc)/2, (ny-nyc)/2,(nz-nzc)/2,nxc,nyc,nzc);
03041 EMData* squared = get_clip(r2,get_edge_mean());
03042 EMData* tmp = squared->copy();
03043 Dict pow;
03044 pow["pow"] = 2.0f;
03045 squared->process_inplace("math.pow",pow);
03046 EMData* s = squared->convolute(mask);
03047 squared->mult(normfac);
03048
03049 EMData* m = tmp->convolute(mask);
03050 m->mult(normfac);
03051 m->process_inplace("math.pow",pow);
03052 delete tmp; tmp = 0;
03053 s->sub(*m);
03054
03055 s->process_inplace("math.sqrt");
03056
03057
03058
03059
03060
03061
03062 if (maskflag) {
03063 delete mask;
03064 mask = 0;
03065 } else {
03066 Region r;
03067 if (ny == 1) r = Region((nxc-mnx)/2,mnx);
03068 else if (nz == 1) r = Region((nxc-mnx)/2, (nyc-mny)/2,mnx,mny);
03069 else r = Region((nxc-mnx)/2, (nyc-mny)/2,(nzc-mnz)/2,mnx,mny,mnz);
03070 mask->clip_inplace(r);
03071 }
03072
03073 delete squared;
03074 delete m;
03075
03076 s->process_inplace("xform.phaseorigin.tocenter");
03077 Region r3;
03078 if (ny == 1) r3 = Region((nxc-nx)/2,nx);
03079 else if (nz == 1) r3 = Region((nxc-nx)/2, (nyc-ny)/2,nx,ny);
03080 else r3 = Region((nxc-nx)/2, (nyc-ny)/2,(nzc-nz)/2,nx,ny,nz);
03081 s->clip_inplace(r3);
03082 EXITFUNC;
03083 return s;
03084
03085 }
03086
03087
03088
03089 EMData *EMData::calc_flcf(EMData * with)
03090 {
03091 ENTERFUNC;
03092
03093
03094 EMData* ones = new EMData(with->get_xsize(), with->get_ysize(),with->get_zsize());
03095 ones->process_inplace("testimage.circlesphere");
03096
03097
03098 EMData* with_resized = with->copy();
03099
03100 with_resized->mult(*ones);
03101
03102
03103 Region r((with->get_xsize()-nx)/2, (with->get_ysize()-ny)/2, (with->get_zsize()-nz)/2,nx,ny,nz);
03104 with_resized->clip_inplace(r);
03105
03106
03107
03108 EMData* s = calc_fast_sigma_image(ones);
03109
03110 EMData* corr = calc_ccf(with_resized);
03111 corr->div(*s);
03112
03113 delete with_resized; delete ones;
03114 delete s;
03115
03116 EXITFUNC;
03117 return corr;
03118 }
03119
03120 EMData *EMData::convolute(EMData * with)
03121 {
03122 ENTERFUNC;
03123
03124 EMData *f1 = do_fft();
03125 if (!f1) {
03126 LOGERR("FFT returns NULL image");
03127 throw NullPointerException("FFT returns NULL image");
03128 }
03129
03130 f1->ap2ri();
03131
03132 EMData *cf = 0;
03133 if (with) {
03134 cf = with->do_fft();
03135 if (!cf) {
03136 LOGERR("FFT returns NULL image");
03137 throw NullPointerException("FFT returns NULL image");
03138 }
03139 cf->ap2ri();
03140 }
03141 else {
03142 cf = f1->copy();
03143 }
03144
03145 if (with && !EMUtil::is_same_size(f1, cf)) {
03146 LOGERR("images not same size");
03147 throw ImageFormatException("images not same size");
03148 }
03149
03150 float *rdata1 = f1->get_data();
03151 float *rdata2 = cf->get_data();
03152 size_t cf_size = cf->get_xsize() * cf->get_ysize() * cf->get_zsize();
03153
03154 float re,im;
03155 for (size_t i = 0; i < cf_size; i += 2) {
03156 re = rdata1[i] * rdata2[i] - rdata1[i + 1] * rdata2[i + 1];
03157 im = rdata1[i + 1] * rdata2[i] + rdata1[i] * rdata2[i + 1];
03158 rdata2[i]=re;
03159 rdata2[i+1]=im;
03160 }
03161
03162 cf->update();
03163 EMData *f2 = cf->do_ift();
03164
03165 if( cf )
03166 {
03167 delete cf;
03168 cf = 0;
03169 }
03170
03171 if( f1 )
03172 {
03173 delete f1;
03174 f1=0;
03175 }
03176
03177 EXITFUNC;
03178 return f2;
03179 }
03180
03181
03182 void EMData::common_lines(EMData * image1, EMData * image2,
03183 int mode, int steps, bool horizontal)
03184 {
03185 ENTERFUNC;
03186
03187 if (!image1 || !image2) {
03188 throw NullPointerException("NULL image");
03189 }
03190
03191 if (mode < 0 || mode > 2) {
03192 throw OutofRangeException(0, 2, mode, "invalid mode");
03193 }
03194
03195 if (!image1->is_complex()) {
03196 image1 = image1->do_fft();
03197 }
03198 if (!image2->is_complex()) {
03199 image2 = image2->do_fft();
03200 }
03201
03202 image1->ap2ri();
03203 image2->ap2ri();
03204
03205 if (!EMUtil::is_same_size(image1, image2)) {
03206 throw ImageFormatException("images not same sizes");
03207 }
03208
03209 int image2_nx = image2->get_xsize();
03210 int image2_ny = image2->get_ysize();
03211
03212 int rmax = image2_ny / 4 - 1;
03213 int array_size = steps * rmax * 2;
03214 float *im1 = new float[array_size];
03215 float *im2 = new float[array_size];
03216 for (int i = 0; i < array_size; i++) {
03217 im1[i] = 0;
03218 im2[i] = 0;
03219 }
03220
03221 set_size(steps * 2, steps * 2, 1);
03222
03223 float *image1_data = image1->get_data();
03224 float *image2_data = image2->get_data();
03225
03226 float da = M_PI / steps;
03227 float a = -M_PI / 2.0f + da / 2.0f;
03228 int jmax = 0;
03229
03230 for (int i = 0; i < steps * 2; i += 2, a += da) {
03231 float s1 = 0;
03232 float s2 = 0;
03233 int i2 = i * rmax;
03234 int j = 0;
03235
03236 for (float r = 3.0f; r < rmax - 3.0f; j += 2, r += 1.0f) {
03237 float x = r * cos(a);
03238 float y = r * sin(a);
03239
03240 if (x < 0) {
03241 x = -x;
03242 y = -y;
03243 LOGERR("CCL ERROR %d, %f !\n", i, -x);
03244 }
03245
03246 int k = (int) (floor(x) * 2 + floor(y + image2_ny / 2) * image2_nx);
03247 int l = i2 + j;
03248 float x2 = x - floor(x);
03249 float y2 = y - floor(y);
03250
03251 im1[l] = Util::bilinear_interpolate(image1_data[k],
03252 image1_data[k + 2],
03253 image1_data[k + image2_nx],
03254 image1_data[k + 2 + image2_nx], x2, y2);
03255
03256 im2[l] = Util::bilinear_interpolate(image2_data[k],
03257 image2_data[k + 2],
03258 image2_data[k + image2_nx],
03259 image2_data[k + 2 + image2_nx], x2, y2);
03260
03261 k++;
03262
03263 im1[l + 1] = Util::bilinear_interpolate(image1_data[k],
03264 image1_data[k + 2],
03265 image1_data[k + image2_nx],
03266 image1_data[k + 2 + image2_nx], x2, y2);
03267
03268 im2[l + 1] = Util::bilinear_interpolate(image2_data[k],
03269 image2_data[k + 2],
03270 image2_data[k + image2_nx],
03271 image2_data[k + 2 + image2_nx], x2, y2);
03272
03273 s1 += Util::square_sum(im1[l], im1[l + 1]);
03274 s2 += Util::square_sum(im2[l], im2[l + 1]);
03275 }
03276
03277 jmax = j - 1;
03278 float sqrt_s1 = std::sqrt(s1);
03279 float sqrt_s2 = std::sqrt(s2);
03280
03281 int l = 0;
03282 for (float r = 1; r < rmax; r += 1.0f) {
03283 int i3 = i2 + l;
03284 im1[i3] /= sqrt_s1;
03285 im1[i3 + 1] /= sqrt_s1;
03286 im2[i3] /= sqrt_s2;
03287 im2[i3 + 1] /= sqrt_s2;
03288 l += 2;
03289 }
03290 }
03291 float * data = get_data();
03292
03293 switch (mode) {
03294 case 0:
03295 for (int m1 = 0; m1 < 2; m1++) {
03296 for (int m2 = 0; m2 < 2; m2++) {
03297
03298 if (m1 == 0 && m2 == 0) {
03299 for (int i = 0; i < steps; i++) {
03300 int i2 = i * rmax * 2;
03301 for (int j = 0; j < steps; j++) {
03302 int l = i + j * steps * 2;
03303 int j2 = j * rmax * 2;
03304 data[l] = 0;
03305 for (int k = 0; k < jmax; k++) {
03306 data[l] += im1[i2 + k] * im2[j2 + k];
03307 }
03308 }
03309 }
03310 }
03311 else {
03312 int steps2 = steps * m2 + steps * steps * 2 * m1;
03313
03314 for (int i = 0; i < steps; i++) {
03315 int i2 = i * rmax * 2;
03316 for (int j = 0; j < steps; j++) {
03317 int j2 = j * rmax * 2;
03318 int l = i + j * steps * 2 + steps2;
03319 data[l] = 0;
03320
03321 for (int k = 0; k < jmax; k += 2) {
03322 i2 += k;
03323 j2 += k;
03324 data[l] += im1[i2] * im2[j2];
03325 data[l] += -im1[i2 + 1] * im2[j2 + 1];
03326 }
03327 }
03328 }
03329 }
03330 }
03331 }
03332
03333 break;
03334 case 1:
03335 for (int m1 = 0; m1 < 2; m1++) {
03336 for (int m2 = 0; m2 < 2; m2++) {
03337 int steps2 = steps * m2 + steps * steps * 2 * m1;
03338 int p1_sign = 1;
03339 if (m1 != m2) {
03340 p1_sign = -1;
03341 }
03342
03343 for (int i = 0; i < steps; i++) {
03344 int i2 = i * rmax * 2;
03345
03346 for (int j = 0; j < steps; j++) {
03347 int j2 = j * rmax * 2;
03348
03349 int l = i + j * steps * 2 + steps2;
03350 data[l] = 0;
03351 float a = 0;
03352
03353 for (int k = 0; k < jmax; k += 2) {
03354 i2 += k;
03355 j2 += k;
03356
03357 #ifdef _WIN32
03358 float a1 = (float) _hypot(im1[i2], im1[i2 + 1]);
03359 #else
03360 float a1 = (float) hypot(im1[i2], im1[i2 + 1]);
03361 #endif //_WIN32
03362 float p1 = atan2(im1[i2 + 1], im1[i2]);
03363 float p2 = atan2(im2[j2 + 1], im2[j2]);
03364
03365 data[l] += Util::angle_sub_2pi(p1_sign * p1, p2) * a1;
03366 a += a1;
03367 }
03368
03369 data[l] /= (float)(a * M_PI / 180.0f);
03370 }
03371 }
03372 }
03373 }
03374
03375 break;
03376 case 2:
03377 for (int m1 = 0; m1 < 2; m1++) {
03378 for (int m2 = 0; m2 < 2; m2++) {
03379 int steps2 = steps * m2 + steps * steps * 2 * m1;
03380
03381 for (int i = 0; i < steps; i++) {
03382 int i2 = i * rmax * 2;
03383
03384 for (int j = 0; j < steps; j++) {
03385 int j2 = j * rmax * 2;
03386 int l = i + j * steps * 2 + steps2;
03387 data[l] = 0;
03388
03389 for (int k = 0; k < jmax; k += 2) {
03390 i2 += k;
03391 j2 += k;
03392 #ifdef _WIN32
03393 data[l] += (float) (_hypot(im1[i2], im1[i2 + 1]) * _hypot(im2[j2], im2[j2 + 1]));
03394 #else
03395 data[l] += (float) (hypot(im1[i2], im1[i2 + 1]) * hypot(im2[j2], im2[j2 + 1]));
03396 #endif //_WIN32
03397 }
03398 }
03399 }
03400 }
03401 }
03402
03403 break;
03404 default:
03405 break;
03406 }
03407
03408 if (horizontal) {
03409 float *tmp_array = new float[ny];
03410 for (int i = 1; i < nx; i++) {
03411 for (int j = 0; j < ny; j++) {
03412 tmp_array[j] = get_value_at(i, j);
03413 }
03414 for (int j = 0; j < ny; j++) {
03415 set_value_at(i, j, 0, tmp_array[(j + i) % ny]);
03416 }
03417 }
03418 if( tmp_array )
03419 {
03420 delete[]tmp_array;
03421 tmp_array = 0;
03422 }
03423 }
03424
03425 if( im1 )
03426 {
03427 delete[]im1;
03428 im1 = 0;
03429 }
03430
03431 if( im2 )
03432 {
03433 delete im2;
03434 im2 = 0;
03435 }
03436
03437
03438 image1->update();
03439 image2->update();
03440 if( image1 )
03441 {
03442 delete image1;
03443 image1 = 0;
03444 }
03445 if( image2 )
03446 {
03447 delete image2;
03448 image2 = 0;
03449 }
03450 update();
03451 EXITFUNC;
03452 }
03453
03454
03455
03456 void EMData::common_lines_real(EMData * image1, EMData * image2,
03457 int steps, bool horiz)
03458 {
03459 ENTERFUNC;
03460
03461 if (!image1 || !image2) {
03462 throw NullPointerException("NULL image");
03463 }
03464
03465 if (!EMUtil::is_same_size(image1, image2)) {
03466 throw ImageFormatException("images not same size");
03467 }
03468
03469 int steps2 = steps * 2;
03470 int image_ny = image1->get_ysize();
03471 EMData *image1_copy = image1->copy();
03472 EMData *image2_copy = image2->copy();
03473
03474 float *im1 = new float[steps2 * image_ny];
03475 float *im2 = new float[steps2 * image_ny];
03476
03477 EMData *images[] = { image1_copy, image2_copy };
03478 float *ims[] = { im1, im2 };
03479
03480 for (int m = 0; m < 2; m++) {
03481 float *im = ims[m];
03482 float a = M_PI / steps2;
03483 Transform t(Dict("type","2d","alpha",-a));
03484 for (int i = 0; i < steps2; i++) {
03485 images[i]->transform(t);
03486 float *data = images[i]->get_data();
03487
03488 for (int j = 0; j < image_ny; j++) {
03489 float sum = 0;
03490 for (int k = 0; k < image_ny; k++) {
03491 sum += data[j * image_ny + k];
03492 }
03493 im[i * image_ny + j] = sum;
03494 }
03495
03496 float sum1 = 0;
03497 float sum2 = 0;
03498 for (int j = 0; j < image_ny; j++) {
03499 int l = i * image_ny + j;
03500 sum1 += im[l];
03501 sum2 += im[l] * im[l];
03502 }
03503
03504 float mean = sum1 / image_ny;
03505 float sigma = std::sqrt(sum2 / image_ny - sum1 * sum1);
03506
03507 for (int j = 0; j < image_ny; j++) {
03508 int l = i * image_ny + j;
03509 im[l] = (im[l] - mean) / sigma;
03510 }
03511
03512 images[i]->update();
03513 a += M_PI / steps;
03514 }
03515 }
03516
03517 set_size(steps2, steps2, 1);
03518 float *data1 = get_data();
03519
03520 if (horiz) {
03521 for (int i = 0; i < steps2; i++) {
03522 for (int j = 0, l = i; j < steps2; j++, l++) {
03523 if (l == steps2) {
03524 l = 0;
03525 }
03526
03527 float sum = 0;
03528 for (int k = 0; k < image_ny; k++) {
03529 sum += im1[i * image_ny + k] * im2[l * image_ny + k];
03530 }
03531 data1[i + j * steps2] = sum;
03532 }
03533 }
03534 }
03535 else {
03536 for (int i = 0; i < steps2; i++) {
03537 for (int j = 0; j < steps2; j++) {
03538 float sum = 0;
03539 for (int k = 0; k < image_ny; k++) {
03540 sum += im1[i * image_ny + k] * im2[j * image_ny + k];
03541 }
03542 data1[i + j * steps2] = sum;
03543 }
03544 }
03545 }
03546
03547 update();
03548
03549 if( image1_copy )
03550 {
03551 delete image1_copy;
03552 image1_copy = 0;
03553 }
03554
03555 if( image2_copy )
03556 {
03557 delete image2_copy;
03558 image2_copy = 0;
03559 }
03560
03561 if( im1 )
03562 {
03563 delete[]im1;
03564 im1 = 0;
03565 }
03566
03567 if( im2 )
03568 {
03569 delete[]im2;
03570 im2 = 0;
03571 }
03572 EXITFUNC;
03573 }
03574
03575
03576 void EMData::cut_slice(const EMData *const map, const Transform& transform, bool interpolate)
03577 {
03578 ENTERFUNC;
03579
03580 if (!map) throw NullPointerException("NULL image");
03581
03582 if ( get_ndim() != 2 ) throw ImageDimensionException("Can not call cut slice on an image that is not 2D");
03583 if ( map->get_ndim() != 3 ) throw ImageDimensionException("Can not cut slice from an image that is not 3D");
03584
03585 if ( is_complex() ) throw ImageFormatException("Can not call cut slice on an image that is complex");
03586 if ( map->is_complex() ) throw ImageFormatException("Can not cut slice from a complex image");
03587
03588
03589 float *sdata = map->get_data();
03590 float *ddata = get_data();
03591
03592 int map_nx = map->get_xsize();
03593 int map_ny = map->get_ysize();
03594 int map_nz = map->get_zsize();
03595 int map_nxy = map_nx * map_ny;
03596
03597 int ymax = ny/2;
03598 if ( ny % 2 == 1 ) ymax += 1;
03599 int xmax = nx/2;
03600 if ( nx % 2 == 1 ) xmax += 1;
03601 for (int y = -ny/2; y < ymax; y++) {
03602 for (int x = -nx/2; x < xmax; x++) {
03603 Vec3f coord(x,y,0);
03604 Vec3f soln = transform*coord;
03605
03606
03607
03608
03609
03610
03611
03612
03613
03614
03615 float xx = soln[0]+map_nx/2;
03616 float yy = s