#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 | |
Reconstructor * | NEW () |
Factory incorporation uses the pointer of this function. | |
Static Public Attributes | |
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. 00543 {};
|
|
Deconstructor calls free_memory().
Definition at line 548 of file reconstructor.h. 00548 { }
|
|
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 958 of file reconstructor.cpp. References EMAN::EMData::copy(), do_compare_slice_work(), do_insert_slice_work(), EMAN::EMData::get_attr(), 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(), and weight. 00959 { 00960 // Are these exceptions really necessary? (d.woolford) 00961 if (!input_slice) throw NullPointerException("EMData pointer (input image) is NULL"); 00962 00963 Transform * rotation; 00964 rotation = new Transform(arg); // assignment operator 00965 00966 EMData *slice; 00967 if (input_slice->get_attr_default("reconstruct_preproc",(int) 0)) slice=input_slice->copy(); 00968 else slice = preprocess_slice( input_slice, *rotation); 00969 00970 00971 // We must use only the rotational component of the transform, scaling, translation and mirroring 00972 // are not implemented in Fourier space, but are in preprocess_slice 00973 rotation->set_scale(1.0); 00974 rotation->set_mirror(false); 00975 rotation->set_trans(0,0,0); 00976 00977 // tmp_data->write_image("dbug.hdf",0); 00978 00979 // Remove the current slice first (not threadsafe, but otherwise performance would be awful) 00980 if (sub) do_insert_slice_work(slice, *rotation, -weight); 00981 00982 // Compare 00983 do_compare_slice_work(slice, *rotation,weight); 00984 00985 input_slice->set_attr("reconstruct_norm",slice->get_attr("reconstruct_norm")); 00986 input_slice->set_attr("reconstruct_absqual",slice->get_attr("reconstruct_absqual")); 00987 // input_slice->set_attr("reconstruct_qual",slice->get_attr("reconstruct_qual")); 00988 input_slice->set_attr("reconstruct_weight",slice->get_attr("reconstruct_weight")); 00989 00990 // Now put the slice back 00991 if (sub) do_insert_slice_work(slice, *rotation, weight); 00992 00993 00994 delete rotation; 00995 delete slice; 00996 00997 // image->update(); 00998 return 0; 00999 01000 }
|
|
A function to perform the nuts and bolts of comparing an image slice.
Reimplemented from EMAN::FourierReconstructor. Definition at line 1002 of file reconstructor.cpp. References dot(), dt, EMAN::EMData::get_data(), EMAN::Symmetry3D::get_symmetries(), EMAN::EMData::get_xsize(), EMAN::EMData::get_ysize(), pixel_at(), power(), EMAN::EMData::set_attr(), sqrt(), EMAN::Vec3f, weight, x, and y. Referenced by determine_slice_agreement(). 01003 { 01004 01005 float dt[3]; // This stores the complex and weight from the volume 01006 float dt2[2]; // This stores the local image complex 01007 float *dat = input_slice->get_data(); 01008 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]); 01009 01010 float inx=(float)(input_slice->get_xsize()); // x/y dimensions of the input image 01011 float iny=(float)(input_slice->get_ysize()); 01012 01013 double dot=0; // summed pixel*weight dot product 01014 double vweight=0; // sum of weights 01015 double power=0; // sum of inten*weight from volume 01016 double power2=0; // sum of inten*weight from image 01017 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) { 01018 Transform t3d = arg*(*it); 01019 for (int y = -iny/2; y < iny/2; y++) { 01020 for (int x = 0; x <= inx/2; x++) { 01021 if (x==0 && y==0) continue; // We don't want to use the Fourier origin 01022 01023 float rx = (float) x/(inx-2); // coords relative to Nyquist=.5 01024 float ry = (float) y/iny; 01025 01026 // if ((rx * rx + Util::square(ry - max_input_dim / 2)) > rl) 01027 // continue; 01028 01029 Vec3f coord(rx,ry,0); 01030 coord = coord*t3d; // transpose multiplication 01031 float xx = coord[0]; // transformed coordinates in terms of Nyquist 01032 float yy = coord[1]; 01033 float zz = coord[2]; 01034 01035 01036 if (fabs(xx)>0.5 || fabs(yy)>=0.5 || fabs(zz)>=0.5) continue; 01037 01038 // Map back to actual pixel coordinates in output volume 01039 xx=xx*(nx-2); 01040 yy=yy*ny; 01041 zz=zz*nz; 01042 01043 01044 int idx = (int)(x * 2 + inx*(y<0?iny+y:y)); 01045 dt2[0] = dat[idx]; 01046 dt2[1] = dat[idx+1]; 01047 01048 // value returned indirectly in dt 01049 if (!pixel_at(xx,yy,zz,dt) || dt[2]<=0) continue; 01050 01051 // printf("%f\t%f\t%f\t%f\t%f\n",dt[0],dt[1],dt[2],dt2[0],dt2[1]); 01052 dot+=(dt[0]*dt2[0]+dt[1]*dt2[1])*dt[2]; 01053 vweight+=dt[2]; 01054 power+=(dt[0]*dt[0]+dt[1]*dt[1])*dt[2]; 01055 power2+=(dt2[0]*dt2[0]+dt2[1]*dt2[1])*dt[2]; 01056 } 01057 } 01058 } 01059 01060 dot/=sqrt(power*power2); // normalize the dot product 01061 // input_slice->set_attr("reconstruct_norm",(float)(power2<=0?1.0:sqrt(power/power2)/(inx*iny))); 01062 input_slice->set_attr("reconstruct_norm",(float)(power2<=0?1.0:sqrt(power/power2))); 01063 input_slice->set_attr("reconstruct_absqual",(float)dot); 01064 float rw=weight<=0?1.0f:1.0f/weight; 01065 input_slice->set_attr("reconstruct_qual",(float)(dot*rw/((rw-1.0)*dot+1.0))); // here weight is a proxy for SNR 01066 input_slice->set_attr("reconstruct_weight",(float)vweight/(float)(subnx*subny*subnz)); 01067 // printf("** %g\t%g\t%g\t%g ##\n",dot,vweight,power,power2); 01068 //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))); 01069 }
|
|
A function to perform the nuts and bolts of inserting an image slice.
Reimplemented from EMAN::FourierReconstructor. Definition at line 903 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::Util::linear_interpolate(), sub(), EMAN::Vec3f, weight, x, and y. Referenced by determine_slice_agreement(), and insert_slice(). 00904 { 00905 00906 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]); 00907 00908 float inx=(float)(input_slice->get_xsize()); // x/y dimensions of the input image 00909 float iny=(float)(input_slice->get_ysize()); 00910 00911 int undo_wiener=(int)input_slice->get_attr_default("ctf_wiener_filtered",0); // indicates whether we need to undo a wiener filter before insertion 00912 // if (undo_wiener) throw UnexpectedBehaviorException("wiener_fourier does not yet accept already Wiener filtered class-averages. Suggest using ctf.auto averager for now."); 00913 00914 vector<float> snr=input_slice->get_attr("ctf_snr_total"); 00915 float sub=1.0; 00916 if (inweight<0) sub=-1.0; 00917 float weight; 00918 00919 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) { 00920 Transform t3d = arg*(*it); 00921 for (int y = -iny/2; y < iny/2; y++) { 00922 for (int x = 0; x <= inx/2; x++) { 00923 00924 float rx = (float) x/(inx-2.0f); // coords relative to Nyquist=.5 00925 float ry = (float) y/iny; 00926 00927 // This deals with the SNR weight 00928 float rn = hypot(rx,ry); 00929 if (rn>=.5) continue; // no SNR in the corners, and we're going to mask them later anyway 00930 rn*=snr.size()*2.0; 00931 int rni=(int)floor(rn); 00932 if (rni>=snr.size()-1) weight=snr[snr.size()-1]*sub; 00933 else { 00934 rn-=rni; 00935 weight=Util::linear_interpolate(snr[rni],snr[rni+1],rn); 00936 } 00937 // if (weight>500.0) printf("%f %d %d %f %f %d %f\n",weight,x,y,rx,ry,rni); 00938 00939 Vec3f coord(rx,ry,0); 00940 coord = coord*t3d; // transpose multiplication 00941 float xx = coord[0]; // transformed coordinates in terms of Nyquist 00942 float yy = coord[1]; 00943 float zz = coord[2]; 00944 00945 // Map back to real pixel coordinates in output volume 00946 xx=xx*(nx-2); 00947 yy=yy*ny; 00948 zz=zz*nz; 00949 00950 // printf("%f\n",weight); 00951 if (undo_wiener) inserter->insert_pixel(xx,yy,zz,(input_slice->get_complex_at(x,y))*((weight+1.0f)/weight),weight*sub); 00952 else inserter->insert_pixel(xx,yy,zz,input_slice->get_complex_at(x,y),weight*sub); 00953 } 00954 } 00955 } 00956 }
|
|
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 1145 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::normalize_threed(), EMAN::EMData::process_inplace(), EMAN::Dict::set_default(), EMAN::EMData::update(), and EMAN::EMData::write_image(). 01146 { 01147 01148 bool sqrtnorm=params.set_default("sqrtnorm",false); 01149 normalize_threed(sqrtnorm,true); // true is the wiener filter 01150 01151 if (doift) { 01152 image->do_ift_inplace(); 01153 image->depad(); 01154 image->process_inplace("xform.phaseorigin.tocenter"); 01155 } 01156 01157 image->update(); 01158 01159 if (params.has_key("savenorm") && strlen((const char *)params["savenorm"])>0) { 01160 if (tmp_data->get_ysize()%2==0 && tmp_data->get_zsize()%2==0) tmp_data->process_inplace("xform.fourierorigin.tocenter"); 01161 tmp_data->write_image((const char *)params["savenorm"]); 01162 } 01163 01164 delete tmp_data; 01165 tmp_data=0; 01166 EMData *ret=image; 01167 image=0; 01168 01169 return ret; 01170 }
|
|
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. 00592 {
00593 return NAME;
00594 }
|
|
Insert a slice into a 3D volume, in a given orientation.
Reimplemented from EMAN::FourierReconstructor. Definition at line 867 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(), EMAN::Transform::set_trans(), and weight. 00868 { 00869 // Are these exceptions really necessary? (d.woolford) 00870 if (!input_slice) throw NullPointerException("EMData pointer (input image) is NULL"); 00871 00872 Transform * rotation; 00873 /* if ( input_slice->has_attr("xform.projection") ) { 00874 rotation = (Transform*) (input_slice->get_attr("xform.projection")); // assignment operator 00875 } else {*/ 00876 rotation = new Transform(arg); // assignment operator 00877 // } 00878 00879 if (!input_slice->has_attr("ctf_snr_total")) 00880 throw NotExistingObjectException("ctf_snr_total","No SNR information present in class-average. Must use the ctf.auto or ctfw.auto averager."); 00881 00882 EMData *slice; 00883 if (input_slice->get_attr_default("reconstruct_preproc",(int) 0)) slice=input_slice->copy(); 00884 else slice = preprocess_slice( input_slice, *rotation); 00885 00886 00887 // We must use only the rotational component of the transform, scaling, translation and mirroring 00888 // are not implemented in Fourier space, but are in preprocess_slice 00889 rotation->set_scale(1.0); 00890 rotation->set_mirror(false); 00891 rotation->set_trans(0,0,0); 00892 00893 // Finally to the pixel wise slice insertion 00894 do_insert_slice_work(slice, *rotation, weight); 00895 00896 delete rotation; rotation=0; 00897 delete slice; 00898 00899 // image->update(); 00900 return 0; 00901 }
|
|
Factory incorporation uses the pointer of this function.
Reimplemented from EMAN::FourierReconstructor. Definition at line 606 of file reconstructor.h. 00607 { 00608 return new WienerFourierReconstructor(); 00609 }
|
|
Disallow assignment.
|
|
This is a mode-2 pixel extractor.
Reimplemented from EMAN::FourierReconstructor. Definition at line 1071 of file reconstructor.cpp. References dt, EMAN::Util::fast_exp(), EMAN::EMData::get_complex_index(), EMAN::EMData::get_complex_index_fast(), EMAN::EMData::get_data(), EMAN::Util::hypot3sq(), norm(), and rdata. Referenced by do_compare_slice_work(). 01072 { 01073 int x0 = (int) floor(xx); 01074 int y0 = (int) floor(yy); 01075 int z0 = (int) floor(zz); 01076 01077 float *rdata=image->get_data(); 01078 float *norm=tmp_data->get_data(); 01079 float normsum=0,normsum2=0; 01080 01081 dt[0]=dt[1]=dt[2]=0.0; 01082 01083 if (nx==subnx) { // normal full reconstruction 01084 if (x0<-nx2-1 || y0<-ny2-1 || z0<-nz2-1 || x0>nx2 || y0>ny2 || z0>nz2 ) return false; 01085 01086 // no error checking on add_complex_fast, so we need to be careful here 01087 int x1=x0+1; 01088 int y1=y0+1; 01089 int z1=z0+1; 01090 if (x0<-nx2) x0=-nx2; 01091 if (x1>nx2) x1=nx2; 01092 if (y0<-ny2) y0=-ny2; 01093 if (y1>ny2) y1=ny2; 01094 if (z0<-nz2) z0=-nz2; 01095 if (z1>nz2) z1=nz2; 01096 01097 size_t idx=0; 01098 float r, gg; 01099 for (int k = z0 ; k <= z1; k++) { 01100 for (int j = y0 ; j <= y1; j++) { 01101 for (int i = x0; i <= x1; i ++) { 01102 r = Util::hypot3sq((float) i - xx, j - yy, k - zz); 01103 idx=image->get_complex_index_fast(i,j,k); 01104 gg = Util::fast_exp(-r / EMConsts::I2G); 01105 01106 dt[0]+=gg*rdata[idx]; 01107 dt[1]+=(i<0?-1.0f:1.0f)*gg*rdata[idx+1]; 01108 dt[2]+=norm[idx/2]*gg; 01109 normsum2+=gg; 01110 normsum+=gg*norm[idx/2]; 01111 } 01112 } 01113 } 01114 if (normsum==0) return false; 01115 dt[0]/=normsum; 01116 dt[1]/=normsum; 01117 dt[2]/=normsum2; 01118 // 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]); 01119 return true; 01120 } 01121 else { // for subvolumes, not optimized yet 01122 size_t idx; 01123 float r, gg; 01124 for (int k = z0 ; k <= z0 + 1; k++) { 01125 for (int j = y0 ; j <= y0 + 1; j++) { 01126 for (int i = x0; i <= x0 + 1; i ++) { 01127 r = Util::hypot3sq((float) i - xx, j - yy, k - zz); 01128 idx=image->get_complex_index(i,j,k,subx0,suby0,subz0,nx,ny,nz); 01129 gg = Util::fast_exp(-r / EMConsts::I2G)*norm[idx/2]; 01130 01131 dt[0]+=gg*rdata[idx]; 01132 dt[1]+=(i<0?-1.0f:1.0f)*gg*rdata[idx+1]; 01133 dt[2]+=norm[idx/2]; 01134 normsum+=gg; 01135 } 01136 } 01137 } 01138 01139 if (normsum==0) return false; 01140 return true; 01141 } 01142 }
|
|
Reimplemented from EMAN::FourierReconstructor. Definition at line 75 of file reconstructor.cpp. |