#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 | |
Reconstructor * | NEW () |
Factory incorporation uses the pointer of this function. | |
Static Public Attributes | |
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. 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 624 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, preprocess_slice(), EMAN::EMData::set_attr(), EMAN::Transform::set_mirror(), EMAN::Transform::set_scale(), EMAN::Transform::set_trans(), and weight. 00625 { 00626 // Are these exceptions really necessary? (d.woolford) 00627 if (!input_slice) throw NullPointerException("EMData pointer (input image) is NULL"); 00628 00629 Transform * rotation; 00630 rotation = new Transform(arg); // assignment operator 00631 00632 EMData *slice; 00633 if (input_slice->get_attr_default("reconstruct_preproc",(int) 0)) slice=input_slice->copy(); 00634 else slice = preprocess_slice( input_slice, *rotation); 00635 00636 00637 // We must use only the rotational component of the transform, scaling, translation and mirroring 00638 // are not implemented in Fourier space, but are in preprocess_slice 00639 rotation->set_scale(1.0); 00640 rotation->set_mirror(false); 00641 rotation->set_trans(0,0,0); 00642 00643 // Remove the current slice first (not threadsafe, but otherwise performance would be awful) 00644 if (sub) do_insert_slice_work(slice, *rotation, -weight); 00645 00646 // Compare 00647 do_compare_slice_work(slice, *rotation,weight); 00648 00649 input_slice->set_attr("reconstruct_norm",slice->get_attr("reconstruct_norm")); 00650 input_slice->set_attr("reconstruct_absqual",slice->get_attr("reconstruct_absqual")); 00651 // input_slice->set_attr("reconstruct_qual",slice->get_attr("reconstruct_qual")); 00652 input_slice->set_attr("reconstruct_weight",slice->get_attr("reconstruct_weight")); 00653 00654 // Now put the slice back 00655 if (sub) do_insert_slice_work(slice, *rotation, weight); 00656 00657 00658 delete rotation; 00659 delete slice; 00660 00661 // image->update(); 00662 return 0; 00663 00664 }
|
|
A function to perform the nuts and bolts of comparing an image slice.
Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 666 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(). 00667 { 00668 00669 float dt[3]; // This stores the complex and weight from the volume 00670 float dt2[2]; // This stores the local image complex 00671 float *dat = input_slice->get_data(); 00672 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]); 00673 00674 float inx=(float)(input_slice->get_xsize()); // x/y dimensions of the input image 00675 float iny=(float)(input_slice->get_ysize()); 00676 00677 double dot=0; // summed pixel*weight dot product 00678 double vweight=0; // sum of weights 00679 double power=0; // sum of inten*weight from volume 00680 double power2=0; // sum of inten*weight from image 00681 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) { 00682 Transform t3d = arg*(*it); 00683 for (int y = -iny/2; y < iny/2; y++) { 00684 for (int x = 0; x <= inx/2; x++) { 00685 if (x==0 && y==0) continue; // We don't want to use the Fourier origin 00686 00687 float rx = (float) x/(inx-2); // coords relative to Nyquist=.5 00688 float ry = (float) y/iny; 00689 00690 // if ((rx * rx + Util::square(ry - max_input_dim / 2)) > rl) 00691 // continue; 00692 00693 Vec3f coord(rx,ry,0); 00694 coord = coord*t3d; // transpose multiplication 00695 float xx = coord[0]; // transformed coordinates in terms of Nyquist 00696 float yy = coord[1]; 00697 float zz = coord[2]; 00698 00699 00700 if (fabs(xx)>0.5 || fabs(yy)>=0.5 || fabs(zz)>=0.5) continue; 00701 00702 // Map back to actual pixel coordinates in output volume 00703 xx=xx*(nx-2); 00704 yy=yy*ny; 00705 zz=zz*nz; 00706 00707 00708 int idx = (int)(x * 2 + inx*(y<0?iny+y:y)); 00709 dt2[0] = dat[idx]; 00710 dt2[1] = dat[idx+1]; 00711 00712 // value returned indirectly in dt 00713 if (!pixel_at(xx,yy,zz,dt) || dt[2]==0) continue; 00714 00715 // printf("%f\t%f\t%f\t%f\t%f\n",dt[0],dt[1],dt[2],dt2[0],dt2[1]); 00716 dot+=(dt[0]*dt2[0]+dt[1]*dt2[1])*dt[2]; 00717 vweight+=dt[2]; 00718 power+=(dt[0]*dt[0]+dt[1]*dt[1])*dt[2]; 00719 power2+=(dt2[0]*dt2[0]+dt2[1]*dt2[1])*dt[2]; 00720 } 00721 } 00722 } 00723 00724 dot/=sqrt(power*power2); // normalize the dot product 00725 // input_slice->set_attr("reconstruct_norm",(float)(power2<=0?1.0:sqrt(power/power2)/(inx*iny))); 00726 input_slice->set_attr("reconstruct_norm",(float)(power2<=0?1.0:sqrt(power/power2))); 00727 input_slice->set_attr("reconstruct_absqual",(float)dot); 00728 float rw=weight<=0?1.0f:1.0f/weight; 00729 input_slice->set_attr("reconstruct_qual",(float)(dot*rw/((rw-1.0)*dot+1.0))); // here weight is a proxy for SNR 00730 input_slice->set_attr("reconstruct_weight",(float)vweight/(float)(subnx*subny*subnz)); 00731 // printf("** %g\t%g\t%g\t%g ##\n",dot,vweight,power,power2); 00732 //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))); 00733 }
|
|
A function to perform the nuts and bolts of inserting an image slice.
Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 574 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::Vec3f, x, and y. Referenced by determine_slice_agreement(), and insert_slice(). 00575 { 00576 // Reload the inserter if the mode has changed 00577 // string mode = (string) params["mode"]; 00578 // if ( mode != inserter->get_name() ) load_inserter(); 00579 00580 // int y_in = input_slice->get_ysize(); 00581 // int x_in = input_slice->get_xsize(); 00582 // // Adjust the dimensions to account for odd and even ffts 00583 // if (input_slice->is_fftodd()) x_in -= 1; 00584 // else x_in -= 2; 00585 00586 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]); 00587 00588 float inx=(float)(input_slice->get_xsize()); // x/y dimensions of the input image 00589 float iny=(float)(input_slice->get_ysize()); 00590 00591 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) { 00592 Transform t3d = arg*(*it); 00593 for (int y = -iny/2; y < iny/2; y++) { 00594 for (int x = 0; x <= inx/2; x++) { 00595 00596 float rx = (float) x/(inx-2.0f); // coords relative to Nyquist=.5 00597 float ry = (float) y/iny; 00598 00599 Vec3f coord(rx,ry,0); 00600 coord = coord*t3d; // transpose multiplication 00601 float xx = coord[0]; // transformed coordinates in terms of Nyquist 00602 float yy = coord[1]; 00603 float zz = coord[2]; 00604 00605 // Map back to real pixel coordinates in output volume 00606 xx=xx*(nx-2); 00607 yy=yy*ny; 00608 zz=zz*nz; 00609 00610 // 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", 00611 // 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); 00612 // 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", 00613 // 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)); 00614 00615 //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); 00616 // 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); 00617 // 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); 00618 inserter->insert_pixel(xx,yy,zz,input_slice->get_complex_at(x,y),weight); 00619 } 00620 } 00621 } 00622 }
|
|
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 809 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(). 00810 { 00811 // float *norm = tmp_data->get_data(); 00812 // float *rdata = image->get_data(); 00813 00814 bool sqrtnorm=params.set_default("sqrtnorm",false); 00815 normalize_threed(sqrtnorm); 00816 00817 // tmp_data->write_image("density.mrc"); 00818 00819 // we may as well delete the tmp data now... it saves memory and the calling program might 00820 // need memory after it gets the return volume. 00821 // If this delete didn't happen now, it would happen when the deconstructor was called --david 00822 // no longer a good idea with the new iterative scheme -- steve 00823 // if ( tmp_data != 0 ) 00824 // { 00825 // delete tmp_data; 00826 // tmp_data = 0; 00827 // } 00828 00829 /* image->process_inplace("xform.fourierorigin.tocorner");*/ 00830 00831 if (doift) { 00832 image->do_ift_inplace(); 00833 image->depad(); 00834 image->process_inplace("xform.phaseorigin.tocenter"); 00835 } 00836 // If the image was padded it should be the original size, as the client would expect 00837 // I blocked the rest, it is almost certainly incorrect PAP 07/31/08 00838 // No, it's not incorrect. You are wrong. You have the meaning of nx mixed up. DSAW 09/23/cd 00839 // This should now be handled in the calling program --steve 11/03/09 00840 // bool is_fftodd = (nx % 2 == 1); 00841 // if ( (nx-2*(!is_fftodd)) != output_x || ny != output_y || nz != output_z ) 00842 // { 00843 // FloatPoint origin( (nx-output_x)/2, (ny-output_y)/2, (nz-output_z)/2 ); 00844 // FloatSize region_size( output_x, output_y, output_z); 00845 // Region clip_region( origin, region_size ); 00846 // image->clip_inplace( clip_region ); 00847 // } 00848 00849 // Should be an "if (verbose)" here or something 00850 //print_stats(quality_scores); 00851 00852 image->update(); 00853 00854 if (params.has_key("savenorm") && strlen((const char *)params["savenorm"])>0) { 00855 if (tmp_data->get_ysize()%2==0 && tmp_data->get_zsize()%2==0) tmp_data->process_inplace("xform.fourierorigin.tocenter"); 00856 tmp_data->write_image((const char *)params["savenorm"]); 00857 } 00858 00859 delete tmp_data; 00860 tmp_data=0; 00861 EMData *ret=image; 00862 image=0; 00863 00864 return ret; 00865 }
|
|
Frees the memory owned by this object (but not parent objects) Deletes the FourierPixelInserter3D pointer.
Reimplemented from EMAN::ReconstructorVolumeData. Definition at line 327 of file reconstructor.cpp. References inserter. 00328 { 00329 if (image) { delete image; image=0; } 00330 if (tmp_data) { delete tmp_data; tmp_data=0; } 00331 if ( inserter != 0 ) 00332 { 00333 delete inserter; 00334 inserter = 0; 00335 } 00336 }
|
|
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. 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::TypeDict::put(). 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 541 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(), EMAN::Transform::set_trans(), and weight. 00542 { 00543 // Are these exceptions really necessary? (d.woolford) 00544 if (!input_slice) throw NullPointerException("EMData pointer (input image) is NULL"); 00545 00546 Transform * rotation; 00547 /* if ( input_slice->has_attr("xform.projection") ) { 00548 rotation = (Transform*) (input_slice->get_attr("xform.projection")); // assignment operator 00549 } else {*/ 00550 rotation = new Transform(arg); // assignment operator 00551 // } 00552 00553 EMData *slice; 00554 if (input_slice->get_attr_default("reconstruct_preproc",(int) 0)) slice=input_slice->copy(); 00555 else slice = preprocess_slice( input_slice, *rotation); 00556 00557 00558 // We must use only the rotational component of the transform, scaling, translation and mirroring 00559 // are not implemented in Fourier space, but are in preprocess_slice 00560 rotation->set_scale(1.0); 00561 rotation->set_mirror(false); 00562 rotation->set_trans(0,0,0); 00563 00564 // Finally to the pixel wise slice insertion 00565 do_insert_slice_work(slice, *rotation, weight); 00566 00567 delete rotation; rotation=0; 00568 delete slice; 00569 00570 // image->update(); 00571 return 0; 00572 }
|
|
Load default settings.
Definition at line 320 of file reconstructor.cpp. References inserter.
|
|
Load the pixel inserter based on the information in params.
Definition at line 340 of file reconstructor.cpp. References EMAN::Factory< T >::get(), EMAN::EMData::get_data(), EMAN::FourierPixelInserter3D::init(), and inserter. Referenced by setup(), and setup_seed(). 00341 { 00342 // ss 00343 // string mode = (string)params["mode"]; 00344 Dict parms; 00345 parms["data"] = image; 00346 parms["norm"] = tmp_data->get_data(); 00347 // These aren't necessary because we deal with them before calling the inserter 00348 // parms["subnx"] = nx; 00349 // parms["subny"] = ny; 00350 // parms["subnx"] = nz; 00351 // parms["subx0"] = x0; 00352 // parms["suby0"] = y0; 00353 // parms["subz0"] = z0; 00354 00355 if ( inserter != 0 ) 00356 { 00357 delete inserter; 00358 } 00359 00360 inserter = Factory<FourierPixelInserter3D>::get((string)params["mode"], parms); 00361 inserter->init(); 00362 }
|
|
Factory incorporation uses the pointer of this function.
Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 456 of file reconstructor.h. 00457 { 00458 return new FourierReconstructor(); 00459 }
|
|
Disallow assignment.
|
|
This is a mode-2 pixel extractor.
Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 735 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(). 00736 { 00737 int x0 = (int) floor(xx); 00738 int y0 = (int) floor(yy); 00739 int z0 = (int) floor(zz); 00740 00741 float *rdata=image->get_data(); 00742 float *norm=tmp_data->get_data(); 00743 float normsum=0,normsum2=0; 00744 00745 dt[0]=dt[1]=dt[2]=0.0; 00746 00747 if (nx==subnx) { // normal full reconstruction 00748 if (x0<-nx2-1 || y0<-ny2-1 || z0<-nz2-1 || x0>nx2 || y0>ny2 || z0>nz2 ) return false; 00749 00750 // no error checking on add_complex_fast, so we need to be careful here 00751 int x1=x0+1; 00752 int y1=y0+1; 00753 int z1=z0+1; 00754 if (x0<-nx2) x0=-nx2; 00755 if (x1>nx2) x1=nx2; 00756 if (y0<-ny2) y0=-ny2; 00757 if (y1>ny2) y1=ny2; 00758 if (z0<-nz2) z0=-nz2; 00759 if (z1>nz2) z1=nz2; 00760 00761 size_t idx=0; 00762 float r, gg; 00763 for (int k = z0 ; k <= z1; k++) { 00764 for (int j = y0 ; j <= y1; j++) { 00765 for (int i = x0; i <= x1; i ++) { 00766 r = Util::hypot3sq((float) i - xx, j - yy, k - zz); 00767 idx=image->get_complex_index_fast(i,j,k); 00768 gg = Util::fast_exp(-r / EMConsts::I2G); 00769 00770 dt[0]+=gg*rdata[idx]; 00771 dt[1]+=(i<0?-1.0f:1.0f)*gg*rdata[idx+1]; 00772 dt[2]+=norm[idx/2]*gg; 00773 normsum2+=gg; 00774 normsum+=gg*norm[idx/2]; 00775 } 00776 } 00777 } 00778 if (normsum==0) return false; 00779 dt[0]/=normsum; 00780 dt[1]/=normsum; 00781 dt[2]/=normsum2; 00782 // 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]); 00783 return true; 00784 } 00785 else { // for subvolumes, not optimized yet 00786 size_t idx; 00787 float r, gg; 00788 for (int k = z0 ; k <= z0 + 1; k++) { 00789 for (int j = y0 ; j <= y0 + 1; j++) { 00790 for (int i = x0; i <= x0 + 1; i ++) { 00791 r = Util::hypot3sq((float) i - xx, j - yy, k - zz); 00792 idx=image->get_complex_index(i,j,k,subx0,suby0,subz0,nx,ny,nz); 00793 gg = Util::fast_exp(-r / EMConsts::I2G)*norm[idx/2]; 00794 00795 dt[0]+=gg*rdata[idx]; 00796 dt[1]+=(i<0?-1.0f:1.0f)*gg*rdata[idx+1]; 00797 dt[2]+=norm[idx/2]; 00798 normsum+=gg; 00799 } 00800 } 00801 } 00802 00803 if (normsum==0) return false; 00804 return true; 00805 } 00806 }
|
|
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 513 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(), sqrt(), and t. Referenced by EMAN::WienerFourierReconstructor::determine_slice_agreement(), determine_slice_agreement(), EMAN::WienerFourierReconstructor::insert_slice(), and insert_slice(). 00514 { 00515 // Shift the image pixels so the real space origin is now located at the phase origin (at the bottom left of the image) 00516 EMData* return_slice = 0; 00517 Transform tmp(t); 00518 tmp.set_rotation(Dict("type","eman")); // resets the rotation to 0 implicitly, this way we only do 2d translation,scaling and mirroring 00519 00520 if (tmp.is_identity()) return_slice=slice->copy(); 00521 else return_slice = slice->process("xform",Dict("transform",&tmp)); 00522 00523 return_slice->process_inplace("xform.phaseorigin.tocorner"); 00524 00525 // printf("@@@ %d\n",(int)return_slice->get_attr("nx")); 00526 // Fourier transform the slice 00527 return_slice->do_fft_inplace(); 00528 00529 // printf("%d\n",(int)return_slice->get_attr("nx")); 00530 00531 return_slice->mult((float)sqrt(1.0f/(return_slice->get_ysize())*return_slice->get_xsize())); 00532 00533 // Shift the Fourier transform so that it's origin is in the center (bottom) of the image. 00534 // return_slice->process_inplace("xform.fourierorigin.tocenter"); 00535 00536 return_slice->set_attr("reconstruct_preproc",(int)1); 00537 return return_slice; 00538 }
|
|
Setup the Fourier reconstructor.
Implements EMAN::Reconstructor. Definition at line 364 of file reconstructor.cpp. References EMAN::Dict::has_key(), ImageDimensionException, is_fftodd(), load_inserter(), 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::EMData::to_zero(), and EMAN::EMData::update(). 00365 { 00366 // default setting behavior - does not override if the parameter is already set 00367 params.set_default("mode","gauss_2"); 00368 00369 vector<int> size=params["size"]; 00370 00371 nx = size[0]; 00372 ny = size[1]; 00373 nz = size[2]; 00374 nx2=nx/2-1; 00375 ny2=ny/2; 00376 nz2=nz/2; 00377 00378 00379 // Adjust nx if for Fourier transform even odd issues 00380 bool is_fftodd = (nx % 2 == 1); 00381 // The Fourier transform requires one extra pixel in the x direction, 00382 // which is two spaces in memory, one each for the complex and the 00383 // real components 00384 nx += 2-is_fftodd; 00385 00386 if (params.has_key("subvolume")) { 00387 vector<int> sub=params["subvolume"]; 00388 subx0=sub[0]; 00389 suby0=sub[1]; 00390 subz0=sub[2]; 00391 subnx=sub[3]; 00392 subny=sub[4]; 00393 subnz=sub[5]; 00394 00395 if (subx0<0 || suby0<0 || subz0<0 || subx0+subnx>nx || suby0+subny>ny || subz0+subnz>nz) 00396 throw ImageDimensionException("The subvolume cannot extend outside the reconstructed volume"); 00397 00398 } 00399 else { 00400 subx0=suby0=subz0=0; 00401 subnx=nx; 00402 subny=ny; 00403 subnz=nz; 00404 } 00405 00406 00407 // Odd dimension support is here atm, but not above. 00408 if (image) delete image; 00409 image = new EMData(); 00410 image->set_size(subnx, subny, subnz); 00411 image->set_complex(true); 00412 image->set_fftodd(is_fftodd); 00413 image->set_ri(true); 00414 image->to_zero(); 00415 00416 if (params.has_key("subvolume")) { 00417 image->set_attr("subvolume_x0",subx0); 00418 image->set_attr("subvolume_y0",suby0); 00419 image->set_attr("subvolume_z0",subz0); 00420 image->set_attr("subvolume_full_nx",nx); 00421 image->set_attr("subvolume_full_ny",ny); 00422 image->set_attr("subvolume_full_nz",nz); 00423 } 00424 00425 if (tmp_data) delete tmp_data; 00426 tmp_data = new EMData(); 00427 tmp_data->set_size(subnx/2, subny, subnz); 00428 tmp_data->to_zero(); 00429 tmp_data->update(); 00430 00431 load_inserter(); 00432 00433 if ( (bool) params["quiet"] == false ) 00434 { 00435 cout << "3D Fourier dimensions are " << nx << " " << ny << " " << nz << endl; 00436 cout << "3D Fourier subvolume is " << subnx << " " << subny << " " << subnz << endl; 00437 cout << "You will require approximately " << setprecision(3) << (subnx*subny*subnz*sizeof(float)*1.5)/1000000000.0 << "GB of memory to reconstruct this volume" << endl; 00438 } 00439 }
|
|
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 441 of file reconstructor.cpp. References EMAN::EMData::get_xsize(), EMAN::EMData::get_ysize(), EMAN::EMData::get_zsize(), EMAN::Dict::has_key(), ImageDimensionException, EMAN::EMData::is_complex(), is_fftodd(), load_inserter(), EMAN::EMData::set_attr(), EMAN::Dict::set_default(), EMAN::EMData::set_size(), sub(), and EMAN::EMData::to_value(). 00441 { 00442 // default setting behavior - does not override if the parameter is already set 00443 params.set_default("mode","gauss_2"); 00444 00445 vector<int> size=params["size"]; 00446 00447 nx = size[0]; 00448 ny = size[1]; 00449 nz = size[2]; 00450 nx2=nx/2-1; 00451 ny2=ny/2; 00452 nz2=nz/2; 00453 00454 00455 // Adjust nx if for Fourier transform even odd issues 00456 bool is_fftodd = (nx % 2 == 1); 00457 // The Fourier transform requires one extra pixel in the x direction, 00458 // which is two spaces in memory, one each for the complex and the 00459 // real components 00460 nx += 2-is_fftodd; 00461 00462 if (params.has_key("subvolume")) { 00463 vector<int> sub=params["subvolume"]; 00464 subx0=sub[0]; 00465 suby0=sub[1]; 00466 subz0=sub[2]; 00467 subnx=sub[3]; 00468 subny=sub[4]; 00469 subnz=sub[5]; 00470 00471 if (subx0<0 || suby0<0 || subz0<0 || subx0+subnx>nx || suby0+subny>ny || subz0+subnz>nz) 00472 throw ImageDimensionException("The subvolume cannot extend outside the reconstructed volume"); 00473 00474 } 00475 else { 00476 subx0=suby0=subz0=0; 00477 subnx=nx; 00478 subny=ny; 00479 subnz=nz; 00480 } 00481 00482 if (seed->get_xsize()!=subnx || seed->get_ysize()!=subny || seed->get_zsize()!=subnz || !seed->is_complex()) 00483 throw ImageDimensionException("The dimensions of the seed volume do not match the reconstruction size"); 00484 00485 // Odd dimension support is here atm, but not above. 00486 image = seed; 00487 if (params.has_key("subvolume")) { 00488 image->set_attr("subvolume_x0",subx0); 00489 image->set_attr("subvolume_y0",suby0); 00490 image->set_attr("subvolume_z0",subz0); 00491 image->set_attr("subvolume_full_nx",nx); 00492 image->set_attr("subvolume_full_ny",ny); 00493 image->set_attr("subvolume_full_nz",nz); 00494 } 00495 00496 if (tmp_data) delete tmp_data; 00497 tmp_data = new EMData(); 00498 tmp_data->set_size(subnx/2, subny, subnz); 00499 tmp_data->to_value(seed_weight); 00500 00501 load_inserter(); 00502 00503 if ( (bool) params["quiet"] == false ) 00504 { 00505 cout << "Seeded direct Fourier inversion"; 00506 cout << "3D Fourier dimensions are " << nx << " " << ny << " " << nz << endl; 00507 cout << "3D Fourier subvolume is " << subnx << " " << subny << " " << subnz << endl; 00508 cout << "You will require approximately " << setprecision(3) << (subnx*subny*subnz*sizeof(float)*1.5)/1000000000.0 << "GB of memory to reconstruct this volume" << endl; 00509 } 00510 }
|
|
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 do_insert_slice_work(), free_memory(), load_default_settings(), and load_inserter(). |
|
Reimplemented in EMAN::WienerFourierReconstructor. Definition at line 73 of file reconstructor.cpp. |