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