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
Exceptions:
InvalidValueException When one of the input parameters is invalid.

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

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

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.

References load_default_settings().

Referenced by NEW().

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 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 }

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 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 }

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 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 }

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 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 }

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 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 }

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.

References NAME.

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::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                 }

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 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 }

void FourierReconstructor::load_default_settings (  )  [protected, virtual]

Load default settings.

Definition at line 316 of file reconstructor.cpp.

References EMAN::ReconstructorVolumeData::image, inserter, and EMAN::ReconstructorVolumeData::tmp_data.

Referenced by FourierReconstructor().

00317 {
00318         inserter=0;
00319         image=0;
00320         tmp_data=0;
00321 }

void FourierReconstructor::load_inserter (  )  [protected, virtual]

Load the pixel inserter based on the information in params.

Definition at line 336 of file reconstructor.cpp.

References 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 }

static 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.

References FourierReconstructor().

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 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 }

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 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(), sqrt(), and t.

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 }

void FourierReconstructor::setup (  )  [virtual]

Setup the Fourier reconstructor

Exceptions:
InvalidValueException When one of the input parameters is invalid.

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 }

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 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 }


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 EMAN::WienerFourierReconstructor::do_insert_slice_work(), 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 477 of file reconstructor.h.

Referenced by get_name().


The documentation for this class was generated from the following files:
Generated on Mon Jul 19 12:44:24 2010 for EMAN2 by  doxygen 1.4.7