Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

EMAN::FourierReconstructor Class Reference

Fourier space 3D reconstruction The Fourier reconstructor is designed to work in an iterative fashion, where similarity ("quality") metrics are used to determine if a slice should be inserted into the 3D in each subsequent iteration. More...

#include <reconstructor.h>

Inheritance diagram for EMAN::FourierReconstructor:

Inheritance graph
[legend]
Collaboration diagram for EMAN::FourierReconstructor:

Collaboration graph
[legend]
List of all members.

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 EMDatapreprocess_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 EMDatafinish (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

ReconstructorNEW ()
 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

FourierPixelInserter3Dinserter
 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.
FourierReconstructoroperator= (const FourierReconstructor &)
 Disallow assignment.

Detailed Description

Fourier space 3D reconstruction The Fourier reconstructor is designed to work in an iterative fashion, where similarity ("quality") metrics are used to determine if a slice should be inserted into the 3D in each subsequent iteration.

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

Definition at line 363 of file reconstructor.h.


Constructor & Destructor Documentation

EMAN::FourierReconstructor::FourierReconstructor  )  [inline]
 

Default constructor calls load_default_settings().

Definition at line 369 of file reconstructor.h.

00369 { load_default_settings(); }

virtual EMAN::FourierReconstructor::~FourierReconstructor  )  [inline, virtual]
 

Deconstructor calls free_memory().

Definition at line 374 of file reconstructor.h.

References free_memory().

00374 { free_memory(); }

EMAN::FourierReconstructor::FourierReconstructor const FourierReconstructor that  )  [private]
 

Disallow copy construction.


Member Function Documentation

int FourierReconstructor::determine_slice_agreement EMData slice,
const Transform euler,
const float  weight = 1.0,
bool  sub = true
[virtual]
 

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

Parameters:
input_slice The EMData slice to be compared
euler The orientation of the slice as a Transform object
weight A weighting factor for this slice, generally the number of particles in a class-average. May be ignored by some reconstructors
sub Flag indicating whether to subtract the slice from the volume before comparing. May be ignored by some reconstructors
Returns:
0 if OK. 1 if error.
Exceptions:
NullPointerException if the input EMData pointer is null
ImageFormatException if the image is complex as opposed to real

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 }

void FourierReconstructor::do_compare_slice_work EMData input_slice,
const Transform euler,
float  weight
[protected, virtual]
 

A function to perform the nuts and bolts of comparing an image slice.

Parameters:
input_slice the slice to insert into the 3D volume
euler a transform3D storing the slice euler angle

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 }

void FourierReconstructor::do_insert_slice_work const EMData *const   input_slice,
const Transform euler,
const float  weight
[protected, virtual]
 

A function to perform the nuts and bolts of inserting an image slice.

Parameters:
input_slice the slice to insert into the 3D volume
euler a transform3D storing the slice euler angle
weight weighting factor for this slice (usually number of particles in a class-average)

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 }

EMData * FourierReconstructor::finish bool  doift = true  )  [virtual]
 

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.

Parameters:
doift A flag indicating whether the returned object should be guaranteed to be in real-space (true) or should be left in whatever space the reconstructor generated
Returns:
The real space reconstructed volume

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 }

void FourierReconstructor::free_memory  )  [protected, virtual]
 

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 }

virtual string EMAN::FourierReconstructor::get_desc  )  const [inline, virtual]
 

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                 }

virtual string EMAN::FourierReconstructor::get_name  )  const [inline, virtual]
 

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                 }

virtual TypeDict EMAN::FourierReconstructor::get_param_types  )  const [inline, virtual]
 

Get the parameter types of this object.

Returns:
a TypeDict detailing all of the acceptable (and necessary) parameters

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                 }

int FourierReconstructor::insert_slice const EMData *const   slice,
const Transform euler,
const float  weight = 1.0
[virtual]
 

Insert a slice into a 3D volume, in a given orientation.

Returns:
0 if successful, 1 otherwise
Parameters:
slice the image slice to be inserted into the 3D volume
euler Euler angle of this image slice.
weight A weighting factor for this slice, generally the number of particles in a class-average. May be ignored by some reconstructors
Returns:
0 if OK. 1 if error.
Exceptions:
NullPointerException if the input EMData pointer is null
ImageFormatException if the image is complex as opposed to real

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 }

void FourierReconstructor::load_default_settings  )  [protected, virtual]
 

Load default settings.

Definition at line 320 of file reconstructor.cpp.

References inserter.

00321 {
00322         inserter=0;
00323         image=0;
00324         tmp_data=0;
00325 }

void FourierReconstructor::load_inserter  )  [protected, virtual]
 

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 }

Reconstructor* EMAN::FourierReconstructor::NEW  )  [inline, static]
 

Factory incorporation uses the pointer of this function.

Returns:
a Reconstructor pointer to a newly allocated FourierReconstructor

Reimplemented in EMAN::WienerFourierReconstructor.

Definition at line 456 of file reconstructor.h.

00457                 {
00458                         return new FourierReconstructor();
00459                 }

FourierReconstructor& EMAN::FourierReconstructor::operator= const FourierReconstructor  )  [private]
 

Disallow assignment.

bool FourierReconstructor::pixel_at const float &  xx,
const float &  yy,
const float &  zz,
float *  dt
[protected, virtual]
 

This is a mode-2 pixel extractor.

Parameters:
xx,yy,zz voxel coordinates (need not be integers)
dt float pointer with 3 floats allocated for returned complex value and weight sum

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 }

EMData * FourierReconstructor::preprocess_slice const EMData *const   slice,
const Transform t = Transform()
[virtual]
 

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.

Returns:
the processed slice
Parameters:
slice the slice to be prepocessed
t transform to be used for insertion
Exceptions:
InvalidValueException when the specified padding value is less than the size of the images

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 }

void FourierReconstructor::setup  )  [virtual]
 

Setup the Fourier reconstructor.

Exceptions:
InvalidValueException When one of the input parameters is invalid

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 }

void FourierReconstructor::setup_seed EMData seed,
float  seed_weight
[virtual]
 

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.

Exceptions:
InvalidValueException When one of the input parameters is invalid

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 }


Member Data Documentation

FourierPixelInserter3D* EMAN::FourierReconstructor::inserter [protected]
 

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().

const string FourierReconstructor::NAME = "fourier" [static]
 

Reimplemented in EMAN::WienerFourierReconstructor.

Definition at line 73 of file reconstructor.cpp.


The documentation for this class was generated from the following files:
Generated on Thu Dec 9 13:48:33 2010 for EMAN2 by  doxygen 1.3.9.1