processor.h

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