#include <cmp.h>
Inheritance diagram for EMAN::PhaseCmp:
Public Member Functions | |
float | cmp (EMData *image, EMData *with) const |
To compare 'image' with another image passed in through its parameters. | |
string | get_name () const |
Get the Cmp's name. | |
string | get_desc () const |
TypeDict | get_param_types () const |
Get Cmp parameter information in a dictionary. | |
Static Public Member Functions | |
Cmp * | NEW () |
Static Public Attributes | |
const string | NAME = "phase" |
SNR should be an array as returned by ctfcurve() 'with' should be the less noisy image, since it's amplitudes will be used to weight the phase residual. 2D only.
Use Phase Residual as a measure of similarity Differential phase residual (DPR) is a measure of statistical dependency between two averages, computed over rings in Fourier space as a function of ring radius (= spatial frequency, or resolution)
Definition at line 460 of file cmp.h.
|
To compare 'image' with another image passed in through its parameters. An optional transformation may be used to transform the 2 images.
Implements EMAN::Cmp. Definition at line 865 of file cmp.cpp. References EMAN::Util::angle_err_ri(), EMAN::Ctf::apix, EMAN::Ctf::compute_1d(), EMAN::EMData::copy(), EMAN::EMData::do_fft(), EMAN::EMData::do_fft_inplace(), EMAN::EMData::do_ift_inplace(), EMAN::EMObject::f, EMAN::EMData::get_attr(), EMAN::EMData::get_const_data(), EMAN::EMData::get_data(), EMAN::EMData::get_xsize(), EMAN::EMData::get_ysize(), EMAN::EMData::get_zsize(), EMAN::EMData::has_attr(), EMAN::Util::hypot3(), EMAN::Util::hypot_fast_int(), InvalidCallException, EMAN::EMData::is_complex(), norm(), ny, EMAN::EMData::set_attr(), EMAN::Dict::set_default(), EMAN::EMData::update(), x, and y. 00866 { 00867 ENTERFUNC; 00868 00869 int snrweight = params.set_default("snrweight", 0); 00870 int snrfn = params.set_default("snrfn",0); 00871 int ampweight = params.set_default("ampweight",0); 00872 int zeromask = params.set_default("zeromask",0); 00873 float minres = params.set_default("minres",500.0f); 00874 float maxres = params.set_default("maxres",2.0f); 00875 00876 if (snrweight && snrfn) throw InvalidCallException("SNR weight and SNRfn cannot both be set in the phase comparator"); 00877 00878 #ifdef EMAN2_USING_CUDA 00879 if (image->gpu_operation_preferred()) { 00880 // cout << "Cuda cmp" << endl; 00881 EXITFUNC; 00882 return cuda_cmp(image,with); 00883 } 00884 #endif 00885 00886 EMData *image_fft = NULL; 00887 EMData *with_fft = NULL; 00888 00889 int ny = image->get_ysize(); 00890 // int np = (int) ceil(Ctf::CTFOS * sqrt(2.0f) * ny / 2) + 2; 00891 int np = 0; 00892 vector<float> snr; 00893 00894 // weighting based on SNR estimate from CTF 00895 if (snrweight) { 00896 Ctf *ctf = NULL; 00897 if (!image->has_attr("ctf")) { 00898 if (!with->has_attr("ctf")) throw InvalidCallException("SNR weight with no CTF parameters"); 00899 ctf=with->get_attr("ctf"); 00900 } 00901 else ctf=image->get_attr("ctf"); 00902 00903 float ds=1.0f/(ctf->apix*ny); 00904 snr=ctf->compute_1d(ny,ds,Ctf::CTF_SNR); // note that this returns ny/2 values 00905 if(ctf) {delete ctf; ctf=0;} 00906 np=snr.size(); 00907 } 00908 // weighting based on empirical SNR function (not really good) 00909 else if (snrfn==1) { 00910 np=ny/2; 00911 snr.resize(np); 00912 00913 for (int i = 0; i < np; i++) { 00914 float x2 = 10.0f*i/np; 00915 snr[i] = x2 * exp(-x2); 00916 } 00917 } 00918 // no weighting 00919 else { 00920 np=ny/2; 00921 snr.resize(np); 00922 00923 for (int i = 0; i < np; i++) snr[i]=1.0; 00924 } 00925 00926 // Min/max modifications to weighting 00927 float pmin,pmax; 00928 if (minres>0) pmin=((float)image->get_attr("apix_x")*image->get_ysize())/minres; //cutoff in pixels, assume square 00929 else pmin=0; 00930 if (maxres>0) pmax=((float)image->get_attr("apix_x")*image->get_ysize())/maxres; 00931 else pmax=0; 00932 00933 // printf("%f\t%f\n",pmin,pmax); 00934 00935 // We use 'soft' edges for the Fourier cutoffs to minimize issues with pixel interpolation 00936 for (int i = 0; i < np; i++) { 00937 if (pmin>0) snr[i]*=(tanh(5.0f*(i-pmin)/pmin)+1.0f)/2.0f; 00938 if (pmax>0) snr[i]*=(1.0f-tanh(i-pmax))/2.0f; 00939 // printf("%d\t%f\n",i,snr[i]); 00940 } 00941 00942 if (zeromask) { 00943 image_fft=image->copy(); 00944 with_fft=with->copy(); 00945 00946 if (image_fft->is_complex()) image_fft->do_ift_inplace(); 00947 if (with_fft->is_complex()) with_fft->do_ift_inplace(); 00948 00949 int sz=image_fft->get_xsize()*image_fft->get_ysize()*image_fft->get_zsize(); 00950 float *d1=image_fft->get_data(); 00951 float *d2=with_fft->get_data(); 00952 00953 for (int i=0; i<sz; i++) { 00954 if (d1[i]==0.0 || d2[i]==0.0) { d1[i]=0.0; d2[i]=0.0; } 00955 } 00956 00957 image_fft->update(); 00958 with_fft->update(); 00959 image_fft->do_fft_inplace(); 00960 with_fft->do_fft_inplace(); 00961 image_fft->set_attr("free_me",1); 00962 with_fft->set_attr("free_me",1); 00963 } 00964 else { 00965 if (image->is_complex()) image_fft=image; 00966 else { 00967 image_fft=image->do_fft(); 00968 image_fft->set_attr("free_me",1); 00969 } 00970 00971 if (with->is_complex()) with_fft=with; 00972 else { 00973 with_fft=with->do_fft(); 00974 with_fft->set_attr("free_me",1); 00975 } 00976 } 00977 // image_fft->ri2ap(); 00978 // with_fft->ri2ap(); 00979 00980 const float *const image_fft_data = image_fft->get_const_data(); 00981 const float *const with_fft_data = with_fft->get_const_data(); 00982 double sum = 0; 00983 double norm = FLT_MIN; 00984 size_t i = 0; 00985 // int nx=image_fft->get_xsize(); 00986 ny=image_fft->get_ysize(); 00987 int nz=image_fft->get_zsize(); 00988 int nx2=image_fft->get_xsize()/2; 00989 int ny2=image_fft->get_ysize()/2; 00990 // int nz2=image_fft->get_zsize()/2; 00991 00992 // This can never happen any more... 00993 if (np==0) { 00994 for (int z = 0; z < nz; z++){ 00995 for (int y = 0; y < ny; y++) { 00996 for (int x = 0; x < nx2; x ++) { 00997 float a; 00998 if (ampweight) a= (float)hypot(with_fft_data[i],with_fft_data[i+1]); 00999 else a=1.0f; 01000 sum += Util::angle_err_ri(image_fft_data[i],image_fft_data[i+1],with_fft_data[i],with_fft_data[i+1]) * a; 01001 norm += a; 01002 i += 2; 01003 } 01004 } 01005 } 01006 01007 } 01008 else if (nz==1) { 01009 for (int y = 0; y < ny; y++) { 01010 for (int x = 0; x < nx2; x ++) { 01011 int r=Util::hypot_fast_int(x,y>ny/2?ny-y:y); 01012 if (r>=ny2) { i+=2; continue; } // we only have snr values to the box radius 01013 01014 float a; 01015 if (ampweight) a= (float)hypot(with_fft_data[i],with_fft_data[i+1]); 01016 else a=1.0f; 01017 a*=snr[r]; 01018 sum += Util::angle_err_ri(image_fft_data[i],image_fft_data[i+1],with_fft_data[i],with_fft_data[i+1]) * a; 01019 norm += a; 01020 i += 2; 01021 } 01022 } 01023 } 01024 else { 01025 for (int z = 0; z < nz; z++){ 01026 for (int y = 0; y < ny; y++) { 01027 for (int x = 0; x < nx2; x ++) { 01028 int r=(int)Util::hypot3(x,y>ny/2?ny-y:y,z>nz/2?nz-z:z); 01029 if (r>=ny2) { i+=2; continue; } // we only have snr values to the box radius 01030 01031 float a; 01032 if (ampweight) a= (float)hypot(with_fft_data[i],with_fft_data[i+1]); 01033 else a=1.0f; 01034 a*=snr[r]; 01035 sum += Util::angle_err_ri(image_fft_data[i],image_fft_data[i+1],with_fft_data[i],with_fft_data[i+1]) * a; 01036 norm += a; 01037 i += 2; 01038 } 01039 } 01040 } 01041 01042 } 01043 01044 EXITFUNC; 01045 01046 if( image_fft->has_attr("free_me") ) 01047 { 01048 delete image_fft; 01049 image_fft = 0; 01050 } 01051 if( with_fft->has_attr("free_me") ) 01052 { 01053 delete with_fft; 01054 with_fft = 0; 01055 } 01056 #if 0 01057 return (1.0f - sum / norm); 01058 #endif 01059 return (float)(sum / norm); 01060 }
|
|
Implements EMAN::Cmp. Definition at line 470 of file cmp.h. 00471 { 00472 return "Mean phase difference"; 00473 }
|
|
Get the Cmp's name. Each Cmp is identified by a unique name.
Implements EMAN::Cmp. Definition at line 465 of file cmp.h. 00466 {
00467 return NAME;
00468 }
|
|
Get Cmp parameter information in a dictionary. Each parameter has one record in the dictionary. Each record contains its name, data-type, and description.
Implements EMAN::Cmp. Definition at line 480 of file cmp.h. References EMAN::TypeDict::put(). 00481 { 00482 TypeDict d; 00483 d.put("snrweight", EMObject::INT, "If set, the SNR of 'this' will be used to weight the result. If 'this' lacks CTF info, it will check 'with'. (default=0)"); 00484 d.put("snrfn", EMObject::INT, "If nonzero, an empirical function will be used as a radial weight rather than the true SNR. (1 - exp decay)'. (default=0)"); 00485 d.put("ampweight", EMObject::INT, "If set, the amplitude of 'with' will be used as a weight in the averaging'. (default=0)"); 00486 d.put("zeromask", EMObject::INT, "Treat regions in either image that are zero as a mask"); 00487 d.put("minres", EMObject::FLOAT, "Lowest resolution to use in comparison (soft cutoff). Requires accurate A/pix in image. <0 disables. Default=500"); 00488 d.put("maxres", EMObject::FLOAT, "Highest resolution to use in comparison (soft cutoff). Requires accurate A/pix in image. <0 disables. Default=10"); 00489 return d; 00490 }
|
|
Definition at line 475 of file cmp.h. 00476 { 00477 return new PhaseCmp(); 00478 }
|
|
|