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, "Resolution in 1/A (0 - 1 / size*apix)");
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 virtual void create_radial_func(vector < float >&radial_mask) const = 0;
00359 };
00360
00368 class FourierAnlProcessor:public Processor
00369 {
00370 public:
00371 void process_inplace(EMData * image);
00372
00373 static string get_group_desc()
00374 {
00375 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]. ";
00376 }
00377
00378 TypeDict get_param_types() const
00379 {
00380 TypeDict d;
00381 d.put("cutoff_abs", EMObject::FLOAT, "Processor radius in terms of Nyquist (0-.5)");
00382 d.put("cutoff_pixels", EMObject::FLOAT, " Width in Fourier pixels (0 - size()/2)");
00383 d.put("cutoff_freq", EMObject::FLOAT, "Resolution in 1/A (0 - 1 / size*apix)");
00384 d.put("apix", EMObject::FLOAT, " Override A/pix in the image header (changes x,y and z)");
00385 return d;
00386 }
00387
00388 protected:
00389 virtual void preprocess(EMData * image) {}
00390 virtual void create_radial_func(vector < float >&radial_mask,EMData *image) const = 0;
00391 };
00392
00395 class SNREvalProcessor:public Processor
00396 {
00397 public:
00398 string get_name() const
00399 {
00400 return "eval.maskedsnr";
00401 }
00402
00403 void process_inplace(EMData * image);
00404
00405 void set_params(const Dict & new_params)
00406 {
00407 params = new_params;
00408
00409
00410
00411 }
00412
00413 TypeDict get_param_types() const
00414 {
00415 TypeDict d;
00416
00417
00418 return d;
00419 }
00420
00421 static Processor *NEW()
00422 {
00423 return new SNREvalProcessor();
00424 }
00425
00426 string get_desc() const
00427 {
00428 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";
00429 }
00430
00431 protected:
00432 EMData *sum;
00433 int dosqrt;
00434 };
00435
00436
00441 class AmpweightFourierProcessor:public Processor
00442 {
00443 public:
00444 string get_name() const
00445 {
00446 return "filter.ampweight";
00447 }
00448
00449 void process_inplace(EMData * image);
00450
00451 void set_params(const Dict & new_params)
00452 {
00453 params = new_params;
00454 sum = params["sum"];
00455 dosqrt = params["sqrt"];
00456
00457 }
00458
00459 TypeDict get_param_types() const
00460 {
00461 TypeDict d;
00462 d.put("sum", EMObject::EMDATA, "Adds the weights to sum for normalization");
00463 d.put("sqrt", EMObject::INT, "Weights using sqrt of the amplitude if set");
00464 return d;
00465 }
00466
00467 static Processor *NEW()
00468 {
00469 return new AmpweightFourierProcessor();
00470 }
00471
00472 string get_desc() const
00473 {
00474 return "Multiplies each Fourier pixel by its amplitude";
00475 }
00476
00477 protected:
00478 EMData *sum;
00479 int dosqrt;
00480 };
00487 class ConvolutionProcessor : public Processor
00488 {
00489 public:
00490 ConvolutionProcessor() {}
00491
00492 string get_name() const
00493 {
00494 return "math.convolution";
00495 }
00496
00497 void process_inplace(EMData *image);
00498
00499 static Processor *NEW()
00500 {
00501 return new ConvolutionProcessor();
00502 }
00503
00504 string get_desc() const
00505 {
00506 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.";
00507 }
00508
00509 TypeDict get_param_types() const
00510 {
00511 TypeDict d;
00512 d.put("with", EMObject::EMDATA, "The image that will convolute the other image");
00513 return d;
00514 }
00515 };
00516
00523 class XGradientProcessor : public Processor
00524 {
00525 public:
00526 XGradientProcessor() {}
00527
00528 string get_name() const
00529 {
00530 return "math.edge.xgradient";
00531 }
00532
00533 void process_inplace(EMData *image);
00534
00535 static Processor *NEW()
00536 {
00537 return new XGradientProcessor();
00538 }
00539
00540 string get_desc() const
00541 {
00542 return "Determines the image gradient in the x direction";
00543 }
00544
00545 TypeDict get_param_types() const
00546 {
00547 TypeDict d;
00548 return d;
00549 }
00550 };
00551
00552 class YGradientProcessor : public Processor
00553 {
00554 public:
00555 YGradientProcessor() {}
00556
00557 string get_name() const
00558 {
00559 return "math.edge.ygradient";
00560 }
00561
00562 void process_inplace(EMData *image);
00563
00564 static Processor *NEW()
00565 {
00566 return new YGradientProcessor();
00567 }
00568
00569 string get_desc() const
00570 {
00571 return "Determines the image gradient in the y direction";
00572 }
00573
00574
00575 TypeDict get_param_types() const
00576 {
00577 TypeDict d;
00578 return d;
00579 }
00580 };
00581
00582 class ZGradientProcessor : public Processor
00583 {
00584 public:
00585 ZGradientProcessor() {}
00586
00587 string get_name() const
00588 {
00589 return "math.edge.zgradient";
00590 }
00591
00592 void process_inplace(EMData *image);
00593
00594 static Processor *NEW()
00595 {
00596 return new ZGradientProcessor();
00597 }
00598
00599 string get_desc() const
00600 {
00601 return "Determines the image gradient in the z direction";
00602 }
00603
00604 TypeDict get_param_types() const
00605 {
00606 TypeDict d;
00607 return d;
00608 }
00609 };
00610
00619 class Wiener2DAutoAreaProcessor:public Processor
00620 {
00621 public:
00622 string get_name() const
00623 {
00624 return "filter.wiener2dauto";
00625 }
00626
00627 virtual EMData* process(const EMData * const image);
00628
00629 void process_inplace(EMData *image);
00630
00631 void set_params(const Dict & new_params)
00632 {
00633 params = new_params;
00634 bgsize = params["size"];
00635
00636 }
00637
00638 TypeDict get_param_types() const
00639 {
00640 TypeDict d;
00641 d.put("size", EMObject::INT, "Size in pixels of the boxes to chop the image into");
00642 return d;
00643 }
00644
00645 static Processor *NEW()
00646 {
00647 return new Wiener2DAutoAreaProcessor();
00648 }
00649
00650 string get_desc() const
00651 {
00652 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";
00653 }
00654
00655 protected:
00656 int bgsize;
00657 };
00658
00659
00666 class Wiener2DFourierProcessor:public Processor
00667 {
00668 public:
00669 string get_name() const
00670 {
00671 return "filter.wiener2d";
00672 }
00673
00674 virtual EMData* process(const EMData * const image);
00675
00676 void process_inplace(EMData *image);
00677
00678 void set_params(const Dict & new_params)
00679 {
00680 params = new_params;
00681 ctf = params["ctf"];
00682
00683 }
00684
00685 TypeDict get_param_types() const
00686 {
00687 TypeDict d;
00688 d.put("ctf", EMObject::EMDATA, "Ctf object to use for Wiener filter parameters");
00689 return d;
00690 }
00691
00692 static Processor *NEW()
00693 {
00694 return new Wiener2DFourierProcessor();
00695 }
00696
00697 string get_desc() const
00698 {
00699 return "Applies a 2-D Wiener filter to an image based on its Ctf parameters";
00700 }
00701
00702 protected:
00703 Ctf *ctf;
00704 };
00705
00709 class LowpassFourierProcessor:public FourierProcessor
00710 {
00711 public:
00712 LowpassFourierProcessor():lowpass(0)
00713 {
00714 }
00715
00716 void set_params(const Dict & new_params)
00717 {
00718 params = new_params;
00719 if( params.has_key("lowpass") ) {
00720 lowpass = params["lowpass"];
00721 }
00722
00723 }
00724
00725 TypeDict get_param_types() const
00726 {
00727 TypeDict d = FourierProcessor::get_param_types();
00728 d.put("lowpass", EMObject::FLOAT, "Processor radius in terms of Nyquist (0-.5)");
00729 return d;
00730 }
00731
00732 static string get_group_desc()
00733 {
00734 return "Low-pass processor attenuates amplitudes at high spatial frequencies. It has the result of blurring the image, and of eliminating sharp edges and noise. The base class for all low pass fourier processors.";
00735 }
00736
00737 protected:
00738 virtual void preprocess(EMData * image);
00739 float lowpass;
00740 };
00741
00742 class LinearRampFourierProcessor:public FourierProcessor
00743 {
00744 public:
00745 virtual string get_name() const { return "filter.linearfourier"; }
00746
00747 virtual string get_desc() const
00748 {
00749 return "";
00750 }
00751
00752 static Processor *NEW()
00753 {
00754 return new LinearRampFourierProcessor();
00755 }
00756
00757 protected:
00758 virtual void create_radial_func(vector < float >&radial_mask) const ;
00759 };
00760
00764 class HighpassFourierProcessor:public FourierProcessor
00765 {
00766 public:
00767 HighpassFourierProcessor():highpass(0)
00768 {
00769 }
00770
00771 void set_params(const Dict & new_params)
00772 {
00773 params = new_params;
00774 if( params.has_key("highpass") ) {
00775 highpass = params["highpass"];
00776 }
00777 }
00778
00779 TypeDict get_param_types() const
00780 {
00781 TypeDict d = FourierProcessor::get_param_types();
00782 d.put("highpass", EMObject::FLOAT, "Processor radius in terms of Nyquist (0-.5)");
00783 return d;
00784 }
00785
00786 static string get_group_desc()
00787 {
00788 return "High-pass processor is rotationally symmetric 2D function. It attenuates amplitudes at low spatial frequencies, and increases amplitudes for high spatial frequencies. It has the result of enhancing the edges in the image while suppressing all slow-moving variations. <br> HighpassFourierProcessor class is the base class for all high pass fourier processors.";
00789 }
00790
00791 protected:
00792 virtual void preprocess(EMData * image);
00793 float highpass;
00794 };
00795
00798 class LowpassSharpCutoffProcessor:public LowpassFourierProcessor
00799 {
00800 public:
00801 string get_name() const
00802 {
00803 return "eman1.filter.lowpass.sharp";
00804 }
00805
00806 static Processor *NEW()
00807 {
00808 return new LowpassSharpCutoffProcessor();
00809 }
00810
00811 string get_desc() const
00812 {
00813 return "processor radial function: if x <= lowpass, f(x) = 1; else f(x) = 0;";
00814 }
00815
00816 protected:
00817 void create_radial_func(vector < float >&radial_mask) const;
00818 };
00819
00822 class HighpassSharpCutoffProcessor:public HighpassFourierProcessor
00823 {
00824 public:
00825 string get_name() const
00826 {
00827 return "eman1.filter.highpass.sharp";
00828 }
00829
00830 static Processor *NEW()
00831 {
00832 return new HighpassSharpCutoffProcessor();
00833 }
00834
00835 string get_desc() const
00836 {
00837 return "processor radial function: if x >= highpass, f(x) = 1; else f(x) = 0;";
00838 }
00839
00840
00841 protected:
00842 void create_radial_func(vector < float >&radial_mask) const;
00843 };
00844
00847 class LowpassGaussProcessor:public LowpassFourierProcessor
00848 {
00849 public:
00850 string get_name() const
00851 {
00852 return "eman1.filter.lowpass.gaussian";
00853 }
00854
00855 static Processor *NEW()
00856 {
00857 return new LowpassGaussProcessor();
00858 }
00859
00860 string get_desc() const
00861 {
00862 return "processor radial function: if lowpass > 0, f(x) = exp(-x*x/(lowpass*lowpass)); else f(x) = exp(x*x/(lowpass*lowpass));";
00863 }
00864
00865 protected:
00866 void create_radial_func(vector < float >&radial_mask) const;
00867 };
00868
00871 class HighpassAutoPeakProcessor:public FourierAnlProcessor
00872 {
00873 public:
00874 string get_name() const
00875 {
00876 return "filter.highpass.autopeak";
00877 }
00878 static Processor *NEW()
00879 {
00880 return new HighpassAutoPeakProcessor();
00881 }
00882
00883 string get_desc() const
00884 {
00885 return "Attempts to automatically remove the low resolution peak present in virtually all cryoEM data.";
00886 }
00887
00888 protected:
00889 void create_radial_func(vector < float >&radial_mask, EMData *image) const;
00890 virtual void preprocess(EMData * image);
00891 float highpass;
00892 };
00893
00894
00897 class HighpassGaussProcessor:public HighpassFourierProcessor
00898 {
00899 public:
00900 string get_name() const
00901 {
00902 return "eman1.filter.highpass.gaussian";
00903 }
00904 static Processor *NEW()
00905 {
00906 return new HighpassGaussProcessor();
00907 }
00908
00909 string get_desc() const
00910 {
00911 return "processor radial function: f(x) = 1.0-exp(-x*x/(highpass*highpass);";
00912 }
00913
00914 protected:
00915 void create_radial_func(vector < float >&radial_mask) const;
00916 };
00917
00920 class LowpassTanhProcessor:public LowpassFourierProcessor
00921 {
00922 public:
00923 string get_name() const
00924 {
00925 return "eman1.filter.lowpass.tanh";
00926 }
00927 static Processor *NEW()
00928 {
00929 return new LowpassTanhProcessor();
00930 }
00931
00932 string get_desc() const
00933 {
00934 return "processor radial function: f(x)=tanh(lowpass-x)/2.0 + 0.5;";
00935 }
00936
00937 protected:
00938 void create_radial_func(vector < float >&radial_mask) const;
00939 };
00940
00941
00944 class HighpassTanhProcessor:public HighpassFourierProcessor
00945 {
00946 public:
00947 string get_name() const
00948 {
00949 return "eman1.filter.highpass.tanh";
00950 }
00951 static Processor *NEW()
00952 {
00953 return new HighpassTanhProcessor();
00954 }
00955
00956 string get_desc() const
00957 {
00958 return "processor radial function: f(x)=tanh(x-highpass)/2.0+0.5;";
00959 }
00960
00961 protected:
00962 void create_radial_func(vector < float >&radial_mask) const;
00963 };
00964
00967 class HighpassButterworthProcessor:public HighpassFourierProcessor
00968 {
00969 public:
00970 string get_name() const
00971 {
00972 return "eman1.filter.highpass.butterworth";
00973 }
00974 static Processor *NEW()
00975 {
00976 return new HighpassButterworthProcessor();
00977 }
00978
00979 string get_desc() const
00980 {
00981 return "processor radial function: f(x) = 1/(1+t*t);";
00982 }
00983
00984 protected:
00985 void create_radial_func(vector < float >&radial_mask) const;
00986 };
00987
00992 class LinearRampProcessor:public FourierProcessor
00993 {
00994 public:
00995 LinearRampProcessor():intercept(0), slope(0)
00996 {
00997 }
00998
00999 string get_name() const
01000 {
01001 return "eman1.filter.ramp";
01002 }
01003 static Processor *NEW()
01004 {
01005 return new LinearRampProcessor();
01006 }
01007
01008 string get_desc() const
01009 {
01010 return "processor radial function: f(x) = slope * x + intercept;";
01011 }
01012
01013 void set_params(const Dict & new_params)
01014 {
01015 params = new_params;
01016 intercept = params["intercept"];
01017 slope = params["slope"];
01018 }
01019
01020 TypeDict get_param_types() const
01021 {
01022 TypeDict d;
01023 d.put("intercept", EMObject::FLOAT, "intercept in 'f(x) = slope * x + intercept'");
01024 d.put("slope", EMObject::FLOAT, "slope in 'f(x) = slope * x + intercept'");
01025 return d;
01026 }
01027
01028 protected:
01029 void create_radial_func(vector < float >&radial_mask) const;
01030
01031 private:
01032 float intercept;
01033 float slope;
01034 };
01035
01038 class RealPixelProcessor:public Processor
01039 {
01040 public:
01041 RealPixelProcessor():value(0), maxval(1), mean(0), sigma(0)
01042 {
01043 }
01044 void process_inplace(EMData * image);
01045
01046 void set_params(const Dict & new_params)
01047 {
01048 params = new_params;
01049 if (params.size() == 1) {
01050 vector < EMObject > dict_values = params.values();
01051 value = dict_values[0];
01052 }
01053 }
01054
01055 static string get_group_desc()
01056 {
01057 return "The base class for real space processor working on individual pixels. The processor won't consider the pixel's coordinates and neighbors.";
01058 }
01059
01060 protected:
01061 virtual void process_pixel(float *x) const = 0;
01062 virtual void calc_locals(EMData *)
01063 {
01064 }
01065 virtual void normalize(EMData *) const
01066 {
01067 }
01068
01069 float value;
01070 float maxval;
01071 float mean;
01072 float sigma;
01073 };
01074
01077 class AbsoluateValueProcessor:public RealPixelProcessor
01078 {
01079 public:
01080 string get_name() const
01081 {
01082 return "math.absvalue";
01083 }
01084 static Processor *NEW()
01085 {
01086 return new AbsoluateValueProcessor();
01087 }
01088 protected:
01089 void process_pixel(float *x) const
01090 {
01091 *x = fabs(*x);
01092 }
01093
01094 string get_desc() const
01095 {
01096 return "f(x) = |x|";
01097 }
01098
01099 };
01100
01101
01104 class BooleanProcessor:public RealPixelProcessor
01105 {
01106 public:
01107 string get_name() const
01108 {
01109 return "threshold.notzero";
01110 }
01111 static Processor *NEW()
01112 {
01113 return new BooleanProcessor();
01114 }
01115
01116 string get_desc() const
01117 {
01118 return "f(x) = 0 if x = 0; f(x) = 1 if x != 0;";
01119 }
01120
01121 protected:
01122 void process_pixel(float *x) const
01123 {
01124 if (*x != 0)
01125 {
01126 *x = 1.0;
01127 }
01128 }
01129 };
01130
01134 class InvertCarefullyProcessor:public RealPixelProcessor
01135 {
01136 public:
01137 string get_name() const
01138 {
01139 return "math.invert.carefully";
01140 }
01141 static Processor *NEW()
01142 {
01143 return new InvertCarefullyProcessor();
01144 }
01145
01146 void set_params(const Dict & new_params)
01147 {
01148 params = new_params;
01149 zero_to = params.set_default("zero_to",0.0f);
01150 }
01151
01152 TypeDict get_param_types() const
01153 {
01154 TypeDict d;
01155 d.put("zero_to", EMObject::FLOAT, "Inverted zero values are set to this value, default is 0.");
01156 return d;
01157 }
01158
01159 string get_desc() const
01160 {
01161 return "if f(x) != 0: f(x) = 1/f(x) else: f(x) = zero_to";
01162 }
01163
01164 protected:
01165 void process_pixel(float *x) const
01166 {
01167 if (*x == 0) *x = zero_to;
01168 else *x = 1/(*x);
01169 }
01170 private:
01171 float zero_to;
01172 };
01173
01177 class ValuePowProcessor:public RealPixelProcessor
01178 {
01179 public:
01180 string get_name() const
01181 {
01182 return "math.pow";
01183 }
01184 static Processor *NEW()
01185 {
01186 return new ValuePowProcessor();
01187 }
01188
01189 void set_params(const Dict & new_params)
01190 {
01191 params = new_params;
01192 pwr = params["pow"];
01193 }
01194
01195 TypeDict get_param_types() const
01196 {
01197 TypeDict d;
01198 d.put("pow", EMObject::FLOAT, "Each pixel is raised to this power");
01199 return d;
01200 }
01201
01202 string get_desc() const
01203 {
01204 return "f(x) = x ^ pow;";
01205 }
01206
01207 protected:
01208 void process_pixel(float *x) const
01209 {
01210 if (*x<0 && pwr!=(int)pwr) *x=0;
01211 else (*x) = pow(*x,pwr);
01212 }
01213 private:
01214 float pwr;
01215 };
01216
01219 class ValueSquaredProcessor:public RealPixelProcessor
01220 {
01221 public:
01222 string get_name() const
01223 {
01224 return "math.squared";
01225 }
01226 static Processor *NEW()
01227 {
01228 return new ValueSquaredProcessor();
01229 }
01230
01231
01232 string get_desc() const
01233 {
01234 return "f(x) = x * x;";
01235 }
01236
01237 protected:
01238 void process_pixel(float *x) const
01239 {
01240 (*x) *= (*x);
01241 }
01242 };
01243
01246 class ValueSqrtProcessor:public RealPixelProcessor
01247 {
01248 public:
01249 string get_name() const
01250 {
01251 return "math.sqrt";
01252 }
01253 static Processor *NEW()
01254 {
01255 return new ValueSqrtProcessor();
01256 }
01257
01258 string get_desc() const
01259 {
01260 return "f(x) = sqrt(x)";
01261 }
01262
01263 protected:
01264 void process_pixel(float *x) const
01265 {
01266 *x = sqrt(*x);
01267 }
01268 };
01269
01273 class ToZeroProcessor:public RealPixelProcessor
01274 {
01275 public:
01276 string get_name() const
01277 {
01278 return "threshold.belowtozero";
01279 }
01280 static Processor *NEW()
01281 {
01282 return new ToZeroProcessor();
01283 }
01284 TypeDict get_param_types() const
01285 {
01286 TypeDict d;
01287 d.put("minval", EMObject::FLOAT, "Everything below this value is set to zero");
01288 return d;
01289 }
01290
01291 string get_desc() const
01292 {
01293 return "f(x) = x if x >= minval; f(x) = 0 if x < minval.";
01294 }
01295
01296 protected:
01297 inline void process_pixel(float *x) const
01298 {
01299 if (*x < value) {
01300 *x = 0;
01301 }
01302 }
01303 };
01304
01310 class Rotate180Processor:public Processor
01311 {
01312 public:
01313 string get_name() const
01314 {
01315 return "math.rotate.180";
01316 }
01317 static Processor *NEW()
01318 {
01319 return new Rotate180Processor();
01320 }
01321
01325 void process_inplace(EMData* image);
01326
01327 string get_desc() const
01328 {
01329 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.";
01330 }
01331 };
01332
01339 class TransformProcessor:public Processor
01340 {
01341 public:
01342 virtual string get_name() const
01343 {
01344 return "math.transform";
01345 }
01346 static Processor *NEW()
01347 {
01348 return new TransformProcessor();
01349 }
01350
01355 virtual void process_inplace(EMData* image);
01356
01361 virtual EMData* process(const EMData* const image);
01362
01363 virtual TypeDict get_param_types() const
01364 {
01365 TypeDict d;
01366 d.put("transform", EMObject::TRANSFORM, "The Transform object that will be applied to the image" );
01367 return d;
01368 }
01369
01370 virtual string get_desc() const
01371 {
01372 return "The image is transformed using Transform parameter.";
01373 }
01374 private:
01375 float* transform(const EMData* const image, const Transform& t) const;
01376
01377
01378
01379
01380 void assert_valid_aspect(const EMData* const image) const;
01381 };
01382
01390 class IntTranslateProcessor:public Processor
01391 {
01392 public:
01393 virtual string get_name() const
01394 {
01395 return "math.translate.int";
01396 }
01397
01398 static Processor *NEW()
01399 {
01400 return new IntTranslateProcessor();
01401 }
01402
01407 virtual void process_inplace(EMData* image);
01408
01413 virtual EMData* process(const EMData* const image);
01414
01415 virtual TypeDict get_param_types() const
01416 {
01417 TypeDict d;
01418 d.put("trans", EMObject::INTARRAY, "The displacement array, can be length 1-3" );
01419 return d;
01420 }
01421
01422 virtual string get_desc() const
01423 {
01424 return "The image is translated an integer amount";
01425 }
01426 private:
01430 void assert_valid_aspect(const vector<int>& translation, const EMData* const image) const;
01431
01437 Region get_clip_region(vector<int>& translation, const EMData* const image) const;
01438 };
01439
01446 class ScaleTransformProcessor:public Processor
01447 {
01448 public:
01449 virtual string get_name() const
01450 {
01451 return "math.transform.scale";
01452 }
01453 static Processor *NEW()
01454 {
01455 return new ScaleTransformProcessor();
01456 }
01457
01462 virtual void process_inplace(EMData* image);
01463
01468 virtual EMData* process(const EMData* const image);
01469
01470 virtual TypeDict get_param_types() const
01471 {
01472 TypeDict d;
01473 d.put("scale", EMObject::FLOAT, "The amount by which to scale" );
01474 d.put("clip", EMObject::INT, "The length of each output dimension. Non sophisticated, output dimensions can't be different" );
01477 return d;
01478 }
01479
01480 virtual string get_desc() const
01481 {
01482 return "The image is scaled with the clip variable in mind, being sure to preserve as much pixel information as possible.";
01483 }
01484 };
01485
01492 class ClampingProcessor :public Processor
01493 {
01494 public:
01495 ClampingProcessor() : default_max(1.0), default_min(0.0) {}
01496
01497 string get_name() const
01498 {
01499 return "threshold.clampminmax";
01500 }
01501 static Processor *NEW()
01502 {
01503 return new ClampingProcessor();
01504 }
01505
01506 void process_inplace(EMData *image);
01507
01508 TypeDict get_param_types() const
01509 {
01510 TypeDict d;
01511 d.put("minval", EMObject::FLOAT, "The pixel values that bounds the smallest pixel value in the output image" );
01512 d.put("maxval", EMObject::FLOAT, "The pixel values that bounds the largest pixel value in the output image" );
01513 d.put("tomean", EMObject::BOOL, "Replace outlying pixels values with the mean pixel value instead" );
01514 return d;
01515 }
01516
01517 string get_desc() const
01518 {
01519 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.";
01520 }
01521
01522 protected:
01523 float default_max, default_min;
01524 };
01525
01531 class NSigmaClampingProcessor : public ClampingProcessor
01532 {
01533 public:
01534 NSigmaClampingProcessor() : default_sigma(2.0) {}
01535
01536 string get_name() const
01537 {
01538 return "threshold.clampminmax.nsigma";
01539 }
01540
01541 static Processor *NEW()
01542 {
01543 return new NSigmaClampingProcessor();
01544 }
01545
01546 TypeDict get_param_types() const
01547 {
01548 TypeDict d;
01549 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" );
01550 d.put("tomean", EMObject::BOOL, "Replace outlying pixels values with the mean pixel value instead" );
01551 return d;
01552 }
01553
01554 void process_inplace(EMData *image);
01555
01556 string get_desc() const
01557 {
01558 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.";
01559 }
01560
01561 protected:
01562 float default_sigma;
01563 };
01564
01568 class ToMinvalProcessor:public RealPixelProcessor
01569 {
01570 public:
01571 string get_name() const
01572 {
01573 return "threshold.belowtominval";
01574 }
01575 static Processor *NEW()
01576 {
01577 return new ToMinvalProcessor();
01578 }
01579
01580 TypeDict get_param_types() const
01581 {
01582 TypeDict d;
01583 d.put("minval", EMObject::FLOAT, "Everything below this value is set to this value");
01584 return d;
01585 }
01586
01587 string get_desc() const
01588 {
01589 return "f(x) = x if x >= minval; f(x) = minval if x < minval.";
01590 }
01591
01592 protected:
01593 inline void process_pixel(float *x) const
01594 {
01595 if (*x < value) {
01596 *x = value;
01597 }
01598 }
01599 };
01600
01601
01605 class CutToZeroProcessor:public RealPixelProcessor
01606 {
01607 public:
01608 string get_name() const
01609 {
01610 return "threshold.belowtozero_cut";
01611 }
01612 static Processor *NEW()
01613 {
01614 return new CutToZeroProcessor();
01615 }
01616 TypeDict get_param_types() const
01617 {
01618 TypeDict d;
01619 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" );
01620 return d;
01621 }
01622
01623 string get_desc() const
01624 {
01625 return "f(x) = x-minval if x >= minval; f(x) = 0 if x < minval.";
01626 }
01627
01628 protected:
01629 void process_pixel(float *x) const
01630 {
01631 *x = *x - value;
01632 if (*x < 0) {
01633 *x = 0;
01634 }
01635 }
01636 };
01637
01641 class BinarizeProcessor:public RealPixelProcessor
01642 {
01643 public:
01644 string get_name() const
01645 {
01646 return "threshold.binary";
01647 }
01648 static Processor *NEW()
01649 {
01650 return new BinarizeProcessor();
01651 }
01652 TypeDict get_param_types() const
01653 {
01654 TypeDict d;
01655 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" );
01656 return d;
01657 }
01658
01659 string get_desc() const
01660 {
01661 return "f(x) = 0 if x < value; f(x) = 1 if x >= value.";
01662 }
01663
01664 protected:
01665 void process_pixel(float *x) const
01666 {
01667 if (*x < value)
01668 {
01669 *x = 0;
01670 }
01671 else
01672 {
01673 *x = 1;
01674 }
01675 }
01676 };
01677
01689 class BinarizeFourierProcessor:public Processor
01690 {
01691 public:
01692 virtual string get_name() const
01693 {
01694 return "threshold.binary.fourier";
01695 }
01696 static Processor *NEW()
01697 {
01698 return new BinarizeFourierProcessor();
01699 }
01700
01707 virtual void process_inplace(EMData* image);
01708
01709 virtual TypeDict get_param_types() const
01710 {
01711 TypeDict d;
01712 d.put("value", EMObject::FLOAT, "The Fourier amplitude threshold cutoff" );
01713 return d;
01714 }
01715
01716 virtual string get_desc() const
01717 {
01718 return "f(k) = 0 + 0i if ||f(k)|| < value; f(k) = 1 + 0i if ||f(k)|| >= value.";
01719 }
01720 };
01721
01726 class CollapseProcessor:public RealPixelProcessor
01727 {
01728 public:
01729 string get_name() const
01730 {
01731 return "threshold.compress";
01732 }
01733 static Processor *NEW()
01734 {
01735 return new CollapseProcessor();
01736 }
01737
01738 void set_params(const Dict & new_params)
01739 {
01740 params = new_params;
01741 range = params["range"];
01742 value = params["value"];
01743 }
01744
01745 TypeDict get_param_types() const
01746 {
01747 TypeDict d;
01748 d.put("range", EMObject::FLOAT, "The range about 'value' which will be collapsed to 'value'");
01749 d.put("value", EMObject::FLOAT, "The pixel value where the focus of the collapse operation is");
01750 return d;
01751 }
01752
01753 string get_desc() const
01754 {
01755 return "f(x): if v-r<x<v+r -> v; if x>v+r -> x-r; if x<v-r -> x+r";
01756 }
01757
01758 protected:
01759 void process_pixel(float *x) const
01760 {
01761 if (*x>value+range) *x-=range;
01762 else if (*x<value-range) *x+=range;
01763 else *x=value;
01764 }
01765 float range;
01766 };
01767
01772 class LinearXformProcessor:public RealPixelProcessor
01773 {
01774 public:
01775 LinearXformProcessor():shift(0), scale(0)
01776 {
01777 }
01778
01779 string get_name() const
01780 {
01781 return "math.linear";
01782 }
01783 static Processor *NEW()
01784 {
01785 return new LinearXformProcessor();
01786 }
01787
01788 void set_params(const Dict & new_params)
01789 {
01790 params = new_params;
01791 shift = params.get("shift");
01792 scale = params.get("scale");
01793 }
01794
01795 TypeDict get_param_types() const
01796 {
01797 TypeDict d;
01798 d.put("shift", EMObject::FLOAT, "The amount to shift pixel values by before scaling");
01799 d.put("scale", EMObject::FLOAT, "The scaling factor to be applied to pixel values");
01800 return d;
01801 }
01802
01803 string get_desc() const
01804 {
01805 return "linear transform processor: f(x) = x * scale + shift. This is equivalent to a regular contrast stretching operation";
01806 }
01807
01808 protected:
01809 void process_pixel(float *x) const
01810 {
01811 *x = (*x) * scale + shift;
01812 }
01813
01814 private:
01815 float shift;
01816 float scale;
01817 };
01818
01823 class ExpProcessor:public RealPixelProcessor
01824 {
01825 public:
01826 ExpProcessor():low(0), high(0)
01827 {
01828 }
01829
01830 string get_name() const
01831 {
01832 return "math.exp";
01833 }
01834
01835 static Processor *NEW()
01836 {
01837 return new ExpProcessor();
01838 }
01839
01840 void set_params(const Dict & new_params)
01841 {
01842 params = new_params;
01843 low = params.get("low");
01844 high = params.get("high");
01845 }
01846
01847 TypeDict get_param_types() const
01848 {
01849 TypeDict d;
01850 d.put("low", EMObject::FLOAT, "Pixels are divided by (low - high) prior to the exponential operation");
01851 d.put("high", EMObject::FLOAT, "Pixels are divided by (low - high) prior to the exponential operation");
01852 return d;
01853 }
01854
01855 string get_desc() const
01856 {
01857 return "f(x) = exp( x / low - high)";
01858 }
01859
01860 protected:
01864 void process_pixel(float *x) const
01865 {
01866 float v = *x / low - high;
01867 if (v > 40) {
01868 v = 40;
01869 }
01870 *x = exp(v);
01871 }
01872
01873 private:
01874 float low;
01875 float high;
01876 };
01877
01881 class FiniteProcessor:public RealPixelProcessor
01882 {
01883 public:
01884 FiniteProcessor():to(0)
01885 {
01886 }
01887
01888 string get_name() const
01889 {
01890 return "math.finite";
01891 }
01892
01893 static Processor *NEW()
01894 {
01895 return new FiniteProcessor();
01896 }
01897
01898 void set_params(const Dict & new_params)
01899 {
01900 if (new_params.has_key("to") )
01901 to = params["to"];
01902 }
01903
01904 TypeDict get_param_types() const
01905 {
01906 TypeDict d;
01907 d.put("to", EMObject::FLOAT, "Pixels which are not finite will be set to this value");
01908 return d;
01909 }
01910
01911 string get_desc() const
01912 {
01913 return "f(x) = f(x) if f(x) is finite | to if f(x) is not finite";
01914 }
01915
01916 protected:
01920 void process_pixel(float *x) const;
01921 private:
01922 float to;
01923 };
01924
01929 class RangeThresholdProcessor:public RealPixelProcessor
01930 {
01931 public:
01932 RangeThresholdProcessor():low(0), high(0)
01933 {
01934 }
01935
01936 string get_name() const
01937 {
01938 return "threshold.binaryrange";
01939 }
01940 static Processor *NEW()
01941 {
01942 return new RangeThresholdProcessor();
01943 }
01944
01945 void set_params(const Dict & new_params)
01946 {
01947 params = new_params;
01948 low = params.get("low");
01949 high = params.get("high");
01950 }
01951
01952 TypeDict get_param_types() const
01953 {
01954 TypeDict d;
01955 d.put("low", EMObject::FLOAT, "The lower limit of the range that will be set to 1");
01956 d.put("high", EMObject::FLOAT, "The upper limit of the range that will be set to 1");
01957 return d;
01958 }
01959
01960 string get_desc() const
01961 {
01962 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";
01963 }
01964
01965 protected:
01966 void process_pixel(float *x) const
01967 {
01968 if (*x >= low && *x <= high) {
01969 *x = 1;
01970 }
01971 else {
01972 *x = 0;
01973 }
01974 }
01975 private:
01976 float low;
01977 float high;
01978
01979 };
01980
01985 class SigmaProcessor:public RealPixelProcessor
01986 {
01987 public:
01988 string get_name() const
01989 {
01990 return "math.sigma";
01991 }
01992 static Processor *NEW()
01993 {
01994 return new SigmaProcessor();
01995 }
01996
01997 void set_params(const Dict & new_params)
01998 {
01999 params = new_params;
02000 value1 = params.get("value1");
02001 value2 = params.get("value2");
02002 }
02003
02004 TypeDict get_param_types() const
02005 {
02006 TypeDict d;
02007 d.put("value1", EMObject::FLOAT, "A number reflecting total standard deviations in the right direction");
02008 d.put("value2", EMObject::FLOAT, "A number reflecting total standard deviations in the left direction");
02009 return d;
02010 }
02011
02012 string get_desc() const
02013 {
02014 return "f(x) = mean if x<(mean-v2*sigma) or x>(mean+v1*sigma); else f(x) = x;";
02015 }
02016
02017 protected:
02018 void process_pixel(float *x) const
02019 {
02020 if (*x < (mean - value2 * sigma) || *x > (mean + value1 * sigma))
02021 {
02022 *x = mean;
02023 }
02024 }
02025
02026 private:
02027 float value1;
02028 float value2;
02029 };
02030
02033 class LogProcessor:public RealPixelProcessor
02034 {
02035 public:
02036 string get_name() const
02037 {
02038 return "math.log";
02039 }
02040 static Processor *NEW()
02041 {
02042 return new LogProcessor();
02043 }
02044
02045 string get_desc() const
02046 {
02047 return "f(x) = log10(x) if x > 0; else f(x) = 0;";
02048 }
02049
02050 protected:
02051 void process_pixel(float *x) const
02052 {
02053 if (*x > 0)
02054 {
02055 *x = log10(*x);
02056 }
02057 else
02058 {
02059 *x = 0;
02060 }
02061 }
02062 };
02063
02066 class CoordinateProcessor:public Processor
02067 {
02068 public:
02069 CoordinateProcessor():nx(0), ny(0), nz(0), mean(0), sigma(0), maxval(0), is_complex(false)
02070 {
02071 }
02072 void process_inplace(EMData * image);
02073
02074 static string get_group_desc()
02075 {
02076 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().";
02077 }
02078
02079 protected:
02080 virtual void process_pixel(float *pixel, int xi, int yi, int zi) const = 0;
02081 virtual void calc_locals(EMData *)
02082 {
02083 }
02084 virtual bool is_valid() const
02085 {
02086 return true;
02087 }
02088
02089 int nx;
02090 int ny;
02091 int nz;
02092 float mean;
02093 float sigma;
02094 float maxval;
02095
02096 bool is_complex;
02097 };
02098
02106 class CircularMaskProcessor:public CoordinateProcessor
02107 {
02108 public:
02109 CircularMaskProcessor():inner_radius(0), outer_radius(0), inner_radius_square(0),
02110 outer_radius_square(0), dx(0), dy(0), dz(0), xc(0), yc(0), zc(0)
02111 {
02112 }
02113
02114 void set_params(const Dict & new_params)
02115 {
02116 params = new_params;
02117
02118 if (params.has_key("inner_radius")) {
02119 inner_radius = params["inner_radius"];
02120 inner_radius_square = inner_radius * inner_radius;
02121 }
02122 else {
02123 inner_radius = -1;
02124 inner_radius_square = -1;
02125 }
02126
02127 if (params.has_key("outer_radius")) {
02128 outer_radius = params["outer_radius"];
02129 outer_radius_square = outer_radius * outer_radius;
02130 }
02131 else {
02132 outer_radius = INT_MAX;
02133 outer_radius_square = INT_MAX;
02134 }
02135
02136 if (params.has_key("xc")) xc = params["xc"];
02137 if (params.has_key("yc")) yc = params["yc"];
02138 if (params.has_key("zc")) zc = params["zc"];
02139 if (params.has_key("dx")) dx = params["dx"];
02140 if (params.has_key("dy")) dy = params["dy"];
02141 if (params.has_key("dz")) dz = params["dz"];
02142 }
02143
02144 string get_desc() const
02145 {
02146 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().";
02147 }
02148
02149 TypeDict get_param_types() const
02150 {
02151 TypeDict d;
02152
02153 d.put("inner_radius", EMObject::INT, "inner mask radius. optional, default=-1");
02154 d.put("outer_radius", EMObject::INT, "outer mask radius");
02155
02156 d.put("dx", EMObject::FLOAT,
02157 "Modify mask center by dx relative to the default center nx/2");
02158 d.put("dy", EMObject::FLOAT,
02159 "Modify mask center by dy relative to the default center ny/2");
02160 d.put("dz", EMObject::FLOAT,
02161 "Modify mask center by dz relative to the default center nz/2");
02162
02163 return d;
02164 }
02165 protected:
02166 void calc_locals(EMData * image);
02167
02168 bool is_valid() const
02169 {
02170 return (!is_complex);
02171 }
02172
02173 void process_pixel(float *pixel, int xi, int yi, int zi) const
02174 {
02175 float dist = (xi - xc) * (xi - xc) + (yi - yc) * (yi - yc) + (zi - zc) * (zi - zc);
02176 process_dist_pixel(pixel, dist);
02177 }
02178
02179 virtual void process_dist_pixel(float *pixel, float dist) const = 0;
02180
02181 int inner_radius;
02182 int outer_radius;
02183 int inner_radius_square;
02184 int outer_radius_square;
02185 float dx, dy, dz;
02186 float xc, yc, zc;
02187 };
02188
02192 class MaskSharpProcessor:public CircularMaskProcessor
02193 {
02194 public:
02195 MaskSharpProcessor():value(0)
02196 {
02197 }
02198
02199 string get_name() const
02200 {
02201 return "mask.sharp";
02202 }
02203 static Processor *NEW()
02204 {
02205 return new MaskSharpProcessor();
02206 }
02207
02208 void set_params(const Dict & new_params)
02209 {
02210 CircularMaskProcessor::set_params(new_params);
02211 value = params.set_default("value",0.0f);
02212 }
02213
02214 TypeDict get_param_types() const
02215 {
02216 TypeDict d = CircularMaskProcessor::get_param_types();
02217 d.put("value", EMObject::FLOAT, "step cutoff to this value. Default is 0.");
02218 return d;
02219 }
02220
02221 string get_desc() const
02222 {
02223 return "step cutoff to a user-given value in both inner and outer circles.";
02224 }
02225
02226 protected:
02227 void process_dist_pixel(float *pixel, float dist) const
02228 {
02229 if (dist >= outer_radius_square || dist < inner_radius_square)
02230 {
02231 *pixel = value;
02232 }
02233 }
02234
02235 float value;
02236 };
02237
02238
02242 class MaskEdgeMeanProcessor:public CircularMaskProcessor
02243 {
02244 public:
02245 string get_name() const
02246 {
02247 return "mask.ringmean";
02248 }
02249 static Processor *NEW()
02250 {
02251 return new MaskEdgeMeanProcessor();
02252 }
02253
02254 void set_params(const Dict & new_params)
02255 {
02256 CircularMaskProcessor::set_params(new_params);
02257 ring_width = params["ring_width"];
02258 if (ring_width == 0) {
02259 ring_width = 1;
02260 }
02261 }
02262
02263 TypeDict get_param_types() const
02264 {
02265 TypeDict d = CircularMaskProcessor::get_param_types();
02266 d.put("ring_width", EMObject::INT, "The width of the mask ring.");
02267 return d;
02268 }
02269
02270 string get_desc() const
02271 {
02272 return "A step cutoff to the the mean value in a ring centered on the outer radius";
02273 }
02274
02275 protected:
02276 void calc_locals(EMData * image);
02277
02278
02279 void process_dist_pixel(float *pixel, float dist) const
02280 {
02281 if (dist >= outer_radius_square || dist < inner_radius_square){
02282 *pixel = ring_avg;
02283 }
02284 }
02285
02286 private:
02287 int ring_width;
02288 float ring_avg;
02289 };
02290
02293 class MaskNoiseProcessor:public CircularMaskProcessor
02294 {
02295 public:
02296 string get_name() const
02297 {
02298 return "mask.noise";
02299 }
02300 static Processor *NEW()
02301 {
02302 return new MaskNoiseProcessor();
02303 }
02304
02305 string get_desc() const
02306 {
02307 return "fills masked region";
02308 }
02309
02310 protected:
02311 void process_dist_pixel(float *pixel, float dist) const
02312 {
02313 if (dist >= outer_radius_square || dist < inner_radius_square)
02314 {
02315 *pixel = Util::get_gauss_rand(mean, sigma);
02316 }
02317 }
02318 };
02319
02322 class MaskGaussProcessor:public CircularMaskProcessor
02323 {
02324 public:
02325 string get_name() const
02326 {
02327 return "mask.gaussian";
02328 }
02329 static Processor *NEW()
02330 {
02331 return new MaskGaussProcessor();
02332 }
02333
02334 void set_params(const Dict & new_params)
02335 {
02336 CircularMaskProcessor::set_params(new_params);
02337 exponent = params["exponent"];
02338 if (exponent <= 0.0) {
02339 exponent = 2.0;
02340 }
02341 }
02342
02343 TypeDict get_param_types() const
02344 {
02345 TypeDict d = CircularMaskProcessor::get_param_types();
02346 d.put("exponent", EMObject::FLOAT, "The exponent, f in e^-Bs^f. default 2.0, producing a Gaussian");
02347 return d;
02348 }
02349
02350 string get_desc() const
02351 {
02352 return "a gaussian falloff to zero, radius is the 1/e of the width. If inner_radius>0, then \
02353 outer radius specifies width of Gaussian starting at inner_radius rather than total radius.";
02354 }
02355
02356 protected:
02357 float exponent;
02358 void process_dist_pixel(float *pixel, float dist) const
02359 {
02360 if (inner_radius_square>0) {
02361 if (dist>inner_radius_square) {
02362 if (exponent==2.0f) (*pixel) *= exp(-pow(sqrt(dist)-inner_radius,2.0f) / outer_radius_square);
02363 else (*pixel) *= exp(-pow(sqrt(dist)-inner_radius,exponent) / pow(outer_radius_square,exponent/2.0f));
02364 }
02365 }
02366 else {
02367 if (exponent==2.0f) (*pixel) *= exp(-dist / outer_radius_square);
02368 else (*pixel) *= exp(-pow(dist,exponent/2.0f) / pow(outer_radius_square,exponent/2.0f));
02369 }
02370 }
02371 };
02372
02379 class MaskGaussNonuniformProcessor:public CoordinateProcessor
02380 {
02381 public:
02382 MaskGaussNonuniformProcessor():radius_x(0), radius_y(0), radius_z(0), gauss_width(0)
02383 {
02384 }
02385
02386 void set_params(const Dict & new_params)
02387 {
02388 params = new_params;
02389
02390 if (params.has_key("radius_x")) radius_x=params["radius_x"];
02391 else radius_x=5.0;
02392
02393 if (params.has_key("radius_y")) radius_y=params["radius_y"];
02394 else radius_y=5.0;
02395
02396 if (params.has_key("radius_z")) radius_z=params["radius_z"];
02397 else radius_z=5.0;
02398
02399 if (params.has_key("gauss_width")) gauss_width=params["gauss_width"];
02400 else gauss_width=0.05f;
02401 }
02402
02403 TypeDict get_param_types() const
02404 {
02405 TypeDict d;
02406
02407 d.put("radius_x", EMObject::INT, "x-axis radius");
02408 d.put("radius_y", EMObject::INT, "y-axis radius");
02409 d.put("radius_z", EMObject::INT, "z-axis radius");
02410 d.put("gauss_width", EMObject::FLOAT, "Gaussian falloff width, relative to each radius, default 0.05");
02411
02412 return d;
02413 }
02414
02415 string get_name() const
02416 {
02417 return "mask.gaussian.nonuniform";
02418 }
02419 static Processor *NEW()
02420 {
02421 return new MaskGaussNonuniformProcessor();
02422 }
02423
02424 string get_desc() const
02425 {
02426 return "A Gaussian falloff to zero. Nonisotropic, specify inner radius for x,y,z and Gaussian falloff width. Falloff \
02427 width is also nonisotropic and relative to the radii, with 1 being equal to the radius on that axis.";
02428 }
02429
02430 protected:
02431 void process_pixel(float *pixel, int xi, int yi, int zi) const
02432 {
02433 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);
02434 if (dist>1.0) (*pixel)*=exp(-pow((sqrt(dist)-1.0f)/gauss_width,2.0f));
02435 }
02436
02437 float radius_x,radius_y,radius_z,gauss_width;
02438 };
02439
02444 class MaskGaussInvProcessor:public CircularMaskProcessor
02445 {
02446 public:
02447 TypeDict get_param_types() const
02448 {
02449 TypeDict d = CircularMaskProcessor::get_param_types();
02450 d.put("gauss_width", EMObject::FLOAT, "Used to calculate the constant factor - gauss_width / (ny*ny)" );
02451 d.put("ring_width", EMObject::INT, "The width of the mask ring.");
02452 return d;
02453 }
02454
02455 string get_name() const
02456 {
02457 return "math.gausskernelfix";
02458 }
02459
02460 static Processor *NEW()
02461 {
02462 return new MaskGaussInvProcessor();
02463 }
02464
02465 string get_desc() const
02466 {
02467 return "f(x) = f(x) / exp(-radius*radius * gauss_width / (ny*ny))";
02468 }
02469
02470 protected:
02471 void calc_locals(EMData *)
02472 {
02473 float gauss_width = params["gauss_width"];
02474 slice_value = gauss_width / (ny * ny);
02475 }
02476
02477 void process_dist_pixel(float *pixel, float dist) const
02478 {
02479 (*pixel) /= exp(-dist * slice_value);
02480 }
02481 private:
02482 float slice_value;
02483 };
02484
02485
02490 class LinearPyramidProcessor:public Processor
02491 {
02492 public:
02493 string get_name() const
02494 {
02495 return "math.linearpyramid";
02496 }
02497
02498 void process_inplace(EMData *image);
02499
02500 static Processor *NEW()
02501 {
02502 return new LinearPyramidProcessor();
02503 }
02504
02505 string get_desc() const
02506 {
02507 return "Multiplies image by a 'linear pyramid', 1-(|x-xsize/2|*|y-ysize/2|*4/(xsize*ysize))";
02508 }
02509
02510 };
02511
02512
02515 class MakeRadiusSquaredProcessor:public CircularMaskProcessor
02516 {
02517 public:
02518 string get_name() const
02519 {
02520 return "math.toradiussqr";
02521 }
02522 static Processor *NEW()
02523 {
02524 return new MakeRadiusSquaredProcessor();
02525 }
02526
02527 string get_desc() const
02528 {
02529 return "overwrites input, f(x) = radius * radius";
02530 }
02531
02532 protected:
02533 void process_dist_pixel(float *pixel, float dist) const
02534 {
02535 *pixel = dist;
02536 }
02537 };
02538
02541 class MakeRadiusProcessor:public CircularMaskProcessor
02542 {
02543 public:
02544 string get_name() const
02545 {
02546 return "math.toradius";
02547 }
02548 static Processor *NEW()
02549 {
02550 return new MakeRadiusProcessor();
02551 }
02552
02553 string get_desc() const
02554 {
02555 return "overwrites input, f(x) = radius;";
02556 }
02557
02558 protected:
02559 void process_dist_pixel(float *pixel, float dist) const
02560 {
02561 *pixel = sqrt(dist);
02562 }
02563 };
02564
02567 class ComplexPixelProcessor:public Processor
02568 {
02569 public:
02570 void process_inplace(EMData * image);
02571
02572 static string get_group_desc()
02573 {
02574 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.";
02575 }
02576
02577 protected:
02578 virtual void process_pixel(float *x) const = 0;
02579 };
02580
02583 class ComplexNormPixel:public ComplexPixelProcessor
02584 {
02585 public:
02586 string get_name() const
02587 {
02588 return "complex.normpixels";
02589 }
02590 static Processor *NEW()
02591 {
02592 return new ComplexNormPixel();
02593 }
02594
02595 string get_desc() const
02596 {
02597 return "Each Fourier pixel will be normalized. ie - amp=1, phase=unmodified. Useful for performing phase-residual-like computations with dot products.";
02598 }
02599
02600 protected:
02601 void process_pixel(float *x) const
02602 {
02603 *x=1.0;
02604 }
02605 };
02606
02610 class AreaProcessor:public Processor
02611 {
02612 public:
02613 AreaProcessor():areasize(0), kernel(0), nx(0), ny(0), nz(0)
02614 {
02615 }
02616
02617 void process_inplace(EMData * image);
02618
02619 void set_params(const Dict & new_params)
02620 {
02621 params = new_params;
02622 areasize = params["areasize"];
02623 }
02624
02625 TypeDict get_param_types() const
02626 {
02627 TypeDict d;
02628 d.put("areasize", EMObject::INT, "The width of the area to process (not radius)");
02629 return d;
02630 }
02631
02632 string get_desc() const
02633 {
02634 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().";
02635 }
02636
02637 protected:
02638 virtual void process_pixel(float *pixel, float, float, float, float *area_matrix) const
02639 {
02640 for (int i = 0; i < matrix_size; i++)
02641 {
02642 *pixel += area_matrix[i] * kernel[i];
02643 }
02644 }
02645
02646 virtual void create_kernel() const = 0;
02647
02648 int areasize;
02649 int matrix_size;
02650 float *kernel;
02651 int nx;
02652 int ny;
02653 int nz;
02654 };
02655
02658 class LaplacianProcessor:public AreaProcessor
02659 {
02660 public:
02661 string get_name() const
02662 {
02663 return "math.laplacian";
02664 }
02665 static Processor *NEW()
02666 {
02667 return new LaplacianProcessor();
02668 }
02669
02670 string get_desc() const
02671 {
02672 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).";
02673 }
02674
02675 protected:
02676 void create_kernel() const;
02677
02678 };
02679
02682 class ZeroConstantProcessor:public AreaProcessor
02683 {
02684 public:
02685 string get_name() const
02686 {
02687 return "mask.contract";
02688 }
02689 static Processor *NEW()
02690 {
02691 return new ZeroConstantProcessor();
02692 }
02693
02694 string get_desc() const
02695 {
02696 return "Contraction of data, if any nearest neighbor is 0, value -> 0, generally used iteratively";
02697 }
02698
02699 protected:
02700 void process_pixel(float *pixel, float, float, float, float *matrix) const
02701 {
02702 if (*pixel != 0)
02703 {
02704 if (*pixel == matrix[1] || *pixel == matrix[3] || *pixel == matrix[5] ||
02705 *pixel == matrix[7] || matrix[1] == 0 || matrix[3] == 0 ||
02706 matrix[5] == 0 || matrix[7] == 0) {
02707 *pixel = 0;
02708 }
02709 }
02710 }
02711
02712 void create_kernel() const
02713 {
02714 }
02715 };
02716
02725 class BoxStatProcessor:public Processor
02726 {
02727 public:
02728 void process_inplace(EMData * image);
02729
02730 static string get_group_desc()
02731 {
02732 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).";
02733 }
02734
02735 TypeDict get_param_types() const
02736 {
02737 TypeDict d;
02738 d.put("radius", EMObject::INT, "The radius of the search box, default is 1 which results in a 3x3 box (3 = 2xradius + 1)");
02739 return d;
02740 }
02741
02742 protected:
02743 virtual void process_pixel(float *pixel, const float *array, int n) const = 0;
02744 };
02745
02746
02749 class BoxMedianProcessor:public BoxStatProcessor
02750 {
02751 public:
02752 string get_name() const
02753 {
02754 return "eman1.filter.median";
02755 }
02756 static Processor *NEW()
02757 {
02758 return new BoxMedianProcessor();
02759 }
02760
02761 string get_desc() const
02762 {
02763 return "A processor for noise reduction. pixel = median of values surrounding pixel.";
02764 }
02765
02766
02767 protected:
02768 void process_pixel(float *pixel, const float *array, int n) const
02769 {
02770 float *data = new float[n];
02771 memcpy(data, array, sizeof(float) * n);
02772
02773 for (int i = 0; i <= n / 2; i++)
02774 {
02775 for (int j = i + 1; j < n; j++)
02776 {
02777 if (data[i] < data[j]) {
02778 float t = data[i];
02779 data[i] = data[j];
02780 data[j] = t;
02781 }
02782 }
02783 }
02784
02785 if (n % 2 != 0)
02786 {
02787 *pixel = data[n / 2];
02788 }
02789 else {
02790 *pixel = (data[n / 2] + data[n / 2 - 1]) / 2;
02791 }
02792 if( data )
02793 {
02794 delete[]data;
02795 data = 0;
02796 }
02797 }
02798 };
02799
02802 class BoxSigmaProcessor:public BoxStatProcessor
02803 {
02804 public:
02805 string get_name() const
02806 {
02807 return "math.localsigma";
02808 }
02809 static Processor *NEW()
02810 {
02811 return new BoxSigmaProcessor();
02812 }
02813
02814 string get_desc() const
02815 {
02816 return "pixel = standard deviation of values surrounding pixel.";
02817 }
02818
02819 protected:
02820 void process_pixel(float *pixel, const float *data, int n) const
02821 {
02822 float sum = 0;
02823 float square_sum = 0;
02824 for (int i = 0; i < n; i++)
02825 {
02826 sum += data[i];
02827 square_sum += data[i] * data[i];
02828 }
02829
02830 float mean = sum / n;
02831 *pixel = sqrt(square_sum / n - mean * mean);
02832 }
02833 };
02834
02837 class BoxMaxProcessor:public BoxStatProcessor
02838 {
02839 public:
02840 string get_name() const
02841 {
02842 return "math.localmax";
02843 }
02844 static Processor *NEW()
02845 {
02846 return new BoxMaxProcessor();
02847 }
02848
02849 string get_desc() const
02850 {
02851 return "peak processor: pixel = max of values surrounding pixel.";
02852 }
02853
02854 protected:
02855 void process_pixel(float *pixel, const float *data, int n) const
02856 {
02857 float maxval = -FLT_MAX;
02858 for (int i = 0; i < n; i++)
02859 {
02860 if (data[i] > maxval) {
02861 maxval = data[i];
02862 }
02863 }
02864 *pixel = maxval;
02865 }
02866 };
02867
02870 class MinusPeakProcessor:public BoxStatProcessor
02871 {
02872 public:
02873 string get_name() const
02874 {
02875 return "math.submax";
02876 }
02877 static Processor *NEW()
02878 {
02879 return new MinusPeakProcessor();
02880 }
02881
02882 string get_desc() const
02883 {
02884 return "peak processor: pixel = pixel - max of values surrounding pixel. This is a sort of positive peak-finding algorithm.";
02885 }
02886
02887 protected:
02888 void process_pixel(float *pixel, const float *data, int n) const
02889 {
02890 float maxval = -FLT_MAX;
02891 for (int i = 0; i < n; i++)
02892 {
02893 if (data[i] > maxval) {
02894 maxval = data[i];
02895 }
02896 }
02897 *pixel -= maxval;
02898 }
02899 };
02900
02904 class PeakOnlyProcessor:public BoxStatProcessor
02905 {
02906 public:
02907 string get_name() const
02908 {
02909 return "mask.onlypeaks";
02910 }
02911 static Processor *NEW()
02912 {
02913 return new PeakOnlyProcessor();
02914 }
02915 void set_params(const Dict & new_params)
02916 {
02917 params = new_params;
02918 npeaks = params["npeaks"];
02919 if (npeaks == 0) {
02920 npeaks = 1;
02921 }
02922 }
02923
02924 TypeDict get_param_types() const
02925 {
02926 TypeDict d;
02927 d.put("npeaks", EMObject::INT, "the number of surrounding peaks allow to >= pixel values");
02928 return d;
02929 }
02930
02931 string get_desc() const
02932 {
02933 return "peak processor -> if npeaks or more surrounding values >= value, value->0";
02934 }
02935
02936 protected:
02937 void process_pixel(float *pixel, const float *data, int n) const
02938 {
02939 int r = 0;
02940
02941 for (int i = 0; i < n; i++)
02942 {
02943 if (data[i] >= *pixel) {
02944 r++;
02945 }
02946 }
02947
02948 if (r > npeaks)
02949 {
02950 *pixel = 0;
02951 }
02952 }
02953 private:
02954 int npeaks;
02955 };
02956
02961 class DiffBlockProcessor:public Processor
02962 {
02963 public:
02964 void process_inplace(EMData * image);
02965
02966 string get_name() const
02967 {
02968 return "eman1.filter.blockrange";
02969 }
02970 static Processor *NEW()
02971 {
02972 return new DiffBlockProcessor();
02973 }
02974
02975 string get_desc() const
02976 {
02977 return "averages over cal_half_width, then sets the value in a local block";
02978 }
02979
02980 TypeDict get_param_types() const
02981 {
02982 TypeDict d;
02983 d.put("cal_half_width", EMObject::FLOAT, "cal_half_width is dx/dy for calculating an average");
02984 d.put("fill_half_width", EMObject::FLOAT, "fill_half_width is dx/dy for fill/step");
02985 return d;
02986 }
02987 };
02988
02993 class CutoffBlockProcessor:public Processor
02994 {
02995 public:
02996 void process_inplace(EMData * image);
02997
02998 string get_name() const
02999 {
03000 return "eman1.filter.blockcutoff";
03001 }
03002 static Processor *NEW()
03003 {
03004 return new CutoffBlockProcessor();
03005 }
03006
03007 TypeDict get_param_types() const
03008 {
03009 TypeDict d;
03010 d.put("value1", EMObject::FLOAT, "val1 is dx/dy");
03011 d.put("value2", EMObject::FLOAT, "val2 is lowpass freq cutoff in pixels");
03012 return d;
03013 }
03014
03015 string get_desc() const
03016 {
03017 return "Block processor, val1 is dx/dy, val2 is lp freq cutoff in pixels. Mystery processor.";
03018 }
03019
03020 };
03021
03027 class BooleanShrinkProcessor
03028 {
03029 protected:
03037 template<class LogicOp>
03038 EMData* process(const EMData *const image, Dict& params);
03039
03046 template<class LogicOp>
03047 void process_inplace(EMData * image, Dict& params);
03048
03049 };
03050
03059 class MaxShrinkProcessor:public BooleanShrinkProcessor, public Processor
03060 {
03061 public:
03068 virtual EMData* process(const EMData *const image)
03069 {
03070 return BooleanShrinkProcessor::process<GreaterThan>(image, params);
03071 }
03072
03073
03074 virtual void process_inplace(EMData * image)
03075 {
03076 BooleanShrinkProcessor::process_inplace<GreaterThan>(image, params);
03077 }
03078
03079 string get_desc() const
03080 {
03081 return "Shrink an image by a given amount (default 2), using the maximum value found in the pixel neighborhood.";
03082 }
03083
03084 string get_name() const
03085 {
03086 return "math.maxshrink";
03087 }
03088 static Processor *NEW()
03089 {
03090 return new MaxShrinkProcessor();
03091 }
03092
03093 TypeDict get_param_types() const
03094 {
03095 TypeDict d;
03096 d.put("n", EMObject::INT, "The shrink factor");
03097 d.put("search", EMObject::INT, "The search area (cubic volume width, usually the same as shrink)");
03098 return d;
03099 }
03100
03101 private:
03102 struct GreaterThan
03103 {
03104 inline bool operator()(float left,float right) const { return left > right; }
03105 inline float get_start_val() { return -10000000; }
03106 };
03107 };
03108
03117 class MinShrinkProcessor:public BooleanShrinkProcessor, public Processor
03118 {
03119 public:
03126 virtual EMData* process(const EMData *const image)
03127 {
03128 return BooleanShrinkProcessor::process<LessThan>(image, params);
03129 }
03130
03131
03132 virtual void process_inplace(EMData * image)
03133 {
03134 BooleanShrinkProcessor::process_inplace<LessThan>(image, params);
03135 }
03136 string get_desc() const
03137 {
03138 return "Shrink an image by a given amount (default 2), using the minimum value found in the pixel neighborhood.";
03139 }
03140
03141 string get_name() const
03142 {
03143 return "math.minshrink";
03144 }
03145 static Processor *NEW()
03146 {
03147 return new MinShrinkProcessor();
03148 }
03149
03150 TypeDict get_param_types() const
03151 {
03152 TypeDict d;
03153 d.put("n", EMObject::INT, "The shrink factor");
03154 d.put("search", EMObject::INT, "The search area (cubic volume width, usually the same as shrink)");
03155 return d;
03156 }
03157
03158 private:
03159 struct LessThan
03160 {
03161 inline bool operator()(float left,float right) const { return left < right; }
03162 inline float get_start_val() { return 9999999999.0f; }
03163 };
03164 };
03165
03172 class MeanShrinkProcessor : public Processor
03173 {
03174 public:
03185 virtual EMData* process(const EMData *const image);
03186
03193 virtual void process_inplace(EMData * image);
03194
03195 string get_desc() const
03196 {
03197 return "Shrink an image by a given amount , using the mean value found in the pixel neighborhood.";
03198 }
03199
03200 virtual string get_name() const
03201 {
03202 return "math.meanshrink";
03203 }
03204 static Processor *NEW()
03205 {
03206 return new MeanShrinkProcessor();
03207 }
03208
03209 virtual TypeDict get_param_types() const
03210 {
03211 TypeDict d;
03212 d.put("n", EMObject::FLOAT, "The shrink factor");
03213 return d;
03214 }
03215 private:
03223 void accrue_mean(EMData* to, const EMData *const from, const int shrinkfactor);
03224
03231 void accrue_mean_one_p_five(EMData* to, const EMData * const from);
03232 };
03233
03234
03241 class MedianShrinkProcessor : public Processor
03242 {
03243 public:
03254 virtual EMData* process(const EMData *const image);
03255
03262 virtual void process_inplace(EMData * image);
03263
03264 string get_desc() const
03265 {
03266 return "Shrink an image by a given amount , using the median value found in the pixel neighborhood.";
03267 }
03268
03269 virtual string get_name() const
03270 {
03271 return "math.medianshrink";
03272 }
03273 static Processor *NEW()
03274 {
03275 return new MedianShrinkProcessor();
03276 }
03277
03278 virtual TypeDict get_param_types() const
03279 {
03280 TypeDict d;
03281 d.put("n", EMObject::INT, "The shrink factor");
03282 return d;
03283 }
03284 private:
03292 void accrue_median(EMData* to, const EMData* const from,const int shrink_factor);
03293 };
03294
03295
03304 class FFTResampleProcessor : public Processor
03305 {
03306 public:
03307 virtual EMData* process(const EMData *const image);
03308
03309 virtual void process_inplace(EMData * image);
03310
03311 string get_desc() const
03312 {
03313 return "Robust resampling of an image by clipping its Fourier transform.";
03314 }
03315
03316 string get_name() const
03317 {
03318 return "math.fft.resample";
03319 }
03320 static Processor *NEW()
03321 {
03322 return new FFTResampleProcessor();
03323 }
03324
03325 TypeDict get_param_types() const
03326 {
03327 TypeDict d;
03328 d.put("n", EMObject::FLOAT, "The sample rate. Less than one enlarges the image, greater than one shrinks it.");
03329 return d;
03330 }
03331 private:
03338 void fft_resample(EMData* to, const EMData *const from, const float& sample_rate);
03339
03340 };
03341
03344 class GradientRemoverProcessor:public Processor
03345 {
03346 public:
03347 void process_inplace(EMData * image);
03348
03349 string get_name() const
03350 {
03351 return "math.lineargradientfix";
03352 }
03353 static Processor *NEW()
03354 {
03355 return new GradientRemoverProcessor();
03356 }
03357
03358 string get_desc() const
03359 {
03360 return "Gradient remover, does a rough plane fit to find linear gradients.";
03361 }
03362
03363 };
03364
03373 class GradientPlaneRemoverProcessor:public Processor
03374 {
03375 public:
03376 void process_inplace(EMData * image);
03377
03378 string get_name() const
03379 {
03380 return "filter.gradientPlaneRemover";
03381 }
03382 static Processor *NEW()
03383 {
03384 return new GradientPlaneRemoverProcessor();
03385 }
03386
03387 string get_desc() const
03388 {
03389 return "Remove gradient by least square plane fit";
03390 }
03391
03392 TypeDict get_param_types() const
03393 {
03394 TypeDict d;
03395 d.put("mask", EMObject::EMDATA, "mask object: nonzero pixel positions will be used to fit plane. default = 0");
03396 d.put("changeZero", EMObject::INT, "if zero pixels are modified when removing gradient. default = 0");
03397 d.put("planeParam", EMObject::FLOATARRAY, "fitted plane parameters output");
03398 return d;
03399 }
03400 };
03401
03402
03409 class FlattenBackgroundProcessor:public Processor
03410 {
03411 public:
03412 void process_inplace(EMData * image);
03413
03414 string get_name() const
03415 {
03416 return "filter.flattenbackground";
03417 }
03418
03419 static Processor *NEW()
03420 {
03421 return new FlattenBackgroundProcessor();
03422 }
03423
03424 string get_desc() const
03425 {
03426 return "Flattens the background by subtracting the local mean";
03427 }
03428
03429 TypeDict get_param_types() const
03430 {
03431 TypeDict d;
03432 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");
03433 d.put("radius", EMObject::INT, "The radius of circle/sphere that defines the local neighborhood. Exclusive of the mask argument");
03434 return d;
03435 }
03436 };
03437
03438
03441 class RampProcessor:public Processor
03442 {
03443 public:
03444 void process_inplace(EMData * image);
03445
03446 string get_name() const
03447 {
03448 return "filter.ramp";
03449 }
03450 static Processor *NEW()
03451 {
03452 return new RampProcessor();
03453 }
03454
03455 string get_desc() const
03456 {
03457 return "Ramp processor -- Fits a least-squares plane "
03458 "to the picture, and subtracts the plane from "
03459 "the picture. A wedge-shaped overall density "
03460 "profile can thus be removed from the picture.";
03461 }
03462
03463 };
03464
03467 class VerticalStripeProcessor:public Processor
03468 {
03469 public:
03470 void process_inplace(EMData * image);
03471
03472 string get_name() const
03473 {
03474 return "math.verticalstripefix";
03475 }
03476
03477 static Processor *NEW()
03478 {
03479 return new VerticalStripeProcessor();
03480 }
03481
03482 string get_desc() const
03483 {
03484 return "Tries to fix images scanned on the zeiss for poor ccd normalization.";
03485 }
03486
03487 };
03488
03491 class RealToFFTProcessor:public Processor
03492 {
03493 public:
03494 void process_inplace(EMData *image);
03495
03496 string get_name() const
03497 {
03498 return "math.realtofft";
03499 }
03500
03501 static Processor *NEW()
03502 {
03503 return new RealToFFTProcessor();
03504 }
03505
03506 string get_desc() const
03507 {
03508 return "This will replace the image with a full-circle 2D fft amplitude rendering. Note that this renders amplitude, when intensity is more common.";
03509 }
03510
03511 };
03512
03513
03516 class SigmaZeroEdgeProcessor:public Processor
03517 {
03518 public:
03519 void process_inplace(EMData * image);
03520
03521 string get_name() const
03522 {
03523 return "mask.zeroedgefill";
03524 }
03525 static Processor *NEW()
03526 {
03527 return new SigmaZeroEdgeProcessor();
03528 }
03529
03530 string get_desc() const
03531 {
03532 return "Fill zeroes at edges with nearest horizontal/vertical value.";
03533 }
03534
03535 };
03536
03542 class BeamstopProcessor:public Processor
03543 {
03544 public:
03545 void process_inplace(EMData * image);
03546
03547 string get_name() const
03548 {
03549 return "mask.beamstop";
03550 }
03551
03552 static Processor *NEW()
03553 {
03554 return new BeamstopProcessor();
03555 }
03556
03557 string get_desc() const
03558 {
03559 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.";
03560 }
03561
03562 TypeDict get_param_types() const
03563 {
03564 TypeDict d;
03565 d.put("value1", EMObject::FLOAT, "sig multiplier");
03566 d.put("value2", EMObject::FLOAT, "x of center");
03567 d.put("value3", EMObject::FLOAT, "y of center");
03568 return d;
03569 }
03570 };
03571
03574 class MeanZeroEdgeProcessor:public Processor
03575 {
03576 public:
03577 void process_inplace(EMData * image);
03578
03579 string get_name() const
03580 {
03581 return "mask.dampedzeroedgefill";
03582 }
03583
03584 static Processor *NEW()
03585 {
03586 return new MeanZeroEdgeProcessor();
03587 }
03588
03589 string get_desc() const
03590 {
03591 return "Fill zeroes at edges with nearest horizontal/vertical value damped towards Mean2.";
03592 }
03593
03594 };
03595
03596
03599 class AverageXProcessor:public Processor
03600 {
03601 public:
03602 void process_inplace(EMData * image);
03603
03604 string get_name() const
03605 {
03606 return "math.averageovery";
03607 }
03608
03609 static Processor *NEW()
03610 {
03611 return new AverageXProcessor();
03612 }
03613
03614 string get_desc() const
03615 {
03616 return "Average along Y and replace with average";
03617 }
03618
03619 };
03620
03624 class DecayEdgeProcessor:public Processor
03625 {
03626 public:
03627 void process_inplace(EMData * image);
03628 string get_name() const
03629 {
03630 return "mask.decayedge2d";
03631 }
03632
03633 static Processor *NEW()
03634 {
03635 return new DecayEdgeProcessor();
03636 }
03637
03638 string get_desc() const
03639 {
03640 return "Decay edges of image to zero";
03641 }
03642
03643 TypeDict get_param_types() const
03644 {
03645 TypeDict d;
03646 d.put("width", EMObject::INT, "Width of the decay region around the edge of the image in pixels");
03647 return d;
03648 }
03649 };
03650
03657 class ZeroEdgeRowProcessor:public Processor
03658 {
03659