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

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

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