#include <reconstructor.h>
Inheritance diagram for EMAN::WienerFourierReconstructor:
Public Member Functions | |
WienerFourierReconstructor () | |
Default constructor calls load_default_settings(). | |
virtual | ~WienerFourierReconstructor () |
Deconstructor calls free_memory(). | |
virtual int | insert_slice (const EMData *const slice, const Transform &euler, const float weight=1.0) |
Insert a slice into a 3D volume, in a given orientation. | |
virtual int | determine_slice_agreement (EMData *slice, const Transform &euler, const float weight=1.0, bool sub=true) |
Compares a slice to the current reconstruction volume and computes a normalization factor and quality. | |
virtual EMData * | finish (bool doift=true) |
Get the reconstructed volume Normally will return the volume in real-space with the requested size. | |
virtual string | get_name () const |
Get the unique name of the reconstructor. | |
virtual string | get_desc () const |
Get the one line description of the reconstructor. | |
Static Public Member Functions | |
static Reconstructor * | NEW () |
Factory incorporation uses the pointer of this function. | |
Static Public Attributes | |
static const string | NAME = "wiener_fourier" |
Protected Member Functions | |
virtual void | do_insert_slice_work (const EMData *const input_slice, const Transform &euler, const float weight) |
A function to perform the nuts and bolts of inserting an image slice. | |
virtual void | do_compare_slice_work (EMData *input_slice, const Transform &euler, float weight) |
A function to perform the nuts and bolts of comparing an image slice. | |
virtual bool | pixel_at (const float &xx, const float &yy, const float &zz, float *dt) |
This is a mode-2 pixel extractor. | |
Private Member Functions | |
WienerFourierReconstructor (const WienerFourierReconstructor &that) | |
Disallow copy construction. | |
WienerFourierReconstructor & | operator= (const WienerFourierReconstructor &) |
Disallow assignment. |
It will perform a reconstruction with a nonisotropic Wiener filter applied to the final reconstruction, and will 'undo' the Wiener filter on the individual class-averages if ctf_wiener_filtered is set. This represents something which was not possible to accomplish in EMAN1, and should produce superior results, with proper anisotropic filtering. Still, the filtration makes the assumption that the original SNR estimates were accurate, and that the data will average completely coherently, which is not truly the case. This may produce models which are somewhat underfiltered in the Wiener sense, but since B-factor corrections are not applied in the ctf.auto averager, this effect is likely already more than compensated for.
Definition at line 537 of file reconstructor.h.
|
Default constructor calls load_default_settings().
Definition at line 543 of file reconstructor.h. Referenced by NEW().
|
|
Deconstructor calls free_memory().
Definition at line 548 of file reconstructor.h.
|
|
Disallow copy construction.
|
|
Compares a slice to the current reconstruction volume and computes a normalization factor and quality. Normalization and quality are returned via attributes set in the passed slice. You may freely mix calls to determine_slice_agreement with calls to insert_slice, but note that determine_slice_agreement can only use information from slices that have already been inserted. Attributes set in the slice are: reconstruct_norm the relative normalization factor which should be applied before inserting the slice reconstruct_qual a scaled quality factor (larger better) for this slice as compared to the existing reconstruction reconstruct_absqual the absolute (not scaled based on weight) quality factor comparing this slice to the existing reconstruction reconstruct_weight the summed weights from all voxels intersecting with the inserted slice, larger -> more overlap with other slices
Reimplemented from EMAN::FourierReconstructor. Definition at line 954 of file reconstructor.cpp. References EMAN::EMData::copy(), do_compare_slice_work(), do_insert_slice_work(), EMAN::EMData::get_attr_default(), NullPointerException, EMAN::FourierReconstructor::preprocess_slice(), EMAN::EMData::set_attr(), EMAN::Transform::set_mirror(), EMAN::Transform::set_scale(), EMAN::Transform::set_trans(), EMAN::ReconstructorVolumeData::tmp_data, and EMAN::EMData::write_image(). 00955 { 00956 // Are these exceptions really necessary? (d.woolford) 00957 if (!input_slice) throw NullPointerException("EMData pointer (input image) is NULL"); 00958 00959 Transform * rotation; 00960 rotation = new Transform(arg); // assignment operator 00961 00962 EMData *slice; 00963 if (input_slice->get_attr_default("reconstruct_preproc",(int) 0)) slice=input_slice->copy(); 00964 else slice = preprocess_slice( input_slice, *rotation); 00965 00966 00967 // We must use only the rotational component of the transform, scaling, translation and mirroring 00968 // are not implemented in Fourier space, but are in preprocess_slice 00969 rotation->set_scale(1.0); 00970 rotation->set_mirror(false); 00971 rotation->set_trans(0,0,0); 00972 00973 tmp_data->write_image("dbug.hdf",0); 00974 00975 // Remove the current slice first (not threadsafe, but otherwise performance would be awful) 00976 if (sub) do_insert_slice_work(slice, *rotation, -weight); 00977 00978 // Compare 00979 do_compare_slice_work(slice, *rotation,weight); 00980 00981 input_slice->set_attr("reconstruct_norm",slice->get_attr("reconstruct_norm")); 00982 input_slice->set_attr("reconstruct_absqual",slice->get_attr("reconstruct_absqual")); 00983 // input_slice->set_attr("reconstruct_qual",slice->get_attr("reconstruct_qual")); 00984 input_slice->set_attr("reconstruct_weight",slice->get_attr("reconstruct_weight")); 00985 00986 // Now put the slice back 00987 if (sub) do_insert_slice_work(slice, *rotation, weight); 00988 00989 00990 delete rotation; 00991 delete slice; 00992 00993 // image->update(); 00994 return 0; 00995 00996 }
|
|
A function to perform the nuts and bolts of comparing an image slice.
Reimplemented from EMAN::FourierReconstructor. Definition at line 998 of file reconstructor.cpp. References EMAN::dot(), dt, EMAN::EMData::get_data(), EMAN::Symmetry3D::get_symmetries(), EMAN::EMData::get_xsize(), EMAN::EMData::get_ysize(), EMAN::ReconstructorVolumeData::nx, EMAN::ReconstructorVolumeData::ny, EMAN::ReconstructorVolumeData::nz, EMAN::FactoryBase::params, pixel_at(), power(), EMAN::EMData::set_attr(), sqrt(), EMAN::ReconstructorVolumeData::subnx, EMAN::ReconstructorVolumeData::subny, EMAN::ReconstructorVolumeData::subnz, x, and y. Referenced by determine_slice_agreement(). 00999 { 01000 01001 float dt[3]; // This stores the complex and weight from the volume 01002 float dt2[2]; // This stores the local image complex 01003 float *dat = input_slice->get_data(); 01004 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]); 01005 01006 float inx=(float)(input_slice->get_xsize()); // x/y dimensions of the input image 01007 float iny=(float)(input_slice->get_ysize()); 01008 01009 double dot=0; // summed pixel*weight dot product 01010 double vweight=0; // sum of weights 01011 double power=0; // sum of inten*weight from volume 01012 double power2=0; // sum of inten*weight from image 01013 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) { 01014 Transform t3d = arg*(*it); 01015 for (int y = -iny/2; y < iny/2; y++) { 01016 for (int x = 0; x <= inx/2; x++) { 01017 if (x==0 && y==0) continue; // We don't want to use the Fourier origin 01018 01019 float rx = (float) x/(inx-2); // coords relative to Nyquist=.5 01020 float ry = (float) y/iny; 01021 01022 // if ((rx * rx + Util::square(ry - max_input_dim / 2)) > rl) 01023 // continue; 01024 01025 Vec3f coord(rx,ry,0); 01026 coord = coord*t3d; // transpose multiplication 01027 float xx = coord[0]; // transformed coordinates in terms of Nyquist 01028 float yy = coord[1]; 01029 float zz = coord[2]; 01030 01031 01032 if (fabs(xx)>0.5 || fabs(yy)>=0.5 || fabs(zz)>=0.5) continue; 01033 01034 // Map back to actual pixel coordinates in output volume 01035 xx=xx*(nx-2); 01036 yy=yy*ny; 01037 zz=zz*nz; 01038 01039 01040 int idx = (int)(x * 2 + inx*(y<0?iny+y:y)); 01041 dt2[0] = dat[idx]; 01042 dt2[1] = dat[idx+1]; 01043 01044 // value returned indirectly in dt 01045 if (!pixel_at(xx,yy,zz,dt) || dt[2]<=0) continue; 01046 01047 // printf("%f\t%f\t%f\t%f\t%f\n",dt[0],dt[1],dt[2],dt2[0],dt2[1]); 01048 dot+=(dt[0]*dt2[0]+dt[1]*dt2[1])*dt[2]; 01049 vweight+=dt[2]; 01050 power+=(dt[0]*dt[0]+dt[1]*dt[1])*dt[2]; 01051 power2+=(dt2[0]*dt2[0]+dt2[1]*dt2[1])*dt[2]; 01052 } 01053 } 01054 } 01055 01056 dot/=sqrt(power*power2); // normalize the dot product 01057 // input_slice->set_attr("reconstruct_norm",(float)(power2<=0?1.0:sqrt(power/power2)/(inx*iny))); 01058 input_slice->set_attr("reconstruct_norm",(float)(power2<=0?1.0:sqrt(power/power2))); 01059 input_slice->set_attr("reconstruct_absqual",(float)dot); 01060 float rw=weight<=0?1.0f:1.0f/weight; 01061 input_slice->set_attr("reconstruct_qual",(float)(dot*rw/((rw-1.0)*dot+1.0))); // here weight is a proxy for SNR 01062 input_slice->set_attr("reconstruct_weight",(float)vweight/(float)(subnx*subny*subnz)); 01063 // printf("** %g\t%g\t%g\t%g ##\n",dot,vweight,power,power2); 01064 //printf("** %f %f %f ##\n",(float)(power2<=0?1.0:sqrt(power/power2)/(inx*iny)),(float)dot,(float)(dot*weight/((weight-1.0)*dot+1.0))); 01065 }
|
|
A function to perform the nuts and bolts of inserting an image slice.
Reimplemented from EMAN::FourierReconstructor. Definition at line 899 of file reconstructor.cpp. References EMAN::EMData::get_attr(), EMAN::EMData::get_attr_default(), EMAN::EMData::get_complex_at(), EMAN::Symmetry3D::get_symmetries(), EMAN::EMData::get_xsize(), EMAN::EMData::get_ysize(), EMAN::FourierPixelInserter3D::insert_pixel(), EMAN::FourierReconstructor::inserter, EMAN::Util::linear_interpolate(), EMAN::ReconstructorVolumeData::nx, EMAN::ReconstructorVolumeData::ny, EMAN::ReconstructorVolumeData::nz, EMAN::FactoryBase::params, sub(), weight, x, and y. Referenced by determine_slice_agreement(), and insert_slice(). 00900 { 00901 00902 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]); 00903 00904 float inx=(float)(input_slice->get_xsize()); // x/y dimensions of the input image 00905 float iny=(float)(input_slice->get_ysize()); 00906 00907 int undo_wiener=(int)input_slice->get_attr_default("ctf_wiener_filtered",0); // indicates whether we need to undo a wiener filter before insertion 00908 // if (undo_wiener) throw UnexpectedBehaviorException("wiener_fourier does not yet accept already Wiener filtered class-averages. Suggest using ctf.auto averager for now."); 00909 00910 vector<float> snr=input_slice->get_attr("ctf_snr_total"); 00911 float sub=1.0; 00912 if (inweight<0) sub=-1.0; 00913 float weight; 00914 00915 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) { 00916 Transform t3d = arg*(*it); 00917 for (int y = -iny/2; y < iny/2; y++) { 00918 for (int x = 0; x <= inx/2; x++) { 00919 00920 float rx = (float) x/(inx-2.0f); // coords relative to Nyquist=.5 00921 float ry = (float) y/iny; 00922 00923 // This deals with the SNR weight 00924 float rn = hypot(rx,ry); 00925 if (rn>=.5) continue; // no SNR in the corners, and we're going to mask them later anyway 00926 rn*=snr.size()*2.0; 00927 int rni=(int)floor(rn); 00928 if (rni>=snr.size()-1) weight=snr[snr.size()-1]*sub; 00929 else { 00930 rn-=rni; 00931 weight=Util::linear_interpolate(snr[rni],snr[rni+1],rn); 00932 } 00933 // if (weight>500.0) printf("%f %d %d %f %f %d %f\n",weight,x,y,rx,ry,rni); 00934 00935 Vec3f coord(rx,ry,0); 00936 coord = coord*t3d; // transpose multiplication 00937 float xx = coord[0]; // transformed coordinates in terms of Nyquist 00938 float yy = coord[1]; 00939 float zz = coord[2]; 00940 00941 // Map back to real pixel coordinates in output volume 00942 xx=xx*(nx-2); 00943 yy=yy*ny; 00944 zz=zz*nz; 00945 00946 // printf("%f\n",weight); 00947 if (undo_wiener) inserter->insert_pixel(xx,yy,zz,(input_slice->get_complex_at(x,y))*((weight+1.0f)/weight),weight*sub); 00948 else inserter->insert_pixel(xx,yy,zz,input_slice->get_complex_at(x,y),weight*sub); 00949 } 00950 } 00951 } 00952 }
|
|
Get the reconstructed volume Normally will return the volume in real-space with the requested size. The calling application is responsible for removing any padding.
Reimplemented from EMAN::FourierReconstructor. Definition at line 1141 of file reconstructor.cpp. References EMAN::EMData::depad(), EMAN::EMData::do_ift_inplace(), EMAN::EMData::get_ysize(), EMAN::EMData::get_zsize(), EMAN::Dict::has_key(), EMAN::ReconstructorVolumeData::image, EMAN::ReconstructorVolumeData::normalize_threed(), EMAN::FactoryBase::params, EMAN::EMData::process_inplace(), EMAN::Dict::set_default(), EMAN::ReconstructorVolumeData::tmp_data, EMAN::EMData::update(), and EMAN::EMData::write_image(). 01142 { 01143 01144 bool sqrtnorm=params.set_default("sqrtnorm",false); 01145 normalize_threed(sqrtnorm,true); // true is the wiener filter 01146 01147 if (doift) { 01148 image->do_ift_inplace(); 01149 image->depad(); 01150 image->process_inplace("xform.phaseorigin.tocenter"); 01151 } 01152 01153 image->update(); 01154 01155 if (params.has_key("savenorm") && strlen((const char *)params["savenorm"])>0) { 01156 if (tmp_data->get_ysize()%2==0 && tmp_data->get_zsize()%2==0) tmp_data->process_inplace("xform.fourierorigin.tocenter"); 01157 tmp_data->write_image((const char *)params["savenorm"]); 01158 } 01159 01160 delete tmp_data; 01161 tmp_data=0; 01162 EMData *ret=image; 01163 image=0; 01164 01165 return ret; 01166 }
|
|
Get the one line description of the reconstructor.
Reimplemented from EMAN::FourierReconstructor. Definition at line 598 of file reconstructor.h. 00599 { 00600 return "Reconstruction via direct Fourier methods using one of a variety of different kernels, most of which are Gaussian based. This version also incorporates a nonisotropic Wiener filter based on SNR estimates stored in the class-average headers by the ctf.auto averager."; 00601 }
|
|
Get the unique name of the reconstructor.
Reimplemented from EMAN::FourierReconstructor. Definition at line 591 of file reconstructor.h. References NAME. 00592 { 00593 return NAME; 00594 }
|
|
Insert a slice into a 3D volume, in a given orientation.
Reimplemented from EMAN::FourierReconstructor. Definition at line 863 of file reconstructor.cpp. References EMAN::EMData::copy(), do_insert_slice_work(), EMAN::EMData::get_attr_default(), EMAN::EMData::has_attr(), NotExistingObjectException, NullPointerException, EMAN::FourierReconstructor::preprocess_slice(), EMAN::Transform::set_mirror(), EMAN::Transform::set_scale(), and EMAN::Transform::set_trans(). 00864 { 00865 // Are these exceptions really necessary? (d.woolford) 00866 if (!input_slice) throw NullPointerException("EMData pointer (input image) is NULL"); 00867 00868 Transform * rotation; 00869 /* if ( input_slice->has_attr("xform.projection") ) { 00870 rotation = (Transform*) (input_slice->get_attr("xform.projection")); // assignment operator 00871 } else {*/ 00872 rotation = new Transform(arg); // assignment operator 00873 // } 00874 00875 if (!input_slice->has_attr("ctf_snr_total")) 00876 throw NotExistingObjectException("ctf_snr_total","No SNR information present in class-average. Must use the ctf.auto or ctfw.auto averager."); 00877 00878 EMData *slice; 00879 if (input_slice->get_attr_default("reconstruct_preproc",(int) 0)) slice=input_slice->copy(); 00880 else slice = preprocess_slice( input_slice, *rotation); 00881 00882 00883 // We must use only the rotational component of the transform, scaling, translation and mirroring 00884 // are not implemented in Fourier space, but are in preprocess_slice 00885 rotation->set_scale(1.0); 00886 rotation->set_mirror(false); 00887 rotation->set_trans(0,0,0); 00888 00889 // Finally to the pixel wise slice insertion 00890 do_insert_slice_work(slice, *rotation, weight); 00891 00892 delete rotation; rotation=0; 00893 delete slice; 00894 00895 // image->update(); 00896 return 0; 00897 }
|
|
Factory incorporation uses the pointer of this function.
Reimplemented from EMAN::FourierReconstructor. Definition at line 606 of file reconstructor.h. References WienerFourierReconstructor(). 00607 { 00608 return new WienerFourierReconstructor(); 00609 }
|
|
Disallow assignment.
|
|
This is a mode-2 pixel extractor.
Reimplemented from EMAN::FourierReconstructor. Definition at line 1067 of file reconstructor.cpp. References EMAN::Util::fast_exp(), EMAN::EMData::get_complex_index(), EMAN::EMData::get_complex_index_fast(), EMAN::EMData::get_data(), EMAN::Util::hypot3sq(), EMAN::EMConsts::I2G, EMAN::ReconstructorVolumeData::image, norm(), EMAN::ReconstructorVolumeData::nx, EMAN::ReconstructorVolumeData::nx2, EMAN::ReconstructorVolumeData::ny, EMAN::ReconstructorVolumeData::ny2, EMAN::ReconstructorVolumeData::nz, EMAN::ReconstructorVolumeData::nz2, rdata, EMAN::ReconstructorVolumeData::subnx, EMAN::ReconstructorVolumeData::subx0, EMAN::ReconstructorVolumeData::suby0, EMAN::ReconstructorVolumeData::subz0, and EMAN::ReconstructorVolumeData::tmp_data. Referenced by do_compare_slice_work(). 01068 { 01069 int x0 = (int) floor(xx); 01070 int y0 = (int) floor(yy); 01071 int z0 = (int) floor(zz); 01072 01073 float *rdata=image->get_data(); 01074 float *norm=tmp_data->get_data(); 01075 float normsum=0,normsum2=0; 01076 01077 dt[0]=dt[1]=dt[2]=0.0; 01078 01079 if (nx==subnx) { // normal full reconstruction 01080 if (x0<-nx2-1 || y0<-ny2-1 || z0<-nz2-1 || x0>nx2 || y0>ny2 || z0>nz2 ) return false; 01081 01082 // no error checking on add_complex_fast, so we need to be careful here 01083 int x1=x0+1; 01084 int y1=y0+1; 01085 int z1=z0+1; 01086 if (x0<-nx2) x0=-nx2; 01087 if (x1>nx2) x1=nx2; 01088 if (y0<-ny2) y0=-ny2; 01089 if (y1>ny2) y1=ny2; 01090 if (z0<-nz2) z0=-nz2; 01091 if (z1>nz2) z1=nz2; 01092 01093 size_t idx=0; 01094 float r, gg; 01095 for (int k = z0 ; k <= z1; k++) { 01096 for (int j = y0 ; j <= y1; j++) { 01097 for (int i = x0; i <= x1; i ++) { 01098 r = Util::hypot3sq((float) i - xx, j - yy, k - zz); 01099 idx=image->get_complex_index_fast(i,j,k); 01100 gg = Util::fast_exp(-r / EMConsts::I2G); 01101 01102 dt[0]+=gg*rdata[idx]; 01103 dt[1]+=(i<0?-1.0f:1.0f)*gg*rdata[idx+1]; 01104 dt[2]+=norm[idx/2]*gg; 01105 normsum2+=gg; 01106 normsum+=gg*norm[idx/2]; 01107 } 01108 } 01109 } 01110 if (normsum==0) return false; 01111 dt[0]/=normsum; 01112 dt[1]/=normsum; 01113 dt[2]/=normsum2; 01114 // printf("%1.2f,%1.2f,%1.2f\t%1.3f\t%1.3f\t%1.3f\t%1.3f\t%1.3f\n",xx,yy,zz,dt[0],dt[1],dt[2],rdata[idx],rdata[idx+1]); 01115 return true; 01116 } 01117 else { // for subvolumes, not optimized yet 01118 size_t idx; 01119 float r, gg; 01120 for (int k = z0 ; k <= z0 + 1; k++) { 01121 for (int j = y0 ; j <= y0 + 1; j++) { 01122 for (int i = x0; i <= x0 + 1; i ++) { 01123 r = Util::hypot3sq((float) i - xx, j - yy, k - zz); 01124 idx=image->get_complex_index(i,j,k,subx0,suby0,subz0,nx,ny,nz); 01125 gg = Util::fast_exp(-r / EMConsts::I2G)*norm[idx/2]; 01126 01127 dt[0]+=gg*rdata[idx]; 01128 dt[1]+=(i<0?-1.0f:1.0f)*gg*rdata[idx+1]; 01129 dt[2]+=norm[idx/2]; 01130 normsum+=gg; 01131 } 01132 } 01133 } 01134 01135 if (normsum==0) return false; 01136 return true; 01137 } 01138 }
|
|
Reimplemented from EMAN::FourierReconstructor. Definition at line 611 of file reconstructor.h. Referenced by get_name(). |