00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef eman_processor_h__
00037 #define eman_processor_h__ 1
00038
00039 #include "emobject.h"
00040 #include "util.h"
00041 #include "geometry.h"
00042 #include "transform.h"
00043 #include "emdata.h"
00044 #include "gorgon/skeletonizer.h"
00045
00046 #include <cfloat>
00047 #include <climits>
00048 #include <cstring>
00049
00050 using std::vector;
00051 using std::map;
00052 using std::string;
00053
00054 namespace EMAN
00055 {
00056 class EMData;
00057
00093 class Processor
00094 {
00095 public:
00096 virtual ~ Processor()
00097 {
00098 }
00099
00105 virtual void process_inplace(EMData *image) = 0;
00106
00113 virtual EMData* process(const EMData * const image);
00114
00118 virtual void process_list_inplace(vector < EMData * > & images)
00119 {
00120 for (size_t i = 0; i < images.size(); i++) {
00121 process_inplace(images[i]);
00122 }
00123 }
00124
00128 virtual string get_name() const = 0;
00129
00133 virtual Dict get_params() const
00134 {
00135 return params;
00136 }
00137
00141 virtual void set_params(const Dict & new_params)
00142 {
00143 params = new_params;
00144 }
00145
00152 virtual TypeDict get_param_types() const
00153 {
00154 return TypeDict();
00155 }
00156
00163 static string get_group_desc()
00164 {
00165 return "EMAN processors are in-place image processors. You may apply a processor to process a single image or process multiple images. Processor class is the base class for all processor. <br> \
00166 The basic design of EMAN Processors: <br>\
00167 1) Each Processor class defines an image-processinging algorithm. <br>\
00168 2) All the Processor classes in EMAN are managed by a Factory pattern. So each Processor class must define: <br> a) a unique name to idenfity itself in the factory. <br>b) a static method to register itself in the factory.<br>\
00169 3) Each Processor class defines its own parameter set.<br>\
00170 4) Each Processor class defines functions to return its documentation including parameter information, and processor description. These functions enable EMAN to generate processor manuals dynamically.";
00171 }
00172
00178 virtual string get_desc() const = 0;
00179
00186 enum fourier_filter_types {
00187 TOP_HAT_LOW_PASS,
00188 TOP_HAT_HIGH_PASS,
00189 TOP_HAT_BAND_PASS,
00190 TOP_HOMOMORPHIC,
00191 GAUSS_LOW_PASS,
00192 GAUSS_HIGH_PASS,
00193 GAUSS_BAND_PASS,
00194 GAUSS_INVERSE,
00195 GAUSS_HOMOMORPHIC,
00196 BUTTERWORTH_LOW_PASS,
00197 BUTTERWORTH_HIGH_PASS,
00198 BUTTERWORTH_HOMOMORPHIC,
00199 KAISER_I0,
00200 KAISER_SINH,
00201 KAISER_I0_INVERSE,
00202 KAISER_SINH_INVERSE,
00203 SHIFT,
00204 TANH_LOW_PASS,
00205 TANH_HIGH_PASS,
00206 TANH_HOMOMORPHIC,
00207 TANH_BAND_PASS,
00208 RADIAL_TABLE,
00209 CTF_,
00210 };
00211
00236 static void
00237 EMFourierFilterInPlace(EMData* fimage, Dict params) {
00238 bool doInPlace = true;
00239 EMFourierFilterFunc(fimage, params, doInPlace);
00240 }
00241
00267 static EMData*
00268 EMFourierFilter(EMData* fimage, Dict params) {
00269 bool doInPlace = false;
00270 return EMFourierFilterFunc(fimage, params, doInPlace);
00271 }
00272
00273 private:
00309 static EMData*
00310 EMFourierFilterFunc(EMData* fimage, Dict params, bool doInPlace=true);
00311
00312 protected:
00313 mutable Dict params;
00314 };
00315
00316 class ImageProcessor:public Processor
00317 {
00318 public:
00319 void process_inplace(EMData * image);
00320
00321 static string get_group_desc()
00322 {
00323 return "An Image Processor defines a way to create a processor image. The processor image is used to multiply the input-image in the fourier space. ImageFilter class is the base class. Each specific ImageFilter class must define function create_processor_image(). ";
00324 }
00325
00326 protected:
00327 virtual EMData * create_processor_image() const = 0;
00328 };
00329
00336 class FourierProcessor:public Processor
00337 {
00338 public:
00339 void process_inplace(EMData * image);
00340
00341 static string get_group_desc()
00342 {
00343 return "Fourier Filter processors are a group of processor in the frequency domain. Before using such processors on an image, the image must be transformed from real space to the fourier space. FourierProcessor class is the base class of fourier space processors. Each specific processor is either a lowpass filter processor, or a highpass filter processor, or neighter. The unit of lowpass and highpass parameters are in terms of Nyquist, valid range is [0,0.5]. ";
00344 }
00345
00346 TypeDict get_param_types() const
00347 {
00348 TypeDict d;
00349 d.put("cutoff_abs", EMObject::FLOAT, "Processor radius in terms of Nyquist (0-.5)");
00350 d.put("cutoff_pixels", EMObject::FLOAT, " Width in Fourier pixels (0 - size()/2)");
00351 d.put("cutoff_freq", EMObject::FLOAT, "1/Resolution in 1/A (0 - 1 / 2*apix). eg - a 20 A filter is cutoff_freq=0.05");
00352 d.put("apix", EMObject::FLOAT, " Override A/pix in the image header (changes x,y and z)");
00353 return d;
00354 }
00355
00356 protected:
00357 virtual void preprocess(EMData *image) {
00358 if(params.has_key("apix")) {
00359 image->set_attr("apix_x", (float)params["apix"]);
00360 image->set_attr("apix_y", (float)params["apix"]);
00361 image->set_attr("apix_z", (float)params["apix"]);
00362 }
00363
00364 const Dict dict = image->get_attr_dict();
00365 if( params.has_key("sigma")) {
00366 params["cutoff_abs"] = (float)params["sigma"];
00367 }
00368 else if( params.has_key("cutoff_abs") ) {
00369 params["sigma"] = (float)params["cutoff_abs"];
00370 }
00371 else if( params.has_key("cutoff_freq") ) {
00372 float val = (float)params["cutoff_freq"] * (float)dict["apix_x"];
00373 params["cutoff_abs"] = val;
00374 params["sigma"] = val;
00375 }
00376 else if( params.has_key("cutoff_pixels") ) {
00377 float val = (0.5f*(float)params["cutoff_pixels"] / (float)dict["nx"]);
00378 params["cutoff_abs"] = val;
00379 params["sigma"] = val;
00380 }
00381
00382 }
00383 virtual void create_radial_func(vector < float >&radial_mask) const = 0;
00384 };
00385
00393 class FourierAnlProcessor:public Processor
00394 {
00395 public:
00396 void process_inplace(EMData * image);
00397
00398 static string get_group_desc()
00399 {
00400 return "Fourier Filter processors are a group of processor in the frequency domain. Before using such processors on an image, the image must be transformed from real space to the fourier space. FourierProcessor class is the base class of fourier space processors. Each specific processor is either a lowpass filter processor, or a highpass filter processor, or neighter. The unit of lowpass and highpass parameters are in terms of Nyquist, valid range is [0,0.5]. ";
00401 }
00402
00403 TypeDict get_param_types() const
00404 {
00405 TypeDict d;
00406 d.put("cutoff_abs", EMObject::FLOAT, "Processor radius in terms of Nyquist (0-.5)");
00407 d.put("cutoff_pixels", EMObject::FLOAT, " Width in Fourier pixels (0 - size()/2)");
00408 d.put("cutoff_freq", EMObject::FLOAT, "1/Resolution in 1/A (0 - 1 / 2*apix). eg - a 20 A filter is cutoff_freq=0.05");
00409 d.put("apix", EMObject::FLOAT, " Override A/pix in the image header (changes x,y and z)");
00410 return d;
00411 }
00412
00413 protected:
00414 virtual void preprocess(EMData *) {}
00415 virtual void create_radial_func(vector < float >&radial_mask,EMData *image) const = 0;
00416 };
00417
00420 class SNREvalProcessor:public Processor
00421 {
00422 public:
00423 string get_name() const
00424 {
00425 return NAME;
00426 }
00427
00428 void process_inplace(EMData * image);
00429
00430 void set_params(const Dict & new_params)
00431 {
00432 params = new_params;
00433
00434
00435
00436 }
00437
00438 TypeDict get_param_types() const
00439 {
00440 TypeDict d;
00441
00442
00443 return d;
00444 }
00445
00446 static Processor *NEW()
00447 {
00448 return new SNREvalProcessor();
00449 }
00450
00451 string get_desc() const
00452 {
00453 return "Evaluates the SNR of the particle using a masking method similar to that used in the CTF analysis process. The image is not changed. The resulting value is placed in the particle dictionary as eval_maskedsnr";
00454 }
00455
00456 static const string NAME;
00457
00458 protected:
00459 EMData *sum;
00460 int dosqrt;
00461 };
00462
00463
00468 class AmpweightFourierProcessor:public Processor
00469 {
00470 public:
00471 string get_name() const
00472 {
00473 return NAME;
00474 }
00475
00476 void process_inplace(EMData * image);
00477
00478 void set_params(const Dict & new_params)
00479 {
00480 params = new_params;
00481 sum = params["sum"];
00482 dosqrt = params["sqrt"];
00483
00484 }
00485
00486 TypeDict get_param_types() const
00487 {
00488 TypeDict d;
00489 d.put("sum", EMObject::EMDATA, "Adds the weights to sum for normalization");
00490 d.put("sqrt", EMObject::INT, "Weights using sqrt of the amplitude if set");
00491 return d;
00492 }
00493
00494 static Processor *NEW()
00495 {
00496 return new AmpweightFourierProcessor();
00497 }
00498
00499 string get_desc() const
00500 {
00501 return "Multiplies each Fourier pixel by its amplitude";
00502 }
00503
00504 static const string NAME;
00505
00506 protected:
00507 EMData *sum;
00508 int dosqrt;
00509 };
00516 class ConvolutionProcessor : public Processor
00517 {
00518 public:
00519 ConvolutionProcessor() {}
00520
00521 string get_name() const
00522 {
00523 return NAME;
00524 }
00525
00526 void process_inplace(EMData *image);
00527
00528 static Processor *NEW()
00529 {
00530 return new ConvolutionProcessor();
00531 }
00532
00533 string get_desc() const
00534 {
00535 return "Performs Fourier space convolution. Maintains the space that the image is in - i.e. if image is real, the result is real and vice versa.";
00536 }
00537
00538 TypeDict get_param_types() const
00539 {
00540 TypeDict d;
00541 d.put("with", EMObject::EMDATA, "The image that will convolute the other image");
00542 return d;
00543 }
00544
00545 static const string NAME;
00546 };
00547
00554 class XGradientProcessor : public Processor
00555 {
00556 public:
00557 XGradientProcessor() {}
00558
00559 string get_name() const
00560 {
00561 return NAME;
00562 }
00563
00564 void process_inplace(EMData *image);
00565
00566 static Processor *NEW()
00567 {
00568 return new XGradientProcessor();
00569 }
00570
00571 string get_desc() const
00572 {
00573 return "Determines the image gradient in the x direction";
00574 }
00575
00576 TypeDict get_param_types() const
00577 {
00578 TypeDict d;
00579 return d;
00580 }
00581
00582 static const string NAME;
00583 };
00584
00585 class YGradientProcessor : public Processor
00586 {
00587 public:
00588 YGradientProcessor() {}
00589
00590 string get_name() const
00591 {
00592 return NAME;
00593 }
00594
00595 void process_inplace(EMData *image);
00596
00597 static Processor *NEW()
00598 {
00599 return new YGradientProcessor();
00600 }
00601
00602 string get_desc() const
00603 {
00604 return "Determines the image gradient in the y direction";
00605 }
00606
00607
00608 TypeDict get_param_types() const
00609 {
00610 TypeDict d;
00611 return d;
00612 }
00613
00614 static const string NAME;
00615 };
00616
00617 class ZGradientProcessor : public Processor
00618 {
00619 public:
00620 ZGradientProcessor() {}
00621
00622 string get_name() const
00623 {
00624 return NAME;
00625 }
00626
00627 void process_inplace(EMData *image);
00628
00629 static Processor *NEW()
00630 {
00631 return new ZGradientProcessor();
00632 }
00633
00634 string get_desc() const
00635 {
00636 return "Determines the image gradient in the z direction";
00637 }
00638
00639 TypeDict get_param_types() const
00640 {
00641 TypeDict d;
00642 return d;
00643 }
00644
00645 static const string NAME;
00646 };
00647
00656 class Wiener2DAutoAreaProcessor:public Processor
00657 {
00658 public:
00659 string get_name() const
00660 {
00661 return NAME;
00662 }
00663
00664 virtual EMData* process(const EMData * const image);
00665
00666 void process_inplace(EMData *image);
00667
00668 void set_params(const Dict & new_params)
00669 {
00670 params = new_params;
00671 bgsize = params["size"];
00672
00673 }
00674
00675 TypeDict get_param_types() const
00676 {
00677 TypeDict d;
00678 d.put("size", EMObject::INT, "Size in pixels of the boxes to chop the image into");
00679 return d;
00680 }
00681
00682 static Processor *NEW()
00683 {
00684 return new Wiener2DAutoAreaProcessor();
00685 }
00686
00687 string get_desc() const
00688 {
00689 return "Automatically detrmines the background for the image then uses this to perform Wiener filters on overlapping subregions of the image, which are then combined using linear interpolation";
00690 }
00691
00692 static const string NAME;
00693
00694 protected:
00695 int bgsize;
00696 };
00697
00704 class DistanceSegmentProcessor:public Processor
00705 {
00706 public:
00707 string get_name() const
00708 {
00709 return NAME;
00710 }
00711
00712 virtual EMData* process(const EMData * const image);
00713 void process_inplace( EMData * image);
00714
00715 TypeDict get_param_types() const
00716 {
00717 TypeDict d ;
00718 d.put("thr",EMObject::FLOAT,"Optional : Isosurface threshold value. Pixels below this will not be segment centers (default = 0.9)");
00719 d.put("minsegsep",EMObject::FLOAT,"Required: Minimum segment separation in pixels. Segments too close will trigger a reseed");
00720 d.put("maxsegsep",EMObject::FLOAT,"Required: Maximum segment separation in pixels. Segments too close will trigger a reseed");
00721 d.put("verbose",EMObject::INT,"Be verbose while running");
00722 return d;
00723 }
00724
00725 static Processor *NEW()
00726 {
00727 return new DistanceSegmentProcessor();
00728 }
00729
00730 string get_desc() const
00731 {
00732 return "Segments a volume into pieces separated by distances in the specified range.";
00733 }
00734
00735 static const string NAME;
00736
00737 };
00738
00745 class KmeansSegmentProcessor:public Processor
00746 {
00747 public:
00748 string get_name() const
00749 {
00750 return NAME;
00751 }
00752
00753 virtual EMData* process(const EMData * const image);
00754 void process_inplace( EMData * image);
00755
00756 TypeDict get_param_types() const
00757 {
00758 TypeDict d ;
00759 d.put("nseg", EMObject::INT, "Number of segments to divide the image into. default=12" );
00760 d.put("thr",EMObject::FLOAT,"Isosurface threshold value. Pixels below this will not be segmented");
00761 d.put("ampweight",EMObject::INT,"If set, will weight centers by voxel amplitude. default = 1");
00762 d.put("maxsegsize",EMObject::FLOAT,"Maximum radial distance from segment center to member voxel. Default=10000");
00763 d.put("minsegsep",EMObject::FLOAT,"Minimum segment separation. Segments too close will trigger a reseed");
00764 d.put("maxiter",EMObject::FLOAT,"Maximum number of iterations to run before stopping. Default=100");
00765 d.put("maxvoxmove",EMObject::FLOAT,"Maximum number of voxels that can move before quitting. Default=25");
00766 d.put("verbose",EMObject::INT,"Be verbose while running");
00767 return d;
00768 }
00769
00770 static Processor *NEW()
00771 {
00772 return new KmeansSegmentProcessor();
00773 }
00774
00775 string get_desc() const
00776 {
00777 return "Performs K-means segmentation on a volume. Note that this method uses random seeds, and thus will return different results each time it is run. Returned map contains number of segment for each voxel (or 0 for unsegmented voxels). Segmentation centers are stored in 'segmentcenters' attribute, consisting of a list of 3n floats in x,y,z triples.";
00778 }
00779
00780 static const string NAME;
00781
00782 };
00783
00797 class CtfSimProcessor:public Processor
00798 {
00799 public:
00800 string get_name() const
00801 {
00802 return NAME;
00803 }
00804
00805 virtual EMData* process(const EMData * const image);
00806
00807 void process_inplace(EMData *image);
00808
00809 TypeDict get_param_types() const
00810 {
00811 TypeDict d;
00812 d.put("defocus", EMObject::FLOAT, "Defocus in microns (underfocus positive)");
00813 d.put("ampcont", EMObject::FLOAT, "% amplitude contrast (0-100)");
00814 d.put("bfactor", EMObject::FLOAT, "B-factor in A^2, uses MRC convention rather than EMAN1 convention");
00815 d.put("noiseamp", EMObject::FLOAT, "Amplitude of the added empirical pink noise");
00816 d.put("noiseampwhite", EMObject::FLOAT, "Amplitude of added white noise");
00817 d.put("voltage", EMObject::FLOAT, "Microscope voltage in KV");
00818 d.put("cs", EMObject::FLOAT, "Cs of microscope in mm");
00819 d.put("apix", EMObject::FLOAT, "A/pix of data");
00820 return d;
00821 }
00822
00823 static Processor *NEW()
00824 {
00825 return new CtfSimProcessor();
00826 }
00827
00828 string get_desc() const
00829 {
00830 return "Applies a simulated CTF with noise to an image. The added noise is either white or based on an empirical curve generated from cryoEM data. ";
00831 }
00832
00833 static const string NAME;
00834
00835
00836 };
00837
00838
00845 class Wiener2DFourierProcessor:public Processor
00846 {
00847 public:
00848 string get_name() const
00849 {
00850 return NAME;
00851 }
00852
00853 virtual EMData* process(const EMData * const image);
00854
00855 void process_inplace(EMData *image);
00856
00857 void set_params(const Dict & new_params)
00858 {
00859 params = new_params;
00860 ctf = params["ctf"];
00861
00862 }
00863
00864 TypeDict get_param_types() const
00865 {
00866 TypeDict d;
00867 d.put("ctf", EMObject::EMDATA, "Ctf object to use for Wiener filter parameters");
00868 return d;
00869 }
00870
00871 static Processor *NEW()
00872 {
00873 return new Wiener2DFourierProcessor();
00874 }
00875
00876 string get_desc() const
00877 {
00878 return "Applies a 2-D Wiener filter to an image based on its Ctf parameters";
00879 }
00880
00881 static const string NAME;
00882
00883 protected:
00884 Ctf *ctf;
00885 };
00886
00887 class LinearRampFourierProcessor:public FourierProcessor
00888 {
00889 public:
00890 virtual string get_name() const
00891 {
00892 return NAME;
00893 }
00894
00895 virtual string get_desc() const
00896 {
00897 return "";
00898 }
00899
00900 static Processor *NEW()
00901 {
00902 return new LinearRampFourierProcessor();
00903 }
00904
00905 static const string NAME;
00906
00907 protected:
00908 virtual void create_radial_func(vector < float >&radial_mask) const ;
00909 };
00910
00911
00914 class LowpassRandomPhaseProcessor:public FourierProcessor
00915 {
00916 public:
00917 string get_name() const
00918 { return NAME; }
00919 static Processor *NEW() { return new LowpassRandomPhaseProcessor(); }
00920 string get_desc() const
00921 {
00922 return "Above the cutoff frequency, phases will be completely randomized, but amplitudes will be unchanged. Used for testing for noise bias. If you can reconstruct information that isn't there, then you have noise bias problems.";
00923 }
00924 void process_inplace(EMData * image);
00925 void create_radial_func(vector < float >&radial_mask) const;
00926
00927 static const string NAME;
00928 };
00929
00930
00933 class LowpassAutoBProcessor:public FourierAnlProcessor
00934 {
00935 public:
00936 string get_name() const
00937 {
00938 return NAME;
00939 }
00940
00941 static Processor *NEW()
00942 {
00943 return new LowpassAutoBProcessor();
00944 }
00945
00946 string get_desc() const
00947 {
00948 return "This processor sharpens a map based on the concept that the power spectrum should be roughly flat over the ~15 A-Nyquist resolution range, then combines this inverse B-factor with the specified low-pass Gaussian filter parameters to produce a single aggregate Gaussian filter.";
00949 }
00950
00951 static const string NAME;
00952
00953 virtual TypeDict get_param_types() const
00954 {
00955 TypeDict d = FourierAnlProcessor::get_param_types();
00956 d.put("bfactor", EMObject::FLOAT, "B-factor in terms of e^-(B s^2/4)");
00957 d.put("noisecutoff", EMObject::FLOAT, "Spatial frequency past which inverse-B will not be applied");
00958
00959 d.put("verbose", EMObject::INT, "Print information about the determined B-factor");
00960 return d;
00961 }
00962
00963 protected:
00964 virtual void preprocess(EMData * image) {
00965 if(params.has_key("apix")) {
00966 image->set_attr("apix_x", (float)params["apix"]);
00967 image->set_attr("apix_y", (float)params["apix"]);
00968 image->set_attr("apix_z", (float)params["apix"]);
00969 }
00970 float apix=(float)image->get_attr("apix_x");
00971
00972 const Dict dict = image->get_attr_dict();
00973 if (params.has_key("cutoff_abs")) {
00974 params["bfactor"] = pow(apix/(float)params["cutoff_abs"],2.0f);
00975 }
00976 else if( params.has_key("cutoff_freq") ) {
00977 float val = (float)params["cutoff_freq"] * apix;
00978 params["cutoff_abs"] = val;
00979 params["bfactor"] = pow(apix/(float)params["cutoff_abs"],2.0f);
00980 }
00981 else if( params.has_key("cutoff_pixels") ) {
00982 float val = 0.5f*(float)params["cutoff_pixels"] / (float)dict["nx"];
00983 params["cutoff_abs"] = val;
00984 params["bfactor"] = pow(apix/(float)params["cutoff_abs"],2.0f);
00985 }
00986 }
00987
00988 void create_radial_func(vector < float >&radial_mask,EMData *image) const;
00989 };
00990
00993 class HighpassAutoPeakProcessor:public FourierAnlProcessor
00994 {
00995 public:
00996 string get_name() const
00997 {
00998 return NAME;
00999 }
01000 static Processor *NEW()
01001 {
01002 return new HighpassAutoPeakProcessor();
01003 }
01004
01005 string get_desc() const
01006 {
01007 return "Attempts to automatically remove the low resolution peak present in virtually all cryoEM data.";
01008 }
01009
01010 static const string NAME;
01011
01012 protected:
01013 void create_radial_func(vector < float >&radial_mask, EMData *image) const;
01014 virtual void preprocess(EMData * image);
01015 float highpass;
01016 };
01017
01022 class LinearRampProcessor:public FourierProcessor
01023 {
01024 public:
01025 LinearRampProcessor():intercept(0), slope(0)
01026 {
01027 }
01028
01029 string get_name() const
01030 {
01031 return NAME;
01032 }
01033 static Processor *NEW()
01034 {
01035 return new LinearRampProcessor();
01036 }
01037
01038 string get_desc() const
01039 {
01040 return "processor radial function: f(x) = slope * x + intercept;";
01041 }
01042
01043 void set_params(const Dict & new_params)
01044 {
01045 params = new_params;
01046 intercept = params["intercept"];
01047 slope = params["slope"];
01048 }
01049
01050 TypeDict get_param_types() const
01051 {
01052 TypeDict d;
01053 d.put("intercept", EMObject::FLOAT, "intercept in 'f(x) = slope * x + intercept'");
01054 d.put("slope", EMObject::FLOAT, "slope in 'f(x) = slope * x + intercept'");
01055 return d;
01056 }
01057
01058 static const string NAME;
01059
01060 protected:
01061 void create_radial_func(vector < float >&radial_mask) const;
01062
01063 private:
01064 float intercept;
01065 float slope;
01066 };
01067
01071 class LoGFourierProcessor:public FourierProcessor
01072 {
01073 public:
01074 LoGFourierProcessor():sigma(0)
01075 {
01076 }
01077
01078 string get_name() const
01079 {
01080 return NAME;
01081 }
01082 static Processor *NEW()
01083 {
01084 return new LoGFourierProcessor();
01085 }
01086
01087 string get_desc() const
01088 {
01089 return "processor radial function: f(x) = ((x^2 - s^2)/s^4)e^-(x^2/2s^2)";
01090 }
01091
01092 void set_params(const Dict & new_params)
01093 {
01094 params = new_params;
01095 sigma = params["sigma"];
01096 }
01097
01098 TypeDict get_param_types() const
01099 {
01100 TypeDict d;
01101 d.put("sigma", EMObject::FLOAT, "LoG sigma");
01102 return d;
01103 }
01104
01105 static const string NAME;
01106
01107 protected:
01108 void create_radial_func(vector < float >&radial_mask) const;
01109
01110 private:
01111 float sigma;
01112 };
01113
01118 class DoGFourierProcessor:public FourierProcessor
01119 {
01120 public:
01121 DoGFourierProcessor():sigma1(0), sigma2(0)
01122 {
01123 }
01124
01125 string get_name() const
01126 {
01127 return NAME;
01128 }
01129 static Processor *NEW()
01130 {
01131 return new DoGFourierProcessor();
01132 }
01133
01134 string get_desc() const
01135 {
01136 return "processor radial function: f(x) = 1/sqrt(2*pi)*[1/sigma1*exp-(x^2/2*sigma1^2) - 1/sigma2*exp-(x^2/2*sigma2^2)]";
01137 }
01138
01139 void set_params(const Dict & new_params)
01140 {
01141 params = new_params;
01142 sigma1 = params["sigma1"];
01143 sigma2 = params["sigma2"];
01144 }
01145
01146 TypeDict get_param_types() const
01147 {
01148 TypeDict d;
01149 d.put("sigma1", EMObject::FLOAT, "DoG sigma1");
01150 d.put("sigma2", EMObject::FLOAT, "DoG sigma2");
01151 return d;
01152 }
01153
01154 static const string NAME;
01155
01156 protected:
01157 void create_radial_func(vector < float >&radial_mask) const;
01158
01159 private:
01160 float sigma1;
01161 float sigma2;
01162 };
01163
01166 class RealPixelProcessor:public Processor
01167 {
01168 public:
01169 RealPixelProcessor():value(0), maxval(1), mean(0), sigma(0)
01170 {
01171 }
01172 void process_inplace(EMData * image);
01173
01174 virtual void set_params(const Dict & new_params)
01175 {
01176 params = new_params;
01177 if (params.size() == 1) {
01178 vector < EMObject > dict_values = params.values();
01179 value = dict_values[0];
01180 }
01181 }
01182
01183 static string get_group_desc()
01184 {
01185 return "The base class for real space processor working on individual pixels. The processor won't consider the pixel's coordinates and neighbors.";
01186 }
01187
01188 protected:
01189 virtual void process_pixel(float *x) const = 0;
01190 virtual void calc_locals(EMData *)
01191 {
01192 }
01193 virtual void normalize(EMData *) const
01194 {
01195 }
01196
01197 float value;
01198 float maxval;
01199 float mean;
01200 float sigma;
01201 };
01202
01205 class AbsoluateValueProcessor:public RealPixelProcessor
01206 {
01207 public:
01208 string get_name() const
01209 {
01210 return NAME;
01211 }
01212 static Processor *NEW()
01213 {
01214 return new AbsoluateValueProcessor();
01215 }
01216
01217 static const string NAME;
01218
01219 protected:
01220 void process_pixel(float *x) const
01221 {
01222 *x = fabs(*x);
01223 }
01224
01225 string get_desc() const
01226 {
01227 return "f(x) = |x|";
01228 }
01229 };
01230
01233 class FloorValueProcessor:public RealPixelProcessor
01234 {
01235 public:
01236 string get_name() const
01237 {
01238 return NAME;
01239 }
01240 static Processor *NEW()
01241 {
01242 return new FloorValueProcessor();
01243 }
01244
01245 static const string NAME;
01246
01247 protected:
01248 void process_pixel(float *x) const
01249 {
01250 *x = floor(*x);
01251 }
01252
01253 string get_desc() const
01254 {
01255 return "f(x) = floor(x)";
01256 }
01257 };
01258
01259
01262 class BooleanProcessor:public RealPixelProcessor
01263 {
01264 public:
01265 string get_name() const
01266 {
01267 return NAME;
01268 }
01269 static Processor *NEW()
01270 {
01271 return new BooleanProcessor();
01272 }
01273
01274 string get_desc() const
01275 {
01276 return "f(x) = 0 if x = 0; f(x) = 1 if x != 0;";
01277 }
01278
01279 static const string NAME;
01280
01281 protected:
01282 void process_pixel(float *x) const
01283 {
01284 if (*x != 0)
01285 {
01286 *x = 1.0;
01287 }
01288 }
01289 };
01290
01294 class InvertCarefullyProcessor:public RealPixelProcessor
01295 {
01296 public:
01297 string get_name() const
01298 {
01299 return NAME;
01300 }
01301 static Processor *NEW()
01302 {
01303 return new InvertCarefullyProcessor();
01304 }
01305
01306 void set_params(const Dict & new_params)
01307 {
01308 params = new_params;
01309 zero_to = params.set_default("zero_to",0.0f);
01310 }
01311
01312 TypeDict get_param_types() const
01313 {
01314 TypeDict d;
01315 d.put("zero_to", EMObject::FLOAT, "Inverted zero values are set to this value, default is 0.");
01316 return d;
01317 }
01318
01319 string get_desc() const
01320 {
01321 return "if f(x) != 0: f(x) = 1/f(x) else: f(x) = zero_to";
01322 }
01323
01324 static const string NAME;
01325
01326 protected:
01327 void process_pixel(float *x) const
01328 {
01329 if (*x == 0) *x = zero_to;
01330 else *x = 1/(*x);
01331 }
01332 private:
01333 float zero_to;
01334 };
01335
01339 class ValuePowProcessor:public RealPixelProcessor
01340 {
01341 public:
01342 string get_name() const
01343 {
01344 return NAME;
01345 }
01346 static Processor *NEW()
01347 {
01348 return new ValuePowProcessor();
01349 }
01350
01351 void set_params(const Dict & new_params)
01352 {
01353 params = new_params;
01354 pwr = params["pow"];
01355 }
01356
01357 TypeDict get_param_types() const
01358 {
01359 TypeDict d;
01360 d.put("pow", EMObject::FLOAT, "Each pixel is raised to this power");
01361 return d;
01362 }
01363
01364 string get_desc() const
01365 {
01366 return "f(x) = x ^ pow;";
01367 }
01368
01369 static const string NAME;
01370
01371 protected:
01372 void process_pixel(float *x) const
01373 {
01374 if (*x<0 && pwr!=(int)pwr) *x=0;
01375 else (*x) = pow(*x,pwr);
01376 }
01377 private:
01378 float pwr;
01379 };
01380
01383 class ValueSquaredProcessor:public RealPixelProcessor
01384 {
01385 public:
01386 string get_name() const
01387 {
01388 return NAME;
01389 }
01390 static Processor *NEW()
01391 {
01392 return new ValueSquaredProcessor();
01393 }
01394
01395
01396 string get_desc() const
01397 {
01398 return "f(x) = x * x;";
01399 }
01400
01401 static const string NAME;
01402
01403 protected:
01404 void process_pixel(float *x) const
01405 {
01406 (*x) *= (*x);
01407 }
01408 };
01409
01412 class ValueSqrtProcessor:public RealPixelProcessor
01413 {
01414 public:
01415 string get_name() const
01416 {
01417 return NAME;
01418 }
01419 static Processor *NEW()
01420 {
01421 return new ValueSqrtProcessor();
01422 }
01423
01424 string get_desc() const
01425 {
01426 return "f(x) = sqrt(x)";
01427 }
01428
01429 static const string NAME;
01430
01431 protected:
01432 void process_pixel(float *x) const
01433 {
01434 *x = sqrt(*x);
01435 }
01436 };
01437
01441 class ToZeroProcessor:public RealPixelProcessor
01442 {
01443 public:
01444 string get_name() const
01445 {
01446 return NAME;
01447 }
01448 static Processor *NEW()
01449 {
01450 return new ToZeroProcessor();
01451 }
01452 TypeDict get_param_types() const
01453 {
01454 TypeDict d;
01455 d.put("minval", EMObject::FLOAT, "Everything below this value is set to zero");
01456 return d;
01457 }
01458
01459 string get_desc() const
01460 {
01461 return "f(x) = x if x >= minval; f(x) = 0 if x < minval.";
01462 }
01463
01464 static const string NAME;
01465
01466 protected:
01467 inline void process_pixel(float *x) const
01468 {
01469 if (*x < value) {
01470 *x = 0;
01471 }
01472 }
01473 };
01474
01480 class Rotate180Processor:public Processor
01481 {
01482 public:
01483 string get_name() const
01484 {
01485 return NAME;
01486 }
01487 static Processor *NEW()
01488 {
01489 return new Rotate180Processor();
01490 }
01491
01495 void process_inplace(EMData* image);
01496
01497 string get_desc() const
01498 {
01499 return "The 2D image is rotated by 180 degree by carefully swapping image pixel values. No explicit matrix multiplication is performed. If image dimensions are even will change pixels along x=0 and y=0. Works for all combinations of even and oddness.";
01500 }
01501
01502 static const string NAME;
01503 };
01504
01511 class TransformProcessor:public Processor
01512 {
01513 public:
01514 virtual string get_name() const
01515 {
01516 return NAME;
01517 }
01518 static Processor *NEW()
01519 {
01520 return new TransformProcessor();
01521 }
01522
01527 virtual void process_inplace(EMData* image);
01528
01533 virtual EMData* process(const EMData* const image);
01534
01535 virtual TypeDict get_param_types() const
01536 {
01537 TypeDict d;
01538 d.put("transform", EMObject::TRANSFORM, "The Transform object that will be applied to the image" );
01539 return d;
01540 }
01541
01542 virtual string get_desc() const
01543 {
01544 return "The image is transformed using Transform parameter.";
01545 }
01546
01547 static const string NAME;
01548
01549 float* transform(const EMData* const image, const Transform& t) const;
01550 private:
01551
01552
01553
01554
01555 void assert_valid_aspect(const EMData* const image) const;
01556 };
01557
01565 class IntTranslateProcessor:public Processor
01566 {
01567 public:
01568 virtual string get_name() const
01569 {
01570 return NAME;
01571 }
01572
01573 static Processor *NEW()
01574 {
01575 return new IntTranslateProcessor();
01576 }
01577
01582 virtual void process_inplace(EMData* image);
01583
01588 virtual EMData* process(const EMData* const image);
01589
01590 virtual TypeDict get_param_types() const
01591 {
01592 TypeDict d;
01593 d.put("trans", EMObject::INTARRAY, "The displacement array, can be length 1-3" );
01594 return d;
01595 }
01596
01597 virtual string get_desc() const
01598 {
01599 return "The image is translated an integer amount";
01600 }
01601
01602 static const string NAME;
01603
01604 private:
01608 void assert_valid_aspect(const vector<int>& translation, const EMData* const image) const;
01609
01615 Region get_clip_region(vector<int>& translation, const EMData* const image) const;
01616 };
01617
01623 class ApplySymProcessor:public Processor
01624 {
01625 public:
01626 virtual string get_name() const
01627 {
01628 return NAME;
01629 }
01630
01631 static Processor *NEW()
01632 {
01633 return new ApplySymProcessor();
01634 }
01635
01636 virtual void process_inplace(EMData* image);
01637
01638 virtual EMData* process(const EMData* const image);
01639
01640 virtual TypeDict get_param_types() const
01641 {
01642 TypeDict d;
01643 d.put("sym", EMObject::STRING, "The symmetry under which to do the alignment, Default=c1" );
01644 return d;
01645 }
01646
01647 virtual string get_desc() const
01648 {
01649 return "Symmetry is applied to the 3D EM object";
01650 }
01651
01652 static const string NAME;
01653
01654 };
01655
01662 class ScaleTransformProcessor:public Processor
01663 {
01664 public:
01665 virtual string get_name() const
01666 {
01667 return NAME;
01668 }
01669 static Processor *NEW()
01670 {
01671 return new ScaleTransformProcessor();
01672 }
01677 virtual void process_inplace(EMData* image);
01678
01683 virtual EMData* process(const EMData* const image);
01684
01685 virtual TypeDict get_param_types() const
01686 {
01687 TypeDict d;
01688 d.put("scale", EMObject::FLOAT, "The amount by which to scale" );
01689 d.put("clip", EMObject::INT, "The length of each output dimension. Non sophisticated, output dimensions can't be different" );
01692 return d;
01693 }
01694
01695 virtual string get_desc() const
01696 {
01697 return "The image is scaled with the clip variable in mind, being sure to preserve as much pixel information as possible.";
01698 }
01699
01700 static const string NAME;
01701 };
01702
01709 class ClampingProcessor :public Processor
01710 {
01711 public:
01712 ClampingProcessor() : default_max(1.0), default_min(0.0) {}
01713
01714 string get_name() const
01715 {
01716 return NAME;
01717 }
01718 static Processor *NEW()
01719 {
01720 return new ClampingProcessor();
01721 }
01722
01723 void process_inplace(EMData *image);
01724
01725 TypeDict get_param_types() const
01726 {
01727 TypeDict d;
01728 d.put("minval", EMObject::FLOAT, "The pixel values that bounds the smallest pixel value in the output image" );
01729 d.put("maxval", EMObject::FLOAT, "The pixel values that bounds the largest pixel value in the output image" );
01730 d.put("tomean", EMObject::BOOL, "Replace outlying pixels values with the mean pixel value instead" );
01731 return d;
01732 }
01733
01734 string get_desc() const
01735 {
01736 return "This function clamps the min and max vals in the image at minval and maxval, respectively. In a sense this a bi-truncation of the data.";
01737 }
01738
01739 static const string NAME;
01740
01741 protected:
01742 float default_max, default_min;
01743 };
01744
01750 class NSigmaClampingProcessor : public ClampingProcessor
01751 {
01752 public:
01753 NSigmaClampingProcessor() : default_sigma(2.0) {}
01754
01755 string get_name() const
01756 {
01757 return NAME;
01758 }
01759
01760 static Processor *NEW()
01761 {
01762 return new NSigmaClampingProcessor();
01763 }
01764
01765 TypeDict get_param_types() const
01766 {
01767 TypeDict d;
01768 d.put("nsigma", EMObject::FLOAT, "The number (n) of sigmas to clamp min and max vals at, so that the clamped boundaries are mean-n*sigma and mean+n*sigma" );
01769 d.put("tomean", EMObject::BOOL, "Replace outlying pixels values with the mean pixel value instead" );
01770 return d;
01771 }
01772
01773 void process_inplace(EMData *image);
01774
01775 string get_desc() const
01776 {
01777 return "This function clamps the min and max vals in the image at minval and maxval at mean-n*sigma and mean+n*sigma, respectively. The parameter specified by the user is n, the default value of n is 2.";
01778 }
01779
01780 static const string NAME;
01781
01782 protected:
01783 float default_sigma;
01784 };
01785
01789 class ToMinvalProcessor:public Processor
01790 {
01791 public:
01792 string get_name() const
01793 {
01794 return NAME;
01795 }
01796 static Processor *NEW()
01797 {
01798 return new ToMinvalProcessor();
01799 }
01800
01801 void process_inplace(EMData *image);
01802
01803 TypeDict get_param_types() const
01804 {
01805 TypeDict d;
01806 d.put("minval", EMObject::FLOAT, "Everything below this value is set to this value");
01807 d.put("newval", EMObject::FLOAT, "If set, values below minval will be set to newval instead of minval ");
01808 return d;
01809 }
01810
01811 string get_desc() const
01812 {
01813 return "f(x) = x if x >= minval; f(x) = minval|newval if x < minval.";
01814 }
01815
01816 static const string NAME;
01817
01818 protected:
01819
01820 };
01821
01822
01823
01827 class CutToZeroProcessor:public RealPixelProcessor
01828 {
01829 public:
01830 string get_name() const
01831 {
01832 return NAME;
01833 }
01834 static Processor *NEW()
01835 {
01836 return new CutToZeroProcessor();
01837 }
01838 TypeDict get_param_types() const
01839 {
01840 TypeDict d;
01841 d.put("minval", EMObject::FLOAT, "the value that will be set to zero - all values below will also be set to zero. Values above get minval subtracted from them" );
01842 return d;
01843 }
01844
01845 string get_desc() const
01846 {
01847 return "f(x) = x-minval if x >= minval; f(x) = 0 if x < minval.";
01848 }
01849
01850 static const string NAME;
01851
01852 protected:
01853 void process_pixel(float *x) const
01854 {
01855 *x = *x - value;
01856 if (*x < 0) {
01857 *x = 0;
01858 }
01859 }
01860 };
01861
01865 class BinarizeProcessor:public RealPixelProcessor
01866 {
01867 public:
01868 string get_name() const
01869 {
01870 return NAME;
01871 }
01872 static Processor *NEW()
01873 {
01874 return new BinarizeProcessor();
01875 }
01876 TypeDict get_param_types() const
01877 {
01878 TypeDict d;
01879 d.put("value", EMObject::FLOAT, "The thresholding value. If a pixel value is equal to or above the threshold it is set to 1. If it is below it is set to 0" );
01880 return d;
01881 }
01882
01883 string get_desc() const
01884 {
01885 return "f(x) = 0 if x < value; f(x) = 1 if x >= value.";
01886 }
01887
01888 static const string NAME;
01889
01890 protected:
01891 void process_pixel(float *x) const
01892 {
01893 if (*x < value)
01894 {
01895 *x = 0;
01896 }
01897 else
01898 {
01899 *x = 1;
01900 }
01901 }
01902 };
01903
01911 class BinarizeFourierProcessor:public Processor
01912 {
01913 public:
01914 virtual string get_name() const
01915 {
01916 return NAME;
01917 }
01918 static Processor *NEW()
01919 {
01920 return new BinarizeFourierProcessor();
01921 }
01922
01927 virtual void process_inplace(EMData* image);
01928
01929 virtual TypeDict get_param_types() const
01930 {
01931 TypeDict d;
01932 d.put("value", EMObject::FLOAT, "The Fourier amplitude threshold cutoff" );
01933 return d;
01934 }
01935
01936 virtual string get_desc() const
01937 {
01938 return "f(k) = 0 + 0i if ||f(k)|| < value; f(k) = a + bi if ||f(k)|| >= value.";
01939 }
01940
01941 static const string NAME;
01942 };
01943
01948 class CollapseProcessor:public RealPixelProcessor
01949 {
01950 public:
01951 string get_name() const
01952 {
01953 return NAME;
01954 }
01955 static Processor *NEW()
01956 {
01957 return new CollapseProcessor();
01958 }
01959
01960 void set_params(const Dict & new_params)
01961 {
01962 params = new_params;
01963 range = params["range"];
01964 value = params["value"];
01965 }
01966
01967 TypeDict get_param_types() const
01968 {
01969 TypeDict d;
01970 d.put("range", EMObject::FLOAT, "The range about 'value' which will be collapsed to 'value'");
01971 d.put("value", EMObject::FLOAT, "The pixel value where the focus of the collapse operation is");
01972 return d;
01973 }
01974
01975 string get_desc() const
01976 {
01977 return "f(x): if v-r<x<v+r -> v; if x>v+r -> x-r; if x<v-r -> x+r";
01978 }
01979
01980 static const string NAME;
01981
01982 protected:
01983 void process_pixel(float *x) const
01984 {
01985 if (*x>value+range) *x-=range;
01986 else if (*x<value-range) *x+=range;
01987 else *x=value;
01988 }
01989 float range;
01990 };
01991
01996 class LinearXformProcessor:public RealPixelProcessor
01997 {
01998 public:
01999 LinearXformProcessor():shift(0), scale(0)
02000 {
02001 }
02002
02003 string get_name() const
02004 {
02005 return NAME;
02006 }
02007 static Processor *NEW()
02008 {
02009 return new LinearXformProcessor();
02010 }
02011
02012 void set_params(const Dict & new_params)
02013 {
02014 params = new_params;
02015 shift = params.get("shift");
02016 scale = params.get("scale");
02017 }
02018
02019 TypeDict get_param_types() const
02020 {
02021 TypeDict d;
02022 d.put("shift", EMObject::FLOAT, "The amount to shift pixel values by before scaling");
02023 d.put("scale", EMObject::FLOAT, "The scaling factor to be applied to pixel values");
02024 return d;
02025 }
02026
02027 string get_desc() const
02028 {
02029 return "linear transform processor: f(x) = x * scale + shift. This is equivalent to a regular contrast stretching operation";
02030 }
02031
02032 static const string NAME;
02033
02034 protected:
02035 void process_pixel(float *x) const
02036 {
02037 *x = (*x) * scale + shift;
02038 }
02039
02040 private:
02041 float shift;
02042 float scale;
02043 };
02044
02049 class ExpProcessor:public RealPixelProcessor
02050 {
02051 public:
02052 ExpProcessor():low(0), high(0)
02053 {
02054 }
02055
02056 string get_name() const
02057 {
02058 return NAME;
02059 }
02060
02061 static Processor *NEW()
02062 {
02063 return new ExpProcessor();
02064 }
02065
02066 void set_params(const Dict & new_params)
02067 {
02068 params = new_params;
02069 low = params.get("low");
02070 high = params.get("high");
02071 }
02072
02073 TypeDict get_param_types() const
02074 {
02075 TypeDict d;
02076 d.put("low", EMObject::FLOAT, "Pixels are divided by (low - high) prior to the exponential operation");
02077 d.put("high", EMObject::FLOAT, "Pixels are divided by (low - high) prior to the exponential operation");
02078 return d;
02079 }
02080
02081 string get_desc() const
02082 {
02083 return "f(x) = exp( x / low - high)";
02084 }
02085
02086 static const string NAME;
02087
02088 protected:
02092 void process_pixel(float *x) const
02093 {
02094 float v = *x / low - high;
02095 if (v > 40) {
02096 v = 40;
02097 }
02098 *x = exp(v);
02099 }
02100
02101 private:
02102 float low;
02103 float high;
02104 };
02105
02109 class FiniteProcessor:public RealPixelProcessor
02110 {
02111 public:
02112 FiniteProcessor():to(0)
02113 {
02114 }
02115
02116 string get_name() const
02117 {
02118 return NAME;
02119 }
02120
02121 static Processor *NEW()
02122 {
02123 return new FiniteProcessor();
02124 }
02125
02126 void set_params(const Dict & new_params)
02127 {
02128 if (new_params.has_key("to") )
02129 to = params["to"];
02130 }
02131
02132 TypeDict get_param_types() const
02133 {
02134 TypeDict d;
02135 d.put("to", EMObject::FLOAT, "Pixels which are not finite will be set to this value");
02136 return d;
02137 }
02138
02139 string get_desc() const
02140 {
02141 return "f(x) = f(x) if f(x) is finite | to if f(x) is not finite";
02142 }
02143
02144 static const string NAME;
02145
02146 protected:
02150 void process_pixel(float *x) const;
02151 private:
02152 float to;
02153 };
02154
02159 class RangeThresholdProcessor:public RealPixelProcessor
02160 {
02161 public:
02162 RangeThresholdProcessor():low(0), high(0)
02163 {
02164 }
02165
02166 string get_name() const
02167 {
02168 return NAME;
02169 }
02170 static Processor *NEW()
02171 {
02172 return new RangeThresholdProcessor();
02173 }
02174
02175 void set_params(const Dict & new_params)
02176 {
02177 params = new_params;
02178 low = params.get("low");
02179 high = params.get("high");
02180 }
02181
02182 TypeDict get_param_types() const
02183 {
02184 TypeDict d;
02185 d.put("low", EMObject::FLOAT, "The lower limit of the range that will be set to 1");
02186 d.put("high", EMObject::FLOAT, "The upper limit of the range that will be set to 1");
02187 return d;
02188 }
02189
02190 string get_desc() const
02191 {
02192 return "Range thresholding. A range of values is set to 1, all else is set to 0. f(x) = 1 if (low <= x <= high); else f(x) = 0";
02193 }
02194
02195 static const string NAME;
02196
02197 protected:
02198 void process_pixel(float *x) const
02199 {
02200 if (*x >= low && *x <= high) {
02201 *x = 1;
02202 }
02203 else {
02204 *x = 0;
02205 }
02206 }
02207 private:
02208 float low;
02209 float high;
02210
02211 };
02212
02217 class SigmaProcessor:public RealPixelProcessor
02218 {
02219 public:
02220 string get_name() const
02221 {
02222 return NAME;
02223 }
02224 static Processor *NEW()
02225 {
02226 return new SigmaProcessor();
02227 }
02228
02229 void set_params(const Dict & new_params)
02230 {
02231 params = new_params;
02232 value1 = params.get("value1");
02233 value2 = params.get("value2");
02234 }
02235
02236 TypeDict get_param_types() const
02237 {
02238 TypeDict d;
02239 d.put("value1", EMObject::FLOAT, "A number reflecting total standard deviations in the right direction");
02240 d.put("value2", EMObject::FLOAT, "A number reflecting total standard deviations in the left direction");
02241 return d;
02242 }
02243
02244 string get_desc() const
02245 {
02246 return "f(x) = mean if x<(mean-v2*sigma) or x>(mean+v1*sigma); else f(x) = x;";
02247 }
02248
02249 static const string NAME;
02250
02251 protected:
02252 void process_pixel(float *x) const
02253 {
02254 if (*x < (mean - value2 * sigma) || *x > (mean + value1 * sigma))
02255 {
02256 *x = mean;
02257 }
02258 }
02259
02260 private:
02261 float value1;
02262 float value2;
02263 };
02264
02267 class LogProcessor:public RealPixelProcessor
02268 {
02269 public:
02270 string get_name() const
02271 {
02272 return NAME;
02273 }
02274 static Processor *NEW()
02275 {
02276 return new LogProcessor();
02277 }
02278
02279 string get_desc() const
02280 {
02281 return "f(x) = log10(x) if x > 0; else f(x) = 0;";
02282 }
02283
02284 static const string NAME;
02285
02286 protected:
02287 void process_pixel(float *x) const
02288 {
02289 if (*x > 0)
02290 {
02291 *x = log10(*x);
02292 }
02293 else
02294 {
02295 *x = 0;
02296 }
02297 }
02298 };
02299
02302 class CoordinateProcessor:public Processor
02303 {
02304 public:
02305 CoordinateProcessor():nx(0), ny(0), nz(0), mean(0), sigma(0), maxval(0), is_complex(false)
02306 {
02307 }
02308 void process_inplace(EMData * image);
02309
02310 static string get_group_desc()
02311 {
02312 return "CoordinateProcessor applies processing based on a pixel's value and it coordinates. This is the base class. Specific coordinate processor should implement process_pixel().";
02313 }
02314
02315 protected:
02316 virtual void process_pixel(float *pixel, int xi, int yi, int zi) const = 0;
02317 virtual void calc_locals(EMData *)
02318 {
02319 }
02320 virtual bool is_valid() const
02321 {
02322 return true;
02323 }
02324
02325 int nx;
02326 int ny;
02327 int nz;
02328 float mean;
02329 float sigma;
02330 float maxval;
02331
02332 bool is_complex;
02333 };
02334
02342 class CircularMaskProcessor:public CoordinateProcessor
02343 {
02344 public:
02345 CircularMaskProcessor():inner_radius(0), outer_radius(0), inner_radius_square(0),
02346 outer_radius_square(0), dx(0), dy(0), dz(0), xc(0), yc(0), zc(0)
02347 {
02348 }
02349
02350 void set_params(const Dict & new_params)
02351 {
02352 params = new_params;
02353
02354 if (params.has_key("inner_radius")) {
02355 inner_radius = params["inner_radius"];
02356 inner_radius_square = inner_radius * inner_radius;
02357 }
02358 else {
02359 inner_radius = -1;
02360 inner_radius_square = -1;
02361 }
02362
02363 if (params.has_key("outer_radius")) {
02364 outer_radius = params["outer_radius"];
02365 outer_radius_square = outer_radius * outer_radius;
02366 }
02367 else {
02368 outer_radius = INT_MAX;
02369 outer_radius_square = INT_MAX;
02370 }
02371
02372 if (params.has_key("xc")) xc = params["xc"];
02373 if (params.has_key("yc")) yc = params["yc"];
02374 if (params.has_key("zc")) zc = params["zc"];
02375 if (params.has_key("dx")) dx = params["dx"];
02376 if (params.has_key("dy")) dy = params["dy"];
02377 if (params.has_key("dz")) dz = params["dz"];
02378 }
02379
02380 string get_desc() const
02381 {
02382 return "CircularMaskProcessor applies a circular mask to the data.This is the base class for specific circular mask processors.Its subclass must implement process_dist_pixel().";
02383 }
02384
02385 TypeDict get_param_types() const
02386 {
02387 TypeDict d;
02388
02389 d.put("inner_radius", EMObject::INT, "inner mask radius. optional");
02390 d.put("outer_radius", EMObject::INT, "outer mask radius. Negative value -> box radius + outer_radius +1");
02391
02392 d.put("dx", EMObject::FLOAT,
02393 "Modify mask center by dx relative to the default center nx/2");
02394 d.put("dy", EMObject::FLOAT,
02395 "Modify mask center by dy relative to the default center ny/2");
02396 d.put("dz", EMObject::FLOAT,
02397 "Modify mask center by dz relative to the default center nz/2");
02398
02399 return d;
02400 }
02401 protected:
02402 void calc_locals(EMData * image);
02403
02404 bool is_valid() const
02405 {
02406 return (!is_complex);
02407 }
02408
02409 void process_pixel(float *pixel, int xi, int yi, int zi) const
02410 {
02411 float dist = (xi - xc) * (xi - xc) + (yi - yc) * (yi - yc) + (zi - zc) * (zi - zc);
02412 process_dist_pixel(pixel, dist);
02413 }
02414
02415 virtual void process_dist_pixel(float *pixel, float dist) const = 0;
02416
02417 int inner_radius;
02418 int outer_radius;
02419 int inner_radius_square;
02420 int outer_radius_square;
02421 float dx, dy, dz;
02422 float xc, yc, zc;
02423 };
02424
02428 class MaskSharpProcessor:public CircularMaskProcessor
02429 {
02430 public:
02431 MaskSharpProcessor():value(0)
02432 {
02433 }
02434
02435 string get_name() const
02436 {
02437 return NAME;
02438 }
02439 static Processor *NEW()
02440 {
02441 return new MaskSharpProcessor();
02442 }
02443
02444 void set_params(const Dict & new_params)
02445 {
02446 CircularMaskProcessor::set_params(new_params);
02447 value = params.set_default("value",0.0f);
02448 }
02449
02450 TypeDict get_param_types() const
02451 {
02452 TypeDict d = CircularMaskProcessor::get_param_types();
02453 d.put("value", EMObject::FLOAT, "step cutoff to this value. Default is 0.");
02454 return d;
02455 }
02456
02457 string get_desc() const
02458 {
02459 return "step cutoff to a user-given value in both inner and outer circles.";
02460 }
02461
02462 static const string NAME;
02463
02464 protected:
02465 void process_dist_pixel(float *pixel, float dist) const
02466 {
02467 if (dist >= outer_radius_square || dist < inner_radius_square)
02468 {
02469 *pixel = value;
02470 }
02471 }
02472
02473 float value;
02474 };
02475
02476
02480 class MaskEdgeMeanProcessor:public CircularMaskProcessor
02481 {
02482 public:
02483 string get_name() const
02484 {
02485 return NAME;
02486 }
02487 static Processor *NEW()
02488 {
02489 return new MaskEdgeMeanProcessor();
02490 }
02491
02492 void set_params(const Dict & new_params)
02493 {
02494 CircularMaskProcessor::set_params(new_params);
02495 ring_width = params["ring_width"];
02496 if (ring_width == 0) {
02497 ring_width = 1;
02498 }
02499 }
02500
02501 TypeDict get_param_types() const
02502 {
02503 TypeDict d = CircularMaskProcessor::get_param_types();
02504 d.put("ring_width", EMObject::INT, "The width of the mask ring.");
02505 return d;
02506 }
02507
02508 string get_desc() const
02509 {
02510 return "A step cutoff to the the mean value in a ring centered on the outer radius";
02511 }
02512
02513 static const string NAME;
02514
02515 protected:
02516 void calc_locals(EMData * image);
02517
02518
02519 void process_dist_pixel(float *pixel, float dist) const
02520 {
02521 if (dist >= outer_radius_square || dist < inner_radius_square){
02522 *pixel = ring_avg;
02523 }
02524 }
02525
02526 private:
02527 int ring_width;
02528 float ring_avg;
02529 };
02530
02533 class MaskNoiseProcessor:public CircularMaskProcessor
02534 {
02535 public:
02536 string get_name() const
02537 {
02538 return NAME;
02539 }
02540 static Processor *NEW()
02541 {
02542 return new MaskNoiseProcessor();
02543 }
02544
02545 string get_desc() const
02546 {
02547 return "fills masked region";
02548 }
02549
02550 static const string NAME;
02551
02552 protected:
02553 void process_dist_pixel(float *pixel, float dist) const
02554 {
02555 if (dist >= outer_radius_square || dist < inner_radius_square)
02556 {
02557 *pixel = Util::get_gauss_rand(mean, sigma);
02558 }
02559 }
02560 };
02561
02564 class MaskGaussProcessor:public CircularMaskProcessor
02565 {
02566 public:
02567 string get_name() const
02568 {
02569 return NAME;
02570 }
02571 static Processor *NEW()
02572 {
02573 return new MaskGaussProcessor();
02574 }
02575
02576 void set_params(const Dict & new_params)
02577 {
02578 CircularMaskProcessor::set_params(new_params);
02579 exponent = params["exponent"];
02580 if (exponent <= 0.0) {
02581 exponent = 2.0;
02582 }
02583 }
02584
02585 TypeDict get_param_types() const
02586 {
02587 TypeDict d = CircularMaskProcessor::get_param_types();
02588 d.put("exponent", EMObject::FLOAT, "The exponent, f in e^-Bs^f. default 2.0, producing a Gaussian");
02589 return d;
02590 }
02591
02592 string get_desc() const
02593 {
02594 return "a gaussian falloff to zero, radius is the 1/e of the width. If inner_radius>0, then \
02595 outer radius specifies width of Gaussian starting at inner_radius rather than total radius.";
02596 }
02597
02598 static const string NAME;
02599
02600 protected:
02601 float exponent;
02602 void process_dist_pixel(float *pixel, float dist) const
02603 {
02604 if (inner_radius_square>0) {
02605 if (dist>inner_radius_square) {
02606 if (exponent==2.0f) (*pixel) *= exp(-pow(sqrt(dist)-inner_radius,2.0f) / outer_radius_square);
02607 else (*pixel) *= exp(-pow(sqrt(dist)-inner_radius,exponent) / pow((float)outer_radius_square,exponent/2.0f));
02608 }
02609 }
02610 else {
02611 if (exponent==2.0f) (*pixel) *= exp(-dist / outer_radius_square);
02612 else (*pixel) *= exp(-pow(dist,exponent/2.0f) / pow((float)outer_radius_square,exponent/2.0f));
02613 }
02614 }
02615 };
02616
02623 class MaskGaussNonuniformProcessor:public CoordinateProcessor
02624 {
02625 public:
02626 MaskGaussNonuniformProcessor():radius_x(0), radius_y(0), radius_z(0), gauss_width(0)
02627 {
02628 }
02629
02630 void set_params(const Dict & new_params)
02631 {
02632 params = new_params;
02633
02634 if (params.has_key("radius_x")) radius_x=params["radius_x"];
02635 else radius_x=5.0;
02636
02637 if (params.has_key("radius_y")) radius_y=params["radius_y"];
02638 else radius_y=5.0;
02639
02640 if (params.has_key("radius_z")) radius_z=params["radius_z"];
02641 else radius_z=5.0;
02642
02643 if (params.has_key("gauss_width")) gauss_width=params["gauss_width"];
02644 else gauss_width=0.05f;
02645 }
02646
02647 TypeDict get_param_types() const
02648 {
02649 TypeDict d;
02650
02651 d.put("radius_x", EMObject::INT, "x-axis radius");
02652 d.put("radius_y", EMObject::INT, "y-axis radius");
02653 d.put("radius_z", EMObject::INT, "z-axis radius");
02654 d.put("gauss_width", EMObject::FLOAT, "Gaussian falloff width, relative to each radius, default 0.05");
02655
02656 return d;
02657 }
02658
02659 string get_name() const
02660 {
02661 return NAME;
02662 }
02663 static Processor *NEW()
02664 {
02665 return new MaskGaussNonuniformProcessor();
02666 }
02667
02668 string get_desc() const
02669 {
02670 return "A Gaussian falloff to zero. Nonisotropic, specify inner radius for x,y,z and Gaussian falloff width. Falloff \
02671 width is also nonisotropic and relative to the radii, with 1 being equal to the radius on that axis.";
02672 }
02673
02674 static const string NAME;
02675
02676 protected:
02677 void process_pixel(float *pixel, int xi, int yi, int zi) const
02678 {
02679 float dist = pow((xi - nx/2)/radius_x,2.0f) + pow((yi - ny/2)/radius_y,2.0f) + pow((zi - nz/2)/radius_z,2.0f);
02680 if (dist>1.0) (*pixel)*=exp(-pow((sqrt(dist)-1.0f)/gauss_width,2.0f));
02681 }
02682
02683 float radius_x,radius_y,radius_z,gauss_width;
02684 };
02685
02690 class MaskGaussInvProcessor:public CircularMaskProcessor
02691 {
02692 public:
02693 TypeDict get_param_types() const
02694 {
02695 TypeDict d = CircularMaskProcessor::get_param_types();
02696 d.put("gauss_width", EMObject::FLOAT, "Used to calculate the constant factor - gauss_width / (ny*ny)" );
02697 d.put("ring_width", EMObject::INT, "The width of the mask ring.");
02698 return d;
02699 }
02700
02701 string get_name() const
02702 {
02703 return NAME;
02704 }
02705
02706 static Processor *NEW()
02707 {
02708 return new MaskGaussInvProcessor();
02709 }
02710
02711 string get_desc() const
02712 {
02713 return "f(x) = f(x) / exp(-radius*radius * gauss_width / (ny*ny))";
02714 }
02715
02716 static const string NAME;
02717
02718 protected:
02719 void calc_locals(EMData *)
02720 {
02721 float gauss_width = params["gauss_width"];
02722 slice_value = gauss_width / (ny * ny);
02723 }
02724
02725 void process_dist_pixel(float *pixel, float dist) const
02726 {
02727 (*pixel) /= exp(-dist * slice_value);
02728 }
02729 private:
02730 float slice_value;
02731 };
02732
02733
02738 class LinearPyramidProcessor:public Processor
02739 {
02740 public:
02741 string get_name() const
02742 {
02743 return NAME;
02744 }
02745
02746 void process_inplace(EMData *image);
02747
02748 static Processor *NEW()
02749 {
02750 return new LinearPyramidProcessor();
02751 }
02752
02753 string get_desc() const
02754 {
02755 return "Multiplies image by a 'linear pyramid', 1-(|x-xsize/2|*|y-ysize/2|*4/(xsize*ysize))";
02756 }
02757
02758 static const string NAME;
02759 };
02760
02761
02764 class MakeRadiusSquaredProcessor:public CircularMaskProcessor
02765 {
02766 public:
02767 string get_name() const
02768 {
02769 return NAME;
02770 }
02771 static Processor *NEW()
02772 {
02773 return new MakeRadiusSquaredProcessor();
02774 }
02775
02776 string get_desc() const
02777 {
02778 return "overwrites input, f(x) = radius * radius";
02779 }
02780
02781 static const string NAME;
02782
02783 protected:
02784 void process_dist_pixel(float *pixel, float dist) const
02785 {
02786 *pixel = dist;
02787 }
02788 };
02789
02792 class MakeRadiusProcessor:public CircularMaskProcessor
02793 {
02794 public:
02795 string get_name() const
02796 {
02797 return NAME;
02798 }
02799 static Processor *NEW()
02800 {
02801 return new MakeRadiusProcessor();
02802 }
02803
02804 string get_desc() const
02805 {
02806 return "overwrites input, f(x) = radius;";
02807 }
02808
02809 static const string NAME;
02810
02811 protected:
02812 void process_dist_pixel(float *pixel, float dist) const
02813 {
02814 *pixel = sqrt(dist);
02815 }
02816 };
02817
02820 class ComplexPixelProcessor:public Processor
02821 {
02822 public:
02823 void process_inplace(EMData * image);
02824
02825 static string get_group_desc()
02826 {
02827 return "The base class for fourier space processor working on individual pixels. ri2ap() is called before processing, so individual pixels will be A/P rather than R/I. The processor won't consider the pixel's coordinates and neighbors.";
02828 }
02829
02830 protected:
02831 virtual void process_pixel(float *x) const = 0;
02832 };
02833
02836 class ComplexNormPixel:public ComplexPixelProcessor
02837 {
02838 public:
02839 string get_name() const
02840 {
02841 return NAME;
02842 }
02843 static Processor *NEW()
02844 {
02845 return new ComplexNormPixel();
02846 }
02847
02848 string get_desc() const
02849 {
02850 return "Each Fourier pixel will be normalized. ie - amp=1, phase=unmodified. Useful for performing phase-residual-like computations with dot products.";
02851 }
02852
02853 static const string NAME;
02854
02855 protected:
02856 void process_pixel(float *x) const
02857 {
02858 *x=1.0;
02859 }
02860 };
02861
02865 class AreaProcessor:public Processor
02866 {
02867 public:
02868 AreaProcessor():areasize(0), kernel(0), nx(0), ny(0), nz(0)
02869 {
02870 }
02871
02872 void process_inplace(EMData * image);
02873
02874 void set_params(const Dict & new_params)
02875 {
02876 params = new_params;
02877 areasize = params["areasize"];
02878 }
02879
02880 TypeDict get_param_types() const
02881 {
02882 TypeDict d;
02883 d.put("areasize", EMObject::INT, "The width of the area to process (not radius)");
02884 return d;
02885 }
02886
02887 string get_desc() const
02888 {
02889 return "AreaProcessor use pixel values and coordinates of a real-space square area. This is the base class. Specific AreaProcessor needs to implement function create_kernel().";
02890 }
02891
02892 protected:
02893 virtual void process_pixel(float *pixel, float, float, float, float *area_matrix) const
02894 {
02895 for (int i = 0; i < matrix_size; i++)
02896 {
02897 *pixel += area_matrix[i] * kernel[i];
02898 }
02899 }
02900
02901 virtual void create_kernel() const = 0;
02902
02903 int areasize;
02904 int matrix_size;
02905 float *kernel;
02906 int nx;
02907 int ny;
02908 int nz;
02909 };
02910
02913 class LaplacianProcessor:public AreaProcessor
02914 {
02915 public:
02916 string get_name() const
02917 {
02918 return NAME;
02919 }
02920 static Processor *NEW()
02921 {
02922 return new LaplacianProcessor();
02923 }
02924
02925 string get_desc() const
02926 {
02927 return "Discrete approximation to Laplacian. Edge enchancement, but works poorly in the presence of noise. Laplacian processor (x -> d^2/dx^2 + d^2/dy^2 + d^2/dz^2).";
02928 }
02929
02930 static const string NAME;
02931
02932 protected:
02933 void create_kernel() const;
02934
02935 };
02936
02939 class ZeroConstantProcessor:public AreaProcessor
02940 {
02941 public:
02942 string get_name() const
02943 {
02944 return NAME;
02945 }
02946 static Processor *NEW()
02947 {
02948 return new ZeroConstantProcessor();
02949 }
02950
02951 string get_desc() const
02952 {
02953 return "Contraction of data, if any nearest neighbor is 0, value -> 0, generally used iteratively";
02954 }
02955
02956 static const string NAME;
02957
02958 protected:
02959 void process_pixel(float *pixel, float, float, float, float *matrix) const
02960 {
02961 if (*pixel != 0)
02962 {
02963 if (*pixel == matrix[1] || *pixel == matrix[3] || *pixel == matrix[5] ||
02964 *pixel == matrix[7] || matrix[1] == 0 || matrix[3] == 0 ||
02965 matrix[5] == 0 || matrix[7] == 0) {
02966 *pixel = 0;
02967 }
02968 }
02969 }
02970
02971 void create_kernel() const
02972 {
02973 }
02974 };
02975
02984 class BoxStatProcessor:public Processor
02985 {
02986 public:
02987 void process_inplace(EMData * image);
02988
02989 static string get_group_desc()
02990 {
02991 return "BoxStatProcessor files are a kind of neighborhood processors. These processors compute every output pixel using information from a reduced region on the neighborhood of the input pixel. The classical form are the 3x3 processors. BoxStatProcessors could perform diverse tasks ranging from noise reduction, to differential , to mathematical morphology. BoxStatProcessor class is the base class. Specific BoxStatProcessor needs to define process_pixel(float *pixel, const float *array, int n).";
02992 }
02993
02994 TypeDict get_param_types() const
02995 {
02996 TypeDict d;
02997 d.put("radius", EMObject::INT, "The radius of the search box, default is 1 which results in a 3x3 box (3 = 2xradius + 1)");
02998 return d;
02999 }
03000
03001 protected:
03002 virtual void process_pixel(float *pixel, const float *array, int n) const = 0;
03003 };
03004
03005
03008 class BoxMedianProcessor:public BoxStatProcessor
03009 {
03010 public:
03011 string get_name() const
03012 {
03013 return NAME;
03014 }
03015 static Processor *NEW()
03016 {
03017 return new BoxMedianProcessor();
03018 }
03019
03020 string get_desc() const
03021 {
03022 return "A processor for noise reduction. pixel = median of values surrounding pixel.";
03023 }
03024
03025 static const string NAME;
03026
03027 protected:
03028 void process_pixel(float *pixel, const float *array, int n) const
03029 {
03030 float *data = new float[n];
03031 memcpy(data, array, sizeof(float) * n);
03032
03033 for (int i = 0; i <= n / 2; i++)
03034 {
03035 for (int j = i + 1; j < n; j++)
03036 {
03037 if (data[i] < data[j]) {
03038 float t = data[i];
03039 data[i] = data[j];
03040 data[j] = t;
03041 }
03042 }
03043 }
03044
03045 if (n % 2 != 0)
03046 {
03047 *pixel = data[n / 2];
03048 }
03049 else {
03050 *pixel = (data[n / 2] + data[n / 2 - 1]) / 2;
03051 }
03052 if( data )
03053 {
03054 delete[]data;
03055 data = 0;
03056 }
03057 }
03058 };
03059
03062 class BoxSigmaProcessor:public BoxStatProcessor
03063 {
03064 public:
03065 string get_name() const
03066 {
03067 return NAME;
03068 }
03069 static Processor *NEW()
03070 {
03071 return new BoxSigmaProcessor();
03072 }
03073
03074 string get_desc() const
03075 {
03076 return "pixel = standard deviation of values surrounding pixel.";
03077 }
03078
03079 static const string NAME;
03080
03081 protected:
03082 void process_pixel(float *pixel, const float *data, int n) const
03083 {
03084 float sum = 0;
03085 float square_sum = 0;
03086 for (int i = 0; i < n; i++)
03087 {
03088 sum += data[i];
03089 square_sum += data[i] * data[i];
03090 }
03091
03092 float mean = sum / n;
03093 *pixel = sqrt(square_sum / n - mean * mean);
03094 }
03095 };
03096
03099 class BoxMaxProcessor:public BoxStatProcessor
03100 {
03101 public:
03102 string get_name() const
03103 {
03104 return NAME;
03105 }
03106 static Processor *NEW()
03107 {
03108 return new BoxMaxProcessor();
03109 }
03110
03111 string get_desc() const
03112 {
03113 return "peak processor: pixel = max of values surrounding pixel.";
03114 }
03115
03116 static const string NAME;
03117
03118 protected:
03119 void process_pixel(float *pixel, const float *data, int n) const
03120 {
03121 float maxval = -FLT_MAX;
03122 for (int i = 0; i < n; i++)
03123 {
03124 if (data[i] > maxval) {
03125 maxval = data[i];
03126 }
03127 }
03128 *pixel = maxval;
03129 }
03130 };
03131
03134 class MinusPeakProcessor:public BoxStatProcessor
03135 {
03136 public:
03137 string get_name() const
03138 {
03139 return NAME;
03140 }
03141 static Processor *NEW()
03142 {
03143 return new MinusPeakProcessor();
03144 }
03145
03146 string get_desc() const
03147 {
03148 return "peak processor: pixel = pixel - max of values surrounding pixel. This is a sort of positive peak-finding algorithm.";
03149 }
03150
03151 static const string NAME;
03152
03153 protected:
03154 void process_pixel(float *pixel, const float *data, int n) const
03155 {
03156 float maxval = -FLT_MAX;
03157 for (int i = 0; i < n; i++)
03158 {
03159 if (data[i] > maxval) {
03160 maxval = data[i];
03161 }
03162 }
03163 *pixel -= maxval;
03164 }
03165 };
03166
03170 class PeakOnlyProcessor:public BoxStatProcessor
03171 {
03172 public:
03173 string get_name() const
03174 {
03175 return NAME;
03176 }
03177 static Processor *NEW()
03178 {
03179 return new PeakOnlyProcessor();
03180 }
03181 void set_params(const Dict & new_params)
03182 {
03183 params = new_params;
03184 npeaks = params["npeaks"];
03185 if (npeaks == 0) {
03186 npeaks = 1;
03187 }
03188 }
03189
03190 TypeDict get_param_types() const
03191 {
03192 TypeDict d;
03193 d.put("npeaks", EMObject::INT, "the number of surrounding peaks allow to >= pixel values");
03194 return d;
03195 }
03196
03197 string get_desc() const
03198 {
03199 return "peak processor -> if npeaks or more surrounding values >= value, value->0";
03200 }
03201
03202 static const string NAME;
03203
03204 protected:
03205 void process_pixel(float *pixel, const float *data, int n) const
03206 {
03207 int r = 0;
03208
03209 for (int i = 0; i < n; i++)
03210 {
03211 if (data[i] >= *pixel) {
03212 r++;
03213 }
03214 }
03215
03216 if (r > npeaks)
03217 {
03218 *pixel = 0;
03219 }
03220 }
03221 private:
03222 int npeaks;
03223 };
03224
03229 class DiffBlockProcessor:public Processor
03230 {
03231 public:
03232 void process_inplace(EMData * image);
03233
03234 string get_name() const
03235 {
03236 return NAME;
03237 }
03238 static Processor *NEW()
03239 {
03240 return new DiffBlockProcessor();
03241 }
03242
03243 string get_desc() const
03244 {
03245 return "averages over cal_half_width, then sets the value in a local block";
03246 }
03247
03248 TypeDict get_param_types() const
03249 {
03250 TypeDict d;
03251 d.put("cal_half_width", EMObject::FLOAT, "cal_half_width is dx/dy for calculating an average");
03252 d.put("fill_half_width", EMObject::FLOAT, "fill_half_width is dx/dy for fill/step");
03253 return d;
03254 }
03255
03256 static const string NAME;
03257 };
03258
03263 class CutoffBlockProcessor:public Processor
03264 {
03265 public:
03266 void process_inplace(EMData * image);
03267
03268 string get_name() const
03269 {
03270 return NAME;
03271 }
03272 static Processor *NEW()
03273 {
03274 return new CutoffBlockProcessor();
03275 }
03276
03277 TypeDict get_param_types() const
03278 {
03279 TypeDict d;
03280 d.put("value1", EMObject::FLOAT, "val1 is dx/dy");
03281 d.put("value2", EMObject::FLOAT, "val2 is lowpass freq cutoff in pixels");
03282 return d;
03283 }
03284
03285 string get_desc() const
03286 {
03287 return "Block processor, val1 is dx/dy, val2 is lp freq cutoff in pixels. Mystery processor.";
03288 }
03289
03290 static const string NAME;
03291 };
03292
03298 class BooleanShrinkProcessor
03299 {
03300 protected:
03308 template<class LogicOp>
03309 EMData* process(const EMData *const image, Dict& params);
03310
03317 template<class LogicOp>
03318 void process_inplace(EMData * image, Dict& params);
03319
03320 };
03321
03330 class MaxShrinkProcessor:public BooleanShrinkProcessor, public Processor
03331 {
03332 public:
03339 virtual EMData* process(const EMData *const image)
03340 {
03341 return BooleanShrinkProcessor::process<GreaterThan>(image, params);
03342 }
03343
03344
03345 virtual void process_inplace(EMData * image)
03346 {
03347 BooleanShrinkProcessor::process_inplace<GreaterThan>(image, params);
03348 }
03349
03350 string get_desc() const
03351 {
03352 return "Shrink an image by a given amount (default 2), using the maximum value found in the pixel neighborhood.";
03353 }
03354
03355 string get_name() const
03356 {
03357 return NAME;
03358 }
03359 static Processor *NEW()
03360 {
03361 return new MaxShrinkProcessor();
03362 }
03363
03364 TypeDict get_param_types() const
03365 {
03366 TypeDict d;
03367 d.put("n", EMObject::INT, "The shrink factor");
03368 d.put("search", EMObject::INT, "The search area (cubic volume width, usually the same as shrink)");
03369 return d;
03370 }
03371
03372 static const string NAME;
03373
03374 private:
03375 struct GreaterThan
03376 {
03377 inline bool operator()(float left,float right) const { return left > right; }
03378 inline float get_start_val() { return -10000000; }
03379 };
03380 };
03381
03390 class MinShrinkProcessor:public BooleanShrinkProcessor, public Processor
03391 {
03392 public:
03399 virtual EMData* process(const EMData *const image)
03400 {
03401 return BooleanShrinkProcessor::process<LessThan>(image, params);
03402 }
03403
03404
03405 virtual void process_inplace(EMData * image)
03406 {
03407 BooleanShrinkProcessor::process_inplace<LessThan>(image, params);
03408 }
03409 string get_desc() const
03410 {
03411 return "Shrink an image by a given amount (default 2), using the minimum value found in the pixel neighborhood.";
03412 }
03413
03414 string get_name() const
03415 {
03416 return NAME;
03417 }
03418 static Processor *NEW()
03419 {
03420 return new MinShrinkProcessor();
03421 }
03422
03423 TypeDict get_param_types() const
03424 {
03425 TypeDict d;
03426 d.put("n", EMObject::INT, "The shrink factor");
03427 d.put("search", EMObject::INT, "The search area (cubic volume width, usually the same as shrink)");
03428 return d;
03429 }
03430
03431 static const string NAME;
03432
03433 private:
03434 struct LessThan
03435 {
03436 inline bool operator()(float left,float right) const { return left < right; }
03437 inline float get_start_val() { return 9999999999.0f; }
03438 };
03439 };
03440
03447 class MeanShrinkProcessor : public Processor
03448 {
03449 public:
03460 virtual EMData* process(const EMData *const image);
03461
03468 virtual void process_inplace(EMData * image);
03469
03470 string get_desc() const
03471 {
03472 return "Shrink an image by a given amount , using the mean value found in the pixel neighborhood.";
03473 }
03474
03475 virtual string get_name() const
03476 {
03477 return NAME;
03478 }
03479 static Processor *NEW()
03480 {
03481 return new MeanShrinkProcessor();
03482 }
03483
03484 virtual TypeDict get_param_types() const
03485 {
03486 TypeDict d;
03487 d.put("n", EMObject::FLOAT, "The shrink factor");
03488 return d;
03489 }
03490
03491 static const string NAME;
03492
03493 private:
03501 void accrue_mean(EMData* to, const EMData *const from, const int shrinkfactor);
03502
03509 void accrue_mean_one_p_five(EMData* to, const EMData * const from);
03510 };
03511
03512
03519 class MedianShrinkProcessor : public Processor
03520 {
03521 public:
03532 virtual EMData* process(const EMData *const image);
03533
03540 virtual void process_inplace(EMData * image);
03541
03542 string get_desc() const
03543 {
03544 return "Shrink an image by a given amount , using the median value found in the pixel neighborhood.";
03545 }
03546
03547 virtual string get_name() const
03548 {
03549 return NAME;
03550 }
03551 static Processor *NEW()
03552 {
03553 return new MedianShrinkProcessor();
03554 }
03555
03556 virtual TypeDict get_param_types() const
03557 {
03558 TypeDict d;
03559 d.put("n", EMObject::INT, "The shrink factor");
03560 return d;
03561 }
03562
03563 static const string NAME;
03564
03565 private:
03573 void accrue_median(EMData* to, const EMData* const from,const int shrink_factor);
03574 };
03575
03576
03585 class FFTResampleProcessor : public Processor
03586 {
03587 public:
03588 virtual EMData* process(const EMData *const image);
03589
03590 virtual void process_inplace(EMData * image);
03591
03592 string get_desc() const
03593 {
03594 return "Robust resampling of an image by clipping its Fourier transform.";
03595 }
03596
03597 string get_name() const
03598 {
03599 return NAME;
03600 }
03601 static Processor *NEW()
03602 {
03603 return new FFTResampleProcessor();
03604 }
03605
03606 TypeDict get_param_types() const
03607 {
03608 TypeDict d;
03609 d.put("n", EMObject::FLOAT, "The sample rate. Less than one enlarges the image, greater than one shrinks it.");
03610 return d;
03611 }
03612
03613 static const string NAME;
03614
03615 private:
03622 void fft_resample(EMData* to, const EMData *const from, const float& sample_rate);
03623
03624 };
03625
03628 class GradientRemoverProcessor:public Processor
03629 {
03630 public:
03631 void process_inplace(EMData * image);
03632
03633 string get_name() const
03634 {
03635 return NAME;
03636 }
03637 static Processor *NEW()
03638 {
03639 return new GradientRemoverProcessor();
03640 }
03641
03642 string get_desc() const
03643 {
03644 return "Gradient remover, does a rough plane fit to find linear gradients.";
03645 }
03646
03647 static const string NAME;
03648 };
03649
03658 class GradientPlaneRemoverProcessor:public Processor
03659 {
03660 public:
03661 void process_inplace(EMData * image);
03662
03663 string get_name() const
03664 {
03665 return NAME;
03666 }
03667 static Processor *NEW()
03668 {
03669 return new GradientPlaneRemoverProcessor();
03670 }
03671
03672 string get_desc() const
03673 {
03674 return "Remove gradient by least square plane fit";
03675 }
03676
03677 TypeDict get_param_types() const
03678 {
03679 TypeDict d;
03680 d.put("mask", EMObject::EMDATA, "mask object: nonzero pixel positions will be used to fit plane. default = 0");
03681 d.put("changeZero", EMObject::INT, "if zero pixels are modified when removing gradient. default = 0");
03682 d.put("planeParam", EMObject::FLOATARRAY, "fitted plane parameters output");
03683 return d;
03684 }
03685
03686 static const string NAME;
03687 };
03688
03694 class NonConvexProcessor:public Processor
03695 {
03696 public:
03697 void process_inplace(EMData * image);
03698
03699 string get_name() const
03700 {
03701 return NAME;
03702 }
03703 static Processor *NEW()
03704 {
03705 return new NonConvexProcessor();
03706 }
03707
03708 string get_desc() const
03709 {
03710 return "Makes a curve or plane monotonically decreasing and non-convex. Useful in generating background curves from power spectra. Anchored at edges and (in 2d) at the center. If local value > mean(surrounding values) => mean(surrounding values).";
03711 }
03712
03713 TypeDict get_param_types() const
03714 {
03715 TypeDict d;
03716
03717
03718
03719 return d;
03720 }
03721
03722 static const string NAME;
03723 };
03724
03731 class FlattenBackgroundProcessor:public Processor
03732 {
03733 public:
03734 void process_inplace(EMData * image);
03735
03736 string get_name() const
03737 {
03738 return NAME;
03739 }
03740
03741 static Processor *NEW()
03742 {
03743 return new FlattenBackgroundProcessor();
03744 }
03745
03746 string get_desc() const
03747 {
03748 return "Flattens the background by subtracting the local mean";
03749 }
03750
03751 TypeDict get_param_types() const
03752 {
03753 TypeDict d;
03754 d.put("mask", EMObject::EMDATA, "A mask the defines the local neighborhood that will be used to find the local mean. Exclusive of the radius argument");
03755 d.put("radius", EMObject::INT, "The radius of circle/sphere that defines the local neighborhood. Exclusive of the mask argument");
03756 return d;
03757 }
03758
03759 static const string NAME;
03760 };
03761
03762
03765 class RampProcessor:public Processor
03766 {
03767 public:
03768 void process_inplace(EMData * image);
03769
03770 string get_name() const
03771 {
03772 return NAME;
03773 }
03774 static Processor *NEW()
03775 {
03776 return new RampProcessor();
03777 }
03778
03779 string get_desc() const
03780 {
03781 return "Ramp processor -- Fits a least-squares plane "
03782 "to the picture, and subtracts the plane from "
03783 "the picture. A wedge-shaped overall density "
03784 "profile can thus be removed from the picture.";
03785 }
03786
03787 static const string NAME;
03788 };
03789
03792 class VerticalStripeProcessor:public Processor
03793 {
03794 public:
03795 void process_inplace(EMData * image);
03796
03797 string get_name() const
03798 {
03799 return NAME;
03800 }
03801
03802 static Processor *NEW()
03803 {
03804 return new VerticalStripeProcessor();
03805 }
03806
03807 string get_desc() const
03808 {
03809 return "Tries to fix images scanned on the zeiss for poor ccd normalization.";
03810 }
03811
03812 static const string NAME;
03813 };
03814
03817 class RealToFFTProcessor:public Processor
03818 {
03819 public:
03820 void process_inplace(EMData *image);
03821
03822 string get_name() const
03823 {
03824 return NAME;
03825 }
03826
03827 static Processor *NEW()
03828 {
03829 return new RealToFFTProcessor();
03830 }
03831
03832 string get_desc() const
03833 {
03834 return "This will replace the image with a full-circle 2D fft amplitude rendering. Note that this renders amplitude, when intensity is more common.";
03835 }
03836
03837 static const string NAME;
03838 };
03839
03840
03843 class SigmaZeroEdgeProcessor:public Processor
03844 {
03845 public:
03846 void process_inplace(EMData * image);
03847
03848 string get_name() const
03849 {
03850 return NAME;
03851 }
03852 static Processor *NEW()
03853 {
03854 return new SigmaZeroEdgeProcessor();
03855 }
03856
03857 string get_desc() const
03858 {
03859 return "Fill zeroes at edges with nearest horizontal/vertical value.";
03860 }
03861
03862 static const string NAME;
03863 };
03864
03870 class BeamstopProcessor:public Processor
03871 {
03872 public:
03873 void process_inplace(EMData * image);
03874
03875 string get_name() const
03876 {
03877 return NAME;
03878 }
03879
03880 static Processor *NEW()
03881 {
03882 return new BeamstopProcessor();
03883 }
03884
03885 string get_desc() const
03886 {
03887 return "Try to eliminate beamstop in electron diffraction patterns. value1=sig multiplier; value2,value3 are x,y of center, if value1<0 also does radial subtract.";
03888 }
03889
03890 TypeDict get_param_types() const
03891 {
03892 TypeDict d;
03893 d.put("value1", EMObject::FLOAT, "sig multiplier");
03894 d.put("value2", EMObject::FLOAT, "x of center");
03895 d.put("value3", EMObject::FLOAT, "y of center");
03896 return d;
03897 }
03898
03899 static const string NAME;
03900 };
03901
03904 class MeanZeroEdgeProcessor:public Processor
03905 {
03906 public:
03907 void process_inplace(EMData * image);
03908
03909 string get_name() const
03910 {
03911 return NAME;
03912 }
03913
03914 static Processor *NEW()
03915 {
03916 return new MeanZeroEdgeProcessor();
03917 }
03918
03919 string get_desc() const
03920 {
03921 return "Fill zeroes at edges with nearest horizontal/vertical value damped towards Mean2.";
03922 }
03923
03924 static const string NAME;
03925 };
03926
03927
03930 class AverageXProcessor:public Processor
03931 {
03932 public:
03933 void process_inplace(EMData * image);
03934
03935 string get_name() const
03936 {
03937 return NAME;
03938 }
03939
03940 static Processor *NEW()
03941 {
03942 return new AverageXProcessor();
03943 }
03944
03945 string get_desc() const
03946 {
03947 return "Average along Y and replace with average";
03948 }
03949
03950 static const string NAME;
03951 };
03952
03956 class DecayEdgeProcessor:public Processor
03957 {
03958 public:
03959 void process_inplace(EMData * image);
03960 string get_name() const
03961 {
03962 return NAME;
03963 }
03964
03965 static Processor *NEW()
03966 {
03967 return new DecayEdgeProcessor();
03968 }
03969
03970 string get_desc() const
03971 {
03972 return "Decay edges of image to zero";
03973 }
03974
03975 TypeDict get_param_types() const
03976 {
03977 TypeDict d;
03978 d.put("width", EMObject::INT, "Width of the decay region around the edge of the image in pixels");
03979 return d;
03980 }
03981
03982 static const string NAME;
03983 };
03984
03991 class ZeroEdgeRowProcessor:public Processor
03992 {
03993 public:
03994 void process_inplace(EMData * image);
03995 string get_name() const
03996 {
03997 return NAME;
03998 }
03999
04000 static Processor *NEW()
04001 {
04002 return new ZeroEdgeRowProcessor();
04003 }
04004
04005 string get_desc() const
04006 {
04007 return "zero edges of image on top and bottom, and on left and right.";
04008 }
04009
04010 TypeDict get_param_types() const
04011 {
04012 TypeDict d;
04013 d.put("x0", EMObject::INT, "The number of columns to zero from left");
04014 d.put("x1", EMObject::INT, "The number of columns to zero from right");
04015 d.put("y0", EMObject::INT, "The number of rows to zero from the bottom");
04016 d.put("y1", EMObject::INT, "The number of rows to zero from the top");
04017 return d;
04018 }
04019
04020 static const string NAME;
04021 };
04022
04031 class ZeroEdgePlaneProcessor:public Processor
04032 {
04033 public:
04034 void process_inplace(EMData * image);
04035 string get_name() const
04036 {
04037 return NAME;
04038 }
04039
04040 static Processor *NEW()
04041 {
04042 return new ZeroEdgePlaneProcessor();
04043 }
04044
04045 string get_desc() const
04046 {
04047 return "zero edges of volume on all sides";
04048 }
04049
04050 TypeDict get_param_types() const
04051 {
04052 TypeDict d;
04053 d.put("x0", EMObject::INT, "The number of columns to zero from left");
04054 d.put("x1", EMObject::INT, "The number of columns to zero from right");
04055 d.put("y0", EMObject::INT, "The number of rows to zero from the bottom");
04056 d.put("y1", EMObject::INT, "The number of rows to zero from the top");
04057 d.put("z0", EMObject::INT, "The number of slices to zero from the bottom");
04058 d.put("z1", EMObject::INT, "The number of slices to zero from the top");
04059 return d;
04060 }
04061
04062 static const string NAME;
04063 };
04064
04065
04072 class BilateralProcessor:public Processor
04073 {
04074 public:
04075 void process_inplace(EMData * image);
04076 string get_name() const
04077 {
04078 return NAME;
04079 }
04080
04081 string get_desc() const
04082 {
04083 return "Bilateral processing on 2D or 3D volume data. Bilateral processing does non-linear weighted averaging processing within a certain window. ";
04084 }
04085
04086 static Processor *NEW()
04087 {
04088 return new BilateralProcessor();
04089 }
04090
04091 TypeDict get_param_types() const
04092 {
04093 TypeDict d;
04094 d.put("distance_sigma", EMObject::FLOAT, "means how large the voxel has impact on its neighbors in spatial domain. The larger it is, the more blurry the resulting image.");
04095 d.put("value_sigma", EMObject::FLOAT, "means how large the voxel has impact on its in range domain. The larger it is, the more blurry the resulting image.");
04096 d.put("niter", EMObject::INT, "how many times to apply this processing on your data.");
04097 d.put("half_width", EMObject::INT, "processing window size = (2 * half_widthh + 1) ^ 3.");
04098 return d;
04099 }
04100
04101 static const string NAME;
04102 };
04103
04106 class NormalizeProcessor:public Processor
04107 {
04108 public:
04109 void process_inplace(EMData * image);
04110
04111 static string get_group_desc()
04112 {
04113 return "Base class for normalization processors. Each specific normalization processor needs to define how to calculate mean and how to calculate sigma.";
04114 }
04115
04116 protected:
04117 virtual float calc_sigma(EMData * image) const;
04118 virtual float calc_mean(EMData * image) const = 0;
04119 };
04120
04123 class NormalizeUnitProcessor:public NormalizeProcessor
04124 {
04125 public:
04126 string get_name() const
04127 {
04128 return NAME;
04129 }
04130
04131 static Processor *NEW()
04132 {
04133 return new NormalizeUnitProcessor();
04134 }
04135
04136 string get_desc() const
04137 {
04138 return "Normalize an image so its vector length is 1.0.";
04139 }
04140
04141 static const string NAME;
04142
04143 protected:
04144 float calc_sigma(EMData * image) const;
04145 float calc_mean(EMData * image) const;
04146 };
04147
04148 inline float NormalizeUnitProcessor::calc_mean(EMData *) const { return 0; }
04149
04152 class NormalizeUnitSumProcessor:public NormalizeProcessor
04153 {
04154 public:
04155 string get_name() const
04156 {
04157 return NAME;
04158 }
04159
04160 static Processor *NEW()
04161 {
04162 return new NormalizeUnitSumProcessor();
04163 }
04164
04165 string get_desc() const
04166 {
04167 return "Normalize an image so its elements sum to 1.0 (fails if mean=0)";
04168 }
04169
04170 static const string NAME;
04171
04172 protected:
04173 float calc_sigma(EMData * image) const;
04174 float calc_mean(EMData * image) const;
04175 };
04176
04177 inline float NormalizeUnitSumProcessor::calc_mean(EMData *) const { return 0; }
04178
04179
04182 class NormalizeStdProcessor:public NormalizeProcessor
04183 {
04184 public:
04185 string get_name() const
04186 {
04187 return NAME;
04188 }
04189
04190 static Processor *NEW()
04191 {
04192 return new NormalizeStdProcessor();
04193 }
04194
04195 string get_desc() const
04196 {
04197 return "do a standard normalization on an image.";
04198 }
04199
04200 static const string NAME;
04201
04202 protected:
04203 float calc_mean(EMData * image) const;
04204 };
04205
04210 class NormalizeMaskProcessor:public NormalizeProcessor
04211 {
04212 public:
04213 string get_name() const
04214 {
04215 return NAME;
04216 }
04217
04218 string get_desc() const
04219 {
04220 return "Uses a 1/0 mask defining a region to use for the zero-normalization.if no_sigma is 1, standard deviation not modified.";
04221 }
04222
04223 static Processor *NEW()
04224 {
04225 return new NormalizeMaskProcessor();
04226 }
04227
04228 TypeDict get_param_types() const
04229 {
04230 TypeDict d;
04231 d.put("mask", EMObject::EMDATA, "the 1/0 mask defining a region to use for the zero-normalization");
04232 d.put("no_sigma", EMObject::INT, "if this flag is zero, only average under the mask will be substracted. set this flag to 1, standard deviation not modified");
04233 return d;
04234 }
04235
04236 static const string NAME;
04237
04238 protected:
04239 float calc_sigma(EMData * image) const;
04240 float calc_mean(EMData * image) const;
04241 };
04242
04248 class NormalizeRampNormVar: public Processor
04249 {
04250 public:
04251 string get_name() const
04252 {
04253 return NAME;
04254 }
04255
04256 static Processor *NEW()
04257 {
04258 return new NormalizeRampNormVar();
04259 }
04260
04261 string get_desc() const
04262 {
04263 return "First call filter.ramp on the image, then make the mean 0 and norm 1";
04264 }
04265
04266 void process_inplace(EMData * image);
04267
04268 static const string NAME;
04269 };
04270
04279 class NormalizeByMassProcessor: public Processor
04280 {
04281 public:
04282 string get_name() const
04283 {
04284 return NAME;
04285 }
04286
04287 static Processor *NEW()
04288 {
04289 return new NormalizeByMassProcessor();
04290 }
04291
04292 string get_desc() const
04293 {
04294 return "Normalize the mass of the image assuming a density of 1.35 g/ml (0.81 Da/A^3) (3D only)";
04295 }
04296
04297 TypeDict get_param_types() const
04298 {
04299 TypeDict d;
04300 d.put("apix", EMObject::FLOAT,"Angstrom per pixel of the image. If not set will use the apix_x attribute of the image");
04301 d.put("mass", EMObject::FLOAT,"The approximate mass of protein/structure in kilodaltons");
04302 d.put("thr", EMObject::FLOAT,"The isosurface threshold which encapsulates the structure");
04303 return d;
04304 }
04305
04306 void process_inplace(EMData * image);
04307
04308 static const string NAME;
04309 };
04310
04311
04314 class NormalizeEdgeMeanProcessor:public NormalizeProcessor
04315 {
04316 public:
04317 string get_name() const
04318 {
04319 return NAME;
04320 }
04321
04322 static Processor *NEW()
04323 {
04324 return new NormalizeEdgeMeanProcessor();
04325 }
04326
04327 string get_desc() const
04328 {
04329 return "normalizes an image, mean value equals to edge mean.";
04330 }
04331
04332 static const string NAME;
04333
04334 protected:
04335 float calc_mean(EMData * image) const;
04336 };
04337
04340 class NormalizeCircleMeanProcessor:public NormalizeProcessor
04341 {
04342 public:
04343 string get_name() const
04344 {
04345 return NAME;
04346 }
04347
04348 static Processor *NEW()
04349 {
04350 return new NormalizeCircleMeanProcessor();
04351 }
04352
04353 string get_desc() const
04354 {
04355 return "normalizes an image, mean value equals to mean of 2 pixel circular border.";
04356 }
04357
04358 static const string NAME;
04359
04360 protected:
04361 float calc_mean(EMData * image) const;
04362 };
04363
04366 class NormalizeLREdgeMeanProcessor:public NormalizeProcessor
04367 {
04368 public:
04369 string get_name() const
04370 {
04371 return NAME;
04372 }
04373
04374 static Processor *NEW()
04375 {
04376 return new NormalizeLREdgeMeanProcessor();
04377 }
04378
04379 string get_desc() const
04380 {
04381 return "normalizes an image, uses 2 pixels on left and right edge";
04382 }
04383
04384 static const string NAME;
04385
04386 protected:
04387 float calc_mean(EMData * image) const;
04388 };
04389
04392 class NormalizeMaxMinProcessor:public NormalizeProcessor
04393 {
04394 public:
04395 string get_name() const
04396 {
04397 return NAME;
04398 }
04399
04400 static Processor *NEW()
04401 {
04402 return new NormalizeMaxMinProcessor();
04403 }
04404
04405 string get_desc() const
04406 {
04407 return "normalizes an image. mean -> (maxval-minval)/2; std dev = (maxval+minval)/2;";
04408 }
04409
04410 static const string NAME;
04411
04412 protected:
04413 float calc_sigma(EMData * image) const;
04414 float calc_mean(EMData * image) const;
04415 };
04416
04419 class NormalizeRowProcessor:public Processor
04420 {
04421 public:
04422 string get_name() const
04423 {
04424 return NAME;
04425 }
04426
04427 static Processor *NEW()
04428 {
04429 return new NormalizeRowProcessor();
04430 }
04431
04432 string get_desc() const
04433 {
04434 return "normalizes each row in the image individually";
04435 }
04436
04437 static const string NAME;
04438
04439 void process_inplace(EMData * image);
04440 };
04441
04447 class NormalizeToLeastSquareProcessor:public Processor
04448 {
04449 public:
04450 void process_inplace(EMData * image);
04451
04452 string get_name() const
04453 {
04454 return NAME;
04455 }
04456
04457 static Processor *NEW()
04458 {
04459 return new NormalizeToLeastSquareProcessor();
04460 }
04461
04462 TypeDict get_param_types() const
04463 {
04464 TypeDict d;
04465 d.put("to", EMObject::EMDATA, "reference image normalize to");
04466 d.put("ignore_zero", EMObject::BOOL, "If set, ignores any pixels which are exactly zero in either image. Defaut = True.");
04467 d.put("low_threshold", EMObject::FLOAT, "only take into account the reference image's pixel value between high and low threshold (zero is always ignored)");
04468 d.put("high_threshold", EMObject::FLOAT, "only take into account the reference image's pixel value between high and low threshold (zero is always ignored)");
04469 return d;
04470 }
04471
04472 string get_desc() const
04473 {
04474 return "use least square method to normalize";
04475 }
04476
04477 static const string NAME;
04478 };
04479
04482 class RotationalAverageProcessor:public Processor
04483 {
04484 public:
04485 void process_inplace(EMData * image);
04486
04487 string get_name() const
04488 {
04489 return NAME;
04490 }
04491
04492 static Processor *NEW()
04493 {
04494 return new RotationalAverageProcessor();
04495 }
04496
04497 string get_desc() const
04498 {
04499 return "Makes image circularly/spherically symmetric.";
04500 }
04501
04502 static const string NAME;
04503 };
04504
04507 class RotationalSubstractProcessor:public Processor
04508 {
04509 public:
04510 virtual void process_inplace(EMData * image);
04511
04512 virtual string get_name() const
04513 {
04514 return NAME;
04515 }
04516
04517 static Processor *NEW()
04518 {
04519 return new RotationalSubstractProcessor();
04520 }
04521
04522 virtual string get_desc() const
04523 {
04524 return "subtracts circularly/spherically symmetric part of an image.";
04525 }
04526
04527 static const string NAME;
04528 };
04529
04535 class TransposeProcessor:public Processor
04536 {
04537 public:
04538
04543 virtual void process_inplace(EMData * image);
04544
04549 virtual EMData* process(const EMData * const image);
04550
04551 virtual string get_name() const
04552 {
04553 return NAME;
04554 }
04555
04556 static Processor *NEW()
04557 {
04558 return new TransposeProcessor();
04559 }
04560
04561 virtual TypeDict get_param_types() const
04562 {
04563 TypeDict d;
04564 return d;
04565 }
04566
04567 virtual string get_desc() const
04568 {
04569 return "Get the transpose of an image. Works for 2D only";
04570 }
04571
04572 static const string NAME;
04573 };
04574
04575
04579 class FlipProcessor:public Processor
04580 {
04581 public:
04582 virtual void process_inplace(EMData * image);
04583
04584 virtual string get_name() const
04585 {
04586 return NAME;
04587 }
04588
04589 static Processor *NEW()
04590 {
04591 return new FlipProcessor();
04592 }
04593
04594 virtual TypeDict get_param_types() const
04595 {
04596 TypeDict d;
04597 d.put("axis", EMObject::STRING, "'x', 'y', or 'z' axis.");
04598 return d;
04599 }
04600
04601 virtual string get_desc() const
04602 {
04603 return "Mirrors an image along the specified axis, preserving the center. This will introduce a plane of 0's for even box sizes. Use 'xform.mirror' processor to avoid the zero plane, but not preserve the center.";
04604 }
04605
04606 static const string NAME;
04607 };
04608
04609
04610
04611
04612
04613
04614
04615
04616
04617
04618
04619
04620
04621
04622
04623
04624
04625
04626
04627
04628
04629
04630
04631
04632
04633
04634
04635
04636
04637
04642 class AddNoiseProcessor:public Processor
04643 {
04644 public:
04645 virtual void process_inplace(EMData * image);
04646
04647 virtual string get_name() const
04648 {
04649 return NAME;
04650 }
04651
04652 static Processor *NEW()
04653 {
04654 return new AddNoiseProcessor();
04655 }
04656
04657 virtual TypeDict get_param_types() const
04658 {
04659 TypeDict d;
04660 d.put("noise", EMObject::FLOAT, "noise factor used to generate Gaussian distribution random noise");
04661 d.put("seed", EMObject::INT, "seed for random number generator");
04662 return d;
04663 }
04664
04665 virtual string get_desc() const
04666 {
04667 return "add noise to an image, image multiply by noise then add a random value";
04668 }
04669
04670 static const string NAME;
04671
04672 protected:
04673 virtual float get_sigma(EMData *)
04674 {
04675 return 1.0;
04676 }
04677 };
04678
04681 class AddSigmaNoiseProcessor:public AddNoiseProcessor
04682 {
04683 public:
04684 virtual string get_name() const
04685 {
04686 return NAME;
04687 }
04688
04689 static Processor *NEW()
04690 {
04691 return new AddSigmaNoiseProcessor();
04692 }
04693
04694 virtual string get_desc() const
04695 {
04696 return "add sigma noise.";
04697 }
04698
04699 static const string NAME;
04700
04701 protected:
04702 float get_sigma(EMData * image);
04703 };
04704
04713 class AddRandomNoiseProcessor:public Processor
04714 {
04715 public:
04716 virtual void process_inplace(EMData * image);
04717
04718 virtual string get_name() const
04719 {
04720 return NAME;
04721 }
04722
04723 static Processor *NEW()
04724 {
04725 return new AddRandomNoiseProcessor();
04726 }
04727
04728 virtual TypeDict get_param_types() const
04729 {
04730 TypeDict d;
04731 d.put("n", EMObject::INT);
04732 d.put("x0", EMObject::FLOAT);
04733 d.put("dx", EMObject::FLOAT);
04734 d.put("y", EMObject::FLOATARRAY);
04735 d.put("interpolation", EMObject::INT);
04736 d.put("seed", EMObject::INT, "seed for random number generator");
04737 return d;
04738 }
04739
04740 virtual string get_desc() const
04741 {
04742 return "add spectral noise to a complex image.";
04743 }
04744
04745 static const string NAME;
04746 };
04747
04753 class FourierToCornerProcessor:public Processor
04754 {
04755 public:
04761 virtual void process_inplace(EMData * image);
04762
04763 virtual string get_name() const
04764 {
04765 return NAME;
04766 }
04767
04768 static Processor *NEW()
04769 {
04770 return new FourierToCornerProcessor();
04771 }
04772
04773 virtual string get_desc() const
04774 {
04775 return "Undoes the xform.fourierorigin.tocenter processor";
04776 }
04777
04778 static const string NAME;
04779 };
04780
04781
04793 class FourierToCenterProcessor:public Processor
04794 {
04795 public:
04801 virtual void process_inplace(EMData * image);
04802
04803 virtual string get_name() const
04804 {
04805 return NAME;
04806 }
04807
04808 static Processor *NEW()
04809 {
04810 return new FourierToCenterProcessor();
04811 }
04812
04813 virtual string get_desc() const
04814 {
04815 return "Translates the origin in Fourier space from the corner to the center in y and z - works in 2D and 3D";
04816 }
04817
04818 static const string NAME;
04819 };
04820
04830 class Phase180Processor:public Processor
04831 {
04832 protected:
04845 void swap_corners_180(EMData * image);
04846
04858 void swap_central_slices_180(EMData * image);
04859
04866 void fourier_phaseshift180(EMData * image);
04867
04868 };
04869
04879 class PhaseToCenterProcessor:public Phase180Processor
04880 {
04881 public:
04882 virtual void process_inplace(EMData * image);
04883
04884 virtual string get_name() const
04885 {
04886 return NAME;
04887 }
04888
04889 static Processor *NEW()
04890 {
04891 return new PhaseToCenterProcessor();
04892 }
04893
04894 virtual string get_desc() const
04895 {
04896 return "Undoes the effect of the xform.phaseorigin.tocorner processor";
04897 }
04898
04899 static const string NAME;
04900 };
04901
04909 class PhaseToCornerProcessor:public Phase180Processor
04910 {
04911 public:
04912 virtual void process_inplace(EMData * image);
04913
04914 virtual string get_name() const
04915 {
04916 return NAME;
04917 }
04918
04919 static Processor *NEW()
04920 {
04921 return new PhaseToCornerProcessor();
04922 }
04923
04924 virtual string get_desc() const
04925 {
04926 return "Translates a centered image to the corner in a forward fashion";
04927 }
04928
04929 static const string NAME;
04930 };
04931
04936 class AutoMask2DProcessor:public Processor
04937 {
04938 public:
04939 virtual void process_inplace(EMData * image);
04940
04941 virtual string get_name() const
04942 {
04943 return NAME;
04944 }
04945
04946 static Processor *NEW()
04947 {
04948 return new AutoMask2DProcessor();
04949 }
04950
04951 virtual TypeDict get_param_types() const
04952 {
04953 TypeDict d;
04954 d.put("radius", EMObject::INT,"Pixel radius of a ball which is used to seed the flood filling operation. ");
04955 d.put("nmaxseed",EMObject::INT,"Use the n highest valued pixels in the map as a seed. Alternative to radius. Useful for viruses.");
04956 d.put("threshold", EMObject::FLOAT, "An isosurface threshold that suitably encases the mass.");
04957 d.put("sigma", EMObject::FLOAT, "Alternative to threshold based on mean + x*sigma");
04958 d.put("nshells", EMObject::INT, "The number of dilation operations");
04959 d.put("nshellsgauss", EMObject::INT, "number of Gaussian pixels to expand, following the dilation operations");
04960 d.put("return_mask", EMObject::BOOL, "If true the result of the operation will produce the mask, not the masked volume.");
04961 d.put("verbose", EMObject::INT, "How verbose to be (stdout)");
04962 return d;
04963 }
04964
04965 virtual string get_desc() const
04966 {
04967 return "2D version of mask.auto3d";
04968 }
04969
04970 static const string NAME;
04971 };
04972
04973
04980 class AutoMaskAsymUnit:public Processor
04981 {
04982 public:
04983 virtual void process_inplace(EMData * image);
04984
04985 virtual string get_name() const
04986 {
04987 return NAME;
04988 }
04989
04990 static Processor *NEW()
04991 {
04992 return new AutoMaskAsymUnit();
04993 }
04994
04995 virtual TypeDict get_param_types() const
04996 {
04997 TypeDict d;
04998 d.put("au", EMObject::INT, "The asymmetric unit to mask out. If this is -1 will mask all asymmetric units, giving each a unique number.");
04999 d.put("sym", EMObject::STRING, "The symmetry, for example, d7");
05000 return d;
05001 }
05002
05003 virtual string get_desc() const
05004 {
05005 return "Masks out a specific asymmetric unit of the given symmetry. If the au parameter is -1 will mask all asymmetric units, assigning the asymetric unit number to the masked area.";
05006 }
05007
05008 static const string NAME;
05009 };
05010
05015 class AutoMask3DProcessor:public Processor
05016 {
05017 public:
05018 virtual void process_inplace(EMData * image);
05019
05020 virtual string get_name() const
05021 {
05022 return NAME;
05023 }
05024
05025 static Processor *NEW()
05026 {
05027 return new AutoMask3DProcessor();
05028 }
05029
05030 virtual TypeDict get_param_types() const
05031 {
05032 TypeDict d;
05033 d.put("threshold1", EMObject::FLOAT);
05034 d.put("threshold2", EMObject::FLOAT);
05035 return d;
05036 }
05037
05038 virtual string get_desc() const
05039 {
05040 return "Tries to mask out only interesting density";
05041 }
05042
05043 static void search_nearby(float *dat, float *dat2, int nx, int ny, int nz, float thr);
05044 static void fill_nearby(float *dat2, int nx, int ny, int nz);
05045
05046 static const string NAME;
05047 };
05048
05056 class AutoMask3D2Processor:public Processor
05057 {
05058 public:
05059 virtual void process_inplace(EMData * image);
05060
05061 virtual string get_name() const
05062 {
05063 return NAME;
05064 }
05065
05066 static Processor *NEW()
05067 {
05068 return new AutoMask3D2Processor();
05069 }
05070
05071 virtual string get_desc() const
05072 {
05073 return "This will mask a 3-D volume using a 'flood filling' approach. It begins with a seed generated either as a sphere with \
05074 specified 'radius' or with the 'nmaxseed' highest values. It then includes any mass connected to the seed with value higher than 'threshold'.\
05075 Next, the mask is expanded by 'nshells'+'nshellsgauss'/2 voxels. Finally a gaussian low-pass filter is applied with a width of 'nshellsgauss'.";
05076 }
05077
05078 virtual TypeDict get_param_types() const
05079 {
05080 TypeDict d;
05081 d.put("radius", EMObject::INT,"Pixel radius of a ball which is used to seed the flood filling operation. ");
05082 d.put("nmaxseed",EMObject::INT,"Use the n highest valued pixels in the map as a seed. Alternative to radius. Useful for viruses.");
05083 d.put("threshold", EMObject::FLOAT, "An isosurface threshold that suitably encases the mass.");
05084 d.put("sigma", EMObject::FLOAT, "Alternative to threshold based on mean + x*sigma");
05085 d.put("nshells", EMObject::INT, "Number of 1-voxel shells to expand the mask by.");
05086 d.put("nshellsgauss", EMObject::INT, "Width in voxels of a Gaussian decay at the edge of the mask.");
05087 d.put("return_mask", EMObject::BOOL, "If true the result of the operation will produce the mask, not the masked volume.");
05088 d.put("verbose", EMObject::INT, "How verbose to be (stdout)");
05089 return d;
05090 }
05091
05092 static const string NAME;
05093 };
05094
05098 class AddMaskShellProcessor:public Processor
05099 {
05100 public:
05101 virtual void process_inplace(EMData * image);
05102
05103 virtual string get_name() const
05104 {
05105 return NAME;
05106 }
05107
05108 virtual string get_desc() const
05109 {
05110 return "Add additional shells/rings to an existing 1/0 mask image";
05111 }
05112
05113 static Processor *NEW()
05114 {
05115 return new AddMaskShellProcessor();
05116 }
05117
05118 virtual TypeDict get_param_types() const
05119 {
05120 TypeDict d;
05121 d.put("nshells", EMObject::INT, "number of shells to add");
05122 return d;
05123 }
05124
05125 static const string NAME;
05126 };
05127
05132 class PhaseToMassCenterProcessor:public Processor
05133 {
05134 public:
05135 virtual void process_inplace(EMData * image);
05136
05137 virtual string get_name() const
05138 {
05139 return NAME;
05140 }
05141
05142 static Processor *NEW()
05143 {
05144 return new PhaseToMassCenterProcessor();
05145 }
05146
05147 virtual string get_desc() const
05148 {
05149 return "centers the image the center of mass, which is calculated using Fourier phases, ignores old dx, dy.";
05150 }
05151
05152 virtual TypeDict get_param_types() const
05153 {
05154 TypeDict d;
05155 d.put("int_shift_only", EMObject::INT, "set to 1 only shift by integer, no interpolation");
05156 return d;
05157 }
05158
05159 static const string NAME;
05160 };
05161
05166 class ToMassCenterProcessor:public Processor
05167 {
05168 public:
05169 virtual void process_inplace(EMData * image);
05170
05171 virtual string get_name() const
05172 {
05173 return NAME;
05174 }
05175
05176 static Processor *NEW()
05177 {
05178 return new ToMassCenterProcessor();
05179 }
05180
05181 virtual string get_desc() const
05182 {
05183 return "ToMassCenterProcessor centers image at center of mass, with a threshold. Only values higher than the threshold are considered.";
05184 }
05185
05186 virtual TypeDict get_param_types() const
05187 {
05188 TypeDict d;
05189 d.put("int_shift_only", EMObject::INT, "set to 1 only shift by integer, no interpolation");
05190 d.put("threshold", EMObject::FLOAT, "Only values larger than the threshold are included in the center of mass computation. Default is 0.");
05191
05192 return d;
05193 }
05194
05195 static const string NAME;
05196 };
05197
05201 class ACFCenterProcessor:public Processor
05202 {
05203 public:
05204 virtual void process_inplace(EMData * image);
05205
05206 virtual string get_name() const
05207 {
05208 return NAME;
05209 }
05210
05211 static Processor *NEW()
05212 {
05213 return new ACFCenterProcessor();
05214 }
05215
05216 virtual string get_desc() const
05217 {
05218 return "Center image using self-convolution.";
05219 }
05220
05221 virtual TypeDict get_param_types() const
05222 {
05223 TypeDict d;
05224 return d;
05225 }
05226
05227 static const string NAME;
05228 };
05229
05234 class SNRProcessor:public Processor
05235 {
05236 public:
05237 virtual void process_inplace(EMData * image);
05238
05239 virtual string get_name() const
05240 {
05241 return NAME;
05242 }
05243
05244 static Processor *NEW()
05245 {
05246 return new SNRProcessor();
05247 }
05248
05249 virtual string get_desc() const
05250 {
05251 return "Processor the images by the estimated SNR in each image.if parameter 'wiener' is 1, then wiener processor the images using the estimated SNR with CTF amplitude correction.";
05252 }
05253
05254 virtual TypeDict get_param_types() const
05255 {
05256 TypeDict d;
05257 d.put("wiener", EMObject::INT, "if set to 1, then use wiener processor to process the images using the estimated SNR with CTF amplitude correction");
05258 d.put("snrfile", EMObject::STRING, "structure factor file name");
05259 return d;
05260 }
05261
05262 static const string NAME;
05263 };
05264
05268 class FileFourierProcessor:public Processor
05269 {
05270 public:
05271 virtual void process_inplace(EMData * image);
05272
05273 virtual string get_name() const
05274 {
05275 return NAME;
05276 }
05277
05278 virtual string get_desc() const
05279 {
05280 return "A fourier processor specified in a 2 column text file.";
05281 }
05282
05283 static Processor *NEW()
05284 {
05285 return new FileFourierProcessor();
05286 }
05287
05288 virtual TypeDict get_param_types() const
05289 {
05290 TypeDict d;
05291 d.put("filename", EMObject::STRING, "file name for a 2 column text file which specified a radial function data array.");
05292 return d;
05293 }
05294
05295 static const string NAME;
05296 };
05297
05308 class SymSearchProcessor:public Processor
05309 {
05310 public:
05311 virtual void process_inplace(EMData * image);
05312
05313 virtual string get_name() const
05314 {
05315 return NAME;
05316 }
05317
05318 virtual string get_desc() const
05319 {
05320 return "Identifiy the best symmetry in the given symmetry list for each pixel and then apply the best symmetry to each pixel.";
05321 }
05322
05323 static Processor *NEW()
05324 {
05325 return new SymSearchProcessor();
05326 }
05327
05328 virtual TypeDict get_param_types() const
05329 {
05330 TypeDict d;
05331 d.put("sym", EMObject::STRINGARRAY, "the list of symmetries to search");
05332 d.put("thresh", EMObject::FLOAT, "the minimal level of symmetry to be accepted (0-1)");
05333 d.put("output_symlabel", EMObject::INT, "if output the symmetry label map in which the pixel value is the index of symmetry in the symmetry list");
05334 d.put("symlabel_map", EMObject::EMDATA, "the optional return map when output_symlabel=1");
05335 return d;
05336 }
05337
05338 static const string NAME;
05339 };
05340
05346 class LocalNormProcessor:public Processor
05347 {
05348 public:
05349 void process_inplace(EMData * image);
05350
05351 virtual string get_name() const
05352 {
05353 return NAME;
05354 }
05355
05356 static Processor *NEW()
05357 {
05358 return new LocalNormProcessor();
05359 }
05360
05361 virtual string get_desc() const
05362 {
05363 return "This processor attempts to perform a 'local normalization' so low density and high density features will be on a more even playing field in an isosurface display. threshold is an isosurface threshold at which all desired features are visible, radius is a feature size over which to equalize.";
05364 }
05365
05366 virtual TypeDict get_param_types() const
05367 {
05368 TypeDict d;
05369 d.put("threshold", EMObject::FLOAT, "an isosurface threshold at which all desired features are visible");
05370 d.put("radius", EMObject::FLOAT, "a normalization size similar to an lp= value");
05371 d.put("apix", EMObject::FLOAT, "Angstrom per pixel ratio");
05372 return d;
05373 }
05374
05375 static const string NAME;
05376 };
05377
05382 class IndexMaskFileProcessor:public Processor
05383 {
05384 public:
05385 virtual void process_inplace(EMData * image);
05386
05387 virtual string get_name() const
05388 {
05389 return NAME;
05390 }
05391
05392 static Processor *NEW()
05393 {
05394 return new IndexMaskFileProcessor();
05395 }
05396
05397 virtual TypeDict get_param_types() const
05398 {
05399 TypeDict d;
05400 d.put("filename", EMObject::STRING, "mask image file name");
05401 d.put("ismaskset", EMObject::INT, "If set to 1, it will take a file containing a set of masks and apply the first mask to the image");
05402 return d;
05403 }
05404
05405 virtual string get_desc() const
05406 {
05407 return "Multiplies the image by the specified file using pixel indices. The images must be same size. If 'ismaskset=' is 1, it will take a file containing a set of masks and apply the first mask to the image.";
05408 }
05409
05410 static const string NAME;
05411 };
05412
05416 class CoordinateMaskFileProcessor:public Processor
05417 {
05418 public:
05419 virtual void process_inplace(EMData * image);
05420
05421 virtual string get_name() const
05422 {
05423 return NAME;
05424 }
05425
05426 static Processor *NEW()
05427 {
05428 return new CoordinateMaskFileProcessor();
05429 }
05430
05431 virtual string get_desc() const
05432 {
05433 return "Multiplies the image by the specified file using pixel coordinates instead of pixel indices. The images can be different size.";
05434 }
05435
05436 virtual TypeDict get_param_types() const
05437 {
05438 TypeDict d;
05439 d.put("filename", EMObject::STRING, "mask image file name");
05440 return d;
05441 }
05442
05443 static const string NAME;
05444 };
05445
05456 class PaintProcessor:public Processor
05457 {
05458 public:
05459 PaintProcessor():x(0), y(0), z(0),r1(0), v1(0.0), r2(0), v2(0.0)
05460 {
05461 }
05462
05463 virtual string get_name() const
05464 {
05465 return NAME;
05466 }
05467
05468 static Processor *NEW()
05469 {
05470 return new PaintProcessor();
05471 }
05472
05473 virtual string get_desc() const
05474 {
05475 return "Paints a circle with a decaying edge into the image. r<r1 -> v1, r1<r<r2 -> (v1,v2), r>r2 unchanged";
05476 }
05477
05478 virtual TypeDict get_param_types() const
05479 {
05480 TypeDict d;
05481 d.put("x", EMObject::INT, "x coordinate for Center of circle");
05482 d.put("y", EMObject::INT, "y coordinate for Center of circle");
05483 d.put("z", EMObject::INT, "z coordinate for Center of circle");
05484 d.put("r1", EMObject::INT, "Inner radius");
05485 d.put("v1", EMObject::FLOAT, "Inner value");
05486 d.put("r2", EMObject::INT, "Outter radius");
05487 d.put("v2", EMObject::FLOAT, "Outer Value");
05488 return d;
05489 }
05490
05491 virtual void set_params(const Dict & new_params)
05492 {
05493 params = new_params;
05494
05495 if (params.has_key("x")) x = params["x"];
05496 if (params.has_key("y")) y = params["y"];
05497 if (params.has_key("z")) z = params["z"];
05498 if (params.has_key("r1")) r1 = params["r1"];
05499 if (params.has_key("r2")) r2 = params["r2"];
05500 if (params.has_key("v1")) v1 = params["v1"];
05501 if (params.has_key("v2")) v2 = params["v2"];
05502 }
05503
05504 static const string NAME;
05505
05506 protected:
05507 virtual void process_inplace(EMData *image);
05508
05509 int x,y,z,r1;
05510 float v1;
05511 int r2;
05512 float v2;
05513
05514 };
05515
05516
05521 class DirectionalSumProcessor : public Processor
05522 {
05523 public:
05524 virtual string get_name() const
05525 {
05526 return NAME;
05527 }
05528
05529 static Processor *NEW()
05530 {
05531 return new DirectionalSumProcessor();
05532 }
05533
05537 virtual EMData* process(const EMData* const image);
05538
05542 virtual void process_inplace(EMData*) {
05543 throw InvalidCallException("The directional sum processor does not work inplace");
05544 }
05545
05546 virtual TypeDict get_param_types() const
05547 {
05548 TypeDict d;
05549 d.put("axis", EMObject::STRING,"The direction of the sum, either x,y or z. Returned axes are xy, xz or zy.");
05550 d.put("first", EMObject::INT,"The first position along the speficied axis to use in the sum. Neg val -> nx/y/z+first (default=0)");
05551 d.put("last", EMObject::INT,"The last position along the speficied axis to use in the sum. Neg val -> nx/y/z+last (default=-1)");
05552 return d;
05553 }
05554
05555 string get_desc() const
05556 {
05557 return "Calculates the projection of the image along one of the axial directions, either x, y or z";
05558 }
05559
05560 static const string NAME;
05561 };
05562
05570 class WatershedProcessor:public Processor
05571 {
05572 public:
05573 virtual void process_inplace(EMData * image);
05574
05575 virtual string get_name() const
05576 {
05577 return NAME;
05578 }
05579
05580 static Processor *NEW()
05581 {
05582 return new WatershedProcessor();
05583 }
05584
05585 virtual string get_desc() const
05586 {
05587 return "Does a watershed";
05588 }
05589
05590 virtual TypeDict get_param_types() const
05591 {
05592 TypeDict d;
05593 d.put("xpoints", EMObject::FLOATARRAY,"x coordinates");
05594 d.put("ypoints", EMObject::FLOATARRAY,"y coordinates");
05595 d.put("zpoints", EMObject::FLOATARRAY,"z coordinates");
05596 d.put("minval", EMObject::FLOAT,"min value");
05597 return d;
05598 }
05599
05600 static const string NAME;
05601
05602 private:
05603 vector<Vec3i > watershed(EMData* mask, EMData* image, const float& threshold, const Vec3i& cordinate, const int mask_value);
05604 vector<Vec3i > find_region(EMData* mask,const vector<Vec3i >& coords, const int mask_value, vector<Vec3i >& region);
05605
05606 };
05607
05617 template<class Type>
05618 class BinaryOperateProcessor : public Processor{
05619 public:
05624 virtual void process_inplace(EMData * image) {
05625 if ( ! params.has_key("with") ) throw InvalidParameterException("You must supply the \"with\" parameter");
05626 EMData* with = params["with"];
05627
05628 if ( with->get_xsize() != image->get_xsize() || with->get_ysize() != image->get_ysize() || with->get_zsize() != image->get_zsize() )
05629 throw ImageDimensionException("The images you are operating on do not have the same dimensions");
05630
05631 float* image_data = image->get_data();
05632 float* with_data = with->get_data();
05633
05634 std::transform(image_data,image_data+image->get_size(),with_data,image_data,Type::binary_operate);
05635 image->update();
05636 }
05637
05638 virtual string get_name() const
05639 {
05640 return op.get_name();
05641 }
05642
05643 virtual string get_desc() const
05644 {
05645 return op.get_desc();
05646 }
05647
05648 static Processor *NEW()
05649 {
05650 return new BinaryOperateProcessor<Type>();
05651 }
05652
05653 virtual TypeDict get_param_types() const
05654 {
05655 TypeDict d;
05656 d.put("with", EMObject::EMDATA,"The second image");
05657 return d;
05658 }
05659
05660 static const string NAME;
05661 private:
05662 Type op;
05663 };
05664
05665 class MaxPixelOperator {
05666 public:
05667 string get_name() const
05668 {
05669 return NAME;
05670 }
05671
05672 string get_desc() const
05673 {
05674 return "Compares pixels in two images, returning an image with the maximum pixel value in each pixel location";
05675 }
05676
05677 static float binary_operate(const float& left, const float& right) {
05678 if (left > right) return left;
05679 return right;
05680 }
05681
05682 static const string NAME;
05683 };
05684
05685 class MinPixelOperator {
05686 public:
05687 string get_name() const
05688 {
05689 return NAME;
05690 }
05691
05692 string get_desc() const
05693 {
05694 return "Compares pixels in two images, returning an image with the minimum pixel value in each pixel location";
05695 }
05696
05697 static float binary_operate(const float& left, const float& right) {
05698 if (left < right) return left;
05699 return right;
05700 }
05701
05702 static const string NAME;
05703 };
05704
05708 class MatchSFProcessor:public FourierAnlProcessor
05709 {
05710 public:
05711
05712 virtual string get_name() const
05713 {
05714 return NAME;
05715 }
05716
05717 virtual string get_desc() const
05718 {
05719 return "Filters the image so its 1-D power spectrum matches a second image";
05720 }
05721
05722 static Processor *NEW()
05723 {
05724 return new MatchSFProcessor();
05725 }
05726
05727 virtual TypeDict get_param_types() const
05728 {
05729 TypeDict d;
05730 d.put("to", EMObject::EMDATA, "The image to match with. Make sure apix values are correct.");
05731 return d;
05732 }
05733
05734 static const string NAME;
05735
05736 protected:
05737 void create_radial_func(vector < float >&radial_mask, EMData *image) const;
05738 };
05739
05740
05745 class SetSFProcessor:public FourierAnlProcessor
05746 {
05747 public:
05748
05749 virtual string get_name() const
05750 {
05751 return NAME;
05752 }
05753
05754 virtual string get_desc() const
05755 {
05756 return "Filters the image so its 1-D power spectrum matches a supplied X-Y curve";
05757 }
05758
05759 static Processor *NEW()
05760 {
05761 return new SetSFProcessor();
05762 }
05763
05764 virtual TypeDict get_param_types() const
05765 {
05766 TypeDict d;
05767 d.put("strucfac", EMObject::XYDATA, "An XYData object contaning the curve to be imposed as a function of S");
05768 d.put("apix", EMObject::FLOAT, " Override A/pix in the image header (changes x,y and z)");
05769 return d;
05770 }
05771
05772 static const string NAME;
05773
05774 protected:
05775 void create_radial_func(vector < float >&radial_mask, EMData *image) const;
05776 };
05777
05781 class SmartMaskProcessor:public Processor
05782 {
05783 public:
05784 virtual void process_inplace(EMData * image);
05785
05786 virtual string get_name() const
05787 {
05788 return NAME;
05789 }
05790
05791 static Processor *NEW()
05792 {
05793 return new SmartMaskProcessor();
05794 }
05795
05796 virtual string get_desc() const
05797 {
05798 return "Smart mask processor.";
05799 }
05800
05801 virtual TypeDict get_param_types() const
05802 {
05803 TypeDict d;
05804 d.put("mask", EMObject::FLOAT, "mask value");
05805 return d;
05806 }
05807
05808 static const string NAME;
05809 };
05810
05815 class IterBinMaskProcessor:public Processor
05816 {
05817 public:
05818 virtual void process_inplace(EMData * image);
05819
05820 virtual string get_name() const
05821 {
05822 return NAME;
05823 }
05824
05825 virtual string get_desc() const
05826 {
05827 return "Iterative expansion of a binary mask, val1 is number of pixels to expand, if val2!=0 will make a soft Gaussian edge starting after val2 pixels.";
05828 }
05829
05830 static Processor *NEW()
05831 {
05832 return new IterBinMaskProcessor();
05833 }
05834
05835 virtual TypeDict get_param_types() const
05836 {
05837 TypeDict d;
05838 d.put("val1", EMObject::FLOAT, "number of pixels to expand");
05839 d.put("val2", EMObject::FLOAT, "number of Gaussian pixels to expand, following the first expansion");
05840 return d;
05841 }
05842
05843 static const string NAME;
05844 };
05845
05848 class TestImageProcessor : public Processor
05849 {
05850 public:
05851 static string get_group_desc()
05852 {
05853 return "Base class for a group of 'processors' used to create test image.";
05854 }
05855
05856 protected:
05857 void preprocess(EMData * image);
05858 int nx, ny, nz;
05859 };
05860
05869 class TestImagePureGaussian : public TestImageProcessor
05870 {
05871 public:
05872 virtual void process_inplace(EMData * image);
05873
05874 virtual string get_name() const
05875 {
05876 return NAME;
05877 }
05878
05879 virtual string get_desc() const
05880 {
05881 return "Replace a source image as a strict Gaussian ";
05882 }
05883
05884 static Processor * NEW()
05885 {
05886 return new TestImagePureGaussian();
05887 }
05888
05889 virtual TypeDict get_param_types() const
05890 {
05891 TypeDict d;
05892 d.put("x_sigma", EMObject::FLOAT, "sigma value for this Gaussian blob on x direction");
05893 d.put("y_sigma", EMObject::FLOAT, "sigma value for this Gaussian blob on y direction");
05894 d.put("z_sigma", EMObject::FLOAT, "sigma value for this Gaussian blob on z direction");
05895 d.put("x_center", EMObject::FLOAT, "center for this Gaussian blob on x direction" );
05896 d.put("y_center", EMObject::FLOAT, "center for this Gaussian blob on y direction" );
05897 d.put("z_center", EMObject::FLOAT, "center for this Gaussian blob on z direction" );
05898 return d;
05899 }
05900
05901 static const string NAME;
05902 };
05903
05907 class TestImageFourierNoiseGaussian : public TestImageProcessor
05908 {
05909 public:
05910 virtual void process_inplace(EMData * image);
05911
05912 virtual string get_name() const
05913 {
05914 return NAME;
05915 }
05916
05917 virtual string get_desc() const
05918 {
05919 return "Replace a source image with pink Fourier noise, based on a Gaussian. Random phase.";
05920 }
05921
05922 static Processor * NEW()
05923 {
05924 return new TestImageFourierNoiseGaussian();
05925 }
05926
05927 virtual TypeDict get_param_types() const
05928 {
05929 TypeDict d;
05930 d.put("sigma", EMObject::FLOAT, "sigma value");
05931 return d;
05932 }
05933
05934 static const string NAME;
05935 };
05936
05941 class TestImageFourierNoiseProfile : public TestImageProcessor
05942 {
05943 public:
05944 virtual void process_inplace(EMData * image);
05945
05946 virtual string get_name() const
05947 {
05948 return NAME;
05949 }
05950
05951 virtual string get_desc() const
05952 {
05953 return "Replace a source image with Fourier noise using amplitude information that is stored in a profile.";
05954 }
05955
05956 static Processor * NEW()
05957 {
05958 return new TestImageFourierNoiseProfile();
05959 }
05960
05961 virtual TypeDict get_param_types() const
05962 {
05963 TypeDict d;
05964 d.put("profile", EMObject::FLOATARRAY, "The noise profile, squared amplitude. As in, what is the EMAN2CTF.background attribute");
05965 return d;
05966 }
05967
05968 static const string NAME;
05969 };
05970
05971
05976 class CTFSNRWeightProcessor : public TestImageProcessor
05977 {
05978 public:
05979 virtual void process_inplace(EMData * image);
05980
05981 virtual string get_name() const
05982 {
05983 return NAME;
05984 }
05985
05986 virtual string get_desc() const
05987 {
05988 return "Weight the amplitudes of an image based on radial noise and snr curves ";
05989 }
05990
05991 static Processor * NEW()
05992 {
05993 return new CTFSNRWeightProcessor();
05994 }
05995
05996 virtual TypeDict get_param_types() const
05997 {
05998 TypeDict d;
05999 d.put("noise", EMObject::FLOATARRAY, "The noise profile, squared amplitude. As in, what is the EMAN2CTF.background attribute");
06000 d.put("snr", EMObject::FLOATARRAY, "Squared amplitude divided by squared noise amplitude. As in, what is the EMAN2CTF.snr attribute");
06001 d.put("boost", EMObject::FLOAT, "Multiplicative signal boost");
06002 return d;
06003 }
06004
06005 static const string NAME;
06006 };
06007
06008
06009
06014 class TestImageLineWave : public TestImageProcessor
06015 {
06016 public:
06017 virtual void process_inplace(EMData * image);
06018
06019 virtual string get_name() const
06020 {
06021 return NAME;
06022 }
06023
06024 virtual string get_desc() const
06025 {
06026 return "Insert an oscillating sine wave into the pixel data";
06027 }
06028
06029 static Processor * NEW()
06030 {
06031 return new TestImageLineWave();
06032 }
06033
06034 virtual TypeDict get_param_types() const
06035 {
06036 TypeDict d;
06037 d.put("period", EMObject::FLOAT, "The period of the oscillating sine wave. Default 10.");
06038 return d;
06039 }
06040
06041 static const string NAME;
06042 };
06043
06044
06052 class TestTomoImage : public TestImageProcessor
06053 {
06054 public:
06058 virtual void process_inplace(EMData * image);
06059
06060 virtual string get_name() const
06061 {
06062 return NAME;
06063 }
06064
06065 virtual string get_desc() const
06066 {
06067 return "Make an image consisting various objects, useful for tomographic testing";
06068 }
06069
06070 static Processor * NEW()
06071 {
06072 return new TestTomoImage();
06073 }
06074
06075 static const string NAME;
06076
06077 private:
06078 void insert_solid_ellipse( EMData* image, const Region& region, const float& value, const Transform& t3d = Transform() );
06079 void insert_hollow_ellipse( EMData* image, const Region& region, const float& value, const int& radius, const Transform& t3d = Transform() );
06080 void insert_rectangle( EMData* image, const Region& region, const float& value, const Transform& t3d = Transform() );
06081 };
06082
06090 class TestImageGradient : public TestImageProcessor
06091 {
06092 public:
06093 virtual void process_inplace(EMData * image);
06094
06095 virtual string get_name() const
06096 {
06097 return NAME;
06098 }
06099
06100 virtual string get_desc() const
06101 {
06102 return "Make a gradient image of the form y=mx+b, where x is any of the image axes.";
06103 }
06104
06105 static Processor * NEW()
06106 {
06107 return new TestImageGradient();
06108 }
06109
06110 virtual TypeDict get_param_types() const
06111 {
06112 TypeDict d;
06113 d.put("axis", EMObject::STRING, "The axis the will be used to determine pixel values. Must be x,y or z");
06114 d.put("m", EMObject::FLOAT, "m in the equation m*axis+b. Default is 1.0");
06115 d.put("b", EMObject::FLOAT, "b in the equation m*axis+b. Default is 0.0");
06116 return d;
06117 }
06118
06119 static const string NAME;
06120 };
06121
06129 class TestImageAxes : public TestImageProcessor
06130 {
06131 public:
06136 virtual void process_inplace(EMData * image);
06137
06138 virtual string get_name() const
06139 {
06140 return NAME;
06141 }
06142
06143 virtual string get_desc() const
06144 {
06145 return "Make an image consisting of a single cross";
06146 }
06147
06148 static Processor * NEW()
06149 {
06150 return new TestImageAxes();
06151 }
06152
06153 virtual TypeDict get_param_types() const
06154 {
06155 TypeDict d;
06156 d.put("int", EMObject::FLOAT, "radius of the lines emanating from the origin");
06157 d.put("fill", EMObject::FLOAT, "value to make non-zero pixels");
06158 return d;
06159 }
06160
06161 static const string NAME;
06162 };
06163
06169 class TestImageGaussian : public TestImageProcessor
06170 {
06171 public:
06172 virtual void process_inplace(EMData * image);
06173
06174 virtual string get_name() const
06175 {
06176 return NAME;
06177 }
06178
06179 virtual string get_desc() const
06180 {
06181 return "Replace a source image as a Gaussian Blob";
06182 }
06183
06184 static Processor * NEW()
06185 {
06186 return new TestImageGaussian();
06187 }
06188
06189 virtual TypeDict get_param_types() const
06190 {
06191 TypeDict d;
06192 d.put("sigma", EMObject::FLOAT, "sigma value for this Gaussian blob");
06193 d.put("axis", EMObject::STRING, "specify a major axis for asymmetric features");
06194 d.put("c", EMObject::FLOAT, "distance between focus and the center of an ellipse");
06195 return d;
06196 }
06197
06198 static const string NAME;
06199 };
06200
06203 class TestImageScurve : public TestImageProcessor
06204 {
06205 public:
06206 virtual void process_inplace(EMData * image);
06207
06208 virtual string get_name() const
06209 {
06210 return NAME;
06211 }
06212
06213 virtual string get_desc() const
06214 {
06215 return "Replace a source image with a lumpy S-curve used for alignment testing";
06216 }
06217
06218 static Processor * NEW()
06219 {
06220 return new TestImageScurve();
06221 }
06222
06223 virtual TypeDict get_param_types() const
06224 {
06225 TypeDict d;
06226 return d;
06227 }
06228
06229 static const string NAME;
06230 };
06231
06239 class TestImageSphericalWave : public TestImageProcessor
06240 {
06241 public:
06242 virtual void process_inplace(EMData * image);
06243
06244 virtual string get_name() const
06245 {
06246 return NAME;
06247 }
06248
06249 virtual string get_desc() const
06250 {
06251 return "Replace a source image in 2d or 3d with a spherical wave cos(2*pi*r/wavelength+phase) also 1/r (2d) or 1/r^2 (3d)";
06252 }
06253
06254 static Processor * NEW()
06255 {
06256 return new TestImageSphericalWave();
06257 }
06258
06259 virtual TypeDict get_param_types() const
06260 {
06261 TypeDict d;
06262 d.put("wavelength", EMObject::FLOAT, "cos(2*pi*r/wavelength+phase)");
06263 d.put("phase", EMObject::FLOAT, "in radians");
06264 d.put("x", EMObject::FLOAT, "center of the spherical wave");
06265 d.put("y", EMObject::FLOAT, "center of the spherical wave");
06266 d.put("z", EMObject::FLOAT, "center of the spherical wave");
06267 return d;
06268 }
06269
06270 static const string NAME;
06271 };
06272
06273
06282 class TestImageSinewave : public TestImageProcessor
06283 {
06284 public:
06285 virtual void process_inplace(EMData * image);
06286
06287 virtual string get_name() const
06288 {
06289 return NAME;
06290 }
06291
06292 virtual string get_desc() const
06293 {
06294 return "Replace a source image as a sine wave in specified wave length";
06295 }
06296
06297 static Processor * NEW()
06298 {
06299 return new TestImageSinewave();
06300 }
06301
06302 virtual TypeDict get_param_types() const
06303 {
06304 TypeDict d;
06305 d.put("wavelength", EMObject::FLOAT, "wavelength in equation sin(x*2*PI/wavelength - phase*180/PI)");
06306 d.put("axis", EMObject::STRING, "(optional) specify a major axis for asymmetric features, default x axis");
06307 d.put("phase", EMObject::FLOAT, "(optional) the phase in radians");
06308 d.put("az", EMObject::FLOAT, "(optional) angle in degree. for 2D image, this is the rotated angle of the image, \
06309 in 3D image, it's az for euler angle. default is zero");
06310 d.put("alt", EMObject::FLOAT, "(optional) angle in degree. only in 3D case, alt for euler angle, default is zero");
06311 d.put("phi", EMObject::FLOAT, "(optional) angle in degree. only in 3D case, phi for euler angle, default is zero");
06312 return d;
06313 }
06314
06315 static const string NAME;
06316 };
06317
06324 class TestImageSinewaveCircular : public TestImageProcessor
06325 {
06326 public:
06327 virtual void process_inplace(EMData * image);
06328
06329 virtual string get_name() const
06330 {
06331 return NAME;
06332 }
06333
06334 virtual string get_desc() const
06335 {
06336 return "Replace a source image as a circular sine wave in specified wave length";
06337 }
06338
06339 static Processor * NEW()
06340 {
06341 return new TestImageSinewaveCircular();
06342 }
06343
06344 virtual TypeDict get_param_types() const
06345 {
06346 TypeDict d;
06347 d.put("wavelength", EMObject::FLOAT, "(required)this value is the d in function |sin(x/d)|, unit: pixel");
06348 d.put("axis", EMObject::STRING, "specify a major axis for asymmetric features");
06349 d.put("c", EMObject::FLOAT, "distance between focus and the center of an ellipse");
06350 d.put("phase", EMObject::FLOAT, "(optional)phase for sine wave, default is 0");
06351 return d;
06352 }
06353
06354 static const string NAME;
06355 };
06356
06363 class TestImageSquarecube : public TestImageProcessor
06364 {
06365 public:
06366 virtual void process_inplace(EMData * image);
06367
06368 virtual string get_name() const
06369 {
06370 return NAME;
06371 }
06372
06373 virtual string get_desc() const
06374 {
06375 return "Replace a source image as a square or cube depends on 2D or 3D of the source image";
06376 }
06377
06378 static Processor * NEW()
06379 {
06380 return new TestImageSquarecube();
06381 }
06382
06383 virtual TypeDict get_param_types() const
06384 {
06385 TypeDict d;
06386 d.put("edge_length", EMObject::FLOAT, "edge length of the square or cube, unit: pixel");
06387 d.put("axis", EMObject::STRING, "specify a major axis for asymmetric features");
06388 d.put("odd_edge", EMObject::FLOAT, "edge length for the asymmetric axis");
06389 d.put("fill", EMObject::INT, "Flag indicating if image is filled, default filled, 1 for filled, 0 for blank");
06390 return d;
06391 }
06392
06393 static const string NAME;
06394 };
06395
06403 class TestImageEllipse : public TestImageProcessor
06404 {
06405 public:
06406 virtual void process_inplace(EMData * image);
06407
06408 virtual string get_name() const
06409 {
06410 return NAME;
06411 }
06412
06413 virtual string get_desc() const
06414 {
06415 return "Insert an ellipse into the image.";
06416 }
06417
06418 static Processor * NEW()
06419 {
06420 return new TestImageEllipse();
06421 }
06422
06423 virtual TypeDict get_param_types() const
06424 {
06425 TypeDict d;
06426 d.put("a", EMObject::FLOAT, "equatorial radius along x axes (major semiaxes)");
06427 d.put("b", EMObject::FLOAT, "equatorial radius along y axes (minor semiaxes)");
06428 d.put("c", EMObject::FLOAT, "polar radius for ellipsoid (x^2/a^2+y^2/b^2+z^2/c^2=1)");
06429 d.put("transform", EMObject::TRANSFORM, "Optionally transform the ellipse");
06430 d.put("fill", EMObject::FLOAT, "value you want to fill in ellipse, default to 1.0");
06431 return d;
06432 }
06433
06434 static const string NAME;
06435 };
06436
06448 class TestImageHollowEllipse : public TestImageProcessor
06449 {
06450 public:
06451 virtual void process_inplace(EMData * image);
06452
06453 virtual string get_name() const
06454 {
06455 return NAME;
06456 }
06457
06458 virtual string get_desc() const
06459 {
06460 return "Insert a hollow ellipse into the image.";
06461 }
06462
06463 static Processor * NEW()
06464 {
06465 return new TestImageHollowEllipse();
06466 }
06467
06468 virtual TypeDict get_param_types() const
06469 {
06470 TypeDict d;
06471 d.put("xwidth", EMObject::FLOAT, "inner equatorial radii along x axes");
06472 d.put("ywidth", EMObject::FLOAT, "inner equatorial radii along y axes");
06473 d.put("zwidth", EMObject::FLOAT, "inner polar radius");
06474 d.put("a", EMObject::FLOAT, "outter equatorial radii along x axes");
06475 d.put("b", EMObject::FLOAT, "outter equatorial radii along y axes");
06476 d.put("c", EMObject::FLOAT, "outter polar radius");
06477 d.put("width",EMObject::FLOAT, "width - specify the width or specify each width explicitly - xwidth, ywidth, zwidth");
06478 d.put("transform", EMObject::TRANSFORM, "Optionally transform the ellipse");
06479 d.put("fill", EMObject::FLOAT, "value you want to fill in hollow ellipse, default to 1.0");
06480 return d;
06481 }
06482
06483 static const string NAME;
06484 };
06485
06492 class TestImageCirclesphere : public TestImageProcessor
06493 {
06494 public:
06495 virtual void process_inplace(EMData * image);
06496
06497 virtual string get_name() const
06498 {
06499 return NAME;
06500 }
06501
06502 virtual string get_desc() const
06503 {
06504 return "Replace a source image as a circle or sphere depends on 2D or 3D of the source image";
06505 }
06506
06507 static Processor * NEW()
06508 {
06509 return new TestImageCirclesphere();
06510 }
06511
06512 virtual TypeDict get_param_types() const
06513 {
06514 TypeDict d;
06515 d.put("radius", EMObject::FLOAT, "radius of circle or sphere, unit: pixel");
06516 d.put("axis", EMObject::STRING, "specify a major axis for asymmetric features");
06517 d.put("c", EMObject::FLOAT, "distance between focus and the center of an ellipse");
06518 d.put("fill", EMObject::INT, "Flag indicating if image is filled, default filled, 1 for filled, 0 for blank.");
06519 return d;
06520 }
06521
06522 static const string NAME;
06523 };
06524
06529 class TestImageNoiseUniformRand : public TestImageProcessor
06530 {
06531 public:
06532 virtual void process_inplace(EMData * image);
06533
06534 virtual string get_name() const
06535 {
06536 return NAME;
06537 }
06538
06539 virtual string get_desc() const
06540 {
06541 return "Replace a source image as a uniform random noise, random number generated from gsl_rng_mt19937, the pixel value is [0, 1)";
06542 }
06543
06544 static Processor * NEW()
06545 {
06546 return new TestImageNoiseUniformRand();
06547 }
06548
06549 virtual TypeDict get_param_types() const
06550 {
06551 TypeDict d;
06552 d.put("seed", EMObject::INT, "seed for random number generator");
06553 return d;
06554 }
06555
06556 static const string NAME;
06557 };
06558
06569 class TestImageNoiseGauss : public TestImageProcessor
06570 {
06571 public:
06572 virtual void process_inplace(EMData * image);
06573
06574 virtual string get_name() const
06575 {
06576 return NAME;
06577 }
06578
06579 virtual string get_desc() const
06580 {
06581 return "Replace a source image as a random noise, the random value is gaussian distributed";
06582 }
06583
06584 static Processor * NEW()
06585 {
06586 return new TestImageNoiseGauss();
06587 }
06588
06589 virtual TypeDict get_param_types() const
06590 {
06591 TypeDict d;
06592 d.put("sigma", EMObject::FLOAT, "sigma value of gausian distributed noise, default is 0.5");
06593 d.put("mean", EMObject::FLOAT, "mean value of gausian distributed noise, default is zero.");
06594 d.put("seed", EMObject::INT, "the seed for random number generator, default is not to reseed.");
06595
06596 return d;
06597 }
06598
06599 static const string NAME;
06600 };
06601
06606 class TestImageCylinder : public TestImageProcessor
06607 {
06608 public:
06609 virtual void process_inplace(EMData * image);
06610
06611 virtual string get_name() const
06612 {
06613 return NAME;
06614 }
06615
06616 virtual string get_desc() const
06617 {
06618 return "Replace a source image as a cylinder";
06619 }
06620
06621 static Processor * NEW()
06622 {
06623 return new TestImageCylinder();
06624 }
06625
06626 virtual TypeDict get_param_types() const
06627 {
06628 TypeDict d;
06629 d.put("radius", EMObject::FLOAT, "radius for the cylinder");
06630 d.put("height", EMObject::FLOAT, "height for the cylinder, by default it's the nz");
06631
06632 return d;
06633 }
06634
06635 static const string NAME;
06636 };
06637
06643 class CCDNormProcessor:public Processor
06644 {
06645 public:
06646 virtual void process_inplace(EMData * image);
06647
06648 virtual string get_name() const
06649 {
06650 return NAME;
06651 }
06652
06653 static Processor *NEW()
06654 {
06655 return new CCDNormProcessor();
06656 }
06657
06658 virtual string get_desc() const
06659 {
06660 return "normalize the 4 quadrants of a CCD image";
06661 }
06662
06663 virtual TypeDict get_param_types() const
06664 {
06665 TypeDict d;
06666 d.put("width", EMObject::INT, "number of pixels on either side of the seam to sample");
06667 return d;
06668 }
06669
06670 static const string NAME;
06671 };
06672
06680 class WaveletProcessor:public Processor
06681 {
06682 public:
06683 virtual void process_inplace(EMData * image);
06684
06685 virtual string get_name() const
06686 {
06687 return NAME;
06688 }
06689
06690 static Processor *NEW()
06691 {
06692 return new WaveletProcessor();
06693 }
06694
06695 virtual TypeDict get_param_types() const
06696 {
06697 TypeDict d;
06698 d.put("type", EMObject::STRING, "'daub', 'harr' or 'bspl'");
06699 d.put("dir", EMObject::INT, "1 for forward transform, -1 for inverse transform");
06700 d.put("ord", EMObject::INT, "Daubechies (4,6,8,...,20), for Harr (2), for B-Splines (103, 105, 202, 204, 206, 208, 301, 303, 305 307, 309)");
06701 return d;
06702 }
06703
06704 virtual string get_desc() const
06705 {
06706 return "Computes the DWT (discrete wavelet transform) of an image in one of 3 possible bases";
06707 }
06708
06709 static const string NAME;
06710 };
06711
06727 class TomoTiltEdgeMaskProcessor : public Processor
06728 {
06729 public:
06730 virtual void process_inplace(EMData* image);
06731
06732 virtual string get_name() const
06733 {
06734 return NAME;
06735 }
06736
06737 static Processor *NEW()
06738 {
06739 return new TomoTiltEdgeMaskProcessor();
06740 }
06741
06742 virtual TypeDict get_param_types() const
06743 {
06744 TypeDict d;
06745 d.put("biedgemean", EMObject::BOOL, "Mutually exclusive of edgemean. Experimental. Causes the pixels in the masked out areas to take the average value of both the left and right edge pixel strips");
06746 d.put("edgemean", EMObject::BOOL, "Mutually exclusive of biedgemean. Masked pixels values assume the mean edge pixel value, independently, for both sides of the image.");
06747 d.put("angle", EMObject::INT, "The angle that the image is, with respect to the zero tilt image");
06748 d.put("gauss_falloff",EMObject::INT, "Causes the edge masking to have a smooth Gaussian fall-off - this parameter specifies how many pixels the fall-off will proceed over. Default is 0.");
06749 d.put("gauss_sigma",EMObject::FLOAT,"The sigma of the Gaussian function used to smooth the edge fall-off (functional form is exp(-(pixel distance)^2/sigma^2)");
06750 d.put("angle_fim",EMObject::BOOL,"Read fim as 'from image metadata' - this causes the altitude angle stored in by the image object (i.e. as extracted from the header, as currently stored in memory) to be used as the angle. This overrides the angle argument");
06751 return d;
06752 }
06753
06754 virtual string get_desc() const
06755 {
06756 return "Masks the part of the image which is not present in the 0-tilt image. Masked areas can be 0 or set to the edgemean (of the nearest or both edges). Masked areas can also have a Gaussian fall-off to make the appearance smooth.";
06757 }
06758
06759 static const string NAME;
06760
06761 private:
06762 class GaussianFunctoid
06763 {
06764 public:
06765 GaussianFunctoid(const float sigma, const float mean = 0.0) : m_mean(mean), m_sigma_squared(sigma*sigma) {}
06766 ~GaussianFunctoid() {}
06767
06768 float operator()(const float distance )
06769 {
06770 return exp( -(distance-m_mean)*(distance-m_mean)/ (m_sigma_squared ));
06771 }
06772 private:
06773 float m_mean, m_sigma_squared;
06774 };
06775
06776 };
06777
06792 class TomoTiltAngleWeightProcessor : public Processor
06793 {
06794 public:
06795 virtual void process_inplace(EMData* image);
06796
06797 virtual string get_name() const
06798 {
06799 return NAME;
06800 }
06801
06802 static Processor *NEW()
06803 {
06804 return new TomoTiltAngleWeightProcessor();
06805 }
06806
06807 virtual TypeDict get_param_types() const
06808 {
06809 TypeDict d;
06810 d.put("angle", EMObject::INT, "The angle that the image is, with respect to the zero tilt image");
06811 d.put("angle_fim",EMObject::BOOL,"Read fim as 'from image metadata' - this causes the altitude angle stored in by the image object (i.e. as extracted from the header, as currently stored in memory) to be used as the angle. This overrides the angle argument");
06812 return d;
06813 }
06814
06815 virtual string get_desc() const
06816 {
06817 return "Weights the image by 1/cos(angle)";
06818 }
06819
06820 static const string NAME;
06821
06822 };
06823
06827 class FFTProcessor : public Processor
06828 {
06829 public:
06830 void process_inplace(EMData * image);
06831
06832 string get_name() const
06833 {
06834 return NAME;
06835 }
06836
06837 static Processor *NEW()
06838 {
06839 return new FFTProcessor();
06840 }
06841
06842 TypeDict get_param_types() const
06843 {
06844 TypeDict d;
06845 d.put("dir", EMObject::INT, "1 for forward transform, -1 for inverse transform");
06846 return d;
06847 }
06848
06849 string get_desc() const
06850 {
06851 return "Computes the DFFT (Discrete Fast Fourier Transform) of an image";
06852 }
06853
06854 static const string NAME;
06855 };
06856
06861 class RadialProcessor : public Processor
06862 {
06863 public:
06864 void process_inplace(EMData * image);
06865
06866 string get_name() const
06867 {
06868 return NAME;
06869 }
06870
06871 static Processor *NEW()
06872 {
06873 return new RadialProcessor();
06874 }
06875
06876 TypeDict get_param_types() const
06877 {
06878 TypeDict d;
06879 d.put("table", EMObject::FLOATARRAY, "Radial array of floats, 1 float/pixel");
06880 return d;
06881 }
06882
06883 string get_desc() const
06884 {
06885 return "Multiply a real-space image by a radial function. 1 value / pixel, extending to corner. Missing values -> 0.";
06886 }
06887
06888 static const string NAME;
06889 };
06890
06897 class HistogramBin : public Processor
06898 {
06899 public:
06900 HistogramBin() : default_bins(1024) {}
06901
06902 void process_inplace(EMData * image);
06903
06904 string get_name() const
06905 {
06906 return NAME;
06907 }
06908
06909 static Processor *NEW()
06910 {
06911 return new HistogramBin();
06912 }
06913
06914 TypeDict get_param_types() const
06915 {
06916 TypeDict d;
06917 d.put("nbins", EMObject::INT, "The number of bins the pixel values will be compressed into");
06918 d.put("debug", EMObject::BOOL, "Outputs debugging information (number of pixels per bin)");
06919 return d;
06920 }
06921
06922 string get_desc() const
06923 {
06924 return "Bins pixel values, similar to calculating a histogram. The histogram is comprised of 'nbins' bins, and the value assigned to each pixel in the bin is the midpoint of the bin's upper and lower limits. Defaults to 256 bins";
06925 }
06926
06927 static const string NAME;
06928
06929 protected:
06930 int default_bins;
06931 };
06932
06933 class ModelHelixProcessor : public Processor
06934 {
06935 protected:
06936 float radprofile(float r, int type);
06937 };
06938
06939 class ModelEMCylinderProcessor : public ModelHelixProcessor
06940 {
06941 public:
06942 void process_inplace(EMData * in);
06943
06944 string get_name() const
06945 {
06946 return NAME;
06947 }
06948
06949 static Processor *NEW()
06950 {
06951 return new ModelEMCylinderProcessor();
06952 }
06953
06954 string get_desc() const
06955 {
06956 return "Adds a cylinder with a radial density profile similar to that of an alpha helix.";
06957 }
06958
06959 virtual TypeDict get_param_types() const
06960 {
06961 TypeDict d;
06962 d.put("type", EMObject::INT, "Radial profile of density method, defaults to 2: 0 = pure Gaussian falloff; 1 = Gaussian falloff + dip, so mean is zero; 2 = polynomial fitting of real helix density");
06963 d.put("length", EMObject::FLOAT, "cylinder length in angstroms, defaults to 3 turns (16.2 Angstroms)");
06964 d.put("x0", EMObject::INT, "x coordinate in pixels for the midpoint of the cylinder's axis, defaults to center of map");
06965 d.put("y0", EMObject::INT, "y coordinate in pixels for the midpoint of the cylinder's axis, defaults to center of map");
06966 d.put("z0", EMObject::INT, "z coordinate in pixels for the midpoint of the cylinder's axis, defaults to center of map");
06967
06968 return d;
06969 }
06970
06971 static const string NAME;
06972 };
06973
06974 class ApplyPolynomialProfileToHelix : public ModelHelixProcessor
06975 {
06976 public:
06977 void process_inplace(EMData * in);
06978
06979 string get_name() const
06980 {
06981 return NAME;
06982 }
06983
06984 static Processor *NEW()
06985 {
06986 return new ApplyPolynomialProfileToHelix();
06987 }
06988
06989 string get_desc() const
06990 {
06991 return "Finds the CM of each z-axis slice and applies a polynomial radial profile about it.";
06992 }
06993 virtual TypeDict get_param_types() const
06994 {
06995 TypeDict d;
06996 d.put("length", EMObject::FLOAT, "Helix length in angstroms.");
06997 d.put("z0", EMObject::INT, "z coordinate in pixels for the midpoint of the cylinder's axis, defaults to center of map");
06998 return d;
06999 }
07000
07001 static const string NAME;
07002 };
07003
07004 class BinarySkeletonizerProcessor : public Processor
07005 {
07006 public:
07007 virtual EMData* process(EMData * image);
07008 virtual void process_inplace(EMData * image);
07009
07010 virtual string get_name() const
07011 {
07012 return NAME;
07013
07014 }
07015 static Processor *NEW()
07016 {
07017 return new BinarySkeletonizerProcessor();
07018 }
07019 string get_desc() const
07020 {
07021 return "Creates a skeleton of the 3D image by considering whether density is above or below a threshold value.";
07022 }
07023 virtual TypeDict get_param_types() const
07024 {
07025 TypeDict d;
07026 d.put("threshold", EMObject::FLOAT, "Threshold value.");
07027 d.put("min_curve_width", EMObject::INT, "Minimum curve width.");
07028 d.put("min_surface_width", EMObject::INT, "Minimum surface width.");
07029 d.put("mark_surfaces", EMObject::BOOL, "Mark surfaces with a value of 2.0f, whereas curves are 1.0f.");
07030 return d;
07031 }
07032 static const string NAME;
07033 };
07034
07035 class ConvolutionKernelProcessor : public Processor
07036 {
07037 public:
07038 virtual EMData* process(const EMData* const image);
07039 virtual void process_inplace(EMData * image);
07040
07041 virtual string get_name() const
07042 {
07043 return NAME;
07044 }
07045 static Processor *NEW()
07046 {
07047 return new ConvolutionKernelProcessor();
07048 }
07049 string get_desc() const
07050 {
07051 return "Filters an image with a convolution kernel in real space.";
07052 }
07053 virtual TypeDict get_param_types() const
07054 {
07055 TypeDict d;
07056 d.put("kernel", EMObject::FLOATARRAY, "the convolution kernel");
07057 return d;
07058 }
07059 static const string NAME;
07060 };
07061
07062 class RotateInFSProcessor : public Processor
07063 {
07064 public:
07065
07066 virtual void process_inplace(EMData * image);
07067 virtual EMData* process(const EMData* const image);
07068
07069 virtual string get_name() const
07070 {
07071 return NAME;
07072 }
07073 static Processor *NEW()
07074 {
07075 return new RotateInFSProcessor( );
07076 }
07077 string get_desc() const
07078 {
07079 return "Rotates a Fourier object using a kernel.";
07080 }
07081 virtual TypeDict get_param_types() const
07082 {
07083 TypeDict d;
07084 d.put("transform", EMObject::TRANSFORM, "transform");
07085 d.put("interpCutoff", EMObject::FLOAT, "cutoff for interpolation");
07086
07087
07088 return d;
07089 }
07090 static const string NAME;
07091 };
07092
07093 #ifdef SPARX_USING_CUDA
07094
07095
07096
07097
07098
07099 class MPICUDA_kmeans {
07100 public:
07101 MPICUDA_kmeans();
07102 ~MPICUDA_kmeans();
07103 int setup(int extm, int extN, int extn, int extK, int extn_start);
07104 void append_flat_image(EMData* im, int pos);
07105 int init_mem(int numdev);
07106 void compute_im2();
07107 int random_ASG(long int rnd);
07108 vector<int> get_ASG();
07109 vector<int> get_asg();
07110 void compute_NC();
07111 vector<int> get_NC();
07112 void set_ASG(const vector <int>& ASG);
07113 void set_NC(const vector <int>& NC);
07114 int get_ct_im_mv();
07115 void set_T(float extT);
07116 float get_T();
07117 void compute_AVE();
07118 void set_AVE(EMData* im, int pos);
07119 vector<EMData*> get_AVE();
07120 int one_iter();
07121
07122
07123 int one_iter_SA();
07124 vector<float> compute_ji();
07125 vector<float> compute_criterion(const vector <float>& Ji);
07126 int shutdown();
07127 private:
07128
07129 int m;
07130 int N;
07131 int n;
07132 int K;
07133 int nb_part;
07134 int n_start;
07135 int size_im;
07136 int size_IM;
07137 int size_AVE;
07138 int size_dist;
07139 int BLOCK_SIZE;
07140 int NB;
07141 int ins_BLOCK;
07142 int ite;
07143 float T;
07144
07145 int ct_im_mv;
07146
07147 float* h_IM;
07148 float* h_im;
07149 float* h_AVE;
07150 float* h_dist;
07151 float* h_AVE2;
07152 float* h_im2;
07153 unsigned short int* h_ASG;
07154 unsigned short int* h_asg;
07155 unsigned int* h_NC;
07156 int* params;
07157 float ttt;
07158
07159 float* d_im;
07160 float* d_AVE;
07161 float* d_dist;
07162
07163 float compute_tt();
07164 };
07165
07166 #endif //EMAN2_USING_CUDA
07167
07168 #if 0
07169
07170 class XYZProcessor:public Processor
07171 {
07172 public:
07173 void process_inplace(EMData * image);
07174
07175 string get_name() const
07176 {
07177 return NAME;
07178 }
07179
07180 static Processor *NEW()
07181 {
07182 return new XYZProcessor();
07183 }
07184
07185 string get_desc() const
07186 {
07187 return "N/A";
07188 }
07189
07190 TypeDict get_param_types() const
07191 {
07192 TypeDict d;
07193 return d;
07194 }
07195
07196 static const string NAME;
07197 };
07198
07199
07200 #endif
07201
07202
07203 #if 0
07204
07205 class XYZProcessor:public Processor
07206 {
07207 public:
07208 void process_inplace(EMData * image);
07209
07210 string get_name() const
07211 {
07212 return NAME;
07213 }
07214
07215 static Processor *NEW()
07216 {
07217 return new XYZProcessor();
07218 }
07219
07220 string get_desc() const
07221 {
07222 return "N/A";
07223 }
07224
07225 TypeDict get_param_types() const
07226 {
07227 TypeDict d;
07228 return d;
07229 }
07230
07231 static const string NAME;
07232 };
07233
07234
07235 #endif
07236
07237
07238 int multi_processors(EMData * image, vector < string > processornames);
07239 void dump_processors();
07240 map<string, vector<string> > dump_processors_list();
07241 map<string, vector<string> > group_processors();
07242
07243 template <> Factory < Processor >::Factory();
07244 }
07245
07246 #endif //eman_filter_h__
07247
07248
07249