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 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, "Resolution in 1/A (0 - 1 / size*apix)");
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 "Tries to mask out only interesting density using something akin to a flood file approach.";
05074 }
05075
05076 virtual TypeDict get_param_types() const
05077 {
05078 TypeDict d;
05079 d.put("radius", EMObject::INT,"Pixel radius of a ball which is used to seed the flood filling operation. ");
05080 d.put("nmaxseed",EMObject::INT,"Use the n highest valued pixels in the map as a seed. Alternative to radius. Useful for viruses.");
05081 d.put("threshold", EMObject::FLOAT, "An isosurface threshold that suitably encases the mass.");
05082 d.put("sigma", EMObject::FLOAT, "Alternative to threshold based on mean + x*sigma");
05083 d.put("nshells", EMObject::INT, "The number of dilation operations");
05084 d.put("nshellsgauss", EMObject::INT, "number of Gaussian pixels to expand, following the dilation operations");
05085 d.put("return_mask", EMObject::BOOL, "If true the result of the operation will produce the mask, not the masked volume.");
05086 d.put("verbose", EMObject::INT, "How verbose to be (stdout)");
05087 return d;
05088 }
05089
05090 static const string NAME;
05091 };
05092
05096 class AddMaskShellProcessor:public Processor
05097 {
05098 public:
05099 virtual void process_inplace(EMData * image);
05100
05101 virtual string get_name() const
05102 {
05103 return NAME;
05104 }
05105
05106 virtual string get_desc() const
05107 {
05108 return "Add additional shells/rings to an existing 1/0 mask image";
05109 }
05110
05111 static Processor *NEW()
05112 {
05113 return new AddMaskShellProcessor();
05114 }
05115
05116 virtual TypeDict get_param_types() const
05117 {
05118 TypeDict d;
05119 d.put("nshells", EMObject::INT, "number of shells to add");
05120 return d;
05121 }
05122
05123 static const string NAME;
05124 };
05125
05130 class PhaseToMassCenterProcessor:public Processor
05131 {
05132 public:
05133 virtual void process_inplace(EMData * image);
05134
05135 virtual string get_name() const
05136 {
05137 return NAME;
05138 }
05139
05140 static Processor *NEW()
05141 {
05142 return new PhaseToMassCenterProcessor();
05143 }
05144
05145 virtual string get_desc() const
05146 {
05147 return "centers the image the center of mass, which is calculated using Fourier phases, ignores old dx, dy.";
05148 }
05149
05150 virtual TypeDict get_param_types() const
05151 {
05152 TypeDict d;
05153 d.put("int_shift_only", EMObject::INT, "set to 1 only shift by integer, no interpolation");
05154 return d;
05155 }
05156
05157 static const string NAME;
05158 };
05159
05164 class ToMassCenterProcessor:public Processor
05165 {
05166 public:
05167 virtual void process_inplace(EMData * image);
05168
05169 virtual string get_name() const
05170 {
05171 return NAME;
05172 }
05173
05174 static Processor *NEW()
05175 {
05176 return new ToMassCenterProcessor();
05177 }
05178
05179 virtual string get_desc() const
05180 {
05181 return "ToMassCenterProcessor centers image at center of mass, with a threshold. Only values higher than the threshold are considered.";
05182 }
05183
05184 virtual TypeDict get_param_types() const
05185 {
05186 TypeDict d;
05187 d.put("int_shift_only", EMObject::INT, "set to 1 only shift by integer, no interpolation");
05188 d.put("threshold", EMObject::FLOAT, "Only values larger than the threshold are included in the center of mass computation. Default is 0.");
05189
05190 return d;
05191 }
05192
05193 static const string NAME;
05194 };
05195
05199 class ACFCenterProcessor:public Processor
05200 {
05201 public:
05202 virtual void process_inplace(EMData * image);
05203
05204 virtual string get_name() const
05205 {
05206 return NAME;
05207 }
05208
05209 static Processor *NEW()
05210 {
05211 return new ACFCenterProcessor();
05212 }
05213
05214 virtual string get_desc() const
05215 {
05216 return "Center image using self-convolution.";
05217 }
05218
05219 virtual TypeDict get_param_types() const
05220 {
05221 TypeDict d;
05222 return d;
05223 }
05224
05225 static const string NAME;
05226 };
05227
05232 class SNRProcessor:public Processor
05233 {
05234 public:
05235 virtual void process_inplace(EMData * image);
05236
05237 virtual string get_name() const
05238 {
05239 return NAME;
05240 }
05241
05242 static Processor *NEW()
05243 {
05244 return new SNRProcessor();
05245 }
05246
05247 virtual string get_desc() const
05248 {
05249 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.";
05250 }
05251
05252 virtual TypeDict get_param_types() const
05253 {
05254 TypeDict d;
05255 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");
05256 d.put("snrfile", EMObject::STRING, "structure factor file name");
05257 return d;
05258 }
05259
05260 static const string NAME;
05261 };
05262
05266 class FileFourierProcessor:public Processor
05267 {
05268 public:
05269 virtual void process_inplace(EMData * image);
05270
05271 virtual string get_name() const
05272 {
05273 return NAME;
05274 }
05275
05276 virtual string get_desc() const
05277 {
05278 return "A fourier processor specified in a 2 column text file.";
05279 }
05280
05281 static Processor *NEW()
05282 {
05283 return new FileFourierProcessor();
05284 }
05285
05286 virtual TypeDict get_param_types() const
05287 {
05288 TypeDict d;
05289 d.put("filename", EMObject::STRING, "file name for a 2 column text file which specified a radial function data array.");
05290 return d;
05291 }
05292
05293 static const string NAME;
05294 };
05295
05306 class SymSearchProcessor:public Processor
05307 {
05308 public:
05309 virtual void process_inplace(EMData * image);
05310
05311 virtual string get_name() const
05312 {
05313 return NAME;
05314 }
05315
05316 virtual string get_desc() const
05317 {
05318 return "Identifiy the best symmetry in the given symmetry list for each pixel and then apply the best symmetry to each pixel.";
05319 }
05320
05321 static Processor *NEW()
05322 {
05323 return new SymSearchProcessor();
05324 }
05325
05326 virtual TypeDict get_param_types() const
05327 {
05328 TypeDict d;
05329 d.put("sym", EMObject::STRINGARRAY, "the list of symmetries to search");
05330 d.put("thresh", EMObject::FLOAT, "the minimal level of symmetry to be accepted (0-1)");
05331 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");
05332 d.put("symlabel_map", EMObject::EMDATA, "the optional return map when output_symlabel=1");
05333 return d;
05334 }
05335
05336 static const string NAME;
05337 };
05338
05344 class LocalNormProcessor:public Processor
05345 {
05346 public:
05347 void process_inplace(EMData * image);
05348
05349 virtual string get_name() const
05350 {
05351 return NAME;
05352 }
05353
05354 static Processor *NEW()
05355 {
05356 return new LocalNormProcessor();
05357 }
05358
05359 virtual string get_desc() const
05360 {
05361 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.";
05362 }
05363
05364 virtual TypeDict get_param_types() const
05365 {
05366 TypeDict d;
05367 d.put("threshold", EMObject::FLOAT, "an isosurface threshold at which all desired features are visible");
05368 d.put("radius", EMObject::FLOAT, "a normalization size similar to an lp= value");
05369 d.put("apix", EMObject::FLOAT, "Angstrom per pixel ratio");
05370 return d;
05371 }
05372
05373 static const string NAME;
05374 };
05375
05380 class IndexMaskFileProcessor:public Processor
05381 {
05382 public:
05383 virtual void process_inplace(EMData * image);
05384
05385 virtual string get_name() const
05386 {
05387 return NAME;
05388 }
05389
05390 static Processor *NEW()
05391 {
05392 return new IndexMaskFileProcessor();
05393 }
05394
05395 virtual TypeDict get_param_types() const
05396 {
05397 TypeDict d;
05398 d.put("filename", EMObject::STRING, "mask image file name");
05399 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");
05400 return d;
05401 }
05402
05403 virtual string get_desc() const
05404 {
05405 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.";
05406 }
05407
05408 static const string NAME;
05409 };
05410
05414 class CoordinateMaskFileProcessor:public Processor
05415 {
05416 public:
05417 virtual void process_inplace(EMData * image);
05418
05419 virtual string get_name() const
05420 {
05421 return NAME;
05422 }
05423
05424 static Processor *NEW()
05425 {
05426 return new CoordinateMaskFileProcessor();
05427 }
05428
05429 virtual string get_desc() const
05430 {
05431 return "Multiplies the image by the specified file using pixel coordinates instead of pixel indices. The images can be different size.";
05432 }
05433
05434 virtual TypeDict get_param_types() const
05435 {
05436 TypeDict d;
05437 d.put("filename", EMObject::STRING, "mask image file name");
05438 return d;
05439 }
05440
05441 static const string NAME;
05442 };
05443
05454 class PaintProcessor:public Processor
05455 {
05456 public:
05457 PaintProcessor():x(0), y(0), z(0),r1(0), v1(0.0), r2(0), v2(0.0)
05458 {
05459 }
05460
05461 virtual string get_name() const
05462 {
05463 return NAME;
05464 }
05465
05466 static Processor *NEW()
05467 {
05468 return new PaintProcessor();
05469 }
05470
05471 virtual string get_desc() const
05472 {
05473 return "Paints a circle with a decaying edge into the image. r<r1 -> v1, r1<r<r2 -> (v1,v2), r>r2 unchanged";
05474 }
05475
05476 virtual TypeDict get_param_types() const
05477 {
05478 TypeDict d;
05479 d.put("x", EMObject::INT, "x coordinate for Center of circle");
05480 d.put("y", EMObject::INT, "y coordinate for Center of circle");
05481 d.put("z", EMObject::INT, "z coordinate for Center of circle");
05482 d.put("r1", EMObject::INT, "Inner radius");
05483 d.put("v1", EMObject::FLOAT, "Inner value");
05484 d.put("r2", EMObject::INT, "Outter radius");
05485 d.put("v2", EMObject::FLOAT, "Outer Value");
05486 return d;
05487 }
05488
05489 virtual void set_params(const Dict & new_params)
05490 {
05491 params = new_params;
05492
05493 if (params.has_key("x")) x = params["x"];
05494 if (params.has_key("y")) y = params["y"];
05495 if (params.has_key("z")) z = params["z"];
05496 if (params.has_key("r1")) r1 = params["r1"];
05497 if (params.has_key("r2")) r2 = params["r2"];
05498 if (params.has_key("v1")) v1 = params["v1"];
05499 if (params.has_key("v2")) v2 = params["v2"];
05500 }
05501
05502 static const string NAME;
05503
05504 protected:
05505 virtual void process_inplace(EMData *image);
05506
05507 int x,y,z,r1;
05508 float v1;
05509 int r2;
05510 float v2;
05511
05512 };
05513
05514
05519 class DirectionalSumProcessor : public Processor
05520 {
05521 public:
05522 virtual string get_name() const
05523 {
05524 return NAME;
05525 }
05526
05527 static Processor *NEW()
05528 {
05529 return new DirectionalSumProcessor();
05530 }
05531
05535 virtual EMData* process(const EMData* const image);
05536
05540 virtual void process_inplace(EMData*) {
05541 throw InvalidCallException("The directional sum processor does not work inplace");
05542 }
05543
05544 virtual TypeDict get_param_types() const
05545 {
05546 TypeDict d;
05547 d.put("axis", EMObject::STRING,"The direction of the sum, either x,y or z. Returned axes are xy, xz or zy.");
05548 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)");
05549 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)");
05550 return d;
05551 }
05552
05553 string get_desc() const
05554 {
05555 return "Calculates the projection of the image along one of the axial directions, either x, y or z";
05556 }
05557
05558 static const string NAME;
05559 };
05560
05568 class WatershedProcessor:public Processor
05569 {
05570 public:
05571 virtual void process_inplace(EMData * image);
05572
05573 virtual string get_name() const
05574 {
05575 return NAME;
05576 }
05577
05578 static Processor *NEW()
05579 {
05580 return new WatershedProcessor();
05581 }
05582
05583 virtual string get_desc() const
05584 {
05585 return "Does a watershed";
05586 }
05587
05588 virtual TypeDict get_param_types() const
05589 {
05590 TypeDict d;
05591 d.put("xpoints", EMObject::FLOATARRAY,"x coordinates");
05592 d.put("ypoints", EMObject::FLOATARRAY,"y coordinates");
05593 d.put("zpoints", EMObject::FLOATARRAY,"z coordinates");
05594 d.put("minval", EMObject::FLOAT,"min value");
05595 return d;
05596 }
05597
05598 static const string NAME;
05599
05600 private:
05601 vector<Vec3i > watershed(EMData* mask, EMData* image, const float& threshold, const Vec3i& cordinate, const int mask_value);
05602 vector<Vec3i > find_region(EMData* mask,const vector<Vec3i >& coords, const int mask_value, vector<Vec3i >& region);
05603
05604 };
05605
05615 template<class Type>
05616 class BinaryOperateProcessor : public Processor{
05617 public:
05622 virtual void process_inplace(EMData * image) {
05623 if ( ! params.has_key("with") ) throw InvalidParameterException("You must supply the \"with\" parameter");
05624 EMData* with = params["with"];
05625
05626 if ( with->get_xsize() != image->get_xsize() || with->get_ysize() != image->get_ysize() || with->get_zsize() != image->get_zsize() )
05627 throw ImageDimensionException("The images you are operating on do not have the same dimensions");
05628
05629 float* image_data = image->get_data();
05630 float* with_data = with->get_data();
05631
05632 std::transform(image_data,image_data+image->get_size(),with_data,image_data,Type::binary_operate);
05633 image->update();
05634 }
05635
05636 virtual string get_name() const
05637 {
05638 return op.get_name();
05639 }
05640
05641 virtual string get_desc() const
05642 {
05643 return op.get_desc();
05644 }
05645
05646 static Processor *NEW()
05647 {
05648 return new BinaryOperateProcessor<Type>();
05649 }
05650
05651 virtual TypeDict get_param_types() const
05652 {
05653 TypeDict d;
05654 d.put("with", EMObject::EMDATA,"The second image");
05655 return d;
05656 }
05657
05658 static const string NAME;
05659 private:
05660 Type op;
05661 };
05662
05663 class MaxPixelOperator {
05664 public:
05665 string get_name() const
05666 {
05667 return NAME;
05668 }
05669
05670 string get_desc() const
05671 {
05672 return "Compares pixels in two images, returning an image with the maximum pixel value in each pixel location";
05673 }
05674
05675 static float binary_operate(const float& left, const float& right) {
05676 if (left > right) return left;
05677 return right;
05678 }
05679
05680 static const string NAME;
05681 };
05682
05683 class MinPixelOperator {
05684 public:
05685 string get_name() const
05686 {
05687 return NAME;
05688 }
05689
05690 string get_desc() const
05691 {
05692 return "Compares pixels in two images, returning an image with the minimum pixel value in each pixel location";
05693 }
05694
05695 static float binary_operate(const float& left, const float& right) {
05696 if (left < right) return left;
05697 return right;
05698 }
05699
05700 static const string NAME;
05701 };
05702
05706 class MatchSFProcessor:public FourierAnlProcessor
05707 {
05708 public:
05709
05710 virtual string get_name() const
05711 {
05712 return NAME;
05713 }
05714
05715 virtual string get_desc() const
05716 {
05717 return "Filters the image so its 1-D power spectrum matches a second image";
05718 }
05719
05720 static Processor *NEW()
05721 {
05722 return new MatchSFProcessor();
05723 }
05724
05725 virtual TypeDict get_param_types() const
05726 {
05727 TypeDict d;
05728 d.put("to", EMObject::EMDATA, "The image to match with. Make sure apix values are correct.");
05729 return d;
05730 }
05731
05732 static const string NAME;
05733
05734 protected:
05735 void create_radial_func(vector < float >&radial_mask, EMData *image) const;
05736 };
05737
05738
05743 class SetSFProcessor:public FourierAnlProcessor
05744 {
05745 public:
05746
05747 virtual string get_name() const
05748 {
05749 return NAME;
05750 }
05751
05752 virtual string get_desc() const
05753 {
05754 return "Filters the image so its 1-D power spectrum matches a supplied X-Y curve";
05755 }
05756
05757 static Processor *NEW()
05758 {
05759 return new SetSFProcessor();
05760 }
05761
05762 virtual TypeDict get_param_types() const
05763 {
05764 TypeDict d;
05765 d.put("strucfac", EMObject::XYDATA, "An XYData object contaning the curve to be imposed as a function of S");
05766 d.put("apix", EMObject::FLOAT, " Override A/pix in the image header (changes x,y and z)");
05767 return d;
05768 }
05769
05770 static const string NAME;
05771
05772 protected:
05773 void create_radial_func(vector < float >&radial_mask, EMData *image) const;
05774 };
05775
05779 class SmartMaskProcessor:public Processor
05780 {
05781 public:
05782 virtual void process_inplace(EMData * image);
05783
05784 virtual string get_name() const
05785 {
05786 return NAME;
05787 }
05788
05789 static Processor *NEW()
05790 {
05791 return new SmartMaskProcessor();
05792 }
05793
05794 virtual string get_desc() const
05795 {
05796 return "Smart mask processor.";
05797 }
05798
05799 virtual TypeDict get_param_types() const
05800 {
05801 TypeDict d;
05802 d.put("mask", EMObject::FLOAT, "mask value");
05803 return d;
05804 }
05805
05806 static const string NAME;
05807 };
05808
05813 class IterBinMaskProcessor:public Processor
05814 {
05815 public:
05816 virtual void process_inplace(EMData * image);
05817
05818 virtual string get_name() const
05819 {
05820 return NAME;
05821 }
05822
05823 virtual string get_desc() const
05824 {
05825 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.";
05826 }
05827
05828 static Processor *NEW()
05829 {
05830 return new IterBinMaskProcessor();
05831 }
05832
05833 virtual TypeDict get_param_types() const
05834 {
05835 TypeDict d;
05836 d.put("val1", EMObject::FLOAT, "number of pixels to expand");
05837 d.put("val2", EMObject::FLOAT, "number of Gaussian pixels to expand, following the first expansion");
05838 return d;
05839 }
05840
05841 static const string NAME;
05842 };
05843
05846 class TestImageProcessor : public Processor
05847 {
05848 public:
05849 static string get_group_desc()
05850 {
05851 return "Base class for a group of 'processors' used to create test image.";
05852 }
05853
05854 protected:
05855 void preprocess(EMData * image);
05856 int nx, ny, nz;
05857 };
05858
05867 class TestImagePureGaussian : public TestImageProcessor
05868 {
05869 public:
05870 virtual void process_inplace(EMData * image);
05871
05872 virtual string get_name() const
05873 {
05874 return NAME;
05875 }
05876
05877 virtual string get_desc() const
05878 {
05879 return "Replace a source image as a strict Gaussian ";
05880 }
05881
05882 static Processor * NEW()
05883 {
05884 return new TestImagePureGaussian();
05885 }
05886
05887 virtual TypeDict get_param_types() const
05888 {
05889 TypeDict d;
05890 d.put("x_sigma", EMObject::FLOAT, "sigma value for this Gaussian blob on x direction");
05891 d.put("y_sigma", EMObject::FLOAT, "sigma value for this Gaussian blob on y direction");
05892 d.put("z_sigma", EMObject::FLOAT, "sigma value for this Gaussian blob on z direction");
05893 d.put("x_center", EMObject::FLOAT, "center for this Gaussian blob on x direction" );
05894 d.put("y_center", EMObject::FLOAT, "center for this Gaussian blob on y direction" );
05895 d.put("z_center", EMObject::FLOAT, "center for this Gaussian blob on z direction" );
05896 return d;
05897 }
05898
05899 static const string NAME;
05900 };
05901
05905 class TestImageFourierNoiseGaussian : public TestImageProcessor
05906 {
05907 public:
05908 virtual void process_inplace(EMData * image);
05909
05910 virtual string get_name() const
05911 {
05912 return NAME;
05913 }
05914
05915 virtual string get_desc() const
05916 {
05917 return "Replace a source image with pink Fourier noise, based on a Gaussian. Random phase.";
05918 }
05919
05920 static Processor * NEW()
05921 {
05922 return new TestImageFourierNoiseGaussian();
05923 }
05924
05925 virtual TypeDict get_param_types() const
05926 {
05927 TypeDict d;
05928 d.put("sigma", EMObject::FLOAT, "sigma value");
05929 return d;
05930 }
05931
05932 static const string NAME;
05933 };
05934
05939 class TestImageFourierNoiseProfile : public TestImageProcessor
05940 {
05941 public:
05942 virtual void process_inplace(EMData * image);
05943
05944 virtual string get_name() const
05945 {
05946 return NAME;
05947 }
05948
05949 virtual string get_desc() const
05950 {
05951 return "Replace a source image with Fourier noise using amplitude information that is stored in a profile.";
05952 }
05953
05954 static Processor * NEW()
05955 {
05956 return new TestImageFourierNoiseProfile();
05957 }
05958
05959 virtual TypeDict get_param_types() const
05960 {
05961 TypeDict d;
05962 d.put("profile", EMObject::FLOATARRAY, "The noise profile, squared amplitude. As in, what is the EMAN2CTF.background attribute");
05963 return d;
05964 }
05965
05966 static const string NAME;
05967 };
05968
05969
05974 class CTFSNRWeightProcessor : public TestImageProcessor
05975 {
05976 public:
05977 virtual void process_inplace(EMData * image);
05978
05979 virtual string get_name() const
05980 {
05981 return NAME;
05982 }
05983
05984 virtual string get_desc() const
05985 {
05986 return "Weight the amplitudes of an image based on radial noise and snr curves ";
05987 }
05988
05989 static Processor * NEW()
05990 {
05991 return new CTFSNRWeightProcessor();
05992 }
05993
05994 virtual TypeDict get_param_types() const
05995 {
05996 TypeDict d;
05997 d.put("noise", EMObject::FLOATARRAY, "The noise profile, squared amplitude. As in, what is the EMAN2CTF.background attribute");
05998 d.put("snr", EMObject::FLOATARRAY, "Squared amplitude divided by squared noise amplitude. As in, what is the EMAN2CTF.snr attribute");
05999 d.put("boost", EMObject::FLOAT, "Multiplicative signal boost");
06000 return d;
06001 }
06002
06003 static const string NAME;
06004 };
06005
06006
06007
06012 class TestImageLineWave : public TestImageProcessor
06013 {
06014 public:
06015 virtual void process_inplace(EMData * image);
06016
06017 virtual string get_name() const
06018 {
06019 return NAME;
06020 }
06021
06022 virtual string get_desc() const
06023 {
06024 return "Insert an oscillating sine wave into the pixel data";
06025 }
06026
06027 static Processor * NEW()
06028 {
06029 return new TestImageLineWave();
06030 }
06031
06032 virtual TypeDict get_param_types() const
06033 {
06034 TypeDict d;
06035 d.put("period", EMObject::FLOAT, "The period of the oscillating sine wave. Default 10.");
06036 return d;
06037 }
06038
06039 static const string NAME;
06040 };
06041
06042
06050 class TestTomoImage : public TestImageProcessor
06051 {
06052 public:
06056 virtual void process_inplace(EMData * image);
06057
06058 virtual string get_name() const
06059 {
06060 return NAME;
06061 }
06062
06063 virtual string get_desc() const
06064 {
06065 return "Make an image consisting various objects, useful for tomographic testing";
06066 }
06067
06068 static Processor * NEW()
06069 {
06070 return new TestTomoImage();
06071 }
06072
06073 static const string NAME;
06074
06075 private:
06076 void insert_solid_ellipse( EMData* image, const Region& region, const float& value, const Transform& t3d = Transform() );
06077 void insert_hollow_ellipse( EMData* image, const Region& region, const float& value, const int& radius, const Transform& t3d = Transform() );
06078 void insert_rectangle( EMData* image, const Region& region, const float& value, const Transform& t3d = Transform() );
06079 };
06080
06088 class TestImageGradient : public TestImageProcessor
06089 {
06090 public:
06091 virtual void process_inplace(EMData * image);
06092
06093 virtual string get_name() const
06094 {
06095 return NAME;
06096 }
06097
06098 virtual string get_desc() const
06099 {
06100 return "Make a gradient image of the form y=mx+b, where x is any of the image axes.";
06101 }
06102
06103 static Processor * NEW()
06104 {
06105 return new TestImageGradient();
06106 }
06107
06108 virtual TypeDict get_param_types() const
06109 {
06110 TypeDict d;
06111 d.put("axis", EMObject::STRING, "The axis the will be used to determine pixel values. Must be x,y or z");
06112 d.put("m", EMObject::FLOAT, "m in the equation m*axis+b. Default is 1.0");
06113 d.put("b", EMObject::FLOAT, "b in the equation m*axis+b. Default is 0.0");
06114 return d;
06115 }
06116
06117 static const string NAME;
06118 };
06119
06127 class TestImageAxes : public TestImageProcessor
06128 {
06129 public:
06134 virtual void process_inplace(EMData * image);
06135
06136 virtual string get_name() const
06137 {
06138 return NAME;
06139 }
06140
06141 virtual string get_desc() const
06142 {
06143 return "Make an image consisting of a single cross";
06144 }
06145
06146 static Processor * NEW()
06147 {
06148 return new TestImageAxes();
06149 }
06150
06151 virtual TypeDict get_param_types() const
06152 {
06153 TypeDict d;
06154 d.put("int", EMObject::FLOAT, "radius of the lines emanating from the origin");
06155 d.put("fill", EMObject::FLOAT, "value to make non-zero pixels");
06156 return d;
06157 }
06158
06159 static const string NAME;
06160 };
06161
06167 class TestImageGaussian : public TestImageProcessor
06168 {
06169 public:
06170 virtual void process_inplace(EMData * image);
06171
06172 virtual string get_name() const
06173 {
06174 return NAME;
06175 }
06176
06177 virtual string get_desc() const
06178 {
06179 return "Replace a source image as a Gaussian Blob";
06180 }
06181
06182 static Processor * NEW()
06183 {
06184 return new TestImageGaussian();
06185 }
06186
06187 virtual TypeDict get_param_types() const
06188 {
06189 TypeDict d;
06190 d.put("sigma", EMObject::FLOAT, "sigma value for this Gaussian blob");
06191 d.put("axis", EMObject::STRING, "specify a major axis for asymmetric features");
06192 d.put("c", EMObject::FLOAT, "distance between focus and the center of an ellipse");
06193 return d;
06194 }
06195
06196 static const string NAME;
06197 };
06198
06201 class TestImageScurve : public TestImageProcessor
06202 {
06203 public:
06204 virtual void process_inplace(EMData * image);
06205
06206 virtual string get_name() const
06207 {
06208 return NAME;
06209 }
06210
06211 virtual string get_desc() const
06212 {
06213 return "Replace a source image with a lumpy S-curve used for alignment testing";
06214 }
06215
06216 static Processor * NEW()
06217 {
06218 return new TestImageScurve();
06219 }
06220
06221 virtual TypeDict get_param_types() const
06222 {
06223 TypeDict d;
06224 return d;
06225 }
06226
06227 static const string NAME;
06228 };
06229
06237 class TestImageSphericalWave : public TestImageProcessor
06238 {
06239 public:
06240 virtual void process_inplace(EMData * image);
06241
06242 virtual string get_name() const
06243 {
06244 return NAME;
06245 }
06246
06247 virtual string get_desc() const
06248 {
06249 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)";
06250 }
06251
06252 static Processor * NEW()
06253 {
06254 return new TestImageSphericalWave();
06255 }
06256
06257 virtual TypeDict get_param_types() const
06258 {
06259 TypeDict d;
06260 d.put("wavelength", EMObject::FLOAT, "cos(2*pi*r/wavelength+phase)");
06261 d.put("phase", EMObject::FLOAT, "in radians");
06262 d.put("x", EMObject::FLOAT, "center of the spherical wave");
06263 d.put("y", EMObject::FLOAT, "center of the spherical wave");
06264 d.put("z", EMObject::FLOAT, "center of the spherical wave");
06265 return d;
06266 }
06267
06268 static const string NAME;
06269 };
06270
06271
06280 class TestImageSinewave : public TestImageProcessor
06281 {
06282 public:
06283 virtual void process_inplace(EMData * image);
06284
06285 virtual string get_name() const
06286 {
06287 return NAME;
06288 }
06289
06290 virtual string get_desc() const
06291 {
06292 return "Replace a source image as a sine wave in specified wave length";
06293 }
06294
06295 static Processor * NEW()
06296 {
06297 return new TestImageSinewave();
06298 }
06299
06300 virtual TypeDict get_param_types() const
06301 {
06302 TypeDict d;
06303 d.put("wavelength", EMObject::FLOAT, "wavelength in equation sin(x*2*PI/wavelength - phase*180/PI)");
06304 d.put("axis", EMObject::STRING, "(optional) specify a major axis for asymmetric features, default x axis");
06305 d.put("phase", EMObject::FLOAT, "(optional) the phase in radians");
06306 d.put("az", EMObject::FLOAT, "(optional) angle in degree. for 2D image, this is the rotated angle of the image, \
06307 in 3D image, it's az for euler angle. default is zero");
06308 d.put("alt", EMObject::FLOAT, "(optional) angle in degree. only in 3D case, alt for euler angle, default is zero");
06309 d.put("phi", EMObject::FLOAT, "(optional) angle in degree. only in 3D case, phi for euler angle, default is zero");
06310 return d;
06311 }
06312
06313 static const string NAME;
06314 };
06315
06322 class TestImageSinewaveCircular : public TestImageProcessor
06323 {
06324 public:
06325 virtual void process_inplace(EMData * image);
06326
06327 virtual string get_name() const
06328 {
06329 return NAME;
06330 }
06331
06332 virtual string get_desc() const
06333 {
06334 return "Replace a source image as a circular sine wave in specified wave length";
06335 }
06336
06337 static Processor * NEW()
06338 {
06339 return new TestImageSinewaveCircular();
06340 }
06341
06342 virtual TypeDict get_param_types() const
06343 {
06344 TypeDict d;
06345 d.put("wavelength", EMObject::FLOAT, "(required)this value is the d in function |sin(x/d)|, unit: pixel");
06346 d.put("axis", EMObject::STRING, "specify a major axis for asymmetric features");
06347 d.put("c", EMObject::FLOAT, "distance between focus and the center of an ellipse");
06348 d.put("phase", EMObject::FLOAT, "(optional)phase for sine wave, default is 0");
06349 return d;
06350 }
06351
06352 static const string NAME;
06353 };
06354
06361 class TestImageSquarecube : public TestImageProcessor
06362 {
06363 public:
06364 virtual void process_inplace(EMData * image);
06365
06366 virtual string get_name() const
06367 {
06368 return NAME;
06369 }
06370
06371 virtual string get_desc() const
06372 {
06373 return "Replace a source image as a square or cube depends on 2D or 3D of the source image";
06374 }
06375
06376 static Processor * NEW()
06377 {
06378 return new TestImageSquarecube();
06379 }
06380
06381 virtual TypeDict get_param_types() const
06382 {
06383 TypeDict d;
06384 d.put("edge_length", EMObject::FLOAT, "edge length of the square or cube, unit: pixel");
06385 d.put("axis", EMObject::STRING, "specify a major axis for asymmetric features");
06386 d.put("odd_edge", EMObject::FLOAT, "edge length for the asymmetric axis");
06387 d.put("fill", EMObject::INT, "Flag indicating if image is filled, default filled, 1 for filled, 0 for blank");
06388 return d;
06389 }
06390
06391 static const string NAME;
06392 };
06393
06401 class TestImageEllipse : public TestImageProcessor
06402 {
06403 public:
06404 virtual void process_inplace(EMData * image);
06405
06406 virtual string get_name() const
06407 {
06408 return NAME;
06409 }
06410
06411 virtual string get_desc() const
06412 {
06413 return "Insert an ellipse into the image.";
06414 }
06415
06416 static Processor * NEW()
06417 {
06418 return new TestImageEllipse();
06419 }
06420
06421 virtual TypeDict get_param_types() const
06422 {
06423 TypeDict d;
06424 d.put("a", EMObject::FLOAT, "equatorial radius along x axes (major semiaxes)");
06425 d.put("b", EMObject::FLOAT, "equatorial radius along y axes (minor semiaxes)");
06426 d.put("c", EMObject::FLOAT, "polar radius for ellipsoid (x^2/a^2+y^2/b^2+z^2/c^2=1)");
06427 d.put("transform", EMObject::TRANSFORM, "Optionally transform the ellipse");
06428 d.put("fill", EMObject::FLOAT, "value you want to fill in ellipse, default to 1.0");
06429 return d;
06430 }
06431
06432 static const string NAME;
06433 };
06434
06446 class TestImageHollowEllipse : public TestImageProcessor
06447 {
06448 public:
06449 virtual void process_inplace(EMData * image);
06450
06451 virtual string get_name() const
06452 {
06453 return NAME;
06454 }
06455
06456 virtual string get_desc() const
06457 {
06458 return "Insert a hollow ellipse into the image.";
06459 }
06460
06461 static Processor * NEW()
06462 {
06463 return new TestImageHollowEllipse();
06464 }
06465
06466 virtual TypeDict get_param_types() const
06467 {
06468 TypeDict d;
06469 d.put("xwidth", EMObject::FLOAT, "inner equatorial radii along x axes");
06470 d.put("ywidth", EMObject::FLOAT, "inner equatorial radii along y axes");
06471 d.put("zwidth", EMObject::FLOAT, "inner polar radius");
06472 d.put("a", EMObject::FLOAT, "outter equatorial radii along x axes");
06473 d.put("b", EMObject::FLOAT, "outter equatorial radii along y axes");
06474 d.put("c", EMObject::FLOAT, "outter polar radius");
06475 d.put("width",EMObject::FLOAT, "width - specify the width or specify each width explicitly - xwidth, ywidth, zwidth");
06476 d.put("transform", EMObject::TRANSFORM, "Optionally transform the ellipse");
06477 d.put("fill", EMObject::FLOAT, "value you want to fill in hollow ellipse, default to 1.0");
06478 return d;
06479 }
06480
06481 static const string NAME;
06482 };
06483
06490 class TestImageCirclesphere : public TestImageProcessor
06491 {
06492 public:
06493 virtual void process_inplace(EMData * image);
06494
06495 virtual string get_name() const
06496 {
06497 return NAME;
06498 }
06499
06500 virtual string get_desc() const
06501 {
06502 return "Replace a source image as a circle or sphere depends on 2D or 3D of the source image";
06503 }
06504
06505 static Processor * NEW()
06506 {
06507 return new TestImageCirclesphere();
06508 }
06509
06510 virtual TypeDict get_param_types() const
06511 {
06512 TypeDict d;
06513 d.put("radius", EMObject::FLOAT, "radius of circle or sphere, unit: pixel");
06514 d.put("axis", EMObject::STRING, "specify a major axis for asymmetric features");
06515 d.put("c", EMObject::FLOAT, "distance between focus and the center of an ellipse");
06516 d.put("fill", EMObject::INT, "Flag indicating if image is filled, default filled, 1 for filled, 0 for blank.");
06517 return d;
06518 }
06519
06520 static const string NAME;
06521 };
06522
06527 class TestImageNoiseUniformRand : public TestImageProcessor
06528 {
06529 public:
06530 virtual void process_inplace(EMData * image);
06531
06532 virtual string get_name() const
06533 {
06534 return NAME;
06535 }
06536
06537 virtual string get_desc() const
06538 {
06539 return "Replace a source image as a uniform random noise, random number generated from gsl_rng_mt19937, the pixel value is [0, 1)";
06540 }
06541
06542 static Processor * NEW()
06543 {
06544 return new TestImageNoiseUniformRand();
06545 }
06546
06547 virtual TypeDict get_param_types() const
06548 {
06549 TypeDict d;
06550 d.put("seed", EMObject::INT, "seed for random number generator");
06551 return d;
06552 }
06553
06554 static const string NAME;
06555 };
06556
06567 class TestImageNoiseGauss : public TestImageProcessor
06568 {
06569 public:
06570 virtual void process_inplace(EMData * image);
06571
06572 virtual string get_name() const
06573 {
06574 return NAME;
06575 }
06576
06577 virtual string get_desc() const
06578 {
06579 return "Replace a source image as a random noise, the random value is gaussian distributed";
06580 }
06581
06582 static Processor * NEW()
06583 {
06584 return new TestImageNoiseGauss();
06585 }
06586
06587 virtual TypeDict get_param_types() const
06588 {
06589 TypeDict d;
06590 d.put("sigma", EMObject::FLOAT, "sigma value of gausian distributed noise, default is 0.5");
06591 d.put("mean", EMObject::FLOAT, "mean value of gausian distributed noise, default is zero.");
06592 d.put("seed", EMObject::INT, "the seed for random number generator, default is not to reseed.");
06593
06594 return d;
06595 }
06596
06597 static const string NAME;
06598 };
06599
06604 class TestImageCylinder : public TestImageProcessor
06605 {
06606 public:
06607 virtual void process_inplace(EMData * image);
06608
06609 virtual string get_name() const
06610 {
06611 return NAME;
06612 }
06613
06614 virtual string get_desc() const
06615 {
06616 return "Replace a source image as a cylinder";
06617 }
06618
06619 static Processor * NEW()
06620 {
06621 return new TestImageCylinder();
06622 }
06623
06624 virtual TypeDict get_param_types() const
06625 {
06626 TypeDict d;
06627 d.put("radius", EMObject::FLOAT, "radius for the cylinder");
06628 d.put("height", EMObject::FLOAT, "height for the cylinder, by default it's the nz");
06629
06630 return d;
06631 }
06632
06633 static const string NAME;
06634 };
06635
06641 class CCDNormProcessor:public Processor
06642 {
06643 public:
06644 virtual void process_inplace(EMData * image);
06645
06646 virtual string get_name() const
06647 {
06648 return NAME;
06649 }
06650
06651 static Processor *NEW()
06652 {
06653 return new CCDNormProcessor();
06654 }
06655
06656 virtual string get_desc() const
06657 {
06658 return "normalize the 4 quadrants of a CCD image";
06659 }
06660
06661 virtual TypeDict get_param_types() const
06662 {
06663 TypeDict d;
06664 d.put("width", EMObject::INT, "number of pixels on either side of the seam to sample");
06665 return d;
06666 }
06667
06668 static const string NAME;
06669 };
06670
06678 class WaveletProcessor:public Processor
06679 {
06680 public:
06681 virtual void process_inplace(EMData * image);
06682
06683 virtual string get_name() const
06684 {
06685 return NAME;
06686 }
06687
06688 static Processor *NEW()
06689 {
06690 return new WaveletProcessor();
06691 }
06692
06693 virtual TypeDict get_param_types() const
06694 {
06695 TypeDict d;
06696 d.put("type", EMObject::STRING, "'daub', 'harr' or 'bspl'");
06697 d.put("dir", EMObject::INT, "1 for forward transform, -1 for inverse transform");
06698 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)");
06699 return d;
06700 }
06701
06702 virtual string get_desc() const
06703 {
06704 return "Computes the DWT (discrete wavelet transform) of an image in one of 3 possible bases";
06705 }
06706
06707 static const string NAME;
06708 };
06709
06725 class TomoTiltEdgeMaskProcessor : public Processor
06726 {
06727 public:
06728 virtual void process_inplace(EMData* image);
06729
06730 virtual string get_name() const
06731 {
06732 return NAME;
06733 }
06734
06735 static Processor *NEW()
06736 {
06737 return new TomoTiltEdgeMaskProcessor();
06738 }
06739
06740 virtual TypeDict get_param_types() const
06741 {
06742 TypeDict d;
06743 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");
06744 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.");
06745 d.put("angle", EMObject::INT, "The angle that the image is, with respect to the zero tilt image");
06746 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.");
06747 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)");
06748 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");
06749 return d;
06750 }
06751
06752 virtual string get_desc() const
06753 {
06754 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.";
06755 }
06756
06757 static const string NAME;
06758
06759 private:
06760 class GaussianFunctoid
06761 {
06762 public:
06763 GaussianFunctoid(const float sigma, const float mean = 0.0) : m_mean(mean), m_sigma_squared(sigma*sigma) {}
06764 ~GaussianFunctoid() {}
06765
06766 float operator()(const float distance )
06767 {
06768 return exp( -(distance-m_mean)*(distance-m_mean)/ (m_sigma_squared ));
06769 }
06770 private:
06771 float m_mean, m_sigma_squared;
06772 };
06773
06774 };
06775
06790 class TomoTiltAngleWeightProcessor : public Processor
06791 {
06792 public:
06793 virtual void process_inplace(EMData* image);
06794
06795 virtual string get_name() const
06796 {
06797 return NAME;
06798 }
06799
06800 static Processor *NEW()
06801 {
06802 return new TomoTiltAngleWeightProcessor();
06803 }
06804
06805 virtual TypeDict get_param_types() const
06806 {
06807 TypeDict d;
06808 d.put("angle", EMObject::INT, "The angle that the image is, with respect to the zero tilt image");
06809 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");
06810 return d;
06811 }
06812
06813 virtual string get_desc() const
06814 {
06815 return "Weights the image by 1/cos(angle)";
06816 }
06817
06818 static const string NAME;
06819
06820 };
06821
06825 class FFTProcessor : public Processor
06826 {
06827 public:
06828 void process_inplace(EMData * image);
06829
06830 string get_name() const
06831 {
06832 return NAME;
06833 }
06834
06835 static Processor *NEW()
06836 {
06837 return new FFTProcessor();
06838 }
06839
06840 TypeDict get_param_types() const
06841 {
06842 TypeDict d;
06843 d.put("dir", EMObject::INT, "1 for forward transform, -1 for inverse transform");
06844 return d;
06845 }
06846
06847 string get_desc() const
06848 {
06849 return "Computes the DFFT (Discrete Fast Fourier Transform) of an image";
06850 }
06851
06852 static const string NAME;
06853 };
06854
06859 class RadialProcessor : public Processor
06860 {
06861 public:
06862 void process_inplace(EMData * image);
06863
06864 string get_name() const
06865 {
06866 return NAME;
06867 }
06868
06869 static Processor *NEW()
06870 {
06871 return new RadialProcessor();
06872 }
06873
06874 TypeDict get_param_types() const
06875 {
06876 TypeDict d;
06877 d.put("table", EMObject::FLOATARRAY, "Radial array of floats, 1 float/pixel");
06878 return d;
06879 }
06880
06881 string get_desc() const
06882 {
06883 return "Multiply a real-space image by a radial function. 1 value / pixel, extending to corner. Missing values -> 0.";
06884 }
06885
06886 static const string NAME;
06887 };
06888
06895 class HistogramBin : public Processor
06896 {
06897 public:
06898 HistogramBin() : default_bins(1024) {}
06899
06900 void process_inplace(EMData * image);
06901
06902 string get_name() const
06903 {
06904 return NAME;
06905 }
06906
06907 static Processor *NEW()
06908 {
06909 return new HistogramBin();
06910 }
06911
06912 TypeDict get_param_types() const
06913 {
06914 TypeDict d;
06915 d.put("nbins", EMObject::INT, "The number of bins the pixel values will be compressed into");
06916 d.put("debug", EMObject::BOOL, "Outputs debugging information (number of pixels per bin)");
06917 return d;
06918 }
06919
06920 string get_desc() const
06921 {
06922 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";
06923 }
06924
06925 static const string NAME;
06926
06927 protected:
06928 int default_bins;
06929 };
06930
06931 class ModelHelixProcessor : public Processor
06932 {
06933 protected:
06934 float radprofile(float r, int type);
06935 };
06936
06937 class ModelEMCylinderProcessor : public ModelHelixProcessor
06938 {
06939 public:
06940 void process_inplace(EMData * in);
06941
06942 string get_name() const
06943 {
06944 return NAME;
06945 }
06946
06947 static Processor *NEW()
06948 {
06949 return new ModelEMCylinderProcessor();
06950 }
06951
06952 string get_desc() const
06953 {
06954 return "Adds a cylinder with a radial density profile similar to that of an alpha helix.";
06955 }
06956
06957 virtual TypeDict get_param_types() const
06958 {
06959 TypeDict d;
06960 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");
06961 d.put("length", EMObject::FLOAT, "cylinder length in angstroms, defaults to 3 turns (16.2 Angstroms)");
06962 d.put("x0", EMObject::INT, "x coordinate in pixels for the midpoint of the cylinder's axis, defaults to center of map");
06963 d.put("y0", EMObject::INT, "y coordinate in pixels for the midpoint of the cylinder's axis, defaults to center of map");
06964 d.put("z0", EMObject::INT, "z coordinate in pixels for the midpoint of the cylinder's axis, defaults to center of map");
06965
06966 return d;
06967 }
06968
06969 static const string NAME;
06970 };
06971
06972 class ApplyPolynomialProfileToHelix : public ModelHelixProcessor
06973 {
06974 public:
06975 void process_inplace(EMData * in);
06976
06977 string get_name() const
06978 {
06979 return NAME;
06980 }
06981
06982 static Processor *NEW()
06983 {
06984 return new ApplyPolynomialProfileToHelix();
06985 }
06986
06987 string get_desc() const
06988 {
06989 return "Finds the CM of each z-axis slice and applies a polynomial radial profile about it.";
06990 }
06991 virtual TypeDict get_param_types() const
06992 {
06993 TypeDict d;
06994 d.put("length", EMObject::FLOAT, "Helix length in angstroms.");
06995 d.put("z0", EMObject::INT, "z coordinate in pixels for the midpoint of the cylinder's axis, defaults to center of map");
06996 return d;
06997 }
06998
06999 static const string NAME;
07000 };
07001
07002 class BinarySkeletonizerProcessor : public Processor
07003 {
07004 public:
07005 virtual EMData* process(EMData * image);
07006 virtual void process_inplace(EMData * image);
07007
07008 virtual string get_name() const
07009 {
07010 return NAME;
07011
07012 }
07013 static Processor *NEW()
07014 {
07015 return new BinarySkeletonizerProcessor();
07016 }
07017 string get_desc() const
07018 {
07019 return "Creates a skeleton of the 3D image by considering whether density is above or below a threshold value.";
07020 }
07021 virtual TypeDict get_param_types() const
07022 {
07023 TypeDict d;
07024 d.put("threshold", EMObject::FLOAT, "Threshold value.");
07025 d.put("min_curve_width", EMObject::INT, "Minimum curve width.");
07026 d.put("min_surface_width", EMObject::INT, "Minimum surface width.");
07027 d.put("mark_surfaces", EMObject::BOOL, "Mark surfaces with a value of 2.0f, whereas curves are 1.0f.");
07028 return d;
07029 }
07030 static const string NAME;
07031 };
07032
07033 class ConvolutionKernelProcessor : public Processor
07034 {
07035 public:
07036 virtual EMData* process(const EMData* const image);
07037 virtual void process_inplace(EMData * image);
07038
07039 virtual string get_name() const
07040 {
07041 return NAME;
07042 }
07043 static Processor *NEW()
07044 {
07045 return new ConvolutionKernelProcessor();
07046 }
07047 string get_desc() const
07048 {
07049 return "Filters an image with a convolution kernel in real space.";
07050 }
07051 virtual TypeDict get_param_types() const
07052 {
07053 TypeDict d;
07054 d.put("kernel", EMObject::FLOATARRAY, "the convolution kernel");
07055 return d;
07056 }
07057 static const string NAME;
07058 };
07059
07060 class RotateInFSProcessor : public Processor
07061 {
07062 public:
07063
07064 virtual void process_inplace(EMData * image);
07065 virtual EMData* process(const EMData* const image);
07066
07067 virtual string get_name() const
07068 {
07069 return NAME;
07070 }
07071 static Processor *NEW()
07072 {
07073 return new RotateInFSProcessor( );
07074 }
07075 string get_desc() const
07076 {
07077 return "Rotates a Fourier object using a kernel.";
07078 }
07079 virtual TypeDict get_param_types() const
07080 {
07081 TypeDict d;
07082 d.put("transform", EMObject::TRANSFORM, "transform");
07083 d.put("interpCutoff", EMObject::FLOAT, "cutoff for interpolation");
07084
07085
07086 return d;
07087 }
07088 static const string NAME;
07089 };
07090
07091 #ifdef SPARX_USING_CUDA
07092
07093
07094
07095
07096
07097 class MPICUDA_kmeans {
07098 public:
07099 MPICUDA_kmeans();
07100 ~MPICUDA_kmeans();
07101 int setup(int extm, int extN, int extn, int extK, int extn_start);
07102 void append_flat_image(EMData* im, int pos);
07103 int init_mem(int numdev);
07104 void compute_im2();
07105 int random_ASG(long int rnd);
07106 vector<int> get_ASG();
07107 vector<int> get_asg();
07108 void compute_NC();
07109 vector<int> get_NC();
07110 void set_ASG(const vector <int>& ASG);
07111 void set_NC(const vector <int>& NC);
07112 int get_ct_im_mv();
07113 void set_T(float extT);
07114 float get_T();
07115 void compute_AVE();
07116 void set_AVE(EMData* im, int pos);
07117 vector<EMData*> get_AVE();
07118 int one_iter();
07119
07120
07121 int one_iter_SA();
07122 vector<float> compute_ji();
07123 vector<float> compute_criterion(const vector <float>& Ji);
07124 int shutdown();
07125 private:
07126
07127 int m;
07128 int N;
07129 int n;
07130 int K;
07131 int nb_part;
07132 int n_start;
07133 int size_im;
07134 int size_IM;
07135 int size_AVE;
07136 int size_dist;
07137 int BLOCK_SIZE;
07138 int NB;
07139 int ins_BLOCK;
07140 int ite;
07141 float T;
07142
07143 int ct_im_mv;
07144
07145 float* h_IM;
07146 float* h_im;
07147 float* h_AVE;
07148 float* h_dist;
07149 float* h_AVE2;
07150 float* h_im2;
07151 unsigned short int* h_ASG;
07152 unsigned short int* h_asg;
07153 unsigned int* h_NC;
07154 int* params;
07155 float ttt;
07156
07157 float* d_im;
07158 float* d_AVE;
07159 float* d_dist;
07160
07161 float compute_tt();
07162 };
07163
07164 #endif //EMAN2_USING_CUDA
07165
07166 #if 0
07167
07168 class XYZProcessor:public Processor
07169 {
07170 public:
07171 void process_inplace(EMData * image);
07172
07173 string get_name() const
07174 {
07175 return NAME;
07176 }
07177
07178 static Processor *NEW()
07179 {
07180 return new XYZProcessor();
07181 }
07182
07183 string get_desc() const
07184 {
07185 return "N/A";
07186 }
07187
07188 TypeDict get_param_types() const
07189 {
07190 TypeDict d;
07191 return d;
07192 }
07193
07194 static const string NAME;
07195 };
07196
07197
07198 #endif
07199
07200
07201 #if 0
07202
07203 class XYZProcessor:public Processor
07204 {
07205 public:
07206 void process_inplace(EMData * image);
07207
07208 string get_name() const
07209 {
07210 return NAME;
07211 }
07212
07213 static Processor *NEW()
07214 {
07215 return new XYZProcessor();
07216 }
07217
07218 string get_desc() const
07219 {
07220 return "N/A";
07221 }
07222
07223 TypeDict get_param_types() const
07224 {
07225 TypeDict d;
07226 return d;
07227 }
07228
07229 static const string NAME;
07230 };
07231
07232
07233 #endif
07234
07235
07236 int multi_processors(EMData * image, vector < string > processornames);
07237 void dump_processors();
07238 map<string, vector<string> > dump_processors_list();
07239 map<string, vector<string> > group_processors();
07240
07241 template <> Factory < Processor >::Factory();
07242 }
07243
07244 #endif //eman_filter_h__
07245
07246
07247