#include <reconstructor.h>
Inheritance diagram for EMAN::FourierReconstructor:
Public Member Functions | ||||
FourierReconstructor () | ||||
Default constructor calls load_default_settings(). | ||||
virtual | ~FourierReconstructor () | |||
Deconstructor calls free_memory(). | ||||
virtual void | setup () | |||
Setup the Fourier reconstructor
| ||||
virtual void | setup_seed (EMData *seed, float seed_weight) | |||
Initialize the reconstructor with a seed volume. | ||||
virtual EMData * | preprocess_slice (const EMData *const slice, const Transform &t=Transform()) | |||
Preprocess the slice prior to insertion into the 3D volume this Fourier tranforms the slice and make sure all the pixels are in the right position it always returns a copy of the provided slice, so it should be deleted by someone eventually. | ||||
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. | ||||
virtual TypeDict | get_param_types () const | |||
Get the parameter types of this object. | ||||
Static Public Member Functions | ||||
static Reconstructor * | NEW () | |||
Factory incorporation uses the pointer of this function. | ||||
Static Public Attributes | ||||
static const string | NAME = "fourier" | |||
Protected Member Functions | ||||
virtual void | load_default_settings () | |||
Load default settings. | ||||
virtual void | free_memory () | |||
Frees the memory owned by this object (but not parent objects) Deletes the FourierPixelInserter3D pointer. | ||||
virtual void | load_inserter () | |||
Load the pixel inserter based on the information in params. | ||||
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. | ||||
Protected Attributes | ||||
FourierPixelInserter3D * | inserter | |||
A pixel inserter pointer which inserts pixels into the 3D volume using one of a variety of insertion methods. | ||||
Private Member Functions | ||||
FourierReconstructor (const FourierReconstructor &that) | ||||
Disallow copy construction. | ||||
FourierReconstructor & | operator= (const FourierReconstructor &) | |||
Disallow assignment. |
The client creates a Fourier reconstructor to insert real images into a 3D volume. The return image is a real space image
This reconstructor is based on EMAN1's Fourier reconstructor with a handful of modifications including 1. - Fourier ring correlation (FRC) as opposed to the mean phase residual is used to estimate slice quality. The FRC of the slice in the 3D volume is determined - but the slice is removed from the 3D volume before doing this so the score reflects the extent to which the slice agrees with the contribution of the other slices in the 3D volume. The FRC is converted to SNR using the relationship described by Penczek ( Three-dimensional spectral signal to noise ratio for a class of reconstruction algorithms, JSB 2002 138 (24-46) ) FRC = S/(sqrt(S+N1)sqrt(S+N2)) Where N1 is the noise in the slice of the 3D volume and N2 is the noise in the image slice being inserted. We make the assumption that the noise in the 3D volume is 0 (N1=0) to get FRC^2 = SNR/(1+SNR) which gives a spectral SNR plot - we then divide each SNR value by the number of particles in the class average (seeing as SNR should scale linearly with the number of particles) to get the estimated SNR per contributing particle in this class average. If the particles that have been averaged are not homogenous this score should be low etc. The scaled SNR curve is then converted back to a FRC curve and integrated. This integral is the similarity metric, and depends on how far information extends to in Fourier space - typical values range from 0.05 to 0.2, but can vary substantially depending on the data.
2 - Uses half of the memory used by EMAN1's equivalent reconstruction algorithm
Reconstructor* r = Factory<Reconstructor>::get("fourier", params); r->setup(); for k in 0:num_iterations-1 // First do a round of slice quality (metric) determination - only possible if a 3D volume has // already been generated (k>0) if ( k > 0 ) // Determine the agreement of the slices with the previous reconstructed volume (in memory) for i in 0:num_slices-1 r->determine_slice_agreement(image[i], image[i].euler_orientation); // Insert the slices into the 3D volume // Will decide not to insert the slice if the its "quality" is not good enough for i in 0:num_slices-1 int failure = r->insert_slice(image[i], image[i].euler_orientation); if ( failure ) cout << "Slice was not inserted due to poor quality" << endl; // Get the resulting volume EMData* result = r->finish(); result->write_image("threed.mrc");
Definition at line 363 of file reconstructor.h.
|
Default constructor calls load_default_settings().
Definition at line 369 of file reconstructor.h. References load_default_settings(). Referenced by NEW(). 00369 { load_default_settings(); }
|
|
Deconstructor calls free_memory().
Definition at line 374 of file reconstructor.h. References free_memory(). 00374 { free_memory(); }
|
|
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::Reconstructor. Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 620 of file reconstructor.cpp. References EMAN::EMData::copy(), do_compare_slice_work(), do_insert_slice_work(), EMAN::EMData::get_attr_default(), NullPointerException, preprocess_slice(), EMAN::EMData::set_attr(), EMAN::Transform::set_mirror(), EMAN::Transform::set_scale(), and EMAN::Transform::set_trans(). 00621 { 00622 // Are these exceptions really necessary? (d.woolford) 00623 if (!input_slice) throw NullPointerException("EMData pointer (input image) is NULL"); 00624 00625 Transform * rotation; 00626 rotation = new Transform(arg); // assignment operator 00627 00628 EMData *slice; 00629 if (input_slice->get_attr_default("reconstruct_preproc",(int) 0)) slice=input_slice->copy(); 00630 else slice = preprocess_slice( input_slice, *rotation); 00631 00632 00633 // We must use only the rotational component of the transform, scaling, translation and mirroring 00634 // are not implemented in Fourier space, but are in preprocess_slice 00635 rotation->set_scale(1.0); 00636 rotation->set_mirror(false); 00637 rotation->set_trans(0,0,0); 00638 00639 // Remove the current slice first (not threadsafe, but otherwise performance would be awful) 00640 if (sub) do_insert_slice_work(slice, *rotation, -weight); 00641 00642 // Compare 00643 do_compare_slice_work(slice, *rotation,weight); 00644 00645 input_slice->set_attr("reconstruct_norm",slice->get_attr("reconstruct_norm")); 00646 input_slice->set_attr("reconstruct_absqual",slice->get_attr("reconstruct_absqual")); 00647 // input_slice->set_attr("reconstruct_qual",slice->get_attr("reconstruct_qual")); 00648 input_slice->set_attr("reconstruct_weight",slice->get_attr("reconstruct_weight")); 00649 00650 // Now put the slice back 00651 if (sub) do_insert_slice_work(slice, *rotation, weight); 00652 00653 00654 delete rotation; 00655 delete slice; 00656 00657 // image->update(); 00658 return 0; 00659 00660 }
|
|
A function to perform the nuts and bolts of comparing an image slice.
Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 662 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(). 00663 { 00664 00665 float dt[3]; // This stores the complex and weight from the volume 00666 float dt2[2]; // This stores the local image complex 00667 float *dat = input_slice->get_data(); 00668 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]); 00669 00670 float inx=(float)(input_slice->get_xsize()); // x/y dimensions of the input image 00671 float iny=(float)(input_slice->get_ysize()); 00672 00673 double dot=0; // summed pixel*weight dot product 00674 double vweight=0; // sum of weights 00675 double power=0; // sum of inten*weight from volume 00676 double power2=0; // sum of inten*weight from image 00677 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) { 00678 Transform t3d = arg*(*it); 00679 for (int y = -iny/2; y < iny/2; y++) { 00680 for (int x = 0; x <= inx/2; x++) { 00681 if (x==0 && y==0) continue; // We don't want to use the Fourier origin 00682 00683 float rx = (float) x/(inx-2); // coords relative to Nyquist=.5 00684 float ry = (float) y/iny; 00685 00686 // if ((rx * rx + Util::square(ry - max_input_dim / 2)) > rl) 00687 // continue; 00688 00689 Vec3f coord(rx,ry,0); 00690 coord = coord*t3d; // transpose multiplication 00691 float xx = coord[0]; // transformed coordinates in terms of Nyquist 00692 float yy = coord[1]; 00693 float zz = coord[2]; 00694 00695 00696 if (fabs(xx)>0.5 || fabs(yy)>=0.5 || fabs(zz)>=0.5) continue; 00697 00698 // Map back to actual pixel coordinates in output volume 00699 xx=xx*(nx-2); 00700 yy=yy*ny; 00701 zz=zz*nz; 00702 00703 00704 int idx = (int)(x * 2 + inx*(y<0?iny+y:y)); 00705 dt2[0] = dat[idx]; 00706 dt2[1] = dat[idx+1]; 00707 00708 // value returned indirectly in dt 00709 if (!pixel_at(xx,yy,zz,dt) || dt[2]==0) continue; 00710 00711 // printf("%f\t%f\t%f\t%f\t%f\n",dt[0],dt[1],dt[2],dt2[0],dt2[1]); 00712 dot+=(dt[0]*dt2[0]+dt[1]*dt2[1])*dt[2]; 00713 vweight+=dt[2]; 00714 power+=(dt[0]*dt[0]+dt[1]*dt[1])*dt[2]; 00715 power2+=(dt2[0]*dt2[0]+dt2[1]*dt2[1])*dt[2]; 00716 } 00717 } 00718 } 00719 00720 dot/=sqrt(power*power2); // normalize the dot product 00721 // input_slice->set_attr("reconstruct_norm",(float)(power2<=0?1.0:sqrt(power/power2)/(inx*iny))); 00722 input_slice->set_attr("reconstruct_norm",(float)(power2<=0?1.0:sqrt(power/power2))); 00723 input_slice->set_attr("reconstruct_absqual",(float)dot); 00724 float rw=weight<=0?1.0f:1.0f/weight; 00725 input_slice->set_attr("reconstruct_qual",(float)(dot*rw/((rw-1.0)*dot+1.0))); // here weight is a proxy for SNR 00726 input_slice->set_attr("reconstruct_weight",(float)vweight/(float)(subnx*subny*subnz)); 00727 // printf("** %g\t%g\t%g\t%g ##\n",dot,vweight,power,power2); 00728 //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))); 00729 }
|
|
A function to perform the nuts and bolts of inserting an image slice.
Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 570 of file reconstructor.cpp. References EMAN::EMData::get_complex_at(), EMAN::Symmetry3D::get_symmetries(), EMAN::EMData::get_xsize(), EMAN::EMData::get_ysize(), EMAN::FourierPixelInserter3D::insert_pixel(), inserter, EMAN::ReconstructorVolumeData::nx, EMAN::ReconstructorVolumeData::ny, EMAN::ReconstructorVolumeData::nz, EMAN::FactoryBase::params, x, and y. Referenced by determine_slice_agreement(), and insert_slice(). 00571 { 00572 // Reload the inserter if the mode has changed 00573 // string mode = (string) params["mode"]; 00574 // if ( mode != inserter->get_name() ) load_inserter(); 00575 00576 // int y_in = input_slice->get_ysize(); 00577 // int x_in = input_slice->get_xsize(); 00578 // // Adjust the dimensions to account for odd and even ffts 00579 // if (input_slice->is_fftodd()) x_in -= 1; 00580 // else x_in -= 2; 00581 00582 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]); 00583 00584 float inx=(float)(input_slice->get_xsize()); // x/y dimensions of the input image 00585 float iny=(float)(input_slice->get_ysize()); 00586 00587 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) { 00588 Transform t3d = arg*(*it); 00589 for (int y = -iny/2; y < iny/2; y++) { 00590 for (int x = 0; x <= inx/2; x++) { 00591 00592 float rx = (float) x/(inx-2.0f); // coords relative to Nyquist=.5 00593 float ry = (float) y/iny; 00594 00595 Vec3f coord(rx,ry,0); 00596 coord = coord*t3d; // transpose multiplication 00597 float xx = coord[0]; // transformed coordinates in terms of Nyquist 00598 float yy = coord[1]; 00599 float zz = coord[2]; 00600 00601 // Map back to real pixel coordinates in output volume 00602 xx=xx*(nx-2); 00603 yy=yy*ny; 00604 zz=zz*nz; 00605 00606 // if (x==10 && y==0) printf("10,0 -> %1.2f,%1.2f,%1.2f\t(%5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f) %1.0f %d\n", 00607 // xx,yy,zz,t3d.at(0,0),t3d.at(0,1),t3d.at(0,2),t3d.at(1,0),t3d.at(1,1),t3d.at(1,2),t3d.at(2,0),t3d.at(2,1),t3d.at(2,2),inx,nx); 00608 // if (x==0 && y==10) printf("0,10 -> %1.2f,%1.2f,%1.2f\t(%5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f)\n", 00609 // xx,yy,zz,t3d.at(0,0),t3d.at(0,1),t3d.at(0,2),t3d.at(1,0),t3d.at(1,1),t3d.at(1,2),t3d.at(2,0),t3d.at(2,1),t3d.at(2,2)); 00610 00611 //printf("%3.1f %3.1f %3.1f\t %1.4f %1.4f\t%1.4f\n",xx,yy,zz,input_slice->get_complex_at(x,y).real(),input_slice->get_complex_at(x,y).imag(),weight); 00612 // if (floor(xx)==45 && floor(yy)==45 &&floor(zz)==0) printf("%d. 45 45 0\t %d %d\t %1.4f %1.4f\t%1.4f\n",(int)input_slice->get_attr("n"),x,y,input_slice->get_complex_at(x,y).real(),input_slice->get_complex_at(x,y).imag(),weight); 00613 // if (floor(xx)==21 && floor(yy)==21 &&floor(zz)==0) printf("%d. 21 21 0\t %d %d\t %1.4f %1.4f\t%1.4f\n",(int)input_slice->get_attr("n"),x,y,input_slice->get_complex_at(x,y).real(),input_slice->get_complex_at(x,y).imag(),weight); 00614 inserter->insert_pixel(xx,yy,zz,input_slice->get_complex_at(x,y),weight); 00615 } 00616 } 00617 } 00618 }
|
|
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::Reconstructor. Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 805 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(). 00806 { 00807 // float *norm = tmp_data->get_data(); 00808 // float *rdata = image->get_data(); 00809 00810 bool sqrtnorm=params.set_default("sqrtnorm",false); 00811 normalize_threed(sqrtnorm); 00812 00813 // tmp_data->write_image("density.mrc"); 00814 00815 // we may as well delete the tmp data now... it saves memory and the calling program might 00816 // need memory after it gets the return volume. 00817 // If this delete didn't happen now, it would happen when the deconstructor was called --david 00818 // no longer a good idea with the new iterative scheme -- steve 00819 // if ( tmp_data != 0 ) 00820 // { 00821 // delete tmp_data; 00822 // tmp_data = 0; 00823 // } 00824 00825 /* image->process_inplace("xform.fourierorigin.tocorner");*/ 00826 00827 if (doift) { 00828 image->do_ift_inplace(); 00829 image->depad(); 00830 image->process_inplace("xform.phaseorigin.tocenter"); 00831 } 00832 // If the image was padded it should be the original size, as the client would expect 00833 // I blocked the rest, it is almost certainly incorrect PAP 07/31/08 00834 // No, it's not incorrect. You are wrong. You have the meaning of nx mixed up. DSAW 09/23/cd 00835 // This should now be handled in the calling program --steve 11/03/09 00836 // bool is_fftodd = (nx % 2 == 1); 00837 // if ( (nx-2*(!is_fftodd)) != output_x || ny != output_y || nz != output_z ) 00838 // { 00839 // FloatPoint origin( (nx-output_x)/2, (ny-output_y)/2, (nz-output_z)/2 ); 00840 // FloatSize region_size( output_x, output_y, output_z); 00841 // Region clip_region( origin, region_size ); 00842 // image->clip_inplace( clip_region ); 00843 // } 00844 00845 // Should be an "if (verbose)" here or something 00846 //print_stats(quality_scores); 00847 00848 image->update(); 00849 00850 if (params.has_key("savenorm") && strlen((const char *)params["savenorm"])>0) { 00851 if (tmp_data->get_ysize()%2==0 && tmp_data->get_zsize()%2==0) tmp_data->process_inplace("xform.fourierorigin.tocenter"); 00852 tmp_data->write_image((const char *)params["savenorm"]); 00853 } 00854 00855 delete tmp_data; 00856 tmp_data=0; 00857 EMData *ret=image; 00858 image=0; 00859 00860 return ret; 00861 }
|
|
Frees the memory owned by this object (but not parent objects) Deletes the FourierPixelInserter3D pointer.
Reimplemented from EMAN::ReconstructorVolumeData. Definition at line 323 of file reconstructor.cpp. References EMAN::ReconstructorVolumeData::image, inserter, and EMAN::ReconstructorVolumeData::tmp_data. Referenced by ~FourierReconstructor(). 00324 { 00325 if (image) { delete image; image=0; } 00326 if (tmp_data) { delete tmp_data; tmp_data=0; } 00327 if ( inserter != 0 ) 00328 { 00329 delete inserter; 00330 inserter = 0; 00331 } 00332 }
|
|
Get the one line description of the reconstructor.
Implements EMAN::FactoryBase. Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 448 of file reconstructor.h. 00449 { 00450 return "Reconstruction via direct Fourier methods using one of a variety of different kernels, most of which are Gaussian based"; 00451 }
|
|
Get the unique name of the reconstructor.
Implements EMAN::FactoryBase. Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 441 of file reconstructor.h. References NAME. 00442 { 00443 return NAME; 00444 }
|
|
Get the parameter types of this object.
Implements EMAN::FactoryBase. Definition at line 464 of file reconstructor.h. References EMAN::EMObject::BOOL, EMAN::EMObject::INTARRAY, EMAN::TypeDict::put(), and EMAN::EMObject::STRING. 00465 { 00466 TypeDict d; 00467 d.put("size", EMObject::INTARRAY, "Required. The dimensions of the real-space output volume, including any padding (must be handled by the calling application). Assumed that apix x/y/z identical."); 00468 d.put("sym", EMObject::STRING, "Optional. The symmetry of the reconstructed volume, c?, d?, oct, tet, icos, h?. Default is c1, ie - an asymmetric object"); 00469 d.put("mode", EMObject::STRING, "Optional. Fourier pixel insertion mode name (nearest_neighbor, gauss_2, gauss_3, gauss_5, gauss_5_slow, gypergeom_5, experimental) gauss_2 is the default."); 00470 d.put("sqrtnorm", EMObject::BOOL, "Optional. When normalizing, additionally divides by the sqrt of the normalization factor to damp exaggerated features. Is this justifyable ? No idea (yet). Default is false."); 00471 d.put("verbose", EMObject::BOOL, "Optional. Toggles writing useful information to standard out. Default is false."); 00472 d.put("subvolume",EMObject::INTARRAY, "Optional. (xorigin,yorigin,zorigin,xsize,ysize,zsize) all in Fourier pixels. Useful for parallelism."); 00473 d.put("savenorm",EMObject::STRING, "Debug. Will cause the normalization volume to be written directly to the specified file when finish() is called."); 00474 return d; 00475 }
|
|
Insert a slice into a 3D volume, in a given orientation.
Reimplemented from EMAN::Reconstructor. Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 537 of file reconstructor.cpp. References EMAN::EMData::copy(), do_insert_slice_work(), EMAN::EMData::get_attr_default(), NullPointerException, preprocess_slice(), EMAN::Transform::set_mirror(), EMAN::Transform::set_scale(), and EMAN::Transform::set_trans(). 00538 { 00539 // Are these exceptions really necessary? (d.woolford) 00540 if (!input_slice) throw NullPointerException("EMData pointer (input image) is NULL"); 00541 00542 Transform * rotation; 00543 /* if ( input_slice->has_attr("xform.projection") ) { 00544 rotation = (Transform*) (input_slice->get_attr("xform.projection")); // assignment operator 00545 } else {*/ 00546 rotation = new Transform(arg); // assignment operator 00547 // } 00548 00549 EMData *slice; 00550 if (input_slice->get_attr_default("reconstruct_preproc",(int) 0)) slice=input_slice->copy(); 00551 else slice = preprocess_slice( input_slice, *rotation); 00552 00553 00554 // We must use only the rotational component of the transform, scaling, translation and mirroring 00555 // are not implemented in Fourier space, but are in preprocess_slice 00556 rotation->set_scale(1.0); 00557 rotation->set_mirror(false); 00558 rotation->set_trans(0,0,0); 00559 00560 // Finally to the pixel wise slice insertion 00561 do_insert_slice_work(slice, *rotation, weight); 00562 00563 delete rotation; rotation=0; 00564 delete slice; 00565 00566 // image->update(); 00567 return 0; 00568 }
|
|
Load default settings.
Definition at line 316 of file reconstructor.cpp. References EMAN::ReconstructorVolumeData::image, inserter, and EMAN::ReconstructorVolumeData::tmp_data. Referenced by FourierReconstructor().
|
|
Load the pixel inserter based on the information in params.
Definition at line 336 of file reconstructor.cpp. References EMAN::Factory< T >::get(), EMAN::EMData::get_data(), EMAN::ReconstructorVolumeData::image, EMAN::FourierPixelInserter3D::init(), inserter, EMAN::FactoryBase::params, and EMAN::ReconstructorVolumeData::tmp_data. Referenced by setup(), and setup_seed(). 00337 { 00338 // ss 00339 // string mode = (string)params["mode"]; 00340 Dict parms; 00341 parms["data"] = image; 00342 parms["norm"] = tmp_data->get_data(); 00343 // These aren't necessary because we deal with them before calling the inserter 00344 // parms["subnx"] = nx; 00345 // parms["subny"] = ny; 00346 // parms["subnx"] = nz; 00347 // parms["subx0"] = x0; 00348 // parms["suby0"] = y0; 00349 // parms["subz0"] = z0; 00350 00351 if ( inserter != 0 ) 00352 { 00353 delete inserter; 00354 } 00355 00356 inserter = Factory<FourierPixelInserter3D>::get((string)params["mode"], parms); 00357 inserter->init(); 00358 }
|
|
Factory incorporation uses the pointer of this function.
Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 456 of file reconstructor.h. References FourierReconstructor(). 00457 { 00458 return new FourierReconstructor(); 00459 }
|
|
Disallow assignment.
|
|
This is a mode-2 pixel extractor.
Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 731 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(). 00732 { 00733 int x0 = (int) floor(xx); 00734 int y0 = (int) floor(yy); 00735 int z0 = (int) floor(zz); 00736 00737 float *rdata=image->get_data(); 00738 float *norm=tmp_data->get_data(); 00739 float normsum=0,normsum2=0; 00740 00741 dt[0]=dt[1]=dt[2]=0.0; 00742 00743 if (nx==subnx) { // normal full reconstruction 00744 if (x0<-nx2-1 || y0<-ny2-1 || z0<-nz2-1 || x0>nx2 || y0>ny2 || z0>nz2 ) return false; 00745 00746 // no error checking on add_complex_fast, so we need to be careful here 00747 int x1=x0+1; 00748 int y1=y0+1; 00749 int z1=z0+1; 00750 if (x0<-nx2) x0=-nx2; 00751 if (x1>nx2) x1=nx2; 00752 if (y0<-ny2) y0=-ny2; 00753 if (y1>ny2) y1=ny2; 00754 if (z0<-nz2) z0=-nz2; 00755 if (z1>nz2) z1=nz2; 00756 00757 size_t idx=0; 00758 float r, gg; 00759 for (int k = z0 ; k <= z1; k++) { 00760 for (int j = y0 ; j <= y1; j++) { 00761 for (int i = x0; i <= x1; i ++) { 00762 r = Util::hypot3sq((float) i - xx, j - yy, k - zz); 00763 idx=image->get_complex_index_fast(i,j,k); 00764 gg = Util::fast_exp(-r / EMConsts::I2G); 00765 00766 dt[0]+=gg*rdata[idx]; 00767 dt[1]+=(i<0?-1.0f:1.0f)*gg*rdata[idx+1]; 00768 dt[2]+=norm[idx/2]*gg; 00769 normsum2+=gg; 00770 normsum+=gg*norm[idx/2]; 00771 } 00772 } 00773 } 00774 if (normsum==0) return false; 00775 dt[0]/=normsum; 00776 dt[1]/=normsum; 00777 dt[2]/=normsum2; 00778 // 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]); 00779 return true; 00780 } 00781 else { // for subvolumes, not optimized yet 00782 size_t idx; 00783 float r, gg; 00784 for (int k = z0 ; k <= z0 + 1; k++) { 00785 for (int j = y0 ; j <= y0 + 1; j++) { 00786 for (int i = x0; i <= x0 + 1; i ++) { 00787 r = Util::hypot3sq((float) i - xx, j - yy, k - zz); 00788 idx=image->get_complex_index(i,j,k,subx0,suby0,subz0,nx,ny,nz); 00789 gg = Util::fast_exp(-r / EMConsts::I2G)*norm[idx/2]; 00790 00791 dt[0]+=gg*rdata[idx]; 00792 dt[1]+=(i<0?-1.0f:1.0f)*gg*rdata[idx+1]; 00793 dt[2]+=norm[idx/2]; 00794 normsum+=gg; 00795 } 00796 } 00797 } 00798 00799 if (normsum==0) return false; 00800 return true; 00801 } 00802 }
|
|
Preprocess the slice prior to insertion into the 3D volume this Fourier tranforms the slice and make sure all the pixels are in the right position it always returns a copy of the provided slice, so it should be deleted by someone eventually.
Reimplemented from EMAN::Reconstructor. Definition at line 509 of file reconstructor.cpp. References EMAN::EMData::copy(), EMAN::EMData::do_fft_inplace(), EMAN::EMData::get_xsize(), EMAN::EMData::get_ysize(), EMAN::Transform::is_identity(), EMAN::EMData::mult(), EMAN::EMData::process(), EMAN::EMData::process_inplace(), EMAN::EMData::set_attr(), EMAN::Transform::set_rotation(), and sqrt(). Referenced by EMAN::WienerFourierReconstructor::determine_slice_agreement(), determine_slice_agreement(), EMAN::WienerFourierReconstructor::insert_slice(), and insert_slice(). 00510 { 00511 // Shift the image pixels so the real space origin is now located at the phase origin (at the bottom left of the image) 00512 EMData* return_slice = 0; 00513 Transform tmp(t); 00514 tmp.set_rotation(Dict("type","eman")); // resets the rotation to 0 implicitly, this way we only do 2d translation,scaling and mirroring 00515 00516 if (tmp.is_identity()) return_slice=slice->copy(); 00517 else return_slice = slice->process("xform",Dict("transform",&tmp)); 00518 00519 return_slice->process_inplace("xform.phaseorigin.tocorner"); 00520 00521 // printf("@@@ %d\n",(int)return_slice->get_attr("nx")); 00522 // Fourier transform the slice 00523 return_slice->do_fft_inplace(); 00524 00525 // printf("%d\n",(int)return_slice->get_attr("nx")); 00526 00527 return_slice->mult((float)sqrt(1.0f/(return_slice->get_ysize())*return_slice->get_xsize())); 00528 00529 // Shift the Fourier transform so that it's origin is in the center (bottom) of the image. 00530 // return_slice->process_inplace("xform.fourierorigin.tocenter"); 00531 00532 return_slice->set_attr("reconstruct_preproc",(int)1); 00533 return return_slice; 00534 }
|
|
Setup the Fourier reconstructor
Implements EMAN::Reconstructor. Definition at line 360 of file reconstructor.cpp. References EMAN::Dict::has_key(), EMAN::ReconstructorVolumeData::image, ImageDimensionException, is_fftodd(), load_inserter(), EMAN::ReconstructorVolumeData::nx, EMAN::ReconstructorVolumeData::nx2, EMAN::ReconstructorVolumeData::ny, EMAN::ReconstructorVolumeData::ny2, EMAN::ReconstructorVolumeData::nz, EMAN::ReconstructorVolumeData::nz2, EMAN::FactoryBase::params, EMAN::EMData::set_attr(), EMAN::EMData::set_complex(), EMAN::Dict::set_default(), EMAN::EMData::set_fftodd(), EMAN::EMData::set_ri(), EMAN::EMData::set_size(), sub(), EMAN::ReconstructorVolumeData::subnx, EMAN::ReconstructorVolumeData::subny, EMAN::ReconstructorVolumeData::subnz, EMAN::ReconstructorVolumeData::subx0, EMAN::ReconstructorVolumeData::suby0, EMAN::ReconstructorVolumeData::subz0, EMAN::ReconstructorVolumeData::tmp_data, EMAN::EMData::to_zero(), and EMAN::EMData::update(). 00361 { 00362 // default setting behavior - does not override if the parameter is already set 00363 params.set_default("mode","gauss_2"); 00364 00365 vector<int> size=params["size"]; 00366 00367 nx = size[0]; 00368 ny = size[1]; 00369 nz = size[2]; 00370 nx2=nx/2-1; 00371 ny2=ny/2; 00372 nz2=nz/2; 00373 00374 00375 // Adjust nx if for Fourier transform even odd issues 00376 bool is_fftodd = (nx % 2 == 1); 00377 // The Fourier transform requires one extra pixel in the x direction, 00378 // which is two spaces in memory, one each for the complex and the 00379 // real components 00380 nx += 2-is_fftodd; 00381 00382 if (params.has_key("subvolume")) { 00383 vector<int> sub=params["subvolume"]; 00384 subx0=sub[0]; 00385 suby0=sub[1]; 00386 subz0=sub[2]; 00387 subnx=sub[3]; 00388 subny=sub[4]; 00389 subnz=sub[5]; 00390 00391 if (subx0<0 || suby0<0 || subz0<0 || subx0+subnx>nx || suby0+subny>ny || subz0+subnz>nz) 00392 throw ImageDimensionException("The subvolume cannot extend outside the reconstructed volume"); 00393 00394 } 00395 else { 00396 subx0=suby0=subz0=0; 00397 subnx=nx; 00398 subny=ny; 00399 subnz=nz; 00400 } 00401 00402 00403 // Odd dimension support is here atm, but not above. 00404 if (image) delete image; 00405 image = new EMData(); 00406 image->set_size(subnx, subny, subnz); 00407 image->set_complex(true); 00408 image->set_fftodd(is_fftodd); 00409 image->set_ri(true); 00410 image->to_zero(); 00411 00412 if (params.has_key("subvolume")) { 00413 image->set_attr("subvolume_x0",subx0); 00414 image->set_attr("subvolume_y0",suby0); 00415 image->set_attr("subvolume_z0",subz0); 00416 image->set_attr("subvolume_full_nx",nx); 00417 image->set_attr("subvolume_full_ny",ny); 00418 image->set_attr("subvolume_full_nz",nz); 00419 } 00420 00421 if (tmp_data) delete tmp_data; 00422 tmp_data = new EMData(); 00423 tmp_data->set_size(subnx/2, subny, subnz); 00424 tmp_data->to_zero(); 00425 tmp_data->update(); 00426 00427 load_inserter(); 00428 00429 if ( (bool) params["quiet"] == false ) 00430 { 00431 cout << "3D Fourier dimensions are " << nx << " " << ny << " " << nz << endl; 00432 cout << "3D Fourier subvolume is " << subnx << " " << subny << " " << subnz << endl; 00433 cout << "You will require approximately " << setprecision(3) << (subnx*subny*subnz*sizeof(float)*1.5)/1000000000.0 << "GB of memory to reconstruct this volume" << endl; 00434 } 00435 }
|
|
Initialize the reconstructor with a seed volume. This can be used to provide some 'default' value when there is missing data in Fourier space. The passed 'seed' must be of the appropriate padded size, must be in Fourier space, and the same EMData* object will be returned by finish(), meaning the Reconstructor is implicitly taking ownership of the object. However, in Python, this means the seed may be passed in without copying, as the same EMData will be coming back out at the end. The seed_weight determines how 'strong' the seed volume should be as compared to other inserted slices in Fourier space.
Reimplemented from EMAN::Reconstructor. Definition at line 437 of file reconstructor.cpp. References EMAN::EMData::get_xsize(), EMAN::EMData::get_ysize(), EMAN::EMData::get_zsize(), EMAN::Dict::has_key(), EMAN::ReconstructorVolumeData::image, ImageDimensionException, EMAN::EMData::is_complex(), is_fftodd(), load_inserter(), EMAN::ReconstructorVolumeData::nx, EMAN::ReconstructorVolumeData::nx2, EMAN::ReconstructorVolumeData::ny, EMAN::ReconstructorVolumeData::ny2, EMAN::ReconstructorVolumeData::nz, EMAN::ReconstructorVolumeData::nz2, EMAN::FactoryBase::params, EMAN::EMData::set_attr(), EMAN::Dict::set_default(), EMAN::EMData::set_size(), sub(), EMAN::ReconstructorVolumeData::subnx, EMAN::ReconstructorVolumeData::subny, EMAN::ReconstructorVolumeData::subnz, EMAN::ReconstructorVolumeData::subx0, EMAN::ReconstructorVolumeData::suby0, EMAN::ReconstructorVolumeData::subz0, EMAN::ReconstructorVolumeData::tmp_data, and EMAN::EMData::to_value(). 00437 { 00438 // default setting behavior - does not override if the parameter is already set 00439 params.set_default("mode","gauss_2"); 00440 00441 vector<int> size=params["size"]; 00442 00443 nx = size[0]; 00444 ny = size[1]; 00445 nz = size[2]; 00446 nx2=nx/2-1; 00447 ny2=ny/2; 00448 nz2=nz/2; 00449 00450 00451 // Adjust nx if for Fourier transform even odd issues 00452 bool is_fftodd = (nx % 2 == 1); 00453 // The Fourier transform requires one extra pixel in the x direction, 00454 // which is two spaces in memory, one each for the complex and the 00455 // real components 00456 nx += 2-is_fftodd; 00457 00458 if (params.has_key("subvolume")) { 00459 vector<int> sub=params["subvolume"]; 00460 subx0=sub[0]; 00461 suby0=sub[1]; 00462 subz0=sub[2]; 00463 subnx=sub[3]; 00464 subny=sub[4]; 00465 subnz=sub[5]; 00466 00467 if (subx0<0 || suby0<0 || subz0<0 || subx0+subnx>nx || suby0+subny>ny || subz0+subnz>nz) 00468 throw ImageDimensionException("The subvolume cannot extend outside the reconstructed volume"); 00469 00470 } 00471 else { 00472 subx0=suby0=subz0=0; 00473 subnx=nx; 00474 subny=ny; 00475 subnz=nz; 00476 } 00477 00478 if (seed->get_xsize()!=subnx || seed->get_ysize()!=subny || seed->get_zsize()!=subnz || !seed->is_complex()) 00479 throw ImageDimensionException("The dimensions of the seed volume do not match the reconstruction size"); 00480 00481 // Odd dimension support is here atm, but not above. 00482 image = seed; 00483 if (params.has_key("subvolume")) { 00484 image->set_attr("subvolume_x0",subx0); 00485 image->set_attr("subvolume_y0",suby0); 00486 image->set_attr("subvolume_z0",subz0); 00487 image->set_attr("subvolume_full_nx",nx); 00488 image->set_attr("subvolume_full_ny",ny); 00489 image->set_attr("subvolume_full_nz",nz); 00490 } 00491 00492 if (tmp_data) delete tmp_data; 00493 tmp_data = new EMData(); 00494 tmp_data->set_size(subnx/2, subny, subnz); 00495 tmp_data->to_value(seed_weight); 00496 00497 load_inserter(); 00498 00499 if ( (bool) params["quiet"] == false ) 00500 { 00501 cout << "Seeded direct Fourier inversion"; 00502 cout << "3D Fourier dimensions are " << nx << " " << ny << " " << nz << endl; 00503 cout << "3D Fourier subvolume is " << subnx << " " << subny << " " << subnz << endl; 00504 cout << "You will require approximately " << setprecision(3) << (subnx*subny*subnz*sizeof(float)*1.5)/1000000000.0 << "GB of memory to reconstruct this volume" << endl; 00505 } 00506 }
|
|
A pixel inserter pointer which inserts pixels into the 3D volume using one of a variety of insertion methods.
Definition at line 513 of file reconstructor.h. Referenced by EMAN::WienerFourierReconstructor::do_insert_slice_work(), do_insert_slice_work(), free_memory(), load_default_settings(), and load_inserter(). |
|
Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 477 of file reconstructor.h. Referenced by get_name(). |