emdata.cpp

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