emdata_core.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 "ctf.h"
00038 #include "emfft.h"
00039 #include "cmp.h"
00040 
00041 using namespace EMAN;
00042 
00043 // debug only
00044 #include <iostream>
00045 #include <cstring>
00046 
00047 using std::cout;
00048 using std::endl;
00049 
00050 #ifdef EMAN2_USING_CUDA
00051 #include "cuda/cuda_processor.h"
00052 #endif // EMAN2_USING_CUDA
00053 
00054 void EMData::free_memory()
00055 {
00056         ENTERFUNC;
00057         if (rdata) {
00058                 EMUtil::em_free(rdata);
00059                 rdata = 0;
00060         }
00061 
00062         if (supp) {
00063                 EMUtil::em_free(supp);
00064                 supp = 0;
00065         }
00066 
00067         if (rot_fp != 0)
00068         {
00069                 delete rot_fp;
00070                 rot_fp = 0;
00071         }
00072         /*
00073         nx = 0;
00074         ny = 0;
00075         nz = 0;
00076         nxy = 0;
00077          */
00078 
00079         EXITFUNC;
00080 }
00081 
00082 EMData * EMData::copy() const
00083 {
00084         ENTERFUNC;
00085 
00086         EMData *ret = new EMData(*this);
00087 
00088         EXITFUNC;
00089         return ret;
00090 }
00091 
00092 
00093 EMData *EMData::copy_head() const
00094 {
00095         ENTERFUNC;
00096         EMData *ret = new EMData();
00097         ret->attr_dict = attr_dict;
00098 
00099         ret->set_size(nx, ny, nz);
00100         ret->flags = flags;
00101 
00102         ret->all_translation = all_translation;
00103 
00104         ret->path = path;
00105         ret->pathnum = pathnum;
00106 
00107 // should these be here? d.woolford I did not comment them out, merely place them here (commented out) to draw attention
00108 //      ret->xoff = xoff;
00109 //      ret->yoff = yoff;
00110 //      ret->zoff = zoff;
00111 //      ret->changecount = changecount;
00112 
00113         ret->update();
00114 
00115         EXITFUNC;
00116         return ret;
00117 }
00118 
00119 std::complex<float> EMData::get_complex_at(const int &x,const int &y) const{
00120         if (abs(x)>=nx/2 || abs(y)>ny/2) return std::complex<float>(0,0);
00121         if (x>=0 && y>=0) return std::complex<float>(rdata[ x*2+y*nx],      rdata[x*2+y*nx+1]);
00122         if (x>0 && y<0) return std::complex<float>(  rdata[ x*2+(ny+y)*nx], rdata[x*2+(ny+y)*nx+1]);
00123         if (x<0 && y>0) return std::complex<float>(  rdata[-x*2+(ny-y)*nx],-rdata[-x*2+(ny-y)*nx+1]);
00124         return std::complex<float>(rdata[-x*2-y*nx],-rdata[-x*2+-y*nx+1]);
00125 }
00126 
00127 std::complex<float> EMData::get_complex_at(const int &x,const int &y,const int &z) const{
00128         if (abs(x)>=nx/2 || abs(y)>ny/2 || abs(z)>nz/2) return std::complex<float>(0,0);
00129 
00130         if (x<0) {
00131                 int idx=-x*2+(y<=0?-y:ny-y)*nx+(z<=0?-z:nz-z)*nxy;
00132                 return std::complex<float>(rdata[idx],rdata[idx+1]);
00133         }
00134 
00135         int idx=x*2+(y<0?ny+y:y)*nx+(z<0?nz+z:z)*nxy;
00136         return std::complex<float>(rdata[idx],rdata[idx+1]);
00137 }
00138 
00139 size_t EMData::get_complex_index(const int &x,const int &y,const int &z) const {
00140         if (abs(x)>=nx/2 || abs(y)>ny/2 || abs(z)>nz/2) return nxyz;
00141         if (x<0) {
00142                 return -x*2+(y<=0?-y:ny-y)*(size_t)nx+(z<=0?-z:nz-z)*(size_t)nxy;
00143         }
00144         return x*2+(y<0?ny+y:y)*(size_t)nx+(z<0?nz+z:z)*(size_t)nxy;
00145 }
00146 
00147 size_t EMData::get_complex_index(int x,int y,int z,const int &subx0,const int &suby0,const int &subz0,const int &fullnx,const int &fullny,const int &fullnz) const {
00148 if (abs(x)>=fullnx/2 || abs(y)>fullny/2 || abs(z)>fullnz/2) return nxyz;
00149 
00150 if (x<0) {
00151         x*=-1;
00152         y*=-1;
00153         z*=-1;
00154 }
00155 if (y<0) y=fullny+y;
00156 if (z<0) z=fullnz+z;
00157 
00158 if (x<subx0||y<suby0||z<subz0||x>=subx0+nx||y>=suby0+ny||z>=subz0+nz) return nxyz;
00159 
00160 return (x-subx0)*2+(y-suby0)*(size_t)nx+(z-subz0)*(size_t)nx*(size_t)ny;
00161 }
00162 
00163 
00164 void EMData::set_complex_at(const int &x,const int &y,const std::complex<float> &val) {
00165         if (abs(x)>=nx/2 || abs(y)>ny/2) return;
00166         if (x>=0 && y>=0) { rdata[ x*2+y*nx]=val.real(); rdata[x*2+y*nx+1]=val.imag(); }
00167         else if (x>0 && y<0) { rdata[ x*2+(ny+y)*nx]=val.real(); rdata[x*2+(ny+y)*nx+1]=val.imag(); }
00168         else if (x<0 && y>0) { rdata[-x*2+(ny-y)*nx]=val.real(); rdata[-x*2+(ny-y)*nx+1]=-val.imag(); }
00169         else { rdata[-x*2-y*nx]=val.real(); rdata[-x*2+-y*nx+1]=-val.imag(); }
00170         return;
00171 }
00172 
00173 void EMData::set_complex_at(const int &x,const int &y,const int &z,const std::complex<float> &val) {
00174 if (abs(x)>=nx/2 || abs(y)>ny/2 || abs(z)>nz/2) return;
00175 //if (x==0 && (y!=0 || z!=0)) set_complex_at(0,-y,-z,conj(val));
00176 
00177 // for x=0, we need to insert the value in 2 places
00178 // complex conjugate insertion. Removed due to ambiguity with returned index
00179 /*if (x==0 && (y!=0 || z!=0)) {
00180         size_t idx=(y<=0?-y:ny-y)*nx+(z<=0?-z:nz-z)*nx*ny;
00181         rdata[idx]=(float)val.real();
00182         rdata[idx+1]=(float)-val.imag();
00183 }*/
00184 
00185 size_t idx;
00186 if (x<0) {
00187         idx=-x*2+(y<=0?-y:ny-y)*(size_t)nx+(z<=0?-z:nz-z)*(size_t)nxy;
00188         rdata[idx]=(float)val.real();
00189         rdata[idx+1]=-(float)val.imag();
00190         return;
00191 }
00192 
00193 idx=x*2+(y<0?ny+y:y)*(size_t)nx+(z<0?nz+z:z)*(size_t)nxy;
00194 rdata[idx]=(float)val.real();
00195 rdata[idx+1]=(float)val.imag();
00196 
00197 return;
00198 }
00199 
00200 size_t EMData::add_complex_at(const int &x,const int &y,const int &z,const std::complex<float> &val) {
00201 //if (abs(x)>=nx/2 || abs(y)>ny/2 || abs(z)>nz/2) return nxyz;
00202 if (x>=nx/2 || y>ny/2 || z>nz/2 || x<=-nx/2 || y<-ny/2 || z<-nz/2) return nxyz;
00203 
00204 // for x=0, we need to insert the value in 2 places
00205 // complex conjugate insertion. Removed due to ambiguity with returned index
00206 /*if (x==0 && (y!=0 || z!=0)) {
00207         size_t idx=(y<=0?-y:ny-y)*nx+(z<=0?-z:nz-z)*nx*ny;
00208         rdata[idx]+=(float)val.real();
00209         rdata[idx+1]-=(float)val.imag();
00210 }*/
00211 
00212 size_t idx;
00213 if (x<0) {
00214         idx=-x*2+(y<=0?-y:ny-y)*(size_t)nx+(z<=0?-z:nz-z)*(size_t)nxy;
00215         rdata[idx]+=(float)val.real();
00216         rdata[idx+1]-=(float)val.imag();
00217         return idx;
00218 }
00219 
00220 idx=x*2+(y<0?ny+y:y)*(size_t)nx+(z<0?nz+z:z)*(size_t)nxy;
00221 rdata[idx]+=(float)val.real();
00222 rdata[idx+1]+=(float)val.imag();
00223 
00224 return idx;
00225 }
00226 
00227 size_t EMData::add_complex_at(int x,int y,int z,const int &subx0,const int &suby0,const int &subz0,const int &fullnx,const int &fullny,const int &fullnz,const std::complex<float> &val) {
00228 if (abs(x)>=fullnx/2 || abs(y)>fullny/2 || abs(z)>fullnz/2) return nxyz;
00229 //if (x==0 && (y!=0 || z!=0)) add_complex_at(0,-y,-z,subx0,suby0,subz0,fullnx,fullny,fullnz,conj(val));
00230 // complex conjugate insertion. Removed due to ambiguity with returned index
00231 /*if (x==0&& (y!=0 || z!=0)) {
00232         int yy=y<=0?-y:fullny-y;
00233         int zz=z<=0?-z:fullnz-z;
00234 
00235         if (yy<suby0||zz<subz0||yy>=suby0+ny||zz>=subz0+nz) return nx*ny*nz;
00236 
00237         size_t idx=(yy-suby0)*nx+(zz-subz0)*nx*ny;
00238         rdata[idx]+=(float)val.real();
00239         rdata[idx+1]+=(float)-val.imag();
00240 }*/
00241 float cc=1.0;
00242 if (x<0) {
00243         x*=-1;
00244         y*=-1;
00245         z*=-1;
00246         cc=-1.0;
00247 }
00248 if (y<0) y=fullny+y;
00249 if (z<0) z=fullnz+z;
00250 
00251 if (x<subx0||y<suby0||z<subz0||x>=subx0+nx||y>=suby0+ny||z>=subz0+nz) return nxyz;
00252 
00253 size_t idx=(x-subx0)*2+(y-suby0)*(size_t)nx+(z-subz0)*(size_t)nx*ny;
00254 rdata[idx]+=(float)val.real();
00255 rdata[idx+1]+=cc*(float)val.imag();
00256 return idx;
00257 }
00258 
00259 
00260 void EMData::add(float f,int keepzero)
00261 {
00262         ENTERFUNC;
00263 
00264         float * data = get_data();
00265         if( is_real() )
00266         {
00267                 if (f != 0) {
00268 
00269 
00270 #ifdef EMAN2_USING_CUDA
00271                         if ( gpu_operation_preferred () && !keepzero ) {
00272                                 EMDataForCuda tmp = get_data_struct_for_cuda();
00273                                 emdata_processor_add(&tmp,f);
00274                                 gpu_update();
00275                                 EXITFUNC;
00276                                 return;
00277                         }
00278 #endif // EMAN2_USING_CUDA
00279                         size_t size = nxyz;
00280                         if (keepzero) {
00281                                 for (size_t i = 0; i < size; i++) {
00282                                         if (data[i]) data[i] += f;
00283                                 }
00284                         }
00285                         else {
00286                                 for (size_t i = 0; i < size; i++) {
00287                                         data[i] += f;
00288                                 }
00289                         }
00290                         update();
00291                 }
00292         }
00293         else if( is_complex() )
00294         {
00295                 if( f!=0 )
00296                 {
00297                         update();
00298                         size_t size = nx*ny*nz; //size of data
00299                         if( keepzero )
00300                         {
00301                                 for(size_t i=0; i<size; i+=2)
00302                                 {
00303                                         if (data[i]) data[i] += f;
00304                                 }
00305                         }
00306                         else
00307                         {
00308                                 for(size_t i=0; i<size; i+=2)
00309                                 {
00310                                         data[i] += f;
00311                                 }
00312                         }
00313                 }
00314         }
00315         else
00316         {
00317                 throw ImageFormatException("This image is neither a real nor a complex image.");
00318         }
00319         update();
00320         EXITFUNC;
00321 }
00322 
00323 
00324 //for add operation, real and complex image is the same
00325 void EMData::add(const EMData & image)
00326 {
00327         ENTERFUNC;
00328         if (nx != image.get_xsize() || ny != image.get_ysize() || nz != image.get_zsize()) {
00329                 throw ImageFormatException( "images not same sizes");
00330         }
00331         else if( (is_real()^image.is_real()) == true )
00332         {
00333                 throw ImageFormatException( "not support add between real image and complex image");
00334         }
00335         else {
00336 
00337                 const float *src_data = image.get_data();
00338                 size_t size = nxyz;
00339                 float* data = get_data();
00340 
00341                 for (size_t i = 0; i < size; i++) {
00342                         data[i] += src_data[i];
00343                 }
00344                 update();
00345         }
00346         EXITFUNC;
00347 }
00348 
00349 //for add operation, real and complex image is the same
00350 void EMData::addsquare(const EMData & image)
00351 {
00352         ENTERFUNC;
00353         if (nx != image.get_xsize() || ny != image.get_ysize() || nz != image.get_zsize()) {
00354                 throw ImageFormatException( "images not same sizes");
00355         }
00356         else if( this->is_complex() || image.is_complex() )
00357         {
00358                 throw ImageFormatException( "Cannot addsquare() with complex images");
00359         }
00360         else {
00361 
00362                 const float *src_data = image.get_data();
00363                 size_t size = nxyz;
00364                 float* data = get_data();
00365 
00366                 for (size_t i = 0; i < size; i++) {
00367                         data[i] += src_data[i]*src_data[i];
00368                 }
00369                 update();
00370         }
00371         EXITFUNC;
00372 }
00373 
00374 //for add operation, real and complex image is the same
00375 void EMData::subsquare(const EMData & image)
00376 {
00377         ENTERFUNC;
00378         if (nx != image.get_xsize() || ny != image.get_ysize() || nz != image.get_zsize()) {
00379                 throw ImageFormatException( "images not same sizes");
00380         }
00381         else if( this->is_complex() || image.is_complex() )
00382         {
00383                 throw ImageFormatException( "Cannot addsquare() with complex images");
00384         }
00385         else {
00386 
00387                 const float *src_data = image.get_data();
00388                 size_t size = nxyz;
00389                 float* data = get_data();
00390 
00391                 for (size_t i = 0; i < size; i++) {
00392                         data[i] -= src_data[i]*src_data[i];
00393                 }
00394                 update();
00395         }
00396         EXITFUNC;
00397 }
00398 
00399 
00400 void EMData::sub(float f)
00401 {
00402         ENTERFUNC;
00403 
00404         float* data = get_data();
00405         if( is_real() )
00406         {
00407                 if (f != 0) {
00408 #ifdef EMAN2_USING_CUDA
00409                 if ( gpu_operation_preferred () ) {
00410                         EMDataForCuda tmp = get_data_struct_for_cuda();
00411                         emdata_processor_add(&tmp,-f);
00412                         gpu_update();
00413                         EXITFUNC;
00414                         return;
00415                 }
00416 #endif // EMAN2_USING_CUDA
00417                         size_t size = nxyz;
00418                         for (size_t i = 0; i < size; i++) {
00419                                 data[i] -= f;
00420                         }
00421                 }
00422                 update();
00423         }
00424         else if( is_complex() )
00425         {
00426                 if( f != 0 )
00427                 {
00428                         size_t size = nxyz;
00429                         for( size_t i=0; i<size; i+=2 )
00430                         {
00431                                 data[i] -= f;
00432                         }
00433                 }
00434                 update();
00435         }
00436         else
00437         {
00438                 throw ImageFormatException("This image is neither a real nor a complex image.");
00439         }
00440 
00441         EXITFUNC;
00442 }
00443 
00444 
00445 //for sub operation, real and complex image is the same
00446 void EMData::sub(const EMData & em)
00447 {
00448         ENTERFUNC;
00449 
00450         if (nx != em.get_xsize() || ny != em.get_ysize() || nz != em.get_zsize()) {
00451                 throw ImageFormatException("images not same sizes");
00452         }
00453         else if( (is_real()^em.is_real()) == true )
00454         {
00455                 throw ImageFormatException( "not support sub between real image and complex image");
00456         }
00457         else {
00458                 const float *src_data = em.get_data();
00459                 size_t size = nxyz;
00460                 float* data = get_data();
00461 
00462                 for (size_t i = 0; i < size; i++) {
00463                         data[i] -= src_data[i];
00464                 }
00465                 update();
00466         }
00467         EXITFUNC;
00468 }
00469 
00470 
00471 void EMData::mult(float f)
00472 {
00473         ENTERFUNC;
00474 
00475 
00476         if (is_complex()) {
00477                 ap2ri();
00478         }
00479         if (f != 1.0) {
00480 #ifdef EMAN2_USING_CUDA
00481                 if ( gpu_operation_preferred () ) {
00482                         EMDataForCuda tmp = get_data_struct_for_cuda();
00483                         emdata_processor_mult(&tmp,f);
00484                         gpu_update();
00485                         EXITFUNC;
00486                         return;
00487                 }
00488 #endif // EMAN2_USING_CUDA
00489                 float* data = get_data();
00490                 size_t size = nxyz;
00491                 for (size_t i = 0; i < size; i++) {
00492                         data[i] *= f;
00493                 }
00494                 update();
00495         }
00496         EXITFUNC;
00497 }
00498 
00499 
00500 void EMData::mult(const EMData & em, bool prevent_complex_multiplication)
00501 {
00502         ENTERFUNC;
00503 
00504         if (nx != em.get_xsize() || ny != em.get_ysize() || nz != em.get_zsize()) {
00505                 throw ImageFormatException( "can not multiply images that are not the same size");
00506         }
00507         else if( (is_real()^em.is_real()) == true )
00508         {
00509                 throw ImageFormatException( "can not multiply real and complex images.");
00510         }
00511         else
00512         {
00513                 const float *src_data = em.get_data();
00514                 size_t size = nxyz;
00515                 float* data = get_data();
00516                 if( is_real() || prevent_complex_multiplication )
00517                 {
00518                         for (size_t i = 0; i < size; i++) {
00519                                 data[i] *= src_data[i];
00520                         }
00521                 }
00522                 else
00523                 {
00524                         typedef std::complex<float> comp;
00525                         for( size_t i = 0; i < size; i+=2 )
00526                         {
00527                                 comp c_src( src_data[i], src_data[i+1] );
00528                                 comp c_rdat( data[i], data[i+1] );
00529                                 comp c_result = c_src * c_rdat;
00530                                 data[i] = c_result.real();
00531                                 data[i+1] = c_result.imag();
00532                         }
00533                 }
00534                 update();
00535         }
00536 
00537         EXITFUNC;
00538 }
00539 
00540 void EMData::mult_complex_efficient(const EMData & em, const int radius)
00541 {
00542         ENTERFUNC;
00543 
00544         if( is_real() || em.is_real() )throw ImageFormatException( "can call mult_complex_efficient unless both images are complex");
00545 
00546 
00547         const float *src_data = em.get_data();
00548 
00549         size_t i_radius = radius;
00550         size_t k_radius = 1;
00551         size_t j_radius = 1;
00552         int ndim = get_ndim();
00553 
00554         if (ndim != em.get_ndim()) throw ImageDimensionException("Can't do that");
00555 
00556         if ( ndim == 3 ) {
00557                 k_radius = radius;
00558                 j_radius = radius;
00559         } else if ( ndim == 2 ) {
00560                 j_radius = radius;
00561         }
00562 
00563 
00564         int s_nx = em.get_xsize();
00565         int s_nxy = s_nx*em.get_ysize();
00566 
00567         size_t r_size = nxyz;
00568         int s_size = s_nxy*em.get_zsize();
00569         float* data = get_data();
00570 
00571         for (size_t k = 0; k < k_radius; ++k ) {
00572                 for (size_t j = 0; j < j_radius; j++) {
00573                         for (size_t i = 0; i < i_radius; i++) {
00574                                 int r_idx = k*nxy + j*nx + i;
00575                                 int s_idx = k*s_nxy + j*s_nx + i;
00576                                 data[r_idx] *= src_data[s_idx];
00577                                 data[r_size-r_idx-1] *= src_data[s_size-s_idx-1];
00578                         }
00579                 }
00580         }
00581 
00582         update();
00583 
00584         EXITFUNC;
00585 }
00586 
00587 
00588 void EMData::div(float f)
00589 {
00590         ENTERFUNC;
00591         if ( f == 0 ) {
00592                 throw InvalidValueException(f,"Can not divide by zero");
00593         }
00594         mult(1.0f/f);
00595         EXITFUNC;
00596 }
00597 
00598 
00599 void EMData::div(const EMData & em)
00600 {
00601         ENTERFUNC;
00602 
00603         if (nx != em.get_xsize() || ny != em.get_ysize() || nz != em.get_zsize()) {
00604                 throw ImageFormatException( "images not same sizes");
00605         }
00606         else if( (is_real()^em.is_real()) == true )
00607         {
00608                 throw ImageFormatException( "not support division between real image and complex image");
00609         }
00610         else {
00611                 const float *src_data = em.get_data();
00612                 size_t size = nxyz;
00613                 float* data = get_data();
00614 
00615                 if( is_real() )
00616                 {
00617                         for (size_t i = 0; i < size; i++) {
00618                                 if(src_data[i] != 0) {
00619                                         data[i] /= src_data[i];
00620                                 }
00621                                 else {
00622                                         throw InvalidValueException(src_data[i], "divide by zero");
00623                                 }
00624                         }
00625                 }
00626                 else
00627                 {
00628                         typedef std::complex<float> comp;
00629                         for( size_t i = 0; i < size; i+=2 )
00630                         {
00631                                 comp c_src( src_data[i], src_data[i+1] );
00632                                 comp c_rdat( data[i], data[i+1] );
00633                                 comp c_result = c_rdat / c_src;
00634                                 data[i] = c_result.real();
00635                                 data[i+1] = c_result.imag();
00636                         }
00637                 }
00638                 update();
00639         }
00640 
00641         EXITFUNC;
00642 }
00643 
00644 
00645 // just a shortcut for cmp("dot")
00646 float EMData::dot(EMData * with)
00647 {
00648         ENTERFUNC;
00649         if (!with) {
00650                 throw NullPointerException("Null EMData Image");
00651         }
00652         DotCmp dot_cmp;
00653         float r = -dot_cmp.cmp(this, with);
00654         EXITFUNC;
00655         return r;
00656 }
00657 
00658 
00659 EMData *EMData::get_row(int row_index) const
00660 {
00661         ENTERFUNC;
00662 
00663         if (get_ndim() > 2) {
00664                 throw ImageDimensionException("1D/2D image only");
00665         }
00666 
00667         EMData *ret = new EMData();
00668         ret->set_size(nx, 1, 1);
00669         memcpy(ret->get_data(), get_data() + nx * row_index, nx * sizeof(float));
00670         ret->update();
00671         EXITFUNC;
00672         return ret;
00673 }
00674 
00675 
00676 void EMData::set_row(const EMData * d, int row_index)
00677 {
00678         ENTERFUNC;
00679 
00680         if (get_ndim() > 2) {
00681                 throw ImageDimensionException("1D/2D image only");
00682         }
00683         if (d->get_ndim() != 1) {
00684                 throw ImageDimensionException("1D image only");
00685         }
00686 
00687         float *dst = get_data();
00688         float *src = d->get_data();
00689         memcpy(dst + nx * row_index, src, nx * sizeof(float));
00690         update();
00691         EXITFUNC;
00692 }
00693 
00694 EMData *EMData::get_col(int col_index) const
00695 {
00696         ENTERFUNC;
00697 
00698         if (get_ndim() != 2) {
00699                 throw ImageDimensionException("2D image only");
00700         }
00701 
00702         EMData *ret = new EMData();
00703         ret->set_size(ny, 1, 1);
00704         float *dst = ret->get_data();
00705         float *src = get_data();
00706 
00707         for (int i = 0; i < ny; i++) {
00708                 dst[i] = src[i * nx + col_index];
00709         }
00710 
00711         ret->update();
00712         EXITFUNC;
00713         return ret;
00714 }
00715 
00716 
00717 void EMData::set_col(const EMData * d, int n)
00718 {
00719         ENTERFUNC;
00720 
00721         if (get_ndim() != 2) {
00722                 throw ImageDimensionException("2D image only");
00723         }
00724         if (d->get_ndim() != 1) {
00725                 throw ImageDimensionException("1D image only");
00726         }
00727 
00728         float *dst = get_data();
00729         float *src = d->get_data();
00730 
00731         for (int i = 0; i < ny; i++) {
00732                 dst[i * nx + n] = src[i];
00733         }
00734 
00735         update();
00736         EXITFUNC;
00737 }
00738 
00739 float& EMData::get_value_at_wrap(int x)
00740 {
00741         if (x < 0) x = nx + x;
00742         return get_data()[x];
00743 }
00744 
00745 float& EMData::get_value_at_wrap(int x, int y)
00746 {
00747         if (x < 0) x = nx + x;
00748         if (y < 0) y = ny + y;
00749 
00750         return get_data()[x + y * nx];
00751 }
00752 
00753 float& EMData::get_value_at_wrap(int x, int y, int z)
00754 {
00755         int lx = x;
00756         int ly = y;
00757         int lz = z;
00758         if (lx < 0) lx = nx + lx;
00759         if (ly < 0) ly = ny + ly;
00760         if (lz < 0) lz = nz + lz;
00761 
00762         return get_data()[lx + ly * nx + lz * nxy];
00763 }
00764 
00765 
00766 float EMData::get_value_at_wrap(int x) const
00767 {
00768         if (x < 0) x = nx - x;
00769         return get_data()[x];
00770 }
00771 
00772 float EMData::get_value_at_wrap(int x, int y) const
00773 {
00774         if (x < 0) x = nx - x;
00775         if (y < 0) y = ny - y;
00776 
00777         return get_data()[x + y * nx];
00778 }
00779 
00780 float EMData::get_value_at_wrap(int x, int y, int z) const
00781 {
00782         int lx = x;
00783         int ly = y;
00784         int lz = z;
00785         if (lx < 0) lx = nx + lx;
00786         if (ly < 0) ly = ny + ly;
00787         if (lz < 0) lz = nz + lz;
00788 
00789         return get_data()[lx + ly * nx + lz * nxy];
00790 }
00791 
00792 float EMData::sget_value_at(int x, int y, int z) const
00793 {
00794         if (x < 0 || x >= nx || y < 0 || y >= ny || z < 0 || z >= nz) {
00795                 return 0;
00796         }
00797         return get_data()[x + y * nx + z * nxy];
00798 }
00799 
00800 
00801 float EMData::sget_value_at(int x, int y) const
00802 {
00803         if (x < 0 || x >= nx || y < 0 || y >= ny) {
00804                 return 0;
00805         }
00806         return get_data()[x + y * nx];
00807 }
00808 
00809 
00810 float EMData::sget_value_at(size_t i) const
00811 {
00812         size_t size = nx*ny;
00813         size *= nz;
00814         if (i >= size) {
00815                 return 0;
00816         }
00817         return get_data()[i];
00818 }
00819 
00820 
00821 float EMData::sget_value_at_interp(float xx, float yy) const
00822 {
00823         int x = static_cast < int >(Util::fast_floor(xx));
00824         int y = static_cast < int >(Util::fast_floor(yy));
00825 
00826         float p1 = sget_value_at(x, y);
00827         float p2 = sget_value_at(x + 1, y);
00828         float p3 = sget_value_at(x, y + 1);
00829         float p4 = sget_value_at(x + 1, y + 1);
00830 
00831         float result = Util::bilinear_interpolate(p1, p2, p3, p4, xx - x, yy - y);
00832         return result;
00833 }
00834 
00835 
00836 float EMData::sget_value_at_interp(float xx, float yy, float zz) const
00837 {
00838         int x = (int) Util::fast_floor(xx);
00839         int y = (int) Util::fast_floor(yy);
00840         int z = (int) Util::fast_floor(zz);
00841 
00842         float p1 = sget_value_at(x, y, z);
00843         float p2 = sget_value_at(x + 1, y, z);
00844         float p3 = sget_value_at(x, y + 1, z);
00845         float p4 = sget_value_at(x + 1, y + 1, z);
00846 
00847         float p5 = sget_value_at(x, y, z + 1);
00848         float p6 = sget_value_at(x + 1, y, z + 1);
00849         float p7 = sget_value_at(x, y + 1, z + 1);
00850         float p8 = sget_value_at(x + 1, y + 1, z + 1);
00851 
00852         float result = Util::trilinear_interpolate(p1, p2, p3, p4, p5, p6, p7, p8,
00853                                                                                            xx - x, yy - y, zz - z);
00854 
00855         return result;
00856 }
00857 
00858 
00859 EMData & EMData::operator+=(float n)
00860 {
00861         add(n);
00862         update();
00863         return *this;
00864 }
00865 
00866 
00867 EMData & EMData::operator-=(float n)
00868 {
00869         *this += (-n);
00870         return *this;
00871 }
00872 
00873 
00874 EMData & EMData::operator*=(float n)
00875 {
00876         mult(n);
00877         update();
00878         return *this;
00879 }
00880 
00881 
00882 EMData & EMData::operator/=(float n)
00883 {
00884         if (n == 0) {
00885                 LOGERR("divided by zero");
00886                 return *this;
00887         }
00888         *this *= (1.0f / n);
00889         return *this;
00890 }
00891 
00892 
00893 EMData & EMData::operator+=(const EMData & em)
00894 {
00895         add(em);
00896         update();
00897         return *this;
00898 }
00899 
00900 
00901 EMData & EMData::operator-=(const EMData & em)
00902 {
00903         sub(em);
00904         update();
00905         return *this;
00906 }
00907 
00908 
00909 EMData & EMData::operator*=(const EMData & em)
00910 {
00911         mult(em);
00912         update();
00913         return *this;
00914 }
00915 
00916 
00917 EMData & EMData::operator/=(const EMData & em)
00918 {
00919         div(em);
00920         update();
00921         return *this;
00922 }
00923 
00924 
00925 EMData * EMData::power(int n) const
00926 {
00927         ENTERFUNC;
00928 
00929         if( n<0 ) {
00930                 throw InvalidValueException(n, "the power of negative integer not supported.");
00931         }
00932 
00933         EMData * r = this->copy();
00934         if( n == 0 ) {
00935                 r->to_one();
00936         }
00937         else if( n>1 ) {
00938                 for( int i=1; i<n; i++ ) {
00939                         *r *= *this;
00940                 }
00941         }
00942 
00943         r->update();
00944         return r;
00945 
00946         EXITFUNC;
00947 }
00948 
00949 
00950 EMData * EMData::sqrt() const
00951 {
00952         ENTERFUNC;
00953 
00954         if (is_complex()) {
00955                 throw ImageFormatException("real image only");
00956         }
00957 
00958         EMData * r = this->copy();
00959         float * new_data = r->get_data();
00960         float * data = get_data();
00961         size_t size = nxyz;
00962         for (size_t i = 0; i < size; ++i) {
00963                 if(data[i] < 0) {
00964                         throw InvalidValueException(data[i], "pixel value must be non-negative for logrithm");
00965                 }
00966                 else {
00967                         if(data[i]) {   //do nothing with pixel has value zero
00968                                 new_data[i] = std::sqrt(data[i]);
00969                         }
00970                 }
00971         }
00972 
00973         r->update();
00974         return r;
00975 
00976         EXITFUNC;
00977 }
00978 
00979 
00980 EMData * EMData::log() const
00981 {
00982         ENTERFUNC;
00983 
00984         if (is_complex()) {
00985                 throw ImageFormatException("real image only");
00986         }
00987 
00988         EMData * r = this->copy();
00989         float * new_data = r->get_data();
00990         float * data = get_data();
00991         size_t size = nxyz;
00992         for (size_t i = 0; i < size; ++i) {
00993                 if(data[i] < 0) {
00994                         throw InvalidValueException(data[i], "pixel value must be non-negative for logrithm");
00995                 }
00996                 else {
00997                         if(data[i]) {   //do nothing with pixel has value zero
00998                                 new_data[i] = std::log(data[i]);
00999                         }
01000                 }
01001         }
01002 
01003         r->update();
01004         return r;
01005 
01006         EXITFUNC;
01007 }
01008 
01009 
01010 EMData * EMData::log10() const
01011 {
01012         ENTERFUNC;
01013 
01014         if (is_complex()) {
01015                 throw ImageFormatException("real image only");
01016         }
01017 
01018         EMData * r = this->copy();
01019         float * new_data = r->get_data();
01020         float * data = get_data();
01021         size_t size = nxyz;
01022         for (size_t i = 0; i < size; ++i) {
01023                 if(data[i] < 0) {
01024                         throw InvalidValueException(data[i], "pixel value must be non-negative for logrithm");
01025                 }
01026                 else {
01027                         if(data[i]) {   //do nothing with pixel has value zero
01028                                 new_data[i] = std::log10(data[i]);
01029                         }
01030                 }
01031         }
01032 
01033         r->update();
01034         return r;
01035 
01036         EXITFUNC;
01037 }
01038 
01039 
01040 EMData * EMData::real() const //real part has half of x dimension for a complex image
01041 {
01042         ENTERFUNC;
01043 
01044         EMData * e = new EMData();
01045 
01046         if( is_real() ) // a real image, return a copy of itself
01047         {
01048                 e = this->copy();
01049         }
01050         else //for a complex image
01051         {
01052                 if( !is_ri() )
01053                 {
01054                         delete e;
01055                         throw InvalidCallException("This image is in amplitude/phase format, this function call require a complex image in real/imaginary format.");
01056                 }
01057                 int nx = get_xsize();
01058                 int ny = get_ysize();
01059                 int nz = get_zsize();
01060                 e->set_size(nx/2, ny, nz);
01061                 float * edata = e->get_data();
01062                 float * data = get_data();
01063                 size_t idx1, idx2;
01064                 for( int i=0; i<nx; ++i )
01065                 {
01066                         for( int j=0; j<ny; ++j )
01067                         {
01068                                 for( int k=0; k<nz; ++k )
01069                                 {
01070                                         if( i%2 == 0 )
01071                                         {
01072                                                 //complex data in format [real, complex, real, complex...]
01073                                                 idx1 = i/2+j*(nx/2)+k*(nx/2)*ny;
01074                                                 idx2 = i+j*nx+k*nx*ny;
01075                                                 edata[idx1] = data[idx2];
01076                                         }
01077                                 }
01078                         }
01079                 }
01080         }
01081 
01082         e->set_complex(false);
01083         if(e->get_ysize()==1 && e->get_zsize()==1) {
01084                 e->set_complex_x(false);
01085         }
01086         e->update();
01087         return e;
01088 
01089         EXITFUNC;
01090 }
01091 
01092 
01093 EMData * EMData::imag() const
01094 {
01095         ENTERFUNC;
01096 
01097         EMData * e = new EMData();
01098 
01099         if( is_real() ) {       //a real image has no imaginary part, throw exception
01100                 throw InvalidCallException("No imaginary part for a real image, this function call require a complex image.");
01101         }
01102         else {  //for complex image
01103                 if( !is_ri() ) {
01104                         throw InvalidCallException("This image is in amplitude/phase format, this function call require a complex image in real/imaginary format.");
01105                 }
01106                 int nx = get_xsize();
01107                 int ny = get_ysize();
01108                 int nz = get_zsize();
01109                 e->set_size(nx/2, ny, nz);
01110                 float * edata = e->get_data();
01111                 float * data = get_data();
01112                 for( int i=0; i<nx; i++ ) {
01113                         for( int j=0; j<ny; j++ ) {
01114                                 for( int k=0; k<nz; k++ ) {
01115                                         if( i%2 == 1 ) {
01116                                                 //complex data in format [real, complex, real, complex...]
01117                                                 edata[i/2+j*(nx/2)+k*(nx/2)*ny] = data[i+j*nx+k*nx*ny];
01118                                         }
01119                                 }
01120                         }
01121                 }
01122         }
01123 
01124         e->set_complex(false);
01125         if(e->get_ysize()==1 && e->get_zsize()==1) {
01126                 e->set_complex_x(false);
01127         }
01128         e->update();
01129         return e;
01130 
01131         EXITFUNC;
01132 }
01133 
01134 EMData * EMData::absi() const//abs has half of x dimension for a complex image
01135 {
01136         ENTERFUNC;
01137 
01138         EMData * e = new EMData();
01139 
01140         if( is_real() ) // a real image
01141         {
01142                 e = this->copy();
01143                 int nx = get_xsize();
01144                 int ny = get_ysize();
01145                 int nz = get_zsize();
01146                 float *edata = e->get_data();
01147                 float * data = get_data();
01148                 size_t idx;
01149                 for( int i=0; i<nx; ++i ) {
01150                         for( int j=0; j<ny; ++j ) {
01151                                 for( int k=0; k<nz; ++k ) {
01152                                         idx = i+j*nx+k*nx*ny;
01153                                         edata[idx] = std::abs(data[idx]);
01154                                 }
01155                         }
01156                 }
01157         }
01158         else //for a complex image
01159         {
01160                 if( !is_ri() )
01161                 {
01162                         throw InvalidCallException("This image is in amplitude/phase format, this function call require a complex image in real/imaginary format.");
01163                 }
01164                 int nx = get_xsize();
01165                 int ny = get_ysize();
01166                 int nz = get_zsize();
01167                 e->set_size(nx/2, ny, nz);
01168                 float * edata = e->get_data();
01169                 float * data = get_data();
01170                 size_t idx1, idx2;
01171                 for( int i=0; i<nx; ++i )
01172                 {
01173                         for( int j=0; j<ny; ++j )
01174                         {
01175                                 for( int k=0; k<nz; ++k )
01176                                 {
01177                                         if( i%2 == 0 )
01178                                         {
01179                                                 idx1 = i/2+j*(nx/2)+k*(nx/2)*ny;
01180                                                 idx2 = i+j*nx+k*nx*ny;
01181                                                 //complex data in format [real, complex, real, complex...]
01182                                                 edata[idx1] =
01183                                                 std::sqrt(data[idx2]*data[idx2]+data[idx2+1]*data[idx2+1]);
01184                                         }
01185                                 }
01186                         }
01187                 }
01188         }
01189 
01190         e->set_complex(false);
01191         if(e->get_ysize()==1 && e->get_zsize()==1) {
01192                 e->set_complex_x(false);
01193         }
01194         e->update();
01195         return e;
01196 
01197         EXITFUNC;
01198 }
01199 
01200 
01201 EMData * EMData::amplitude() const
01202 {
01203         ENTERFUNC;
01204 
01205         EMData * e = new EMData();
01206 
01207         if( is_real() ) {
01208                 throw InvalidCallException("No imaginary part for a real image, this function call require a complex image.");
01209         }
01210         else {
01211                 if(is_ri()) {
01212                         throw InvalidCallException("This image is in real/imaginary format, this function call require a complex image in amplitude/phase format.");
01213                 }
01214 
01215                 int nx = get_xsize();
01216                 int ny = get_ysize();
01217                 int nz = get_zsize();
01218                 e->set_size(nx/2, ny, nz);
01219                 float * edata = e->get_data();
01220                 float * data = get_data();
01221                 size_t idx1, idx2;
01222                 for( int i=0; i<nx; ++i )
01223                 {
01224                         for( int j=0; j<ny; ++j )
01225                         {
01226                                 for( int k=0; k<nz; ++k )
01227                                 {
01228                                         if( i%2 == 0 )
01229                                         {
01230                                                 idx1 = i/2+j*(nx/2)+k*(nx/2)*ny;
01231                                                 idx2 = i+j*nx+k*nx*ny;
01232                                                 //complex data in format [amp, phase, amp, phase...]
01233                                                 edata[idx1] = data[idx2];
01234                                         }
01235                                 }
01236                         }
01237                 }
01238         }
01239 
01240         e->set_complex(false);
01241         if(e->get_ysize()==1 && e->get_zsize()==1) {
01242                 e->set_complex_x(false);
01243         }
01244         e->update();
01245         return e;
01246 
01247         EXITFUNC;
01248 }
01249 
01250 EMData * EMData::phase() const
01251 {
01252         ENTERFUNC;
01253 
01254         EMData * e = new EMData();
01255 
01256         if( is_real() ) {
01257                 delete e;
01258                 throw InvalidCallException("No imaginary part for a real image, this function call require a complex image.");
01259         }
01260         else {
01261                 if(is_ri()) {
01262                         delete e;
01263                         throw InvalidCallException("This image is in real/imaginary format, this function call require a complex image in amplitude/phase format.");
01264                 }
01265 
01266                 int nx = get_xsize();
01267                 int ny = get_ysize();
01268                 int nz = get_zsize();
01269                 e->set_size(nx/2, ny, nz);
01270                 float * edata = e->get_data();
01271                 float * data = get_data();
01272                 size_t idx1, idx2;
01273                 for( int i=0; i<nx; ++i ) {
01274                         for( int j=0; j<ny; ++j ) {
01275                                 for( int k=0; k<nz; ++k ) {
01276                                         if( i%2 == 1 ) {
01277                                                 idx1 = i/2+j*(nx/2)+k*(nx/2)*ny;
01278                                                 idx2 = i+j*nx+k*nx*ny;
01279                                                 //complex data in format [real, complex, real, complex...]
01280                                                 edata[idx1] = data[idx2];
01281                                         }
01282                                 }
01283                         }
01284                 }
01285         }
01286 
01287         e->set_complex(false);
01288         if(e->get_ysize()==1 && e->get_zsize()==1) {
01289                 e->set_complex_x(false);
01290         }
01291         e->update();
01292         return e;
01293 
01294         EXITFUNC;
01295 }
01296 
01297 EMData * EMData::real2complex(const float img) const
01298 {
01299         ENTERFUNC;
01300 
01301         if( is_complex() ) {
01302                 throw InvalidCallException("This function call only apply to real image");
01303         }
01304 
01305         EMData * e = new EMData();
01306         int nx = get_xsize();
01307         int ny = get_ysize();
01308         int nz = get_zsize();
01309         e->set_size(nx*2, ny, nz);
01310 
01311         for( int k=0; k<nz; ++k ) {
01312                 for( int j=0; j<ny; ++j ) {
01313                         for( int i=0; i<nx; ++i ) {
01314                                 (*e)(i*2,j,k) = (*this)(i,j,k);
01315                                 (*e)(i*2+1,j,k) = img;
01316                         }
01317                 }
01318         }
01319 
01320         e->set_complex(true);
01321         if(e->get_ysize()==1 && e->get_zsize()==1) {
01322                 e->set_complex_x(true);
01323         }
01324         e->set_ri(true);
01325         e->update();
01326         return e;
01327 
01328         EXITFUNC;
01329 }
01330 
01331 void EMData::to_zero()
01332 {
01333         ENTERFUNC;
01334 
01335         if (is_complex()) {
01336                 set_ri(true);
01337         }
01338         else {
01339                 set_ri(false);
01340         }
01341 
01342         //EMUtil::em_memset(get_data(), 0, nxyz * sizeof(float));
01343         to_value(0.0);
01344         update();
01345         EXITFUNC;
01346 }
01347 
01348 void EMData::to_one()
01349 {
01350         ENTERFUNC;
01351 
01352         if (is_complex()) {
01353                 set_ri(true);
01354         }
01355         else {
01356                 set_ri(false);
01357         }
01358         to_value(1.0);
01359 
01360         update();
01361         EXITFUNC;
01362 }
01363 
01364 void EMData::to_value(const float& value)
01365 {
01366         ENTERFUNC;
01367 
01368 #ifdef EMAN2_USING_CUDA
01369         if ( gpu_operation_preferred() ) {
01370                 EMDataForCuda tmp = get_data_struct_for_cuda();
01371                 emdata_processor_to_value(&tmp,value);
01372                 gpu_update();
01373                 EXITFUNC;
01374                 return;
01375         }
01376 #endif // EMAN2_USING_CUDA
01377         float* data = get_data();
01378         if ( value != 0 ) std::fill(data,data+get_size(),value);
01379         else EMUtil::em_memset(data, 0, nxyz * sizeof(float)); // This might be faster, I don't know
01380 
01381         update();
01382         EXITFUNC;
01383 }
01384 
01385 

Generated on Mon Jul 19 12:40:09 2010 for EMAN2 by  doxygen 1.4.7