EMAN2
processor.h
Go to the documentation of this file.
1/*
2 * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
3 * Copyright (c) 2000-2006 Baylor College of Medicine
4 *
5 * This software is issued under a joint BSD/GNU license. You may use the
6 * source code in this file under either license. However, note that the
7 * complete EMAN2 and SPARX software packages have some GPL dependencies,
8 * so you are responsible for compliance with the licenses of these packages
9 * if you opt to use BSD licensing. The warranty disclaimer below holds
10 * in either instance.
11 *
12 * This complete copyright notice must be included in any revised version of the
13 * source code. Additional authorship citations may be added, but existing
14 * author citations must be preserved.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by.edge
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 * */
31
32#ifndef eman_processor_h__
33#define eman_processor_h__ 1
34
35#include "emobject.h"
36#include "util.h"
37#include "geometry.h"
38#include "transform.h"
39#include "emdata.h"
40#include "gorgon/skeletonizer.h"
41
42#include <cfloat>
43#include <climits>
44#include <cstring>
45
46using std::vector;
47using std::map;
48using std::string;
49
50namespace EMAN
51{
52 class EMData;
53
90 {
91 public:
92 virtual ~ Processor()
93 {
94 }
95
101 virtual void process_inplace(EMData *image) = 0;
102
109 virtual EMData* process(const EMData * const image);
110
114 virtual void process_list_inplace(vector < EMData * > & images)
115 {
116 for (size_t i = 0; i < images.size(); i++) {
118 }
119 }
120
124 virtual string get_name() const = 0;
125
129 virtual Dict get_params() const
130 {
131 return params;
132 }
133
137 virtual void set_params(const Dict & new_params)
138 {
139 params = new_params;
140 }
141
148 virtual TypeDict get_param_types() const
149 {
150 return TypeDict();
151 }
152
159 static string get_group_desc()
160 {
161 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> \
162The basic design of EMAN Processors: <br>\
163 1) Each Processor class defines an image-processinging algorithm. <br>\
164 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>\
165 3) Each Processor class defines its own parameter set.<br>\
166 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.";
167 }
168
174 virtual string get_desc() const = 0;
175
206 };
207
232 static void
234 bool doInPlace = true;
235 EMFourierFilterFunc(fimage, params, doInPlace);
236 }
237
263 static EMData*
265 bool doInPlace = false;
266 return EMFourierFilterFunc(fimage, params, doInPlace);
267 }
268
269 private:
305 static EMData*
306 EMFourierFilterFunc(EMData* fimage, Dict params, bool doInPlace=true);
307
308 protected:
309 mutable Dict params;
310 };
311
313 {
314 public:
315 void process_inplace(EMData * image);
316
317 static string get_group_desc()
318 {
319 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(). ";
320 }
321
322 protected:
323 virtual EMData * create_processor_image() const = 0;
324 };
325
333 {
334 public:
335 void process_inplace(EMData * image);
336
337 static string get_group_desc()
338 {
339 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]. ";
340 }
341
343 {
344 TypeDict d;
345 d.put("cutoff_abs", EMObject::FLOAT, "Processor radius in terms of Nyquist (0-.5)");
346 d.put("cutoff_pixels", EMObject::FLOAT, " Width in Fourier pixels (0 - size()/2)");
347 d.put("cutoff_freq", EMObject::FLOAT, "1/Resolution in 1/A (0 - 1 / 2*apix). eg - a 20 A filter is cutoff_freq=0.05");
348 d.put("apix", EMObject::FLOAT, " Override A/pix in the image header (changes x,y and z)");
349 d.put("return_radial", EMObject::BOOL, "Return the radial filter function as an attribute (filter_curve)");
350 return d;
351 }
352
353 protected:
354 virtual void preprocess(EMData *image) {
355 if(params.has_key("apix")) {
356 image->set_attr("apix_x", (float)params["apix"]);
357 image->set_attr("apix_y", (float)params["apix"]);
358 image->set_attr("apix_z", (float)params["apix"]);
359 }
360
361 const Dict dict = image->get_attr_dict();
362 if( params.has_key("sigma")) {
363 params["cutoff_abs"] = (float)params["sigma"];
364 }
365 else if( params.has_key("cutoff_abs") ) {
366 params["sigma"] = (float)params["cutoff_abs"];
367 }
368 else if( params.has_key("cutoff_freq") ) {
369 float val = (float)params["cutoff_freq"] * (float)dict["apix_x"];
370 params["cutoff_abs"] = val;
371 params["sigma"] = val;
372 }
373 else if( params.has_key("cutoff_pixels") ) {
374 float val = ((float)params["cutoff_pixels"] / (float)dict["nx"]);
375 params["cutoff_abs"] = val;
376 params["sigma"] = val;
377 }
378
379 }
380 virtual void create_radial_func(vector < float >&radial_mask) const = 0;
381 };
382
391 {
392 public:
393 void process_inplace(EMData * image);
394
395 static string get_group_desc()
396 {
397 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]. ";
398 }
399
401 {
402 TypeDict d;
403 d.put("cutoff_abs", EMObject::FLOAT, "Processor radius in terms of Nyquist (0-.5)");
404 d.put("cutoff_pixels", EMObject::FLOAT, " Width in Fourier pixels (0 - size()/2)");
405 d.put("cutoff_freq", EMObject::FLOAT, "1/Resolution in 1/A (0 - 1 / 2*apix). eg - a 20 A filter is cutoff_freq=0.05");
406 d.put("apix", EMObject::FLOAT, " Override A/pix in the image header (changes x,y and z)");
407 d.put("return_radial", EMObject::BOOL, "Return the radial filter function as an attribute (filter_curve)");
408 d.put("interpolate", EMObject::BOOL, "Whether or not to interpolate the radial scaling function. Default=false. Prb should be true.");
409 return d;
410 }
411
412 protected:
413 virtual void preprocess(EMData *) {}
414 virtual void create_radial_func(vector < float >&radial_mask,EMData *image) const = 0;
415 };
416
422 {
423 public:
424 void process_inplace(EMData * image);
425
426 string get_name() const
427 {
428 return NAME;
429 }
430
431 static Processor *NEW()
432 {
433 return new AzSharpProcessor();
434 }
435
436 string get_desc() const
437 {
438 return "Typical linear filters are radial, but certain operations can lead to inhomogeneities so the balance between radial and azimuthal power is off. This processor permits enhancing or suppressing azimuthal contrast in Fourier space.";
439 }
440
442 {
443 TypeDict d;
444 d.put("az_scale", EMObject::FLOAT, "Scale factor, >1 enhances contrast <1 decreases");
445 return d;
446 }
447
448 static const string NAME;
449
450 };
451
452
456 {
457 public:
458 string get_name() const
459 {
460 return NAME;
461 }
462
463 void process_inplace(EMData * image);
464
465 void set_params(const Dict & new_params)
466 {
467 params = new_params;
468// sum = params["sum"];
469// dosqrt = params["sqrt"];
470// printf("%s %f\n",params.keys()[0].c_str(),lowpass);
471 }
472
474 {
475 TypeDict d;
476// d.put("sum", EMObject::EMDATA, "Adds the weights to sum for normalization");
477// d.put("sqrt", EMObject::INT, "Weights using sqrt of the amplitude if set");
478 return d;
479 }
480
481 static Processor *NEW()
482 {
483 return new SNREvalProcessor();
484 }
485
486 string get_desc() const
487 {
488 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";
489 }
490
491 static const string NAME;
492
493 protected:
496 };
497
501 {
502 public:
503 string get_name() const
504 {
505 return NAME;
506 }
507
508 void process_inplace(EMData * image);
509
510 void set_params(const Dict & new_params)
511 {
512 params = new_params;
513 }
514
516 {
517 TypeDict d;
518 d.put("x", EMObject::INT, "If set, zeroes along X axis. Default True.");
519 d.put("y", EMObject::INT, "If set, zeroes along Y axis. Default True.");
520 d.put("neighbor", EMObject::INT, "If set, interpolates neighbor values rather than zeroing");
521 d.put("neighbornorm", EMObject::INT, "In neighbor mode it sums the neighboring 2 (complex) pixels, then divides by this factor. default = sqrt(2), which is good for very noisy images");
522 return d;
523 }
524
525 static Processor *NEW()
526 {
527 return new Axis0FourierProcessor();
528 }
529
530 string get_desc() const
531 {
532 return "Sets values along X/Y Fourier axes to 0, except origin";
533 }
534
535 static const string NAME;
536
537 protected:
538 };
539
543 {
544 public:
545 string get_name() const
546 {
547 return NAME;
548 }
549
550 void process_inplace(EMData * image);
551
552 void set_params(const Dict & new_params)
553 {
554 params = new_params;
555 }
556
558 {
559 TypeDict d;
560 d.put("cutoff_abs", EMObject::FLOAT, "Processor radius in terms of Nyquist (0-.5)");
561 d.put("cutoff_pixels", EMObject::FLOAT, " Width in Fourier pixels (0 - size()/2)");
562 d.put("cutoff_freq", EMObject::FLOAT, "1/Resolution in 1/A (0 - 1 / 2*apix). eg - a 20 A filter is cutoff_freq=0.05");
563 d.put("hppix", EMObject::FLOAT, "If specified will also apply a high pass filter with the specified radius in pixels");
564 d.put("apix", EMObject::FLOAT, " Override A/pix in the image header (changes x,y and z)");
565 d.put("centerfreq", EMObject::FLOAT, "center of filter frequency at z");
566 d.put("xynoz", EMObject::INT, "If set, filters the X-Y plane instead of Z");
567 return d;
568 }
569
570 static Processor *NEW()
571 {
572 return new GaussZFourierProcessor();
573 }
574
575 string get_desc() const
576 {
577 return "Applies a Gaussian lowpass filter (or its inverse), but only along the Z axis (or X-Y). May be useful in anisotropic filtering of tomograms.";
578 }
579
580 static const string NAME;
581
582 protected:
583 };
584
585
586
592 {
593 public:
594 string get_name() const
595 {
596 return NAME;
597 }
598
599 void process_inplace(EMData * image);
600
601 void set_params(const Dict & new_params)
602 {
603 params = new_params;
604 sum = params["sum"];
605 dosqrt = params["sqrt"];
606// printf("%s %f\n",params.keys()[0].c_str(),lowpass);
607 }
608
610 {
611 TypeDict d;
612 d.put("sum", EMObject::EMDATA, "Adds the weights to sum for normalization");
613 d.put("sqrt", EMObject::INT, "Weights using sqrt of the amplitude if set");
614 return d;
615 }
616
617 static Processor *NEW()
618 {
619 return new AmpweightFourierProcessor();
620 }
621
622 string get_desc() const
623 {
624 return "Multiplies each Fourier pixel by its amplitude";
625 }
626
627 static const string NAME;
628
629 protected:
632 };
640 {
641 public:
643
644 string get_name() const
645 {
646 return NAME;
647 }
648
649 void process_inplace(EMData *image);
650
651 static Processor *NEW()
652 {
653 return new ConvolutionProcessor();
654 }
655
656 string get_desc() const
657 {
658 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.";
659 }
660
662 {
663 TypeDict d;
664 d.put("with", EMObject::EMDATA, "The image that will convolute the other image");
665 return d;
666 }
667
668 static const string NAME;
669 };
670
682 {
683 public:
685
686 string get_name() const
687 {
688 return NAME;
689 }
690
691 void process_inplace(EMData *image) { throw InvalidCallException("inplace not supported"); }
692
693 virtual EMData* process(const EMData* const image);
694
695 static Processor *NEW()
696 {
697 return new HarmonicProcessor();
698 }
699
700 string get_desc() const
701 {
702 return "Computes invariants including relative phase in harmonic series";
703 }
704
706 {
707 TypeDict d;
708 d.put("hn", EMObject::INT, "Computes a single translational invariant for the nth harmonic, 1 is a normal power spectrum");
709 d.put("rn", EMObject::INT, "Computes a single rot/trans invariant for the nth rotational harmonic, requires hn to be non zero");
710 d.put("rfp", EMObject::INT, "Returns a non square 2-D image with translational invariants, y=radial, x=aziumth. Used for rotational alignment.");
711 d.put("fp", EMObject::INT, "Returns a non-square 2-D image containing n harmonics for each R&T component. R&T invariant. Min 2, default 4");
712// d.put("fb", EMObject::INT, "Fourier Bessel");
713 d.put("size", EMObject::INT, "If specified, will determine the number of rotational samples in the bispectrum. If not set, a size is selected automatically");
714 return d;
715 }
716
717 static const string NAME;
718 };
719
720
735 {
736 public:
738
739 string get_name() const
740 {
741 return NAME;
742 }
743
744 void process_inplace(EMData *image) { throw InvalidCallException("inplace not supported"); }
745
746 virtual EMData* process(const EMData* const image);
747
748 static Processor *NEW()
749 {
750 return new BispecSliceProcessor();
751 }
752
753 string get_desc() const
754 {
755 return "Computes a 2-D slice of the 4-D bispectrum of a 2-D image. Returns zero outside of source image. Input may be real or complex, but output is always complex. kx,ky OR jkx,jky OR k OR fp OR ffp";
756 }
757
759 {
760 TypeDict d;
761 d.put("kx", EMObject::INT, "Kx location of the slice in Fourier pixels");
762 d.put("ky", EMObject::INT, "Ky location of the slice in Fourier pixels");
763 d.put("jkx", EMObject::INT, "Jx+Kx location of the slice in Fourier pixels");
764 d.put("jky", EMObject::INT, "Jy+Ky location of the slice in Fourier pixels");
765 d.put("k", EMObject::FLOAT, "Radius of slice in Fourier pixels, integrates over angle.");
766 d.put("prbk", EMObject::FLOAT, "Radius of slice in Fourier pixels, integrates over angle.");
767 d.put("prbkv2", EMObject::FLOAT, "Radius of slice in Fourier pixels, integrates over angle. k>|q+k|>q");
768 d.put("prb3D", EMObject::FLOAT, "Radius of maximum slic. Returns volume, integrates over angle. k>|q+k|>q");
769 d.put("rfp", EMObject::INT, "Returns a non square 2-D image containing translatinal invariants organized such that X=azimuth. Used for rotational alignment.");
770 d.put("fp", EMObject::INT, "Returns a non-square 2-D image containing n rotationally integrated planes. R&T invariant.");
771 d.put("ffp", EMObject::INT, "Returns a 3-D volume containing n rotationally integrated planes. R&T invariant. This is normally further processed with CTF info to produce fp equivalent.");
772 d.put("size", EMObject::INT, "If specified, will determine the size (x/y) of the real-space bispectrum image. If not set, a size is selected automatically");
773 return d;
774 }
775
776 static const string NAME;
777 };
778
786 {
787 public:
789
790 string get_name() const
791 {
792 return NAME;
793 }
794
795 virtual void process_inplace(EMData *image);
796
797 virtual EMData* process(const EMData* const image);
798
799 static Processor *NEW()
800 {
801 return new EnhanceProcessor();
802 }
803
804 string get_desc() const
805 {
806 return "Visual enhancement filter useful for localizing particles. Results not designed for reconstruction.";
807 }
808
810 {
811 TypeDict d;
812// d.put("kx", EMObject::INT, "Kx location of the slice in Fourier pixels");
813// d.put("ky", EMObject::INT, "Ky location of the slice in Fourier pixels");
814// d.put("jkx", EMObject::INT, "Jx+Kx location of the slice in Fourier pixels");
815// d.put("jky", EMObject::INT, "Jy+Ky location of the slice in Fourier pixels");
816// d.put("k", EMObject::FLOAT, "Radius of slice in Fourier pixels, integrates over angle.");
817// d.put("rfp", EMObject::INT, "Returns a non square 2-D image containing rotational invariants organized such that X=azimuth. Used for rotational alignment.");
818// d.put("fp", EMObject::INT, "Returns a non-square 2-D image containing n rotationally integrated planes. R&T invariant.");
819// d.put("ffp", EMObject::INT, "Returns a 3-D volume containing n rotationally integrated planes. R&T invariant. This is normally further processed with CTF info to produce fp equivalent.");
820// d.put("size", EMObject::INT, "If specified, will determine the size (x/y) of the real-space bispectrum image. If not set, a size is selected automatically");
821 return d;
822 }
823
824 static const string NAME;
825 };
826
836 {
837 public:
839
840 string get_name() const
841 {
842 return NAME;
843 }
844
845 void process_inplace(EMData *image) { throw InvalidCallException("inplace operation not supported"); }
846
847 virtual EMData* process(const EMData* const image);
848
849 static Processor *NEW()
850 {
851 return new MaskPackProcessor();
852 }
853
854 string get_desc() const
855 {
856 return "Given a mask, will return a 1-D image containing values from the original image inside the mask. If unpack is set, then the inverse operation is performed.";
857 }
858
860 {
861 TypeDict d;
862 d.put("unpack", EMObject::INT, "If set, image should be 1-D and return will match the dimensions of the mask");
863 d.put("mask", EMObject::EMDATA, "The mask indicating which pixels to extract. Required");
864 return d;
865 }
866
867 static const string NAME;
868 };
869
870
878 {
879 public:
881
882 string get_name() const
883 {
884 return NAME;
885 }
886
887 void process_inplace(EMData *image);
888
889 static Processor *NEW()
890 {
891 return new XGradientProcessor();
892 }
893
894 string get_desc() const
895 {
896 return "Determines the image gradient in the x direction";
897 }
898
900 {
901 TypeDict d;
902 return d;
903 }
904
905 static const string NAME;
906 };
907
909 {
910 public:
912
913 string get_name() const
914 {
915 return NAME;
916 }
917
918 void process_inplace(EMData *image);
919
920 static Processor *NEW()
921 {
922 return new YGradientProcessor();
923 }
924
925 string get_desc() const
926 {
927 return "Determines the image gradient in the y direction";
928 }
929
930
932 {
933 TypeDict d;
934 return d;
935 }
936
937 static const string NAME;
938 };
939
941 {
942 public:
944
945 string get_name() const
946 {
947 return NAME;
948 }
949
950 void process_inplace(EMData *image);
951
952 static Processor *NEW()
953 {
954 return new ZGradientProcessor();
955 }
956
957 string get_desc() const
958 {
959 return "Determines the image gradient in the z direction";
960 }
961
963 {
964 TypeDict d;
965 return d;
966 }
967
968 static const string NAME;
969 };
970
977 {
978 public:
980
981 string get_name() const
982 {
983 return NAME;
984 }
985
986 void process_inplace(EMData *image);
987
988 static Processor *NEW()
989 {
990 return new ImageDivergenceProcessor();
991 }
992
993 string get_desc() const
994 {
995 return "Determines the divergence of a 2D image.";
996 }
997
999 {
1000 TypeDict d;
1001 return d;
1002 }
1003
1004 static const string NAME;
1005 };
1006
1013 {
1014 public:
1016
1017 string get_name() const
1018 {
1019 return NAME;
1020 }
1021
1022 void process_inplace(EMData *image);
1023
1024 static Processor *NEW()
1025 {
1026 return new GradientMagnitudeProcessor();
1027 }
1028
1029 string get_desc() const
1030 {
1031 return "Determines the magnitude of the gradient of a 2D image.";
1032 }
1033
1035 {
1036 TypeDict d;
1037 return d;
1038 }
1039
1040 static const string NAME;
1041 };
1042
1049 {
1050 public:
1052
1053 string get_name() const
1054 {
1055 return NAME;
1056 }
1057
1058 void process_inplace(EMData *image);
1059
1060 static Processor *NEW()
1061 {
1062 return new GradientDirectionProcessor();
1063 }
1064
1065 string get_desc() const
1066 {
1067 return "Determines the direction of the gradient of a 2D image.";
1068 }
1069
1071 {
1072 TypeDict d;
1073 return d;
1074 }
1075
1076 static const string NAME;
1077 };
1078
1085 {
1086 public:
1088
1089 string get_name() const
1090 {
1091 return NAME;
1092 }
1093
1094 void process_inplace(EMData *image);
1095
1096 static Processor *NEW()
1097 {
1098 return new LaplacianMagnitudeProcessor();
1099 }
1100
1101 string get_desc() const
1102 {
1103 return "Determines the magnitude of the laplacian of a 2D image.";
1104 }
1105
1107 {
1108 TypeDict d;
1109 return d;
1110 }
1111
1112 static const string NAME;
1113 };
1114
1121 {
1122 public:
1124
1125 string get_name() const
1126 {
1127 return NAME;
1128 }
1129
1130 void process_inplace(EMData *image);
1131
1132 static Processor *NEW()
1133 {
1134 return new LaplacianDirectionProcessor();
1135 }
1136
1137 string get_desc() const
1138 {
1139 return "Determines the direction of the laplacian of a 2D image.";
1140 }
1141
1143 {
1144 TypeDict d;
1145 return d;
1146 }
1147
1148 static const string NAME;
1149 };
1150
1157 {
1158 public:
1160
1161 string get_name() const
1162 {
1163 return NAME;
1164 }
1165
1166 void process_inplace(EMData *image);
1167
1168 static Processor *NEW()
1169 {
1170 return new SDGDProcessor();
1171 }
1172
1173 string get_desc() const
1174 {
1175 return "Determines the second derivative of a 2D image in the gradient direction.";
1176 }
1177
1179 {
1180 TypeDict d;
1181 return d;
1182 }
1183
1184 static const string NAME;
1185 };
1186
1194 {
1195 public:
1197
1198 string get_name() const
1199 {
1200 return NAME;
1201 }
1202
1203 virtual EMData* process(const EMData * const image);
1204
1205 void process_inplace(EMData * image);
1206
1207 static Processor *NEW()
1208 {
1209 return new ManhattanDistanceProcessor();
1210 }
1211
1212 string get_desc() const
1213 {
1214 return "Sets pixel values in a binary image equal to their element wise manhattan distance.";
1215 }
1216
1218 {
1219 TypeDict d;
1220 //d.put("threshold", EMObject::FLOAT,"Only considers densities above the threshold");
1221 return d;
1222 }
1223
1224 static const string NAME;
1225 };
1226
1227
1234 {
1235 public:
1237
1238 string get_name() const
1239 {
1240 return NAME;
1241 }
1242
1243 virtual EMData* process(const EMData * const image);
1244
1245 void process_inplace(EMData *image);
1246
1247 static Processor *NEW()
1248 {
1249 return new BinaryDilationProcessor();
1250 }
1251
1252 string get_desc() const
1253 {
1254 return "Performs a morphological dilation of a (binary) image.";
1255 }
1256
1258 {
1259 TypeDict d;
1260 d.put("radius", EMObject::INT, "The number of pixels (radius) to dilate the input image.");
1261 d.put("iters",EMObject::INT, "The number of times to apply this process to the input image.");
1262 d.put("thresh", EMObject::FLOAT,"Only considers densities above the threshold");
1263 return d;
1264 }
1265
1266 static const string NAME;
1267 };
1268
1275 {
1276 public:
1278
1279 string get_name() const
1280 {
1281 return NAME;
1282 }
1283
1284 virtual EMData* process(const EMData * const image);
1285
1286 void process_inplace(EMData *image);
1287
1288 static Processor *NEW()
1289 {
1290 return new BinaryErosionProcessor();
1291 }
1292
1293 string get_desc() const
1294 {
1295 return "Performs a morphological k-pixel erosion of a (binary) image.";
1296 }
1297
1299 {
1300 TypeDict d;
1301 d.put("radius", EMObject::INT, "The number of pixels (radius) to dilate the input image.");
1302 d.put("iters",EMObject::INT, "The number of times to apply this process to the input image.");
1303 d.put("thresh", EMObject::FLOAT,"Only considers densities above the threshold");
1304 return d;
1305 }
1306
1307 static const string NAME;
1308 };
1309
1310
1317 {
1318 public:
1320
1321 string get_name() const
1322 {
1323 return NAME;
1324 }
1325
1326 virtual EMData* process(const EMData * const image);
1327
1328 void process_inplace(EMData *image);
1329
1330 static Processor *NEW()
1331 {
1332 return new BinaryClosingProcessor();
1333 }
1334
1335 string get_desc() const
1336 {
1337 return "Performs a morphological k-pixel closing of a (binary) image/volume. Note the box must be large enough to accommodate the dilation to work properly. iter(dilate) -> iter(erode)";
1338 }
1339
1341 {
1342 TypeDict d;
1343 d.put("radius", EMObject::INT, "The number of pixels (radius) to dilate the input image.");
1344 d.put("iters",EMObject::INT, "The number of times to apply this process to the input image.");
1345 d.put("thresh", EMObject::FLOAT,"Only considers densities above the threshold");
1346 return d;
1347 }
1348
1349 static const string NAME;
1350 };
1351
1352
1359 {
1360 public:
1362
1363 string get_name() const
1364 {
1365 return NAME;
1366 }
1367
1368 virtual EMData* process(const EMData * const image);
1369
1370 void process_inplace(EMData *image);
1371
1372 static Processor *NEW()
1373 {
1374 return new BinaryOpeningProcessor();
1375 }
1376
1377 string get_desc() const
1378 {
1379 return "Performs a morphological k-pixel opening of a (binary) image/volume. iter(erode) -> iter(dilate)";
1380 }
1381
1383 {
1384 TypeDict d;
1385 d.put("radius", EMObject::INT, "The number of pixels (radius) to dilate the input image.");
1386 d.put("iters",EMObject::INT, "The number of times to apply this process to the input image.");
1387 d.put("thresh", EMObject::FLOAT,"Only considers densities above the threshold");
1388 return d;
1389 }
1390
1391 static const string NAME;
1392 };
1393
1394
1401 {
1402 public:
1404
1405 string get_name() const
1406 {
1407 return NAME;
1408 }
1409
1410 virtual EMData* process(const EMData * const image);
1411
1412 void process_inplace(EMData *image);
1413
1414 static Processor *NEW()
1415 {
1417 }
1418
1419 string get_desc() const
1420 {
1421 return "Computes an internal morphological graduent using k-pixel-width operations on a (binary) image.";
1422 }
1423
1425 {
1426 TypeDict d;
1427 d.put("radius", EMObject::INT, "The number of pixels (radius) to dilate the input image.");
1428 d.put("iters",EMObject::INT, "The number of times to apply this process to the input image.");
1429 d.put("thresh", EMObject::FLOAT,"Only considers densities above the threshold");
1430 return d;
1431 }
1432
1433 static const string NAME;
1434 };
1435
1436
1443 {
1444 public:
1446
1447 string get_name() const
1448 {
1449 return NAME;
1450 }
1451
1452 virtual EMData* process(const EMData * const image);
1453
1454 void process_inplace(EMData *image);
1455
1456 static Processor *NEW()
1457 {
1459 }
1460
1461 string get_desc() const
1462 {
1463 return "Computes an external morphological graduent using k-pixel-width operations on a (binary) image.";
1464 }
1465
1467 {
1468 TypeDict d;
1469 d.put("radius", EMObject::INT, "The number of pixels (radius) to dilate the input image.");
1470 d.put("iters",EMObject::INT, "The number of times to apply this process to the input image.");
1471 d.put("thresh", EMObject::FLOAT,"Only considers densities above the threshold");
1472 return d;
1473 }
1474
1475 static const string NAME;
1476 };
1477
1478
1485 {
1486 public:
1488
1489 string get_name() const
1490 {
1491 return NAME;
1492 }
1493
1494 virtual EMData* process(const EMData * const image);
1495
1496 void process_inplace(EMData *image);
1497
1498 static Processor *NEW()
1499 {
1500 return new BinaryMorphGradientProcessor();
1501 }
1502
1503 string get_desc() const
1504 {
1505 return "Computes the morphological graduent using k-pixel-width operations on a (binary) image.";
1506 }
1507
1509 {
1510 TypeDict d;
1511 d.put("radius", EMObject::INT, "The number of pixels (radius) to dilate the input image.");
1512 d.put("iters",EMObject::INT, "The number of times to apply this process to the input image.");
1513 d.put("thresh", EMObject::FLOAT,"Only considers densities above the threshold");
1514 return d;
1515 }
1516
1517 static const string NAME;
1518 };
1519
1520
1527 {
1528 public:
1530
1531 string get_name() const
1532 {
1533 return NAME;
1534 }
1535
1536 virtual EMData* process(const EMData * const image);
1537
1538 void process_inplace(EMData *image);
1539
1540 static Processor *NEW()
1541 {
1542 return new BinaryTopHatProcessor();
1543 }
1544
1545 string get_desc() const
1546 {
1547 return "Performs a morphological top hat operation on a (binary) image.";
1548 }
1549
1551 {
1552 TypeDict d;
1553 d.put("radius", EMObject::INT, "The number of pixels (radius) to dilate the input image.");
1554 d.put("iters",EMObject::INT, "The number of times to apply this process to the input image.");
1555 d.put("thresh", EMObject::FLOAT,"Only considers densities above the threshold");
1556 return d;
1557 }
1558
1559 static const string NAME;
1560 };
1561
1562
1569 {
1570 public:
1572
1573 string get_name() const
1574 {
1575 return NAME;
1576 }
1577
1578 virtual EMData* process(const EMData * const image);
1579
1580 void process_inplace(EMData *image);
1581
1582 static Processor *NEW()
1583 {
1584 return new BinaryBlackHatProcessor();
1585 }
1586
1587 string get_desc() const
1588 {
1589 return "Performs a morphological black hat operation on a (binary) image.";
1590 }
1591
1593 {
1594 TypeDict d;
1595 d.put("radius", EMObject::INT, "The number of pixels (radius) to dilate the input image.");
1596 d.put("iters",EMObject::INT, "The number of times to apply this process to the input image.");
1597 d.put("thresh", EMObject::FLOAT,"Only considers densities above the threshold");
1598 return d;
1599 }
1600
1601 static const string NAME;
1602 };
1603
1613 {
1614 public:
1615 string get_name() const
1616 {
1617 return NAME;
1618 }
1619
1620 virtual EMData* process(const EMData * const image);
1621
1622 void process_inplace(EMData *image);
1623
1624 void set_params(const Dict & new_params)
1625 {
1626 params = new_params;
1627 bgsize = params["size"];
1628// printf("%s %f\n",params.keys()[0].c_str(),lowpass);
1629 }
1630
1632 {
1633 TypeDict d;
1634 d.put("size", EMObject::INT, "Size in pixels of the boxes to chop the image into");
1635 return d;
1636 }
1637
1638 static Processor *NEW()
1639 {
1640 return new Wiener2DAutoAreaProcessor();
1641 }
1642
1643 string get_desc() const
1644 {
1645 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";
1646 }
1647
1648 static const string NAME;
1649
1650 protected:
1652 };
1653
1661 {
1662 public:
1663 string get_name() const
1664 {
1665 return NAME;
1666 }
1667
1668 virtual EMData* process(const EMData * const image);
1669 void process_inplace( EMData * image);
1670
1672 {
1673 TypeDict d ;
1674 d.put("minratio",EMObject::FLOAT,"The ratio of the smallest amplitude segment to locate relative to the strongest peak (default=0.5)");
1675 d.put("maxnseg",EMObject::INT,"Maximum number of segments to return (default = unlimited)");
1676 d.put("width",EMObject::FLOAT,"Required: full width of Gaussians in A at 1/e (FWHM). Also used to determine map prefiltration.");
1677 d.put("mask",EMObject::EMDATA,"Optional: mask to apply to map after filtration to limit where centers are placed");
1678 d.put("skipseg",EMObject::INT,"Normally the returned map is a segmentation map, but this is unnecessary if only the center coordinates are needed. If 1, the returned map will be a residual volume, not a segmentation map. If 2, it will be the filtered map before segmentation");
1679 d.put("verbose",EMObject::INT,"Be verbose while running");
1680 return d;
1681 }
1682
1683 static Processor *NEW()
1684 {
1685 return new GaussSegmentProcessor();
1686 }
1687
1688 string get_desc() const
1689 {
1690 return "Segments a volume by sequentially finding and subtracting Gaussians at a specified resolvability.";
1691 }
1692
1693 static const string NAME;
1694
1695 };
1696
1704 {
1705 public:
1706 string get_name() const
1707 {
1708 return NAME;
1709 }
1710
1711 virtual EMData* process(const EMData * const image);
1712 void process_inplace( EMData * image);
1713
1715 {
1716 TypeDict d ;
1717 d.put("thr",EMObject::FLOAT,"Optional : Isosurface threshold value. Pixels below this will not be segment centers (default = 0.9)");
1718 d.put("minsegsep",EMObject::FLOAT,"Required: Minimum segment separation in pixels. Segments too close will trigger a reseed");
1719 d.put("maxsegsep",EMObject::FLOAT,"Required: Maximum segment separation in pixels. Segments too close will trigger a reseed");
1720 d.put("verbose",EMObject::INT,"Be verbose while running");
1721 return d;
1722 }
1723
1724 static Processor *NEW()
1725 {
1726 return new DistanceSegmentProcessor();
1727 }
1728
1729 string get_desc() const
1730 {
1731 return "Segments a volume into pieces separated by distances in the specified range.";
1732 }
1733
1734 static const string NAME;
1735
1736 };
1737
1745 {
1746 public:
1747 string get_name() const
1748 {
1749 return NAME;
1750 }
1751
1752 virtual EMData* process(const EMData * const image);
1753 void process_inplace( EMData * image);
1754
1756 {
1757 TypeDict d ;
1758 d.put("nseg", EMObject::INT, "Number of segments to divide the image into. default=12" );
1759 d.put("thr",EMObject::FLOAT,"Isosurface threshold value. Pixels below this will not be segmented");
1760 d.put("ampweight",EMObject::INT,"If set, will weight centers by voxel amplitude. default = 1");
1761 d.put("maxsegsize",EMObject::FLOAT,"Maximum radial distance from segment center to member voxel. Default=10000");
1762 d.put("minsegsep",EMObject::FLOAT,"Minimum segment separation. Segments too close will trigger a reseed");
1763 d.put("maxiter",EMObject::FLOAT,"Maximum number of iterations to run before stopping. Default=100");
1764 d.put("maxvoxmove",EMObject::FLOAT,"Maximum number of voxels that can move before quitting. Default=25");
1765 d.put("verbose",EMObject::INT,"Be verbose while running");
1771 d.put("pseudoatom",EMObject::BOOL,"Doing pseudoatom generation");
1772 d.put("sep",EMObject::FLOAT,"Separation distance, used only in pseudoatom generation. Default=3.78");
1773 return d;
1774 }
1775
1776 static Processor *NEW()
1777 {
1778 return new KmeansSegmentProcessor();
1779 }
1780
1781 string get_desc() const
1782 {
1783 return "Performs K-means segmentation on a volume. Note that this method uses random seeds, and thus will return different results each time it is run. Returned map contains number of segment for each voxel (or 0 for unsegmented voxels). Segmentation centers are stored in 'segmentcenters' attribute, consisting of a list of 3n floats in x,y,z triples.";
1784 }
1785
1786 static const string NAME;
1787
1788 };
1789
1790
1805 {
1806 public:
1807 string get_name() const
1808 {
1809 return NAME;
1810 }
1811
1812 virtual EMData* process(const EMData * const image);
1813
1814 void process_inplace(EMData *image);
1815
1817 {
1818 TypeDict d;
1819 d.put("purectf", EMObject::BOOL, "If set, replaces image with simulated CTF instead of multiplying image by CTF");
1820 d.put("defocus", EMObject::FLOAT, "Defocus in microns (underfocus positive)");
1821 d.put("ampcont", EMObject::FLOAT, "% amplitude contrast (0-100)");
1822 d.put("bfactor", EMObject::FLOAT, "B-factor in A^2, uses MRC convention rather than EMAN1 convention");
1823 d.put("noiseamp", EMObject::FLOAT, "Amplitude of the added empirical pink noise");
1824// d.put("noiseampwhite", EMObject::FLOAT, "Amplitude of added white noise");
1825 d.put("voltage", EMObject::FLOAT, "Microscope voltage in KV");
1826 d.put("cs", EMObject::FLOAT, "Cs of microscope in mm");
1827 d.put("apix", EMObject::FLOAT, "A/pix of data");
1828 d.put("phaseflip", EMObject::INT, "If not true, applies fabs(CTF). default true");
1829 d.put("bispectrumfp", EMObject::INT, "If set, the input must be the result of math.bispectrum.slice ffp= mode. Returns something comparable to fp=mode.");
1830 return d;
1831 }
1832
1833 static Processor *NEW()
1834 {
1835 return new CtfSimProcessor();
1836 }
1837
1838 string get_desc() const
1839 {
1840 return "Applies a simulated CTF with noise to an image. Astigmatism is always zero. The added noise is either white or based on an empirical curve generated from cryoEM data. ";
1841 }
1842
1843 static const string NAME;
1844
1845// protected:
1846 };
1847
1848
1856 {
1857 public:
1858 string get_name() const
1859 {
1860 return NAME;
1861 }
1862
1863 virtual EMData* process(const EMData * const image);
1864
1865 void process_inplace(EMData *image);
1866
1867 void set_params(const Dict & new_params)
1868 {
1869 params = new_params;
1870 ctf = params["ctf"];
1871// printf("%s %f\n",params.keys()[0].c_str(),lowpass);
1872 }
1873
1875 {
1876 TypeDict d;
1877 d.put("ctf", EMObject::EMDATA, "Ctf object to use for Wiener filter parameters");
1878 return d;
1879 }
1880
1881 static Processor *NEW()
1882 {
1883 return new Wiener2DFourierProcessor();
1884 }
1885
1886 string get_desc() const
1887 {
1888 return "Applies a 2-D Wiener filter to an image based on its Ctf parameters";
1889 }
1890
1891 static const string NAME;
1892
1893 protected:
1895 };
1896
1898 {
1899 public:
1900 virtual string get_name() const
1901 {
1902 return NAME;
1903 }
1904
1905 virtual string get_desc() const
1906 {
1907 return "";
1908 }
1909
1910 static Processor *NEW()
1911 {
1912 return new LinearRampFourierProcessor();
1913 }
1914
1915 static const string NAME;
1916
1917 protected:
1918 virtual void create_radial_func(vector < float >&radial_mask) const ;
1919 };
1920
1921
1925 {
1926 public:
1927 string get_name() const
1928 { return NAME; }
1929 static Processor *NEW() { return new LowpassRandomPhaseProcessor(); }
1930 string get_desc() const
1931 {
1932 return "Above the cutoff frequency, phases will be completely randomized, but amplitudes will be unchanged. Used for testing for noise bias. If you can reconstruct information that isn't there, then you have noise bias problems.";
1933 }
1934 void process_inplace(EMData * image);
1935 void create_radial_func(vector < float >&radial_mask) const;
1936
1937 static const string NAME;
1938 };
1939
1940
1944 {
1945 public:
1946 string get_name() const
1947 {
1948 return NAME;
1949 }
1950
1951 static Processor *NEW()
1952 {
1953 return new LowpassAutoBProcessor();
1954 }
1955
1956 string get_desc() const
1957 {
1958 return "This processor sharpens a map based on the concept that the power spectrum should be roughly flat over the ~15 A-Nyquist resolution range, then combines this inverse B-factor with the specified low-pass Gaussian filter parameters to produce a single aggregate Gaussian filter.";
1959 }
1960
1961 static const string NAME;
1962
1964 {
1966 d.put("bfactor", EMObject::FLOAT, "B-factor in terms of e^-(B s^2/4)");
1967 d.put("noisecutoff", EMObject::FLOAT, "Spatial frequency past which inverse-B will not be applied, default=1/6A");
1968// d.put("adaptnoise", EMObject::INT, "Dual linear fit separating lower resolution signal from higher resolution noise. Noise region not upweighted.");
1969 d.put("return_radial", EMObject::BOOL, "Return the radial filter function as an attribute (filter_curve)");
1970 d.put("verbose", EMObject::INT, "Print information about the determined B-factor");
1971 return d;
1972 }
1973
1974 protected:
1975 virtual void preprocess(EMData * image) {
1976 if(params.has_key("apix")) {
1977 image->set_attr("apix_x", (float)params["apix"]);
1978 image->set_attr("apix_y", (float)params["apix"]);
1979 image->set_attr("apix_z", (float)params["apix"]);
1980 }
1981 float apix=(float)image->get_attr("apix_x");
1982 params["bfactor"] = pow(apix/(float)params["cutoff_abs"],0.0f);
1983
1984 const Dict dict = image->get_attr_dict();
1985 if (params.has_key("cutoff_abs")) {
1986 params["bfactor"] = pow(apix/(float)params["cutoff_abs"],2.0f);
1987 }
1988 else if( params.has_key("cutoff_freq") ) {
1989 float val = (float)params["cutoff_freq"] * apix;
1990 params["cutoff_abs"] = val;
1991 params["bfactor"] = pow(apix/(float)params["cutoff_abs"],2.0f);
1992 }
1993 else if( params.has_key("cutoff_pixels") ) {
1994 float val = (float)params["cutoff_pixels"] / (float)dict["nx"];
1995 params["cutoff_abs"] = val;
1996 params["bfactor"] = pow(apix/(float)params["cutoff_abs"],2.0f);
1997 }
1998 }
1999
2000 void create_radial_func(vector < float >&radial_mask,EMData *image) const;
2001 };
2002
2006 {
2007 public:
2008 string get_name() const
2009 {
2010 return NAME;
2011 }
2012 static Processor *NEW()
2013 {
2014 return new HighpassAutoPeakProcessor();
2015 }
2016
2017 string get_desc() const
2018 {
2019 return "Attempts to automatically remove the low resolution peak present in virtually all cryoEM data.";
2020 }
2021
2022 static const string NAME;
2023
2024 protected:
2025 void create_radial_func(vector < float >&radial_mask, EMData *image) const;
2026 virtual void preprocess(EMData * image);
2028 };
2029
2035 {
2036 public:
2038 {
2039 }
2040
2041 string get_name() const
2042 {
2043 return NAME;
2044 }
2045 static Processor *NEW()
2046 {
2047 return new LinearRampProcessor();
2048 }
2049
2050 string get_desc() const
2051 {
2052 return "processor radial function: f(x) = slope * x + intercept;";
2053 }
2054
2055 void set_params(const Dict & new_params)
2056 {
2057 params = new_params;
2058 intercept = params["intercept"];
2059 slope = params["slope"];
2060 }
2061
2063 {
2064 TypeDict d;
2065 d.put("intercept", EMObject::FLOAT, "intercept in 'f(x) = slope * x + intercept'");
2066 d.put("slope", EMObject::FLOAT, "slope in 'f(x) = slope * x + intercept'");
2067 return d;
2068 }
2069
2070 static const string NAME;
2071
2072 protected:
2073 void create_radial_func(vector < float >&radial_mask) const;
2074
2075 private:
2077 float slope;
2078 };
2079
2084 {
2085 public:
2087 {
2088 }
2089
2090 string get_name() const
2091 {
2092 return NAME;
2093 }
2094 static Processor *NEW()
2095 {
2096 return new LoGFourierProcessor();
2097 }
2098
2099 string get_desc() const
2100 {
2101 return "processor radial function: f(x) = ((x^2 - s^2)/s^4)e^-(x^2/2s^2)";
2102 }
2103
2104 void set_params(const Dict & new_params)
2105 {
2106 params = new_params;
2107 sigma = params["sigma"];
2108 }
2109
2111 {
2112 TypeDict d;
2113 d.put("sigma", EMObject::FLOAT, "LoG sigma");
2114 return d;
2115 }
2116
2117 static const string NAME;
2118
2119 protected:
2120 void create_radial_func(vector < float >&radial_mask) const;
2121
2122 private:
2123 float sigma;
2124 };
2125
2131 {
2132 public:
2134 {
2135 }
2136
2137 string get_name() const
2138 {
2139 return NAME;
2140 }
2141 static Processor *NEW()
2142 {
2143 return new DoGFourierProcessor();
2144 }
2145
2146 string get_desc() const
2147 {
2148 return "processor radial function: f(x) = 1/sqrt(2*pi)*[1/sigma1*exp-(x^2/2*sigma1^2) - 1/sigma2*exp-(x^2/2*sigma2^2)]";
2149 }
2150
2151 void set_params(const Dict & new_params)
2152 {
2153 params = new_params;
2154 sigma1 = params["sigma1"];
2155 sigma2 = params["sigma2"];
2156 }
2157
2159 {
2160 TypeDict d;
2161 d.put("sigma1", EMObject::FLOAT, "DoG sigma1");
2162 d.put("sigma2", EMObject::FLOAT, "DoG sigma2");
2163 return d;
2164 }
2165
2166 static const string NAME;
2167
2168 protected:
2169 void create_radial_func(vector < float >&radial_mask) const;
2170
2171 private:
2172 float sigma1;
2173 float sigma2;
2174 };
2175
2179 {
2180 public:
2182 {
2183 }
2184 void process_inplace(EMData * image);
2185
2186 virtual void set_params(const Dict & new_params)
2187 {
2188 params = new_params;
2189 if (params.size() == 1) {
2190 vector < EMObject > dict_values = params.values();
2191 value = dict_values[0];
2192 }
2193 }
2194
2195 static string get_group_desc()
2196 {
2197 return "The base class for real space processor working on individual pixels. The processor won't consider the pixel's coordinates and neighbors.";
2198 }
2199
2200 protected:
2201 virtual void process_pixel(float *x) const = 0;
2202 virtual void calc_locals(EMData *)
2203 {
2204 }
2205 virtual void normalize(EMData *) const
2206 {
2207 }
2208
2209 float value;
2210 float maxval;
2211 float mean;
2212 float sigma;
2213 };
2214
2219 {
2220 public:
2221 string get_name() const
2222 {
2223 return NAME;
2224 }
2225 static Processor *NEW()
2226 {
2227 return new CCCSNRProcessor();
2228 }
2229
2231 {
2232 TypeDict d;
2233 d.put("wiener", EMObject::INT, "If set, returns Wiener image, default returns SNR");
2234 d.put("scalesnr", EMObject::FLOAT, "Scales SSNR by provided value prior to return or use in Wiener calculation. Default 2 (compensates for FSC on 1/2 volumes)");
2235 return d;
2236 }
2237
2238 string get_desc() const
2239 {
2240 return "Converts an image containing normalized CCC values to SNR or Wiener filter values. scalesnr defaults to 2, which\
2241 uses the SNR of the average of the two half-image volumes. ie - if scalesnr is 2: SNR = 2*FSC/(1-FSC)";
2242 }
2243
2244 void process_inplace(EMData * image);
2245
2246 static const string NAME;
2247
2248 };
2249
2250
2254 {
2255 public:
2256 string get_name() const
2257 {
2258 return NAME;
2259 }
2260 static Processor *NEW()
2261 {
2262 return new AbsoluteValueProcessor();
2263 }
2264
2265 static const string NAME;
2266
2267 protected:
2268 void process_pixel(float *x) const
2269 {
2270 *x = fabs(*x);
2271 }
2272
2273 string get_desc() const
2274 {
2275 return "f(x) = |x|";
2276 }
2277 };
2278
2282 {
2283 public:
2284 string get_name() const
2285 {
2286 return NAME;
2287 }
2288 static Processor *NEW()
2289 {
2290 return new FloorValueProcessor();
2291 }
2292
2293 static const string NAME;
2294
2295 protected:
2296 void process_pixel(float *x) const
2297 {
2298 *x = floor(*x);
2299 }
2300
2301 string get_desc() const
2302 {
2303 return "f(x) = floor(x)";
2304 }
2305 };
2306
2310 {
2311 public:
2312 string get_name() const
2313 {
2314 return NAME;
2315 }
2316 static Processor *NEW()
2317 {
2318 return new FixSignProcessor();
2319 }
2320
2321 static const string NAME;
2322
2323 void set_params(const Dict & new_params)
2324 {
2325 params = new_params;
2326 if (params.set_default("byte_stou",0)) mode=1;
2327 else if (params.set_default("byte_utos",1)) mode=2;
2328 else mode=0;
2329 }
2330
2332 {
2333 TypeDict d;
2334 d.put("byte_stou", EMObject::BOOL, "8 bit data signed read -> unsigned");
2335 d.put("byte_utos", EMObject::BOOL, "8 bit data unsigned read -> signed");
2336 return d;
2337 }
2338
2339 protected:
2340 void process_pixel(float *x) const
2341 {
2342 switch (mode) {
2343 case 1:
2344 if (*x<0) *x+=256;
2345 break;
2346 case 2:
2347 if (*x>127) *x-=256;
2348 break;
2349 }
2350
2351 }
2352
2353 string get_desc() const
2354 {
2355 return "Fixes errors with reading signed/unsigned data. Need to specify the correct mode.";
2356 }
2357
2358 int mode;
2359 };
2360
2361
2365 {
2366 public:
2367 string get_name() const
2368 {
2369 return NAME;
2370 }
2371 static Processor *NEW()
2372 {
2373 return new BooleanProcessor();
2374 }
2375
2376 string get_desc() const
2377 {
2378 return "f(x) = 0 if x = 0; f(x) = 1 if x != 0;";
2379 }
2380
2381 static const string NAME;
2382
2383 protected:
2384 void process_pixel(float *x) const
2385 {
2386 if (*x != 0)
2387 {
2388 *x = 1.0;
2389 }
2390 }
2391 };
2392
2397 {
2398 public:
2399 string get_name() const
2400 {
2401 return NAME;
2402 }
2403 static Processor *NEW()
2404 {
2405 return new RecipCarefullyProcessor();
2406 }
2407
2408 void set_params(const Dict & new_params)
2409 {
2410 params = new_params;
2411 zero_to = params.set_default("zero_to",0.0f);
2412 }
2413
2415 {
2416 TypeDict d;
2417 d.put("zero_to", EMObject::FLOAT, "Inverted zero values are set to this value, default is 0.");
2418 return d;
2419 }
2420
2421 string get_desc() const
2422 {
2423 return "if f(x) != 0: f(x) = 1/f(x) else: f(x) = zero_to";
2424 }
2425
2426 static const string NAME;
2427
2428 protected:
2429 void process_pixel(float *x) const
2430 {
2431 if (*x == 0.0) *x = zero_to;
2432 else *x = 1.0f/(*x);
2433 }
2434 private:
2435 float zero_to;
2436 };
2437
2442 {
2443 public:
2444 string get_name() const
2445 {
2446 return NAME;
2447 }
2448 static Processor *NEW()
2449 {
2450 return new ValuePowProcessor();
2451 }
2452
2453 void set_params(const Dict & new_params)
2454 {
2455 params = new_params;
2456 pwr = params["pow"];
2457 }
2458
2460 {
2461 TypeDict d;
2462 d.put("pow", EMObject::FLOAT, "Each pixel is raised to this power");
2463 return d;
2464 }
2465
2466 string get_desc() const
2467 {
2468 return "f(x) = x ^ pow;";
2469 }
2470
2471 static const string NAME;
2472
2473 protected:
2474 void process_pixel(float *x) const
2475 {
2476 if (*x<0 && pwr!=(int)pwr) *x=0;
2477 else (*x) = pow(*x,pwr);
2478 }
2479 private:
2480 float pwr;
2481 };
2482
2486 {
2487 public:
2488 string get_name() const
2489 {
2490 return NAME;
2491 }
2492 static Processor *NEW()
2493 {
2494 return new ValueSquaredProcessor();
2495 }
2496
2497
2498 string get_desc() const
2499 {
2500 return "f(x) = x * x;";
2501 }
2502
2503 static const string NAME;
2504
2505 protected:
2506 void process_pixel(float *x) const
2507 {
2508 (*x) *= (*x);
2509 }
2510 };
2511
2515 {
2516 public:
2517 string get_name() const
2518 {
2519 return NAME;
2520 }
2521 static Processor *NEW()
2522 {
2523 return new ValueSqrtProcessor();
2524 }
2525
2526 string get_desc() const
2527 {
2528 return "f(x) = sqrt(x)";
2529 }
2530
2531 static const string NAME;
2532
2533 protected:
2534 void process_pixel(float *x) const
2535 {
2536 *x = sqrt(*x);
2537 }
2538 };
2539
2540
2542 {
2543 public:
2544 string get_name() const
2545 {
2546 return NAME;
2547 }
2548 static Processor *NEW()
2549 {
2550 return new DiscritizeProcessor();
2551 }
2552
2553 void set_params(const Dict & new_params)
2554 {
2555 params = new_params;
2556 if (params.has_key("center")) center=params["center"];
2557 else center=0.0;
2558 if (params.has_key("step")) center=params["step"];
2559 else step=1.0;
2560 if (step<=0) step=1.0;
2561 }
2562
2564 {
2565 TypeDict d;
2566 d.put("center", EMObject::FLOAT, "Center value from which number of standard deviations is computed (default = 0)");
2567 d.put("step", EMObject::FLOAT, "Stepsize in terms of sigma. ie - 1.5 will discritize to 1.5*sigma steps (default = 1.0)");
2568 return d;
2569 }
2570
2571 string get_desc() const
2572 {
2573 return "Converts each pixel value to the integral number of standard deviations from the specified center. Rounds to the nearest integer, -0.5*sigma<x<0.5*sigma -> 0.0 ";
2574 }
2575
2576 static const string NAME;
2577
2578 protected:
2580
2581 void process_pixel(float *x) const
2582 {
2583 *x = Util::fast_floor((*x-center)/(step*sigma)+0.5)*step;
2584 }
2585 };
2586
2591 {
2592 public:
2593 string get_name() const
2594 {
2595 return NAME;
2596 }
2597 static Processor *NEW()
2598 {
2599 return new ToZeroProcessor();
2600 }
2602 {
2603 TypeDict d;
2604 d.put("minval", EMObject::FLOAT, "Everything below this value is set to zero");
2605 return d;
2606 }
2607
2608 string get_desc() const
2609 {
2610 return "f(x) = x if x >= minval; f(x) = 0 if x < minval.";
2611 }
2612
2613 static const string NAME;
2614
2615 protected:
2616 inline void process_pixel(float *x) const
2617 {
2618 if (*x < value) {
2619 *x = 0;
2620 }
2621 }
2622 };
2623
2628 {
2629 public:
2630 string get_name() const
2631 {
2632 return NAME;
2633 }
2634 static Processor *NEW()
2635 {
2636 return new AboveToZeroProcessor();
2637 }
2639 {
2640 TypeDict d;
2641 d.put("maxval", EMObject::FLOAT, "Everything above this value is set to zero");
2642 return d;
2643 }
2644
2645 string get_desc() const
2646 {
2647 return "f(x) = x if x <= maxval; f(x) = 0 if x > maxval.";
2648 }
2649
2650 static const string NAME;
2651
2652 protected:
2653 inline void process_pixel(float *x) const
2654 {
2655 if (*x > value) {
2656 *x = 0;
2657 }
2658 }
2659 };
2660
2666 {
2667 public:
2669 {
2670 }
2671
2672 string get_name() const
2673 {
2674 return NAME;
2675 }
2676
2677 static Processor *NEW()
2678 {
2679 return new RangeZeroProcessor();
2680 }
2681
2682 virtual void process_inplace(EMData * image);
2683
2684
2686 {
2687 TypeDict d;
2688 d.put("minval", EMObject::FLOAT, "Lower threshold (required)");
2689 d.put("maxval", EMObject::FLOAT, "Upper threshold (required)");
2690 d.put("gauss_width", EMObject::FLOAT, "Range will be narrowed around zero based on a radial Gaussian falloff modeled on math.gausskernelfix. Disabled if set to 0.");
2691 return d;
2692 }
2693
2694 void set_params(const Dict & new_params)
2695 {
2696 params = new_params;
2697 minval = params["minval"]; // using existing variable as a convenience
2698 maxval = params["maxval"];
2699 }
2700
2701 string get_desc() const
2702 {
2703 return "Sets values in a range to zero. Opposite of threshold.clampminmax. \nf(x) = x if x > maxval or x < minval; f(x) = 0 for min <= x <= max. If gauss_width set nozero, applies a radial correction factor to both min and max.";
2704 }
2705
2706 static const string NAME;
2707
2708 protected:
2710 };
2711
2717 {
2718 public:
2719 string get_name() const
2720 {
2721 return NAME;
2722 }
2723
2724 static Processor *NEW()
2725 {
2726 return new AddShapeProcessor();
2727 }
2728
2730
2732 {
2733 TypeDict d;
2734 d.put("shape", EMObject::STRING, "Name of the shape to add (");
2735 d.put("x", EMObject::FLOAT, "X coordinate of object center");
2736 d.put("y", EMObject::FLOAT, "Y coordinate of object center");
2737 d.put("z", EMObject::FLOAT, "Z coordinate of object center");
2738 d.put("size1", EMObject::FLOAT, "Size of the object. Meaning varies by shape.");
2739 d.put("size2", EMObject::FLOAT, "2nd axis size of the object. Meaning varies by shape.");
2740 d.put("size3", EMObject::FLOAT, "3rd axis size of the object. Meaning varies by shape.");
2741 d.put("val1", EMObject::FLOAT, "First pixel value. Meaning varies by shape.");
2742 d.put("val2", EMObject::FLOAT, "2nd pixel value. Meaning varies with shape");
2743
2744 return d;
2745 }
2746
2747 string get_desc() const
2748 {
2749 return "Adds a specified shape to a volume.";
2750 }
2751
2752 static const string NAME;
2753 };
2754
2756 {
2757 public:
2758 string get_name() const
2759 {
2760 return NAME;
2761 }
2762 static Processor *NEW()
2763 {
2764 return new SetBitsProcessor();
2765 }
2766
2767 void process_inplace(EMData *image);
2768
2770 {
2771 TypeDict d;
2772 d.put("bits", EMObject::INT, "Number of bits to retain (default 5)");
2773 d.put("nsigma", EMObject::FLOAT, "Number of standard deviations to include in the n bit mapping. eg - max=min(mean+nsigma*sigma,max)");
2774 d.put("floatbits", EMObject::INT, "If set to a >0 number, alters the algorithm, so the specified number of significant floating point bits is retained. The floating point exponent is not modified. This will produce less compressible data, but the values will be less perturbed.");
2775 return d;
2776 }
2777
2778 string get_desc() const
2779 {
2780 return "Converts each pixel value to an integer using the specified number of total bits. This will make the data more compressible, and allows you to handle conversion to integer data modes.\
2781The data itself will remain stored in single precision floating point format, so using >23 bits would be a bad idea.";
2782 }
2783
2784 static const string NAME;
2785
2786 };
2787
2788
2795 {
2796 public:
2797 string get_name() const
2798 {
2799 return NAME;
2800 }
2801 static Processor *NEW()
2802 {
2803 return new Rotate180Processor();
2804 }
2805
2809 void process_inplace(EMData* image);
2810
2811 string get_desc() const
2812 {
2813 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.";
2814 }
2815
2816 static const string NAME;
2817 };
2818
2826 {
2827 public:
2828 virtual string get_name() const
2829 {
2830 return NAME;
2831 }
2832 static Processor *NEW()
2833 {
2834 return new TransformProcessor();
2835 }
2836
2841 virtual void process_inplace(EMData* image);
2842
2847 virtual EMData* process(const EMData* const image);
2848
2850 {
2851 TypeDict d;
2852 d.put("transform", EMObject::TRANSFORM, "The Transform object that will be applied to the image" );
2853 d.put("alpha", EMObject::FLOAT, "2-D alpha angle" );
2854 d.put("az", EMObject::FLOAT, "3-D Azimuth" );
2855 d.put("alt", EMObject::FLOAT, "3-D Altitude" );
2856 d.put("phi", EMObject::FLOAT, "3-D Phi" );
2857 d.put("tx", EMObject::FLOAT, "x translation" );
2858 d.put("ty", EMObject::FLOAT, "y translation" );
2859 d.put("tz", EMObject::FLOAT, "y translation" );
2860 d.put("zerocorners",EMObject::INT,"If set, corners (anything beyond radius/2-1) may be zeroed out in real or Fourier space. This will produce a considerable speedup in Fourier rotations. ");
2861 return d;
2862 }
2863
2864 virtual string get_desc() const
2865 {
2866 return "The image is transformed using transform parameter, or alternatively specific numbers alpha,tx,ty or az,alt,phi,tx,ty,tz (shortcut for convenience)";
2867 }
2868
2869 static const string NAME;
2870
2871 float* transform(const EMData* const image, const Transform& t) const;
2872 private:
2873 // This function became redundant if favor of EMData::scale_pixel
2874 //void update_emdata_attributes(EMData* const image, const Dict& attr_dict, const float& scale) const;
2875
2876
2877 void assert_valid_aspect(const EMData* const image) const;
2878 };
2879
2888 {
2889 public:
2890 virtual string get_name() const
2891 {
2892 return NAME;
2893 }
2894
2895 static Processor *NEW()
2896 {
2897 return new IntTranslateProcessor();
2898 }
2899
2904 virtual void process_inplace(EMData* image);
2905
2910 virtual EMData* process(const EMData* const image);
2911
2913 {
2914 TypeDict d;
2915 d.put("trans", EMObject::INTARRAY, "The displacement array, can be length 1-3" );
2916 return d;
2917 }
2918
2919 virtual string get_desc() const
2920 {
2921 return "The image is translated an integer amount";
2922 }
2923
2924 static const string NAME;
2925
2926 private:
2930 void assert_valid_aspect(const vector<int>& translation, const EMData* const image) const;
2931
2937 Region get_clip_region(vector<int>& translation, const EMData* const image) const;
2938 };
2939
2946 {
2947 public:
2948 virtual string get_name() const
2949 {
2950 return NAME;
2951 }
2952
2953 static Processor *NEW()
2954 {
2955 return new ApplySymProcessor();
2956 }
2957
2958 virtual void process_inplace(EMData* image);
2959
2960 virtual EMData* process(const EMData* const image);
2961
2963 {
2964 TypeDict d;
2965 d.put("sym", EMObject::STRING, "The symmetry under which to do the alignment, Default=c1" );
2966 d.put("averager", EMObject::STRING, "Name of an Averager to use. default=mean" );
2967 return d;
2968 }
2969
2970 virtual string get_desc() const
2971 {
2972 return "Symmetry is imposed on a 2-D image (Cn only) or 3-D volume";
2973 }
2974
2975 static const string NAME;
2976
2977 };
2978
2986 {
2987 public:
2988 virtual string get_name() const
2989 {
2990 return NAME;
2991 }
2992 static Processor *NEW()
2993 {
2994 return new ScaleTransformProcessor();
2995 }
3000 virtual void process_inplace(EMData* image);
3001
3006 virtual EMData* process(const EMData* const image);
3007
3009 {
3010 TypeDict d;
3011 d.put("scale", EMObject::FLOAT, "The amount by which to scale" );
3012 d.put("clip", EMObject::INT, "The length of each output dimension. Non sophisticated, output dimensions can't be different" );
3015 return d;
3016 }
3017
3018 virtual string get_desc() const
3019 {
3020 return "The image is scaled with the clip variable in mind, being sure to preserve as much pixel information as possible.";
3021 }
3022
3023 static const string NAME;
3024 };
3025
3033 {
3034 public:
3036
3037 string get_name() const
3038 {
3039 return NAME;
3040 }
3041 static Processor *NEW()
3042 {
3043 return new ClampingProcessor();
3044 }
3045
3046 void process_inplace(EMData *image);
3047
3049 {
3050 TypeDict d;
3051 d.put("minval", EMObject::FLOAT, "The pixel values that bounds the smallest pixel value in the output image" );
3052 d.put("maxval", EMObject::FLOAT, "The pixel values that bounds the largest pixel value in the output image" );
3053 d.put("tomean", EMObject::BOOL, "Replace outlying pixels values with the mean pixel value instead" );
3054 d.put("tozero", EMObject::BOOL, "Replace outlying pixels values with zero" );
3055 return d;
3056 }
3057
3058 string get_desc() const
3059 {
3060 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.";
3061 }
3062
3063 static const string NAME;
3064
3065 protected:
3067 };
3068
3075 {
3076 public:
3078
3079 string get_name() const
3080 {
3081 return NAME;
3082 }
3083
3084 static Processor *NEW()
3085 {
3086 return new NSigmaClampingProcessor();
3087 }
3088
3090 {
3091 TypeDict d;
3092 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" );
3093 d.put("tomean", EMObject::BOOL, "Replace outlying pixels values with the mean pixel value instead" );
3094 d.put("tozero", EMObject::BOOL, "Replace outlying pixels values with zero" );
3095 return d;
3096 }
3097
3098 void process_inplace(EMData *image);
3099
3100 string get_desc() const
3101 {
3102 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.";
3103 }
3104
3105 static const string NAME;
3106
3107 protected:
3109 };
3110
3115 {
3116 public:
3117 string get_name() const
3118 {
3119 return NAME;
3120 }
3121 static Processor *NEW()
3122 {
3123 return new ToMinvalProcessor();
3124 }
3125
3126 void process_inplace(EMData *image);
3127
3129 {
3130 TypeDict d;
3131 d.put("minval", EMObject::FLOAT, "Everything below this value is set to this value");
3132 d.put("newval", EMObject::FLOAT, "If set, values below minval will be set to newval instead of minval ");
3133 return d;
3134 }
3135
3136 string get_desc() const
3137 {
3138 return "f(x) = x if x >= minval; f(x) = minval|newval if x < minval.";
3139 }
3140
3141 static const string NAME;
3142
3143 protected:
3144
3145 };
3146
3147
3148
3153 {
3154 public:
3155 string get_name() const
3156 {
3157 return NAME;
3158 }
3159 static Processor *NEW()
3160 {
3161 return new CutToZeroProcessor();
3162 }
3164 {
3165 TypeDict d;
3166 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" );
3167 return d;
3168 }
3169
3170 string get_desc() const
3171 {
3172 return "f(x) = x-minval if x >= minval; f(x) = 0 if x < minval.";
3173 }
3174
3175 static const string NAME;
3176
3177 protected:
3178 void process_pixel(float *x) const
3179 {
3180 *x = *x - value;
3181 if (*x < 0) {
3182 *x = 0;
3183 }
3184 }
3185 };
3186
3191 {
3192 public:
3193 string get_name() const
3194 {
3195 return NAME;
3196 }
3197 static Processor *NEW()
3198 {
3199 return new BinarizeProcessor();
3200 }
3202 {
3203 TypeDict d;
3204 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" );
3205 return d;
3206 }
3207
3208 string get_desc() const
3209 {
3210 return "f(x) = 0 if x < value; f(x) = 1 if x >= value.";
3211 }
3212
3213 static const string NAME;
3214
3215 protected:
3216 void process_pixel(float *x) const
3217 {
3218 if (*x < value)
3219 {
3220 *x = 0;
3221 }
3222 else
3223 {
3224 *x = 1;
3225 }
3226 }
3227 };
3228
3237 {
3238 public:
3239 virtual string get_name() const
3240 {
3241 return NAME;
3242 }
3243 static Processor *NEW()
3244 {
3245 return new BinarizeFourierProcessor();
3246 }
3247
3252 virtual void process_inplace(EMData* image);
3253
3255 {
3256 TypeDict d;
3257 d.put("value", EMObject::FLOAT, "The Fourier amplitude threshold cutoff" );
3258 return d;
3259 }
3260
3261 virtual string get_desc() const
3262 {
3263 return "f(k) = 0 + 0i if ||f(k)|| < value; f(k) = a + bi if ||f(k)|| >= value.";
3264 }
3265
3266 static const string NAME;
3267 };
3268
3274 {
3275 public:
3276 string get_name() const
3277 {
3278 return NAME;
3279 }
3280 static Processor *NEW()
3281 {
3282 return new CollapseProcessor();
3283 }
3284
3285 void set_params(const Dict & new_params)
3286 {
3287 params = new_params;
3288 range = params["range"];
3289 value = params["value"];
3290 }
3291
3293 {
3294 TypeDict d;
3295 d.put("range", EMObject::FLOAT, "The range about 'value' which will be collapsed to 'value'");
3296 d.put("value", EMObject::FLOAT, "The pixel value where the focus of the collapse operation is");
3297 d.put("clamponly", EMObject::BOOL, "Leaves values outside the collapse range at their original value, setting pixels in the range to 'value'");
3298 return d;
3299 }
3300
3301 string get_desc() const
3302 {
3303 return "f(x): if v-r<x<v+r -> v; if x>v+r -> x-r; if x<v-r -> x+r";
3304 }
3305
3306 static const string NAME;
3307
3308 protected:
3309 void process_pixel(float *x) const
3310 {
3311 if (*x>value+range) *x-=range;
3312 else if (*x<value-range) *x+=range;
3313 else *x=value;
3314 }
3315 float range;
3316 };
3317
3323 {
3324 public:
3326 {
3327 }
3328
3329 string get_name() const
3330 {
3331 return NAME;
3332 }
3333 static Processor *NEW()
3334 {
3335 return new LinearXformProcessor();
3336 }
3337
3338 void set_params(const Dict & new_params)
3339 {
3340 params = new_params;
3341 shift = params.get("shift");
3342 scale = params.get("scale");
3343 }
3344
3346 {
3347 TypeDict d;
3348 d.put("shift", EMObject::FLOAT, "The amount to shift pixel values by after scaling");
3349 d.put("scale", EMObject::FLOAT, "The scaling factor to be applied to pixel values");
3350 return d;
3351 }
3352
3353 string get_desc() const
3354 {
3355 return "linear transform processor: f(x) = x * scale + shift. This is equivalent to a regular contrast stretching operation";
3356 }
3357
3358 static const string NAME;
3359
3360 protected:
3361 void process_pixel(float *x) const
3362 {
3363 *x = (*x) * scale + shift;
3364 }
3365
3366 private:
3367 float shift;
3368 float scale;
3369 };
3370
3376 {
3377 public:
3379 {
3380 }
3381
3382 string get_name() const
3383 {
3384 return NAME;
3385 }
3386
3387 static Processor *NEW()
3388 {
3389 return new ExpProcessor();
3390 }
3391
3392 void set_params(const Dict & new_params)
3393 {
3394 params = new_params;
3395 low = params.set_default("low",1.0f);
3396 high = params.set_default("high",0.0f);
3397 }
3398
3400 {
3401 TypeDict d;
3402 d.put("low", EMObject::FLOAT, "Pixels are divided by low then high is subtracted prior to the exponential operation, default 1.0");
3403 d.put("high", EMObject::FLOAT, "Pixels are divided by low then high is subtracted prior to the exponential operation, default 0.0");
3404 return d;
3405 }
3406
3407 string get_desc() const
3408 {
3409 return "f(x) = exp( x / low - high)";
3410 }
3411
3412 static const string NAME;
3413
3414 protected:
3418 void process_pixel(float *x) const
3419 {
3420 float v = *x / low - high;
3421 if (v > 40) {
3422 v = 40;
3423 }
3424 *x = exp(v);
3425 }
3426
3427 private:
3428 float low;
3429 float high;
3430 };
3431
3436 {
3437 public:
3439 {
3440 }
3441
3442 string get_name() const
3443 {
3444 return NAME;
3445 }
3446
3447 static Processor *NEW()
3448 {
3449 return new FiniteProcessor();
3450 }
3451
3452 void set_params(const Dict & new_params)
3453 {
3454 if (new_params.has_key("to") )
3455 to = params["to"];
3456 }
3457
3459 {
3460 TypeDict d;
3461 d.put("to", EMObject::FLOAT, "Pixels which are not finite will be set to this value");
3462 return d;
3463 }
3464
3465 string get_desc() const
3466 {
3467 return "f(x) = f(x) if f(x) is finite | to if f(x) is not finite";
3468 }
3469
3470 static const string NAME;
3471
3472 protected:
3476 void process_pixel(float *x) const;
3477 private:
3478 float to;
3479 };
3480
3486 {
3487 public:
3489 {
3490 }
3491
3492 string get_name() const
3493 {
3494 return NAME;
3495 }
3496 static Processor *NEW()
3497 {
3498 return new RangeThresholdProcessor();
3499 }
3500
3501 void set_params(const Dict & new_params)
3502 {
3503 params = new_params;
3504 low = params.get("low");
3505 high = params.get("high");
3506 }
3507
3509 {
3510 TypeDict d;
3511 d.put("low", EMObject::FLOAT, "The lower limit of the range that will be set to 1");
3512 d.put("high", EMObject::FLOAT, "The upper limit of the range that will be set to 1");
3513 return d;
3514 }
3515
3516 string get_desc() const
3517 {
3518 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";
3519 }
3520
3521 static const string NAME;
3522
3523 protected:
3524 void process_pixel(float *x) const
3525 {
3526 if (*x >= low && *x <= high) {
3527 *x = 1;
3528 }
3529 else {
3530 *x = 0;
3531 }
3532 }
3533 private:
3534 float low;
3535 float high;
3536
3537 };
3538
3544 {
3545 public:
3546 string get_name() const
3547 {
3548 return NAME;
3549 }
3550 static Processor *NEW()
3551 {
3552 return new SigmaProcessor();
3553 }
3554
3555 void set_params(const Dict & new_params)
3556 {
3557 params = new_params;
3558 value1 = params.get("value1");
3559 value2 = params.get("value2");
3560 }
3561
3563 {
3564 TypeDict d;
3565 d.put("value1", EMObject::FLOAT, "A number reflecting total standard deviations in the right direction");
3566 d.put("value2", EMObject::FLOAT, "A number reflecting total standard deviations in the left direction");
3567 return d;
3568 }
3569
3570 string get_desc() const
3571 {
3572 return "f(x) = mean if x<(mean-v2*sigma) or x>(mean+v1*sigma); else f(x) = x;";
3573 }
3574
3575 static const string NAME;
3576
3577 protected:
3578 void process_pixel(float *x) const
3579 {
3580 if (*x < (mean - value2 * sigma) || *x > (mean + value1 * sigma))
3581 {
3582 *x = mean;
3583 }
3584 }
3585
3586 private:
3587 float value1;
3588 float value2;
3589 };
3590
3594 {
3595 public:
3596 string get_name() const
3597 {
3598 return NAME;
3599 }
3600 static Processor *NEW()
3601 {
3602 return new LogProcessor();
3603 }
3604
3605 string get_desc() const
3606 {
3607 return "f(x) = log10(x) if x > 0; else f(x) = 0;";
3608 }
3609
3610 static const string NAME;
3611
3612 protected:
3613 void process_pixel(float *x) const
3614 {
3615 if (*x > 0)
3616 {
3617 *x = log10(*x);
3618 }
3619 else
3620 {
3621 *x = 0;
3622 }
3623 }
3624 };
3625
3629 {
3630 public:
3631 CoordinateProcessor():nx(0), ny(0), nz(0), mean(0), sigma(0), maxval(0), is_complex(false)
3632 {
3633 }
3634 void process_inplace(EMData * image);
3635
3636 static string get_group_desc()
3637 {
3638 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().";
3639 }
3640
3641 protected:
3642 virtual void process_pixel(float *pixel, int xi, int yi, int zi) const = 0;
3643 virtual void calc_locals(EMData *)
3644 {
3645 }
3646 virtual bool is_valid() const
3647 {
3648 return true;
3649 }
3650
3651 int nx;
3652 int ny;
3653 int nz;
3654 float mean;
3655 float sigma;
3656 float maxval;
3657
3659 };
3660
3668 {
3669 public:
3670
3671 void process_inplace(EMData * image);
3672
3673 static Processor *NEW()
3674 {
3675 return new MaskAzProcessor();
3676 }
3677
3678 string get_name() const
3679 {
3680 return NAME;
3681 }
3682
3683 static const string NAME;
3684
3685 string get_desc() const
3686 {
3687 return "Masks out an angular arc in circular/cylindrical coordinates with a sharp edge.";
3688 }
3689
3691 {
3692 TypeDict d;
3693
3694 d.put("phicen", EMObject::FLOAT,"Angle in degrees ccw from the x-axis. Center of the region to NOT set to zero.");
3695 d.put("phirange", EMObject::FLOAT,"Angle in degrees. Region phicen+-phirange will not be zeroed");
3696 d.put("phitrirange", EMObject::FLOAT,"Angle in degrees. With phitriangle, width outside phirange to fall from 1 to 0.");
3697 d.put("phitriangle", EMObject::BOOL, "If set mask will fall from 1 at phicen+-phirange to 0 at +-phitrirange");
3698 d.put("cx", EMObject::FLOAT,"Mask X center. Default nx/2");
3699 d.put("cy", EMObject::FLOAT,"Mask Y center. Default ny/2");
3700 d.put("zmin", EMObject::FLOAT,"Minimum Z to include");
3701 d.put("zmax", EMObject::FLOAT,"Maximum Z to include");
3702 d.put("ztriangle", EMObject::FLOAT,"1/2 width in pixels of linear falloff in Z margin. Centered on specified zmin/zmax.");
3703 d.put("inner_radius", EMObject::INT, "inner mask radius. optional. Default 0");
3704 d.put("outer_radius", EMObject::INT, "outer mask radius. optional. Default nx+ny. Negative value -> box radius + outer_radius +1");
3705
3706 return d;
3707 }
3708 protected:
3709
3710
3711 };
3712
3721 {
3722 public:
3724 outer_radius_square(0), dx(0), dy(0), dz(0), xc(0), yc(0), zc(0)
3725 {
3726 }
3727
3728 void set_params(const Dict & new_params)
3729 {
3730 params = new_params;
3731
3732 if (params.has_key("inner_radius")) {
3733 inner_radius = params["inner_radius"];
3735 }
3736 else {
3737 inner_radius = -1;
3739 }
3740
3741 if (params.has_key("outer_radius")) {
3742 outer_radius = params["outer_radius"];
3744 }
3745 else {
3746 outer_radius = INT_MAX;
3747 outer_radius_square = INT_MAX;
3748 }
3749
3750 if (params.has_key("dx")) dx = params["dx"];
3751 if (params.has_key("dy")) dy = params["dy"];
3752 if (params.has_key("dz")) dz = params["dz"];
3753 }
3754
3755 string get_desc() const
3756 {
3757 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().";
3758 }
3759
3761 {
3762 TypeDict d;
3763
3764 d.put("inner_radius", EMObject::FLOAT, "inner mask radius. optional");
3765 d.put("outer_radius", EMObject::FLOAT, "outer mask radius. Negative value -> box radius + outer_radius +1");
3766
3767 d.put("dx", EMObject::FLOAT,
3768 "Modify mask center by dx relative to the default center nx/2");
3769 d.put("dy", EMObject::FLOAT,
3770 "Modify mask center by dy relative to the default center ny/2");
3771 d.put("dz", EMObject::FLOAT,
3772 "Modify mask center by dz relative to the default center nz/2");
3773
3774 return d;
3775 }
3776 protected:
3777 void calc_locals(EMData * image);
3778
3779 bool is_valid() const
3780 {
3781 return (!is_complex);
3782 }
3783
3784 void process_pixel(float *pixel, int xi, int yi, int zi) const
3785 {
3786 float dist = (xi - xc) * (xi - xc) + (yi - yc) * (yi - yc) + (zi - zc) * (zi - zc);
3787 process_dist_pixel(pixel, dist);
3788 }
3789
3790 virtual void process_dist_pixel(float *pixel, float dist) const = 0; // note that this function gets the distance SQUARED !
3791
3796 float dx, dy, dz;
3797 float xc, yc, zc;
3798 };
3799
3804 {
3805 public:
3807 {
3808 }
3809
3810 string get_name() const
3811 {
3812 return NAME;
3813 }
3814 static Processor *NEW()
3815 {
3816 return new MaskSharpProcessor();
3817 }
3818
3819 void set_params(const Dict & new_params)
3820 {
3822 value = params.set_default("value",0.0f);
3823 }
3824
3826 {
3828 d.put("value", EMObject::FLOAT, "step cutoff to this value. Default is 0.");
3829 return d;
3830 }
3831
3832 string get_desc() const
3833 {
3834 return "step cutoff to a user-given value in both inner and outer circles.";
3835 }
3836
3837 static const string NAME;
3838
3839 protected:
3840 void process_dist_pixel(float *pixel, float dist) const
3841 {
3842 if (dist >= outer_radius_square || dist < inner_radius_square)
3843 {
3844 *pixel = value;
3845 }
3846 }
3847
3848 float value;
3849 };
3850
3855 {
3856 public:
3858 {
3859 }
3860
3861 string get_name() const
3862 {
3863 return NAME;
3864 }
3865 static Processor *NEW()
3866 {
3867 return new MaskSoftProcessor();
3868 }
3869
3870 void set_params(const Dict & new_params)
3871 {
3873 value = params.set_default("value",0.0f);
3874 width = params.set_default("width",4.0f);
3875 }
3876
3878 {
3880 d.put("value", EMObject::FLOAT, "cutoff to this value. default=0");
3881 d.put("width", EMObject::FLOAT, "1/e width of Gaussian falloff (both inner and outer) in pixels. default=4");
3882 return d;
3883 }
3884
3885 string get_desc() const
3886 {
3887 return "Outer (optionally also inner) mask to a user-provided value with a soft Gaussian edge.";
3888 }
3889
3890 static const string NAME;
3891
3892 protected:
3893 void process_dist_pixel(float *pixel, float dist) const
3894 {
3895 if (dist>=inner_radius_square && dist<=outer_radius_square) return;
3896
3897 if (dist<inner_radius_square) *pixel=value+(*pixel-value)*exp(-pow((inner_radius-sqrt(dist))/width,2.0f));
3898 else *pixel=value+(*pixel-value)*exp(-pow((sqrt(dist)-outer_radius)/width,2.0f));
3899 }
3900
3902 };
3903
3908 { // 6
3909 public:
3910 string get_name() const
3911 {
3912 return NAME;
3913 }
3914 static Processor *NEW()
3915 {
3916 return new MaskEdgeMeanProcessor();
3917 }
3918
3919 void set_params(const Dict & new_params)
3920 {
3922 ring_width = params["ring_width"];
3923 if (ring_width == 0) {
3924 ring_width = 1;
3925 }
3926 }
3927
3929 {
3931 d.put("ring_width", EMObject::INT, "The width of the mask ring.");
3932 return d;
3933 }
3934
3935 string get_desc() const
3936 {
3937 return "A step cutoff to the the mean value in a ring centered on the outer radius";
3938 }
3939
3940 static const string NAME;
3941
3942 protected:
3943 void calc_locals(EMData * image);
3944
3945
3946 void process_dist_pixel(float *pixel, float dist) const
3947 {
3948 if (dist >= outer_radius_square || dist < inner_radius_square){
3949 *pixel = ring_avg;
3950 }
3951 }
3952
3953 private:
3956 };
3957
3961 {
3962 public:
3963 string get_name() const
3964 {
3965 return NAME;
3966 }
3967 static Processor *NEW()
3968 {
3969 return new MaskNoiseProcessor();
3970 }
3971
3972 string get_desc() const
3973 {
3974 return "fills masked region";
3975 }
3976
3977 static const string NAME;
3978
3979 protected:
3980 void process_dist_pixel(float *pixel, float dist) const
3981 {
3982 if (dist >= outer_radius_square || dist < inner_radius_square)
3983 {
3984 *pixel = Util::get_gauss_rand(mean, sigma);
3985 }
3986 }
3987 };
3988
3992 {
3993 public:
3994 string get_name() const
3995 {
3996 return NAME;
3997 }
3998 static Processor *NEW()
3999 {
4000 return new MaskGaussProcessor();
4001 }
4002
4003 void set_params(const Dict & new_params)
4004 {
4006 exponent = params["exponent"];
4007 if (exponent <= 0.0) {
4008 exponent = 2.0;
4009 }
4010 }
4011
4013 {
4015 d.put("exponent", EMObject::FLOAT, "The exponent, f in e^-Bs^f. default 2.0, producing a Gaussian");
4016 return d;
4017 }
4018
4019 string get_desc() const
4020 {
4021 return "a gaussian falloff to zero, radius is the 1/e of the width. If inner_radius>0, then \
4022outer radius specifies width of Gaussian starting at inner_radius rather than total radius.";
4023 }
4024
4025 static const string NAME;
4026
4027 protected:
4029 void process_dist_pixel(float *pixel, float dist) const
4030 {
4031 if (inner_radius_square>0) {
4032 if (dist>inner_radius_square) {
4033 if (exponent==2.0f) (*pixel) *= exp(-pow(sqrt(dist)-inner_radius,2.0f) / outer_radius_square);
4034 else (*pixel) *= exp(-pow(sqrt(dist)-inner_radius,exponent) / pow((float)outer_radius_square,exponent/2.0f));
4035 }
4036 }
4037 else {
4038 if (exponent==2.0f) (*pixel) *= exp(-dist / outer_radius_square);
4039 else (*pixel) *= exp(-pow(dist,exponent/2.0f) / pow((float)outer_radius_square,exponent/2.0f));
4040 }
4041 }
4042 };
4043
4051 {
4052 public:
4054 {
4055 }
4056
4057 void set_params(const Dict & new_params)
4058 {
4059 params = new_params;
4060
4061 if (params.has_key("radius_x")) radius_x=params["radius_x"];
4062 else radius_x=5.0;
4063
4064 if (params.has_key("radius_y")) radius_y=params["radius_y"];
4065 else radius_y=5.0;
4066
4067 if (params.has_key("radius_z")) radius_z=params["radius_z"];
4068 else radius_z=5.0;
4069
4070 dx=dy=dz=0.0;
4071 if (params.has_key("dx")) dx=params["dx"];
4072 if (params.has_key("dy")) dy=params["dy"];
4073 if (params.has_key("dz")) dz=params["dz"];
4074
4075 if (params.has_key("gauss_width")) gauss_width=params["gauss_width"];
4076 else gauss_width=0.05f;
4077 }
4078
4080 {
4081 TypeDict d;
4082
4083 d.put("radius_x", EMObject::INT, "x-axis radius");
4084 d.put("radius_y", EMObject::INT, "y-axis radius");
4085 d.put("radius_z", EMObject::INT, "z-axis radius");
4086 d.put("gauss_width", EMObject::FLOAT, "Gaussian falloff width, relative to each radius, default 0.05");
4087
4088 d.put("dx", EMObject::FLOAT,
4089 "Modify mask center by dx relative to the default center nx/2");
4090 d.put("dy", EMObject::FLOAT,
4091 "Modify mask center by dy relative to the default center ny/2");
4092 d.put("dz", EMObject::FLOAT,
4093 "Modify mask center by dz relative to the default center nz/2");
4094
4095
4096 return d;
4097 }
4098
4099 string get_name() const
4100 {
4101 return NAME;
4102 }
4103 static Processor *NEW()
4104 {
4105 return new MaskGaussNonuniformProcessor();
4106 }
4107
4108 string get_desc() const
4109 {
4110 return "A Gaussian falloff to zero. Anisotropic, specify inner radius for x,y,z and Gaussian falloff width. Falloff \
4111width is also anisotropic and relative to the radii, with 1 being equal to the radius on that axis.";
4112 }
4113
4114 static const string NAME;
4115
4116 protected:
4117 void process_pixel(float *pixel, int xi, int yi, int zi) const
4118 {
4119 float dist = pow((xi - (nx/2+dx))/radius_x,2.0f) + pow((yi - (ny/2+dy))/radius_y,2.0f) + pow((zi - (nz/2+dz))/radius_z,2.0f);
4120 if (dist>1.0) (*pixel)*=exp(-pow((sqrt(dist)-1.0f)/gauss_width,2.0f));
4121 }
4122
4124 };
4125
4131 {
4132 public:
4134 {
4135// TypeDict d = CircularMaskProcessor::get_param_types();
4136 TypeDict d;
4137 d.put("gauss_width", EMObject::FLOAT, "Used to calculate the constant factor - gauss_width / (ny*ny)" );
4138// d.put("ring_width", EMObject::INT, "The width of the mask ring.");
4139 return d;
4140 }
4141
4142 string get_name() const
4143 {
4144 return NAME;
4145 }
4146
4147 static Processor *NEW()
4148 {
4149 return new MaskGaussInvProcessor();
4150 }
4151
4152 string get_desc() const
4153 {
4154 return "f(x) = f(x) / exp(-radius*radius * gauss_width / (ny*ny))";
4155 }
4156
4157 static const string NAME;
4158
4159 protected:
4161 {
4162 xc = Util::fast_floor(nx/2.0f) + dx;
4163 yc = Util::fast_floor(ny/2.0f) + dy;
4164 zc = Util::fast_floor(nz/2.0f) + dz;
4165
4166 float gauss_width = params["gauss_width"];
4167 slice_value = gauss_width / (ny * ny);
4168 }
4169
4170 void process_dist_pixel(float *pixel, float dist) const
4171 {
4172 (*pixel) /= exp(-dist * slice_value);
4173 }
4174 private:
4176 };
4177
4183 {
4184 public:
4185 string get_name() const
4186 {
4187 return NAME;
4188 }
4189
4190 void process_inplace(EMData *image);
4191
4192 static Processor *NEW()
4193 {
4194 return new GridKernelFixProcessor();
4195 }
4196
4198 {
4199 TypeDict d;
4200 d.put("mode", EMObject::STRING);
4201 return d;
4202 }
4203
4204 string get_desc() const
4205 {
4206 return "This corrects the real-space effects of using one of the gridding insertion functions on the Fourier reconstructor. Valid options for mode are 'gridding_5' and 'gridding7'.";
4207 }
4208
4209 static const string NAME;
4210 };
4211
4212
4218 {
4219 public:
4220 string get_name() const
4221 {
4222 return NAME;
4223 }
4224
4225 void process_inplace(EMData *image);
4226
4227 static Processor *NEW()
4228 {
4229 return new LinearPyramidProcessor();
4230 }
4231
4233 {
4234 TypeDict d;
4235 d.put("x0", EMObject::FLOAT);
4236 d.put("y0", EMObject::FLOAT);
4237 d.put("z0", EMObject::FLOAT);
4238 d.put("xwidth", EMObject::FLOAT);
4239 d.put("ywidth", EMObject::FLOAT);
4240 d.put("zwidth", EMObject::FLOAT);
4241 return d;
4242 }
4243
4244 string get_desc() const
4245 {
4246 return "Multiplies image by a 'linear pyramid' in 1-3 dimensions. The origin and total base width of the pyramid can be specified. Default is centered with the total image size.";
4247 }
4248
4249 static const string NAME;
4250 };
4251
4252
4256 {
4257 public:
4258 string get_name() const
4259 {
4260 return NAME;
4261 }
4262 static Processor *NEW()
4263 {
4264 return new MakeRadiusSquaredProcessor();
4265 }
4266
4267 string get_desc() const
4268 {
4269 return "overwrites input, f(x) = radius * radius";
4270 }
4271
4272 static const string NAME;
4273
4274 protected:
4275 void process_dist_pixel(float *pixel, float dist) const
4276 {
4277 *pixel = dist;
4278 }
4279 };
4280
4284 {
4285 public:
4286 string get_name() const
4287 {
4288 return NAME;
4289 }
4290 static Processor *NEW()
4291 {
4292 return new MakeRadiusProcessor();
4293 }
4294
4295 string get_desc() const
4296 {
4297 return "overwrites input, f(x) = radius;";
4298 }
4299
4300 static const string NAME;
4301
4302 protected:
4303 void process_dist_pixel(float *pixel, float dist) const
4304 {
4305 *pixel = sqrt(dist);
4306 }
4307 };
4308
4312 {
4313 public:
4314 void process_inplace(EMData * image);
4315
4316 static string get_group_desc()
4317 {
4318 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.";
4319 }
4320
4321 protected:
4322 virtual void process_pixel(float *x) const = 0;
4323 };
4324
4328 {
4329 public:
4330 string get_name() const
4331 {
4332 return NAME;
4333 }
4334 static Processor *NEW()
4335 {
4336 return new ComplexNormPixel();
4337 }
4338
4339 string get_desc() const
4340 {
4341 return "Each Fourier pixel will be normalized. ie - amp=1, phase=unmodified. Useful for performing phase-residual-like computations with dot products.";
4342 }
4343
4344 static const string NAME;
4345
4346 protected:
4347 void process_pixel(float *x) const
4348 {
4349 *x=1.0;
4350 }
4351 };
4352
4357 {
4358 public:
4359 AreaProcessor():areasize(0), kernel(0), nx(0), ny(0), nz(0)
4360 {
4361 }
4362
4363 void process_inplace(EMData * image);
4364
4365 void set_params(const Dict & new_params)
4366 {
4367 params = new_params;
4368 areasize = params["areasize"];
4369 }
4370
4372 {
4373 TypeDict d;
4374 d.put("areasize", EMObject::INT, "The width of the area to process (not radius)");
4375 return d;
4376 }
4377
4378 string get_desc() const
4379 {
4380 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().";
4381 }
4382
4383 protected:
4384 virtual void process_pixel(float *pixel, float, float, float, float *area_matrix) const
4385 {
4386 for (int i = 0; i < matrix_size; i++)
4387 {
4388 *pixel += area_matrix[i] * kernel[i];
4389 }
4390 }
4391
4392 virtual void create_kernel() const = 0;
4393
4396 float *kernel;
4397 int nx;
4398 int ny;
4399 int nz;
4400 };
4401
4405 {
4406 public:
4407 string get_name() const
4408 {
4409 return NAME;
4410 }
4411
4412 void process_inplace(EMData *image);
4413
4414 static Processor *NEW()
4415 {
4416 return new LaplacianProcessor();
4417 }
4418
4419 string get_desc() const
4420 {
4421 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).";
4422 }
4423
4424 static const string NAME;
4425
4426
4427 protected:
4428 void create_kernel() const;
4429
4430 };
4431
4435 {
4436 public:
4437 string get_name() const
4438 {
4439 return NAME;
4440 }
4441 static Processor *NEW()
4442 {
4443 return new ZeroConstantProcessor();
4444 }
4445
4446 string get_desc() const
4447 {
4448 return "Contraction of data, if any nearest neighbor is 0, value -> 0, generally used iteratively";
4449 }
4450
4451 static const string NAME;
4452
4453 protected:
4454 void process_pixel(float *pixel, float, float, float, float *matrix) const
4455 {
4456 if (*pixel != 0)
4457 {
4458 if (*pixel == matrix[1] || *pixel == matrix[3] || *pixel == matrix[5] ||
4459 *pixel == matrix[7] || matrix[1] == 0 || matrix[3] == 0 ||
4460 matrix[5] == 0 || matrix[7] == 0) {
4461 *pixel = 0;
4462 }
4463 }
4464 }
4465
4466 void create_kernel() const
4467 {
4468 }
4469 };
4470
4480 {
4481 public:
4482 virtual void process_inplace(EMData * image);
4483 virtual EMData *process(EMData * image);
4484
4485 static string get_group_desc()
4486 {
4487 return "BoxStatProcessor files are real-space 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).";
4488 }
4489
4491 {
4492 TypeDict d;
4493 d.put("radius", EMObject::INT, "The 'radius' of the (square/cube) search box, eg - 1 -> 3x3 box");
4494 d.put("xsize", EMObject::INT, "+- range on X axis, 0 uses the value only, 1 -> -1,0,+1, ...");
4495 d.put("ysize", EMObject::INT, "+- range on Y axis");
4496 d.put("zsize", EMObject::INT, "+- range on Z axis)");
4497 return d;
4498 }
4499
4500 protected:
4501 virtual void process_pixel(float *pixel, const float *array, int n) const = 0;
4502 };
4503
4504
4508 {
4509 public:
4510 string get_name() const
4511 {
4512 return NAME;
4513 }
4514 static Processor *NEW()
4515 {
4516 return new BoxMedianProcessor();
4517 }
4518
4519 string get_desc() const
4520 {
4521 return "A processor for noise reduction. pixel = median of values surrounding pixel.";
4522 }
4523
4524 static const string NAME;
4525
4526 protected:
4527 void process_pixel(float *pixel, const float *array, int n) const
4528 {
4529 float *data = new float[n];
4530 memcpy(data, array, sizeof(float) * n);
4531
4532 for (int i = 0; i <= n / 2; i++)
4533 {
4534 for (int j = i + 1; j < n; j++)
4535 {
4536 if (data[i] < data[j]) {
4537 float t = data[i];
4538 data[i] = data[j];
4539 data[j] = t;
4540 }
4541 }
4542 }
4543
4544 if (n % 2 != 0)
4545 {
4546 *pixel = data[n / 2];
4547 }
4548 else {
4549 *pixel = (data[n / 2] + data[n / 2 - 1]) / 2;
4550 }
4551 if( data )
4552 {
4553 delete[]data;
4554 data = 0;
4555 }
4556 }
4557 };
4558
4562 {
4563 public:
4564 string get_name() const
4565 {
4566 return NAME;
4567 }
4568 static Processor *NEW()
4569 {
4570 return new BoxSigmaProcessor();
4571 }
4572
4573 string get_desc() const
4574 {
4575 return "pixel = standard deviation of values surrounding pixel.";
4576 }
4577
4578 static const string NAME;
4579
4580 protected:
4581 void process_pixel(float *pixel, const float *data, int n) const
4582 {
4583 float sum = 0;
4584 float square_sum = 0;
4585 for (int i = 0; i < n; i++)
4586 {
4587 sum += data[i];
4588 square_sum += data[i] * data[i];
4589 }
4590
4591 float mean = sum / n;
4592 *pixel = sqrt(square_sum / n - mean * mean);
4593 }
4594 };
4595
4599 {
4600 public:
4601 string get_name() const
4602 {
4603 return NAME;
4604 }
4605 static Processor *NEW()
4606 {
4607 return new BoxMaxProcessor();
4608 }
4609
4610 string get_desc() const
4611 {
4612 return "peak processor: pixel = max of values surrounding pixel in a square/cube with specified 1/2 size.";
4613 }
4614
4615 static const string NAME;
4616
4617 protected:
4618 void process_pixel(float *pixel, const float *data, int n) const
4619 {
4620 float maxval = -FLT_MAX;
4621 for (int i = 0; i < n; i++)
4622 {
4623 if (data[i] > maxval) {
4624 maxval = data[i];
4625 }
4626 }
4627 *pixel = maxval;
4628 }
4629 };
4630
4632 {
4633 public:
4634 string get_name() const
4635 {
4636 return NAME;
4637 }
4638 static Processor *NEW()
4639 {
4640 return new LocalMinAbsProcessor();
4641 }
4642
4643 string get_desc() const
4644 {
4645 return "Takes the actual value of the pixel in the local region with the smallest absolute value. This can be used for an effect somewhat like binary erosion with continuous data.";
4646 }
4647
4648 static const string NAME;
4649
4650 protected:
4651 void process_pixel(float *pixel, const float *data, int n) const
4652 {
4653 float minval = FLT_MAX;
4654 for (int i = 0; i < n; i++)
4655 {
4656 if (fabs(data[i]) < fabs(minval)) minval=data[i];
4657 }
4658 *pixel = minval;
4659 }
4660 };
4661
4662
4666 {
4667 public:
4668 string get_name() const
4669 {
4670 return NAME;
4671 }
4672 static Processor *NEW()
4673 {
4674 return new MinusPeakProcessor();
4675 }
4676
4677 string get_desc() const
4678 {
4679 return "peak processor: pixel = pixel - max of values surrounding pixel. This is a sort of positive peak-finding algorithm.";
4680 }
4681
4682 static const string NAME;
4683
4684 protected:
4685 void process_pixel(float *pixel, const float *data, int n) const
4686 {
4687 float maxval = -FLT_MAX;
4688 for (int i = 0; i < n; i++)
4689 {
4690 if (data[i] > maxval) {
4691 maxval = data[i];
4692 }
4693 }
4694 *pixel -= maxval;
4695 }
4696 };
4697
4702 {
4703 public:
4704 string get_name() const
4705 {
4706 return NAME;
4707 }
4708 static Processor *NEW()
4709 {
4710 return new PeakOnlyProcessor();
4711 }
4712 void set_params(const Dict & new_params)
4713 {
4714 params = new_params;
4715 npeaks = params["npeaks"];
4716 if (npeaks == 0) {
4717 npeaks = 1;
4718 }
4719 }
4720
4722 {
4723 TypeDict d;
4724 d.put("npeaks", EMObject::INT, "The number of pixels adjacent to the pixel under consideration which may be higher and still be a valid peak. If 0, finds pure peaks");
4725 d.put("usemean", EMObject::BOOL, "Count all pixels with value higher than the mean of adjacent pixels as peaks. Overwrite npeaks.");
4726 return d;
4727 }
4728
4729 string get_desc() const
4730 {
4731 return "Zeros all pixels with adjacent pixels >= the value being considered. That is, it leaves behind only local maxima.";
4732 }
4733
4734 static const string NAME;
4735
4736 protected:
4737 void process_pixel(float *pixel, const float *data, int n) const
4738 {
4739 if (params["usemean"]){
4740 float mean=0;
4741 for (int i = 0; i < n; i++)
4742 {
4743 mean+=data[i];
4744 }
4745
4746 if (*pixel < mean/float(n))
4747 {
4748 *pixel = 0;
4749 }
4750 }
4751 else{
4752 int r = 0;
4753
4754 for (int i = 0; i < n; i++)
4755 {
4756 if (data[i] >= *pixel) {
4757 r++;
4758 }
4759 }
4760
4761 if (r > npeaks)
4762 {
4763 *pixel = 0;
4764 }
4765 }
4766 }
4767 private:
4769 };
4770
4776 {
4777 public:
4778 void process_inplace(EMData * image);
4779
4780 string get_name() const
4781 {
4782 return NAME;
4783 }
4784 static Processor *NEW()
4785 {
4786 return new DiffBlockProcessor();
4787 }
4788
4789 string get_desc() const
4790 {
4791 return "averages over cal_half_width, then sets the value in a local block";
4792 }
4793
4795 {
4796 TypeDict d;
4797 d.put("cal_half_width", EMObject::FLOAT, "cal_half_width is dx/dy for calculating an average");
4798 d.put("fill_half_width", EMObject::FLOAT, "fill_half_width is dx/dy for fill/step");
4799 return d;
4800 }
4801
4802 static const string NAME;
4803 };
4804
4810 {
4811 public:
4812 void process_inplace(EMData * image);
4813
4814 string get_name() const
4815 {
4816 return NAME;
4817 }
4818 static Processor *NEW()
4819 {
4820 return new CutoffBlockProcessor();
4821 }
4822
4824 {
4825 TypeDict d;
4826 d.put("value1", EMObject::FLOAT, "val1 is dx/dy");
4827 d.put("value2", EMObject::FLOAT, "val2 is lowpass freq cutoff in pixels");
4828 return d;
4829 }
4830
4831 string get_desc() const
4832 {
4833 return "Block processor, val1 is dx/dy, val2 is lp freq cutoff in pixels. Mystery processor.";
4834 }
4835
4836 static const string NAME;
4837 };
4838
4845 {
4846 protected:
4854 template<class LogicOp>
4855 EMData* process(const EMData *const image, Dict& params);
4856
4863 template<class LogicOp>
4864 void process_inplace(EMData * image, Dict& params);
4865
4866 };
4867
4877 {
4878 public:
4885 virtual EMData* process(const EMData *const image)
4886 {
4887 return BooleanShrinkProcessor::process<GreaterThan>(image, params);
4888 }
4889
4890 // resizes the image
4891 virtual void process_inplace(EMData * image)
4892 {
4893 BooleanShrinkProcessor::process_inplace<GreaterThan>(image, params);
4894 }
4895
4896 string get_desc() const
4897 {
4898 return "Shrink an image by a given amount (default 2), using the maximum value found in the pixel neighborhood.";
4899 }
4900
4901 string get_name() const
4902 {
4903 return NAME;
4904 }
4905 static Processor *NEW()
4906 {
4907 return new MaxShrinkProcessor();
4908 }
4909
4911 {
4912 TypeDict d;
4913 d.put("n", EMObject::INT, "The shrink factor");
4914 d.put("search", EMObject::INT, "The search area (cubic volume width, usually the same as shrink)");
4915 return d;
4916 }
4917
4918 static const string NAME;
4919
4920 private:
4922 {
4923 inline bool operator()(float left,float right) const { return left > right; }
4924 inline float get_start_val() { return -10000000; }
4925 };
4926 };
4927
4937 {
4938 public:
4945 virtual EMData* process(const EMData *const image)
4946 {
4947 return BooleanShrinkProcessor::process<LessThan>(image, params);
4948 }
4949
4950 // resizes the image
4951 virtual void process_inplace(EMData * image)
4952 {
4953 BooleanShrinkProcessor::process_inplace<LessThan>(image, params);
4954 }
4955 string get_desc() const
4956 {
4957 return "Shrink an image by a given amount (default 2), using the minimum value found in the pixel neighborhood.";
4958 }
4959
4960 string get_name() const
4961 {
4962 return NAME;
4963 }
4964 static Processor *NEW()
4965 {
4966 return new MinShrinkProcessor();
4967 }
4968
4970 {
4971 TypeDict d;
4972 d.put("n", EMObject::INT, "The shrink factor");
4973 d.put("search", EMObject::INT, "The search area (cubic volume width, usually the same as shrink)");
4974 return d;
4975 }
4976
4977 static const string NAME;
4978
4979 private:
4981 {
4982 inline bool operator()(float left,float right) const { return left < right; }
4983 inline float get_start_val() { return 9999999999.0f; }
4984 };
4985 };
4986
4994 {
4995 public:
5006 virtual EMData* process(const EMData *const image);
5007
5014 virtual void process_inplace(EMData * image);
5015
5016 string get_desc() const
5017 {
5018 return "Shrink an image by a given amount , using the mean value found in the pixel neighborhood.";
5019 }
5020
5021 virtual string get_name() const
5022 {
5023 return NAME;
5024 }
5025 static Processor *NEW()
5026 {
5027 return new MeanShrinkProcessor();
5028 }
5029
5031 {
5032 TypeDict d;
5033 d.put("n", EMObject::FLOAT, "The shrink factor");
5034 return d;
5035 }
5036
5037 static const string NAME;
5038
5039 private:
5047 void accrue_mean(EMData* to, const EMData *const from, const int shrinkfactor);
5048
5055 void accrue_mean_one_p_five(EMData* to, const EMData * const from);
5056 };
5057
5058
5066 {
5067 public:
5078 virtual EMData* process(const EMData *const image);
5079
5086 virtual void process_inplace(EMData * image);
5087
5088 string get_desc() const
5089 {
5090 return "Shrink an image by a given amount , using the median value found in the pixel neighborhood.";
5091 }
5092
5093 virtual string get_name() const
5094 {
5095 return NAME;
5096 }
5097 static Processor *NEW()
5098 {
5099 return new MedianShrinkProcessor();
5100 }
5101
5103 {
5104 TypeDict d;
5105 d.put("n", EMObject::INT, "The shrink factor");
5106 return d;
5107 }
5108
5109 static const string NAME;
5110
5111 private:
5119 void accrue_median(EMData* to, const EMData* const from,const int shrink_factor);
5120 };
5121
5131 {
5132 public:
5133 virtual EMData* process(const EMData *const image);
5134
5135 virtual void process_inplace(EMData * image);
5136
5137 string get_desc() const
5138 {
5139 return "Robust resampling of an image by clipping its Fourier transform.";
5140 }
5141
5142 string get_name() const
5143 {
5144 return NAME;
5145 }
5146 static Processor *NEW()
5147 {
5148 return new FFTResampleProcessor();
5149 }
5150
5152 {
5153 TypeDict d;
5154 d.put("n", EMObject::FLOAT, "The sample rate. Less than one enlarges the image, greater than one shrinks it.");
5155 return d;
5156 }
5157
5158 static const string NAME;
5159
5160 private:
5167 void fft_resample(EMData* to, const EMData *const from, const float& sample_rate);
5168
5169 };
5170
5174 {
5175 public:
5176 void process_inplace(EMData * image);
5177
5178 string get_name() const
5179 {
5180 return NAME;
5181 }
5182 static Processor *NEW()
5183 {
5184 return new GradientRemoverProcessor();
5185 }
5186
5187 string get_desc() const
5188 {
5189 return "Gradient remover, does a rough plane fit to find linear gradients.";
5190 }
5191
5192 static const string