EMAN2
processor.cpp
Go to the documentation of this file.
00001 /*
00002  * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
00003  * Copyright (c) 2000-2006 Baylor College of Medicine
00004  *
00005  * This software is issued under a joint BSD/GNU license. You may use the
00006  * source code in this file under either license. However, note that the
00007  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00008  * so you are responsible for compliance with the licenses of these packages
00009  * if you opt to use BSD licensing. The warranty disclaimer below holds
00010  * in either instance.
00011  *
00012  * This complete copyright notice must be included in any revised version of the
00013  * source code. Additional authorship citations may be added, but existing
00014  * author citations must be preserved.
00015  *
00016  * This program is free software; you can redistribute it and/or modify
00017  * it under the terms of the GNU General Public License as published by
00018  * the Free Software Foundation; either version 2 of the License, or
00019  * (at your option) any later version.
00020  *
00021  * This program is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00024  * GNU General Public License for more details.
00025  *
00026  * You should have received a copy of the GNU General Public License
00027  * along with this program; if not, write to the Free Software
00028  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00029  *
00030  * */
00031 
00032 #include "processor.h"
00033 #include "sparx/processor_sparx.h"
00034 #include "plugins/processor_template.h"
00035 #include "cmp.h"
00036 #include "ctf.h"
00037 #include "xydata.h"
00038 #include "emdata.h"
00039 #include "emassert.h"
00040 #include "randnum.h"
00041 #include "symmetry.h"
00042 #include "averager.h"
00043 
00044 #include <gsl/gsl_randist.h>
00045 #include <gsl/gsl_statistics.h>
00046 #include <gsl/gsl_wavelet.h>
00047 #include <gsl/gsl_wavelet2d.h>
00048 #include <gsl/gsl_multimin.h>
00049 #include <algorithm>
00050 #include <gsl/gsl_fit.h>
00051 #include <ctime>
00052 
00053 #ifdef __APPLE__
00054         typedef unsigned int uint;
00055 #endif  //__APPLE__
00056 
00057 #ifdef _WIN32
00058         typedef unsigned int uint;
00059 #endif  //_WIN32
00060 
00061 #ifdef EMAN2_USING_CUDA
00062 //#include "cuda/cuda_util.h"
00063 #include "cuda/cuda_processor.h"
00064 #endif // EMAN2_USING_CUDA
00065 
00066 using namespace EMAN;
00067 using std::reverse;
00068 
00069 const string SNREvalProcessor::NAME = "eval.maskedsnr";
00070 const string AmpweightFourierProcessor::NAME = "filter.ampweight";
00071 const string Axis0FourierProcessor::NAME = "filter.xyaxes0";
00072 const string ConvolutionProcessor::NAME = "math.convolution";
00073 const string XGradientProcessor::NAME = "math.edge.xgradient";
00074 const string YGradientProcessor::NAME = "math.edge.ygradient";
00075 const string ZGradientProcessor::NAME = "math.edge.zgradient";
00076 const string Wiener2DAutoAreaProcessor::NAME = "filter.wiener2dauto";
00077 const string Wiener2DFourierProcessor::NAME = "filter.wiener2d";
00078 const string CtfSimProcessor::NAME = "math.simulatectf";
00079 const string LinearRampFourierProcessor::NAME = "filter.linearfourier";
00080 const string LoGFourierProcessor::NAME = "filter.LoG";
00081 const string DoGFourierProcessor::NAME = "filter.DoG";
00082 const string HighpassAutoPeakProcessor::NAME = "filter.highpass.autopeak";
00083 const string LinearRampProcessor::NAME = "eman1.filter.ramp";
00084 const string AbsoluateValueProcessor::NAME = "math.absvalue";
00085 const string FloorValueProcessor::NAME = "math.floor";
00086 const string BooleanProcessor::NAME = "threshold.notzero";
00087 const string KmeansSegmentProcessor::NAME = "segment.kmeans";
00088 const string DistanceSegmentProcessor::NAME = "segment.distance";
00089 const string WatershedProcessor::NAME = "segment.watershed";
00090 const string RecipCarefullyProcessor::NAME = "math.reciprocal";
00091 const string SubtractOptProcessor::NAME = "math.sub.optimal";
00092 const string ValuePowProcessor::NAME = "math.pow";
00093 const string ValueSquaredProcessor::NAME = "math.squared";
00094 const string ValueSqrtProcessor::NAME = "math.sqrt";
00095 const string ToZeroProcessor::NAME = "threshold.belowtozero";
00096 const string AboveToZeroProcessor::NAME="threshold.abovetozero";
00097 const string Rotate180Processor::NAME = "math.rotate.180";
00098 const string TransformProcessor::NAME = "xform";
00099 const string IntTranslateProcessor::NAME = "xform.translate.int";
00100 const string ScaleTransformProcessor::NAME = "xform.scale";
00101 const string ApplySymProcessor::NAME = "xform.applysym";
00102 const string ClampingProcessor::NAME = "threshold.clampminmax";
00103 const string NSigmaClampingProcessor::NAME = "threshold.clampminmax.nsigma";
00104 const string ToMinvalProcessor::NAME = "threshold.belowtominval";
00105 const string CutToZeroProcessor::NAME = "threshold.belowtozero_cut";
00106 const string BinarizeProcessor::NAME = "threshold.binary";
00107 //const string BinarizeAmpProcessor::NAME = "threshold.amp.binary";
00108 const string BinarizeFourierProcessor::NAME = "threshold.binary.fourier";
00109 const string CollapseProcessor::NAME = "threshold.compress";
00110 const string LinearXformProcessor::NAME = "math.linear";
00111 const string ExpProcessor::NAME = "math.exp";
00112 const string FiniteProcessor::NAME = "math.finite";
00113 const string RangeThresholdProcessor::NAME = "threshold.binaryrange";
00114 const string SigmaProcessor::NAME = "math.sigma";
00115 const string LogProcessor::NAME = "math.log";
00116 const string MaskSharpProcessor::NAME = "mask.sharp";
00117 const string MaskSoftProcessor::NAME = "mask.soft";
00118 const string MaskEdgeMeanProcessor::NAME = "mask.ringmean";
00119 const string MaskNoiseProcessor::NAME = "mask.noise";
00120 const string MaskGaussProcessor::NAME = "mask.gaussian";
00121 const string MaskGaussNonuniformProcessor::NAME = "mask.gaussian.nonuniform";
00122 const string MaskGaussInvProcessor::NAME = "math.gausskernelfix";
00123 const string LinearPyramidProcessor::NAME = "math.linearpyramid";
00124 const string MakeRadiusSquaredProcessor::NAME = "math.toradiussqr";
00125 const string MakeRadiusProcessor::NAME = "math.toradius";
00126 const string ComplexNormPixel::NAME = "complex.normpixels";
00127 const string LaplacianProcessor::NAME = "math.laplacian";
00128 const string ZeroConstantProcessor::NAME = "mask.contract";     // This is broken, it never worked. Somebody didn't think it through properly
00129 const string BoxMedianProcessor::NAME = "eman1.filter.median";
00130 const string BoxSigmaProcessor::NAME = "math.localsigma";
00131 const string NonConvexProcessor::NAME = "math.nonconvex";
00132 const string BoxMaxProcessor::NAME = "math.localmax";
00133 const string MinusPeakProcessor::NAME = "math.submax";
00134 const string PeakOnlyProcessor::NAME = "mask.onlypeaks";
00135 const string DiffBlockProcessor::NAME = "eman1.filter.blockrange";
00136 const string CutoffBlockProcessor::NAME = "eman1.filter.blockcutoff";
00137 const string MaxShrinkProcessor::NAME = "math.maxshrink";
00138 const string MinShrinkProcessor::NAME = "math.minshrink";
00139 const string MeanShrinkProcessor::NAME = "math.meanshrink";
00140 const string MedianShrinkProcessor::NAME = "math.medianshrink";
00141 const string FFTResampleProcessor::NAME = "math.fft.resample";
00142 const string GradientRemoverProcessor::NAME = "math.lineargradientfix";
00143 const string GradientPlaneRemoverProcessor::NAME = "filter.gradientPlaneRemover";
00144 const string FlattenBackgroundProcessor::NAME = "filter.flattenbackground";
00145 const string RampProcessor::NAME = "filter.ramp";
00146 const string VerticalStripeProcessor::NAME = "math.verticalstripefix";
00147 const string RealToFFTProcessor::NAME = "math.realtofft";
00148 const string SigmaZeroEdgeProcessor::NAME = "mask.zeroedgefill";
00149 const string BeamstopProcessor::NAME = "mask.beamstop";
00150 const string MeanZeroEdgeProcessor::NAME = "mask.dampedzeroedgefill";
00151 const string AverageXProcessor::NAME = "math.averageovery";
00152 const string DecayEdgeProcessor::NAME = "mask.decayedge2d";
00153 const string ZeroEdgeRowProcessor::NAME = "mask.zeroedge2d";
00154 const string ZeroEdgePlaneProcessor::NAME = "mask.zeroedge3d";
00155 const string BilateralProcessor::NAME = "filter.bilateral";
00156 const string NormalizeUnitProcessor::NAME = "normalize.unitlen";
00157 const string NormalizeUnitSumProcessor::NAME = "normalize.unitsum";
00158 const string NormalizeStdProcessor::NAME = "normalize";
00159 const string NormalizeMaskProcessor::NAME = "normalize.mask";
00160 const string NormalizeRampNormVar::NAME = "normalize.ramp.normvar";
00161 const string NormalizeByMassProcessor::NAME = "normalize.bymass";
00162 const string NormalizeEdgeMeanProcessor::NAME = "normalize.edgemean";
00163 const string NormalizeCircleMeanProcessor::NAME = "normalize.circlemean";
00164 const string NormalizeLREdgeMeanProcessor::NAME = "normalize.lredge";
00165 const string NormalizeMaxMinProcessor::NAME = "normalize.maxmin";
00166 const string NormalizeRowProcessor::NAME = "normalize.rows";
00167 const string NormalizeToLeastSquareProcessor::NAME = "normalize.toimage";
00168 const string RotationalAverageProcessor::NAME = "math.rotationalaverage";
00169 const string RotationalSubstractProcessor::NAME = "math.rotationalsubtract";
00170 const string TransposeProcessor::NAME = "xform.transpose";
00171 const string FlipProcessor::NAME = "xform.flip";
00172 const string AddNoiseProcessor::NAME = "math.addnoise";
00173 const string AddSigmaNoiseProcessor::NAME = "math.addsignoise";
00174 const string AddRandomNoiseProcessor::NAME = "math.addspectralnoise";
00175 const string FourierToCornerProcessor::NAME = "xform.fourierorigin.tocorner";
00176 const string FourierToCenterProcessor::NAME = "xform.fourierorigin.tocenter";
00177 const string PhaseToCenterProcessor::NAME = "xform.phaseorigin.tocenter";
00178 const string PhaseToCornerProcessor::NAME = "xform.phaseorigin.tocorner";
00179 const string AutoMask2DProcessor::NAME = "mask.auto2d";
00180 const string AutoMaskAsymUnit::NAME = "mask.asymunit";
00181 const string AutoMask3DProcessor::NAME = "mask.auto3d.thresh";
00182 const string AutoMask3D2Processor::NAME = "mask.auto3d";
00183 const string AutoMaskDustProcessor::NAME = "mask.dust3d";
00184 const string AddMaskShellProcessor::NAME = "mask.addshells";
00185 const string IterMultiMaskProcessor::NAME = "mask.addshells.multilevel";
00186 const string IterBinMaskProcessor::NAME = "mask.addshells.gauss";
00187 const string PhaseToMassCenterProcessor::NAME = "xform.phasecenterofmass";
00188 const string ToMassCenterProcessor::NAME = "xform.centerofmass";
00189 const string ACFCenterProcessor::NAME = "xform.centeracf";
00190 const string SNRProcessor::NAME = "eman1.filter.snr";
00191 const string FileFourierProcessor::NAME = "eman1.filter.byfile";
00192 const string FSCFourierProcessor::NAME = "filter.wiener.byfsc";
00193 const string SymSearchProcessor::NAME = "misc.symsearch";
00194 const string LocalNormProcessor::NAME = "normalize.local";
00195 const string StripeXYProcessor::NAME = "math.xystripefix";
00196 const string IndexMaskFileProcessor::NAME = "mask.fromfile";
00197 const string CoordinateMaskFileProcessor::NAME = "mask.fromfile.sizediff";
00198 const string PaintProcessor::NAME = "mask.paint";
00199 const string DirectionalSumProcessor::NAME = "misc.directional_sum";
00200 template<> const string BinaryOperateProcessor<MaxPixelOperator>::NAME = "math.max";            // These 2 should not really be processors
00201 template<> const string BinaryOperateProcessor<MinPixelOperator>::NAME = "math.min";
00202 const string MaxPixelOperator::NAME = "math.max";
00203 const string MinPixelOperator::NAME = "math.min";
00204 const string MatchSFProcessor::NAME = "filter.matchto";
00205 const string SetSFProcessor::NAME = "filter.setstrucfac";
00206 const string SmartMaskProcessor::NAME = "mask.smart";
00207 const string TestImagePureGaussian::NAME = "testimage.puregaussian";
00208 const string TestImageFourierNoiseGaussian::NAME = "testimage.noise.fourier.gaussian";
00209 const string TestImageFourierNoiseProfile::NAME = "testimage.noise.fourier.profile";
00210 const string CTFSNRWeightProcessor::NAME = "ctf.snr.weight";
00211 const string TestImageLineWave::NAME = "testimage.linewave";
00212 const string TestTomoImage::NAME = "testimage.tomo.objects";
00213 const string TestImageGradient::NAME = "testimage.gradient";
00214 const string TestImageAxes::NAME = "testimage.axes";
00215 const string TestImageGaussian::NAME = "testimage.gaussian";
00216 const string TestImageScurve::NAME = "testimage.scurve";
00217 const string TestImageSphericalWave::NAME = "testimage.sphericalwave";
00218 const string TestImageSinewave::NAME = "testimage.sinewave";
00219 const string TestImageSinewaveCircular::NAME = "testimage.sinewave.circular";
00220 const string TestImageSquarecube::NAME = "testimage.squarecube";
00221 const string TestImageEllipse::NAME = "testimage.ellipsoid";
00222 const string TestImageHollowEllipse::NAME = "testimage.ellipsoid.hollow";
00223 const string TestImageCirclesphere::NAME = "testimage.circlesphere";
00224 const string TestImageNoiseUniformRand::NAME = "testimage.noise.uniform.rand";
00225 const string TestImageNoiseGauss::NAME = "testimage.noise.gauss";
00226 const string TestImageCylinder::NAME = "testimage.cylinder";
00227 const string CCDNormProcessor::NAME = "filter.ccdnorm";
00228 const string WaveletProcessor::NAME = "basis.wavelet";
00229 const string TomoTiltEdgeMaskProcessor::NAME = "tomo.tiltedgemask";
00230 const string TomoTiltAngleWeightProcessor::NAME = "tomo.tiltangleweight";
00231 const string FFTProcessor::NAME = "basis.fft";
00232 const string RadialProcessor::NAME = "mask.radialprofile";
00233 const string HistogramBin::NAME = "histogram.bin";
00234 const string ModelEMCylinderProcessor::NAME = "math.model_em_cylinder";
00235 const string ApplyPolynomialProfileToHelix::NAME = "math.poly_radial_profile";
00236 const string BinarySkeletonizerProcessor::NAME="gorgon.binary_skel";
00237 const string MirrorProcessor::NAME = "xform.mirror";
00238 const string NewLowpassTopHatProcessor::NAME = "filter.lowpass.tophat";
00239 const string NewHighpassTopHatProcessor::NAME = "filter.highpass.tophat";
00240 const string NewBandpassTopHatProcessor::NAME = "filter.bandpass.tophat";
00241 const string NewHomomorphicTopHatProcessor::NAME = "filter.homomorphic.tophat";
00242 const string NewLowpassGaussProcessor::NAME = "filter.lowpass.gauss";
00243 const string LowpassAutoBProcessor::NAME="filter.lowpass.autob";
00244 const string NewHighpassGaussProcessor::NAME = "filter.highpass.gauss";
00245 const string NewBandpassGaussProcessor::NAME = "filter.bandpass.gauss";
00246 const string NewHomomorphicGaussProcessor::NAME = "filter.homomorphic.gauss";
00247 const string NewInverseGaussProcessor::NAME = "filter.gaussinverse";
00248 const string SHIFTProcessor::NAME = "filter.shift";
00249 const string InverseKaiserI0Processor::NAME = "filter.kaiser_io_inverse";
00250 const string InverseKaiserSinhProcessor::NAME = "filter.kaisersinhinverse";
00251 const string NewRadialTableProcessor::NAME = "filter.radialtable";
00252 const string LowpassRandomPhaseProcessor::NAME = "filter.lowpass.randomphase";
00253 const string NewLowpassButterworthProcessor::NAME = "filter.lowpass.butterworth";
00254 const string NewHighpassButterworthProcessor::NAME = "filter.highpass.butterworth";
00255 const string NewHomomorphicButterworthProcessor::NAME = "filter.homomorphic.butterworth";
00256 const string NewLowpassTanhProcessor::NAME = "filter.lowpass.tanh";
00257 const string NewHighpassTanhProcessor::NAME = "filter.highpass.tanh";
00258 const string NewHomomorphicTanhProcessor::NAME = "filter.homomorphic.tanh";
00259 const string NewBandpassTanhProcessor::NAME = "filter.bandpass.tanh";
00260 const string CTF_Processor::NAME = "filter.CTF_";
00261 const string ConvolutionKernelProcessor::NAME = "filter.convolution.kernel";
00262 const string RotateInFSProcessor::NAME = "rotateinfs";
00263 
00264 //#ifdef EMAN2_USING_CUDA
00265 //const string CudaMultProcessor::NAME = "cuda.math.mult";
00266 //const string CudaCorrelationProcessor::NAME = "cuda.correlate";
00267 //#endif //EMAN2_USING_CUDA
00268 
00269 #if 0
00270 //const string XYZProcessor::NAME = "XYZ";
00271 #endif  //0
00272 
00273 
00274 template <> Factory < Processor >::Factory()
00275 {
00276         force_add<HighpassAutoPeakProcessor>();
00277         force_add<LinearRampFourierProcessor>();
00278         force_add<LoGFourierProcessor>();
00279         force_add<DoGFourierProcessor>();
00280 
00281         force_add<AmpweightFourierProcessor>();
00282         force_add<Axis0FourierProcessor>();
00283         force_add<Wiener2DFourierProcessor>();
00284         force_add<LowpassAutoBProcessor>();
00285 
00286         force_add<LinearPyramidProcessor>();
00287         force_add<LinearRampProcessor>();
00288         force_add<AbsoluateValueProcessor>();
00289         force_add<FloorValueProcessor>();
00290         force_add<BooleanProcessor>();
00291         force_add<KmeansSegmentProcessor>();
00292         force_add<DistanceSegmentProcessor>();
00293         force_add<ValuePowProcessor>();
00294         force_add<ValueSquaredProcessor>();
00295         force_add<ValueSqrtProcessor>();
00296         force_add<Rotate180Processor>();
00297         force_add<TransformProcessor>();
00298         force_add<ScaleTransformProcessor>();
00299         force_add<ApplySymProcessor>();
00300         force_add<IntTranslateProcessor>();
00301         force_add<RecipCarefullyProcessor>();
00302         force_add<SubtractOptProcessor>();
00303 
00304         force_add<ClampingProcessor>();
00305         force_add<NSigmaClampingProcessor>();
00306 
00307         force_add<ToZeroProcessor>();
00308         force_add<AboveToZeroProcessor>();
00309         force_add<ToMinvalProcessor>();
00310         force_add<CutToZeroProcessor>();
00311         force_add<BinarizeProcessor>();
00312 //      force_add<BinarizeAmpProcessor>();
00313         force_add<BinarizeFourierProcessor>();
00314         force_add<CollapseProcessor>();
00315         force_add<LinearXformProcessor>();
00316 
00317         force_add<ExpProcessor>();
00318         force_add<RangeThresholdProcessor>();
00319         force_add<SigmaProcessor>();
00320         force_add<LogProcessor>();
00321         force_add<FiniteProcessor>();
00322 
00323         force_add< BinaryOperateProcessor<MaxPixelOperator> >();
00324         force_add< BinaryOperateProcessor<MinPixelOperator> >();
00325 
00326         force_add<PaintProcessor>();
00327         force_add<WatershedProcessor>();
00328         force_add<MaskSharpProcessor>();
00329         force_add<MaskSoftProcessor>();
00330         force_add<MaskEdgeMeanProcessor>();
00331         force_add<MaskNoiseProcessor>();
00332         force_add<MaskGaussProcessor>();
00333         force_add<MaskGaussNonuniformProcessor>();
00334         force_add<MaskGaussInvProcessor>();
00335 
00336         force_add<MaxShrinkProcessor>();
00337         force_add<MinShrinkProcessor>();
00338         force_add<MeanShrinkProcessor>();
00339         force_add<MedianShrinkProcessor>();
00340         force_add<FFTResampleProcessor>();
00341         force_add<NonConvexProcessor>();
00342 
00343         force_add<MakeRadiusSquaredProcessor>();
00344         force_add<MakeRadiusProcessor>();
00345 
00346         force_add<ComplexNormPixel>();
00347 
00348         force_add<LaplacianProcessor>();
00349 //      force_add<ZeroConstantProcessor>();   // this is badly written, it does not work and never did. Who wrote this !?!?
00350 
00351         force_add<BoxMedianProcessor>();
00352         force_add<BoxSigmaProcessor>();
00353         force_add<BoxMaxProcessor>();
00354 
00355         force_add<MinusPeakProcessor>();
00356         force_add<PeakOnlyProcessor>();
00357         force_add<DiffBlockProcessor>();
00358 
00359         force_add<CutoffBlockProcessor>();
00360 //      force_add<GradientRemoverProcessor>();
00361         force_add<GradientPlaneRemoverProcessor>();
00362         force_add<FlattenBackgroundProcessor>();
00363         force_add<VerticalStripeProcessor>();
00364         force_add<RealToFFTProcessor>();
00365         force_add<SigmaZeroEdgeProcessor>();
00366         force_add<RampProcessor>();
00367 
00368         force_add<BeamstopProcessor>();
00369         force_add<MeanZeroEdgeProcessor>();
00370         force_add<AverageXProcessor>();
00371         force_add<DecayEdgeProcessor>();
00372         force_add<ZeroEdgeRowProcessor>();
00373         force_add<ZeroEdgePlaneProcessor>();
00374 
00375         force_add<BilateralProcessor>();
00376 
00377         force_add<ConvolutionProcessor>();
00378 
00379         force_add<NormalizeStdProcessor>();
00380         force_add<NormalizeUnitProcessor>();
00381         force_add<NormalizeUnitSumProcessor>();
00382         force_add<NormalizeMaskProcessor>();
00383         force_add<NormalizeEdgeMeanProcessor>();
00384         force_add<NormalizeCircleMeanProcessor>();
00385         force_add<NormalizeLREdgeMeanProcessor>();
00386         force_add<NormalizeMaxMinProcessor>();
00387         force_add<NormalizeByMassProcessor>();
00388         force_add<NormalizeRowProcessor>();
00389         force_add<NormalizeRampNormVar>();
00390 
00391         force_add<HistogramBin>();
00392 
00393         force_add<NormalizeToLeastSquareProcessor>();
00394 
00395         force_add<RotationalAverageProcessor>();
00396         force_add<RotationalSubstractProcessor>();
00397         force_add<FlipProcessor>();
00398         force_add<TransposeProcessor>();
00399         force_add<MirrorProcessor>();
00400 
00401         force_add<AddNoiseProcessor>();
00402         force_add<AddSigmaNoiseProcessor>();
00403         force_add<AddRandomNoiseProcessor>();
00404 
00405         force_add<PhaseToCenterProcessor>();
00406         force_add<PhaseToCornerProcessor>();
00407         force_add<FourierToCenterProcessor>();
00408         force_add<FourierToCornerProcessor>();
00409         force_add<AutoMask2DProcessor>();
00410         force_add<AutoMask3DProcessor>();
00411         force_add<AutoMask3D2Processor>();
00412         force_add<AutoMaskDustProcessor>();
00413         force_add<AddMaskShellProcessor>();
00414         force_add<IterMultiMaskProcessor>();
00415         force_add<IterBinMaskProcessor>();
00416         force_add<AutoMaskAsymUnit>();
00417 
00418         force_add<CTFSNRWeightProcessor>();
00419 
00420         force_add<ToMassCenterProcessor>();
00421         force_add<PhaseToMassCenterProcessor>();
00422         force_add<ACFCenterProcessor>();
00423 //      force_add<SNRProcessor>();
00424         force_add<FSCFourierProcessor>();
00425 
00426         force_add<XGradientProcessor>();
00427         force_add<YGradientProcessor>();
00428         force_add<ZGradientProcessor>();
00429 
00430 //      force_add<FileFourierProcessor>();
00431 
00432         force_add<SymSearchProcessor>();
00433         force_add<StripeXYProcessor>();
00434         force_add<LocalNormProcessor>();
00435 
00436         force_add<IndexMaskFileProcessor>();
00437         force_add<CoordinateMaskFileProcessor>();
00438         force_add<SetSFProcessor>();
00439         force_add<MatchSFProcessor>();
00440 
00441         force_add<SmartMaskProcessor>();
00442 
00443         force_add<TestImageGaussian>();
00444         force_add<TestImagePureGaussian>();
00445         force_add<TestImageSinewave>();
00446         force_add<TestImageSphericalWave>();
00447         force_add<TestImageSinewaveCircular>();
00448         force_add<TestImageSquarecube>();
00449         force_add<TestImageCirclesphere>();
00450         force_add<TestImageAxes>();
00451         force_add<TestImageNoiseUniformRand>();
00452         force_add<TestImageNoiseGauss>();
00453         force_add<TestImageScurve>();
00454         force_add<TestImageCylinder>();
00455         force_add<TestImageGradient>();
00456         force_add<TestTomoImage>();
00457         force_add<TestImageLineWave>();
00458         force_add<TestImageEllipse>();
00459         force_add<TestImageHollowEllipse>();
00460         force_add<TestImageFourierNoiseGaussian>();
00461         force_add<TestImageFourierNoiseProfile>();
00462 
00463         force_add<TomoTiltEdgeMaskProcessor>();
00464         force_add<TomoTiltAngleWeightProcessor>();
00465 
00466         force_add<NewLowpassTopHatProcessor>();
00467         force_add<NewHighpassTopHatProcessor>();
00468         force_add<NewBandpassTopHatProcessor>();
00469         force_add<NewHomomorphicTopHatProcessor>();
00470         force_add<NewLowpassGaussProcessor>();
00471         force_add<NewHighpassGaussProcessor>();
00472         force_add<NewBandpassGaussProcessor>();
00473         force_add<NewHomomorphicGaussProcessor>();
00474         force_add<NewInverseGaussProcessor>();
00475         force_add<LowpassRandomPhaseProcessor>();
00476         force_add<NewLowpassButterworthProcessor>();
00477         force_add<NewHighpassButterworthProcessor>();
00478         force_add<NewHomomorphicButterworthProcessor>();
00479         force_add<NewLowpassTanhProcessor>();
00480         force_add<NewHighpassTanhProcessor>();
00481         force_add<NewBandpassTanhProcessor>();
00482         force_add<NewHomomorphicTanhProcessor>();
00483         force_add<NewRadialTableProcessor>();
00484         force_add<InverseKaiserI0Processor>();
00485         force_add<InverseKaiserSinhProcessor>();
00486         force_add<CCDNormProcessor>();
00487         force_add<CTF_Processor>();
00488         force_add<SHIFTProcessor>();
00489 
00490         force_add<WaveletProcessor>();
00491         force_add<FFTProcessor>();
00492         force_add<RadialProcessor>();
00493 
00494         force_add<DirectionalSumProcessor>();
00495         force_add<ConvolutionKernelProcessor>();
00496 
00497         //Gorgon-related processors
00498         force_add<ModelEMCylinderProcessor>();
00499         force_add<ApplyPolynomialProfileToHelix>();
00500         force_add<BinarySkeletonizerProcessor>();
00501         force_add<RotateInFSProcessor>();
00502 
00503 //#ifdef EMAN2_USING_CUDA
00504 //      force_add<CudaMultProcessor>();
00505 //      force_add<CudaCorrelationProcessor>();
00506 //#endif // EMAN2_USING_CUDA
00507 
00508 //      force_add<XYZProcessor>();
00509 }
00510 
00511 void FiniteProcessor::process_pixel(float *x) const
00512 {
00513         if ( !Util::goodf(x) ) {
00514                 *x = to;
00515         }
00516 }
00517 
00518 
00519 EMData* Processor::process(const EMData * const image)
00520 {
00521         EMData * result = image->copy();
00522 //      printf("Default copy called\n");
00523         process_inplace(result);
00524         return result;
00525 }
00526 
00527 void ImageProcessor::process_inplace(EMData * image)
00528 {
00529         if (!image) {
00530                 LOGWARN("NULL image");
00531                 return;
00532         }
00533 
00534         EMData *processor_image = create_processor_image();
00535 
00536         if (image->is_complex()) {
00537                 (*image) *= *processor_image;
00538         }
00539         else {
00540                 EMData *fft = image->do_fft();
00541                 (*fft) *= (*processor_image);
00542                 EMData *ift = fft->do_ift();
00543 
00544                 float *data = image->get_data();
00545                 float *t = data;
00546                 float *ift_data = ift->get_data();
00547 
00548                 data = ift_data;
00549                 ift_data = t;
00550 
00551                 ift->update();
00552 
00553                 if( fft )
00554                 {
00555                         delete fft;
00556                         fft = 0;
00557                 }
00558 
00559                 if( ift )
00560                 {
00561                         delete ift;
00562                         ift = 0;
00563                 }
00564         }
00565 
00566         image->update();
00567 }
00568 
00569 #define FFTRADIALOVERSAMPLE 4
00570 void FourierProcessor::process_inplace(EMData * image)
00571 {
00572         if (!image) {
00573                 LOGWARN("NULL Image");
00574                 return;
00575         }
00576 
00577         preprocess(image);
00578 
00579         int array_size = FFTRADIALOVERSAMPLE * image->get_ysize();
00580         float step=0.5f/array_size;
00581 
00582         bool return_radial=(bool)params.set_default("return_radial",0);
00583         vector < float >yarray(array_size);
00584 
00585         create_radial_func(yarray);
00586 
00587         if (image->is_complex()) {
00588                 image->apply_radial_func(0, step, yarray);
00589         }
00590         else {
00591                 EMData *fft = image->do_fft();
00592                 fft->apply_radial_func(0, step, yarray);
00593                 EMData *ift = fft->do_ift();
00594 
00595                 memcpy(image->get_data(),ift->get_data(),ift->get_xsize()*ift->get_ysize()*ift->get_zsize()*sizeof(float));
00596 
00597                 //ift->update(); Unecessary
00598 
00599                 if( fft )
00600                 {
00601                         delete fft;
00602                         fft = 0;
00603                 }
00604 
00605                 if( ift )
00606                 {
00607                         delete ift;
00608                         ift = 0;
00609                 }
00610         }
00611         if (return_radial) image->set_attr("filter_curve",yarray);
00612 
00613         image->update();
00614 }
00615 
00616 void FourierAnlProcessor::process_inplace(EMData * image)
00617 {
00618         if (!image) {
00619                 LOGWARN("NULL Image");
00620                 return;
00621         }
00622 
00623         preprocess(image);
00624 
00625 //      int array_size = FFTRADIALOVERSAMPLE * image->get_ysize();
00626 //      float step=0.5f/array_size;
00627 //
00628 //      vector < float >yarray(array_size);
00629 
00630         bool return_radial=(bool)params.set_default("return_radial",0);
00631         bool interpolate=(bool)params.set_default("interpolate",0);
00632 
00633         if (image->is_complex()) {
00634                 vector <float>yarray = image->calc_radial_dist(image->get_ysize()/2,0,1.0,1);
00635                 create_radial_func(yarray,image);
00636                 image->apply_radial_func(0, 0.5f/yarray.size(), yarray);
00637                 if (return_radial) image->set_attr("filter_curve",yarray);
00638         }
00639         else {
00640                 EMData *fft = image->do_fft();
00641                 vector <float>yarray = fft->calc_radial_dist(fft->get_ysize()/2,0,1.0,1);
00642                 create_radial_func(yarray,image);
00643                 // 4/30/10 stevel turned off interpolation to fix problem with matched filter
00644                 // 9/12/14 stevel, not sure why I turned off interp. Seems to cause rather than fix problems. Adding option to enable. Afraid to turn it on
00645                 fft->apply_radial_func(0, 0.5f/yarray.size(), yarray,0);
00646                 EMData *ift = fft->do_ift();
00647 
00648                 memcpy(image->get_data(),ift->get_data(),ift->get_xsize()*ift->get_ysize()*ift->get_zsize()*sizeof(float));
00649                 if (return_radial) image->set_attr("filter_curve",yarray);
00650 
00651                 //ift->update(); Unecessary
00652 
00653                 delete fft;
00654                 delete ift;
00655 
00656         }
00657 
00658         image->update();
00659 }
00660 
00661 void LowpassAutoBProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const{
00662         float apix=(float)image->get_attr("apix_x");
00663         int verbose=(int)params["verbose"];
00664 //      int adaptnoise=params.set_default("adaptnoise",0);
00665         float noisecutoff=(float)params.set_default("noisecutoff",1.0/6.0);
00666         if (apix<=0 || apix>7.0f) throw ImageFormatException("apix_x > 7.0 or <0");
00667         float ds=1.0f/(apix*image->get_xsize());        // 0.5 is because radial mask is 2x oversampled
00668         unsigned int start=(int)floor(1.0/(15.0*ds));
00669         unsigned int end=radial_mask.size()-2;
00670         if (noisecutoff>0) end=(int)floor(noisecutoff/ds);
00671         if (end>radial_mask.size()-2) {
00672                 if (verbose) printf("WARNING: specified noisecutoff too close to Nyquist, reset !");
00673                 end=radial_mask.size()-2;
00674         }
00675         if (end<start+2) {
00676                 printf("WARNING: noise cutoff too close to 15 A ! Results will not be good...");
00677                 start=end-5;
00678         }
00679 
00680         FILE *out=NULL;
00681         if (verbose>2)  {
00682                 printf("Autob -> %d - %d  ds=%g apix=%g rdlmsk=%d\n",start,end,ds,apix,int(radial_mask.size()));
00683                 out=fopen("fitplot.txt","w");
00684         }
00685         int N=(radial_mask.size()-start-2);
00686         float *x=(float *)malloc(N*sizeof(float));
00687         float *y=(float *)malloc(N*sizeof(float));
00688         float *dy=(float *)malloc(N*sizeof(float));
00689         for (unsigned int i=start; i<radial_mask.size()-2; i++ ) {              // -2 is arbitrary because sometimes the last pixel or two have funny values
00690                 x[i-start]=ds*ds*i*i;
00691                 if (radial_mask[i]>0) y[i-start]=log(radial_mask[i]); // ok
00692                 else if (i>start) y[i-start]=y[i-start-1];              // not good
00693                 else y[i-start]=0.0;                                                    // bad
00694                 if (i>start &&i<radial_mask.size()-3) dy[i-start]=y[i-start]-y[i-start-1];      // creates a 'derivative' of sorts, for use in adaptnoise
00695                 if (out) fprintf(out,"%f\t%f\n",x[i-start],y[i-start]);
00696         }
00697         if (out) fclose(out);
00698 
00699         float slope=0,intercept=0;
00700         Util::calc_least_square_fit(end-start, x,y,&slope,&intercept,1);
00701 
00702         if (verbose) printf("slope=%f  intercept=%f\n",slope,intercept);
00703 
00704         float B=(float)params["bfactor"]+slope*4.0f/2.0f;               // *4 is for Henderson definition, 2.0 is for intensity vs amplitude
00705         float B2=(float)params["bfactor"];
00706 
00707         if (verbose) printf("User B = %1.2f  Corrective B = %1.2f  Total B=%1.3f\n",(float)params["bfactor"],slope*2.0,B);
00708 
00709         float cutval=exp(-B*pow(end*ds,2.0f)/4.0f)/exp(-B2*pow(end*ds,2.0f)/4.0f);
00710         for (unsigned int i=0; i<radial_mask.size(); i++) {
00711                 if (i<=end) radial_mask[i]=exp(-B*pow(i*ds,2.0f)/4.0f);
00712                 else radial_mask[i]=cutval*exp(-B2*pow(i*ds,2.0f)/4.0f);
00713         }
00714         if (verbose>1) Util::save_data(0,ds,radial_mask,"filter.txt");
00715 
00716         free(x);
00717         free(y);
00718         free(dy);
00719  }
00720 
00721 void SNREvalProcessor::process_inplace(EMData * image)
00722 {
00723         int ys=image->get_ysize();
00724 
00725         EMData *mask1=new EMData(ys,ys,1);
00726         mask1->process_inplace("mask.gaussian",Dict("outer_radius", ys/2.0));
00727         EMData *mask2=mask1->copy();
00728         mask2->mult(-1.0f);
00729         mask2->add(1.0);
00730         mask2->process_inplace("mask.decayedge2d",Dict("width",4));
00731 
00732 /*
00733 
00734 
00735 
00736 mask1=EMData(ys2,ys2,1)
00737                 mask1.to_one()
00738                 mask1.process_inplace("mask.gaussian",{"outer_radius":radius})
00739                 mask2=mask1.copy()*-1+1
00740 #               mask1.process_inplace("mask.decayedge2d",{"width":4})
00741                 mask2.process_inplace("mask.decayedge2d",{"width":4})
00742                 mask1.clip_inplace(Region(-(ys2*(oversamp-1)/2),-(ys2*(oversamp-1)/2),ys,ys))
00743                 mask2.clip_inplace(Region(-(ys2*(oversamp-1)/2),-(ys2*(oversamp-1)/2),ys,ys))
00744                 ratio1=mask1.get_attr("square_sum")/(ys*ys)     #/1.035
00745                 ratio2=mask2.get_attr("square_sum")/(ys*ys)
00746                 masks[(ys,radius)]=(mask1,ratio1,mask2,ratio2)
00747 
00748 
00749 
00750 */
00751 }
00752 
00753 void Axis0FourierProcessor::process_inplace(EMData * image)
00754 {
00755         EMData *fft;
00756         float *fftd;
00757         int f=0;
00758 //      static float sum1=0,sum1a=0;
00759 //      static double sum2=0,sum2a=0;
00760 
00761         if (!image) {
00762                 LOGWARN("NULL Image");
00763                 return;
00764         }
00765 
00766         if (!image->is_complex()) {
00767                 fft = image->do_fft();
00768                 fftd = fft->get_data();
00769                 f=1;
00770         }
00771         else {
00772                 fft=image;
00773                 fftd=image->get_data();
00774         }
00775 
00776         int nx=fft->get_xsize();
00777         int ny=fft->get_ysize();
00778         if (params.set_default("x",1)) {
00779                 for (int x=2; x<nx; x++) fftd[x]=0;
00780         }
00781         if (params.set_default("y",1)) {
00782                 for (int y=1; y<ny; y++) { fftd[y*nx]=0; fftd[y*nx+1]=0; }
00783         }
00784 
00785         if (f) {
00786                 fft->update();
00787                 EMData *ift=fft->do_ift();
00788                 memcpy(image->get_data(),ift->get_data(),(nx-2)*ny*sizeof(float));
00789                 delete fft;
00790                 delete ift;
00791         }
00792 
00793         image->update();
00794 
00795 }
00796 
00797 void AmpweightFourierProcessor::process_inplace(EMData * image)
00798 {
00799         EMData *fft;
00800         float *fftd;
00801         int f=0;
00802 //      static float sum1=0,sum1a=0;
00803 //      static double sum2=0,sum2a=0;
00804 
00805         if (!image) {
00806                 LOGWARN("NULL Image");
00807                 return;
00808         }
00809 
00810         if (!image->is_complex()) {
00811                 fft = image->do_fft();
00812                 fftd = fft->get_data();
00813                 f=1;
00814         }
00815         else {
00816                 fft=image;
00817                 fftd=image->get_data();
00818         }
00819         float *sumd = NULL;
00820         if (sum) sumd=sum->get_data();
00821 //printf("%d %d    %d %d\n",fft->get_xsize(),fft->get_ysize(),sum->get_xsize(),sum->get_ysize());
00822         size_t n = (size_t)fft->get_xsize()*fft->get_ysize()*fft->get_zsize();
00823         for (size_t i=0; i<n; i+=2) {
00824                 float c;
00825                 if (dosqrt) c=pow(fftd[i]*fftd[i]+fftd[i+1]*fftd[i+1],0.25f);
00826 #ifdef  _WIN32
00827                 else c = static_cast<float>(_hypot(fftd[i],fftd[i+1]));
00828 #else
00829                 else c = static_cast<float>(hypot(fftd[i],fftd[i+1]));
00830 #endif  //_WIN32
00831                 if (c==0) c=1.0e-30f;   // prevents divide by zero in normalization
00832                 fftd[i]*=c;
00833                 fftd[i+1]*=c;
00834                 if (sumd) { sumd[i]+=c; sumd[i+1]+=0; }
00835 
00836                 // debugging
00837 /*              if (i==290*1+12) {
00838                         sum1+=fftd[i];
00839                         sum2+=fftd[i];
00840                         printf("%f\t%f\t%f\t%f\t%f\t%f\n",sum1,sum2,fftd[i],fftd[i+1],sumd[i],c);
00841                 }
00842                 if (i==290*50+60) {
00843                         sum1a+=fftd[i];
00844                         sum2a+=fftd[i];
00845                         printf("%f\t%f\t%f\t%f\t%f\t%f\n",sum1a,sum2a,fftd[i],fftd[i+1],sumd[i],c);
00846         }*/
00847         }
00848 
00849         if (f) {
00850                 fft->update();
00851                 EMData *ift=fft->do_ift();
00852                 memcpy(image->get_data(),ift->get_data(),n*sizeof(float));
00853                 delete fft;
00854                 delete ift;
00855         }
00856 
00857         sum->update();
00858         image->update();
00859 
00860 }
00861 
00862 void DistanceSegmentProcessor::process_inplace(EMData *)
00863 {
00864         printf("Process inplace not implemented. Please use process.\n");
00865         return;
00866 }
00867 
00868 
00869 EMData *DistanceSegmentProcessor::process(const EMData * const image)
00870 {
00871         EMData * result = image->copy();
00872 
00873         float thr = params.set_default("thr",0.9f);
00874         float minsegsep = params.set_default("minsegsep",5.0f);
00875         float maxsegsep = params.set_default("maxsegsep",5.1f);
00876         int verbose = params.set_default("verbose",0);
00877 
00878         vector<Pixel> pixels=image->calc_highest_locations(thr);
00879 
00880         vector<float> centers(3);       // only 1 to start
00881         int nx=image->get_xsize();
00882         int ny=image->get_ysize();
00883         int nz=image->get_zsize();
00884 //      int nxy=nx*ny;
00885 
00886         // seed the process with the highest valued point
00887         centers[0]=(float)pixels[0].x;
00888         centers[1]=(float)pixels[0].y;
00889         centers[2]=(float)pixels[0].z;
00890         pixels.erase(pixels.begin());
00891 
00892         // outer loop. We add one center per iteration
00893         // This is NOT a very efficient algorithm, it assumes points are fairly sparse
00894         while (pixels.size()>0) {
00895                 // iterate over pixels until we find a new center (then stop), delete any 'bad' pixels
00896                 // no iterators because we remove elements
00897 
00898                 for (unsigned int i=0; i<pixels.size(); i++) {
00899 
00900                         Pixel p=pixels[i];
00901                         // iterate over existing centers to see if this pixel should be removed ... technically we only should need to check the last center
00902                         for (unsigned int j=0; j<centers.size(); j+=3) {
00903                                 float d=Util::hypot3(centers[j]-p.x,centers[j+1]-p.y,centers[j+2]-p.z);
00904                                 if (d<minsegsep) {              // conflicts with existing center, erase
00905                                         pixels.erase(pixels.begin()+i);
00906                                         i--;
00907                                         break;
00908                                 }
00909                         }
00910                 }
00911 
00912                 int found=0;
00913                 for (unsigned int i=0; i<pixels.size() && found==0; i++) {
00914                         Pixel p=pixels[i];
00915 
00916                         // iterate again to see if this may be a new valid center. Start at the end so we tend to build chains
00917                         for (unsigned int j=centers.size()-3; j>0; j-=3) {
00918                                 float d=Util::hypot3(centers[j]-p.x,centers[j+1]-p.y,centers[j+2]-p.z);
00919                                 if (d<maxsegsep) {              // we passed minsegsep question already, so we know we're in the 'good' range
00920                                         centers.push_back((float)p.x);
00921                                         centers.push_back((float)p.y);
00922                                         centers.push_back((float)p.z);
00923                                         pixels.erase(pixels.begin()+i); // in the centers list now, don't need it any more
00924                                         found=1;
00925                                         break;
00926                                 }
00927                         }
00928                 }
00929 
00930                 // If we went through the whole list and didn't find one, we need to reseed again
00931                 if (!found && pixels.size()) {
00932                         if (verbose) printf("New chain\n");
00933                         centers.push_back((float)pixels[0].x);
00934                         centers.push_back((float)pixels[0].y);
00935                         centers.push_back((float)pixels[0].z);
00936                         pixels.erase(pixels.begin());
00937                 }
00938 
00939                 if (verbose) printf("%d points found\n",(int)(centers.size()/3));
00940         }
00941 
00942         // after we have our list of centers classify pixels
00943         for (int z=0; z<nz; z++) {
00944                 for (int y=0; y<ny; y++) {
00945                         for (int x=0; x<nz; x++) {
00946                                 if (image->get_value_at(x,y,z)<thr) {
00947                                         result->set_value_at(x,y,z,-1.0);               //below threshold -> -1 (unclassified)
00948                                         continue;
00949                                 }
00950                                 int bcls=-1;                    // best matching class
00951                                 float bdist=(float)(nx+ny+nz);  // distance for best class
00952                                 for (unsigned int c=0; c<centers.size()/3; c++) {
00953                                         float d=Util::hypot3(x-centers[c*3],y-centers[c*3+1],z-centers[c*3+2]);
00954                                         if (d<bdist) { bdist=d; bcls=c; }
00955                                 }
00956                                 result->set_value_at(x,y,z,(float)bcls);                // set the pixel to the class number
00957                         }
00958                 }
00959         }
00960 
00961         result->set_attr("segment_centers",centers);
00962 
00963         return result;
00964 }
00965 
00966 EMData* ApplySymProcessor::process(const EMData * const image)
00967 {
00968         Averager* imgavg = Factory<Averager>::get((string)params.set_default("avger","mean"));
00969 
00970         if (image->get_zsize()==1) {
00971                 string s=(string)params["sym"];
00972                 if (s[0]!='c' && s[0]!='C') throw ImageDimensionException("xform.applysym: Cn symmetry required for 2-D symmetrization");
00973                 int n=atoi(s.c_str()+1);
00974                 if (n<=0) throw InvalidValueException(n,"xform.applysym: Cn symmetry, n>0");
00975 
00976                 for (int i=0; i<n; i++) {
00977                         Transform t(Dict("type","2d","alpha",(float)(i*360.0f/n)));
00978                         EMData* transformed = image->process("xform",Dict("transform",&t));
00979                         imgavg->add_image(transformed);
00980                         delete transformed;
00981                 }
00982                 EMData *ret=imgavg->finish();
00983                 delete imgavg;
00984                 return ret;
00985         }
00986 
00987         Symmetry3D* sym = Factory<Symmetry3D>::get((string)params.set_default("sym","c1"));
00988         vector<Transform> transforms = sym->get_syms();
00989 
00990         for(vector<Transform>::const_iterator trans_it = transforms.begin(); trans_it != transforms.end(); trans_it++) {
00991                 Transform t = *trans_it;
00992                 EMData* transformed = image->process("xform",Dict("transform",&t));
00993                 imgavg->add_image(transformed);
00994                 delete transformed;
00995         }
00996         EMData *ret=imgavg->finish();
00997         delete imgavg;
00998         return ret;
00999 }
01000 
01001 void ApplySymProcessor::process_inplace(EMData* image)
01002 {
01003         EMData *tmp=process(image);
01004         memcpy(image->get_data(),tmp->get_data(),(size_t)image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
01005         delete tmp;
01006         image->update();
01007         return;
01008 }
01009 
01010 EMData* KmeansSegmentProcessor::process(const EMData * const image)
01011 {
01012         EMData * result = image->copy();
01013 
01014         int nseg = params.set_default("nseg",12);       // Muyuan, you cannot make major changes to default values without thorough testing! I returned this to 12
01015         float thr = params.set_default("thr",-1.0e30f);
01016         int ampweight = params.set_default("ampweight",1);
01017         float maxsegsize = params.set_default("maxsegsize",10000.0f);
01018         float minsegsep = params.set_default("minsegsep",0.0f);
01019         int maxiter = params.set_default("maxiter",100);
01020         int maxvoxmove = params.set_default("maxvoxmove",25);
01021         int verbose = params.set_default("verbose",0);
01022         bool psudoatom = params.set_default("psudoatom",0);
01023         float sep = params.set_default("sep",3.78f);
01024 
01025         int nx=image->get_xsize();
01026         int ny=image->get_ysize();
01027         int nz=image->get_zsize();
01028 //      int nxy=nx*ny;
01029 
01030         // seed
01031         vector<float> centers(nseg*3);
01032         vector<float> count(nseg);
01033         // Alternative seeding method for paudoatom generation. Seed on the gird.
01034         if (psudoatom){
01035                 float ax=image->get_attr("apix_x");
01036                 sep/=ax;
01037                 if (verbose) printf("Seeding .....\n");
01038                 int sx=int(nx/sep)+1,sy=int(ny/sep)+1,sz=int(nz/sep)+1;
01039                 EMData m(sx,sy,sz);
01040                 EMData mcount(sx,sy,sz);
01041 
01042                 for (int i=0; i<nx; i++){
01043                         for (int j=0; j<ny; j++){
01044                                 for (int k=0; k<nz; k++){
01045                                         int ni=(i/sep),nj=(j/sep),nk=(k/sep);
01046                                         float v=image->get_value_at(i,j,k);
01047                                         if (v>thr){
01048                                                 m.set_value_at(ni,nj,nk,(m.get_value_at(ni,nj,nk)+v));
01049                                                 mcount.set_value_at(ni,nj,nk,(mcount.get_value_at(ni,nj,nk)+1));
01050                                         }
01051                                 }
01052                         }
01053                 }
01054                 int nsum=0;
01055                 float l=0,r=2000,th=5;
01056                 while (abs(nsum-nseg)>0){
01057                         th=(l+r)/2;
01058                         nsum=0;
01059                         for (int i=0; i<sx; i++){
01060                                 for (int j=0; j<sy; j++){
01061                                         for (int k=0; k<sz; k++){
01062                                                 if (m.get_value_at(i,j,k)>th)  nsum+=1;
01063                                         }
01064                                 }
01065                         }
01066                         if (verbose) printf("%3f\t %3f\t %3f,\t %4d\t %4d\n", l,th,r,nsum,nseg);
01067                         if (nsum>nseg) l=th;
01068                         if (nsum<nseg) r=th;
01069                         if ((r-l)<.01) break;
01070                 }
01071 //              nseg=nsum;
01072                 int q=0;
01073                 for (int i=0; i<sx; i++){
01074                         for (int j=0; j<sy; j++){
01075                                 for (int k=0; k<sz; k++){
01076                                         if (m.get_value_at(i,j,k)>th){
01077                                                 if(q<nseg*3){
01078                                                         centers[q]=  float(i+.5)*sep;
01079                                                         centers[q+1]=float(j+.5)*sep;
01080                                                         centers[q+2]=float(k+.5)*sep;
01081                                                         q+=3;
01082                                                 }
01083                                         }
01084                                 }
01085                         }
01086                 }
01087         }
01088         // Default: random seeding.
01089         else{
01090                 for (int i=0; i<nseg*3; i+=3) {
01091                         centers[i]=  Util::get_frand(0.0f,(float)nx);
01092                         centers[i+1]=Util::get_frand(0.0f,(float)ny);
01093                         centers[i+2]=Util::get_frand(0.0f,(float)nz);
01094                 }
01095         }
01096 
01097         for (int iter=0; iter<maxiter; iter++) {
01098                 // **** classify
01099                 size_t pixmov=0;                // count of moved pixels
01100                 for (int z=0; z<nz; z++) {
01101                         for (int y=0; y<ny; y++) {
01102                                 for (int x=0; x<nx; x++) {
01103                                         if (image->get_value_at(x,y,z)<thr) {
01104                                                 result->set_value_at(x,y,z,-1.0);               //below threshold -> -1 (unclassified)
01105                                                 continue;
01106                                         }
01107                                         int bcls=-1;                    // best matching class
01108                                         float bdist=(float)(nx+ny+nz);  // distance for best class
01109                                         for (int c=0; c<nseg; c++) {
01110                                                 float d=Util::hypot3(x-centers[c*3],y-centers[c*3+1],z-centers[c*3+2]);
01111                                                 if (d<bdist) { bdist=d; bcls=c; }
01112                                         }
01113                                         if ((int)result->get_value_at(x,y,z)!=bcls) pixmov++;
01114                                         if (bdist>maxsegsize) result->set_value_at(x,y,z,-1);           // pixel is too far from any center
01115                                         else result->set_value_at(x,y,z,(float)bcls);           // set the pixel to the class number
01116                                 }
01117                         }
01118                 }
01119 
01120                 // **** adjust centers
01121                 for (int i=0; i<nseg*3; i++) centers[i]=0;
01122                 for (int i=0; i<nseg; i++) count[i]=0;
01123                 // weighted sums
01124                 for (int z=0; z<nz; z++) {
01125                         for (int y=0; y<ny; y++) {
01126                                 for (int x=0; x<nx; x++) {
01127                                         int cls = (int)result->get_value_at(x,y,z);
01128                                         if (cls==-1) continue;
01129                                         float w=1.0;
01130                                         if (ampweight) w=image->get_value_at(x,y,z);
01131 
01132                                         centers[cls*3]+=x*w;
01133                                         centers[cls*3+1]+=y*w;
01134                                         centers[cls*3+2]+=z*w;
01135                                         count[cls]+=w;
01136                                 }
01137                         }
01138                 }
01139                 // now each becomes center of mass, or gets randomly reseeded
01140                 int nreseed=0;
01141                 for (int c=0; c<nseg; c++) {
01142                         // reseed
01143                         if (count[c]==0) {
01144                                 nreseed++;
01145                                 do {
01146                                         centers[c*3]=  Util::get_frand(0.0f,(float)nx);
01147                                         centers[c*3+1]=Util::get_frand(0.0f,(float)ny);
01148                                         centers[c*3+2]=Util::get_frand(0.0f,(float)nz);
01149                                 } while (image->get_value_at((int)centers[c*3],(int)centers[c*3+1],(int)centers[c*3+2])<thr);           // This makes sure the new point is inside density
01150                         }
01151                         // center of mass
01152                         else {
01153                                 centers[c*3]/=count[c];
01154                                 centers[c*3+1]/=count[c];
01155                                 centers[c*3+2]/=count[c];
01156                         }
01157                 }
01158 
01159                 // with minsegsep, check separation
01160                 if (minsegsep>0) {
01161                         for (int c1=0; c1<nseg-1; c1++) {
01162                                 for (int c2=c1+1; c2<nseg; c2++) {
01163                                         if (Util::hypot3(centers[c1*3]-centers[c2*3],centers[c1*3+1]-centers[c2*3+1],centers[c1*3+2]-centers[c2*3+2])<=minsegsep) {
01164                                                 nreseed++;
01165                                                 do {
01166                                                         centers[c1*3]=  Util::get_frand(0.0f,(float)nx);
01167                                                         centers[c1*3+1]=Util::get_frand(0.0f,(float)ny);
01168                                                         centers[c1*3+2]=Util::get_frand(0.0f,(float)nz);
01169                                                 } while (image->get_value_at((int)centers[c1*3],(int)centers[c1*3+1],(int)centers[c1*3+2])<thr);
01170                                         }
01171                                 }
01172                         }
01173                 }
01174 
01175 
01176                 if (verbose) printf("Iteration %3d: %6ld voxels moved, %3d classes reseeded\n",iter,pixmov,nreseed);
01177                 if (nreseed==0 && pixmov<(size_t)maxvoxmove) break;             // termination conditions met
01178         }
01179 
01180         result->set_attr("segment_centers",centers);
01181 
01182         return result;
01183 }
01184 
01185 void KmeansSegmentProcessor::process_inplace(EMData *)
01186 {
01187         printf("Process inplace not implemented. Please use process.\n");
01188         return;
01189 }
01190 
01191 
01192 void LinearPyramidProcessor::process_inplace(EMData *image) {
01193 
01194         if (image->get_zsize()!=1) { throw ImageDimensionException("Only 2-D images supported"); }
01195 
01196         float *d=image->get_data();
01197         int nx=image->get_xsize();
01198         int ny=image->get_ysize();
01199 
01200         for (int y=0; y<ny; y++) {
01201                 for (int x=0; x<nx; x++) {
01202                         int l=x+y*nx;
01203                         d[l]*=1.0f-abs(x-nx/2)*abs(y-ny/2)*4.0f/(nx*ny);
01204                 }
01205         }
01206         image->update();
01207 }
01208 
01209 EMData * Wiener2DAutoAreaProcessor::process(const EMData * image)
01210 {
01211 // TODO NOT IMPLEMENTED YET !!!
01212         EMData *ret = 0;
01213         const EMData *fft;
01214 //      float *fftd;
01215 //      int f=0;
01216 
01217         if (!image) {
01218                 LOGWARN("NULL Image");
01219                 return ret;
01220         }
01221         throw NullPointerException("Processor not yet implemented");
01222 
01223 //      if (!image->is_complex()) {
01224 //              fft = image->do_fft();
01225 //              fftd = fft->get_data();
01226 //              f=1;
01227 //      }
01228 //      else {
01229 //              fft=image;
01230 //              fftd=image->get_data();
01231 //      }
01232 
01233         return ret;
01234 }
01235 
01236 void Wiener2DAutoAreaProcessor::process_inplace(EMData *image) {
01237         EMData *tmp=process(image);
01238         memcpy(image->get_data(),tmp->get_data(),image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
01239         delete tmp;
01240         image->update();
01241         return;
01242 }
01243 
01244 
01245 EMData * Wiener2DFourierProcessor::process(const EMData *in)
01246 {
01247         const EMData *in2 = 0;
01248         if (in->is_complex()) in2=in;
01249         else in=in->do_fft();
01250 
01251         EMData *filt = in->copy_head();
01252         Ctf *ictf = ctf;
01253 
01254         if (!ictf) ctf=(Ctf *)in->get_attr("ctf");
01255 
01256         ictf->compute_2d_complex(filt,Ctf::CTF_WIENER_FILTER);
01257         filt->mult(*in2);
01258         EMData *ret=filt->do_ift();
01259 
01260         delete filt;
01261         if (!in->is_complex()) delete in2;
01262 
01263         if(!ictf && ctf) {delete ctf; ctf=0;}
01264         return(ret);
01265 /*      const EMData *fft;
01266         float *fftd;
01267         int f=0;
01268 
01269         if (!image) {
01270                 LOGWARN("NULL Image");
01271                 return ret;
01272         }
01273 
01274         if (!image->is_complex()) {
01275                 fft = image->do_fft();
01276                 fftd = fft->get_data();
01277                 f=1;
01278         }
01279         else {
01280                 fft=image;
01281                 fftd=image->get_data();
01282         }
01283         powd=image->get_data();
01284 
01285         int bad=0;
01286         for (int i=0; i<image->get_xsize()*image->get_ysize(); i+=2) {
01287                 snr=(fftd[i]*fftd[i]+fftd[i+1]*fftd[i+1]-powd[i])/powd[i];
01288                 if (snr<0) { bad++; snr=0; }
01289 
01290         }
01291 
01292         print("%d bad pixels\n",snr);
01293 */      return ret;
01294 
01295 }
01296 
01297 void Wiener2DFourierProcessor::process_inplace(EMData *image) {
01298         EMData *tmp=process(image);
01299         memcpy(image->get_data(),tmp->get_data(),image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
01300         delete tmp;
01301         image->update();
01302         return;
01303 }
01304 
01305 void LinearRampFourierProcessor::create_radial_func(vector < float >&radial_mask) const
01306 {
01307         Assert(radial_mask.size() > 0);
01308         for (size_t i = 0; i < radial_mask.size(); i++) {
01309                 radial_mask[i] = (float)i;
01310         }
01311 }
01312 
01313 void LowpassRandomPhaseProcessor::create_radial_func(vector < float >&radial_mask) const { };
01314 
01315 void LowpassRandomPhaseProcessor::process_inplace(EMData *image)
01316 {
01317         float cutoff=0;
01318         preprocess(image);
01319         if( params.has_key("cutoff_abs") ) {
01320                 cutoff=(float)params["cutoff_abs"];
01321         }
01322         else {
01323                 printf("A cutoff_* parameter is required by filter.lowpass.randomphase\n");
01324                 return;
01325         }
01326 
01327 
01328         if (image->get_zsize()==1) {
01329                 int flag=0;
01330                 if (!image->is_complex()) { image->do_fft_inplace(); flag=1; }
01331                 image->ri2ap();
01332                 int nx=image->get_xsize();
01333                 int ny=image->get_ysize();
01334 
01335                 int z=0;
01336                 float *data=image->get_data();
01337                 for (int y=-ny/2; y<ny/2; y++) {
01338                         for (int x=0; x<nx/2+1; x++) {
01339                                 if (hypot(x/float(nx),y/float(ny))>=cutoff) {
01340                                         size_t idx=image->get_complex_index_fast(x,y,z);                // location of the amplitude
01341                                         data[idx+1]=Util::get_frand(0.0f,(float)(M_PI*2.0));
01342                                 }
01343                         }
01344                 }
01345 
01346                 image->ap2ri();
01347 
01348                 if (flag) {
01349                         image->do_ift_inplace();
01350                         image->depad();
01351                 }
01352         }
01353         else {          // 3D
01354                 int flag=0;
01355                 if (!image->is_complex()) { image->do_fft_inplace(); flag=1; }
01356                 image->ri2ap();
01357                 int nx=image->get_xsize();
01358                 int ny=image->get_ysize();
01359                 int nz=image->get_zsize();
01360 
01361                 float *data=image->get_data();
01362                 for (int z=-nz/2; z<nz/2; z++) {
01363                         for (int y=-ny/2; y<ny/2; y++) {
01364                                 for (int x=0; x<nx/2; x++) {
01365                                         if (Util::hypot3(x/float(nx),y/float(ny),z/float(nz))>=cutoff) {
01366                                                 size_t idx=image->get_complex_index_fast(x,y,z);                // location of the amplitude
01367                                                 data[idx+1]=Util::get_frand(0.0f,(float)(M_PI*2.0));
01368                                         }
01369                                 }
01370                         }
01371                 }
01372                 image->ap2ri();
01373 
01374                 if (flag) {
01375                         image->do_ift_inplace();
01376                         image->depad();
01377                 }
01378         }
01379 }
01380 
01381 void HighpassAutoPeakProcessor::preprocess(EMData * image)
01382 {
01383         if(params.has_key("apix")) {
01384                 image->set_attr("apix_x", (float)params["apix"]);
01385                 image->set_attr("apix_y", (float)params["apix"]);
01386                 image->set_attr("apix_z", (float)params["apix"]);
01387         }
01388 
01389         const Dict dict = image->get_attr_dict();
01390 
01391         if( params.has_key("cutoff_abs") ) {
01392                 highpass = params["cutoff_abs"];
01393         }
01394         else if( params.has_key("cutoff_freq") ) {
01395                 highpass = (float)params["cutoff_freq"] * (float)dict["apix_x"] * (float)dict["nx"] / 2.0f;
01396         }
01397         else if( params.has_key("cutoff_pixels") ) {
01398                 highpass = (float)params["cutoff_pixels"] / (float)dict["nx"];
01399         }
01400 }
01401 
01402 void HighpassAutoPeakProcessor::create_radial_func(vector < float >&radial_mask, EMData *) const
01403 {
01404         unsigned int c;
01405 
01406 //      for (unsigned int i=0; i<radial_mask.size(); i++) printf("%d\t%f\n",i,radial_mask[i]);
01407         for (c=2; c<radial_mask.size(); c++) if (radial_mask[c-1]<=radial_mask[c]) break;
01408         if (c>highpass) c=(unsigned int)highpass;               // the *2 is for the 2x oversampling
01409 
01410         radial_mask[0]=0.0;
01411 //      for (int i=1; i<radial_mask.size(); i++) radial_mask[i]=(i<=c?radial_mask[c+1]/radial_mask[i]:1.0);
01412         for (unsigned int i=1; i<radial_mask.size(); i++) radial_mask[i]=(i<=c?0.0f:1.0f);
01413 
01414         printf("%f %d\n",highpass,c);
01415 //      for (unsigned int i=0; i<radial_mask.size(); i++) printf("%d\t%f\n",i,radial_mask[i]);
01416 
01417 }
01418 
01419 void LinearRampProcessor::create_radial_func(vector < float >&radial_mask) const
01420 {
01421         Assert(radial_mask.size() > 0);
01422         float x = 0.0f , step = 0.5f/radial_mask.size();
01423         size_t size=radial_mask.size();
01424         for (size_t i = 0; i < size; i++) {
01425                 radial_mask[i] = intercept + ((slope - intercept) * i) / (size - 1.0f);
01426                 x += step;
01427         }
01428 }
01429 
01430 void LoGFourierProcessor::create_radial_func(vector < float >&radial_mask) const
01431 {
01432 
01433         Assert(radial_mask.size() > 0);
01434         float x = 0.0f , nqstep = 0.5f/radial_mask.size();
01435         size_t size=radial_mask.size();
01436         float var = sigma*sigma;
01437         for (size_t i = 0; i < size; i++) {
01438                 radial_mask[i] = ((x*x - var)/var*var)*exp(-x*x/2*var);
01439                 x += nqstep;
01440         }
01441 }
01442 
01443 void DoGFourierProcessor::create_radial_func(vector < float >&radial_mask) const
01444 {
01445 
01446         Assert(radial_mask.size() > 0);
01447         float x = 0.0f , nqstep = 0.5f/radial_mask.size();
01448         size_t size=radial_mask.size();
01449         float norm = 1.0f/sqrt(2*M_PI);
01450         for (size_t i = 0; i < size; i++) {
01451                 radial_mask[i] = norm*((1.0f/sigma1*exp(-x*x/(2.0f*sigma1*sigma1))) - (1.0f/sigma2*exp(-x*x/(2.0f*sigma2*sigma2))));
01452                 x += nqstep;
01453         }
01454 }
01455 
01456 void RealPixelProcessor::process_inplace(EMData * image)
01457 {
01458         if (!image) {
01459                 LOGWARN("NULL Image");
01460                 return;
01461         }
01462 
01463         maxval = image->get_attr("maximum");
01464         mean = image->get_attr("mean");
01465         sigma = image->get_attr("sigma");
01466 
01467         calc_locals(image);
01468 
01469         size_t size = (size_t)image->get_xsize() *
01470                           (size_t)image->get_ysize() *
01471                           (size_t)image->get_zsize();
01472         float *data = image->get_data();
01473 
01474         for (size_t i = 0; i < size; ++i) {
01475                 process_pixel(&data[i]);
01476         }
01477         image->update();
01478 }
01479 
01480 void CoordinateProcessor::process_inplace(EMData * image)
01481 {
01482         if (!image) {
01483                 LOGWARN("NULL Image");
01484                 return;
01485         }
01486 
01487         maxval = image->get_attr("maximum");
01488         mean = image->get_attr("mean");
01489         sigma = image->get_attr("sigma");
01490         nx = image->get_xsize();
01491         ny = image->get_ysize();
01492         nz = image->get_zsize();
01493         is_complex = image->is_complex();
01494 
01495         calc_locals(image);
01496 
01497 
01498         if (!is_valid()) {
01499                 return;
01500         }
01501 
01502         float *data = image->get_data();
01503         size_t i = 0;
01504 
01505         for (int z = 0; z < nz; z++) {
01506                 for (int y = 0; y < ny; y++) {
01507                         for (int x = 0; x < nx; x++) {
01508                                 process_pixel(&data[i], x, y, z);
01509                                 ++i;
01510                         }
01511                 }
01512         }
01513         image->update();
01514 }
01515 
01516 void PaintProcessor::process_inplace(EMData *image) {
01517         int nx=image->get_xsize();
01518         int ny=image->get_ysize();
01519         int nz=image->get_zsize();
01520 
01521         if (nz==1) {
01522                 float r;
01523                 for (int j=(y<r2?0:y-r2); j<(y+r2>ny?ny:y+r2); j++) {
01524                         for (int i=(x<r2?0:x-r2); i<(x+r2>nx?nx:x+r2); i++) {
01525                                 r=sqrt(float(Util::square(i-x)+Util::square(j-y)));
01526                                 if (r>r2 && r>r1) continue;
01527                                 if (r>r1) image->set_value_at(i,j,0,v2*(r-r1)/(r2-r1)+v1*(r2-r)/(r2-r1));
01528                                 else image->set_value_at(i,j,0,v1);
01529                         }
01530                 }
01531         }
01532         else {
01533                 float r;
01534                 for (int k=(z<r2?0:z-r2); k<(z+r2>nz?nz:z+r2); k++) {
01535                         for (int j=(y<r2?0:y-r2); j<(y+r2>ny?ny:y+r2); j++) {
01536                                 for (int i=(x<r2?0:x-r2); i<(x+r2>nx?nx:x+r2); i++) {
01537                                 r=sqrt(float(Util::square(i-x)+Util::square(j-y)+Util::square(k-z)));
01538                                 if (r>r2 && r>r1) continue;
01539                                 if (r>r1) image->set_value_at(i,j,k,v2*(r-r1)/(r2-r1)+v1*(r2-r)/(r2-r1));
01540                                 else image->set_value_at(i,j,k,v1);
01541                                 }
01542                         }
01543                 }
01544         }
01545         image->update();
01546 }
01547 
01548 
01549 
01550 void CircularMaskProcessor::calc_locals(EMData *)
01551 {
01552         xc = Util::fast_floor(nx/2.0f) + dx;
01553         yc = Util::fast_floor(ny/2.0f) + dy;
01554         zc = Util::fast_floor(nz/2.0f) + dz;
01555 
01556         if (outer_radius < 0) {
01557                 outer_radius = nx / 2 + outer_radius +1;
01558                 outer_radius_square = outer_radius * outer_radius;
01559         }
01560 
01561         if (inner_radius <= 0) {
01562                 inner_radius_square = 0;
01563         }
01564 }
01565 
01566 
01567 void MaskEdgeMeanProcessor::calc_locals(EMData * image)
01568 {
01569         if (!image) {
01570                 throw NullPointerException("NULL image");
01571         }
01572         int nitems = 0;
01573         float sum = 0;
01574         float *data = image->get_data();
01575         size_t i = 0;
01576 
01577         xc = Util::fast_floor(nx/2.0f) + dx;
01578         yc = Util::fast_floor(ny/2.0f) + dy;
01579         zc = Util::fast_floor(nz/2.0f) + dz;
01580 
01581         for (int z = 0; z < nz; ++z) {
01582                 for (int y = 0; y < ny; ++y) {
01583                         for (int x = 0; x < nx; ++x) {
01584                                 float x1 = sqrt((x - xc) * (x - xc) + (y - yc) * (y - yc) + (z - zc) * (z - zc));
01585                                 if (x1 <= outer_radius + ring_width && x1 >= outer_radius - ring_width) {
01586                                         sum += data[i];
01587                                         ++nitems;
01588                                 }
01589                                 ++i;
01590                         }
01591                 }
01592         }
01593 
01594         ring_avg = sum / nitems;
01595 }
01596 
01597 void ToMinvalProcessor::process_inplace(EMData * image)
01598 {
01599         if (!image) {
01600                 LOGWARN("NULL Image");
01601                 return;
01602         }
01603 
01604         float minval = params.set_default("minval",0.0f);
01605         float newval = params.set_default("newval",minval);
01606 
01607         size_t size = (size_t)image->get_xsize() *
01608                           (size_t)image->get_ysize() *
01609                           (size_t)image->get_zsize();
01610         float *data = image->get_data();
01611 
01612 
01613 
01614         for (size_t i = 0; i < size; ++i) {
01615                 if (data[i]<minval) data[i]=newval;
01616         }
01617         image->update();
01618 }
01619 
01620 
01621 void ComplexPixelProcessor::process_inplace(EMData * image)
01622 {
01623         if (!image) {
01624                 LOGWARN("NULL image");
01625                 return;
01626         }
01627         if (!image->is_complex()) {
01628                 LOGWARN("cannot apply complex processor on a real image. Nothing is done.");
01629                 return;
01630         }
01631 
01632         size_t size = (size_t)image->get_xsize() *
01633                           (size_t)image->get_ysize() *
01634                           (size_t)image->get_zsize();
01635         float *data = image->get_data();
01636 
01637         image->ri2ap();
01638 
01639         for (size_t i = 0; i < size; i += 2) {
01640                 process_pixel(data);
01641                 data += 2;
01642         }
01643 
01644         image->update();
01645         image->ap2ri();
01646 }
01647 
01648 
01649 
01650 void AreaProcessor::process_inplace(EMData * image)
01651 {
01652         if (!image) {
01653                 LOGWARN("NULL Image");
01654                 return;
01655         }
01656 
01657         float *data = image->get_data();
01658 
01659         nx = image->get_xsize();
01660         ny = image->get_ysize();
01661         nz = image->get_zsize();
01662 
01663         int n = (areasize - 1) / 2;
01664         matrix_size = areasize * areasize;
01665 
01666         if (nz > 1) {
01667                 matrix_size *= areasize;
01668         }
01669 
01670         float *matrix = new float[matrix_size];
01671         kernel = new float[matrix_size];
01672 
01673         size_t cpysize = areasize * sizeof(float);
01674         size_t start = (nx * ny + nx + 1) * n;
01675 
01676         int xend = nx - n;
01677         int yend = ny - n;
01678 
01679         int zstart = n;
01680         int zend = nz - n;
01681 
01682         int zbox_start = 0;
01683         int zbox_end = areasize;
01684 
01685         if (nz == 1) {
01686                 zstart = 0;
01687                 zend = 1;
01688                 zbox_end = 1;
01689         }
01690 
01691         size_t nsec = (size_t)nx * (size_t)ny;
01692         int box_nsec = areasize * areasize;
01693 
01694         create_kernel();
01695 
01696         size_t total_size = (size_t)nx * (size_t)ny * (size_t)nz;
01697         float *data2 = new float[total_size];
01698         memcpy(data2, data, total_size * sizeof(float));
01699 
01700         size_t k;
01701         for (int z = zstart; z < zend; z++) {
01702                 for (int y = n; y < yend; y++) {
01703                         for (int x = n; x < xend; x++) {
01704 
01705                                 k = (size_t)z * nsec + y * nx + x;
01706 
01707                                 for (int bz = zbox_start; bz < zbox_end; bz++) {
01708                                         for (int by = 0; by < areasize; by++) {
01709                                                 memcpy(&matrix[(size_t)bz * box_nsec + by * areasize],
01710                                                            &data2[k - start + bz * nsec + by * nx], cpysize);
01711                                         }
01712                                 }
01713 
01714                                 process_pixel(&data[k], (float) x, (float) y, (float) z, matrix);
01715                         }
01716                 }
01717         }
01718 
01719         if( matrix )
01720         {
01721                 delete[]matrix;
01722                 matrix = 0;
01723         }
01724 
01725         if( kernel )
01726         {
01727                 delete[]kernel;
01728                 kernel = 0;
01729         }
01730         image->update();
01731 }
01732 
01733 
01734 void LaplacianProcessor::create_kernel() const
01735 {
01736         if (nz == 1) {
01737                 memset(kernel, 0, areasize * areasize);
01738                 kernel[1] = -0.25f;
01739                 kernel[3] = -0.25f;
01740                 kernel[5] = -0.25f;
01741                 kernel[7] = -0.25f;
01742                 kernel[4] = 1;
01743         }
01744         else {
01745                 memset(kernel, 0, (size_t)areasize * areasize * areasize);
01746                 kernel[4] = -1.0f / 6.0f;
01747                 kernel[10] = -1.0f / 6.0f;
01748                 kernel[12] = -1.0f / 6.0f;
01749                 kernel[14] = -1.0f / 6.0f;
01750                 kernel[16] = -1.0f / 6.0f;
01751                 kernel[22] = -1.0f / 6.0f;
01752                 kernel[13] = 1;
01753         }
01754 }
01755 
01756 void BoxStatProcessor::process_inplace(EMData * image)
01757 {
01758         if (!image) {
01759                 LOGWARN("NULL Image");
01760                 return;
01761         }
01762 
01763         int nx = image->get_xsize();
01764         int ny = image->get_ysize();
01765         int nz = image->get_zsize();
01766 
01767         int n = params.set_default("radius",1);
01768         int areasize = 2 * n + 1;
01769 
01770         int matrix_size = areasize * areasize;
01771         if (nz > 1) {
01772                 matrix_size *= areasize;
01773         }
01774 
01775         float *array = new float[matrix_size];
01776 //      image->process_inplace("normalize");
01777 
01778         float *data = image->get_data();
01779         size_t total_size = (size_t)nx * (size_t)ny * (size_t)nz;
01780         float *data2 = new float[total_size];
01781         memcpy(data2, data, total_size * sizeof(float));
01782 
01783         int z_begin = 0;
01784         int z_end = 1;
01785         int nzz=0;
01786         if (nz > 1) {
01787                 z_begin = n;
01788                 z_end = nz - n;
01789                 nzz=n;
01790         }
01791 
01792         int nxy = nx * ny;
01793 
01794         for (int k = z_begin; k < z_end; k++) {
01795                 size_t knxy = (size_t)k * nxy;
01796 
01797                 for (int j = n; j < ny - n; j++) {
01798                         int jnx = j * nx;
01799 
01800                         for (int i = n; i < nx - n; i++) {
01801                                 size_t s = 0;
01802 
01803                                 for (int i2 = i - n; i2 <= i + n; i2++) {
01804                                         for (int j2 = j - n; j2 <= j + n; j2++) {
01805                                                 for (int k2 = k - nzz; k2 <= k + nzz; k2++) {
01806                                                         array[s] = data2[i2 + j2 * nx + (size_t)k2 * nxy];
01807                                                         ++s;
01808                                                 }
01809                                         }
01810                                 }
01811 
01812                                 process_pixel(&data[i + jnx + knxy], array, matrix_size);
01813                         }
01814                 }
01815         }
01816 
01817         image->update();
01818 
01819         if( data2 )
01820         {
01821                 delete[]data2;
01822                 data2 = 0;
01823         }
01824 }
01825 
01826 void DiffBlockProcessor::process_inplace(EMData * image)
01827 {
01828         if (!image) {
01829                 LOGWARN("NULL Image");
01830                 return;
01831         }
01832 
01833         int nz = image->get_zsize();
01834 
01835         if (nz > 1) {
01836                 LOGERR("%s Processor doesn't support 3D", get_name().c_str());
01837                 throw ImageDimensionException("3D model not supported");
01838         }
01839 
01840         int nx = image->get_xsize();
01841         int ny = image->get_ysize();
01842 
01843         int v1 = params["cal_half_width"];
01844         int v2 = params["fill_half_width"];
01845 
01846         int v0 = v1 > v2 ? v1 : v2;
01847 
01848         if (v2 <= 0) {
01849                 v2 = v1;
01850         }
01851 
01852         float *data = image->get_data();
01853 
01854         for (int y = v0; y <= ny - v0 - 1; y += v2) {
01855                 for (int x = v0; x <= nx - v0 - 1; x += v2) {
01856 
01857                         float sum = 0;
01858                         for (int y1 = y - v1; y1 <= y + v1; y1++) {
01859                                 for (int x1 = x - v1; x1 <= x + v1; x1++) {
01860                                         sum += data[x1 + y1 * nx];
01861                                 }
01862                         }
01863                         float mean = sum / ((v1 * 2 + 1) * (v1 * 2 + 1));
01864 
01865                         for (int j = y - v2; j <= y + v2; j++) {
01866                                 for (int i = x - v2; i <= x + v2; i++) {
01867                                         data[i + j * nx] = mean;
01868                                 }
01869                         }
01870                 }
01871         }
01872 
01873         image->update();
01874 }
01875 
01876 
01877 void CutoffBlockProcessor::process_inplace(EMData * image)
01878 {
01879         if (!image) {
01880                 LOGWARN("NULL Image");
01881                 return;
01882         }
01883         int nz = image->get_zsize();
01884 
01885         if (nz > 1) {
01886                 LOGERR("%s Processor doesn't support 3D", get_name().c_str());
01887                 throw ImageDimensionException("3D model not supported");
01888         }
01889 
01890         int nx = image->get_xsize();
01891         int ny = image->get_ysize();
01892 
01893         float value1 = params["value1"];
01894         float value2 = params["value2"];
01895 
01896         int v1 = (int) value1;
01897         int v2 = (int) value2;
01898         if (v2 > v1 / 2) {
01899                 LOGERR("invalid value2 '%f' in CutoffBlockProcessor", value2);
01900                 return;
01901         }
01902 
01903         if (v2 <= 0) {
01904                 v2 = v1;
01905         }
01906 
01907         float *data = image->get_data();
01908         int y = 0, x = 0;
01909         for (y = 0; y <= ny - v1; y += v1) {
01910                 for (x = 0; x <= nx - v1; x += v1) {
01911 
01912                         EMData *clip = image->get_clip(Region(x, y, v1, v1));
01913                         EMData *fft = clip->do_fft();
01914 
01915                         float *fft_data = fft->get_data();
01916                         float sum = 0;
01917                         int nitems = 0;
01918 
01919                         for (int i = -v2; i < v2; i++) {
01920                                 for (int j = 0; j < v2; j++) {
01921                                         if (j == 0 && i == 0) {
01922                                                 continue;
01923                                         }
01924 
01925 #ifdef  _WIN32
01926                                         if (_hypot(j, i) < value2) {
01927 #else
01928                                         if (hypot(j, i) < value2) {
01929 #endif
01930                                                 int t = j * 2 + (i + v1 / 2) * (v1 + 2);
01931                                                 sum += (fft_data[t] * fft_data[t] + fft_data[t + 1] * fft_data[t + 1]);
01932                                                 nitems++;
01933                                         }
01934                                 }
01935                         }
01936 
01937                         if( clip )
01938                         {
01939                                 delete clip;
01940                                 clip = 0;
01941                         }
01942 
01943                         float mean = sum / nitems;
01944 
01945                         for (int i = y; i < y + v1; i++) {
01946                                 for (int j = x; j < x + v1; j++) {
01947                                         data[i * nx + j] = mean;
01948                                 }
01949                         }
01950                 }
01951         }
01952 
01953         memset(&data[y * nx], 0, (ny - y) * nx * sizeof(float));
01954 
01955         for (int i = 0; i < ny; i++) {
01956                 memset(&data[i * nx + x], 0, (nx - x) * sizeof(float));
01957         }
01958 
01959         image->update();
01960 }
01961 
01962 void MedianShrinkProcessor::process_inplace(EMData * image)
01963 {
01964         if (image->is_complex()) throw ImageFormatException("Error, the median shrink processor does not work on complex images");
01965 
01966         int shrink_factor =  params.set_default("n",0);
01967         if (shrink_factor <= 1) {
01968                 throw InvalidValueException(shrink_factor,
01969                                                                         "median shrink: shrink factor must > 1");
01970         }
01971 
01972         int nx = image->get_xsize();
01973         int ny = image->get_ysize();
01974         int nz = image->get_zsize();
01975 
01976 //      if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) || (nz > 1 && (nz % shrink_factor != 0))) {
01977 //              throw InvalidValueException(shrink_factor, "Image size not divisible by shrink factor");
01978 //      }
01979 
01980 
01981         int shrunken_nx = nx / shrink_factor;
01982         int shrunken_ny = ny / shrink_factor;
01983         int shrunken_nz = 1;
01984         if (nz > 1) shrunken_nz = nz / shrink_factor;
01985 
01986         EMData* copy = image->copy();
01987         image->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
01988         accrue_median(image,copy,shrink_factor);
01989         image->update();
01990         if( copy )
01991         {
01992                 delete copy;
01993                 copy = 0;
01994         }
01995 }
01996 
01997 //
01998 EMData* MedianShrinkProcessor::process(const EMData *const image)
01999 {
02000         if (image->is_complex()) throw ImageFormatException("Error, the median shrink processor does not work on complex images");
02001 
02002         int shrink_factor =  params.set_default("n",0);
02003         if (shrink_factor <= 1) {
02004                 throw InvalidValueException(shrink_factor,
02005                                                                         "median shrink: shrink factor must > 1");
02006         }
02007         int nx = image->get_xsize();
02008         int ny = image->get_ysize();
02009         int nz = image->get_zsize();
02010 
02011 
02012 //      if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) || (nz > 1 && (nz % shrink_factor != 0))) {
02013 //              throw InvalidValueException(shrink_factor, "Image size not divisible by shrink factor");
02014 //      }
02015 
02016 
02017         int shrunken_nx = nx / shrink_factor;
02018         int shrunken_ny = ny / shrink_factor;
02019         int shrunken_nz = 1;
02020         if (nz > 1) shrunken_nz = nz / shrink_factor;
02021 
02022 //      EMData* ret = new EMData(shrunken_nx, shrunken_ny, shrunken_nz);
02023         EMData *ret = image->copy_head();
02024         ret->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
02025 
02026         accrue_median(ret,image,shrink_factor);
02027         ret->update();
02028         return ret;
02029 }
02030 
02031 void MedianShrinkProcessor::accrue_median(EMData* to, const EMData* const from,const int shrink_factor)
02032 {
02033 
02034         int nx_old = from->get_xsize();
02035         int ny_old = from->get_ysize();
02036 
02037         int threed_shrink_factor = shrink_factor * shrink_factor;
02038         int z_shrink_factor = 1;
02039         if (from->get_zsize() > 1) {
02040                 threed_shrink_factor *= shrink_factor;
02041                 z_shrink_factor = shrink_factor;
02042         }
02043 
02044         float *mbuf = new float[threed_shrink_factor];
02045 
02046 
02047         int nxy_old = nx_old * ny_old;
02048 
02049         int nx = to->get_xsize();
02050         int ny = to->get_ysize();
02051         int nz = to->get_zsize();
02052         int nxy_new = nx * ny;
02053 
02054         float * rdata = to->get_data();
02055         const float *const data_copy = from->get_const_data();
02056 
02057         for (int l = 0; l < nz; l++) {
02058                 int l_min = l * shrink_factor;
02059                 int l_max = l * shrink_factor + z_shrink_factor;
02060                 size_t cur_l = (size_t)l * nxy_new;
02061 
02062                 for (int j = 0; j < ny; j++) {
02063                         int j_min = j * shrink_factor;
02064                         int j_max = (j + 1) * shrink_factor;
02065                         size_t cur_j = j * nx + cur_l;
02066 
02067                         for (int i = 0; i < nx; i++) {
02068                                 int i_min = i * shrink_factor;
02069                                 int i_max = (i + 1) * shrink_factor;
02070 
02071                                 size_t k = 0;
02072                                 for (int l2 = l_min; l2 < l_max; l2++) {
02073                                         size_t cur_l2 = l2 * nxy_old;
02074 
02075                                         for (int j2 = j_min; j2 < j_max; j2++) {
02076                                                 size_t cur_j2 = j2 * nx_old + cur_l2;
02077 
02078                                                 for (int i2 = i_min; i2 < i_max; i2++) {
02079                                                         mbuf[k] = data_copy[i2 + cur_j2];
02080                                                         ++k;
02081                                                 }
02082                                         }
02083                                 }
02084 
02085                                 for (k = 0; k < size_t(threed_shrink_factor / 2 + 1); k++) {
02086                                         for (int i2 = k + 1; i2 < threed_shrink_factor; i2++) {
02087                                                 if (mbuf[i2] < mbuf[k]) {
02088                                                         float f = mbuf[i2];
02089                                                         mbuf[i2] = mbuf[k];
02090                                                         mbuf[k] = f;
02091                                                 }
02092                                         }
02093                                 }
02094 
02095                                 rdata[i + cur_j] = mbuf[threed_shrink_factor / 2];
02096                         }
02097                 }
02098         }
02099 
02100         if( mbuf )
02101         {
02102                 delete[]mbuf;
02103                 mbuf = 0;
02104         }
02105 
02106         to->scale_pixel((float)shrink_factor);
02107 }
02108 
02109 EMData* FFTResampleProcessor::process(const EMData *const image)
02110 {
02111         float sample_rate = params.set_default("n",0.0f);
02112         if (sample_rate <= 0.0F  )  {
02113                 throw InvalidValueException(sample_rate,        "sample rate must be >0 ");
02114         }
02115 
02116         EMData* result;
02117         if (image->is_complex()) result = image->copy();
02118         else result = image->do_fft();
02119         fft_resample(result,image,sample_rate);
02120         // The image may have been padded - we should shift it so that the phase origin is where FFTW expects it
02121         result->update();
02122         result->scale_pixel(sample_rate);
02123         return result;
02124 }
02125 
02126 void FFTResampleProcessor::process_inplace(EMData * image)
02127 {
02128         if (image->is_complex()) throw ImageFormatException("Error, the fft resampling processor does not work on complex images");
02129 
02130 
02131         float sample_rate = params.set_default("n",0.0f);
02132         if (sample_rate <= 0.0F  )  {
02133                 throw InvalidValueException(sample_rate,        "sample rate (n) must be >0 ");
02134         }
02135 
02136         fft_resample(image,image,sample_rate);
02137 
02138         image->scale_pixel(sample_rate);
02139         image->update();
02140 
02141 
02142 }
02143 
02144 void FFTResampleProcessor::fft_resample(EMData* to, const EMData *const from, const float& sample_rate) {
02145         int nx = from->get_xsize();
02146         int ny = from->get_ysize();
02147         int nz = from->get_zsize();
02148 
02149         int new_nx = static_cast<int>( static_cast<float> (nx) / sample_rate);
02150         int new_ny = static_cast<int>( static_cast<float> (ny) / sample_rate);
02151         int new_nz = static_cast<int>( static_cast<float> (nz) / sample_rate);
02152 
02153         if (new_nx == 0) throw UnexpectedBehaviorException("The resample rate causes the pixel dimensions in the x direction to go to zero");
02154         if (new_ny == 0) new_ny = 1;
02155         if (new_nz == 0) new_nz = 1;
02156 
02157         int ndim = from->get_ndim();
02158         if ( ndim < 3 ) {
02159                 new_nz = 1;
02160         }
02161         if ( ndim < 2 ) {
02162                 new_ny = 1;
02163         }
02164 
02165         int fft_x_correction = 1;
02166         if (new_nx % 2 == 0) fft_x_correction = 2;
02167 
02168         int fft_y_correction = 0;
02169         if (ny != 1 && new_ny % 2 == 0 && ny % 2 == 1) fft_y_correction = 1;
02170         else if (ny != 1 && new_ny % 2 == 1 && ny % 2 == 0) fft_y_correction = -1;
02171 
02172         int fft_z_correction = 0;
02173         if (nz != 1 && new_nz % 2 == 0 && nz % 2 == 1) fft_z_correction = 1;
02174         else if (nz != 1 && new_nz % 2 == 1 && nz % 2 == 0) fft_z_correction = -1;
02175 
02176         if ( ! to->is_complex()) to->do_fft_inplace();
02177 
02178         if (ndim != 1) to->process_inplace("xform.fourierorigin.tocenter");
02179 
02180         Region clip(0,(ny-new_ny)/2-fft_y_correction,(nz-new_nz)/2-fft_z_correction,new_nx+fft_x_correction,new_ny,new_nz);
02181         to->clip_inplace(clip);
02182 
02183         if (fft_x_correction == 1) to->set_fftodd(true);
02184         else to->set_fftodd(false);
02185 
02186         if (ndim != 1) to->process_inplace("xform.fourierorigin.tocorner");
02187 
02188         to->do_ift_inplace();
02189         to->depad_corner();
02190 
02191 }
02192 
02193 
02194 EMData* MeanShrinkProcessor::process(const EMData *const image)
02195 {
02196         if (image->is_complex()) throw ImageFormatException("Error, the mean shrink processor does not work on complex images");
02197 
02198         if (image->get_ndim() == 1) { throw ImageDimensionException("Error, mean shrink works only for 2D & 3D images"); }
02199 
02200         float shrink_factor0 = params.set_default("n",0.0f);
02201         int shrink_factor = int(shrink_factor0);
02202         if (shrink_factor0 <= 1.0F || ((shrink_factor0 != shrink_factor) && (shrink_factor0 != 1.5F) ) ) {
02203                 throw InvalidValueException(shrink_factor0,
02204                                                                         "mean shrink: shrink factor must be >1 integer or 1.5");
02205         }
02206 
02207         int nx = image->get_xsize();
02208         int ny = image->get_ysize();
02209         int nz = image->get_zsize();
02210 
02211 
02212         // here handle the special averaging by 1.5 for 2D case
02213         if (shrink_factor0==1.5 ) {
02214                 if (nz > 1 ) throw InvalidValueException(shrink_factor0, "mean shrink: only support 2D images for shrink factor = 1.5");
02215 
02216                 int shrunken_nx = (int(nx / 1.5)+1)/2*2;        // make sure the output size is even
02217                 int shrunken_ny = (int(ny / 1.5)+1)/2*2;
02218                 EMData* result = new EMData(shrunken_nx,shrunken_ny,1);
02219 
02220                 accrue_mean_one_p_five(result,image);
02221                 result->update();
02222 
02223                 return result;
02224         }
02225 
02226         int shrunken_nx = nx / shrink_factor;
02227         int shrunken_ny = ny / shrink_factor;
02228         int shrunken_nz = 1;
02229 
02230         if (nz > 1) {
02231                 shrunken_nz = nz / shrink_factor;
02232         }
02233 
02234 //      EMData* result = new EMData(shrunken_nx,shrunken_ny,shrunken_nz);
02235         EMData* result = image->copy_head();
02236         result->set_size(shrunken_nx,shrunken_ny,shrunken_nz);
02237         accrue_mean(result,image,shrink_factor);
02238 
02239         result->update();
02240 
02241         return result;
02242 }
02243 
02244 void MeanShrinkProcessor::process_inplace(EMData * image)
02245 {
02246         if (image->is_complex()) throw ImageFormatException("Error, the mean shrink processor does not work on complex images");
02247 
02248         if (image->get_ndim() == 1) { throw ImageDimensionException("Error, mean shrink works only for 2D & 3D images"); }
02249 
02250         float shrink_factor0 = params.set_default("n",0.0f);
02251         int shrink_factor = int(shrink_factor0);
02252         if (shrink_factor0 <= 1.0F || ((shrink_factor0 != shrink_factor) && (shrink_factor0 != 1.5F) ) ) {
02253                 throw InvalidValueException(shrink_factor0,
02254                                                                         "mean shrink: shrink factor must be >1 integer or 1.5");
02255         }
02256 
02257 /*      if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) ||
02258         (nz > 1 && (nz % shrink_factor != 0))) {
02259         throw InvalidValueException(shrink_factor,
02260         "Image size not divisible by shrink factor");
02261 }*/
02262 
02263         int nx = image->get_xsize();
02264         int ny = image->get_ysize();
02265         int nz = image->get_zsize();
02266         // here handle the special averaging by 1.5 for 2D case
02267         if (shrink_factor0==1.5 ) {
02268                 if (nz > 1 ) throw InvalidValueException(shrink_factor0, "mean shrink: only support 2D images for shrink factor = 1.5");
02269 
02270                 int shrunken_nx = (int(nx / 1.5)+1)/2*2;        // make sure the output size is even
02271                 int shrunken_ny = (int(ny / 1.5)+1)/2*2;
02272 
02273                 EMData* orig = image->copy();
02274                 image->set_size(shrunken_nx, shrunken_ny, 1);   // now nx = shrunken_nx, ny = shrunken_ny
02275                 image->to_zero();
02276 
02277                 accrue_mean_one_p_five(image,orig);
02278 
02279                 if( orig ) {
02280                         delete orig;
02281                         orig = 0;
02282                 }
02283                 image->update();
02284 
02285                 return;
02286         }
02287 
02288         accrue_mean(image,image,shrink_factor);
02289 
02290         int shrunken_nx = nx / shrink_factor;
02291         int shrunken_ny = ny / shrink_factor;
02292         int shrunken_nz = 1;
02293         if (nz > 1) shrunken_nz = nz / shrink_factor;
02294 
02295         image->update();
02296         image->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
02297 }
02298 
02299 void MeanShrinkProcessor::accrue_mean(EMData* to, const EMData* const from,const int shrink_factor)
02300 {
02301         const float * const data = from->get_const_data();
02302         float* rdata = to->get_data();
02303 
02304         size_t nx = from->get_xsize();
02305         size_t ny = from->get_ysize();
02306         size_t nz = from->get_zsize();
02307         size_t nxy = nx*ny;
02308 
02309 
02310         size_t shrunken_nx = nx / shrink_factor;
02311         size_t shrunken_ny = ny / shrink_factor;
02312         size_t shrunken_nz = 1;
02313         size_t shrunken_nxy = shrunken_nx * shrunken_ny;
02314 
02315         int normalize_shrink_factor = shrink_factor * shrink_factor;
02316         int z_shrink_factor = 1;
02317 
02318         if (nz > 1) {
02319                 shrunken_nz = nz / shrink_factor;
02320                 normalize_shrink_factor *= shrink_factor;
02321                 z_shrink_factor = shrink_factor;
02322         }
02323 
02324         float invnormfactor = 1.0f/(float)normalize_shrink_factor;
02325 
02326         for (size_t k = 0; k < shrunken_nz; k++) {
02327                 size_t k_min = k * shrink_factor;
02328                 size_t k_max = k * shrink_factor + z_shrink_factor;
02329                 size_t cur_k = k * shrunken_nxy;
02330 
02331                 for (size_t j = 0; j < shrunken_ny; j++) {
02332                         size_t j_min = j * shrink_factor;
02333                         size_t j_max = j * shrink_factor + shrink_factor;
02334                         size_t cur_j = j * shrunken_nx + cur_k;
02335 
02336                         for (size_t i = 0; i < shrunken_nx; i++) {
02337                                 size_t i_min = i * shrink_factor;
02338                                 size_t i_max = i * shrink_factor + shrink_factor;
02339 
02340                                 float sum = 0;
02341                                 for (size_t kk = k_min; kk < k_max; kk++) {
02342                                         size_t cur_kk = kk * nxy;
02343 
02344                                         for (size_t jj = j_min; jj < j_max; jj++) {
02345                                                 size_t cur_jj = jj * nx + cur_kk;
02346                                                 for (size_t ii = i_min; ii < i_max; ii++) {
02347                                                         sum += data[ii + cur_jj];
02348                                                 }
02349                                         }
02350                                 }
02351                                 rdata[i + cur_j] = sum * invnormfactor;
02352                         }
02353                 }
02354         }
02355         to->scale_pixel((float)shrink_factor);
02356 }
02357 
02358 
02359 void MeanShrinkProcessor::accrue_mean_one_p_five(EMData* to, const EMData * const from)
02360 {
02361         int nx0 = from->get_xsize(), ny0 = from->get_ysize();   // the original size
02362 
02363         int nx = to->get_xsize(), ny = to->get_ysize();
02364 
02365         float *data = to->get_data();
02366         const float * const data0 = from->get_const_data();
02367 
02368         for (int j = 0; j < ny; j++) {
02369                 int jj = int(j * 1.5);
02370                 float jw0 = 1.0F, jw1 = 0.5F;   // 3x3 -> 2x2, so each new pixel should have 2.25 of the old pixels
02371                 if ( j%2 ) {
02372                         jw0 = 0.5F;
02373                         jw1 = 1.0F;
02374                 }
02375                 for (int i = 0; i < nx; i++) {
02376                         int ii = int(i * 1.5);
02377                         float iw0 = 1.0F, iw1 = 0.5F;
02378                         float w = 0.0F;
02379 
02380                         if ( i%2 ) {
02381                                 iw0 = 0.5F;
02382                                 iw1 = 1.0F;
02383                         }
02384                         if ( jj < ny0 ) {
02385                                 if ( ii < nx0 ) {
02386                                         data[j * nx + i] = data0[ jj * nx0 + ii ] * jw0 * iw0 ;
02387                                         w += jw0 * iw0 ;
02388                                         if ( ii+1 < nx0 ) {
02389                                                 data[j * nx + i] += data0[ jj * nx0 + ii + 1] * jw0 * iw1;
02390                                                 w += jw0 * iw1;
02391                                         }
02392                                 }
02393                                 if ( jj +1 < ny0 ) {
02394                                         if ( ii < nx0 ) {
02395                                                 data[j * nx + i] += data0[ (jj+1) * nx0 + ii ] * jw1 * iw0;
02396                                                 w += jw1 * iw0;
02397                                                 if ( ii+1 < nx0 ) {
02398                                                         data[j * nx + i] += data0[ (jj+1) * nx0 + ii + 1] * jw1 * iw1;
02399                                                         w += jw1 * iw1;
02400                                                 }
02401                                         }
02402                                 }
02403                         }
02404                         if ( w>0 ) data[j * nx + i] /= w;
02405                 }
02406         }
02407 
02408         to->update();
02409         to->scale_pixel((float)1.5);
02410 }
02411 
02412 // This would have to be moved into the header if it were required in other source files
02413 template<class LogicOp>
02414 EMData* BooleanShrinkProcessor::process(const EMData *const image, Dict& params)
02415 {
02416         // The basic idea of this code is to iterate through each pixel in the output image
02417         // determining its value by investigation a region of the input image
02418 
02419         if (!image) throw NullPointerException("Attempt to max shrink a null image");
02420 
02421         if (image->is_complex() ) throw ImageFormatException("Can not max shrink a complex image");
02422 
02423 
02424         int shrink = params.set_default("n",2);
02425         int search = params.set_default("search",2);
02426 
02427         if ( shrink < 0 ) throw InvalidValueException(shrink, "Can not shrink by a value less than 0");
02428 
02429 
02430         int nz = image->get_zsize();
02431         int ny = image->get_ysize();
02432         int nx = image->get_xsize();
02433 
02434         if (nx == 1 && ny == 1 && nz == 1 ) return image->copy();
02435 
02436         LogicOp op;
02437         EMData* return_image = new EMData();
02438 
02439         int shrinkx = shrink;
02440         int shrinky = shrink;
02441         int shrinkz = shrink;
02442 
02443         int searchx = search;
02444         int searchy = search;
02445         int searchz = search;
02446 
02447         // Clamping the shrink values to the dimension lengths
02448         // ensures that the return image has non zero dimensions
02449         if ( shrinkx > nx ) shrinkx = nx;
02450         if ( shrinky > ny ) shrinky = ny;
02451         if ( shrinkz > nz ) shrinkz = nz;
02452 
02453         if ( nz == 1 && ny == 1 )
02454         {
02455                 return_image->set_size(nx/shrinkx);
02456                 for(int i = 0; i < nx/shrinkx; ++i)
02457                 {
02458                         float tmp = op.get_start_val();
02459                         for(int s=0; s < searchx; ++s)
02460                         {
02461                                 int idx = shrinkx*i+s;
02462                                 // Don't ask for memory beyond limits
02463                                 if ( idx > nx ) break;
02464                                 else
02465                                 {
02466                                         float val = image->get_value_at(idx);
02467                                         if ( op( val,tmp) ) tmp = val;
02468                                 }
02469                         }
02470                         return_image->set_value_at(i,tmp);
02471                 }
02472         }
02473         else if ( nz == 1 )
02474         {
02475                 int ty = ny/shrinky;
02476                 int tx = nx/shrinkx;
02477                 return_image->set_size(tx,ty);
02478                 for(int y = 0; y < ty; ++y) {
02479                         for(int x = 0; x < tx; ++x) {
02480                                 float tmp = op.get_start_val();
02481                                 for(int sy=0; sy < searchy; ++sy) {
02482                                         int yidx = shrinky*y+sy;
02483                                         if ( yidx >= ny) break;
02484                                         for(int sx=0; sx < searchx; ++sx) {
02485                                                 int xidx = shrinkx*x+sx;
02486                                                 if ( xidx >= nx) break;
02487 
02488                                                 float val = image->get_value_at(xidx,yidx);
02489                                                 if ( op( val,tmp) ) tmp = val;
02490                                         }
02491                                 }
02492                                 return_image->set_value_at(x,y,tmp);
02493                         }
02494                 }
02495         }
02496         else
02497         {
02498                 int tz = nz/shrinkz;
02499                 int ty = ny/shrinky;
02500                 int tx = nx/shrinkx;
02501 
02502                 return_image->set_size(tx,ty,tz);
02503                 for(int z = 0; z < tz; ++z) {
02504                         for(int y = 0; y < ty; ++y) {
02505                                 for(int x = 0; x < tx; ++x) {
02506                                         float tmp = op.get_start_val();
02507 
02508                                         for(int sz=0; sz < searchz; ++sz) {
02509                                                 int zidx = shrinkz*z+sz;
02510                                                 if ( zidx >= nz) break;
02511 
02512                                                 for(int sy=0; sy < searchy; ++sy) {
02513                                                         int yidx = shrinky*y+sy;
02514                                                         if ( yidx >= ny) break;
02515 
02516                                                         for(int sx=0; sx < searchx; ++sx) {
02517                                                                 int xidx = shrinkx*x+sx;
02518                                                                 if ( xidx >= nx) break;
02519                                                                 float val = image->get_value_at(xidx,yidx,zidx);
02520                                                                 if ( op( val,tmp) ) tmp = val;
02521                                                         }
02522                                                 }
02523                                         }
02524                                         return_image->set_value_at(x,y,z,tmp);
02525                                 }
02526                         }
02527                 }
02528         }
02529         return_image->update();
02530 
02531         return return_image;
02532 }
02533 
02534 template<class LogicOp>
02535 void BooleanShrinkProcessor::process_inplace(EMData * image, Dict& params)
02536 {
02537         // The basic idea of this code is to iterate through each pixel in the output image
02538         // determining its value by investigation a region of the input image
02539         if (!image) throw NullPointerException("Attempt to max shrink a null image");
02540 
02541         if (image->is_complex() ) throw ImageFormatException("Can not max shrink a complex image");
02542 
02543 
02544         int shrink = params.set_default("shrink",2);
02545         int search = params.set_default("search",2);
02546 
02547         if ( shrink < 0 ) throw InvalidValueException(shrink, "Can not shrink by a value less than 0");
02548 
02549 
02550         int nz = image->get_zsize();
02551         int ny = image->get_ysize();
02552         int nx = image->get_xsize();
02553 
02554         LogicOp op;
02555 
02556         int shrinkx = shrink;
02557         int shrinky = shrink;
02558         int shrinkz = shrink;
02559 
02560         int searchx = search;
02561         int searchy = search;
02562         int searchz = search;
02563 
02564         // Clamping the shrink values to the dimension lengths
02565         // ensures that the return image has non zero dimensions
02566         if ( shrinkx > nx ) shrinkx = nx;
02567         if ( shrinky > ny ) shrinkx = ny;
02568         if ( shrinkz > nz ) shrinkx = nz;
02569 
02570         if (nx == 1 && ny == 1 && nz == 1 ) return;
02571 
02572         if ( nz == 1 && ny == 1 )
02573         {
02574                 for(int i = 0; i < nx/shrink; ++i)
02575                 {
02576                         float tmp = op.get_start_val();
02577                         for(int s=0; s < searchx; ++s)
02578                         {
02579                                 int idx = shrinkx*i+s;
02580                                 if ( idx > nx ) break;
02581                                 else
02582                                 {
02583                                         float val = image->get_value_at(idx);
02584                                         if ( op( val,tmp) ) tmp = val;
02585                                 }
02586                         }
02587                         image->set_value_at(i,tmp);
02588                 }
02589 
02590                 image->set_size(nx/shrinkx);
02591         }
02592         else if ( nz == 1 )
02593         {
02594                 int ty = ny/shrinky;
02595                 int tx = nx/shrinkx;
02596                 for(int y = 0; y < ty; ++y) {
02597                         for(int x = 0; x < tx; ++x) {
02598                                 float tmp = op.get_start_val();
02599                                 for(int sy=0; sy < searchy; ++sy) {
02600                                         int yidx = shrinky*y+sy;
02601                                         if ( yidx >= ny) break;
02602                                         for(int sx=0; sx < searchx; ++sx) {
02603                                                 int xidx = shrinkx*x+sx;
02604                                                 if ( xidx >= nx) break;
02605 
02606                                                 float val = image->get_value_at(xidx,yidx);
02607                                                 if ( op( val,tmp) ) tmp = val;
02608                                         }
02609                                 }
02610                                 (*image)(x+tx*y) = tmp;
02611                         }
02612                 }
02613                 image->set_size(tx,ty);
02614         }
02615         else
02616         {
02617                 int tnxy = nx/shrinkx*ny/shrinky;
02618                 int tz = nz/shrinkz;
02619                 int ty = ny/shrinky;
02620                 int tx = nx/shrinkx;
02621 
02622                 for(int z = 0; z < tz; ++z) {
02623                         for(int y = 0; y < ty; ++y) {
02624                                 for(int x = 0; x < tx; ++x) {
02625                                         float tmp = op.get_start_val();
02626                                         for(int sz=0; sz < searchz; ++sz) {
02627                                                 int zidx = shrinkz*z+sz;
02628                                                 if ( zidx >= nz) break;
02629                                                 for(int sy=0; sy < searchy; ++sy) {
02630                                                         int yidx = shrinky*y+sy;
02631                                                         if ( yidx >= ny) break;
02632                                                         for(int sx=0; sx < shrinkx; ++sx) {
02633                                                                 int xidx = shrinkx*x+sx;
02634                                                                 if ( xidx >= nx) break;
02635 
02636                                                                 float val = image->get_value_at(xidx,yidx,zidx);
02637                                                                 if ( op( val,tmp) ) tmp = val;
02638                                                         }
02639                                                 }
02640                                         }
02641                                         (*image)(x+tx*y+tnxy*z) = tmp;
02642                                 }
02643                         }
02644                 }
02645                 image->set_size(tx,ty,tz);
02646         }
02647         image->update();
02648 }
02649 
02650 
02651 
02652 void GradientRemoverProcessor::process_inplace(EMData * image)
02653 {
02654         if (!image) {
02655                 LOGWARN("NULL Image");
02656                 return;
02657         }
02658 
02659         int nz = image->get_zsize();
02660         if (nz > 1) {
02661                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
02662                 throw ImageDimensionException("3D model not supported");
02663         }
02664 
02665         int nx = image->get_xsize();
02666         int ny = image->get_ysize();
02667         float *dy = new float[ny];
02668         float m = 0;
02669         float b = 0;
02670         float sum_y = 0;
02671         float *data = image->get_data();
02672 
02673         for (int i = 0; i < ny; i++) {
02674                 Util::calc_least_square_fit(nx, 0, data + i * nx, &m, &b, false);
02675                 dy[i] = b;
02676                 sum_y += m;
02677         }
02678 
02679         float mean_y = sum_y / ny;
02680         float sum_x = 0;
02681         Util::calc_least_square_fit(ny, 0, dy, &sum_x, &b, false);
02682 
02683         for (int j = 0; j < ny; j++) {
02684                 for (int i = 0; i < nx; i++) {
02685                         data[i + j * nx] -= i * sum_x + j * mean_y + b;
02686                 }
02687         }
02688 
02689         image->update();
02690 }
02691 
02692 void FlattenBackgroundProcessor::process_inplace(EMData * image)
02693 {
02694 
02695         EMData* mask = params.set_default("mask",(EMData*)0);
02696         int radius = params.set_default("radius",0);
02697 
02698         if (radius != 0 && mask != 0) throw InvalidParameterException("Error - the mask and radius parameters are mutually exclusive.");
02699 
02700         if (mask == 0 && radius == 0) throw InvalidParameterException("Error - you must specify either the mask or the radius parameter.");
02701 
02702         // If the radius isn't 0, then turn the mask into the thing we want...
02703         bool deletemask = false;
02704         if (radius != 0) {
02705                 mask = new EMData;
02706                 int n = image->get_ndim();
02707                 if (n==1){
02708                         mask->set_size(2*radius+1);
02709                 } else if (n==2) {
02710                         mask->set_size(2*radius+1,2*radius+1);
02711                 }
02712                 else /*n==3*/ {
02713                         mask->set_size(2*radius+1,2*radius+1,2*radius+1);
02714                 }
02715                 // assuming default behavior is to make a circle/sphere with using the radius of the mask
02716                 mask->process_inplace("testimage.circlesphere");
02717         }
02718 
02719         // Double check that that mask isn't too big
02720         int mnx = mask->get_xsize(); int mny = mask->get_ysize(); int mnz = mask->get_zsize();
02721         int nx = image->get_xsize(); int ny = image->get_ysize(); int nz = image->get_zsize();
02722         int nxc = nx+mnx; int nyc = ny+mny; int nzc = nz+mnz;
02723         if (nz == 1) nzc = 1; // Sanity check
02724         if (ny == 1) nyc = 1; // Sanity check
02725 
02726         if ( mnx > nx || mny > ny || mnz > nz)
02727                 throw ImageDimensionException("Can not flatten using a mask that is larger than the image.");
02728 
02729         // Get the normalization factor
02730         float normfac = 0.0;
02731         for (int i=0; i<mask->get_xsize()*mask->get_ysize()*mask->get_zsize(); ++i){
02732                 normfac += mask->get_value_at(i);
02733         }
02734         // If the sum is zero the user probably doesn't understand that determining a measure of the mean requires
02735         // strictly positive numbers. The user has specified a mask that consists entirely of zeros, or the mask
02736         // has a mean of zero.
02737         if (normfac == 0) throw InvalidParameterException("Error - the pixels in the mask sum to zero. This breaks the flattening procedure");
02738         normfac = 1.0f/normfac;
02739 
02740         // The mask can now be automatically resized to the dimensions of the image
02741 //      bool undoclip = false;
02742 
02743         Region r;
02744         if (ny == 1) r = Region((mnx-nxc)/2,nxc);
02745         else if (nz == 1) r = Region((mnx-nxc)/2, (mny-nyc)/2,nxc,nyc);
02746         else r = Region((mnx-nxc)/2, (mny-nyc)/2,(mnz-nzc)/2,nxc,nyc,nzc);
02747         mask->clip_inplace(r,0);
02748 //      undoclip = true;
02749 //      if ( mnx < nx || mny < ny || mnz < nz) {
02750 //              Region r((mnx-nx)/2, (mny-ny)/2,(mnz-nz)/2,nx,ny,nz);
02751 //              mask->clip_inplace(r);
02752 //              undoclip = true;
02753 //      }
02754 
02755         Region r2;
02756         if (ny == 1) r2 = Region((nx-nxc)/2,nxc);
02757         else if (nz == 1) r2 = Region((nx-nxc)/2, (ny-nyc)/2,nxc,nyc);
02758         else r2 = Region((nx-nxc)/2, (ny-nyc)/2,(nz-nzc)/2,nxc,nyc,nzc);
02759         image->clip_inplace(r2,image->get_edge_mean());
02760         // Finally do the convolution
02761         EMData* m = image->convolute(mask);
02762         // Normalize so that m is truly the local mean
02763         m->mult(normfac);
02764         // Before we can subtract, the mean must be phase shifted
02765         m->process_inplace("xform.phaseorigin.tocenter");
02766         // Subtract the local mean
02767 //      image->write_image("a.mrc");
02768 //      m->write_image("b.mrc");
02769         image->sub(*m); // WE'RE DONE!
02770         delete m;
02771 
02772         if (deletemask) {
02773                 delete mask;
02774         } else { // I clipped it inplace, so undo this clipping so the user gets back what the put in
02775                 Region r;
02776                 if (ny == 1) r = Region((nxc-mnx)/2,mnx);
02777                 else if (nz == 1) r = Region((nxc-mnx)/2, (nyc-mny)/2,mnx,mny);
02778                 else r = Region((nxc-mnx)/2, (nyc-mny)/2,(nzc-mnz)/2,mnx,mny,mnz);
02779                 mask->clip_inplace(r);
02780         }
02781 
02782         Region r3;
02783         if (ny == 1) r3 = Region((nxc-nx)/2,nx);
02784         else if (nz == 1) r3 = Region((nxc-nx)/2, (nyc-ny)/2,nx,ny);
02785         else r3 = Region((nxc-nx)/2, (nyc-ny)/2,(nzc-nz)/2,nx,ny,nz);
02786         image->clip_inplace(r3);
02787 //      if ( undoclip ) {
02788 //              Region r((nx-mnx)/2, (ny-mny)/2, (nz-mnz)/2,mnx,mny,mnz);
02789 //              mask->clip_inplace(r);
02790 //      }
02791 
02792 }
02793 
02794 void NonConvexProcessor::process_inplace(EMData * image) {
02795         if (!image) { LOGWARN("NULL IMAGE"); return; }
02796         //int isinten=image->get_attr_default("is_intensity",0);
02797 
02798         // 1-D
02799         if (image->get_ysize()==1) {
02800 
02801         }
02802         // 2-D
02803         else if (image->get_zsize()==1) {
02804 //              if (!isinten) throw ImageDimensionException("Only complex intensity images currently supported by NonConvexProcessor");
02805                 int nx2=image->get_xsize()/2;
02806                 int ny2=image->get_ysize()/2;
02807                 vector<float> rdist = image->calc_radial_dist(nx2*1.5,0,1,false);               // radial distribution to make sure nonconvex values decrease radially
02808                 // Make sure rdist is decreasing (or flat)
02809                 for (int i=1; i<nx2; i++) {
02810                         if (rdist[i]>rdist[i-1]) rdist[i]=rdist[i-1];
02811                 }
02812 
02813                 image->process_inplace("xform.fourierorigin.tocenter");
02814                 EMData* binary=image->copy();
02815 
02816                 // First we eliminate convex points from the input image (set to zero)
02817                 for (int x=0; x<image->get_xsize(); x+=2) {
02818                         for (int y=1; y<image->get_ysize()-1; y++) {
02819                                 int r=(int)hypot((float)(x/2),(float)(y-ny2));
02820                                 float cen=(*binary)(x,y);
02821                                 if (x==0 || x==nx2*2-2 || (cen>(*binary)(x+2,y) || cen>(*binary)(x-2,y) || cen>(*binary)(x,y+1) || cen >(*binary)(x,y-1) || (*binary)(x,y)>rdist[r])) {         // point is considered nonconvex if lower than surrounding values and lower than mean
02822                                         image->set_value_at_fast(x/2+nx2,y,0.0);        // we are turning image into a full real-space intensity image for now
02823                                         image->set_value_at_fast(nx2-x/2,ny2*2-y-1,0.0);
02824                                 }
02825                                 else {
02826                                         image->set_value_at_fast(x/2+nx2,y,cen);        // we are turning image into a full real-space intensity image for now
02827                                         image->set_value_at_fast(nx2-x/2,ny2*2-y-1,cen);        // It will contain non-zero values only for nonconvex points
02828                                 }
02829                         }
02830                 }
02831                 image->set_value_at_fast(nx2+1,ny2,(*binary)(2,ny2));   // We keep the points near the Fourier origin as a central anchor even though it's convex
02832                 image->set_value_at_fast(nx2-1,ny2,(*binary)(2,ny2));   // We keep the points near the Fourier origin as a central anchor even though it's convex
02833                 image->set_value_at_fast(nx2,ny2+1,(*binary)(0,ny2+1)); // We keep the points near the Fourier origin as a central anchor even though it's convex
02834                 image->set_value_at_fast(nx2,ny2-1,(*binary)(0,ny2-1)); // We keep the points near the Fourier origin as a central anchor even though it's convex
02835                 for (int y=0; y<ny2*2; y++) image->set_value_at_fast(0,y,0.0f);
02836 
02837                 // Now make a binary version of the convex points
02838                 float *idat=image->get_data();
02839                 float *bdat=binary->get_data();
02840                 int nxy=(nx2*ny2*4);
02841                 for (int i=0; i<nxy; i++) {
02842                         bdat[i]=idat[i]==0?0:1.0f;              // binary version of the convex points in image
02843                 }
02844                 binary->update();
02845 
02846                 // We now use a Gaussian filter on both images, to use Gaussian interpolation to fill in zero values
02847                 image->set_complex(false);              // so we can use a Gaussian filter on it
02848                 binary->set_complex(false);
02849 
02850 /*              image->write_image("con.hdf",0);*/
02851                 image->set_fftpad(false);
02852                 binary->set_fftpad(false);
02853 
02854                 // Gaussian blur of both images
02855                 image->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs",0.04f));
02856                 binary->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs",0.04f));
02857 
02858 /*              image->write_image("con.hdf",1);
02859                 binary->write_image("con.hdf",2);*/
02860 
02861                 for (int x=0; x<image->get_xsize(); x+=2) {
02862                         for (int y=0; y<image->get_ysize(); y++) {
02863                                 float bv=binary->get_value_at(x/2+nx2,y);
02864                                 image->set_value_at_fast(x,y,image->get_value_at(x/2+nx2,y)/(bv<=0?1.0f:bv));
02865                                 image->set_value_at_fast(x+1,y,0.0);
02866                         }
02867                 }
02868                 image->set_complex(true);
02869                 image->set_fftpad(true);
02870                 image->process_inplace("xform.fourierorigin.tocorner");
02871                 delete binary;
02872         }
02873         else throw ImageDimensionException("3D maps not yet supported by NonConvexProcessor");
02874 
02875 }
02876 
02877 
02878 #include <gsl/gsl_linalg.h>
02879 void GradientPlaneRemoverProcessor::process_inplace(EMData * image)
02880 {
02881         if (!image) {
02882                 LOGWARN("NULL Image");
02883                 return;
02884         }
02885 
02886         int nz = image->get_zsize();
02887         if (nz > 1) {
02888                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
02889                 throw ImageDimensionException("3D map not supported");
02890         }
02891 
02892         int nx = image->get_xsize();
02893         int ny = image->get_ysize();
02894         float *d = image->get_data();
02895         EMData *mask = 0;
02896         float *dm = 0;
02897         if (params.has_key("mask")) {
02898                 mask = params["mask"];
02899                 if (nx!=mask->get_xsize() || ny!=mask->get_ysize()) {
02900                         LOGERR("%s Processor requires same size mask image", get_name().c_str());
02901                         throw ImageDimensionException("wrong size mask image");
02902                 }
02903                 dm = mask->get_data();
02904         }
02905         int count = 0;
02906         if (dm) {
02907                 for(int i=0; i<nx*ny; i++) {
02908                         if(dm[i]) count++;
02909                 }
02910         }
02911         else {
02912                 count = nx * ny;
02913         }
02914         if(count<3) {
02915                 LOGERR("%s Processor requires at least 3 pixels to fit a plane", get_name().c_str());
02916                 throw ImageDimensionException("too few usable pixels to fit a plane");
02917         }
02918         // Allocate the working space
02919         gsl_vector *S=gsl_vector_calloc(3);
02920         gsl_matrix *A=gsl_matrix_calloc(count,3);
02921         gsl_matrix *V=gsl_matrix_calloc(3,3);
02922 
02923         double m[3] = {0, 0, 0};
02924         int index=0;
02925         if (dm) {
02926                 for(int j=0; j<ny; j++){
02927                         for(int i=0; i<nx; i++){
02928                                 int ij=j*nx+i;
02929                                 if(dm[ij]) {
02930                                         m[0]+=i;        // x
02931                                         m[1]+=j;        // y
02932                                         m[2]+=d[ij];    // z
02933                                         /*printf("index=%d/%d\ti,j=%d,%d\tval=%g\txm,ym,zm=%g,%g,%g\n", \
02934                                                 index,count,i,j,d[ij],m[0]/(index+1),m[1]/(index+1),m[2]/(index+1));*/
02935                                         index++;
02936                                 }
02937                         }
02938                 }
02939         }
02940         else {
02941                 for(int j=0; j<ny; j++){
02942                         for(int i=0; i<nx; i++){
02943                                 int ij=j*nx+i;
02944                                         m[0]+=i;        // x
02945                                         m[1]+=j;        // y
02946                                         m[2]+=d[ij];    // z
02947                                         /*printf("index=%d/%d\ti,j=%d,%d\tval=%g\txm,ym,zm=%g,%g,%g\n", \
02948                                                 index,count,i,j,d[ij],m[0]/(index+1),m[1]/(index+1),m[2]/(index+1));*/
02949                                         index++;
02950                         }
02951                 }
02952         }
02953 
02954         for(int i=0; i<3; i++) m[i]/=count;     // compute center of the plane
02955 
02956         index=0;
02957         if (dm) {
02958                 for(int j=0; j<ny; j++){
02959                         for(int i=0; i<nx; i++){
02960                                 int ij=j*nx+i;
02961                                 if(dm[ij]) {
02962                                         //printf("index=%d/%d\ti,j=%d,%d\tval=%g\n",index,count,i,j,d[index]);
02963                                         gsl_matrix_set(A,index,0,i-m[0]);
02964                                         gsl_matrix_set(A,index,1,j-m[1]);
02965                                         gsl_matrix_set(A,index,2,d[ij]-m[2]);
02966                                         index++;
02967                                 }
02968                         }
02969                 }
02970                 mask->update();
02971         }
02972         else {
02973                 for(int j=0; j<ny; j++){
02974                         for(int i=0; i<nx; i++){
02975                                 int ij=j*nx+i;
02976                                         //printf("index=%d/%d\ti,j=%d,%d\tval=%g\n",index,count,i,j,d[index]);
02977                                         gsl_matrix_set(A,index,0,i-m[0]);
02978                                         gsl_matrix_set(A,index,1,j-m[1]);
02979                                         gsl_matrix_set(A,index,2,d[ij]-m[2]);
02980                                         index++;
02981                         }
02982                 }
02983         }
02984 
02985         // SVD decomposition and use the V vector associated with smallest singular value as the plan normal
02986         gsl_linalg_SV_decomp_jacobi(A, V, S);
02987 
02988         double n[3];
02989         for(int i=0; i<3; i++) n[i] = gsl_matrix_get(V, i, 2);
02990 
02991         #ifdef DEBUG
02992         printf("S=%g,%g,%g\n",gsl_vector_get(S,0), gsl_vector_get(S,1), gsl_vector_get(S,2));
02993         printf("V[0,:]=%g,%g,%g\n",gsl_matrix_get(V,0,0), gsl_matrix_get(V,0,1),gsl_matrix_get(V,0,2));
02994         printf("V[1,:]=%g,%g,%g\n",gsl_matrix_get(V,1,0), gsl_matrix_get(V,1,1),gsl_matrix_get(V,1,2));
02995         printf("V[2,:]=%g,%g,%g\n",gsl_matrix_get(V,2,0), gsl_matrix_get(V,2,1),gsl_matrix_get(V,2,2));
02996         printf("Fitted plane: p0=%g,%g,%g\tn=%g,%g,%g\n",m[0],m[1],m[2],n[0],n[1],n[2]);
02997         #endif
02998 
02999         int changeZero = 0;
03000         if (params.has_key("changeZero")) changeZero = params["changeZero"];
03001         if (changeZero) {
03002                 for(int j=0; j<nx; j++){
03003                         for(int i=0; i<ny; i++){
03004                                 int ij = j*nx+i;
03005                                 d[ij]-=static_cast<float>(-((i-m[0])*n[0]+(j-m[1])*n[1])/n[2]+m[2]);
03006                         }
03007                 }
03008         }
03009         else {
03010                 for(int j=0; j<nx; j++){
03011                         for(int i=0; i<ny; i++){
03012                                 int ij = j*nx+i;
03013                                 if(d[ij]) d[ij]-=static_cast<float>(-((i-m[0])*n[0]+(j-m[1])*n[1])/n[2]+m[2]);
03014                         }
03015                 }
03016         }
03017         image->update();
03018         // set return plane parameters
03019         vector< float > planeParam;
03020         planeParam.resize(6);
03021         for(int i=0; i<3; i++) planeParam[i] = static_cast<float>(n[i]);
03022         for(int i=0; i<3; i++) planeParam[i+3] = static_cast<float>(m[i]);
03023         params["planeParam"]=EMObject(planeParam);
03024 }
03025 
03026 void VerticalStripeProcessor::process_inplace(EMData * image)
03027 {
03028         if (!image) {
03029                 LOGWARN("NULL Image");
03030                 return;
03031         }
03032 
03033         int nx = image->get_xsize();
03034         int ny = image->get_ysize();
03035         int nz = image->get_zsize();
03036 
03037         float *data = image->get_data();
03038         float sigma = image->get_attr("sigma");
03039 
03040         for (int k = 0; k < nz; k++) {
03041                 for (int i = 0; i < nx; i++) {
03042                         double sum = 0;
03043                         for (int j = ny / 4; j < 3 * ny / 4; j++) {
03044                                 sum += data[i + j * nx];
03045                         }
03046 
03047                         float mean = (float)sum / (ny / 2);
03048                         for (int j = 0; j < ny; j++) {
03049                                 data[i + j * nx] = (data[i + j * nx] - mean) / sigma;
03050                         }
03051                 }
03052         }
03053 
03054         image->update();
03055 }
03056 
03057 void RealToFFTProcessor::process_inplace(EMData *image)
03058 {
03059         if (!image) {
03060                 LOGWARN("NULL Image");
03061                 return;
03062         }
03063 
03064         //Note : real image only!
03065         if(image->is_complex()) {
03066                 LOGERR("%s Processor only operates on real images", get_name().c_str());
03067                 throw ImageFormatException("apply to real image only");
03068         }
03069 
03070         // Note : 2D only!
03071         int nz = image->get_zsize();
03072         if (nz > 1) {
03073                 LOGERR("%s Processor doesn't support 3D models", get_name().c_str());
03074                 throw ImageDimensionException("3D model not supported");
03075         }
03076 
03077         EMData *ff=image->do_fft();
03078         ff->ri2ap();
03079 
03080         int nx=image->get_xsize();
03081         int ny=image->get_ysize();
03082 
03083         int x,y;
03084         float norm=static_cast<float>(nx*ny);
03085 
03086         for (y=0; y<ny; y++) image->set_value_at(0,y,0);
03087 
03088         for (x=1; x<nx/2; x++) {
03089                 for (y=0; y<ny; y++) {
03090                         int y2;
03091                         if (y<ny/2) y2=y+ny/2;
03092                         else if (y==ny/2) y2=ny;
03093                         else y2=y-ny/2;
03094                         image->set_value_at(x,y,ff->get_value_at(nx-x*2,ny-y2)/norm);
03095                 }
03096         }
03097 
03098         for (x=nx/2; x<nx; x++) {
03099                 for (y=0; y<ny; y++) {
03100                         int y2;
03101                         if (y<ny/2) y2=y+ny/2;
03102                         else y2=y-ny/2;
03103                         image->set_value_at(x,y,ff->get_value_at(x*2-nx,y2)/norm);
03104                 }
03105         }
03106 
03107         image->update();
03108         if( ff )
03109         {
03110                 delete ff;
03111                 ff = 0;
03112         }
03113 }
03114 
03115 void SigmaZeroEdgeProcessor::process_inplace(EMData * image)
03116 {
03117         if (!image) {
03118                 LOGWARN("NULL Image");
03119                 return;
03120         }
03121 
03122         if (image->get_zsize() > 1) {
03123                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
03124                 throw ImageDimensionException("3D model not supported");
03125         }
03126 
03127         float nonzero = params.set_default("nonzero",false);
03128 
03129         float *d = image->get_data();
03130         int i = 0;
03131         int j = 0;
03132 
03133         int nx = image->get_xsize();
03134         int ny = image->get_ysize();
03135 
03136         float zval=9.99e23f;            // we're assuming we won't run into this exact value for an edge, not great programming, but good enough
03137         if (nonzero) {
03138                 int x,y;
03139                 size_t corn=nx*ny-1;
03140 
03141                 // this set of 4 tests looks for any edges with exactly the same value
03142                 for (x=1; x<nx; x++) { if (d[x]!=d[0]) break;}
03143                 if (x==nx) zval=d[0];
03144 
03145                 for (y=1; y<ny; y++) { if (d[y*nx]!=d[0]) break; }
03146                 if (y==ny) zval=d[0];
03147 
03148                 for (x=1; x<nx; x++) { if (d[corn-x]!=d[corn]) break;}
03149                 if (x==nx) zval=d[corn];
03150 
03151                 for (y=1; y<ny; y++) { if (d[corn-y*nx]!=d[corn]) break; }
03152                 if (y==ny) zval=d[corn];
03153 
03154                 if (zval!=9.99e23f) { image->set_attr("hadzeroedge",1); printf("zeroedge %f\n",zval); }
03155                 else image->set_attr("hadzeroedge",0);
03156 
03157                 // This tries to detect images where the edges have been filled with the nearest non-zero value. The filter does nothing, but we set the tag.
03158                 for (x=nx/2-5; x<nx/2+5; x++) {
03159                         if (d[x]!=d[x+nx] || d[x]!=d[x+nx*2] ) break;
03160                 }
03161                 if (x==nx/2+5) image->set_attr("hadzeroedge",2);
03162 
03163                 for (x=nx/2-5; x<nx/2+5; x++) {
03164                         if (d[corn-x]!=d[corn-x-nx] || d[corn-x]!=d[corn-x-nx*2]) break;
03165                 }
03166                 if (x==nx/2+5) image->set_attr("hadzeroedge",2);
03167 
03168                 for (y=ny/2-5; y<ny/2+5; y++) {
03169                         if (d[y*nx]!=d[y*nx+1] || d[y*nx]!=d[y*nx+2] ) break;
03170                 }
03171                 if (y==ny/2+5) image->set_attr("hadzeroedge",2);
03172 
03173                 for (y=ny/2-5; y<ny/2+5; y++) {
03174                         if (d[corn-y*nx]!=d[corn-y*nx-1] || d[corn-y*nx]!=d[corn-y*nx-2]) break;
03175                 }
03176                 if (y==ny/2+5) image->set_attr("hadzeroedge",2);
03177 
03178         }
03179         if (zval==9.99e23f) zval=0;
03180 
03181         for (j = 0; j < ny; j++) {
03182                 for (i = 0; i < nx - 1; i++) {
03183                         if (d[i + j * nx] != zval) {
03184                                 break;
03185                         }
03186                 }
03187 
03188                 float v = d[i + j * nx];
03189                 while (i >= 0) {
03190                         d[i + j * nx] = v;
03191                         i--;
03192                 }
03193 
03194                 for (i = nx - 1; i > 0; i--) {
03195                         if (d[i + j * nx] != zval)
03196                                 break;
03197                 }
03198                 v = d[i + j * nx];
03199                 while (i < nx) {
03200                         d[i + j * nx] = v;
03201                         i++;
03202                 }
03203         }
03204 
03205         for (i = 0; i < nx; i++) {
03206                 for (j = 0; j < ny; j++) {
03207                         if (d[i + j * nx] != zval)
03208                                 break;
03209                 }
03210 
03211                 float v = d[i + j * nx];
03212                 while (j >= 0) {
03213                         d[i + j * nx] = v;
03214                         j--;
03215                 }
03216 
03217                 for (j = ny - 1; j > 0; j--) {
03218                         if (d[i + j * nx] != zval)
03219                                 break;
03220                 }
03221                 v = d[i + j * nx];
03222                 while (j < ny) {
03223                         d[i + j * nx] = v;
03224                         j++;
03225                 }
03226         }
03227 
03228 
03229         image->update();
03230 }
03231 
03232 
03233 
03234 void BeamstopProcessor::process_inplace(EMData * image)
03235 {
03236         if (!image) {
03237                 LOGWARN("NULL Image");
03238                 return;
03239         }
03240         if (image->get_zsize() > 1) {
03241                 LOGERR("BeamstopProcessor doesn't support 3D model");
03242                 throw ImageDimensionException("3D model not supported");
03243         }
03244 
03245         float value1 = params["value1"];
03246         float value2 = params["value2"];
03247         float value3 = params["value3"];
03248 
03249         float thr = fabs(value1);
03250         float *data = image->get_data();
03251         int cenx = (int) value2;
03252         int ceny = (int) value3;
03253 
03254         int nx = image->get_xsize();
03255         int ny = image->get_ysize();
03256 
03257         if (cenx <= 0) {
03258                 cenx = nx / 2;
03259         }
03260 
03261         if (ceny <= 0) {
03262                 ceny = ny / 2;
03263         }
03264 
03265         int mxr = (int) floor(sqrt(2.0f) * nx / 2);
03266 
03267         float *mean_values = new float[mxr];
03268         float *sigma_values = new float[mxr];
03269         double sum = 0;
03270         int count = 0;
03271         double square_sum = 0;
03272 
03273         for (int i = 0; i < mxr; i++) {
03274                 sum = 0;
03275                 count = 0;
03276                 square_sum = 0;
03277                 int nitems = 6 * i + 2;
03278 
03279                 for (int j = 0; j < nitems; j++) {
03280                         float ang = j * 2 * M_PI / nitems;
03281                         int x0 = (int) floor(cos(ang) * i + cenx);
03282                         int y0 = (int) floor(sin(ang) * i + ceny);
03283 
03284                         if (x0 < 0 || y0 < 0 || x0 >= nx || y0 >= ny) {
03285                                 continue;
03286                         }
03287 
03288                         float f = data[x0 + y0 * nx];
03289                         sum += f;
03290                         square_sum += f * f;
03291                         count++;
03292                 }
03293 
03294                 mean_values[i] = (float)sum / count;
03295                 sigma_values[i] = (float) sqrt(square_sum / count - mean_values[i] * mean_values[i]);
03296         }
03297 
03298 
03299         for (int k = 0; k < 5; k++) {
03300                 for (int i = 0; i < mxr; i++) {
03301                         sum = 0;
03302                         count = 0;
03303                         square_sum = 0;
03304                         int nitems = 6 * i + 2;
03305                         double thr1 = mean_values[i] - sigma_values[i] * thr;
03306                         double thr2 = mean_values[i] + sigma_values[i];
03307 
03308                         for (int j = 0; j < nitems; j++) {
03309                                 float ang = j * 2 * M_PI / nitems;
03310                                 int x0 = (int) floor(cos(ang) * i + cenx);
03311                                 int y0 = (int) floor(sin(ang) * i + ceny);
03312 
03313                                 if (x0 < 0 || y0 < 0 || x0 >= nx || y0 >= ny ||
03314                                         data[x0 + y0 * nx] < thr1 || data[x0 + y0 * nx] > thr2) {
03315                                         continue;
03316                                 }
03317 
03318                                 sum += data[x0 + y0 * nx];
03319                                 square_sum += data[x0 + y0 * nx] * data[x0 + y0 * nx];
03320                                 count++;
03321                         }
03322 
03323                         mean_values[i] = (float) sum / count;
03324                         sigma_values[i] = (float) sqrt(square_sum / count - mean_values[i] * mean_values[i]);
03325                 }
03326         }
03327 
03328         for (int i = 0; i < nx; i++) {
03329                 for (int j = 0; j < ny; j++) {
03330 
03331 #ifdef  _WIN32
03332                         int r = Util::round(_hypot((float) i - cenx, (float) j - ceny));
03333 #else
03334                         int r = Util::round(hypot((float) i - cenx, (float) j - ceny));
03335 #endif  //_WIN32
03336 
03337                         if (value1 < 0) {
03338                                 if (data[i + j * nx] < (mean_values[r] - sigma_values[r] * thr)) {
03339                                         data[i + j * nx] = 0;
03340                                 }
03341                                 else {
03342                                         data[i + j * nx] -= mean_values[r];
03343                                 }
03344                                 continue;
03345                         }
03346                         if (data[i + j * nx] > (mean_values[r] - sigma_values[r] * thr)) {
03347                                 continue;
03348                         }
03349                         data[i + j * nx] = mean_values[r];
03350                 }
03351         }
03352 
03353         if( mean_values )
03354         {
03355                 delete[]mean_values;
03356                 mean_values = 0;
03357         }
03358 
03359         if( sigma_values )
03360         {
03361                 delete[]sigma_values;
03362                 sigma_values = 0;
03363         }
03364 
03365         image->update();
03366 }
03367 
03368 
03369 
03370 void MeanZeroEdgeProcessor::process_inplace(EMData * image)
03371 {
03372         if (!image) {
03373                 LOGWARN("NULL Image");
03374                 return;
03375         }
03376         if (image->get_zsize() > 1) {
03377                 LOGERR("MeanZeroEdgeProcessor doesn't support 3D model");
03378                 throw ImageDimensionException("3D model not supported");
03379         }
03380 
03381         int nx = image->get_xsize();
03382         int ny = image->get_ysize();
03383         Dict dict = image->get_attr_dict();
03384         float mean_nonzero = dict.get("mean_nonzero");
03385 
03386         float *d = image->get_data();
03387         int i = 0;
03388         int j = 0;
03389 
03390         for (j = 0; j < ny; j++) {
03391                 for (i = 0; i < nx - 1; i++) {
03392                         if (d[i + j * nx] != 0) {
03393                                 break;
03394                         }
03395                 }
03396 
03397                 if (i == nx - 1) {
03398                         i = -1;
03399                 }
03400 
03401                 float v = d[i + j * nx] - mean_nonzero;
03402 
03403                 while (i >= 0) {
03404                         v *= 0.9f;
03405                         d[i + j * nx] = v + mean_nonzero;
03406                         i--;
03407                 }
03408 
03409 
03410                 for (i = nx - 1; i > 0; i--) {
03411                         if (d[i + j * nx] != 0) {
03412                                 break;
03413                         }
03414                 }
03415 
03416                 if (i == 0) {
03417                         i = nx;
03418                 }
03419 
03420                 v = d[i + j * nx] - mean_nonzero;
03421 
03422                 while (i < nx) {
03423                         v *= .9f;
03424                         d[i + j * nx] = v + mean_nonzero;
03425                         i++;
03426                 }
03427         }
03428 
03429 
03430         for (i = 0; i < nx; i++) {
03431                 for (j = 0; j < ny; j++) {
03432                         if (d[i + j * nx] != 0)
03433                                 break;
03434                 }
03435 
03436                 float v = d[i + j * nx] - mean_nonzero;
03437 
03438                 while (j >= 0) {
03439                         v *= .9f;
03440                         d[i + j * nx] = v + mean_nonzero;
03441                         j--;
03442                 }
03443 
03444                 for (j = ny - 1; j > 0; j--) {
03445                         if (d[i + j * nx] != 0)
03446                                 break;
03447                 }
03448 
03449                 v = d[i + j * nx] - mean_nonzero;
03450 
03451                 while (j < ny) {
03452                         v *= .9f;
03453                         d[i + j * nx] = v + mean_nonzero;
03454                         j++;
03455                 }
03456         }
03457 
03458         image->update();
03459 }
03460 
03461 
03462 
03463 void AverageXProcessor::process_inplace(EMData * image)
03464 {
03465         if (!image) {
03466                 LOGWARN("NULL Image");
03467                 return;
03468         }
03469 
03470         float *data = image->get_data();
03471         int nx = image->get_xsize();
03472         int ny = image->get_ysize();
03473         int nz = image->get_zsize();
03474         size_t nxy = (size_t)nx * ny;
03475 
03476         size_t idx;
03477         for (int z = 0; z < nz; z++) {
03478                 for (int x = 0; x < nx; x++) {
03479                         double sum = 0;
03480                         for (int y = 0; y < ny; y++) {
03481                                 idx = x + y * nx + z * nxy;
03482                                 sum += data[idx];
03483                         }
03484                         float mean = (float) sum / ny;
03485 
03486                         for (int y = 0; y < ny; y++) {
03487                                 idx = x + y * nx + z * nxy;
03488                                 data[idx] = mean;
03489                         }
03490                 }
03491         }
03492 
03493         image->update();
03494 }
03495 
03496 void DecayEdgeProcessor::process_inplace(EMData * image)
03497 {
03498         if (!image) {
03499                 LOGWARN("NULL Image");
03500                 return;
03501         }
03502 
03503         if (image->get_zsize() > 1) throw ImageDimensionException("3D model not supported");
03504 
03505         int nx = image->get_xsize();
03506         int ny = image->get_ysize();
03507 
03508         float *d = image->get_data();
03509         int width = params["width"];
03510 
03511         for (int i=0; i<width; i++) {
03512                 float frac=i/(float)width;
03513                 for (int j=0; j<nx; j++) {
03514                         d[j+i*nx]*=frac;
03515                         d[nx*ny-j-i*nx-1]*=frac;
03516                 }
03517                 for (int j=0; j<ny; j++) {
03518                         d[j*nx+i]*=frac;
03519                         d[nx*ny-j*nx-i-1]*=frac;
03520                 }
03521         }
03522 
03523         image->update();
03524 }
03525 
03526 void ZeroEdgeRowProcessor::process_inplace(EMData * image)
03527 {
03528         if (!image) {
03529                 LOGWARN("NULL Image");
03530                 return;
03531         }
03532 
03533         if (image->get_zsize() > 1) {
03534                 LOGERR("ZeroEdgeRowProcessor is not supported in 3D models");
03535                 throw ImageDimensionException("3D model not supported");
03536         }
03537 
03538         int nx = image->get_xsize();
03539         int ny = image->get_ysize();
03540 
03541         float *d = image->get_data();
03542         int top_nrows = params["y0"];
03543         int bottom_nrows = params["y1"];
03544 
03545         int left_ncols = params["x0"];
03546         int right_ncols = params["x1"];
03547 
03548         size_t row_size = nx * sizeof(float);
03549 
03550         memset(d, 0, top_nrows * row_size);
03551         memset(d + (ny - bottom_nrows) * nx, 0, bottom_nrows * row_size);
03552 
03553         for (int i = top_nrows; i < ny - bottom_nrows; i++) {
03554                 memset(d + i * nx, 0, left_ncols * sizeof(float));
03555                 memset(d + i * nx + nx - right_ncols, 0, right_ncols * sizeof(float));
03556         }
03557         image->update();
03558 }
03559 
03560 void ZeroEdgePlaneProcessor::process_inplace(EMData * image)
03561 {
03562         if (!image) {
03563                 LOGWARN("NULL Image");
03564                 return;
03565         }
03566 
03567         if (image->get_zsize() <= 1) {
03568                 LOGERR("ZeroEdgePlaneProcessor only support 3D models");
03569                 throw ImageDimensionException("3D model only");
03570         }
03571 
03572         int nx = image->get_xsize();
03573         int ny = image->get_ysize();
03574         int nz = image->get_zsize();
03575 
03576         float *d = image->get_data();
03577 
03578         int x0=params["x0"];
03579         int x1=params["x1"];
03580         int y0=params["y0"];
03581         int y1=params["y1"];
03582         int z0=params["z0"];
03583         int z1=params["z1"];
03584 
03585         size_t row_size = nx * sizeof(float);
03586         size_t nxy = nx * ny;
03587         size_t sec_size = nxy * sizeof(float);
03588         size_t y0row = y0 * row_size;
03589         size_t y1row = y1 * row_size;
03590         int max_y = ny-y1;
03591         size_t x0size = x0*sizeof(float);
03592         size_t x1size = x1*sizeof(float);
03593 
03594         memset(d,0,z0*sec_size);                                        // zero -z
03595         memset(d+(nxy*(nz-z1)),0,sec_size*z1);      // zero +z
03596 
03597         for (int z=z0; z<nz-z1; z++) {
03598                 memset(d+z*nxy,0,y0row);                        // zero -y
03599                 memset(d+z*nxy+(ny-y1)*nx,0,y1row);     // zero +y
03600 
03601                 int znxy = z * nxy;
03602                 int znxy2 = znxy + nx - x1;
03603 
03604                 for (int y=y0; y<max_y; y++) {
03605                         memset(d+znxy+y*nx,0,x0size);   // zero -x
03606                         memset(d+znxy2+y*nx,0,x1size);  // zero +x
03607                 }
03608         }
03609 
03610         image->update();
03611 }
03612 
03613 
03614 float NormalizeProcessor::calc_sigma(EMData * image) const
03615 {
03616         return image->get_attr("sigma");
03617 }
03618 
03619 void NormalizeProcessor::process_inplace(EMData * image)
03620 {
03621         if (!image) {
03622                 LOGWARN("cannot do normalization on NULL image");
03623                 return;
03624         }
03625 
03626         if (image->is_complex()) {
03627                 LOGWARN("cannot do normalization on complex image");
03628                 return;
03629         }
03630 
03631         float sigma = calc_sigma(image);
03632         if (sigma == 0 || !Util::goodf(&sigma)) {
03633                 LOGWARN("cannot do normalization on image with sigma = 0");
03634                 return;
03635         }
03636 
03637         float mean = calc_mean(image);
03638 
03639         size_t size = (size_t)image->get_xsize() * image->get_ysize() * image->get_zsize();
03640         float *data = image->get_data();
03641 
03642         for (size_t i = 0; i < size; ++i) {
03643                 data[i] = (data[i] - mean) / sigma;
03644         }
03645 
03646         image->update();
03647 }
03648 
03649 float NormalizeUnitProcessor::calc_sigma(EMData * image) const
03650 {
03651         if (!image) {
03652                 LOGWARN("NULL Image");
03653                 return 0;
03654         }
03655         float ret=sqrt((float)image->get_attr("square_sum"));
03656         return ret==0.0f?1.0f:ret;
03657 }
03658 
03659 float NormalizeUnitSumProcessor::calc_sigma(EMData * image) const
03660 {
03661         if (!image) {
03662                 LOGWARN("NULL Image");
03663                 return 0;
03664         }
03665         float ret=(float)image->get_attr("mean")*image->get_xsize()*image->get_ysize()*image->get_zsize();
03666         return ret==0.0f?1.0f:ret;
03667 }
03668 
03669 float NormalizeMaskProcessor::calc_sigma(EMData * image) const
03670 {
03671         if (!image) {
03672                 LOGWARN("NULL Image");
03673                 return 0;
03674         }
03675         EMData *mask = params["mask"];
03676         int no_sigma = params["no_sigma"];
03677 
03678         if(no_sigma == 0) {
03679                 return 1;
03680         }
03681         else {
03682                 if (!EMUtil::is_same_size(mask, image)) {
03683                         LOGERR("normalize.maskProcessor: mask and image must be the same size");
03684                         throw ImageDimensionException("mask and image must be the same size");
03685                 }
03686 
03687                 float *data = image->get_data();
03688                 float *mask_data = mask->get_data();
03689                 size_t size = (size_t)image->get_xsize() * image->get_ysize() * image->get_zsize();
03690                 double sum = 0;
03691                 double sq2 = 0;
03692                 size_t n_norm = 0;
03693 
03694                 for (size_t i = 0; i < size; ++i) {
03695                         if (mask_data[i] > 0.5f) {
03696                                 sum += data[i];
03697                                 sq2 += data[i]*double (data[i]);
03698                                 n_norm++;
03699                         }
03700                 }
03701                 return sqrt(static_cast<float>((sq2 - sum * sum /n_norm)/(n_norm -1))) ;
03702         }
03703 }
03704 
03705 float NormalizeMaskProcessor::calc_mean(EMData * image) const
03706 {
03707         if (!image) {
03708                 LOGWARN("NULL Image");
03709                 return 0;
03710         }
03711         EMData *mask = params["mask"];
03712 
03713         if (!EMUtil::is_same_size(mask, image)) {
03714                 LOGERR("normalize.maskProcessor: mask and image must be the same size");
03715                 throw ImageDimensionException("mask and image must be the same size");
03716         }
03717 
03718         float *data = image->get_data();
03719         float *mask_data = mask->get_data();
03720         size_t size = (size_t)image->get_xsize() * image->get_ysize() * image->get_zsize();
03721         double sum = 0;
03722         size_t n_norm = 0;
03723 
03724         for (size_t i = 0; i < size; ++i) {
03725                 if (mask_data[i] > 0.5f) {
03726                         sum += data[i];
03727                         n_norm++;
03728                 }
03729         }
03730 
03731         float mean = 0;
03732         if (n_norm == 0) {
03733                 mean = image->get_edge_mean();
03734         }
03735         else {
03736                 mean = (float) sum / n_norm;
03737         }
03738 
03739         return mean;
03740 }
03741 
03742 void NormalizeRampNormVar::process_inplace(EMData * image)
03743 {
03744         if (!image) {
03745                 LOGWARN("cannot do normalization on NULL image");
03746                 return;
03747         }
03748 
03749         if (image->is_complex()) {
03750                 LOGWARN("cannot do normalization on complex image");
03751                 return;
03752         }
03753 
03754         image->process_inplace( "filter.ramp" );
03755         int nx = image->get_xsize();
03756         EMData mask(nx,nx);
03757         mask.process_inplace("testimage.circlesphere", Dict("radius",nx/2-2,"fill",1));
03758 
03759         vector<float> rstls = Util::infomask( image, &mask, false);
03760         image->add((float)-rstls[0]);
03761         image->mult((float)1.0/rstls[1]);
03762         image->update();
03763 }
03764 
03765 void NormalizeByMassProcessor::process_inplace(EMData * image)
03766 {
03767         float mass = params.set_default("mass",-1.0f);
03768         int verbose = params.set_default("verbose",0);
03769 
03770         if (mass <= 0) throw InvalidParameterException("You must specify a positive non zero mass");
03771 
03772         float tthr = params.set_default("thr",(float)image->get_attr("mean")+(float)image->get_attr("sigma"));
03773 
03774         float apix = image->get_attr_default("apix_x",1.0f);
03775         apix = params.set_default("apix",apix);
03776 
03777         if (apix <= 0) throw InvalidParameterException("You must specify a positive non zero apix");
03778 
03779         float step = ((float)image->get_attr("sigma"))/5.0f;
03780 
03781         if (step==0) throw InvalidParameterException("This image has sigma=0, cannot give it mass");
03782 
03783 
03784         size_t n = image->get_size();
03785         float* d = image->get_data();
03786 
03787 
03788         float thr=(float)image->get_attr("mean")+(float)image->get_attr("sigma")/2.0;
03789         int count=0;
03790         for (size_t i=0; i<n; ++i) {
03791                 if (d[i]>=thr) ++count;
03792         }
03793         if (verbose) printf("apix=%1.3f\tmass=%1.1f\tthr=%1.2f\tstep=%1.3g\n",apix,mass,thr,step);
03794 
03795         float max = image->get_attr("maximum");
03796         float min = image->get_attr("minimum");
03797         for (int j=0; j<4; j++) {
03798                 int err=0;
03799                 while (thr<max && count*apix*apix*apix*.81/1000.0>mass) {
03800                         thr+=step;
03801                         count=0;
03802                         for (size_t i=0; i<n; ++i) {
03803                                 if (d[i]>=thr) ++count;
03804                         }
03805                         err+=1;
03806                         if (err>1000) throw InvalidParameterException("Specified mass could not be achieved");
03807                         if (verbose>1) printf("%d\t%d\t%1.3f\t%1.2f\n",err,count,thr,count*apix*apix*apix*.81/1000.0);
03808                 }
03809 
03810                 step/=4.0;
03811 
03812                 while (thr>min && count*apix*apix*apix*.81/1000.0<mass) {
03813                         thr-=step;
03814                         count=0;
03815                         for (size_t i=0; i<n; ++i) {
03816                                 if (d[i]>=thr) ++count;
03817                         }
03818                         err+=1;
03819                         if (err>1000) throw InvalidParameterException("Specified mass could not be achieved");
03820                         if (verbose>1) printf("%d\t%d\t%1.3f\t%1.2f\n",err,count,thr,count*apix*apix*apix*.81/1000.0);
03821 
03822                 }
03823                 step/=4.0;
03824         }
03825 
03826         image->mult((float)tthr/thr);
03827         image->update();
03828 }
03829 
03830 float NormalizeEdgeMeanProcessor::calc_mean(EMData * image) const
03831 {
03832         if (!image) {
03833                 LOGWARN("NULL Image");
03834                 return 0;
03835         }
03836         return image->get_edge_mean();
03837 }
03838 
03839 float NormalizeCircleMeanProcessor::calc_mean(EMData * image) const
03840 {
03841         if (!image) {
03842                 LOGWARN("NULL Image");
03843                 return 0;
03844         }
03845 //      return image->get_circle_mean();
03846         int nx=image->get_xsize();
03847         int ny=image->get_ysize();
03848         int nz=image->get_zsize();
03849 
03850         float radius = params.set_default("radius",((float)ny/2-2));
03851 
03852 //      static bool busy = false;
03853         static EMData *mask = 0;
03854 
03855         if (!mask || !EMUtil::is_same_size(image, mask)) {
03856                 if (!mask) {
03857                         mask = new EMData();
03858                 }
03859                 mask->set_size(nx, ny, nz);
03860                 mask->to_one();
03861 
03862                 mask->process_inplace("mask.sharp", Dict("inner_radius", radius - 1,
03863                                                          "outer_radius", radius + 1));
03864 
03865         }
03866         double n = 0,s=0;
03867         float *d = mask->get_data();
03868         float * data = image->get_data();
03869         size_t size = (size_t)nx*ny*nz;
03870         for (size_t i = 0; i < size; ++i) {
03871                 if (d[i]) { n+=1.0; s+=data[i]; }
03872         }
03873 
03874 
03875         float result = (float)(s/n);
03876 
03877         return result;
03878 
03879 
03880 }
03881 
03882 
03883 float NormalizeMaxMinProcessor::calc_sigma(EMData * image) const
03884 {
03885         if (!image) {
03886                 LOGWARN("NULL Image");
03887                 return 0;
03888         }
03889         float maxval = image->get_attr("maximum");
03890         float minval = image->get_attr("minimum");
03891         return (maxval + minval) / 2;
03892 }
03893 
03894 float NormalizeMaxMinProcessor::calc_mean(EMData * image) const
03895 {
03896         if (!image) {
03897                 LOGWARN("NULL Image");
03898                 return 0;
03899         }
03900         float maxval = image->get_attr("maximum");
03901         float minval = image->get_attr("minimum");
03902         return (maxval - minval) / 2;
03903 }
03904 
03905 float NormalizeLREdgeMeanProcessor::calc_mean(EMData * image) const
03906 {
03907         if (!image) {
03908                 LOGWARN("NULL Image");
03909                 return 0;
03910         }
03911         double sum = 0;
03912         int nx = image->get_xsize();
03913         int ny = image->get_ysize();
03914         int nz = image->get_zsize();
03915         float *d = image->get_data();
03916         size_t nyz = ny * nz;
03917 
03918         for (size_t i = 0; i < nyz; i++) {
03919                 size_t l = i * nx;
03920                 size_t r = l + nx - 2;
03921                 sum += d[l] + d[l + 1] + d[r] + d[r + 1];
03922         }
03923         float mean = (float) sum / (4 * nyz);
03924         return mean;
03925 }
03926 
03927 void NormalizeRowProcessor::process_inplace(EMData * image)
03928 {
03929         if (!image) {
03930                 LOGWARN("NULL Image");
03931                 return;
03932         }
03933 
03934         if (image->get_zsize() > 1) {
03935                 LOGERR("row normalize only works for 2D image");
03936                 return;
03937         }
03938 
03939         float *rdata = image->get_data();
03940         int nx = image->get_xsize();
03941         int ny = image->get_ysize();
03942 
03943         for (int y = 0; y < ny; y++) {
03944                 double row_sum = 0;
03945                 for (int x = 0; x < nx; x++) {
03946                         row_sum += rdata[x + y * nx];
03947                 }
03948 
03949                 double row_mean = row_sum / nx;
03950                 if (row_mean <= 0) {
03951                         row_mean = 1;
03952                 }
03953 
03954                 for (int x = 0; x < nx; x++) {
03955                         rdata[x + y * nx] /= (float)row_mean;
03956                 }
03957         }
03958 
03959         image->update();
03960 }
03961 
03962 float NormalizeStdProcessor::calc_mean(EMData * image) const
03963 {
03964         if (!image) {
03965                 LOGWARN("NULL Image");
03966                 return 0;
03967         }
03968         return image->get_attr("mean");
03969 }
03970 
03971 EMData *SubtractOptProcessor::process(const EMData * const image)
03972 {
03973         if (!image) {
03974                 LOGWARN("NULL Image");
03975                 return NULL;
03976         }
03977 
03978         EMData *refr = params["ref"];
03979         EMData *actual = params.set_default("actual",(EMData*)NULL);
03980         EMData *ref;
03981         bool return_radial = params.set_default("return_radial",false);
03982         bool return_fft = params.set_default("return_fft",false);
03983         bool ctfweight = params.set_default("ctfweight",false);
03984         bool return_presigma = params.set_default("return_presigma",false);
03985         int si0=(int)floor(params.set_default("low_cutoff_frequency",0.0f)*image->get_ysize());
03986         int si1=(int)ceil(params.set_default("high_cutoff_frequency",0.7071f)*image->get_ysize());              // include the corners unless explicitly excluded
03987         
03988         // We will be modifying imf, so it needs to be a copy
03989         EMData *imf;
03990         if (image->is_complex()) imf=image->copy();
03991         else imf=image->do_fft();
03992 
03993         if (ctfweight) {
03994                 EMData *ctfi=imf->copy_head();
03995                 Ctf *ctf;
03996 //              if (image->has_attr("ctf")) 
03997                         ctf=(Ctf *)(image->get_attr("ctf"));
03998 //              else ctf=(Ctf *)(ref->get_attr("ctf"));
03999                 ctf->compute_2d_complex(ctfi,Ctf::CTF_INTEN);
04000                 imf->mult(*ctfi);
04001                 delete ctfi;
04002         }
04003         
04004         // Make sure ref is complex
04005         if (refr->is_complex()) ref=refr;
04006         else ref=refr->do_fft();
04007 
04008         EMData *actf;
04009         if (actual==NULL) actf=ref;
04010         else {
04011                 if (ctfweight) throw InvalidCallException("math.sub.optimal: Sorry, cannot use ctfweight in combination with actual");
04012                 if (actual->is_complex()) actf=actual;
04013                 else actf=actual->do_fft();
04014         }
04015                 
04016         int ny2=(int)(image->get_ysize()*sqrt(2.0)/2);
04017         vector <double>rad(ny2+1);
04018         vector <double>norm(ny2+1);
04019 
04020         // We are essentially computing an FSC here, but while the reference (the image
04021         // we plan to subtract) is normalized, the other image is not. This gives us a filter
04022         // to apply to the reference to optimally eliminate its contents from 'image'.
04023         for (int y=-ny2; y<ny2; y++) {
04024                 for (int x=0; x<ny2; x++) {
04025                         int r=int(Util::hypot_fast(x,y));
04026                         if (r>ny2) continue;
04027                         std::complex<float> v1=imf->get_complex_at(x,y);
04028                         std::complex<float> v2=ref->get_complex_at(x,y);
04029                         rad[r]+=(double)(v1.real()*v2.real()+v1.imag()*v2.imag());
04030 //                      norm[r]+=v2.real()*v2.real()+v2.imag()*v2.imag()+v1.real()*v1.real()+v1.imag()*v1.imag();
04031                         norm[r]+=(double)(v2.real()*v2.real()+v2.imag()*v2.imag());
04032                 }
04033         }
04034         for (int i=0; i<ny2; i++) rad[i]/=norm[i];
04035 
04036 //      FILE *out=fopen("dbug.txt","w");
04037 //      for (int i=0; i<ny2; i++) fprintf(out,"%lf\t%lf\t%lf\n",(float)i,rad[i],norm[i]);
04038 //      fclose(out);
04039         
04040         float oldsig=-1.0;
04041         // This option computes the real-space sigma on the input-image after the specified filter
04042         // This is an expensive option, but more efficient than computing the same using other means
04043         if (return_presigma) {
04044                 for (int y=-ny2; y<ny2; y++) {
04045                         for (int x=0; x<imf->get_xsize()/2; x++) {
04046                                 int r=int(Util::hypot_fast(x,y));
04047                                 if (r>=ny2 || r>=si1 || r<si0) {
04048                                         imf->set_complex_at(x,y,0);
04049                                         continue;
04050                                 }
04051                                 std::complex<float> v1=imf->get_complex_at(x,y);
04052                                 imf->set_complex_at(x,y,v1);
04053                         }
04054                 }
04055                 EMData *tmp=imf->do_ift();
04056                 oldsig=(float)tmp->get_attr("sigma");
04057                 delete tmp;
04058         }
04059         
04060         for (int y=-ny2; y<ny2; y++) {
04061                 for (int x=0; x<imf->get_xsize()/2; x++) {
04062                         int r=int(Util::hypot_fast(x,y));
04063                         if (r>=ny2 || r>=si1 || r<si0) {
04064                                 imf->set_complex_at(x,y,0);
04065                                 continue;
04066                         }
04067                         std::complex<float> v1=imf->get_complex_at(x,y);
04068                         std::complex<float> v2=actf->get_complex_at(x,y);
04069                         v2*=(float)rad[r];
04070                         imf->set_complex_at(x,y,v1-v2);
04071                 }
04072         }
04073         
04074         if (!refr->is_complex()) delete ref;
04075         if (actual!=NULL && !actual->is_complex()) delete actf;
04076 
04077         vector <float>radf;
04078         if (return_radial) {
04079                 radf.resize(ny2);
04080                 for (int i=0; i<ny2; i++) radf[i]=(float)rad[i];
04081         }
04082                 
04083         if (!return_fft) {
04084                 EMData *ret=imf->do_ift();
04085                 delete imf;
04086                 if (return_radial) ret->set_attr("filter_curve",radf);
04087                 if (return_presigma) {
04088                         ret->set_attr("sigma_presub",oldsig);
04089 //                      printf("Set %f\n",(float)image->get_attr("sigma_presub"));
04090                 }
04091                 return ret;
04092         }
04093         if (return_radial) imf->set_attr("filter_curve",radf);
04094         if (return_presigma) imf->set_attr("sigma_presub",oldsig);
04095         return imf;
04096 }
04097 
04098 void SubtractOptProcessor::process_inplace(EMData * image)
04099 {
04100         if (!image) {
04101                 LOGWARN("NULL image");
04102                 return;
04103         }
04104 
04105         EMData *tmp=process(image);
04106         memcpy(image->get_data(),tmp->get_data(),(size_t)image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
04107         delete tmp;
04108         image->update();
04109         return;
04110 }
04111 
04112 
04113 void NormalizeToLeastSquareProcessor::process_inplace(EMData * image)
04114 {
04115         if (!image) {
04116                 LOGWARN("NULL Image");
04117                 return;
04118         }
04119 
04120         EMData *to = params["to"];
04121 
04122         bool ignore_zero = params.set_default("ignore_zero",true);
04123         float ignore_lowsig = params.set_default("ignore_lowsig",-1.0);
04124         float low_threshold = params.set_default("low_threshold",-FLT_MAX);
04125         float high_threshold = params.set_default("high_threshold",FLT_MAX);
04126 
04127         float *dimage = image->get_data();
04128         float *dto = to->get_data();
04129 
04130         int nx = image->get_xsize();
04131         int ny = image->get_ysize();
04132         int nz = image->get_zsize();
04133         size_t size = (size_t)nx * ny * nz;
04134 
04135         // rewrote this to just use GSL and get rid of David's old code.
04136         // The two passes are just to make sure we don't eat too much RAM if we do 3D
04137         if (ignore_lowsig<0) ignore_lowsig=0;
04138 //      FILE *dbug = fopen("dbug.txt","w");
04139 
04140         size_t count=0;
04141         float meani=(float)image->get_attr("mean");
04142         float meant=(float)to->get_attr("mean");
04143         float sigi=(float)image->get_attr("sigma")*ignore_lowsig;
04144         float sigt=(float)to->get_attr("sigma")*ignore_lowsig;
04145         for (size_t i = 0; i < size; ++i) {
04146                 if (dto[i] >= low_threshold && dto[i] <= high_threshold
04147                         && (dto[i]>=meant+sigt || dto[i]<=meant-sigt)
04148                         && (dimage[i]>=meani+sigi || dimage[i]<=meani-sigi)
04149                         && (!ignore_zero ||(dto[i] != 0.0f && dimage[i] != 0.0f))) {
04150                         count++;
04151 //                      fprintf(dbug,"%f\t%f\n",dimage[i],dto[i]);
04152                 }
04153         }
04154 //      fclose(dbug);
04155 
04156         double *x=(double *)malloc(count*sizeof(double));
04157         double *y=(double *)malloc(count*sizeof(double));
04158         count=0;
04159         for (size_t i = 0; i < size; ++i) {
04160                 if (dto[i] >= low_threshold && dto[i] <= high_threshold
04161                         && (dto[i]>=meant+sigt || dto[i]<=meant-sigt)
04162                         && (dimage[i]>=meani+sigi || dimage[i]<=meani-sigi)
04163                         && (!ignore_zero ||(dto[i] != 0.0f && dimage[i] != 0.0f))) {
04164                         x[count]=dimage[i];
04165                         y[count]=dto[i];
04166                         count++;
04167                 }
04168         }
04169         double c0,c1;
04170         double cov00,cov01,cov11,sumsq;
04171         gsl_fit_linear (x, 1, y, 1, count, &c0, &c1, &cov00, &cov01, &cov11, &sumsq);
04172 
04173         free(x);
04174         free(y);
04175 
04176         for (size_t i = 0; i < size; ++i) dimage[i]=dimage[i]*c1+c0;
04177         image->set_attr("norm_mult",c1);
04178         image->set_attr("norm_add",c0);
04179         image->update();
04180 }
04181 
04182 void BinarizeFourierProcessor::process_inplace(EMData* image) {
04183         ENTERFUNC;
04184         if (!image->is_complex()) throw ImageFormatException("Fourier binary thresholding processor only works for complex images");
04185 
04186         float threshold = params.set_default("value",0.0f);
04187         image->ri2ap(); //  works for cuda
04188 
04189         float* d = image->get_data();
04190         for( size_t i = 0; i < image->get_size()/2; ++i, d+=2) {
04191                 if ( *d < threshold ) {
04192                         *d = 0;
04193                         *(d+1) = 0;
04194                 }
04195         }
04196         image->ap2ri();
04197         image->set_ri(true); // So it can be used for fourier multiplaction, for example
04198         image->update();
04199         EXITFUNC;
04200 }
04201 
04202 void BilateralProcessor::process_inplace(EMData * image)
04203 {
04204         if (!image) {
04205                 LOGWARN("NULL Image");
04206                 return;
04207         }
04208 
04209         float distance_sigma = params["distance_sigma"];
04210         float value_sigma = params["value_sigma"];
04211         int max_iter = params["niter"];
04212         int half_width = params["half_width"];
04213 
04214         if (half_width < distance_sigma) {
04215                 LOGWARN("localwidth(=%d) should be larger than distance_sigma=(%f)\n",
04216                                                         half_width, distance_sigma);
04217         }
04218 
04219         distance_sigma *= distance_sigma;
04220 
04221         float image_sigma = image->get_attr("sigma");
04222         if (image_sigma > value_sigma) {
04223                 LOGWARN("image sigma(=%f) should be smaller than value_sigma=(%f)\n",
04224                                                         image_sigma, value_sigma);
04225         }
04226         value_sigma *= value_sigma;
04227 
04228         int nx = image->get_xsize();
04229         int ny = image->get_ysize();
04230         int nz = image->get_zsize();
04231 
04232         if(nz==1) {     //for 2D image
04233                 int width=nx, height=ny;
04234 
04235                 int i,j,m,n;
04236 
04237                 float tempfloat1,tempfloat2,tempfloat3;
04238                 int   index1,index2,index;
04239                 int   Iter;
04240                 int   tempint1,tempint3;
04241 
04242                 tempint1=width;
04243                 tempint3=width+2*half_width;
04244 
04245                 float* mask=(float*)calloc((2*half_width+1)*(2*half_width+1),sizeof(float));
04246                 float* OrgImg=(float*)calloc((2*half_width+width)*(2*half_width+height),sizeof(float));
04247                 float* NewImg=image->get_data();
04248 
04249                 for(m=-(half_width);m<=half_width;m++)
04250                         for(n=-(half_width);n<=half_width;n++) {
04251                    index=(m+half_width)*(2*half_width+1)+(n+half_width);
04252                    mask[index]=exp((float)(-(m*m+n*n)/distance_sigma/2.0));
04253                 }
04254 
04255                 //printf("entering bilateral filtering process \n");
04256 
04257                 Iter=0;
04258                 while(Iter<max_iter) {
04259                         for(i=0;i<height;i++)
04260                         for(j=0;j<width;j++) {
04261                                 index1=(i+half_width)*tempint3+(j+half_width);
04262                                         index2=i*tempint1+j;
04263                                 OrgImg[index1]=NewImg[index2];
04264                         }
04265 
04266                         // Mirror Padding
04267                         for(i=0;i<height;i++){
04268                                 for(j=0;j<half_width;j++) OrgImg[(i+half_width)*tempint3+(j)]=OrgImg[(i+half_width)*tempint3+(2*half_width-j)];
04269                                 for(j=0;j<half_width;j++) OrgImg[(i+half_width)*tempint3+(j+width+half_width)]=OrgImg[(i+half_width)*tempint3+(width+half_width-j-2)];
04270                         }
04271                         for(i=0;i<half_width;i++){
04272                                 for(j=0;j<(width+2*half_width);j++) OrgImg[i*tempint3+j]=OrgImg[(2*half_width-i)*tempint3+j];
04273                                 for(j=0;j<(width+2*half_width);j++) OrgImg[(i+height+half_width)*tempint3+j]=OrgImg[(height+half_width-2-i)*tempint3+j];
04274                         }
04275 
04276                         //printf("finish mirror padding process \n");
04277                         //now mirror padding have been done
04278 
04279                         for(i=0;i<height;i++){
04280                                 //printf("now processing the %d th row \n",i);
04281                                 for(j=0;j<width;j++){
04282                                         tempfloat1=0.0; tempfloat2=0.0;
04283                                         for(m=-(half_width);m<=half_width;m++)
04284                                                 for(n=-(half_width);n<=half_width;n++){
04285                                                         index =(m+half_width)*(2*half_width+1)+(n+half_width);
04286                                                         index1=(i+half_width)*tempint3+(j+half_width);
04287                                                         index2=(i+half_width+m)*tempint3+(j+half_width+n);
04288                                                         tempfloat3=(OrgImg[index1]-OrgImg[index2])*(OrgImg[index1]-OrgImg[index2]);
04289 
04290                                                         tempfloat3=mask[index]*(1.0f/(1+tempfloat3/value_sigma));       // Lorentz kernel
04291                                                         //tempfloat3=mask[index]*exp(tempfloat3/Sigma2/(-2.0)); // Guassian kernel
04292                                                         tempfloat1+=tempfloat3;
04293 
04294                                                         tempfloat2+=tempfloat3*OrgImg[(i+half_width+m)*tempint3+(j+half_width+n)];
04295                                         }
04296                                         NewImg[i*width+j]=tempfloat2/tempfloat1;
04297                                 }
04298                         }
04299                         Iter++;
04300             }
04301 
04302             //printf("have finished %d  th iteration\n ",Iter);
04303 //              doneData();
04304                 free(mask);
04305                 free(OrgImg);
04306                 // end of BilaFilter routine
04307 
04308         }
04309         else {  //3D case
04310                 int width = nx;
04311                 int height = ny;
04312                 int slicenum = nz;
04313 
04314                 int slice_size = width * height;
04315                 int new_width = width + 2 * half_width;
04316                 int new_slice_size = (width + 2 * half_width) * (height + 2 * half_width);
04317 
04318                 int width1 = 2 * half_width + 1;
04319                 int mask_size = width1 * width1;
04320                 int old_img_size = (2 * half_width + width) * (2 * half_width + height);
04321 
04322                 int zstart = -half_width;
04323                 int zend = -half_width;
04324                 int is_3d = 0;
04325                 if (nz > 1) {
04326                         mask_size *= width1;
04327                         old_img_size *= (2 * half_width + slicenum);
04328                         zend = half_width;
04329                         is_3d = 1;
04330                 }
04331 
04332                 float *mask = (float *) calloc(mask_size, sizeof(float));
04333                 float *old_img = (float *) calloc(old_img_size, sizeof(float));
04334 
04335                 float *new_img = image->get_data();
04336 
04337                 for (int p = zstart; p <= zend; p++) {
04338                         int cur_p = (p + half_width) * (2 * half_width + 1) * (2 * half_width + 1);
04339 
04340                         for (int m = -half_width; m <= half_width; m++) {
04341                                 int cur_m = (m + half_width) * (2 * half_width + 1) + half_width;
04342 
04343                                 for (int n = -half_width; n <= half_width; n++) {
04344                                         int l = cur_p + cur_m + n;
04345                                         mask[l] = exp((float) (-(m * m + n * n + p * p * is_3d) / distance_sigma / 2.0f));
04346                                 }
04347                         }
04348                 }
04349 
04350                 int iter = 0;
04351                 while (iter < max_iter) {
04352                         for (int k = 0; k < slicenum; k++) {
04353                                 size_t cur_k1 = (size_t)(k + half_width) * new_slice_size * is_3d;
04354                                 int cur_k2 = k * slice_size;
04355 
04356                                 for (int i = 0; i < height; i++) {
04357                                         int cur_i1 = (i + half_width) * new_width;
04358                                         int cur_i2 = i * width;
04359 
04360                                         for (int j = 0; j < width; j++) {
04361                                                 size_t k1 = cur_k1 + cur_i1 + (j + half_width);
04362                                                 int k2 = cur_k2 + cur_i2 + j;
04363                                                 old_img[k1] = new_img[k2];
04364                                         }
04365                                 }
04366                         }
04367 
04368                         for (int k = 0; k < slicenum; k++) {
04369                                 size_t cur_k = (k + half_width) * new_slice_size * is_3d;
04370 
04371                                 for (int i = 0; i < height; i++) {
04372                                         int cur_i = (i + half_width) * new_width;
04373 
04374                                         for (int j = 0; j < half_width; j++) {
04375                                                 size_t k1 = cur_k + cur_i + j;
04376                                                 size_t k2 = cur_k + cur_i + (2 * half_width - j);
04377                                                 old_img[k1] = old_img[k2];
04378                                         }
04379 
04380                                         for (int j = 0; j < half_width; j++) {
04381                                                 size_t k1 = cur_k + cur_i + (width + half_width + j);
04382                                                 size_t k2 = cur_k + cur_i + (width + half_width - j - 2);
04383                                                 old_img[k1] = old_img[k2];
04384                                         }
04385                                 }
04386 
04387 
04388                                 for (int i = 0; i < half_width; i++) {
04389                                         int i2 = i * new_width;
04390                                         int i3 = (2 * half_width - i) * new_width;
04391                                         for (int j = 0; j < (width + 2 * half_width); j++) {
04392                                                 size_t k1 = cur_k + i2 + j;
04393                                                 size_t k2 = cur_k + i3 + j;
04394                                                 old_img[k1] = old_img[k2];
04395                                         }
04396 
04397                                         i2 = (height + half_width + i) * new_width;
04398                                         i3 = (height + half_width - 2 - i) * new_width;
04399                                         for (int j = 0; j < (width + 2 * half_width); j++) {
04400                                                 size_t k1 = cur_k + i2 + j;
04401                                                 size_t k2 = cur_k + i3 + j;
04402                                                 old_img[k1] = old_img[k2];
04403                                         }
04404                                 }
04405                         }
04406 
04407                         size_t idx;
04408                         for (int k = 0; k < slicenum; k++) {
04409                                 size_t cur_k = (k + half_width) * new_slice_size;
04410 
04411                                 for (int i = 0; i < height; i++) {
04412                                         int cur_i = (i + half_width) * new_width;
04413 
04414                                         for (int j = 0; j < width; j++) {
04415                                                 float f1 = 0;
04416                                                 float f2 = 0;
04417                                                 size_t k1 = cur_k + cur_i + (j + half_width);
04418 
04419                                                 for (int p = zstart; p <= zend; p++) {
04420                                                         size_t cur_p1 = (p + half_width) * (2 * half_width + 1) * (2 * half_width + 1);
04421                                                         size_t cur_p2 = (k + half_width + p) * new_slice_size;
04422 
04423                                                         for (int m = -half_width; m <= half_width; m++) {
04424                                                                 size_t cur_m1 = (m + half_width) * (2 * half_width + 1);
04425                                                                 size_t cur_m2 = cur_p2 + cur_i + m * new_width + j + half_width;
04426 
04427                                                                 for (int n = -half_width; n <= half_width; n++) {
04428                                                                         size_t k = cur_p1 + cur_m1 + (n + half_width);
04429                                                                         size_t k2 = cur_m2 + n;
04430                                                                         float f3 = Util::square(old_img[k1] - old_img[k2]);
04431 
04432                                                                         f3 = mask[k] * (1.0f / (1 + f3 / value_sigma));
04433                                                                         f1 += f3;
04434                                                                         size_t l1 = cur_m2 + n;
04435                                                                         f2 += f3 * old_img[l1];
04436                                                                 }
04437 
04438                                                                 idx = (size_t)k * height * width + i * width + j;
04439                                                                 new_img[idx] = f2 / f1;
04440                                                         }
04441                                                 }
04442                                         }
04443                                 }
04444                         }
04445                         iter++;
04446                 }
04447                 if( mask ) {
04448                         free(mask);
04449                         mask = 0;
04450                 }
04451 
04452                 if( old_img ) {
04453                         free(old_img);
04454                         old_img = 0;
04455                 }
04456         }
04457 
04458         image->update();
04459 }
04460 
04461 void RotationalAverageProcessor::process_inplace(EMData * image)
04462 {
04463         if (!image || image->is_complex()) {
04464                 LOGWARN("only works on real image. do nothing.");
04465                 return;
04466         }
04467 
04468         if (image->get_ndim() <= 0 || image->get_ndim() > 3)    throw ImageDimensionException("radial average processor only works for 2D and 3D images");
04469 
04470         float *rdata = image->get_data();
04471         int nx = image->get_xsize();
04472         int ny = image->get_ysize();
04473 
04474         vector < float >dist = image->calc_radial_dist(nx / 2, 0, 1,0);
04475 
04476         float midx = (float)((int)nx/2);
04477         float midy = (float)((int)ny/2);
04478 
04479         size_t c = 0;
04480         if (image->get_ndim() == 2) {
04481                 for (int y = 0; y < ny; y++) {
04482                         for (int x = 0; x < nx; x++, c++) {
04483         #ifdef  _WIN32
04484                                 float r = (float) _hypot(x - midx, y - midy);
04485         #else
04486                                 float r = (float) hypot(x - midx, y - midy);
04487         #endif  //_WIN32
04488 
04489 
04490                                 int i = (int) floor(r);
04491                                 r -= i;
04492                                 if (i >= 0 && i < nx / 2 - 1) {
04493                                         rdata[c] = dist[i] * (1.0f - r) + dist[i + 1] * r;
04494                                 }
04495                                 else if (i < 0) {
04496                                         rdata[c] = dist[0];
04497                                 }
04498                                 else {
04499                                         rdata[c] = 0;
04500                                 }
04501                         }
04502                 }
04503         }
04504         else if (image->get_ndim() == 3) {
04505                 int nz = image->get_zsize();
04506                 float midz = (float)((int)nz/2);
04507                 float r;
04508                 int i;
04509                 for (int z = 0; z < nz; ++z) {
04510                         for (int y = 0; y < ny; ++y) {
04511                                 for (int x = 0; x < nx; ++x, ++c) {
04512 
04513                                         r = (float) Util::hypot3(x - midx, y - midy, z - midz);
04514 
04515                                         i = Util::fast_floor(r);
04516                                         r -= i;
04517                                         if (i >= 0 && i < nx / 2 - 1) {
04518                                                 rdata[c] = dist[i] * (1.0f - r) + dist[i + 1] * r;
04519                                         }
04520                                         else if (i < 0) {
04521                                                 rdata[c] = dist[0];
04522                                         }
04523                                         else {
04524                                                 rdata[c] = 0;
04525                                         }
04526                                 }
04527                         }
04528                 }
04529         }
04530 
04531         image->update();
04532 }
04533 
04534 
04535 
04536 void RotationalSubstractProcessor::process_inplace(EMData * image)
04537 {
04538         if (!image || image->is_complex()) {
04539                 LOGWARN("only works on real image. do nothing.");
04540                 return;
04541         }
04542 
04543         if (image->get_ndim() != 2) throw ImageDimensionException("This processor works only for 2D images");
04544 
04545         float *rdata = image->get_data();
04546         int nx = image->get_xsize();
04547         int ny = image->get_ysize();
04548 
04549         vector < float >dist = image->calc_radial_dist(nx / 2, 0, 1,0);
04550 
04551         int c = 0;
04552         for (int y = 0; y < ny; y++) {
04553                 for (int x = 0; x < nx; x++, c++) {
04554 #ifdef  _WIN32
04555                         float r = (float) _hypot(x - nx / 2, y - ny / 2);
04556 #else
04557                         float r = (float) hypot(x - nx / 2, y - ny / 2);
04558 #endif
04559                         int i = (int) floor(r);
04560                         r -= i;
04561                         if (i >= 0 && i < nx / 2 - 1) {
04562                                 rdata[c] -= dist[i] * (1.0f - r) + dist[i + 1] * r;
04563                         }
04564                         else {
04565                                 rdata[c] = 0;
04566                         }
04567                 }
04568         }
04569 
04570         image->update();
04571 }
04572 
04573 
04574 EMData* TransposeProcessor::process(const EMData* const image) {
04575         if (image->get_ndim() != 2) throw UnexpectedBehaviorException("Transpose processor only works with 2D images");
04576         if (image->is_complex()) throw UnexpectedBehaviorException("Transpose processor only works with real images");
04577 
04578         EMData* ret = new EMData(image->get_ysize(),image->get_xsize(),1); // transpose dimensions
04579 
04580         for(int j = 0; j< image->get_ysize();++j) {
04581                 for(int i = 0; i< image->get_xsize();++i) {
04582                         ret->set_value_at(j,i,image->get_value_at(i,j));
04583                 }
04584         }
04585 
04586         return ret;
04587 
04588 }
04589 
04590 void TransposeProcessor::process_inplace(EMData* image) {
04591         if (image->get_ndim() != 2) throw UnexpectedBehaviorException("Transpose processor only works with 2D images");
04592         if (image->is_complex()) throw UnexpectedBehaviorException("Transpose processor only works with real images");
04593 
04594         float* data = (float*)malloc(image->get_ysize()*image->get_xsize()*sizeof(float));
04595 
04596         int nx = image->get_ysize(); // note tranpose
04597         for(int j = 0; j< image->get_ysize();++j) {
04598                 for(int i = 0; i< image->get_xsize();++i) {
04599                         data[i*nx+j] = image->get_value_at(i,j);
04600                 }
04601         }
04602 
04603         image->set_data(data,image->get_ysize(),image->get_xsize(),1);
04604 
04605 }
04606 
04607 void FlipProcessor::process_inplace(EMData * image)
04608 {
04609         ENTERFUNC;
04610         if (!image) {
04611                 LOGWARN("NULL Image");
04612                 return;
04613         }
04614         string axis = (const char*)params["axis"];
04615 
04616 #ifdef EMAN2_USING_CUDA
04617         if (EMData::usecuda == 1 && image->getcudarwdata()) {
04618                 //cout << "flip processor" << endl;
04619                 float array[12] = {1.0, 0.0, 0.0, 0.0,
04620                                                    0.0, 1.0, 0.0, 0.0,
04621                                                    0.0, 0.0, 1.0, 0.0};
04622                 if (axis == "x" || axis == "X") {               // horizontal flip
04623                         array[0] = -1.0;
04624                 }else if (axis == "y" || axis == "Y") {         // vertical flip
04625                         array[5] = -1.0;
04626                 }
04627                 else if (axis == "z" || axis == "Z") {          // vertical flip
04628                         array[10] = -1.0;
04629                 }
04630                 Transform t(array);
04631                 Dict params("transform",(Transform*)&t);
04632                 image->process_inplace("xform",params);
04633 
04634                 EXITFUNC;
04635                 return;
04636         }
04637 #endif
04638 
04639 
04640         float *d = image->get_data();
04641         int nx = image->get_xsize();
04642         int ny = image->get_ysize();
04643         int nz = image->get_zsize();
04644 
04645         size_t nxy = nx * ny;
04646 
04647 
04648         // Note in all cases the origin is nx/2, ny/2 and nz/2
04649         // This means when flipping even sized dimensions that some pixels are redundant.
04650         // Here redundant pixels are set to zero, however, should this change to something
04651         // like the mean.
04652         if (axis == "x" || axis == "X") {               // Horizontal flip
04653                 int offset = (nx%2 == 0);
04654                 size_t idx1, idx2;
04655                 for(int z = 0; z < nz; ++z) {
04656                         for(int y = 0; y < ny; ++y) {
04657                                 if (offset != 0 ) {
04658                                         idx1 = z*nxy + y*nx;
04659                                         d[idx1] = 0; // Here's where you'd make it the mean
04660                                 }
04661                                 for(int x = offset; x < nx / 2; ++x) {
04662                                         idx1 = z*nxy + y*nx + x;
04663                                         idx2 = z*nxy + y*nx + (nx-x-1+offset);
04664                                         std::swap(d[idx1], d[idx2]);
04665                                 }
04666 
04667                         }
04668                 }
04669         }
04670 
04671         else if (axis == "y" || axis == "Y") {          // vertical flip
04672                 int offset = (ny%2 == 0);
04673                 for(int z=0; z<nz; ++z) {
04674                         if (offset != 0) {
04675                                 std::fill(d+z*nxy,d+(size_t)z*nxy+nx,0); // So if we have change it to the mean it's easy to do so. (instead of using memset)
04676                         }
04677                         for(int y=offset; y<ny/2; ++y) {
04678                                 for(int x=0; x<nx; ++x) {
04679                                         std::swap(d[(size_t)z*nxy + y*nx +x], d[(size_t)z*nxy + (ny -y -1+offset)*nx +x]);
04680                                 }
04681                         }
04682                 }
04683         }
04684         else if (axis == "z" || axis == "Z") {          //z axis flip
04685                 int offset = (nz%2 == 0);
04686                 if (offset != 0) {
04687                         std::fill(d,d+nxy,0);// So if we have change it to the mean it's easy to do so. (instead of using memset)
04688                 }
04689                 size_t idx1, idx2;
04690                 for(int z=offset; z<nz/2; ++z) {
04691                         for(int y=0; y<ny; ++y) {
04692                                 for(int x=0; x<nx; ++x) {
04693                                         idx1 = (size_t)z*nxy + y*nx + x;
04694                                         idx2 = (size_t)(nz-z-1+offset)*nxy + y*nx + x;
04695                                         std::swap(d[idx1], d[idx2]);
04696                                 }
04697                         }
04698                 }
04699         }
04700 
04701         image->update();
04702         EXITFUNC;
04703 }
04704 
04705 void AddNoiseProcessor::process_inplace(EMData * image)
04706 {
04707         if (!image) {
04708                 LOGWARN("NULL Image");
04709                 return;
04710         }
04711 
04712         Randnum * randnum = Randnum::Instance();
04713         if(params.has_key("seed")) {
04714                 randnum->set_seed((int)params["seed"]);
04715         }
04716 
04717         float addnoise = params["noise"];
04718         addnoise *= get_sigma(image);
04719         float *dat = image->get_data();
04720 
04721         for (size_t j = 0; j < image->get_size(); ++j) {
04722                 dat[j] += randnum->get_gauss_rand(addnoise, addnoise / 2);
04723         }
04724 
04725         image->update();
04726 }
04727 
04728 float AddSigmaNoiseProcessor::get_sigma(EMData * image)
04729 {
04730         if (!image) {
04731                 LOGWARN("NULL Image");
04732                 return 0;
04733         }
04734         return image->get_attr("sigma");
04735 }
04736 
04737 void FourierToCornerProcessor::process_inplace(EMData * image)
04738 {
04739         if ( !image->is_complex() ) throw ImageFormatException("Can not Fourier origin shift an image that is not complex");
04740 
04741         int nx=image->get_xsize();
04742         int ny=image->get_ysize();
04743         int nz=image->get_zsize();
04744 
04745         int nxy = nx*ny;
04746 
04747         if ( ny == 1 && nz == 1 ){
04748                 cout << "Warning- attempted     Fourier origin shift a 1D image - no action taken" << endl;
04749                 return;
04750         }
04751         int yodd = (ny%2==1);
04752         int zodd = (nz%2==1);
04753 
04754         float* rdata = image->get_data();
04755 
04756         float tmp[2];
04757         float* p1;
04758         float* p2;
04759 
04760         if (yodd){
04761                 // Swap the middle slice (with respect to the y direction) with the bottom slice
04762                 // shifting all slices above the middles slice upwards by one pixel, stopping
04763                 // at the middle slice, not if nz = 1 we are not talking about slices, we are
04764                 // talking about rows
04765                 float prev[2];
04766                 size_t idx;
04767                 for( int s = 0; s < nz; s++ ) {
04768                         for( int c =0; c < nx; c += 2 ) {
04769                                 idx = (size_t)s*nxy+ny/2*nx+c;
04770                                 prev[0] = rdata[idx];
04771                                 prev[1] = rdata[idx+1];
04772                                 for( int r = 0; r <= ny/2; ++r ) {
04773                                         idx = (size_t)s*nxy+r*nx+c;
04774                                         float* p1 = &rdata[idx];
04775                                         tmp[0] = p1[0];
04776                                         tmp[1] = p1[1];
04777 
04778                                         p1[0] = prev[0];
04779                                         p1[1] = prev[1];
04780 
04781                                         prev[0] = tmp[0];
04782                                         prev[1] = tmp[1];
04783                                 }
04784                         }
04785                 }
04786         }
04787 
04788         // Shift slices (3D) or rows (2D) correctly in the y direction
04789         size_t idx1, idx2;
04790         for( int s = 0; s < nz; ++s ) {
04791                 for( int r = 0 + yodd; r < ny/2+yodd; ++r ) {
04792                         for( int c =0; c < nx; c += 2 ) {
04793                                 idx1 = (size_t)s*nxy+r*nx+c;
04794                                 idx2 = (size_t)s*nxy+(r+ny/2)*nx+c;
04795                                 p1 = &rdata[idx1];
04796                                 p2 = &rdata[idx2];
04797 
04798                                 tmp[0] = p1[0];
04799                                 tmp[1] = p1[1];
04800 
04801                                 p1[0] = p2[0];
04802                                 p1[1] = p2[1];
04803 
04804                                 p2[0] = tmp[0];
04805                                 p2[1] = tmp[1];
04806                         }
04807                 }
04808         }
04809 
04810         if ( nz != 1 )
04811         {
04812 
04813                 if (zodd){
04814                         // Swap the middle slice (with respect to the z direction) and the front slice
04815                         // shifting all behind the front slice towards the middle a distance of 1 voxel,
04816                         // stopping at the middle slice.
04817                         float prev[2];
04818                         size_t idx;
04819                         for( int r = 0; r < ny; ++r ) {
04820                                 for( int c =0; c < nx; c += 2 ) {
04821                                         idx = (size_t)nz/2*nxy+r*nx+c;
04822                                         prev[0] = rdata[idx];
04823                                         prev[1] = rdata[idx+1];
04824                                         for( int s = 0; s <= nz/2; ++s ) {
04825                                                 idx = (size_t)s*nxy+r*nx+c;
04826                                                 float* p1 = &rdata[idx];
04827                                                 tmp[0] = p1[0];
04828                                                 tmp[1] = p1[1];
04829 
04830                                                 p1[0] = prev[0];
04831                                                 p1[1] = prev[1];
04832 
04833                                                 prev[0] = tmp[0];
04834                                                 prev[1] = tmp[1];
04835                                         }
04836                                 }
04837                         }
04838                 }
04839 
04840                 // Shift slices correctly in the z direction
04841                 size_t idx1, idx2;
04842                 for( int s = 0+zodd; s < nz/2 + zodd; ++s ) {
04843                         for( int r = 0; r < ny; ++r ) {
04844                                 for( int c =0; c < nx; c += 2 ) {
04845                                         idx1 = (size_t)s*nxy+r*nx+c;
04846                                         idx2 = (size_t)(s+nz/2)*nxy+r*nx+c;
04847                                         p1 = &rdata[idx1];
04848                                         p2 = &rdata[idx2];
04849 
04850                                         tmp[0] = p1[0];
04851                                         tmp[1] = p1[1];
04852 
04853                                         p1[0] = p2[0];
04854                                         p1[1] = p2[1];
04855 
04856                                         p2[0] = tmp[0];
04857                                         p2[1] = tmp[1];
04858                                 }
04859                         }
04860                 }
04861         }
04862         image->set_shuffled(false);
04863 }
04864 
04865 void FourierToCenterProcessor::process_inplace(EMData * image)
04866 {
04867 //      if ( !image->is_complex() ) throw ImageFormatException("Can not Fourier origin shift an image that is not complex");
04868 
04869         int nx=image->get_xsize();
04870         int ny=image->get_ysize();
04871         int nz=image->get_zsize();
04872 
04873         int nxy = nx*ny;
04874 
04875         if ( ny == 1 && nz == 1 ){
04876                 cout << "Warning- attempted     Fourier origin shift a 1D image - no action taken" << endl;
04877                 return;
04878         }
04879 
04880         int yodd = (ny%2==1);
04881         int zodd = (nz%2==1);
04882 
04883         float* rdata = image->get_data();
04884 
04885         float tmp[2];
04886         float* p1;
04887         float* p2;
04888 
04889         // This will tackle the 'normalization' images which come out of the Fourier reconstructor.
04890         // ie- real-space 1/2 FFt images centered on the corner
04891         if ( !image->is_complex() ) {
04892                 if (nz!=1 && !yodd && !zodd) {
04893                         for (int x=0; x<nx; x++) {
04894                                 for (int y=0; y<ny; y++) {
04895                                         for (int z=0; z<nz/2; z++) {
04896                                                 int y2=(y+ny/2)%ny;
04897                                                 int z2=(z+nz/2)%nz;             // %nz should be redundant here
04898                                                 size_t i=x+y*nx+(size_t)z*nxy;
04899                                                 size_t i2=x+y2*nx+(size_t)z2*nxy;
04900                                                 float swp=rdata[i];
04901                                                 rdata[i]=rdata[i2];
04902                                                 rdata[i2]=swp;
04903                                         }
04904                                 }
04905                         }
04906 
04907                         return;
04908                 }
04909                 else throw ImageFormatException("Can not Fourier origin shift an image that is not complex unless it is even in ny,nz and nx=ny/2+1");
04910         }
04911 
04912         if (yodd){
04913                 // In 3D this is swapping the bottom slice (with respect to the y direction) and the middle slice,
04914                 // shifting all slices below the middle slice down one. In 2D it is equivalent, but in terms of rows.
04915                 float prev[2];
04916                 size_t idx;
04917                 for( int s = 0; s < nz; s++ ) {
04918                         for( int c =0; c < nx; c += 2 ) {
04919                                 idx = (size_t)s*nxy+c;
04920                                 prev[0] = rdata[idx];
04921                                 prev[1] = rdata[idx+1];
04922                                 for( int r = ny/2; r >= 0; --r ) {
04923                                         idx = (size_t)s*nxy+r*nx+c;
04924                                         float* p1 = &rdata[idx];
04925                                         tmp[0] = p1[0];
04926                                         tmp[1] = p1[1];
04927 
04928                                         p1[0] = prev[0];
04929                                         p1[1] = prev[1];
04930 
04931                                         prev[0] = tmp[0];
04932                                         prev[1] = tmp[1];
04933                                 }
04934                         }
04935                 }
04936         }
04937 
04938         // 3D - Shift slices correctly in the y direction, 2D - shift rows
04939         size_t idx1, idx2;
04940         for( int s = 0; s < nz; ++s ) {
04941                 for( int r = 0; r < ny/2; ++r ) {
04942                         for( int c =0; c < nx; c += 2 ) {
04943                                 idx1 = (size_t)s*nxy+r*nx+c;
04944                                 idx2 = (size_t)s*nxy+(r+ny/2+yodd)*nx+c;
04945                                 p1 = &rdata[idx1];
04946                                 p2 = &rdata[idx2];
04947 
04948                                 tmp[0] = p1[0];
04949                                 tmp[1] = p1[1];
04950 
04951                                 p1[0] = p2[0];
04952                                 p1[1] = p2[1];
04953 
04954                                 p2[0] = tmp[0];
04955                                 p2[1] = tmp[1];
04956                         }
04957                 }
04958         }
04959 
04960         if ( nz != 1 )  {
04961                 if (zodd){
04962                         // Swap the front slice (with respect to the z direction) and the middle slice
04963                         // shifting all slices behind the middles slice towards the front slice 1 voxel.
04964                         float prev[2];
04965                         size_t idx;
04966                         for( int r = 0; r < ny; ++r ) {
04967                                 for( int c =0; c < nx; c += 2 ) {
04968                                         prev[0] = rdata[r*nx+c];
04969                                         prev[1] = rdata[r*nx+c+1];
04970                                         for( int s = nz/2; s >= 0; --s ) {
04971                                                 idx = (size_t)s*nxy+r*nx+c;
04972                                                 float* p1 = &rdata[idx];
04973                                                 tmp[0] = p1[0];
04974                                                 tmp[1] = p1[1];
04975 
04976                                                 p1[0] = prev[0];
04977                                                 p1[1] = prev[1];
04978 
04979                                                 prev[0] = tmp[0];
04980                                                 prev[1] = tmp[1];
04981                                         }
04982                                 }
04983                         }
04984                 }
04985 
04986                 // Shift slices correctly in the y direction
04987                 size_t idx1, idx2;
04988                 for( int s = 0; s < nz/2; ++s ) {
04989                         for( int r = 0; r < ny; ++r ) {
04990                                 for( int c =0; c < nx; c += 2 ) {
04991                                         idx1 = (size_t)s*nxy+r*nx+c;
04992                                         idx2 = (size_t)(s+nz/2+zodd)*nxy+r*nx+c;
04993                                         p1 = &rdata[idx1];
04994                                         p2 = &rdata[idx2];
04995 
04996                                         tmp[0] = p1[0];
04997                                         tmp[1] = p1[1];
04998 
04999                                         p1[0] = p2[0];
05000                                         p1[1] = p2[1];
05001 
05002                                         p2[0] = tmp[0];
05003                                         p2[1] = tmp[1];
05004                                 }
05005                         }
05006                 }
05007         }
05008         image->set_shuffled(true);
05009 }
05010 
05011 void Phase180Processor::fourier_phaseshift180(EMData * image)
05012 {
05013         if ( !image->is_complex() ) throw ImageFormatException("Can not handle images that are not complex in fourier phase shift 180");
05014 
05015         int nx = image->get_xsize();
05016         int ny = image->get_ysize();
05017         int nz = image->get_zsize();
05018 
05019         int nxy = nx * ny;
05020 
05021         float *rdata = image->get_data();
05022 
05023         // Who uses this function? It doesn't work for odd images, and it will give incorrect results for some even images
05024         // d.woolford, March 15 2009
05025         int of=0;
05026         if (((ny/2)%2)+((nz/2)%2)==1) of=1;
05027 
05028         for (int k = 0; k < nz; k++) {
05029                 size_t k2 = (size_t)k * nxy;
05030 
05031                 for (int j = 0; j < ny; j++) {
05032                         int i = ((k+j)%2==of?2:0);
05033                         size_t j2 = j * nx + k2;
05034 
05035                         for (; i < nx; i += 4) {
05036                                 rdata[i + j2] *= -1.0f;
05037                                 rdata[i + j2 + 1] *= -1.0f;
05038                         }
05039                 }
05040         }
05041 }
05042 
05043 void Phase180Processor::swap_corners_180(EMData * image)
05044 {
05045         int nx = image->get_xsize();
05046         int ny = image->get_ysize();
05047         int nz = image->get_zsize();
05048 
05049         int xodd = (nx % 2) == 1;
05050         int yodd = (ny % 2) == 1;
05051         int zodd = (nz % 2) == 1;
05052 
05053         int nxy = nx * ny;
05054 
05055         float *rdata = image->get_data();
05056 
05057         if ( ny == 1 && nz == 1 ){
05058                 throw ImageDimensionException("Error, cannot handle 1D images. This function should not have been called");
05059         }
05060         else if ( nz == 1 ) {
05061 
05062                 // Swap the bottom left and top right corners
05063                 for ( int r = 0; r < ny/2; ++r ) {
05064                         for ( int c = 0; c < nx/2; ++c) {
05065                                 int idx1 = r*nx + c;
05066                                 int idx2 = (r+ny/2+yodd)*nx + c + nx/2+xodd;
05067                                 float tmp = rdata[idx1];
05068                                 rdata[idx1] = rdata[idx2];
05069                                 rdata[idx2] = tmp;
05070                         }
05071                 }
05072 
05073                 // Swap the top left and bottom right corners
05074                 for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
05075                         for ( int c = 0; c < nx/2; ++c) {
05076                                 int idx1 = r*nx + c;
05077                                 int idx2 = (r-ny/2-yodd)*nx + c + nx/2+xodd;
05078                                 float tmp = rdata[idx1];
05079                                 rdata[idx1] = rdata[idx2];
05080                                 rdata[idx2] = tmp;
05081                         }
05082                 }
05083         }
05084         else // nx && ny && nz are greater than 1
05085         {
05086                 float tmp;
05087                 // Swap the bottom left front and back right top quadrants
05088                 size_t idx1, idx2;
05089 
05090                 for ( int s = 0; s < nz/2; ++s ) {
05091                         for ( int r = 0; r < ny/2; ++r ) {
05092                                 for ( int c = 0; c < nx/2; ++ c) {
05093                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05094                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c+nx/2+xodd;
05095                                         tmp = rdata[idx1];
05096                                         rdata[idx1] = rdata[idx2];
05097                                         rdata[idx2] = tmp;
05098                                 }
05099                         }
05100                 }
05101                 // Swap the bottom right front and back left top quadrants
05102                 for ( int s = 0; s < nz/2; ++s ) {
05103                         for ( int r = 0; r < ny/2; ++r ) {
05104                                 for ( int c = nx-1; c >= (nx/2+xodd); --c) {
05105                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05106                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c-nx/2-xodd;
05107                                         tmp = rdata[idx1];
05108                                         rdata[idx1] = rdata[idx2];
05109                                         rdata[idx2] = tmp;
05110                                 }
05111                         }
05112                 }
05113                 // Swap the top right front and back left bottom quadrants
05114                 for ( int s = 0; s < nz/2; ++s ) {
05115                         for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
05116                                 for ( int c = nx-1; c >= (nx/2+xodd); --c) {
05117                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05118                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r-ny/2-yodd)*(size_t)nx+c-nx/2-xodd;
05119                                         tmp = rdata[idx1];
05120                                         rdata[idx1] = rdata[idx2];
05121                                         rdata[idx2] = tmp;
05122                                 }
05123                         }
05124                 }
05125                 // Swap the top left front and back right bottom quadrants
05126                 for ( int s = 0; s < nz/2; ++s ) {
05127                         for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
05128                                 for ( int c = 0; c < nx/2; ++c) {
05129                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05130                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r-ny/2-yodd)*(size_t)nx+c+nx/2+xodd;
05131                                         tmp = rdata[idx1];
05132                                         rdata[idx1] = rdata[idx2];
05133                                         rdata[idx2] = tmp;
05134                                 }
05135                         }
05136                 }
05137         }
05138 }
05139 
05140 void Phase180Processor::swap_central_slices_180(EMData * image)
05141 {
05142         int nx = image->get_xsize();
05143         int ny = image->get_ysize();
05144         int nz = image->get_zsize();
05145 
05146         int xodd = (nx % 2) == 1;
05147         int yodd = (ny % 2) == 1;
05148         int zodd = (nz % 2) == 1;
05149 
05150         int nxy = nx * ny;
05151 
05152         float *rdata = image->get_data();
05153 
05154         if ( ny == 1 && nz == 1 ){
05155                 throw ImageDimensionException("Error, cannot handle 1D images. This function should not have been called");
05156         }
05157         else if ( nz == 1 ) {
05158                 float tmp;
05159                 if ( yodd ) {
05160                         // Iterate along middle row, swapping values where appropriate
05161                         int r = ny/2;
05162                         for ( int c = 0; c < nx/2; ++c ) {
05163                                 int idx1 = r*nx + c;
05164                                 int idx2 = r*nx + c + nx/2+ xodd;
05165                                 tmp = rdata[idx1];
05166                                 rdata[idx1] = rdata[idx2];
05167                                 rdata[idx2] = tmp;
05168                         }
05169                 }
05170 
05171                 if ( xodd )     {
05172                         // Iterate along the central column, swapping values where appropriate
05173                         int c = nx/2;
05174                         for (  int r = 0; r < ny/2; ++r ) {
05175                                 int idx1 = r*nx + c;
05176                                 int idx2 = (r+ny/2+yodd)*nx + c;
05177                                 tmp = rdata[idx1];
05178                                 rdata[idx1] = rdata[idx2];
05179                                 rdata[idx2] = tmp;
05180                         }
05181                 }
05182         }
05183         else // nx && ny && nz are greater than 1
05184         {
05185                 float tmp;
05186                 if ( xodd ) {
05187                         // Iterate along the x = nx/2 slice, swapping values where appropriate
05188                         int c = nx/2;
05189                         size_t idx1, idx2;
05190                         for( int s = 0; s < nz/2; ++s ) {
05191                                 for ( int r = 0; r < ny/2; ++r ) {
05192                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05193                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c;
05194                                         tmp = rdata[idx1];
05195                                         rdata[idx1] = rdata[idx2];
05196                                         rdata[idx2] = tmp;
05197                                 }
05198                         }
05199 
05200                         for( int s = nz-1; s >= (nz/2+zodd); --s ) {
05201                                 for ( int r = 0; r < ny/2; ++r ) {
05202                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05203                                         idx2 = (s-nz/2-zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c;
05204                                         tmp = rdata[idx1];
05205                                         rdata[idx1] = rdata[idx2];
05206                                         rdata[idx2] = tmp;
05207                                 }
05208                         }
05209                 }
05210                 if ( yodd ) {
05211                         // Iterate along the y = ny/2 slice, swapping values where appropriate
05212                         int r = ny/2;
05213                         size_t idx1, idx2;
05214                         for( int s = 0; s < nz/2; ++s ) {
05215                                 for ( int c = 0; c < nx/2; ++c ) {
05216                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05217                                         idx2 =(s+nz/2+zodd)*(size_t)nxy+(size_t)r*nx+c+nx/2+xodd;
05218                                         tmp = rdata[idx1];
05219                                         rdata[idx1] = rdata[idx2];
05220                                         rdata[idx2] = tmp;
05221                                 }
05222                         }
05223 
05224                         for( int s = nz-1; s >= (nz/2+zodd); --s ) {
05225                                 for ( int c = 0; c < nx/2; ++c ) {
05226                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05227                                         idx2 = (s-nz/2-zodd)*(size_t)nxy+(size_t)r*nx+c+nx/2+xodd;
05228                                         tmp = rdata[idx1];
05229                                         rdata[idx1] = rdata[idx2];
05230                                         rdata[idx2] = tmp;
05231                                 }
05232                         }
05233                 }
05234                 if ( zodd ) {
05235                         // Iterate along the z = nz/2 slice, swapping values where appropriate
05236                         int s = nz/2;
05237                         size_t idx1, idx2;
05238                         for( int r = 0; r < ny/2; ++r ) {
05239                                 for ( int c = 0; c < nx/2; ++c ) {
05240                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05241                                         idx2 = (size_t)s*nxy+(r+ny/2+yodd)*(size_t)nx+c+nx/2+xodd;
05242                                         tmp = rdata[idx1];
05243                                         rdata[idx1] = rdata[idx2];
05244                                         rdata[idx2] = tmp;
05245                                 }
05246                         }
05247 
05248                         for( int r = ny-1; r >= (ny/2+yodd); --r ) {
05249                                 for ( int c = 0; c < nx/2; ++c ) {
05250                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05251                                         idx2 = (size_t)s*nxy+(r-ny/2-yodd)*(size_t)nx+c+nx/2+xodd;
05252                                         tmp = rdata[idx1];
05253                                         rdata[idx1] = rdata[idx2];
05254                                         rdata[idx2] = tmp;
05255                                 }
05256                         }
05257                 }
05258         }
05259 }
05260 
05261 void PhaseToCornerProcessor::process_inplace(EMData * image)
05262 {
05263         if (!image)     throw NullPointerException("Error: attempt to phase shift a null image");
05264 
05265 #ifdef EMAN2_USING_CUDA
05266         if (EMData::usecuda == 1 && image->getcudarwdata() && image->get_ndim() == 2) { // Because CUDA phase origin to center only works for 2D atm
05267                 //cout << "CUDA tocorner " << image->getcudarwdata() << endl;
05268                 emdata_phaseorigin_to_corner(image->getcudarwdata(), image->get_xsize(), image->get_ysize(), image->get_zsize());
05269                 return;
05270         }
05271 #endif // EMAN2_USING_CUDA
05272 
05273         if (image->is_complex()) {
05274                 fourier_phaseshift180(image);
05275                 return;
05276         }
05277 
05278         int nx = image->get_xsize();
05279         int ny = image->get_ysize();
05280         int nz = image->get_zsize();
05281 
05282         if ( ny == 1 && nz == 1 && nx == 1) return;
05283 
05284         int nxy = nx * ny;
05285 
05286         float *rdata = image->get_data();
05287 
05288         bool xodd = (nx % 2) == 1;
05289         bool yodd = (ny % 2) == 1;
05290         bool zodd = (nz % 2) == 1;
05291 
05292         if ( ny == 1 && nz == 1 ){
05293                 if (xodd){
05294                         // Put the last pixel in the center, shifting the contents
05295                         // to right of the center one step to the right
05296                         float in_x = rdata[nx-1];
05297                         float tmp;
05298                         for ( int i = nx/2; i < nx; ++i ) {
05299                                 tmp = rdata[i];
05300                                 rdata[i] = in_x;
05301                                 in_x = tmp;
05302                         }
05303                 }
05304                 // now the operation is straight forward
05305                 for ( int i = 0; i < nx/2; ++i ) {
05306                         int idx = i+nx/2+xodd;
05307                         float tmp = rdata[i];
05308                         rdata[i] = rdata[idx];
05309                         rdata[idx] = tmp;
05310                 }
05311 
05312         }
05313         else if ( nz == 1 ) {
05314                 if (yodd) {
05315                         // Tranfer the top row into the middle row,
05316                         // shifting all pixels above and including the current middle up one.
05317                         for ( int c = 0; c < nx; ++c ) {
05318                                 // Get the value in the top row
05319                                 float last_val = rdata[(ny-1)*nx + c];
05320                                 float tmp;
05321                                 for ( int r = ny/2; r < ny; ++r ){
05322                                         int idx =r*nx+c;
05323                                         tmp = rdata[idx];
05324                                         rdata[idx] = last_val;
05325                                         last_val = tmp;
05326                                 }
05327                         }
05328                 }
05329 
05330                 if (xodd) {
05331                         // Transfer the right most column into the center column
05332                         // Shift all columns right of and including center to the right one pixel
05333                         for ( int r  = 0; r < ny; ++r ) {
05334                                 float last_val = rdata[(r+1)*nx -1];
05335                                 float tmp;
05336                                 for ( int c = nx/2; c < nx; ++c ){
05337                                         int idx =r*nx+c;
05338                                         tmp = rdata[idx];
05339                                         rdata[idx] = last_val;
05340                                         last_val = tmp;
05341                                 }
05342                         }
05343                 }
05344                 // It is important central slice shifting come after the previous two operations
05345                 swap_central_slices_180(image);
05346                 // Now the corners of the image can be shifted...
05347                 swap_corners_180(image);
05348 
05349         }
05350         else
05351         {
05352                 float tmp;
05353                 if (zodd) {
05354                         // Tranfer the back slice into the middle slice,
05355                         // shifting all pixels beyond and including the middle slice back one.
05356                         size_t idx = 0;
05357                         for (int r = 0; r < ny; ++r){
05358                                 for (int c = 0; c < nx; ++c) {
05359                                         float last_val = rdata[(nz-1)*nxy+r*nx+c];
05360                                         for (int s = nz/2; s < nz; ++s) {
05361                                                 idx = (size_t)s*nxy+r*nx+c;
05362                                                 tmp = rdata[idx];
05363                                                 rdata[idx] = last_val;
05364                                                 last_val = tmp;
05365                                         }
05366                                 }
05367                         }
05368                 }
05369                 if (yodd) {
05370                         // Tranfer the top slice into the middle slice,
05371                         // shifting all pixels above and including the middle slice up one.
05372                         size_t idx = 0;
05373                         for (int s = 0; s < nz; ++s) {
05374                                 for (int c = 0; c < nx; ++c) {
05375                                 float last_val = rdata[s*nxy+(ny-1)*nx+c];
05376                                         for (int r = ny/2; r < ny; ++r){
05377                                                 idx = (size_t)s*nxy+r*nx+c;
05378                                                 tmp = rdata[idx];
05379                                                 rdata[idx] = last_val;
05380                                                 last_val = tmp;
05381                                         }
05382                                 }
05383                         }
05384                 }
05385                 if (xodd) {
05386                         // Transfer the right most slice into the central slice
05387                         // Shift all pixels to right of and including center slice to the right one pixel
05388                         size_t idx = 0;
05389                         for (int s = 0; s < nz; ++s) {
05390                                 for (int r = 0; r < ny; ++r) {
05391                                         float last_val = rdata[s*nxy+r*nx+nx-1];
05392                                         for (int c = nx/2; c < nx; ++c){
05393                                                 idx = (size_t)s*nxy+r*nx+c;
05394                                                 tmp = rdata[idx];
05395                                                 rdata[idx] = last_val;
05396                                                 last_val = tmp;
05397                                         }
05398                                 }
05399                         }
05400                 }
05401                 // Now swap the various parts in the central slices
05402                 swap_central_slices_180(image);
05403                 // Now shift the corners
05404                 swap_corners_180(image);
05405         }
05406 }
05407 
05408 
05409 void PhaseToCenterProcessor::process_inplace(EMData * image)
05410 {
05411         if (!image)     throw NullPointerException("Error: attempt to phase shift a null image");
05412 
05413 #ifdef EMAN2_USING_CUDA
05414         if (EMData::usecuda == 1 && image->getcudarwdata() && image->get_ndim() == 2) { // Because CUDA phase origin to center only works for 2D atm
05415                 //cout << "CUDA tocenter" << endl;
05416                 emdata_phaseorigin_to_center(image->getcudarwdata(), image->get_xsize(), image->get_ysize(), image->get_zsize());
05417                 return;
05418         }
05419 #endif // EMAN2_USING_CUDA
05420 
05421         if (image->is_complex()) {
05422                 fourier_phaseshift180(image);
05423                 return;
05424         }
05425 
05426         int nx = image->get_xsize();
05427         int ny = image->get_ysize();
05428         int nz = image->get_zsize();
05429 
05430         if ( ny == 1 && nz == 1 && nx == 1) return;
05431 
05432         int nxy = nx * ny;
05433 
05434         float *rdata = image->get_data();
05435 
05436         bool xodd = (nx % 2) == 1;
05437         bool yodd = (ny % 2) == 1;
05438         bool zodd = (nz % 2) == 1;
05439 
05440         if ( ny == 1 && nz == 1 ){
05441                 if (xodd) {
05442                         // Put the center pixel at the end, shifting the contents
05443                         // to right of the center one step to the left
05444                         float in_x = rdata[nx/2];
05445                         float tmp;
05446                         for ( int i = nx-1; i >= nx/2; --i ) {
05447                                 tmp = rdata[i];
05448                                 rdata[i] = in_x;
05449                                 in_x = tmp;
05450                         }
05451                 }
05452                 // now the operation is straight forward
05453                 for ( int i = 0; i < nx/2; ++i ) {
05454                         int idx = i + nx/2;
05455                         float tmp = rdata[i];
05456                         rdata[i] = rdata[idx];
05457                         rdata[idx] = tmp;
05458                 }
05459         }
05460         else if ( nz == 1 ){
05461                 // The order in which these operations occur literally undoes what the
05462                 // PhaseToCornerProcessor did to the image.
05463                 // First, the corners sections of the image are swapped appropriately
05464                 swap_corners_180(image);
05465                 // Second, central pixel lines are swapped
05466                 swap_central_slices_180(image);
05467 
05468                 float tmp;
05469                 // Third, appropriate sections of the image are cyclically shifted by one pixel
05470                 if (xodd) {
05471                         // Transfer the middle column to the far right
05472                         // Shift all from the far right to (but not including the) middle one to the left
05473                         for ( int r  = 0; r < ny; ++r ) {
05474                                 float last_val = rdata[r*nx+nx/2];
05475                                 for ( int c = nx-1; c >=  nx/2; --c ){
05476                                         int idx = r*nx+c;
05477                                         tmp = rdata[idx];
05478                                         rdata[idx] = last_val;
05479                                         last_val = tmp;
05480                                 }
05481                         }
05482                 }
05483                 if (yodd) {
05484                         // Tranfer the middle row to the top,
05485                         // shifting all pixels from the top row down one, until  but not including the) middle
05486                         for ( int c = 0; c < nx; ++c ) {
05487                                 // Get the value in the top row
05488                                 float last_val = rdata[ny/2*nx + c];
05489                                 for ( int r = ny-1; r >= ny/2; --r ){
05490                                         int idx = r*nx+c;
05491                                         tmp = rdata[idx];
05492                                         rdata[idx] = last_val;
05493                                         last_val = tmp;
05494                                 }
05495                         }
05496                 }
05497         }
05498         else
05499         {
05500                 // The order in which these operations occur literally undoes the
05501                 // PhaseToCornerProcessor operation - in 3D.
05502                 // First, the corner quadrants of the voxel volume are swapped
05503                 swap_corners_180(image);
05504                 // Second, appropriate parts of the central slices are swapped
05505                 swap_central_slices_180(image);
05506 
05507                 float tmp;
05508                 // Third, appropriate sections of the image are cyclically shifted by one voxel
05509                 if (xodd) {
05510                         // Transfer the central slice in the x direction to the far right
05511                         // moving all slices on the far right toward the center one pixel, until
05512                         // the center x slice is ecountered
05513                         size_t idx = 0;
05514                         for (int s = 0; s < nz; ++s) {
05515                                 for (int r = 0; r < ny; ++r) {
05516                                         float last_val = rdata[s*nxy+r*nx+nx/2];
05517                                         for (int c = nx-1; c >= nx/2; --c){
05518                                                 idx = (size_t)s*nxy+r*nx+c;
05519                                                 tmp = rdata[idx];
05520                                                 rdata[idx] = last_val;
05521                                                 last_val = tmp;
05522                                         }
05523                                 }
05524                         }
05525                 }
05526                 if (yodd) {
05527                         // Tranfer the central slice in the y direction to the top
05528                         // shifting all pixels below it down on, until the center y slice is encountered.
05529                         size_t idx = 0;
05530                         for (int s = 0; s < nz; ++s) {
05531                                 for (int c = 0; c < nx; ++c) {
05532                                         float last_val = rdata[s*nxy+ny/2*nx+c];
05533                                         for (int r = ny-1; r >= ny/2; --r){
05534                                                 idx = (size_t)s*nxy+r*nx+c;
05535                                                 tmp = rdata[idx];
05536                                                 rdata[idx] = last_val;
05537                                                 last_val = tmp;
05538                                         }
05539                                 }
05540                         }
05541                 }
05542                 if (zodd) {
05543                         // Tranfer the central slice in the z direction to the back
05544                         // shifting all pixels beyond and including the middle slice back one.
05545                         size_t idx = 0;
05546                         for (int r = 0; r < ny; ++r){
05547                                 for (int c = 0; c < nx; ++c) {
05548                                         float last_val = rdata[nz/2*nxy+r*nx+c];
05549                                         for (int s = nz-1; s >= nz/2; --s) {
05550                                                 idx = (size_t)s*nxy+r*nx+c;
05551                                                 tmp = rdata[idx];
05552                                                 rdata[idx] = last_val;
05553                                                 last_val = tmp;
05554                                         }
05555                                 }
05556                         }
05557                 }
05558 
05559 
05560         }
05561 }
05562 
05563 void AutoMaskAsymUnit::process_inplace(EMData* image) {
05564         if (!image) {
05565                 LOGWARN("NULL Image");
05566                 return;
05567         }
05568 
05569         int nx = image->get_xsize();
05570         int ny = image->get_ysize();
05571         int nz = image->get_zsize();
05572 
05573         int ox = nx/2;
05574         int oy = ny/2;
05575         int oz = nz/2;
05576 
05577         Symmetry3D* sym = Factory<Symmetry3D>::get((string)params["sym"]);
05578         int au = params.set_default("au",0);
05579 
05580         float *d = image->get_data();
05581         for(int k = 0; k < nz; ++k ) {
05582                 for(int j = 0; j < ny; ++j ) {
05583                         for (int i = 0; i< nx; ++i, ++d) {
05584                                 //cout << i << " " << j << " " << k << endl;
05585                                 Vec3f v(i-ox,j-oy,k-oz);
05586 //                              v.normalize();
05587                                 int a = sym->point_in_which_asym_unit(v);
05588                                 if (au == -1) {
05589                                         *d = (float)a;
05590                                 } else {
05591                                         if ( a == au ) *d = 1;
05592                                         else *d = 0;
05593                                 }
05594                         }
05595                 }
05596         }
05597 
05598         delete sym;
05599 
05600 }
05601 
05602 void AutoMask2DProcessor::process_inplace(EMData * image)
05603 {
05604         if (!image) {
05605                 LOGWARN("NULL Image");
05606                 return;
05607         }
05608 
05609         if (image->get_ndim() != 2) {
05610                 throw ImageDimensionException("This processor only supports 2D images.");
05611         }
05612 
05613         /*
05614          The mask writing functionality was removed to comply with an EMAN2 policy which dictates that file io is not allowed from within a processor
05615          To get around this just use the return_mask parameter.
05616         string mask_output = params.set_default("write_mask", "");
05617         if ( mask_output != "") {
05618                 if (Util::is_file_exist(mask_output) ) throw InvalidParameterException("The mask output file name already exists. Please remove it if you don't need it.");
05619                 if (!EMUtil::is_valid_filename(mask_output)) throw InvalidParameterException("The mask output file name type is invalid or unrecognized");
05620         }
05621         */
05622 
05623         int radius=0;
05624         if (params.has_key("radius")) {
05625                 radius = params["radius"];
05626         }
05627         int nmaxseed=0;
05628         if (params.has_key("nmaxseed")) {
05629                 nmaxseed = params["nmaxseed"];
05630         }
05631 
05632         float threshold=0.0;
05633         if (params.has_key("sigma")) threshold=(float)(image->get_attr("mean"))+(float)(image->get_attr("sigma"))*(float)params["sigma"];
05634         else threshold=params["threshold"];
05635 
05636 
05637         int nshells = params["nshells"];
05638         int nshellsgauss = params["nshellsgauss"];
05639         int verbose=params.set_default("verbose",0);
05640 
05641         int nx = image->get_xsize();
05642         int ny = image->get_ysize();
05643 
05644         EMData *amask = new EMData();
05645         amask->set_size(nx, ny);
05646 
05647         float *dat = image->get_data();
05648         float *dat2 = amask->get_data();
05649         int i,j;
05650         size_t l = 0;
05651 
05652         if (verbose) printf("%f\t%f\t%f\n",(float)image->get_attr("mean"),(float)image->get_attr("sigma"),threshold);
05653 
05654         // Seeds with the highest valued pixels
05655         if (nmaxseed>0) {
05656                 vector<Pixel> maxs=image->calc_n_highest_locations(nmaxseed);
05657 
05658                 for (vector<Pixel>::iterator i=maxs.begin(); i<maxs.end(); i++) {
05659                         amask->set_value_at((*i).x,(*i).y,0,1.0);
05660                         if (verbose) printf("Seed at %d,%d,%d (%1.3f)\n",(*i).x,(*i).y,(*i).z,(*i).value);
05661                 }
05662         }
05663 
05664         // Seeds with a circle
05665         if (radius>0) {
05666                 // start with an initial circle
05667                 l=0;
05668                 for (j = -ny / 2; j < ny / 2; ++j) {
05669                         for (i = -nx / 2; i < nx / 2; ++i,++l) {
05670                                 if ( abs(j) > radius || abs(i) > radius) continue;
05671 //                              if ( (j * j + i * i) > (radius*radius) || dat[l] < threshold) continue;         // torn on the whole threshold issue here. Removing it prevents images from being totally masked out
05672                                 if ( (j * j + i * i) > (radius*radius) ) continue;
05673                                 dat2[l] = 1.0f;
05674                         }
05675                 }
05676         }
05677 
05678         // iteratively 'flood fills' the map... recursion would be better
05679         int done=0;
05680         int iter=0;
05681         while (!done) {
05682                 iter++;
05683                 done=1;
05684                 if (verbose && iter%10==0) printf("%d iterations\n",iter);
05685                 for (j=1; j<ny-1; ++j) {
05686                         for (i=1; i<nx-1; ++i) {
05687                                 l=i+j*nx;
05688                                 if (dat2[l]) continue;
05689                                 if (dat[l]>threshold && (dat2[l-1]||dat2[l+1]||dat2[l+nx]||dat2[l-nx])) {
05690                                         dat2[l]=1.0;
05691                                         done=0;
05692                                 }
05693                         }
05694                 }
05695         }
05696 
05697         amask->update();
05698 
05699         if (verbose) printf("extending mask\n");
05700         amask->process_inplace("mask.addshells.gauss", Dict("val1", nshells, "val2", nshellsgauss));
05701 
05702         bool return_mask = params.set_default("return_mask",false);
05703         if (return_mask) {
05704                 // Yes there is probably a much more efficient way of getting the mask itself, but I am only providing a stop gap at the moment.
05705                 memcpy(dat,dat2,image->get_size()*sizeof(float));
05706         } else {
05707                 image->mult(*amask);
05708         }
05709 
05710         // EMAN2 policy is not to allow file io from with a processor
05711         //if (mask_output != "") {
05712         //      amask->write_image(mask_output);
05713         //}
05714 
05715 
05716         delete amask;
05717 }
05718 
05719 void CtfSimProcessor::process_inplace(EMData *image) {
05720         EMData *tmp=process(image);
05721         memcpy(image->get_data(),tmp->get_data(),(size_t)image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
05722         delete tmp;
05723         image->update();
05724         return;
05725 }
05726 
05727 EMData* CtfSimProcessor::process(const EMData * const image) {
05728         if (!image) {
05729                 LOGWARN("NULL Image");
05730                 return NULL;
05731         }
05732 
05733         EMData *fft;
05734         if (!image->is_complex()) fft=image->do_fft();
05735         else fft=image->copy();
05736 
05737         EMAN2Ctf ctf;
05738         ctf.defocus=params["defocus"];
05739         ctf.bfactor=params["bfactor"];
05740         ctf.ampcont=params.set_default("ampcont",10.0f);
05741         ctf.voltage=params.set_default("voltage",200.0f);
05742         ctf.cs=params.set_default("cs",2.0);
05743         ctf.apix=params.set_default("apix",image->get_attr_default("apix_x",1.0));
05744         ctf.dsbg=1.0/(ctf.apix*fft->get_ysize()*4.0);           //4x oversampling
05745 
05746         float noiseamp=params.set_default("noiseamp",0.0f);
05747         float noiseampwhite=params.set_default("noiseampwhite",0.0f);
05748 
05749         // compute and apply the CTF
05750         vector <float> ctfc = ctf.compute_1d(fft->get_ysize()*6,ctf.dsbg,ctf.CTF_AMP,NULL); // *6 goes to corner, remember you provide 2x the number of points you need
05751 
05752 //      printf("%1.3f\t%1.3f\t%1.3f\t%1.3f\t%1.3f\t%d\n",ctf.defocus,ctf.bfactor,ctf.ampcont,ctf.dsbg,ctf.apix,fft->get_ysize());
05753 //      FILE *out=fopen("x.txt","w");
05754 //      for (int i=0; i<ctfc.size(); i++) fprintf(out,"%f\t%1.3g\n",0.25*i/(float)fft->get_ysize(),ctfc[i]);
05755 //      fclose(out);
05756 
05757         fft->apply_radial_func(0,0.25f/fft->get_ysize(),ctfc,1);
05758 
05759         // Add noise
05760         if (noiseamp!=0 || noiseampwhite!=0) {
05761                 EMData *noise = new EMData(image->get_ysize(),image->get_ysize(),1);
05762                 noise->process_inplace("testimage.noise.gauss");
05763                 noise->do_fft_inplace();
05764 
05765                 // White noise
05766                 if (noiseampwhite!=0) {
05767                         noise->mult((float)noiseampwhite*15.0f);                // The 15.0 is to roughly compensate for the stronger pink noise curve
05768                         fft->add(*noise);
05769                         noise->mult((float)1.0/(noiseampwhite*15.0f));
05770                 }
05771 
05772                 // Pink noise
05773                 if (noiseamp!=0) {
05774                         vector <float> pinkbg;
05775                         pinkbg.resize(500);
05776                         float nyimg=0.5f/ctf.apix;      // image nyquist
05777                         // This pink curve came from a typical image in the GroEL 4A data set
05778                         for (int i=0; i<500; i++) pinkbg[i]=noiseamp*(44.0f*exp(-5.0f*nyimg*i/250.0f)+10.0f*exp(-90.0f*nyimg*i/250.0f));                // compute curve to image Nyquist*2
05779                         noise->apply_radial_func(0,.002f,pinkbg,1);             // Image nyquist is at 250 -> 0.5
05780                         fft->add(*noise);
05781                 }
05782 
05783         }
05784 
05785         EMData *ret=fft->do_ift();
05786         delete fft;
05787 
05788         return ret;
05789 }
05790 
05791 void AddRandomNoiseProcessor::process_inplace(EMData * image)
05792 {
05793         if (!image) {
05794                 LOGWARN("NULL Image");
05795                 return;
05796         }
05797 
05798         if (!image->is_complex()) {
05799                 LOGERR("AddRandomNoise Processor only works for complex image");
05800                 throw ImageFormatException("only work for complex image");
05801         }
05802 
05803         int n = params["n"];
05804         float x0 = params["x0"];
05805         float dx = params["dx"];
05806         vector < float >y = params["y"];
05807 
05808         int interpolation = 1;
05809         if (params.has_key("interpolation")) {
05810                 interpolation = params["interpolation"];
05811         }
05812 
05813         Randnum * randnum = Randnum::Instance();
05814         if(params.has_key("seed")) {
05815                 randnum->set_seed((int)params["seed"]);
05816         }
05817 
05818         int nx = image->get_xsize();
05819         int ny = image->get_ysize();
05820         int nz = image->get_zsize();
05821 
05822         image->ap2ri();
05823         float *rdata = image->get_data();
05824 
05825         size_t k = 0;
05826         float half_nz = 0;
05827         if (nz > 1) {
05828                 half_nz = nz / 2.0f;
05829         }
05830 
05831         const float sqrt_2 = sqrt((float) 2);
05832 
05833         float r;
05834         for (int h = 0; h < nz; h++) {
05835                 for (int j = 0; j < ny; j++) {
05836                         for (int i = 0; i < nx; i += 2, k += 2) {
05837                                 r = (Util::hypot3(i / 2.0f, j - ny / 2.0f, h - half_nz));
05838 //                              r = sqrt(Util::hypot3(i / 2.0f, j - ny / 2.0f, h - half_nz)); // I don't think this sqrt was supposed to be here --steve
05839                                 r = (r - x0) / dx;
05840                                 int l = 0;
05841                                 if (interpolation) {
05842                                         l = Util::fast_floor(r);
05843                                 }
05844                                 else {
05845                                         l = Util::fast_floor(r + 0.5f);
05846                                 }
05847                                 r -= l;
05848                                 float f = 0;
05849                                 if (l >= n - 2) {
05850                                         f = y[n - 1];
05851                                 }
05852                                 else if (l < 0) {
05853                                         l = 0;
05854                                 }
05855                                 else {
05856                                         if (interpolation) {
05857                                                 f = (y[l] * (1 - r) + y[l + 1] * r);
05858                                         }
05859                                         else {
05860                                                 f = y[l];
05861                                         }
05862                                 }
05863                                 f = randnum->get_gauss_rand(sqrt(f), sqrt(f) / 3);
05864                                 float a = randnum->get_frand(0.0f, (float)(2 * M_PI));
05865                                 if (i == 0) {
05866                                         f *= sqrt_2;
05867                                 }
05868                                 rdata[k] += f * cos(a);
05869                                 rdata[k + 1] += f * sin(a);
05870                         }
05871                 }
05872         }
05873 
05874         image->update();
05875 }
05876 
05877 void IterMultiMaskProcessor::process_inplace(EMData * image)
05878 {
05879         if (!image) {
05880                 LOGWARN("NULL Image");
05881                 return;
05882         }
05883 
05884         int nx = image->get_xsize();
05885         int ny = image->get_ysize();
05886         int nz = image->get_zsize();
05887 
05888         if (ny == 1) {
05889                 LOGERR("Tried to add mask shell to 1d image");
05890                 return;
05891         }
05892 
05893         int num_shells = params.set_default("nshells",1);
05894 
05895         // there are other strategies which might allow us to avoid the extra copy, but this will have to do for now
05896         EMData *image1=image;
05897         EMData *image2=image->copy();
05898         if (nz == 1) {
05899                 for (int i = 0; i < num_shells; i++) {
05900                         for (int y = 1; y < ny - 1; y++) {
05901                                 for (int x = 1; x < nx - 1; x++) {
05902                                         if (image1->get_value_at(x,y)>=0) continue;             // already part of a masked region
05903 
05904                                         // Note that this produces a directional bias in the case of ambiguous pixels
05905                                         // While this could be improved upon slightly, there can be truly ambiguous cases
05906                                         // and at least this method is deterministic
05907                                         if      (image1->get_value_at(x-1,y)>=0) image2->set_value_at_fast(x,y,image1->get_value_at(x-1,y));
05908                                         else if (image1->get_value_at(x+1,y)>=0) image2->set_value_at_fast(x,y,image1->get_value_at(x+1,y));
05909                                         else if (image1->get_value_at(x,y-1)>=0) image2->set_value_at_fast(x,y,image1->get_value_at(x,y-1));
05910                                         else if (image1->get_value_at(x,y+1)>=0) image2->set_value_at_fast(x,y,image1->get_value_at(x,y+1));
05911 
05912                                 }
05913                         }
05914                         memcpy(image1->get_data(),image2->get_data(),image1->get_size()*sizeof(float));
05915                 }
05916         }
05917         else {
05918                 for (int i = 0; i < num_shells; i++) {
05919                         for (int z = 1; z < nz - 1; z++) {
05920                                 for (int y = 1; y < ny - 1; y++) {
05921                                         for (int x = 1; x < nx - 1; x++) {
05922                                                 if (image1->get_value_at(x,y,z)>=0) continue;           // already part of a masked region
05923 
05924                                                 // Note that this produces a directional bias in the case of ambiguous pixels
05925                                                 // While this could be improved upon slightly, there can be truly ambiguous cases
05926                                                 // and at least this method is deterministic
05927                                                 if      (image1->get_value_at(x-1,y,z)>=0) image2->set_value_at_fast(x,y,z,image1->get_value_at(x-1,y,z));
05928                                                 else if (image1->get_value_at(x+1,y,z)>=0) image2->set_value_at_fast(x,y,z,image1->get_value_at(x+1,y,z));
05929                                                 else if (image1->get_value_at(x,y-1,z)>=0) image2->set_value_at_fast(x,y,z,image1->get_value_at(x,y-1,z));
05930                                                 else if (image1->get_value_at(x,y+1,z)>=0) image2->set_value_at_fast(x,y,z,image1->get_value_at(x,y+1,z));
05931                                                 else if (image1->get_value_at(x,y,z-1)>=0) image2->set_value_at_fast(x,y,z,image1->get_value_at(x,y,z-1));
05932                                                 else if (image1->get_value_at(x,y,z+1)>=0) image2->set_value_at_fast(x,y,z,image1->get_value_at(x,y,z+1));
05933 
05934                                         }
05935                                 }
05936                         }
05937                         memcpy(image1->get_data(),image2->get_data(),image1->get_size()*sizeof(float));
05938                 }
05939         }
05940 
05941         delete image2;
05942         image->update();
05943 }
05944 
05945 
05946 void AddMaskShellProcessor::process_inplace(EMData * image)
05947 {
05948         if (!image) {
05949                 LOGWARN("NULL Image");
05950                 return;
05951         }
05952 
05953         int nx = image->get_xsize();
05954         int ny = image->get_ysize();
05955         int nz = image->get_zsize();
05956 
05957         if (ny == 1) {
05958                 LOGERR("Tried to add mask shell to 1d image");
05959                 return;
05960         }
05961 
05962         int num_shells = params.set_default("nshells",1);
05963 
05964         float *d = image->get_data();
05965         float k = 0.99999f;
05966         int nxy = nx * ny;
05967 
05968         if (nz == 1) {
05969                 for (int i = 0; i < num_shells; i++) {
05970                         for (int y = 1; y < ny - 1; y++) {
05971                                 int cur_y = y * nx;
05972 
05973                                 for (int x = 1; x < nx - 1; x++) {
05974                                         int j = x + cur_y;
05975                                         if (!d[j] && (d[j - 1] > k || d[j + 1] > k || d[j + nx] > k || d[j - nx] > k)) {
05976                                                 d[j] = k;
05977                                         }
05978                                 }
05979                         }
05980                         k -= 0.00001f;
05981                 }
05982         }
05983         else {
05984                 for (int i = 0; i < num_shells; i++) {
05985                         for (int z = 1; z < nz - 1; z++) {
05986                                 size_t cur_z = (size_t)z * nx * ny;
05987 
05988                                 for (int y = 1; y < ny - 1; y++) {
05989                                         size_t cur_y = y * nx + cur_z;
05990 
05991                                         for (int x = 1; x < nx - 1; x++) {
05992                                                 size_t j = x + cur_y;
05993 
05994                                                 if (!d[j] && (d[j - 1] > k || d[j + 1] > k || d[j + nx] > k ||
05995                                                                           d[j - nx] > k || d[j - nxy] > k || d[j + nxy] > k)) {
05996                                                         d[j] = k;
05997                                                 }
05998                                         }
05999                                 }
06000                         }
06001 
06002                         k -= 0.00001f;
06003                 }
06004         }
06005 
06006         size_t size = (size_t)nx * ny * nz;
06007         for (size_t i = 0; i < size; ++i) {
06008                 if (d[i]) {
06009                         d[i] = 1;
06010                 }
06011                 else {
06012                         d[i] = 0;
06013                 }
06014         }
06015 
06016         image->update();
06017 }
06018 
06019 void ToMassCenterProcessor::process_inplace(EMData * image)
06020 {
06021         if (!image) {
06022                 LOGWARN("NULL Image");
06023                 return;
06024         }
06025 
06026         int int_shift_only = params.set_default("int_shift_only",1);
06027         float threshold = params.set_default("threshold",0.0f);
06028 //      int positive = params.set_default("positive",0);
06029 
06030         if ((float)image->get_attr("sigma")==0.0f) return;              // Can't center a constant valued image
06031         if (threshold>(float)image->get_attr("maximum")) {
06032                 printf("Warning, centering threshold %1.2f, but image max %1.2f. Adjusting.",threshold,(float)image->get_attr("maximum"));
06033                 threshold=(float)image->get_attr("mean")+(float)image->get_attr("sigma");
06034         }
06035 
06036         FloatPoint com = image->calc_center_of_mass(threshold);
06037 
06038         int nx = image->get_xsize();
06039         int ny = image->get_ysize();
06040         int nz = image->get_zsize();
06041 
06042         if (int_shift_only) {
06043                 int dx = -(int)(floor(com[0] + 0.5f) - nx / 2);
06044                 int dy = -(int)(floor(com[1] + 0.5f) - ny / 2);
06045                 int dz = 0;
06046                 if (nz > 1) {
06047                         dz = -(int)(floor(com[2] + 0.5f) - nz / 2);
06048                 }
06049                 if (abs(dx)>=nx-1 || abs(dy)>=ny-1 || abs(dz)>=nz) {
06050                         printf("ERROR, center of mass outside image\n");
06051                 }
06052                 else {
06053                         image->translate(dx, dy, dz);
06054 
06055                         Transform t;
06056                         t.set_trans((float)dx,(float)dy,(float)dz);
06057 
06058                         if (nz > 1) {
06059                                 image->set_attr("xform.align3d",&t);
06060                         } else {
06061                                 image->set_attr("xform.align2d",&t);
06062                         }
06063                 }
06064         }
06065         else {
06066                 float dx = -(com[0] - nx / 2);
06067                 float dy = -(com[1] - ny / 2);
06068                 float dz = 0;
06069                 if (nz > 1) {
06070                         dz = -(com[2] - nz / 2);
06071                 }
06072                 if (fabs(dx)>=nx-1 || fabs(dy)>=ny-2 || fabs(dz)>=nz) {
06073                         printf("ERROR, center of mass outside image\n");
06074                 }
06075                 else {
06076                         image->translate(dx, dy, dz);
06077 
06078                         Transform t;
06079                         t.set_trans(dx,dy,dz);
06080 
06081                         if (nz > 1) {
06082                                 image->set_attr("xform.align3d",&t);
06083                         } else {
06084                                 image->set_attr("xform.align2d",&t);
06085                         }
06086                 }
06087         }
06088 }
06089 
06090 void PhaseToMassCenterProcessor::process_inplace(EMData * image)
06091 {
06092         if (!image) {
06093                 LOGWARN("NULL Image");
06094                 return;
06095         }
06096 
06097         int int_shift_only = params.set_default("int_shift_only",1);
06098 
06099         vector<float> pcog = image->phase_cog();
06100 
06101         int dims = image->get_ndim();
06102 
06103         if (int_shift_only) {
06104                 int dx=-int(pcog[0]+0.5f),dy=0,dz=0;
06105                 if ( dims >= 2 ) dy = -int(pcog[1]+0.5);
06106                 if ( dims == 3 ) dz = -int(pcog[2]+0.5);
06107 
06108                 Transform t;
06109                 t.set_trans((float)dx,(float)dy,(float)dz);
06110                 if (dims == 3) image->set_attr("xform.align3d",&t);
06111                 else if (dims == 2) image->set_attr("xform.align2d",&t);
06112 
06113                 image->translate(dx,dy,dz);
06114         } else  {
06115                 float dx=-pcog[0],dy=0.0,dz=0.0;
06116                 if ( dims >= 2 ) dy = -pcog[1];
06117                 if ( dims == 3 ) dz = -pcog[2];
06118                 image->translate(dx,dy,dz);
06119 
06120                 Transform t;
06121                 t.set_trans(dx,dy,dz);
06122                 if (dims == 3) image->set_attr("xform.align3d",&t);
06123                 else if (dims == 2) image->set_attr("xform.align2d",&t);
06124         }
06125 }
06126 
06127 void ACFCenterProcessor::process_inplace(EMData * image)
06128 {
06129         if (!image) {
06130                 LOGWARN("NULL Image");
06131                 return;
06132         }
06133 
06134         Dict params1;
06135         params1["intonly"] = 1;
06136         params1["maxshift"] = image->get_xsize() / 4;
06137         EMData* aligned = image->align("translational", 0, params1);
06138         if ( image->get_ndim() == 3 ) {
06139                 Transform* t = aligned->get_attr("xform.align3d");
06140                 image->translate(t->get_trans());
06141                 image->set_attr("xform.align3d",t);
06142                 delete t;
06143         }
06144         else {
06145                 // assumption is the image is 2D which may be  false
06146                 Transform* t = aligned->get_attr("xform.align2d");
06147                 image->translate(t->get_trans());
06148                 image->set_attr("xform.align2d",t);
06149                 delete t;
06150         }
06151 
06152         delete aligned;
06153 
06154 }
06155 
06156 void FSCFourierProcessor::process_inplace(EMData *image)
06157 {
06158         EMData *tmp=process(image);
06159         size_t n = (size_t)image->get_xsize()*image->get_ysize()*image->get_zsize();
06160         memcpy(image->get_data(),tmp->get_data(),n*sizeof(float));
06161         image->update();
06162         delete tmp;
06163 }
06164 
06165 EMData *FSCFourierProcessor::process(EMData const *image)
06166 {
06167         const char *fsp = params["fscfile"];
06168         float snrmult = params.set_default("snrmult",2.0f);
06169         float sscale = params.set_default("sscale",1.0f);
06170         float maxfreq = params.set_default("sscale",1.0f);
06171 
06172         XYData fsc;
06173         fsc.read_file(fsp);
06174         float nyquist=1.0/(2.0f*(float)image->get_attr("apix_x"));
06175 
06176         float lf=1.0f;
06177         int N=(int)fsc.get_size();
06178         int localav=0;                          // once triggered, this uses a local average of 5 points instead of the point itself
06179         // While this could all be in one equation, the compiler will optimize it, and this is much more transparent
06180         for (int i=0; i<N; i++) {
06181                 if (localav==2) {
06182                         fsc.set_y(i,0.00001);
06183                         continue;
06184                 }
06185 
06186                 float s=i*nyquist/N;
06187                 float f=fsc.get_y(i);
06188                 float snr;
06189                 if (s>=maxfreq && lf<f) f=lf;
06190                 if (f<0 && i>2) localav=1;
06191                 if (localav) f=(fsc.get_y(i-2)+fsc.get_y(i-1)+fsc.get_y(i)+fsc.get_y(i+1)+fsc.get_y(i+2))/5.0f;
06192                 if (f>=1.0) snr=1000.0;
06193                 else if (f<0) localav=2;
06194                 else snr=snrmult*f/(1.0-f);     // if FSC==1, we just set it to 1000, which is large enough to make the Wiener filter effectively 1
06195                 float wiener=snr*snr/(snr*snr+1);
06196                 if (wiener<.00001) wiener=.00001;       // we don't want to go all the way to zero. We leave behind just just a touch to preserve potential phase info
06197                 fsc.set_y(i,wiener);
06198                 lf=f;
06199         }
06200         fsc.set_x(0,0);         // just to make sure we have values to the origin.
06201 //      fsc.write_file("wiener.txt");
06202         FILE *out=fopen("wiener.txt","w");
06203         vector<float> wienerary(image->get_ysize());
06204         for (int i=0; i<image->get_ysize(); i++) {
06205                 wienerary[i]=fsc.get_yatx(i*nyquist/image->get_ysize());
06206                 fprintf(out,"%f\t%f\n",sscale*i*nyquist/image->get_ysize(),wienerary[i]);
06207         }
06208         fclose(out);
06209 
06210         EMData *fft=image->do_fft();
06211         fft->apply_radial_func(0,sscale*0.5/(float)image->get_ysize(),wienerary);
06212 
06213         EMData *ret=fft->do_ift();
06214         delete fft;
06215 
06216         return ret;
06217 }
06218 
06219 void SNRProcessor::process_inplace(EMData * image)
06220 {
06221         if (!image) {
06222                 return;
06223         }
06224 
06225         int wiener = params["wiener"];
06226         const char *snrfile = params["snrfile"];
06227 
06228         XYData sf;
06229         int err = sf.read_file(snrfile);
06230         if (err) {
06231                 LOGERR("couldn't read structure factor file!");
06232                 return;
06233         }
06234 
06235 
06236         for (size_t i = 0; i < sf.get_size(); i++) {
06237                 if (sf.get_y(i) <= 0) {
06238                         sf.set_y(i, -4.0f);
06239                 }
06240                 else {
06241                         sf.set_y(i, log10(sf.get_y(i)));
06242                 }
06243         }
06244         sf.update();
06245 
06246         Ctf *image_ctf = image->get_ctf();
06247 
06248         vector < float >ctf;
06249         if (wiener) {
06250                 ctf = image_ctf->compute_1d(image->get_ysize(),1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_WIENER_FILTER, &sf);
06251         }
06252         else {
06253                 ctf = image_ctf->compute_1d(image->get_ysize(),1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_SNR, &sf);
06254         }
06255 
06256         if(image_ctf) {delete image_ctf; image_ctf=0;}
06257 
06258         image->process_inplace("normalize.circlemean");
06259 
06260         int nx = image->get_xsize();
06261         int ny = image->get_ysize();
06262 
06263         Region clip_r(-nx / 2, -ny / 2, nx * 2, ny * 2);
06264         EMData *d3 = image->get_clip(clip_r);
06265         EMData *d2 = d3->do_fft();
06266 
06267         d2->apply_radial_func(0, 2.0f / Ctf::CTFOS, ctf, 0);
06268 
06269         if( d3 )
06270         {
06271                 delete d3;
06272                 d3 = 0;
06273         }
06274 
06275         if( image )
06276         {
06277                 delete image;
06278                 image = 0;
06279         }
06280 
06281         EMData *d1 = d2->do_ift();
06282         int d1_nx = d1->get_xsize();
06283         int d1_ny = d1->get_ysize();
06284         Region d1_r(d1_nx / 4, d1_ny / 4, d1_nx / 2, d1_ny / 2);
06285 
06286         image = d1->get_clip(d1_r);
06287 
06288         if( d1 )
06289         {
06290                 delete d1;
06291                 d1 = 0;
06292         }
06293 
06294         if( d2 )
06295         {
06296                 delete d2;
06297                 d2 = 0;
06298         }
06299 }
06300 
06301 void FileFourierProcessor::process_inplace(EMData * image)
06302 {
06303         if (!image) {
06304                 LOGWARN("NULL Image");
06305                 return;
06306         }
06307         const char *filename = params["filename"];
06308         float apix = params["apix"];
06309 
06310         FILE *in = fopen(filename, "rb");
06311         if (!in) {
06312                 LOGERR("FileFourierProcessor: cannot open file '%s'", filename);
06313                 return;
06314         }
06315 
06316         float f = 0;
06317         int n = 0;
06318         while (fscanf(in, " %f %f", &f, &f) == 2) {
06319                 n++;
06320         }
06321         rewind(in);
06322 
06323         vector < float >xd(n);
06324         vector < float >yd(n);
06325 
06326         float sf = apix * image->get_xsize();
06327 
06328         for (int i = 0; fscanf(in, " %f %f", &xd[i], &yd[i]) == 2; i++) {
06329                 xd[i] *= sf;
06330         }
06331 
06332         if (xd[2] - xd[1] != xd[1] - xd[0]) {
06333                 LOGWARN("Warning, x spacing appears nonuniform %g!=%g\n",
06334                                 xd[2] - xd[1], xd[1] - xd[0]);
06335         }
06336 
06337         EMData *d2 = image->do_fft();
06338         if( image )
06339         {
06340                 delete image;
06341                 image = 0;
06342         }
06343 
06344         d2->apply_radial_func(xd[0], xd[1] - xd[0], yd, 1);
06345         image = d2->do_ift();
06346 }
06347 
06348 void StripeXYProcessor::process_inplace(EMData * image)
06349 {
06350         if (!image) {
06351                 LOGWARN("NULL Image");
06352                 return;
06353         }
06354         int xlen = params.set_default("xlen",10);
06355         int ylen = params.set_default("ylen",10);
06356 
06357         int nx=image->get_attr("nx");
06358         int ny=image->get_attr("ny");
06359         EMData *tmp=new EMData(nx,ny,1);
06360 
06361         // we do this in real-space, since the integration size is small, and we don't want Fourier edge effects
06362         // we use a 'moving window' to avoid summing the same points multiple times
06363         // start with y
06364         if (ylen>0) {
06365                 for (int x=0; x<nx; x++) {
06366                         float sum=0.0;
06367                         float sumn=0.0;
06368                         for (int y=0; y<(ylen<ny?ylen:ny); y++) { sum+=image->get_value_at(x,y); sumn+=1.0; } // we seed the process with a 1/2 stripe
06369                         // now loop over each final pixel
06370                         for (int y=0; y<ny; y++) {
06371                                 if (y+ylen<ny) { sum+=image->get_value_at(x,y+ylen); sumn+=1.0; }
06372                                 if (y-ylen-1>=0) { sum-=image->get_value_at(x,y-ylen-1); sumn-=1.0; }
06373                                 tmp->set_value_at_fast(x,y,sum/sumn);
06374                         }
06375                 }
06376                 tmp->write_image("tmp.hdf",0);
06377                 image->sub(*tmp);
06378         }
06379 
06380         // now x
06381         if (xlen>0) {
06382                 for (int y=0; y<ny; y++) {
06383                         float sum=0.0;
06384                         float sumn=0.0;
06385                         for (int x=0; x<(xlen<nx?xlen:nx); x++) { sum+=image->get_value_at(x,y); sumn+=1.0; } // we seed the process with a 1/2 stripe
06386                         // now loop over each final pixel
06387                         for (int x=0; x<nx; x++) {
06388                                 if (x+xlen<nx) { sum+=image->get_value_at(x+xlen,y); sumn+=1.0; }
06389                                 if (x-xlen-1>=0) { sum-=image->get_value_at(x-xlen-1,y); sumn-=1.0; }
06390                                 tmp->set_value_at_fast(x,y,sum/sumn);
06391                         }
06392                 }
06393                 tmp->write_image("tmp.hdf",1);
06394                 image->sub(*tmp);
06395         }
06396 
06397         delete tmp;
06398 }
06399 
06400 
06401 void LocalNormProcessor::process_inplace(EMData * image)
06402 {
06403         if (!image) {
06404                 LOGWARN("NULL Image");
06405                 return;
06406         }
06407         float apix = params["apix"];
06408         float threshold = params["threshold"];
06409         float radius = params["radius"];
06410 
06411         if (apix > 0) {
06412                 int ny = image->get_ysize();
06413                 radius = ny * apix / radius;
06414                 //printf("Norm filter radius=%1.1f\n", radius);
06415         }
06416 
06417         EMData *blur = image->copy();
06418         EMData *maskblur = image->copy();
06419 
06420         maskblur->process_inplace("threshold.binary", Dict("value", threshold));
06421         maskblur->process_inplace("filter.lowpass.gauss", Dict("cutoff_pixels", radius));
06422 //      maskblur->process_inplace("filter.highpass.tanh", Dict("highpass", -10.0f));
06423         maskblur->process_inplace("threshold.belowtozero", Dict("minval", 0.001f));
06424 //      maskblur->process_inplace("threshold.belowtozero", Dict("minval", 0.001f));
06425 
06426 
06427         blur->process_inplace("threshold.belowtozero", Dict("minval", threshold));
06428         blur->process_inplace("filter.lowpass.gauss", Dict("cutoff_pixels", radius));
06429 //      blur->process_inplace("filter.highpass.tanh", Dict("cutoff_abs", -10.0f));
06430 
06431         maskblur->div(*blur);
06432         image->mult(*maskblur);
06433 //      maskblur->write_image("norm.mrc", 0, EMUtil::IMAGE_MRC);
06434 
06435         if( maskblur )
06436         {
06437                 delete maskblur;
06438                 maskblur = 0;
06439         }
06440 
06441         if( blur )
06442         {
06443                 delete blur;
06444                 blur = 0;
06445         }
06446 }
06447 
06448 
06449 void SymSearchProcessor::process_inplace(EMData * image)
06450 {
06451         if (!image) {
06452                 LOGWARN("NULL Image");
06453                 return;
06454         }
06455         float thresh = params["thresh"];
06456         int output_symlabel = params["output_symlabel"];
06457 
06458         // set up all the symmetry transforms for all the searched symmetries
06459         const vector<string> sym_list = params["sym"];
06460         int sym_num = sym_list.size();
06461         vector< vector< Transform > > transforms(sym_num);
06462         vector< float* > symvals(sym_num);
06463         for (int i =0; i < sym_num; i++) {
06464                 vector<Transform> sym_transform =  Symmetry3D::get_symmetries(sym_list[i]);
06465                 transforms[i] = sym_transform;
06466                 symvals[i] = new float[sym_transform.size()]; // new float(nsym);
06467         }
06468 
06469         EMData *orig = image->copy();
06470 
06471         image->to_zero();
06472 
06473         int nx= image->get_xsize();
06474         int ny= image->get_ysize();
06475         int nz= image->get_zsize();
06476         int xy = nx * ny;
06477         float * data = image->get_data();
06478         float * sdata = orig->get_data();
06479 
06480         EMData *symlabel = 0;
06481         float * ldata = symlabel->get_data();
06482         if (output_symlabel) {
06483                 symlabel = image->copy();
06484                 symlabel->to_zero();
06485                 ldata = symlabel->get_data();
06486         }
06487 
06488         for (int k = 0; k < nz; k++) {
06489                 for (int j = 0; j < ny; j++) {
06490                         for(int i = 0; i < nx; i++) {
06491                                 size_t index = (size_t)k * nx * ny + j * nx + i;
06492                                 float val = sdata[ index ];
06493                                 float bestmean = val, bestsymlevel = FLT_MAX;
06494                                 int bestsym = 0;
06495                                 for( int sym = 0; sym< sym_num; sym++) {
06496                                         int cur_sym_num = transforms[sym].size();
06497                                         float *symval = symvals[sym];
06498                                         // first find out all the symmetry related location values
06499                                         for( int s = 0; s < cur_sym_num; s++){
06500                                                 Transform r = transforms[sym][s];
06501                                                 float x2 = (float)(r[0][0] * (i-nx/2) + r[0][1] * (j-ny/2) + r[0][2] * (k-nz/2) + nx / 2);
06502                                                 float y2 = (float)(r[1][0] * (i-nx/2) + r[1][1] * (j-ny/2) + r[1][2] * (k-nz/2) + ny / 2);
06503                                                 float z2 = (float)(r[2][0] * (i-nx/2) + r[2][1] * (j-ny/2) + r[2][2] * (k-nz/2) + nz / 2);
06504 
06505                                                 if (x2 >= 0 && y2 >= 0 && z2 >= 0 && x2 < (nx - 1) && y2 < (ny - 1)
06506                                                         && z2 < (nz - 1)) {
06507                                                         float x = (float)Util::fast_floor(x2);
06508                                                         float y = (float)Util::fast_floor(y2);
06509                                                         float z = (float)Util::fast_floor(z2);
06510 
06511                                                         float t = x2 - x;
06512                                                         float u = y2 - y;
06513                                                         float v = z2 - z;
06514 
06515                                                         size_t ii = x + y * nx + z * (size_t)xy;
06516 
06517                                                         symval[s]=
06518                                                                 Util::trilinear_interpolate(sdata[ii], sdata[ii + 1], sdata[ii + nx],
06519                                                                                                                         sdata[ii + nx + 1], sdata[ii + nx * ny],
06520                                                                                                                         sdata[ii + xy + 1], sdata[ii + xy + nx],
06521                                                                                                                         sdata[ii + xy + nx + 1], t, u, v);
06522                                                 }
06523                                                 else {
06524                                                         symval[s] = 0.0 ;
06525                                                 }
06526                                         }
06527                                         float tmean=0, tsigma=0;
06528                                         for( int s = 0; s < cur_sym_num; s++) {
06529                                                 tmean += symval[s];
06530                                                 tsigma += symval[s] * symval[s];
06531                                         }
06532                                         tmean /= cur_sym_num;
06533                                         tsigma = tsigma/cur_sym_num - tmean*tmean;
06534                                         if (tsigma < bestsymlevel ) {
06535                                                 bestsymlevel = tsigma;
06536                                                 bestmean = tmean;
06537                                                 bestsym = sym;
06538                                         }
06539                                 }
06540                                 if ( bestsymlevel > thresh) {
06541                                         if (output_symlabel) ldata[index] = (float)bestsym;
06542                                         data[index] = bestmean;
06543                                 }
06544                                 else {
06545                                         if (output_symlabel) ldata[index] = -1;
06546                                         data[index] = val;
06547                                 }
06548                         }
06549                 }
06550         }
06551         if( orig )
06552         {
06553                 delete orig;
06554                 orig = 0;
06555         }
06556         for (int i =0; i < sym_num; i++) {
06557                 if( symvals[i] )
06558                 {
06559                         delete symvals[i];
06560                         symvals[i] = 0;
06561                 }
06562         }
06563         if (symlabel) params.put("symlabel_map", EMObject(symlabel));
06564 }
06565 
06566 
06567 void IndexMaskFileProcessor::process_inplace(EMData * image)
06568 {
06569         if (!image) {
06570                 LOGWARN("NULL Image");
06571                 return;
06572         }
06573 
06574         const char *filename = params["filename"];
06575         EMData *msk = new EMData();
06576         msk->read_image(filename);
06577         if (!EMUtil::is_same_size(image, msk)) {
06578                 LOGERR("IndexMaskFileProcessor: Mask size different than image");
06579                 return;
06580         }
06581 
06582         if ((int) params["ismaskset"] != 0) {
06583                 msk->process_inplace("threshold.binaryrange", Dict("low", 0.5f, "high", 1.5f));
06584         }
06585 
06586         image->mult(*msk);
06587         if( msk )
06588         {
06589                 delete msk;
06590                 msk = 0;
06591         }
06592 }
06593 
06594 
06595 void CoordinateMaskFileProcessor::process_inplace(EMData * image)
06596 {
06597         if (!image) {
06598                 LOGWARN("NULL Image");
06599                 return;
06600         }
06601 
06602         const char *filename = params["filename"];
06603         EMData *msk = new EMData();
06604         msk->read_image(filename);
06605 
06606         int nx = image->get_xsize();
06607         int ny = image->get_ysize();
06608         int nz = image->get_zsize();
06609 
06610         int xm = msk->get_xsize();
06611         int ym = msk->get_ysize();
06612         int zm = msk->get_zsize();
06613 
06614         float apix = image->get_attr("apix_x");
06615         float apixm = msk->get_attr("apix_x");
06616 
06617         float xo = image->get_attr_default("origin_x",0.0);
06618         float yo = image->get_attr_default("origin_y",0.0);
06619         float zo = image->get_attr_default("origin_z",0.0);
06620 
06621         float xom = msk->get_attr_default("origin_x",0.0);
06622         float yom = msk->get_attr_default("origin_y",0.0);
06623         float zom = msk->get_attr_default("origin_z",0.0);
06624 
06625         float *dp = image->get_data();
06626         float *dpm = msk->get_data();
06627         int nxy = nx * ny;
06628 
06629         for (int k = 0; k < nz; k++) {
06630                 float zc = zo + k * apix;
06631                 if (zc <= zom || zc >= zom + zm * apixm) {
06632                         memset(&(dp[k * nxy]), 0, sizeof(float) * nxy);
06633                 }
06634                 else {
06635                         int km = (int) ((zc - zom) / apixm);
06636 
06637                         for (int j = 0; j < ny; j++) {
06638                                 float yc = yo + j * apix;
06639                                 if (yc <= yom || yc >= yom + ym * apixm) {
06640                                         memset(&(dp[k * nxy + j * nx]), 0, sizeof(float) * nx);
06641                                 }
06642                                 else {
06643                                         int jm = (int) ((yc - yom) / apixm);
06644                                         size_t idx = 0;
06645                                         float xc;
06646                                         int im;
06647                                         for (int i = 0; i < nx; i++) {
06648                                                 xc = xo + i * apix;
06649                                                 idx = (size_t)k * nxy + j * nx + i;
06650                                                 if (xc <= xom || xc >= xom + xm * apixm) {
06651                                                         dp[idx] = 0;
06652                                                 }
06653                                                 else {
06654                                                         im = (int) ((xc - xom) / apixm);
06655                                                         if (dpm[km * xm * ym + jm * xm + im] <= 0) {
06656                                                                 dp[idx] = 0;
06657                                                         }
06658                                                 }
06659                                         }
06660                                 }
06661                         }
06662                 }
06663         }
06664 
06665         image->update();
06666         msk->update();
06667         if( msk )
06668         {
06669                 delete msk;
06670                 msk = 0;
06671         }
06672 }
06673 
06674 void MatchSFProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const {
06675         // The radial mask comes in with the existing radial image profile
06676         // The radial mask runs from 0 to the 1-D Nyquist (it leaves out the corners in Fourier space)
06677 
06678         EMData *to = params["to"];
06679         XYData *sf = new XYData();
06680         float apixto = to->get_attr("apix_x");
06681 
06682 
06683         if (to->is_complex()) {
06684                 vector<float> rd=to->calc_radial_dist(to->get_ysize()/2.0f,0,1.0f,1);
06685                 for (size_t i=0; i<rd.size(); ++i) {
06686                         sf->set_x(i,i/(apixto*2.0f*rd.size()));
06687                         sf->set_y(i,rd[i]);
06688                 }
06689         }
06690         else {
06691                 EMData *tmp=to->do_fft();
06692                 vector<float> rd=tmp->calc_radial_dist(to->get_ysize()/2,0,1.0,1);
06693                 for (size_t i=0; i<rd.size(); ++i) {
06694                         sf->set_x(i,i/(apixto*2.0f*rd.size()));
06695                         sf->set_y(i,rd[i]);
06696                 }
06697                 delete tmp;
06698         }
06699 
06700         float apix=image->get_attr("apix_x");
06701 
06702 //      sf->write_file("a.txt");
06703 //      Util::save_data(0,sf->get_x(1),radial_mask,"b.txt");
06704 
06705         int n = radial_mask.size();
06706         for (int i=0; i<n; i++) {
06707                 if (radial_mask[i]>0) radial_mask[i]= sqrt(sf->get_yatx(i/(apix*2.0f*n),false)/radial_mask[i]);
06708                 else if (i>0) radial_mask[i]=radial_mask[i-1];
06709         }
06710 
06711 //      Util::save_data(0,sf->get_x(1),radial_mask,"c.txt");
06712 
06713         delete sf;
06714 }
06715 
06716 void SetSFProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const {
06717         // The radial mask comes in with the existing radial image profile
06718         // The radial mask runs from 0 to the 1-D Nyquist (it leaves out the corners in Fourier space)
06719 
06720         XYData *sf = params["strucfac"];
06721         if(params.has_key("apix")) {
06722                 image->set_attr("apix_x", (float)params["apix"]);
06723                 image->set_attr("apix_y", (float)params["apix"]);
06724                 image->set_attr("apix_z", (float)params["apix"]);
06725         }
06726 
06727         float apix=image->get_attr("apix_x");
06728         int n = radial_mask.size();
06729         int nmax=(int)floor(sf->get_x(sf->get_size()-1)*apix*2.0f*n);           // This is the radius at which we have our last valid value from the curve
06730         if (nmax>n) nmax=n;
06731 
06732         if ((nmax)<3) throw InvalidParameterException("Insufficient structure factor data for SetSFProcessor to be meaningful");
06733 
06734         int i;
06735         for (i=0; i<nmax; i++) {
06736 //              if (radial_mask[i]>0)
06737 //              {
06738 //                      radial_mask[i]= sqrt(n*sf->get_yatx(i/(apix*2.0f*n),false)/radial_mask[i]);
06739 //              }
06740                 if (radial_mask[i]>0) {
06741                         radial_mask[i]= sqrt((n*n*n)*sf->get_yatx(i/(apix*2.0f*n))/radial_mask[i]);
06742                 }
06743                 else if (i>0) radial_mask[i]=radial_mask[i-1];  // For points where the existing power spectrum was 0
06744         }
06745 
06746         // Continue to use a fixed factor after we run out of 'sf' values
06747 
06748         while (i<n) {
06749                 radial_mask[i]=radial_mask[nmax-1];
06750                 i++;
06751         }
06752 
06753 }
06754 
06755 void SmartMaskProcessor::process_inplace(EMData * image)
06756 {
06757         if (!image) {
06758                 LOGWARN("NULL Image");
06759                 return;
06760         }
06761 
06762         float mask = params["mask"];
06763 
06764         int nx = image->get_xsize();
06765         int ny = image->get_ysize();
06766         int nz = image->get_zsize();
06767 
06768         float *dat = image->get_data();
06769         double sma = 0;
06770         size_t smn = 0;
06771         float r = 0.0f;
06772         for (int k = 0; k < nz; ++k) {
06773                 for (int j = 0; j < ny; ++j) {
06774                         for (int i = 0; i < nx; ++i, ++dat) {
06775                                 r =
06776                                         sqrt((float) Util::square(i - nx / 2) + Util::square(j - ny / 2) +
06777                                                  Util::square(k - nz / 2));
06778                                 if (r > mask - 1.5f && r < mask - 0.5f) {
06779                                         sma += *dat;
06780                                         smn++;
06781                                 }
06782                         }
06783                 }
06784         }
06785 
06786         float smask = (float) (sma / smn);
06787         image->update();
06788 
06789         dat = image->get_data();
06790         for (int k = 0; k < nz; ++k) {
06791                 for (int j = 0; j < ny; ++j) {
06792                         for (int i = 0; i < nx; ++i, ++dat) {
06793                                 r =
06794                                         sqrt((float) Util::square(i - nx / 2) + Util::square(j - ny / 2) +
06795                                                  Util::square(k - nz / 2));
06796                                 if (r > mask - .5) {
06797                                         *dat = 0;
06798                                 }
06799                                 else {
06800                                         *dat -= smask;
06801                                 }
06802                         }
06803                 }
06804         }
06805 
06806         image->update();
06807 }
06808 
06809 void AutoMask3DProcessor::search_nearby(float *dat, float *dat2, int nx, int ny, int nz, float threshold)
06810 {
06811         Assert(dat != 0);
06812         Assert(dat2 != 0);
06813         Assert(nx > 0);
06814         Assert(ny > 0);
06815 
06816         bool done = false;
06817         int nxy = nx * ny;
06818 
06819         while (!done) {
06820                 done = true;
06821                 for (int k = 1; k < nz - 1; k++) {
06822                         size_t k2 = (size_t)k * nxy;
06823                         for (int j = 1; j < ny - 1; j++) {
06824                                 size_t l = j * nx + k2 + 1;
06825 
06826                                 for (int i = 1; i < nx - 1; i++) {
06827                                         if (dat[l] >= threshold || dat2[l]) {
06828                                                 if (dat2[l - 1] || dat2[l + 1] ||
06829                                                         dat2[l - nx] || dat2[l + nx] || dat2[l - nxy] || dat2[l + nxy]) {
06830                                                         dat2[l] = 1.0f;
06831                                                         done = false;
06832                                                 }
06833                                         }
06834                                         ++l;
06835                                 }
06836                         }
06837                 }
06838         }
06839 }
06840 
06841 void AutoMask3DProcessor::fill_nearby(float *dat2, int nx, int ny, int nz)
06842 {
06843         Assert(dat2 != 0);
06844         Assert(nx > 0);
06845         Assert(ny > 0);
06846         Assert(nz >= 0);
06847 
06848         int nxy = nx * ny;
06849         size_t idx;
06850         for (int i = 0; i < nx; ++i) {
06851                 for (int j = 0; j < ny; ++j) {
06852                         int j2 = j * nx + i;
06853                         int k0 = 0;
06854                         for (int k = 0; k < nz; ++k) {
06855                                 idx = j2 + (size_t)k * nxy;
06856                                 if (dat2[idx]) {
06857                                         k0 = k;
06858                                         break;
06859                                 }
06860                         }
06861 
06862                         if (k0 != nz) {
06863                                 int k1 = nz - 1;
06864                                 for (int k = nz - 1; k >= 0; --k) {
06865                                         idx = j2 + (size_t)k * nxy;
06866                                         if (dat2[idx]) {
06867                                                 k1 = k;
06868                                                 break;
06869                                         }
06870                                 }
06871 
06872                                 for (int k = k0 + 1; k < k1; ++k) {
06873                                         idx = j2 + (size_t)k * nxy;
06874                                         dat2[idx] = 1.0f;
06875                                 }
06876                         }
06877                 }
06878         }
06879 
06880         for (int i = 0; i < nx; ++i) {
06881                 for (int j = 0; j < nz; ++j) {
06882                         size_t j2 = (size_t)j * nxy + i;
06883                         int k0 = 0;
06884                         for (int k = 0; k < ny; ++k) {
06885                                 idx = (size_t)k * nx + j2;
06886                                 if (dat2[idx]) {
06887                                         k0 = k;
06888                                         break;
06889                                 }
06890                         }
06891 
06892                         if (k0 != ny) {
06893                                 int k1 = ny - 1;
06894                                 for (int k = ny - 1; k >= 0; --k) {
06895                                         idx = (size_t)k * nx + j2;
06896                                         if (dat2[idx]) {
06897                                                 k1 = k;
06898                                                 break;
06899                                         }
06900                                 }
06901 
06902                                 for (int k = k0 + 1; k < k1; ++k) {
06903                                         idx = (size_t)k * nx + j2;
06904                                         dat2[idx] = 1.0f;
06905                                 }
06906                         }
06907                 }
06908         }
06909 
06910         for (int i = 0; i < ny; ++i) {
06911                 for (int j = 0; j < nz; ++j) {
06912                         size_t j2 = i * nx + (size_t)j * nxy;
06913                         int k0 = 0;
06914                         for (int k = 0; k < nx; ++k) {
06915                                 if (dat2[k + j2]) {
06916                                         k0 = k;
06917                                         break;
06918                                 }
06919                         }
06920                         if (k0 != nx) {
06921                                 int k1 = nx - 1;
06922                                 for (int k = nx - 1; k >= 0; --k) {
06923                                         if (dat2[k + j2]) {
06924                                                 k1 = k;
06925                                                 break;
06926                                         }
06927                                 }
06928 
06929                                 for (int k = k0 + 1; k < k1; ++k) {
06930                                         dat2[k + j2] = 1.0f;
06931                                 }
06932                         }
06933                 }
06934         }
06935 
06936 }
06937 
06938 void AutoMask3DProcessor::process_inplace(EMData * image)
06939 {
06940         if (!image) {
06941                 LOGWARN("NULL Image");
06942                 return;
06943         }
06944 
06945         int nx = image->get_xsize();
06946         int ny = image->get_ysize();
06947         int nz = image->get_zsize();
06948 
06949         EMData *amask = new EMData();
06950         amask->set_size(nx, ny, nz);
06951 
06952         float sig = 0;
06953         float mean = 0;
06954 
06955         if (params.has_key("threshold1") && params.has_key("threshold2")) {
06956                 sig = image->get_attr("sigma");
06957                 mean = image->get_attr("mean");
06958         }
06959 
06960         float *dat = image->get_data();
06961         float *dat2 = amask->get_data();
06962 
06963         float t = 0;
06964         if (params.has_key("threshold1")) {
06965                 t = params["threshold1"];
06966         }
06967         else {
06968                 t = mean + sig * 2.5f;
06969         }
06970 
06971         size_t l = 0;
06972         for (int k = 0; k < nz; ++k) {
06973                 for (int j = 0; j < ny; ++j) {
06974                         for (int i = 0; i < nx; ++i) {
06975                                 if (dat[l] > t) {
06976                                         dat2[l] = 1.0f;
06977                                 }
06978                                 ++l;
06979                         }
06980                 }
06981         }
06982 
06983 
06984         if (params.has_key("threshold2")) {
06985                 t = params["threshold2"];
06986         }
06987         else {
06988                 t = mean + sig * 0.5f;
06989         }
06990 
06991         search_nearby(dat, dat2, nx, ny, nz, t);
06992 
06993         int nxy = nx * ny;
06994 
06995         for (int k = 1; k < nz - 1; ++k) {
06996                 for (int j = 1; j < ny - 1; ++j) {
06997                         size_t l = j * nx + (size_t)k * nxy + 1;
06998                         for (int i = 1; i < nx - 1; ++i, ++l) {
06999                                 if (dat2[l - 1] == 1.0f || dat2[l + 1] == 1.0f ||
07000                                         dat2[l - nx] == 1.0f || dat2[l + nx] == 1.0f ||
07001                                         dat2[l - nxy] == 1.0f || dat2[l + nxy] == 1.0f) {
07002                                         dat2[l] = 2.0f;
07003                                 }
07004                         }
07005                 }
07006         }
07007 
07008         size_t size = (size_t)nx * ny * nz;
07009         for (size_t i = 0; i < size; ++i) {
07010                 if (dat2[i] == 2.0f) {
07011                         dat2[i] = 1.0f;
07012                 }
07013         }
07014 
07015         fill_nearby(dat2, nx, ny, nz);
07016 
07017         image->update();
07018         amask->update();
07019 
07020         image->mult(*amask);
07021         amask->write_image("mask.mrc", 0, EMUtil::IMAGE_MRC);
07022         if( amask )
07023         {
07024                 delete amask;
07025                 amask = 0;
07026         }
07027 }
07028 
07029 // Originally this was done recursively, but there were issues with exceeding the maximum recursion depth,
07030 // so switched to a vector-style algorithm instead
07031 void AutoMaskDustProcessor::process_inplace(EMData * imagein)
07032 {
07033         if (!imagein) {
07034                 LOGWARN("NULL Image");
07035                 return;
07036         }
07037         image=imagein;
07038 
07039         int nx = image->get_xsize();
07040         int ny = image->get_ysize();
07041         int nz = image->get_zsize();
07042 
07043         int verbose=params.set_default("verbose",0);
07044         unsigned int voxels=params.set_default("voxels",27);
07045         float threshold=params.set_default("threshold",1.5);
07046 
07047         mask = new EMData();
07048         mask->set_size(nx, ny, nz);
07049         mask->to_one();
07050 
07051         for (int zz = 0; zz < nz; zz++) {
07052                 for (int yy = 0; yy < ny; yy++) {
07053                         for (int xx = 0; xx < nx; xx++) {
07054                                 if (image->get_value_at(xx,yy,zz)>threshold && mask->get_value_at(xx,yy,zz)==1.0) {
07055                                         vector<Vec3i> pvec;
07056                                         pvec.push_back(Vec3i(xx,yy,zz));
07057                                         for (uint i=0; i<pvec.size(); i++) {
07058                                                 // Duplicates will occur the way the algorithm is constructed, so we eliminate them as we encounter them
07059                                                 if (mask->sget_value_at(pvec[i])==0.0f) {
07060                                                         pvec.erase(pvec.begin()+i);
07061                                                         i--;
07062                                                         continue;
07063                                                 }
07064 
07065                                                 // mask out the points in the volume
07066                                                 mask->set_value_at(pvec[i],0.0f);
07067 
07068                                                 int x=pvec[i][0];
07069                                                 int y=pvec[i][1];
07070                                                 int z=pvec[i][2];
07071                                                 // Any neighboring values above threshold we haven't already set get added to the list
07072                                                 if (image->sget_value_at(x-1,y,z)>threshold && mask->get_value_at(x-1,y,z)==1.0) pvec.push_back(Vec3i(x-1,y,z));
07073                                                 if (image->sget_value_at(x+1,y,z)>threshold && mask->get_value_at(x+1,y,z)==1.0) pvec.push_back(Vec3i(x+1,y,z));
07074                                                 if (image->sget_value_at(x,y-1,z)>threshold && mask->get_value_at(x,y-1,z)==1.0) pvec.push_back(Vec3i(x,y-1,z));
07075                                                 if (image->sget_value_at(x,y+1,z)>threshold && mask->get_value_at(x,y+1,z)==1.0) pvec.push_back(Vec3i(x,y+1,z));
07076                                                 if (image->sget_value_at(x,y,z-1)>threshold && mask->get_value_at(x,y,z-1)==1.0) pvec.push_back(Vec3i(x,y,z-1));
07077                                                 if (image->sget_value_at(x,y,z+1)>threshold && mask->get_value_at(x,y,z+1)==1.0) pvec.push_back(Vec3i(x,y,z+1));
07078                                         }
07079 
07080                                         // If the blob is too big, then we don't mask it out after all, but we set the value
07081                                         // to 2.0 so we know the voxels have already been examined, and don't check them again
07082                                         if (pvec.size()>voxels) {
07083                                                 if (verbose) printf("%d\t%d\t%d\tvoxels: %d\n",xx,yy,zz,(int)pvec.size());
07084                                                 for (uint i=0; i<pvec.size(); i++) mask->set_value_at(pvec[i],2.0);
07085                                         }
07086                                 }
07087                         }
07088                 }
07089         }
07090 
07091         mask->process_inplace("threshold.binary",Dict("value",0.5));
07092 
07093         // Now we expand the mask by 1 pixel and blur the edge
07094         mask->mult(-1.0f);
07095         mask->add(1.0f);
07096         mask->process_inplace("mask.addshells",Dict("nshells",2));              // expand by 1 shell
07097         mask->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs",0.25f));
07098         mask->mult(-1.0f);
07099         mask->add(1.0f);
07100         mask->update();
07101 
07102         // apply the mask
07103         image->mult(*mask);
07104         if (verbose>1) mask->write_image("mask.hdf", 0, EMUtil::IMAGE_HDF);
07105 
07106         delete mask;
07107 }
07108 
07109 
07110 void AutoMask3D2Processor::process_inplace(EMData * image)
07111 {
07112         if (!image) {
07113                 LOGWARN("NULL Image");
07114                 return;
07115         }
07116 
07117         if (image->get_ndim() != 3) {
07118                 throw ImageDimensionException("This processor was only ever designed to work on 3D images.");
07119         }
07120 
07121         /*
07122          The mask writing functionality was removed to comply with an EMAN2 policy which dictates that file io is not allowed from within a processor
07123          To get around this just use the return_mask parameter.
07124         string mask_output = params.set_default("write_mask", "");
07125         if ( mask_output != "") {
07126                 if (Util::is_file_exist(mask_output) ) throw InvalidParameterException("The mask output file name already exists. Please remove it if you don't need it.");
07127                 if (!EMUtil::is_valid_filename(mask_output)) throw InvalidParameterException("The mask output file name type is invalid or unrecognized");
07128         }
07129         */
07130 
07131         int radius=0;
07132         if (params.has_key("radius")) {
07133                 radius = params["radius"];
07134         }
07135         int nmaxseed=0;
07136         if (params.has_key("nmaxseed")) {
07137                 nmaxseed = params["nmaxseed"];
07138         }
07139 
07140         float threshold=0.0;
07141         if (params.has_key("sigma")) threshold=(float)(image->get_attr("mean"))+(float)(image->get_attr("sigma"))*(float)params["sigma"];
07142         else threshold=params["threshold"];
07143 
07144         int nshells = params["nshells"];
07145         int nshellsgauss = params["nshellsgauss"];
07146         int verbose=params.set_default("verbose",0);
07147 
07148         int nx = image->get_xsize();
07149         int ny = image->get_ysize();
07150         int nz = image->get_zsize();
07151         int nxy=nx*ny;
07152 
07153         EMData *amask = new EMData();
07154         amask->set_size(nx, ny, nz);
07155 
07156         float *dat = image->get_data();
07157         float *dat2 = amask->get_data();
07158         int i,j,k;
07159         size_t l = 0;
07160 
07161         // Seeds with the highest valued pixels
07162         if (nmaxseed>0) {
07163                 vector<Pixel> maxs=image->calc_n_highest_locations(nmaxseed);
07164 
07165                 for (vector<Pixel>::iterator i=maxs.begin(); i<maxs.end(); i++) {
07166                         amask->set_value_at((*i).x,(*i).y,(*i).z,1.0);
07167                         if (verbose) printf("Seed at %d,%d,%d (%1.3f)\n",(*i).x,(*i).y,(*i).z,(*i).value);
07168                 }
07169         }
07170 
07171         // Seeds with a sphere
07172         if (radius>0) {
07173                 // start with an initial sphere
07174                 for (k = -nz / 2; k < nz / 2; ++k) {
07175                         for (j = -ny / 2; j < ny / 2; ++j) {
07176                                 for (i = -nx / 2; i < nx / 2; ++i,++l) {
07177                                         if (abs(k) > radius || abs(j) > radius || abs(i) > radius) continue;
07178                                         if ( (k * k + j * j + i * i) > (radius*radius) || dat[l] < threshold) continue;
07179                                         dat2[l] = 1.0f;
07180                                 }
07181                         }
07182                 }
07183         }
07184 
07185 
07186         // iteratively 'flood fills' the map... recursion would be better
07187         int done=0;
07188         int iter=0;
07189         while (!done) {
07190                 iter++;
07191                 done=1;
07192                 if (verbose && iter%10==0) printf("%d iterations\n",iter);
07193                 for (k=1; k<nz-1; ++k) {
07194                         for (j=1; j<ny-1; ++j) {
07195                                 for (i=1; i<nx-1; ++i) {
07196                                         l=i+j*nx+k*nx*ny;
07197                                         if (dat2[l]) continue;
07198                                         if (dat[l]>threshold && (dat2[l-1]||dat2[l+1]||dat2[l+nx]||dat2[l-nx]||dat2[l-nxy]||dat2[l+nxy])) {
07199                                                 dat2[l]=1.0;
07200                                                 done=0;
07201                                         }
07202                                 }
07203                         }
07204                 }
07205         }
07206 
07207         amask->update();
07208 
07209         if (verbose) printf("expanding mask\n");
07210         amask->process_inplace("mask.addshells.gauss", Dict("val1", (int)(nshells+nshellsgauss/2),"val2",0));
07211         if (verbose) printf("filtering mask\n");
07212         amask->process_inplace("filter.lowpass.gauss", Dict("cutoff_abs", (float)(1.0f/(float)nshellsgauss)));
07213         amask->process_inplace("threshold.belowtozero", Dict("minval",(float)0.002));   // this makes the value exactly 0 beyond ~2.5 sigma
07214 
07215         boo