Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

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 <ctime>
00051 
00052 #ifdef EMAN2_USING_CUDA
00053 //#include "cuda/cuda_util.h"
00054 #include "cuda/cuda_processor.h"
00055 #endif // EMAN2_USING_CUDA
00056 
00057 using namespace EMAN;
00058 using std::reverse;
00059 
00060 const string SNREvalProcessor::NAME = "eval.maskedsnr";
00061 const string AmpweightFourierProcessor::NAME = "filter.ampweight";
00062 const string ConvolutionProcessor::NAME = "math.convolution";
00063 const string XGradientProcessor::NAME = "math.edge.xgradient";
00064 const string YGradientProcessor::NAME = "math.edge.ygradient";
00065 const string ZGradientProcessor::NAME = "math.edge.zgradient";
00066 const string Wiener2DAutoAreaProcessor::NAME = "filter.wiener2dauto";
00067 const string Wiener2DFourierProcessor::NAME = "filter.wiener2d";
00068 const string CtfSimProcessor::NAME = "math.simulatectf";
00069 const string LinearRampFourierProcessor::NAME = "filter.linearfourier";
00070 const string LoGFourierProcessor::NAME = "filter.LoG";
00071 const string DoGFourierProcessor::NAME = "filter.DoG";
00072 const string HighpassAutoPeakProcessor::NAME = "filter.highpass.autopeak";
00073 const string LinearRampProcessor::NAME = "eman1.filter.ramp";
00074 const string AbsoluateValueProcessor::NAME = "math.absvalue";
00075 const string FloorValueProcessor::NAME = "math.floor";
00076 const string BooleanProcessor::NAME = "threshold.notzero";
00077 const string KmeansSegmentProcessor::NAME = "segment.kmeans";
00078 const string DistanceSegmentProcessor::NAME = "segment.distance";
00079 const string WatershedProcessor::NAME = "segment.watershed";
00080 const string InvertCarefullyProcessor::NAME = "math.invert.carefully";
00081 const string ValuePowProcessor::NAME = "math.pow";
00082 const string ValueSquaredProcessor::NAME = "math.squared";
00083 const string ValueSqrtProcessor::NAME = "math.sqrt";
00084 const string ToZeroProcessor::NAME = "threshold.belowtozero";
00085 const string Rotate180Processor::NAME = "math.rotate.180";
00086 const string TransformProcessor::NAME = "xform";
00087 const string IntTranslateProcessor::NAME = "xform.translate.int";
00088 const string ScaleTransformProcessor::NAME = "xform.scale";
00089 const string ApplySymProcessor::NAME = "xform.applysym";
00090 const string ClampingProcessor::NAME = "threshold.clampminmax";
00091 const string NSigmaClampingProcessor::NAME = "threshold.clampminmax.nsigma";
00092 const string ToMinvalProcessor::NAME = "threshold.belowtominval";
00093 const string CutToZeroProcessor::NAME = "threshold.belowtozero_cut";
00094 const string BinarizeProcessor::NAME = "threshold.binary";
00095 //const string BinarizeAmpProcessor::NAME = "threshold.amp.binary";
00096 const string BinarizeFourierProcessor::NAME = "threshold.binary.fourier";
00097 const string CollapseProcessor::NAME = "threshold.compress";
00098 const string LinearXformProcessor::NAME = "math.linear";
00099 const string ExpProcessor::NAME = "math.exp";
00100 const string FiniteProcessor::NAME = "math.finite";
00101 const string RangeThresholdProcessor::NAME = "threshold.binaryrange";
00102 const string SigmaProcessor::NAME = "math.sigma";
00103 const string LogProcessor::NAME = "math.log";
00104 const string MaskSharpProcessor::NAME = "mask.sharp";
00105 const string MaskEdgeMeanProcessor::NAME = "mask.ringmean";
00106 const string MaskNoiseProcessor::NAME = "mask.noise";
00107 const string MaskGaussProcessor::NAME = "mask.gaussian";
00108 const string MaskGaussNonuniformProcessor::NAME = "mask.gaussian.nonuniform";
00109 const string MaskGaussInvProcessor::NAME = "math.gausskernelfix";
00110 const string LinearPyramidProcessor::NAME = "math.linearpyramid";
00111 const string MakeRadiusSquaredProcessor::NAME = "math.toradiussqr";
00112 const string MakeRadiusProcessor::NAME = "math.toradius";
00113 const string ComplexNormPixel::NAME = "complex.normpixels";
00114 const string LaplacianProcessor::NAME = "math.laplacian";
00115 const string ZeroConstantProcessor::NAME = "mask.contract";
00116 const string BoxMedianProcessor::NAME = "eman1.filter.median";
00117 const string BoxSigmaProcessor::NAME = "math.localsigma";
00118 const string NonConvexProcessor::NAME = "math.nonconvex";
00119 const string BoxMaxProcessor::NAME = "math.localmax";
00120 const string MinusPeakProcessor::NAME = "math.submax";
00121 const string PeakOnlyProcessor::NAME = "mask.onlypeaks";
00122 const string DiffBlockProcessor::NAME = "eman1.filter.blockrange";
00123 const string CutoffBlockProcessor::NAME = "eman1.filter.blockcutoff";
00124 const string MaxShrinkProcessor::NAME = "math.maxshrink";
00125 const string MinShrinkProcessor::NAME = "math.minshrink";
00126 const string MeanShrinkProcessor::NAME = "math.meanshrink";
00127 const string MedianShrinkProcessor::NAME = "math.medianshrink";
00128 const string FFTResampleProcessor::NAME = "math.fft.resample";
00129 const string GradientRemoverProcessor::NAME = "math.lineargradientfix";
00130 const string GradientPlaneRemoverProcessor::NAME = "filter.gradientPlaneRemover";
00131 const string FlattenBackgroundProcessor::NAME = "filter.flattenbackground";
00132 const string RampProcessor::NAME = "filter.ramp";
00133 const string VerticalStripeProcessor::NAME = "math.verticalstripefix";
00134 const string RealToFFTProcessor::NAME = "math.realtofft";
00135 const string SigmaZeroEdgeProcessor::NAME = "mask.zeroedgefill";
00136 const string BeamstopProcessor::NAME = "mask.beamstop";
00137 const string MeanZeroEdgeProcessor::NAME = "mask.dampedzeroedgefill";
00138 const string AverageXProcessor::NAME = "math.averageovery";
00139 const string DecayEdgeProcessor::NAME = "mask.decayedge2d";
00140 const string ZeroEdgeRowProcessor::NAME = "mask.zeroedge2d";
00141 const string ZeroEdgePlaneProcessor::NAME = "mask.zeroedge3d";
00142 const string BilateralProcessor::NAME = "filter.bilateral";
00143 const string NormalizeUnitProcessor::NAME = "normalize.unitlen";
00144 const string NormalizeUnitSumProcessor::NAME = "normalize.unitsum";
00145 const string NormalizeStdProcessor::NAME = "normalize";
00146 const string NormalizeMaskProcessor::NAME = "normalize.mask";
00147 const string NormalizeRampNormVar::NAME = "normalize.ramp.normvar";
00148 const string NormalizeByMassProcessor::NAME = "normalize.bymass";
00149 const string NormalizeEdgeMeanProcessor::NAME = "normalize.edgemean";
00150 const string NormalizeCircleMeanProcessor::NAME = "normalize.circlemean";
00151 const string NormalizeLREdgeMeanProcessor::NAME = "normalize.lredge";
00152 const string NormalizeMaxMinProcessor::NAME = "normalize.maxmin";
00153 const string NormalizeRowProcessor::NAME = "normalize.rows";
00154 const string NormalizeToLeastSquareProcessor::NAME = "normalize.toimage";
00155 const string RotationalAverageProcessor::NAME = "math.rotationalaverage";
00156 const string RotationalSubstractProcessor::NAME = "math.rotationalsubtract";
00157 const string TransposeProcessor::NAME = "xform.transpose";
00158 const string FlipProcessor::NAME = "xform.flip";
00159 const string AddNoiseProcessor::NAME = "math.addnoise";
00160 const string AddSigmaNoiseProcessor::NAME = "math.addsignoise";
00161 const string AddRandomNoiseProcessor::NAME = "math.addspectralnoise";
00162 const string FourierToCornerProcessor::NAME = "xform.fourierorigin.tocorner";
00163 const string FourierToCenterProcessor::NAME = "xform.fourierorigin.tocenter";
00164 const string PhaseToCenterProcessor::NAME = "xform.phaseorigin.tocenter";
00165 const string PhaseToCornerProcessor::NAME = "xform.phaseorigin.tocorner";
00166 const string AutoMask2DProcessor::NAME = "mask.auto2d";
00167 const string AutoMaskAsymUnit::NAME = "mask.asymunit";
00168 const string AutoMask3DProcessor::NAME = "mask.auto3d.thresh";
00169 const string AutoMask3D2Processor::NAME = "mask.auto3d";
00170 const string AddMaskShellProcessor::NAME = "mask.addshells";
00171 const string PhaseToMassCenterProcessor::NAME = "xform.phasecenterofmass";
00172 const string ToMassCenterProcessor::NAME = "xform.centerofmass";
00173 const string ACFCenterProcessor::NAME = "xform.centeracf";
00174 const string SNRProcessor::NAME = "eman1.filter.snr";
00175 const string FileFourierProcessor::NAME = "eman1.filter.byfile";
00176 const string SymSearchProcessor::NAME = "misc.symsearch";
00177 const string LocalNormProcessor::NAME = "normalize.local";
00178 const string IndexMaskFileProcessor::NAME = "mask.fromfile";
00179 const string CoordinateMaskFileProcessor::NAME = "mask.fromfile.sizediff";
00180 const string PaintProcessor::NAME = "mask.paint";
00181 const string DirectionalSumProcessor::NAME = "misc.directional_sum";
00182 template<> const string BinaryOperateProcessor<MaxPixelOperator>::NAME = "math.max";            // These 2 should not really be processors
00183 template<> const string BinaryOperateProcessor<MinPixelOperator>::NAME = "math.min";
00184 const string MaxPixelOperator::NAME = "math.max";
00185 const string MinPixelOperator::NAME = "math.min";
00186 const string MatchSFProcessor::NAME = "filter.matchto";
00187 const string SetSFProcessor::NAME = "filter.setstrucfac";
00188 const string SmartMaskProcessor::NAME = "mask.smart";
00189 const string IterBinMaskProcessor::NAME = "mask.addshells.gauss";
00190 const string TestImagePureGaussian::NAME = "testimage.puregaussian";
00191 const string TestImageFourierNoiseGaussian::NAME = "testimage.noise.fourier.gaussian";
00192 const string TestImageFourierNoiseProfile::NAME = "testimage.noise.fourier.profile";
00193 const string CTFSNRWeightProcessor::NAME = "ctf.snr.weight";
00194 const string TestImageLineWave::NAME = "testimage.linewave";
00195 const string TestTomoImage::NAME = "testimage.tomo.objects";
00196 const string TestImageGradient::NAME = "testimage.gradient";
00197 const string TestImageAxes::NAME = "testimage.axes";
00198 const string TestImageGaussian::NAME = "testimage.gaussian";
00199 const string TestImageScurve::NAME = "testimage.scurve";
00200 const string TestImageSphericalWave::NAME = "testimage.sphericalwave";
00201 const string TestImageSinewave::NAME = "testimage.sinewave";
00202 const string TestImageSinewaveCircular::NAME = "testimage.sinewave.circular";
00203 const string TestImageSquarecube::NAME = "testimage.squarecube";
00204 const string TestImageEllipse::NAME = "testimage.ellipsoid";
00205 const string TestImageHollowEllipse::NAME = "testimage.ellipsoid.hollow";
00206 const string TestImageCirclesphere::NAME = "testimage.circlesphere";
00207 const string TestImageNoiseUniformRand::NAME = "testimage.noise.uniform.rand";
00208 const string TestImageNoiseGauss::NAME = "testimage.noise.gauss";
00209 const string TestImageCylinder::NAME = "testimage.cylinder";
00210 const string CCDNormProcessor::NAME = "filter.ccdnorm";
00211 const string WaveletProcessor::NAME = "basis.wavelet";
00212 const string TomoTiltEdgeMaskProcessor::NAME = "tomo.tiltedgemask";
00213 const string TomoTiltAngleWeightProcessor::NAME = "tomo.tiltangleweight";
00214 const string FFTProcessor::NAME = "basis.fft";
00215 const string RadialProcessor::NAME = "mask.radialprofile";
00216 const string HistogramBin::NAME = "histogram.bin";
00217 const string ModelEMCylinderProcessor::NAME = "math.model_em_cylinder";
00218 const string ApplyPolynomialProfileToHelix::NAME = "math.poly_radial_profile";
00219 const string BinarySkeletonizerProcessor::NAME="gorgon.binary_skel";
00220 const string MirrorProcessor::NAME = "xform.mirror";
00221 const string NewLowpassTopHatProcessor::NAME = "filter.lowpass.tophat";
00222 const string NewHighpassTopHatProcessor::NAME = "filter.highpass.tophat";
00223 const string NewBandpassTopHatProcessor::NAME = "filter.bandpass.tophat";
00224 const string NewHomomorphicTopHatProcessor::NAME = "filter.homomorphic.tophat";
00225 const string NewLowpassGaussProcessor::NAME = "filter.lowpass.gauss";
00226 const string LowpassAutoBProcessor::NAME="filter.lowpass.autob";
00227 const string NewHighpassGaussProcessor::NAME = "filter.highpass.gauss";
00228 const string NewBandpassGaussProcessor::NAME = "filter.bandpass.gauss";
00229 const string NewHomomorphicGaussProcessor::NAME = "filter.homomorphic.gauss";
00230 const string NewInverseGaussProcessor::NAME = "filter.gaussinverse";
00231 const string SHIFTProcessor::NAME = "filter.shift";
00232 const string InverseKaiserI0Processor::NAME = "filter.kaiser_io_inverse";
00233 const string InverseKaiserSinhProcessor::NAME = "filter.kaisersinhinverse";
00234 const string NewRadialTableProcessor::NAME = "filter.radialtable";
00235 const string LowpassRandomPhaseProcessor::NAME = "filter.lowpass.randomphase";
00236 const string NewLowpassButterworthProcessor::NAME = "filter.lowpass.butterworth";
00237 const string NewHighpassButterworthProcessor::NAME = "filter.highpass.butterworth";
00238 const string NewHomomorphicButterworthProcessor::NAME = "filter.homomorphic.butterworth";
00239 const string NewLowpassTanhProcessor::NAME = "filter.lowpass.tanh";
00240 const string NewHighpassTanhProcessor::NAME = "filter.highpass.tanh";
00241 const string NewHomomorphicTanhProcessor::NAME = "filter.homomorphic.tanh";
00242 const string NewBandpassTanhProcessor::NAME = "filter.bandpass.tanh";
00243 const string CTF_Processor::NAME = "filter.CTF_";
00244 const string ConvolutionKernelProcessor::NAME = "filter.convolution.kernel";
00245 const string RotateInFSProcessor::NAME = "rotateinfs";
00246 
00247 //#ifdef EMAN2_USING_CUDA
00248 //const string CudaMultProcessor::NAME = "cuda.math.mult";
00249 //const string CudaCorrelationProcessor::NAME = "cuda.correlate";
00250 //#endif //EMAN2_USING_CUDA
00251 
00252 #if 0
00253 //const string XYZProcessor::NAME = "XYZ";
00254 #endif  //0
00255 
00256 
00257 template <> Factory < Processor >::Factory()
00258 {
00259         force_add<HighpassAutoPeakProcessor>();
00260         force_add<LinearRampFourierProcessor>();
00261         force_add<LoGFourierProcessor>();
00262         force_add<DoGFourierProcessor>();
00263 
00264         force_add<AmpweightFourierProcessor>();
00265         force_add<Wiener2DFourierProcessor>();
00266         force_add<LowpassAutoBProcessor>();
00267         
00268         force_add<LinearPyramidProcessor>();
00269         force_add<LinearRampProcessor>();
00270         force_add<AbsoluateValueProcessor>();
00271         force_add<FloorValueProcessor>();
00272         force_add<BooleanProcessor>();
00273         force_add<KmeansSegmentProcessor>();
00274         force_add<DistanceSegmentProcessor>();
00275         force_add<ValuePowProcessor>();
00276         force_add<ValueSquaredProcessor>();
00277         force_add<ValueSqrtProcessor>();
00278         force_add<Rotate180Processor>();
00279         force_add<TransformProcessor>();
00280         force_add<ScaleTransformProcessor>();
00281         force_add<ApplySymProcessor>();
00282         force_add<IntTranslateProcessor>();
00283         force_add<InvertCarefullyProcessor>();
00284 
00285         force_add<ClampingProcessor>();
00286         force_add<NSigmaClampingProcessor>();
00287 
00288         force_add<ToZeroProcessor>();
00289         force_add<ToMinvalProcessor>();
00290         force_add<CutToZeroProcessor>();
00291         force_add<BinarizeProcessor>();
00292 //      force_add<BinarizeAmpProcessor>();
00293         force_add<BinarizeFourierProcessor>();
00294         force_add<CollapseProcessor>();
00295         force_add<LinearXformProcessor>();
00296 
00297         force_add<ExpProcessor>();
00298         force_add<RangeThresholdProcessor>();
00299         force_add<SigmaProcessor>();
00300         force_add<LogProcessor>();
00301         force_add<FiniteProcessor>();
00302 
00303         force_add< BinaryOperateProcessor<MaxPixelOperator> >();
00304         force_add< BinaryOperateProcessor<MinPixelOperator> >();
00305 
00306         force_add<PaintProcessor>();
00307         force_add<WatershedProcessor>();
00308         force_add<MaskSharpProcessor>();
00309         force_add<MaskEdgeMeanProcessor>();
00310         force_add<MaskNoiseProcessor>();
00311         force_add<MaskGaussProcessor>();
00312         force_add<MaskGaussNonuniformProcessor>();
00313         force_add<MaskGaussInvProcessor>();
00314 
00315         force_add<MaxShrinkProcessor>();
00316         force_add<MinShrinkProcessor>();
00317         force_add<MeanShrinkProcessor>();
00318         force_add<MedianShrinkProcessor>();
00319         force_add<FFTResampleProcessor>();
00320         force_add<NonConvexProcessor>();
00321 
00322         force_add<MakeRadiusSquaredProcessor>();
00323         force_add<MakeRadiusProcessor>();
00324 
00325         force_add<ComplexNormPixel>();
00326 
00327         force_add<LaplacianProcessor>();
00328         force_add<ZeroConstantProcessor>();
00329 
00330         force_add<BoxMedianProcessor>();
00331         force_add<BoxSigmaProcessor>();
00332         force_add<BoxMaxProcessor>();
00333 
00334         force_add<MinusPeakProcessor>();
00335         force_add<PeakOnlyProcessor>();
00336         force_add<DiffBlockProcessor>();
00337 
00338         force_add<CutoffBlockProcessor>();
00339 //      force_add<GradientRemoverProcessor>();
00340         force_add<GradientPlaneRemoverProcessor>();
00341         force_add<FlattenBackgroundProcessor>();
00342         force_add<VerticalStripeProcessor>();
00343         force_add<RealToFFTProcessor>();
00344         force_add<SigmaZeroEdgeProcessor>();
00345         force_add<RampProcessor>();
00346 
00347         force_add<BeamstopProcessor>();
00348         force_add<MeanZeroEdgeProcessor>();
00349         force_add<AverageXProcessor>();
00350         force_add<DecayEdgeProcessor>();
00351         force_add<ZeroEdgeRowProcessor>();
00352         force_add<ZeroEdgePlaneProcessor>();
00353 
00354         force_add<BilateralProcessor>();
00355 
00356         force_add<ConvolutionProcessor>();
00357 
00358         force_add<NormalizeStdProcessor>();
00359         force_add<NormalizeUnitProcessor>();
00360         force_add<NormalizeUnitSumProcessor>();
00361         force_add<NormalizeMaskProcessor>();
00362         force_add<NormalizeEdgeMeanProcessor>();
00363         force_add<NormalizeCircleMeanProcessor>();
00364         force_add<NormalizeLREdgeMeanProcessor>();
00365         force_add<NormalizeMaxMinProcessor>();
00366         force_add<NormalizeByMassProcessor>();
00367         force_add<NormalizeRowProcessor>();
00368         force_add<NormalizeRampNormVar>();
00369 
00370         force_add<HistogramBin>();
00371 
00372         force_add<NormalizeToLeastSquareProcessor>();
00373 
00374         force_add<RotationalAverageProcessor>();
00375         force_add<RotationalSubstractProcessor>();
00376         force_add<FlipProcessor>();
00377         force_add<TransposeProcessor>();
00378         force_add<MirrorProcessor>();
00379 
00380         force_add<AddNoiseProcessor>();
00381         force_add<AddSigmaNoiseProcessor>();
00382         force_add<AddRandomNoiseProcessor>();
00383 
00384         force_add<PhaseToCenterProcessor>();
00385         force_add<PhaseToCornerProcessor>();
00386         force_add<FourierToCenterProcessor>();
00387         force_add<FourierToCornerProcessor>();
00388         force_add<AutoMask2DProcessor>();
00389         force_add<AutoMask3DProcessor>();
00390         force_add<AutoMask3D2Processor>();
00391         force_add<AddMaskShellProcessor>();
00392         force_add<AutoMaskAsymUnit>();
00393 
00394         force_add<CTFSNRWeightProcessor>();
00395 
00396         force_add<ToMassCenterProcessor>();
00397         force_add<PhaseToMassCenterProcessor>();
00398         force_add<ACFCenterProcessor>();
00399         force_add<SNRProcessor>();
00400 
00401         force_add<XGradientProcessor>();
00402         force_add<YGradientProcessor>();
00403         force_add<ZGradientProcessor>();
00404 
00405         force_add<FileFourierProcessor>();
00406 
00407         force_add<SymSearchProcessor>();
00408         force_add<LocalNormProcessor>();
00409 
00410         force_add<IndexMaskFileProcessor>();
00411         force_add<CoordinateMaskFileProcessor>();
00412         force_add<SetSFProcessor>();
00413         force_add<MatchSFProcessor>();
00414 
00415         force_add<SmartMaskProcessor>();
00416         force_add<IterBinMaskProcessor>();
00417 
00418         force_add<TestImageGaussian>();
00419         force_add<TestImagePureGaussian>();
00420         force_add<TestImageSinewave>();
00421         force_add<TestImageSphericalWave>();
00422         force_add<TestImageSinewaveCircular>();
00423         force_add<TestImageSquarecube>();
00424         force_add<TestImageCirclesphere>();
00425         force_add<TestImageAxes>();
00426         force_add<TestImageNoiseUniformRand>();
00427         force_add<TestImageNoiseGauss>();
00428         force_add<TestImageScurve>();
00429         force_add<TestImageCylinder>();
00430         force_add<TestImageGradient>();
00431         force_add<TestTomoImage>();
00432         force_add<TestImageLineWave>();
00433         force_add<TestImageEllipse>();
00434         force_add<TestImageHollowEllipse>();
00435         force_add<TestImageFourierNoiseGaussian>();
00436         force_add<TestImageFourierNoiseProfile>();
00437 
00438         force_add<TomoTiltEdgeMaskProcessor>();
00439         force_add<TomoTiltAngleWeightProcessor>();
00440 
00441         force_add<NewLowpassTopHatProcessor>();
00442         force_add<NewHighpassTopHatProcessor>();
00443         force_add<NewBandpassTopHatProcessor>();
00444         force_add<NewHomomorphicTopHatProcessor>();
00445         force_add<NewLowpassGaussProcessor>();
00446         force_add<NewHighpassGaussProcessor>();
00447         force_add<NewBandpassGaussProcessor>();
00448         force_add<NewHomomorphicGaussProcessor>();
00449         force_add<NewInverseGaussProcessor>();
00450         force_add<LowpassRandomPhaseProcessor>();
00451         force_add<NewLowpassButterworthProcessor>();
00452         force_add<NewHighpassButterworthProcessor>();
00453         force_add<NewHomomorphicButterworthProcessor>();
00454         force_add<NewLowpassTanhProcessor>();
00455         force_add<NewHighpassTanhProcessor>();
00456         force_add<NewBandpassTanhProcessor>();
00457         force_add<NewHomomorphicTanhProcessor>();
00458         force_add<NewRadialTableProcessor>();
00459         force_add<InverseKaiserI0Processor>();
00460         force_add<InverseKaiserSinhProcessor>();
00461         force_add<CCDNormProcessor>();
00462         force_add<CTF_Processor>();
00463         force_add<SHIFTProcessor>();
00464 
00465         force_add<WaveletProcessor>();
00466         force_add<FFTProcessor>();
00467         force_add<RadialProcessor>();
00468 
00469         force_add<DirectionalSumProcessor>();
00470         force_add<ConvolutionKernelProcessor>();
00471         
00472         //Gorgon-related processors
00473         force_add<ModelEMCylinderProcessor>();
00474         force_add<ApplyPolynomialProfileToHelix>();
00475         force_add<BinarySkeletonizerProcessor>();
00476         force_add<RotateInFSProcessor>();
00477 
00478 //#ifdef EMAN2_USING_CUDA
00479 //      force_add<CudaMultProcessor>();
00480 //      force_add<CudaCorrelationProcessor>();
00481 //#endif // EMAN2_USING_CUDA
00482 
00483 //      force_add<XYZProcessor>();
00484 }
00485 
00486 void FiniteProcessor::process_pixel(float *x) const
00487 {
00488         if ( !Util::goodf(x) ) {
00489                 *x = to;
00490         }
00491 }
00492 
00493 
00494 EMData* Processor::process(const EMData * const image)
00495 {
00496         EMData * result = image->copy();
00497         process_inplace(result);
00498         return result;
00499 }
00500 
00501 void ImageProcessor::process_inplace(EMData * image)
00502 {
00503         if (!image) {
00504                 LOGWARN("NULL image");
00505                 return;
00506         }
00507 
00508         EMData *processor_image = create_processor_image();
00509 
00510         if (image->is_complex()) {
00511                 (*image) *= *processor_image;
00512         }
00513         else {
00514                 EMData *fft = image->do_fft();
00515                 (*fft) *= (*processor_image);
00516                 EMData *ift = fft->do_ift();
00517 
00518                 float *data = image->get_data();
00519                 float *t = data;
00520                 float *ift_data = ift->get_data();
00521 
00522                 data = ift_data;
00523                 ift_data = t;
00524 
00525                 ift->update();
00526 
00527                 if( fft )
00528                 {
00529                         delete fft;
00530                         fft = 0;
00531                 }
00532 
00533                 if( ift )
00534                 {
00535                         delete ift;
00536                         ift = 0;
00537                 }
00538         }
00539 
00540         image->update();
00541 }
00542 
00543 #define FFTRADIALOVERSAMPLE 4
00544 void FourierProcessor::process_inplace(EMData * image)
00545 {
00546         if (!image) {
00547                 LOGWARN("NULL Image");
00548                 return;
00549         }
00550 
00551         preprocess(image);
00552 
00553         int array_size = FFTRADIALOVERSAMPLE * image->get_ysize();
00554         float step=0.5f/array_size;
00555 
00556         vector < float >yarray(array_size);
00557 
00558         create_radial_func(yarray);
00559 
00560         if (image->is_complex()) {
00561                 image->apply_radial_func(0, step, yarray);
00562         }
00563         else {
00564                 EMData *fft = image->do_fft();
00565                 fft->apply_radial_func(0, step, yarray);
00566                 EMData *ift = fft->do_ift();
00567 
00568                 memcpy(image->get_data(),ift->get_data(),ift->get_xsize()*ift->get_ysize()*ift->get_zsize()*sizeof(float));
00569 
00570                 //ift->update(); Unecessary
00571 
00572                 if( fft )
00573                 {
00574                         delete fft;
00575                         fft = 0;
00576                 }
00577 
00578                 if( ift )
00579                 {
00580                         delete ift;
00581                         ift = 0;
00582                 }
00583         }
00584 
00585         image->update();
00586 }
00587 
00588 void FourierAnlProcessor::process_inplace(EMData * image)
00589 {
00590         if (!image) {
00591                 LOGWARN("NULL Image");
00592                 return;
00593         }
00594 
00595         preprocess(image);
00596 
00597 //      int array_size = FFTRADIALOVERSAMPLE * image->get_ysize();
00598 //      float step=0.5f/array_size;
00599 //
00600 //      vector < float >yarray(array_size);
00601 
00602 
00603         if (image->is_complex()) {
00604                 vector <float>yarray = image->calc_radial_dist(image->get_ysize()/2,0,1.0,1);
00605                 create_radial_func(yarray,image);
00606                 image->apply_radial_func(0, 0.5f/yarray.size(), yarray);
00607         }
00608         else {
00609                 EMData *fft = image->do_fft();
00610                 vector <float>yarray = fft->calc_radial_dist(fft->get_ysize()/2,0,1.0,1);
00611                 create_radial_func(yarray,image);
00612                 fft->apply_radial_func(0, 0.5f/yarray.size(), yarray,0);                // 4/30/10 stevel turned off interpolation to fix problem with matched filter
00613                 EMData *ift = fft->do_ift();
00614 
00615                 memcpy(image->get_data(),ift->get_data(),ift->get_xsize()*ift->get_ysize()*ift->get_zsize()*sizeof(float));
00616 
00617                 //ift->update(); Unecessary
00618 
00619                 delete fft;
00620                 delete ift;
00621 
00622         }
00623 
00624         image->update();
00625 }
00626 
00627 void LowpassAutoBProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const{
00628         float apix=(float)image->get_attr("apix_x");
00629         int verbose=(int)params["verbose"];
00630 //      int adaptnoise=params.set_default("adaptnoise",0);
00631         float noisecutoff=(float)params.set_default("noisecutoff",0.0);
00632         if (apix<=0 || apix>7.0f) throw ImageFormatException("0 < apix_x < 7.0");
00633         float ds=1.0f/(apix*image->get_xsize());        // 0.5 is because radial mask is 2x oversampled
00634         unsigned int start=(int)floor(1.0/(15.0*ds));
00635         unsigned int end=radial_mask.size()-2;
00636         if (noisecutoff>0) end=(int)floor(noisecutoff/ds);
00637         if (end>radial_mask.size()-2) {
00638                 printf("WARNING: specified noisecutoff too close to Nyquist, reset !");
00639                 end=radial_mask.size()-2;
00640         }
00641         if (end<start+2) {
00642                 printf("WARNING: noise cutoff too close to 15 A ! Results will not be good...");
00643                 start=end-5;
00644         }
00645 
00646         FILE *out=NULL;
00647         if (verbose>2)  out=fopen("fitplot.txt","w");
00648         int N=(radial_mask.size()-start-2);
00649         float *x=(float *)malloc(N*sizeof(float));
00650         float *y=(float *)malloc(N*sizeof(float));
00651         float *dy=(float *)malloc(N*sizeof(float));
00652         for (unsigned int i=start; i<radial_mask.size()-2; i++ ) {              // -2 is arbitrary because sometimes the last pixel or two have funny values
00653                 x[i-start]=ds*ds*i*i;
00654                 if (radial_mask[i]>0) y[i-start]=log(radial_mask[i]); // ok
00655                 else if (i>start) y[i-start]=y[i-start-1];              // not good
00656                 else y[i-start]=0.0;                                                    // bad
00657                 if (i<radial_mask.size()-3) dy[i-start]=y[i-start]-y[i-start-1];        // creates a 'derivative' of sorts, for use in adaptnoise
00658                 if (out) fprintf(out,"%f\t%f\n",x[i-start],y[i-start]);
00659         }
00660         if (out) fclose(out);
00661 
00662         float slope=0,intercept=0;
00663         Util::calc_least_square_fit(end-start, x,y,&slope,&intercept,1);
00664 
00665         if (verbose) printf("slope=%f  intercept=%f\n",slope,intercept);
00666 
00667         float B=(float)params["bfactor"]+slope*4.0f/2.0f;               // *4 is for Henderson definition, 2.0 is for intensity vs amplitude
00668         float B2=(float)params["bfactor"];
00669 
00670         if (verbose) printf("User B = %1.2f  Corrective B = %1.2f  Total B=%1.3f\n",(float)params["bfactor"],slope*2.0,B);
00671 
00672         float cutval=exp(-B*pow(end*ds,2.0f)/4.0f)/exp(-B2*pow(end*ds,2.0f)/4.0f);
00673         for (unsigned int i=0; i<radial_mask.size(); i++) {
00674                 if (i<=end) radial_mask[i]=exp(-B*pow(i*ds,2.0f)/4.0f);
00675                 else radial_mask[i]=cutval*exp(-B2*pow(i*ds,2.0f)/4.0f);
00676         }
00677         if (verbose>1) Util::save_data(0,ds,radial_mask,"filter.txt");
00678 
00679         free(x);
00680         free(y);
00681         free(dy);
00682  }
00683 
00684 void SNREvalProcessor::process_inplace(EMData * image)
00685 {
00686         int ys=image->get_ysize();
00687 
00688         EMData *mask1=new EMData(ys,ys,1);
00689         mask1->process_inplace("mask.gaussian",Dict("outer_radius", ys/2.0));
00690         EMData *mask2=mask1->copy();
00691         mask2->mult(-1.0f);
00692         mask2->add(1.0);
00693         mask2->process_inplace("mask.decayedge2d",Dict("width",4));
00694 
00695 /*
00696 
00697 
00698 
00699 mask1=EMData(ys2,ys2,1)
00700                 mask1.to_one()
00701                 mask1.process_inplace("mask.gaussian",{"outer_radius":radius})
00702                 mask2=mask1.copy()*-1+1
00703 #               mask1.process_inplace("mask.decayedge2d",{"width":4})
00704                 mask2.process_inplace("mask.decayedge2d",{"width":4})
00705                 mask1.clip_inplace(Region(-(ys2*(oversamp-1)/2),-(ys2*(oversamp-1)/2),ys,ys))
00706                 mask2.clip_inplace(Region(-(ys2*(oversamp-1)/2),-(ys2*(oversamp-1)/2),ys,ys))
00707                 ratio1=mask1.get_attr("square_sum")/(ys*ys)     #/1.035
00708                 ratio2=mask2.get_attr("square_sum")/(ys*ys)
00709                 masks[(ys,radius)]=(mask1,ratio1,mask2,ratio2)
00710 
00711 
00712 
00713 */
00714 }
00715 
00716 void AmpweightFourierProcessor::process_inplace(EMData * image)
00717 {
00718         EMData *fft;
00719         float *fftd;
00720         int f=0;
00721 //      static float sum1=0,sum1a=0;
00722 //      static double sum2=0,sum2a=0;
00723 
00724         if (!image) {
00725                 LOGWARN("NULL Image");
00726                 return;
00727         }
00728 
00729         if (!image->is_complex()) {
00730                 fft = image->do_fft();
00731                 fftd = fft->get_data();
00732                 f=1;
00733         }
00734         else {
00735                 fft=image;
00736                 fftd=image->get_data();
00737         }
00738         float *sumd = NULL;
00739         if (sum) sumd=sum->get_data();
00740 //printf("%d %d    %d %d\n",fft->get_xsize(),fft->get_ysize(),sum->get_xsize(),sum->get_ysize());
00741         size_t n = (size_t)fft->get_xsize()*fft->get_ysize()*fft->get_zsize();
00742         for (size_t i=0; i<n; i+=2) {
00743                 float c;
00744                 if (dosqrt) c=pow(fftd[i]*fftd[i]+fftd[i+1]*fftd[i+1],0.25f);
00745 #ifdef  _WIN32
00746                 else c = static_cast<float>(_hypot(fftd[i],fftd[i+1]));
00747 #else
00748                 else c = static_cast<float>(hypot(fftd[i],fftd[i+1]));
00749 #endif  //_WIN32
00750                 if (c==0) c=1.0e-30f;   // prevents divide by zero in normalization
00751                 fftd[i]*=c;
00752                 fftd[i+1]*=c;
00753                 if (sumd) { sumd[i]+=c; sumd[i+1]+=0; }
00754 
00755                 // debugging
00756 /*              if (i==290*1+12) {
00757                         sum1+=fftd[i];
00758                         sum2+=fftd[i];
00759                         printf("%f\t%f\t%f\t%f\t%f\t%f\n",sum1,sum2,fftd[i],fftd[i+1],sumd[i],c);
00760                 }
00761                 if (i==290*50+60) {
00762                         sum1a+=fftd[i];
00763                         sum2a+=fftd[i];
00764                         printf("%f\t%f\t%f\t%f\t%f\t%f\n",sum1a,sum2a,fftd[i],fftd[i+1],sumd[i],c);
00765         }*/
00766         }
00767 
00768         if (f) {
00769                 fft->update();
00770                 EMData *ift=fft->do_ift();
00771                 memcpy(image->get_data(),ift->get_data(),n*sizeof(float));
00772                 delete fft;
00773                 delete ift;
00774         }
00775 
00776         sum->update();
00777         image->update();
00778 
00779 }
00780 
00781 void DistanceSegmentProcessor::process_inplace(EMData *)
00782 {
00783         printf("Process inplace not implemented. Please use process.\n");
00784         return;
00785 }
00786 
00787 
00788 EMData *DistanceSegmentProcessor::process(const EMData * const image)
00789 {
00790         EMData * result = image->copy();
00791 
00792         float thr = params.set_default("thr",0.9f);
00793         float minsegsep = params.set_default("minsegsep",5.0f);
00794         float maxsegsep = params.set_default("maxsegsep",5.1f);
00795         int verbose = params.set_default("verbose",0);
00796 
00797         vector<Pixel> pixels=image->calc_highest_locations(thr);
00798 
00799         vector<float> centers(3);       // only 1 to start
00800         int nx=image->get_xsize();
00801         int ny=image->get_ysize();
00802         int nz=image->get_zsize();
00803 //      int nxy=nx*ny;
00804 
00805         // seed the process with the highest valued point
00806         centers[0]=(float)pixels[0].x;
00807         centers[1]=(float)pixels[0].y;
00808         centers[2]=(float)pixels[0].z;
00809         pixels.erase(pixels.begin());
00810 
00811         // outer loop. We add one center per iteration
00812         // This is NOT a very efficient algorithm, it assumes points are fairly sparse
00813         while (pixels.size()>0) {
00814                 // iterate over pixels until we find a new center (then stop), delete any 'bad' pixels
00815                 // no iterators because we remove elements
00816 
00817                 for (unsigned int i=0; i<pixels.size(); i++) {
00818 
00819                         Pixel p=pixels[i];
00820                         // iterate over existing centers to see if this pixel should be removed ... technically we only should need to check the last center
00821                         for (unsigned int j=0; j<centers.size(); j+=3) {
00822                                 float d=Util::hypot3(centers[j]-p.x,centers[j+1]-p.y,centers[j+2]-p.z);
00823                                 if (d<minsegsep) {              // conflicts with existing center, erase
00824                                         pixels.erase(pixels.begin()+i);
00825                                         i--;
00826                                         break;
00827                                 }
00828                         }
00829                 }
00830 
00831                 int found=0;
00832                 for (unsigned int i=0; i<pixels.size() && found==0; i++) {
00833                         Pixel p=pixels[i];
00834 
00835                         // iterate again to see if this may be a new valid center. Start at the end so we tend to build chains
00836                         for (unsigned int j=centers.size()-3; j>0; j-=3) {
00837                                 float d=Util::hypot3(centers[j]-p.x,centers[j+1]-p.y,centers[j+2]-p.z);
00838                                 if (d<maxsegsep) {              // we passed minsegsep question already, so we know we're in the 'good' range
00839                                         centers.push_back((float)p.x);
00840                                         centers.push_back((float)p.y);
00841                                         centers.push_back((float)p.z);
00842                                         pixels.erase(pixels.begin()+i); // in the centers list now, don't need it any more
00843                                         found=1;
00844                                         break;
00845                                 }
00846                         }
00847                 }
00848 
00849                 // If we went through the whole list and didn't find one, we need to reseed again
00850                 if (!found && pixels.size()) {
00851                         if (verbose) printf("New chain\n");
00852                         centers.push_back((float)pixels[0].x);
00853                         centers.push_back((float)pixels[0].y);
00854                         centers.push_back((float)pixels[0].z);
00855                         pixels.erase(pixels.begin());
00856                 }
00857 
00858                 if (verbose) printf("%d points found\n",(int)(centers.size()/3));
00859         }
00860 
00861         // after we have our list of centers classify pixels
00862         for (int z=0; z<nz; z++) {
00863                 for (int y=0; y<ny; y++) {
00864                         for (int x=0; x<nz; x++) {
00865                                 if (image->get_value_at(x,y,z)<thr) {
00866                                         result->set_value_at(x,y,z,-1.0);               //below threshold -> -1 (unclassified)
00867                                         continue;
00868                                 }
00869                                 int bcls=-1;                    // best matching class
00870                                 float bdist=(float)(nx+ny+nz);  // distance for best class
00871                                 for (unsigned int c=0; c<centers.size()/3; c++) {
00872                                         float d=Util::hypot3(x-centers[c*3],y-centers[c*3+1],z-centers[c*3+2]);
00873                                         if (d<bdist) { bdist=d; bcls=c; }
00874                                 }
00875                                 result->set_value_at(x,y,z,(float)bcls);                // set the pixel to the class number
00876                         }
00877                 }
00878         }
00879 
00880         result->set_attr("segment_centers",centers);
00881 
00882         return result;
00883 }
00884 
00885 EMData* ApplySymProcessor::process(const EMData * const image)
00886 {
00887         Symmetry3D* sym = Factory<Symmetry3D>::get((string)params.set_default("sym","c1"));
00888         vector<Transform> transforms = sym->get_syms();
00889         
00890         Averager* imgavg = Factory<Averager>::get((string)params.set_default("avger","mean"));
00891         for(vector<Transform>::const_iterator trans_it = transforms.begin(); trans_it != transforms.end(); trans_it++) {
00892                 Transform t = *trans_it;
00893                 EMData* transformed = image->process("xform",Dict("transform",&t));
00894                 imgavg->add_image(transformed);
00895                 delete transformed;
00896         }
00897         return imgavg->finish();
00898 }
00899 
00900 void ApplySymProcessor::process_inplace(EMData* image)
00901 {
00902         cout << "Not implemented yet" << endl;
00903 }
00904 
00905 EMData* KmeansSegmentProcessor::process(const EMData * const image)
00906 {
00907         EMData * result = image->copy();
00908 
00909         int nseg = params.set_default("nseg",12);
00910         float thr = params.set_default("thr",-1.0e30f);
00911         int ampweight = params.set_default("ampweight",1);
00912         float maxsegsize = params.set_default("maxsegsize",10000.0f);
00913         float minsegsep = params.set_default("minsegsep",0.0f);
00914         int maxiter = params.set_default("maxiter",100);
00915         int maxvoxmove = params.set_default("maxvoxmove",25);
00916         int verbose = params.set_default("verbose",0);
00917 
00918         vector<float> centers(nseg*3);
00919         vector<float> count(nseg);
00920         int nx=image->get_xsize();
00921         int ny=image->get_ysize();
00922         int nz=image->get_zsize();
00923 //      int nxy=nx*ny;
00924 
00925         // seed
00926         for (int i=0; i<nseg*3; i+=3) {
00927                 centers[i]=  Util::get_frand(0.0f,(float)nx);
00928                 centers[i+1]=Util::get_frand(0.0f,(float)ny);
00929                 centers[i+2]=Util::get_frand(0.0f,(float)nz);
00930         }
00931 
00932         for (int iter=0; iter<maxiter; iter++) {
00933                 // **** classify
00934                 size_t pixmov=0;                // count of moved pixels
00935                 for (int z=0; z<nz; z++) {
00936                         for (int y=0; y<ny; y++) {
00937                                 for (int x=0; x<nz; x++) {
00938                                         if (image->get_value_at(x,y,z)<thr) {
00939                                                 result->set_value_at(x,y,z,-1.0);               //below threshold -> -1 (unclassified)
00940                                                 continue;
00941                                         }
00942                                         int bcls=-1;                    // best matching class
00943                                         float bdist=(float)(nx+ny+nz);  // distance for best class
00944                                         for (int c=0; c<nseg; c++) {
00945                                                 float d=Util::hypot3(x-centers[c*3],y-centers[c*3+1],z-centers[c*3+2]);
00946                                                 if (d<bdist) { bdist=d; bcls=c; }
00947                                         }
00948                                         if ((int)result->get_value_at(x,y,z)!=bcls) pixmov++;
00949                                         if (bdist>maxsegsize) result->set_value_at(x,y,z,-1);           // pixel is too far from any center
00950                                         else result->set_value_at(x,y,z,(float)bcls);           // set the pixel to the class number
00951                                 }
00952                         }
00953                 }
00954 
00955                 // **** adjust centers
00956                 for (int i=0; i<nseg*3; i++) centers[i]=0;
00957                 for (int i=0; i<nseg; i++) count[i]=0;
00958 
00959                 // weighted sums
00960                 for (int z=0; z<nz; z++) {
00961                         for (int y=0; y<ny; y++) {
00962                                 for (int x=0; x<nz; x++) {
00963                                         int cls = (int)result->get_value_at(x,y,z);
00964                                         if (cls==-1) continue;
00965                                         float w=1.0;
00966                                         if (ampweight) w=image->get_value_at(x,y,z);
00967 
00968                                         centers[cls*3]+=x*w;
00969                                         centers[cls*3+1]+=y*w;
00970                                         centers[cls*3+2]+=z*w;
00971                                         count[cls]+=w;
00972                                 }
00973                         }
00974                 }
00975 
00976                 // now each becomes center of mass, or gets randomly reseeded
00977                 int nreseed=0;
00978                 for (int c=0; c<nseg; c++) {
00979                         // reseed
00980                         if (count[c]==0) {
00981                                 nreseed++;
00982                                 do {
00983                                         centers[c*3]=  Util::get_frand(0.0f,(float)nx);
00984                                         centers[c*3+1]=Util::get_frand(0.0f,(float)ny);
00985                                         centers[c*3+2]=Util::get_frand(0.0f,(float)nz);
00986                                 } 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
00987                         }
00988                         // center of mass
00989                         else {
00990                                 centers[c*3]/=count[c];
00991                                 centers[c*3+1]/=count[c];
00992                                 centers[c*3+2]/=count[c];
00993                         }
00994                 }
00995 
00996                 // with minsegsep, check separation
00997                 if (minsegsep>0) {
00998                         for (int c1=0; c1<nseg-1; c1++) {
00999                                 for (int c2=c1+1; c2<nseg; c2++) {
01000                                         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) {
01001                                                 nreseed++;
01002                                                 do {
01003                                                         centers[c1*3]=  Util::get_frand(0.0f,(float)nx);
01004                                                         centers[c1*3+1]=Util::get_frand(0.0f,(float)ny);
01005                                                         centers[c1*3+2]=Util::get_frand(0.0f,(float)nz);
01006                                                 } while (image->get_value_at((int)centers[c1*3],(int)centers[c1*3+1],(int)centers[c1*3+2])<thr);
01007                                         }
01008                                 }
01009                         }
01010                 }
01011 
01012 
01013                 if (verbose) printf("Iteration %3d: %6ld voxels moved, %3d classes reseeded\n",iter,pixmov,nreseed);
01014                 if (nreseed==0 && pixmov<(size_t)maxvoxmove) break;             // termination conditions met
01015         }
01016 
01017         result->set_attr("segment_centers",centers);
01018 
01019         return result;
01020 }
01021 
01022 void KmeansSegmentProcessor::process_inplace(EMData *)
01023 {
01024         printf("Process inplace not implemented. Please use process.\n");
01025         return;
01026 }
01027 
01028 
01029 void LinearPyramidProcessor::process_inplace(EMData *image) {
01030 
01031         if (image->get_zsize()!=1) { throw ImageDimensionException("Only 2-D images supported"); }
01032 
01033         float *d=image->get_data();
01034         int nx=image->get_xsize();
01035         int ny=image->get_ysize();
01036 
01037         for (int y=0; y<ny; y++) {
01038                 for (int x=0; x<nx; x++) {
01039                         int l=x+y*nx;
01040                         d[l]*=1.0f-abs(x-nx/2)*abs(y-ny/2)*4.0f/(nx*ny);
01041                 }
01042         }
01043         image->update();
01044 }
01045 
01046 EMData * Wiener2DAutoAreaProcessor::process(const EMData * image)
01047 {
01048 // TODO NOT IMPLEMENTED YET !!!
01049         EMData *ret = 0;
01050         const EMData *fft;
01051         float *fftd;
01052         int f=0;
01053 
01054         if (!image) {
01055                 LOGWARN("NULL Image");
01056                 return ret;
01057         }
01058         throw NullPointerException("Processor not yet implemented");
01059 
01060         if (!image->is_complex()) {
01061                 fft = image->do_fft();
01062                 fftd = fft->get_data();
01063                 f=1;
01064         }
01065         else {
01066                 fft=image;
01067                 fftd=image->get_data();
01068         }
01069 
01070         return ret;
01071 }
01072 
01073 void Wiener2DAutoAreaProcessor::process_inplace(EMData *image) {
01074         EMData *tmp=process(image);
01075         memcpy(image->get_data(),tmp->get_data(),image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
01076         delete tmp;
01077         image->update();
01078         return;
01079 }
01080 
01081 
01082 EMData * Wiener2DFourierProcessor::process(const EMData *in)
01083 {
01084         const EMData *in2 = 0;
01085         if (in->is_complex()) in2=in;
01086         else in=in->do_fft();
01087 
01088         EMData *filt = in->copy_head();
01089         Ctf *ictf = ctf;
01090 
01091         if (!ictf) ctf=(Ctf *)in->get_attr("ctf");
01092 
01093         ictf->compute_2d_complex(filt,Ctf::CTF_WIENER_FILTER);
01094         filt->mult(*in2);
01095         EMData *ret=filt->do_ift();
01096 
01097         delete filt;
01098         if (!in->is_complex()) delete in2;
01099 
01100         if(!ictf && ctf) {delete ctf; ctf=0;}
01101         return(ret);
01102 /*      const EMData *fft;
01103         float *fftd;
01104         int f=0;
01105 
01106         if (!image) {
01107                 LOGWARN("NULL Image");
01108                 return ret;
01109         }
01110 
01111         if (!image->is_complex()) {
01112                 fft = image->do_fft();
01113                 fftd = fft->get_data();
01114                 f=1;
01115         }
01116         else {
01117                 fft=image;
01118                 fftd=image->get_data();
01119         }
01120         powd=image->get_data();
01121 
01122         int bad=0;
01123         for (int i=0; i<image->get_xsize()*image->get_ysize(); i+=2) {
01124                 snr=(fftd[i]*fftd[i]+fftd[i+1]*fftd[i+1]-powd[i])/powd[i];
01125                 if (snr<0) { bad++; snr=0; }
01126 
01127         }
01128 
01129         print("%d bad pixels\n",snr);
01130 */      return ret;
01131 
01132 }
01133 
01134 void Wiener2DFourierProcessor::process_inplace(EMData *image) {
01135         EMData *tmp=process(image);
01136         memcpy(image->get_data(),tmp->get_data(),image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
01137         delete tmp;
01138         image->update();
01139         return;
01140 }
01141 
01142 void LinearRampFourierProcessor::create_radial_func(vector < float >&radial_mask) const
01143 {
01144         Assert(radial_mask.size() > 0);
01145         for (size_t i = 0; i < radial_mask.size(); i++) {
01146                 radial_mask[i] = (float)i;
01147         }
01148 }
01149 
01150 void LowpassRandomPhaseProcessor::create_radial_func(vector < float >&radial_mask) const { };
01151 
01152 void LowpassRandomPhaseProcessor::process_inplace(EMData *image)
01153 {
01154         float cutoff=0;
01155         preprocess(image);
01156         if( params.has_key("cutoff_abs") ) {
01157                 cutoff=(float)params["cutoff_abs"];
01158         }
01159         else {
01160                 printf("A cutoff_* parameter is required by filter.lowpass.randomphase\n");
01161                 return;
01162         }
01163         
01164         
01165         if (image->get_zsize()==1) {
01166                 int flag=0;
01167                 if (!image->is_complex()) { image->do_fft_inplace(); flag=1; }
01168                 image->ri2ap();
01169                 int nx=image->get_xsize();
01170                 int ny=image->get_ysize();
01171                 
01172                 int z=0;
01173                 float *data=image->get_data();
01174                 for (int y=-ny/2; y<ny/2; y++) {
01175                         for (int x=0; x<nx/2+1; x++) {
01176                                 if (hypot(x/float(nx),y/float(ny))>=cutoff) {
01177                                         size_t idx=image->get_complex_index_fast(x,y,z);                // location of the amplitude
01178                                         data[idx+1]=Util::get_frand(0.0f,(float)(M_PI*2.0));
01179                                 }
01180                         }
01181                 }
01182 
01183                 image->ap2ri();
01184 
01185                 if (flag) {
01186                         image->do_ift_inplace();
01187                         image->depad();
01188                 }
01189         }
01190         else {          // 3D
01191                 int flag=0;
01192                 if (!image->is_complex()) { image->do_fft_inplace(); flag=1; }
01193                 image->ri2ap();
01194                 int nx=image->get_xsize();
01195                 int ny=image->get_ysize();
01196                 int nz=image->get_zsize();
01197                 
01198                 float *data=image->get_data();
01199                 for (int z=-nz/2; z<nz/2; z++) {
01200                         for (int y=-ny/2; y<ny/2; y++) {
01201                                 for (int x=0; x<nx/2+1; x++) {
01202                                         if (Util::hypot3(x/float(nx),y/float(ny),z/float(nz))>=cutoff) {
01203                                                 size_t idx=image->get_complex_index_fast(x,y,z);                // location of the amplitude
01204                                                 data[idx+1]=Util::get_frand(0.0f,(float)(M_PI*2.0));
01205                                         }
01206                                 }
01207                         }
01208                 }
01209                 image->ap2ri();
01210 
01211                 if (flag) {
01212                         image->do_ift_inplace();
01213                         image->depad();
01214                 }
01215         }
01216 }
01217 
01218 void HighpassAutoPeakProcessor::preprocess(EMData * image)
01219 {
01220         if(params.has_key("apix")) {
01221                 image->set_attr("apix_x", (float)params["apix"]);
01222                 image->set_attr("apix_y", (float)params["apix"]);
01223                 image->set_attr("apix_z", (float)params["apix"]);
01224         }
01225 
01226         const Dict dict = image->get_attr_dict();
01227 
01228         if( params.has_key("cutoff_abs") ) {
01229                 highpass = params["cutoff_abs"];
01230         }
01231         else if( params.has_key("cutoff_freq") ) {
01232                 highpass = (float)params["cutoff_freq"] * (float)dict["apix_x"] * (float)dict["nx"] / 2.0f;
01233         }
01234         else if( params.has_key("cutoff_pixels") ) {
01235                 highpass = (float)params["cutoff_pixels"] / (float)dict["nx"];
01236         }
01237 }
01238 
01239 void HighpassAutoPeakProcessor::create_radial_func(vector < float >&radial_mask, EMData *) const
01240 {
01241         unsigned int c;
01242 
01243 //      for (unsigned int i=0; i<radial_mask.size(); i++) printf("%d\t%f\n",i,radial_mask[i]);
01244         for (c=2; c<radial_mask.size(); c++) if (radial_mask[c-1]<=radial_mask[c]) break;
01245         if (c>highpass) c=(unsigned int)highpass;               // the *2 is for the 2x oversampling
01246 
01247         radial_mask[0]=0.0;
01248 //      for (int i=1; i<radial_mask.size(); i++) radial_mask[i]=(i<=c?radial_mask[c+1]/radial_mask[i]:1.0);
01249         for (unsigned int i=1; i<radial_mask.size(); i++) radial_mask[i]=(i<=c?0.0f:1.0f);
01250 
01251         printf("%f %d\n",highpass,c);
01252 //      for (unsigned int i=0; i<radial_mask.size(); i++) printf("%d\t%f\n",i,radial_mask[i]);
01253 
01254 }
01255 
01256 void LinearRampProcessor::create_radial_func(vector < float >&radial_mask) const
01257 {
01258         Assert(radial_mask.size() > 0);
01259         float x = 0.0f , step = 0.5f/radial_mask.size();
01260         size_t size=radial_mask.size();
01261         for (size_t i = 0; i < size; i++) {
01262                 radial_mask[i] = intercept + ((slope - intercept) * i) / (size - 1.0f);
01263                 x += step;
01264         }
01265 }
01266 
01267 void LoGFourierProcessor::create_radial_func(vector < float >&radial_mask) const
01268 {
01269         
01270         Assert(radial_mask.size() > 0);
01271         float x = 0.0f , nqstep = 0.5f/radial_mask.size();
01272         size_t size=radial_mask.size();
01273         float var = sigma*sigma;
01274         for (size_t i = 0; i < size; i++) {
01275                 radial_mask[i] = ((x*x - var)/var*var)*exp(-x*x/2*var);
01276                 x += nqstep;
01277         }
01278 }
01279 
01280 void DoGFourierProcessor::create_radial_func(vector < float >&radial_mask) const
01281 {
01282         
01283         Assert(radial_mask.size() > 0);
01284         float x = 0.0f , nqstep = 0.5f/radial_mask.size();
01285         size_t size=radial_mask.size();
01286         float norm = 1.0f/sqrt(2*M_PI);
01287         for (size_t i = 0; i < size; i++) {
01288                 radial_mask[i] = norm*((1.0f/sigma1*exp(-x*x/(2.0f*sigma1*sigma1))) - (1.0f/sigma2*exp(-x*x/(2.0f*sigma2*sigma2))));
01289                 x += nqstep;
01290         }
01291 }
01292 
01293 void RealPixelProcessor::process_inplace(EMData * image)
01294 {
01295         if (!image) {
01296                 LOGWARN("NULL Image");
01297                 return;
01298         }
01299 
01300         maxval = image->get_attr("maximum");
01301         mean = image->get_attr("mean");
01302         sigma = image->get_attr("sigma");
01303 
01304         calc_locals(image);
01305 
01306         size_t size = (size_t)image->get_xsize() *
01307                           (size_t)image->get_ysize() *
01308                           (size_t)image->get_zsize();
01309         float *data = image->get_data();
01310 
01311         for (size_t i = 0; i < size; ++i) {
01312                 process_pixel(&data[i]);
01313         }
01314         image->update();
01315 }
01316 
01317 void CoordinateProcessor::process_inplace(EMData * image)
01318 {
01319         if (!image) {
01320                 LOGWARN("NULL Image");
01321                 return;
01322         }
01323 
01324         maxval = image->get_attr("maximum");
01325         mean = image->get_attr("mean");
01326         sigma = image->get_attr("sigma");
01327         nx = image->get_xsize();
01328         ny = image->get_ysize();
01329         nz = image->get_zsize();
01330         is_complex = image->is_complex();
01331 
01332         calc_locals(image);
01333 
01334 
01335         if (!is_valid()) {
01336                 return;
01337         }
01338 
01339         float *data = image->get_data();
01340         size_t i = 0;
01341 
01342         for (int z = 0; z < nz; z++) {
01343                 for (int y = 0; y < ny; y++) {
01344                         for (int x = 0; x < nx; x++) {
01345                                 process_pixel(&data[i], x, y, z);
01346                                 ++i;
01347                         }
01348                 }
01349         }
01350         image->update();
01351 }
01352 
01353 void PaintProcessor::process_inplace(EMData *image) {
01354         int nx=image->get_xsize();
01355         int ny=image->get_ysize();
01356         int nz=image->get_zsize();
01357 
01358         if (nz==1) {
01359                 float r;
01360                 for (int j=(y<r2?0:y-r2); j<(y+r2>ny?ny:y+r2); j++) {
01361                         for (int i=(x<r2?0:x-r2); i<(x+r2>nx?nx:x+r2); i++) {
01362                                 r=sqrt(float(Util::square(i-x)+Util::square(j-y)));
01363                                 if (r>r2 && r>r1) continue;
01364                                 if (r>r1) image->set_value_at(i,j,0,v2*(r-r1)/(r2-r1)+v1*(r2-r)/(r2-r1));
01365                                 else image->set_value_at(i,j,0,v1);
01366                         }
01367                 }
01368         }
01369         else {
01370                 float r;
01371                 for (int k=(z<r2?0:z-r2); k<(z+r2>nz?nz:z+r2); k++) {
01372                         for (int j=(y<r2?0:y-r2); j<(y+r2>ny?ny:y+r2); j++) {
01373                                 for (int i=(x<r2?0:x-r2); i<(x+r2>nx?nx:x+r2); i++) {
01374                                 r=sqrt(float(Util::square(i-x)+Util::square(j-y)+Util::square(k-z)));
01375                                 if (r>r2 && r>r1) continue;
01376                                 if (r>r1) image->set_value_at(i,j,k,v2*(r-r1)/(r2-r1)+v1*(r2-r)/(r2-r1));
01377                                 else image->set_value_at(i,j,k,v1);
01378                                 }
01379                         }
01380                 }
01381         }
01382         image->update();
01383 }
01384 
01385 void WatershedProcessor::process_inplace(EMData * image) {
01386         vector<float> xpoints = params["xpoints"];
01387         vector<float> ypoints = params["ypoints"];
01388         vector<float> zpoints = params["zpoints"];
01389 
01390         vector<int> x(xpoints.begin(),xpoints.end());
01391         vector<int> y(ypoints.begin(),ypoints.end());
01392         vector<int> z(zpoints.begin(),zpoints.end());
01393 
01394 
01395         // throw if vector lengths are unequal
01396 
01397 //      float maxval = -99999;
01398         /*
01399         for(unsigned int i = 0; i < xpoints.size(); ++i) {
01400                 float val = image->get_value_at(x[i],y[i],z[i]);
01401                 if (val > maxval) {
01402                         maxval = val;
01403                 }
01404         }*/
01405 
01406         float minval = params["minval"];
01407 
01408         EMData* mask = new EMData(*image);
01409         mask->to_zero();
01410 
01411         // Set the original mask values
01412         for(unsigned int i = 0; i < xpoints.size(); ++i) {
01413                 try {
01414                         mask->set_value_at(x[i],y[i],z[i], (float)(i+1));
01415                 } catch (...) {
01416                         continue;
01417                 }
01418         }
01419         mask->write_image("seeds2.mrc");
01420 //      int dis = 500;
01421 //      float dx = (maxval-minval)/((float) dis - 1);
01422 
01423 
01424 //      for(int i = 0; i < dis; ++i) {
01425 //              float val = maxval-i*dx;
01426 
01427                 while( true ) {
01428                         bool cont= false;
01429                         for(unsigned int j = 0; j < xpoints.size(); ++j)
01430                         {
01431 
01432                                 Vec3i coord(x[j],y[j],z[j]);
01433                                 vector<Vec3i> region;
01434                                 region.push_back(coord);
01435                                 vector<Vec3i> find_region_input = region;
01436                                 while (true) {
01437                                         vector<Vec3i> v = find_region(mask,find_region_input, j+1, region);
01438                                         if (v.size() == 0 ) break;
01439                                         else find_region_input = v;
01440                                 }
01441 
01442                                 vector<Vec3i> tmp(region.begin(),region.end());
01443                                 region.clear();
01444                                 for(vector<Vec3i>::const_iterator it = tmp.begin(); it != tmp.end(); ++it ) {
01445                                         vector<Vec3i> tmp2 = watershed(mask, image, minval, *it, j+1);
01446                                         copy(tmp2.begin(),tmp2.end(),back_inserter(region));
01447                                 }
01448                                 if (region.size() != 0) cont = true;
01449                         }
01450 
01451                         if (!cont) break;
01452                 }
01453 //      }
01454 
01455         memcpy(image->get_data(),mask->get_data(),sizeof(float)*image->get_size());
01456         image->update();
01457 }
01458 
01459 
01460 vector<Vec3i > WatershedProcessor::find_region(EMData* mask,const vector<Vec3i >& coords, const int mask_value, vector<Vec3i >& region)
01461 {
01462         static vector<Vec3i> two_six_connected;
01463         if (two_six_connected.size() == 0) {
01464                 for(int i = -1; i <= 1; ++i) {
01465                         for(int j = -1; j <= 1; ++j) {
01466                                 for(int  k = -1; k <= 1; ++k) {
01467                                         if ( j != 0 || i != 0 || k != 0) {
01468                                                 two_six_connected.push_back(Vec3i(i,j,k));
01469                                         }
01470                                 }
01471                         }
01472                 }
01473         }
01474 
01475         vector<Vec3i> ret;
01476         for(vector<Vec3i>::const_iterator it = two_six_connected.begin(); it != two_six_connected.end(); ++it ) {
01477                 for(vector<Vec3i>::const_iterator it2 = coords.begin(); it2 != coords.end(); ++it2 ) {
01478                         if  (mask->get_value_at((*it2)[0],(*it2)[1],(*it2)[2]) != mask_value) throw;
01479                         Vec3i c = (*it)+(*it2);
01480 
01481                         if ( c[0] < 0 || c[0] >= mask->get_xsize()) continue;
01482                         if ( c[1] < 0 || c[1] >= mask->get_ysize()) continue;
01483                         if ( c[2] < 0 || c[2] >= mask->get_zsize()) continue;
01484 
01485                         if( mask->get_value_at(c[0],c[1],c[2]) == mask_value ) {
01486                                 if (find(ret.begin(),ret.end(),c) == ret.end()) {
01487                                         if (find(region.begin(),region.end(),c) == region.end()) {
01488                                                 region.push_back(c);
01489                                                 ret.push_back(c);
01490                                         }
01491                                 }
01492                         }
01493                 }
01494         }
01495         return ret;
01496 }
01497 
01498 vector<Vec3i > WatershedProcessor::watershed(EMData* mask, EMData* image, const float&, const Vec3i& coordinate, const int mask_value)
01499 {
01500         static vector<Vec3i> two_six_connected;
01501         if (two_six_connected.size() == 0) {
01502                 for(int i = -1; i <= 1; ++i) {
01503                         for(int j = -1; j <= 1; ++j) {
01504                                 for(int  k = -1; k <= 1; ++k) {
01505                                         if ( j != 0 || i != 0 || k != 0) {
01506                                                 two_six_connected.push_back(Vec3i(i,j,k));
01507                                         }
01508                                 }
01509                         }
01510                 }
01511         }
01512 
01513         if  (mask->get_value_at(coordinate[0],coordinate[1],coordinate[2]) != mask_value) throw;
01514 
01515         vector<Vec3i> ret;
01516         for(vector<Vec3i>::const_iterator it = two_six_connected.begin(); it != two_six_connected.end(); ++it ) {
01517                 Vec3i c = (*it)+coordinate;
01518 
01519                 if ( c[0] < 0 || c[0] >= image->get_xsize()) continue;
01520                 if ( c[1] < 0 || c[1] >= image->get_ysize()) continue;
01521                 if ( c[2] < 0 || c[2] >= image->get_zsize()) continue;
01522 
01523         //      cout << image->get_value_at(c[0],c[1],c[2] ) << " " << threshold << endl;
01524                 if( image->get_value_at(c[0],c[1],c[2]) != 0 && (mask->get_value_at(c[0],c[1],c[2]) == 0 )) {
01525                         //cout << "Added something " << mask_value << endl;
01526                         mask->set_value_at(c[0],c[1],c[2], (float)mask_value);
01527                         ret.push_back(c);
01528                 }
01529         }
01530         return ret;
01531 }
01532 
01533 
01534 void CircularMaskProcessor::calc_locals(EMData *)
01535 {
01536         xc = Util::fast_floor(nx/2.0f) + dx;
01537         yc = Util::fast_floor(ny/2.0f) + dy;
01538         zc = Util::fast_floor(nz/2.0f) + dz;
01539 
01540         if (outer_radius < 0) {
01541                 outer_radius = nx / 2 + outer_radius +1;
01542                 outer_radius_square = outer_radius * outer_radius;
01543         }
01544 
01545         if (inner_radius <= 0) {
01546                 inner_radius_square = 0;
01547         }
01548 }
01549 
01550 
01551 void MaskEdgeMeanProcessor::calc_locals(EMData * image)
01552 {
01553         if (!image) {
01554                 throw NullPointerException("NULL image");
01555         }
01556         int nitems = 0;
01557         float sum = 0;
01558         float *data = image->get_data();
01559         size_t i = 0;
01560 
01561         xc = Util::fast_floor(nx/2.0f) + dx;
01562         yc = Util::fast_floor(ny/2.0f) + dy;
01563         zc = Util::fast_floor(nz/2.0f) + dz;
01564         
01565         for (int z = 0; z < nz; ++z) {
01566                 for (int y = 0; y < ny; ++y) {
01567                         for (int x = 0; x < nx; ++x) {
01568                                 float x1 = sqrt((x - xc) * (x - xc) + (y - yc) * (y - yc) + (z - zc) * (z - zc));
01569                                 if (x1 <= outer_radius + ring_width && x1 >= outer_radius - ring_width) {
01570                                         sum += data[i];
01571                                         ++nitems;
01572                                 }
01573                                 ++i;
01574                         }
01575                 }
01576         }
01577 
01578         ring_avg = sum / nitems;
01579 }
01580 
01581 void ToMinvalProcessor::process_inplace(EMData * image)
01582 {
01583         if (!image) {
01584                 LOGWARN("NULL Image");
01585                 return;
01586         }
01587 
01588         float minval = params.set_default("minval",0.0f);
01589         float newval = params.set_default("newval",minval);
01590 
01591         size_t size = (size_t)image->get_xsize() *
01592                           (size_t)image->get_ysize() *
01593                           (size_t)image->get_zsize();
01594         float *data = image->get_data();
01595 
01596 
01597 
01598         for (size_t i = 0; i < size; ++i) {
01599                 if (data[i]<minval) data[i]=newval;
01600         }
01601         image->update();
01602 }
01603 
01604 
01605 void ComplexPixelProcessor::process_inplace(EMData * image)
01606 {
01607         if (!image) {
01608                 LOGWARN("NULL image");
01609                 return;
01610         }
01611         if (!image->is_complex()) {
01612                 LOGWARN("cannot apply complex processor on a real image. Nothing is done.");
01613                 return;
01614         }
01615 
01616         size_t size = (size_t)image->get_xsize() *
01617                           (size_t)image->get_ysize() *
01618                           (size_t)image->get_zsize();
01619         float *data = image->get_data();
01620 
01621         image->ri2ap();
01622 
01623         for (size_t i = 0; i < size; i += 2) {
01624                 process_pixel(data);
01625                 data += 2;
01626         }
01627 
01628         image->update();
01629         image->ap2ri();
01630 }
01631 
01632 
01633 
01634 void AreaProcessor::process_inplace(EMData * image)
01635 {
01636         if (!image) {
01637                 LOGWARN("NULL Image");
01638                 return;
01639         }
01640 
01641         float *data = image->get_data();
01642 
01643         nx = image->get_xsize();
01644         ny = image->get_ysize();
01645         nz = image->get_zsize();
01646 
01647         int n = (areasize - 1) / 2;
01648         matrix_size = areasize * areasize;
01649 
01650         if (nz > 1) {
01651                 matrix_size *= areasize;
01652         }
01653 
01654         float *matrix = new float[matrix_size];
01655         kernel = new float[matrix_size];
01656 
01657         size_t cpysize = areasize * sizeof(float);
01658         size_t start = (nx * ny + nx + 1) * n;
01659 
01660         int xend = nx - n;
01661         int yend = ny - n;
01662 
01663         int zstart = n;
01664         int zend = nz - n;
01665 
01666         int zbox_start = 0;
01667         int zbox_end = areasize;
01668 
01669         if (nz == 1) {
01670                 zstart = 0;
01671                 zend = 1;
01672                 zbox_end = 1;
01673         }
01674 
01675         size_t nsec = (size_t)nx * (size_t)ny;
01676         int box_nsec = areasize * areasize;
01677 
01678         create_kernel();
01679 
01680         size_t total_size = (size_t)nx * (size_t)ny * (size_t)nz;
01681         float *data2 = new float[total_size];
01682         memcpy(data2, data, total_size * sizeof(float));
01683 
01684         size_t k;
01685         for (int z = zstart; z < zend; z++) {
01686                 for (int y = n; y < yend; y++) {
01687                         for (int x = n; x < xend; x++) {
01688 
01689                                 k = (size_t)z * nsec + y * nx + x;
01690 
01691                                 for (int bz = zbox_start; bz < zbox_end; bz++) {
01692                                         for (int by = 0; by < areasize; by++) {
01693                                                 memcpy(&matrix[(size_t)bz * box_nsec + by * areasize],
01694                                                            &data2[k - start + bz * nsec + by * nx], cpysize);
01695                                         }
01696                                 }
01697 
01698                                 process_pixel(&data[k], (float) x, (float) y, (float) z, matrix);
01699                         }
01700                 }
01701         }
01702 
01703         if( matrix )
01704         {
01705                 delete[]matrix;
01706                 matrix = 0;
01707         }
01708 
01709         if( kernel )
01710         {
01711                 delete[]kernel;
01712                 kernel = 0;
01713         }
01714         image->update();
01715 }
01716 
01717 
01718 void LaplacianProcessor::create_kernel() const
01719 {
01720         if (nz == 1) {
01721                 memset(kernel, 0, areasize * areasize);
01722                 kernel[1] = -0.25f;
01723                 kernel[3] = -0.25f;
01724                 kernel[5] = -0.25f;
01725                 kernel[7] = -0.25f;
01726                 kernel[4] = 1;
01727         }
01728         else {
01729                 memset(kernel, 0, (size_t)areasize * areasize * areasize);
01730                 kernel[4] = -1.0f / 6.0f;
01731                 kernel[10] = -1.0f / 6.0f;
01732                 kernel[12] = -1.0f / 6.0f;
01733                 kernel[14] = -1.0f / 6.0f;
01734                 kernel[16] = -1.0f / 6.0f;
01735                 kernel[22] = -1.0f / 6.0f;
01736                 kernel[13] = 1;
01737         }
01738 }
01739 
01740 void BoxStatProcessor::process_inplace(EMData * image)
01741 {
01742         if (!image) {
01743                 LOGWARN("NULL Image");
01744                 return;
01745         }
01746 
01747         int nx = image->get_xsize();
01748         int ny = image->get_ysize();
01749         int nz = image->get_zsize();
01750 
01751         int n = params.set_default("radius",1);
01752         int areasize = 2 * n + 1;
01753 
01754         int matrix_size = areasize * areasize;
01755         if (nz > 1) {
01756                 matrix_size *= areasize;
01757         }
01758 
01759         float *array = new float[matrix_size];
01760 //      image->process_inplace("normalize");
01761 
01762         float *data = image->get_data();
01763         size_t total_size = (size_t)nx * (size_t)ny * (size_t)nz;
01764         float *data2 = new float[total_size];
01765         memcpy(data2, data, total_size * sizeof(float));
01766 
01767         int z_begin = 0;
01768         int z_end = 1;
01769         int nzz=0;
01770         if (nz > 1) {
01771                 z_begin = n;
01772                 z_end = nz - n;
01773                 nzz=n;
01774         }
01775 
01776         int nxy = nx * ny;
01777 
01778         for (int k = z_begin; k < z_end; k++) {
01779                 size_t knxy = (size_t)k * nxy;
01780 
01781                 for (int j = n; j < ny - n; j++) {
01782                         int jnx = j * nx;
01783 
01784                         for (int i = n; i < nx - n; i++) {
01785                                 size_t s = 0;
01786 
01787                                 for (int i2 = i - n; i2 <= i + n; i2++) {
01788                                         for (int j2 = j - n; j2 <= j + n; j2++) {
01789                                                 for (int k2 = k - nzz; k2 <= k + nzz; k2++) {
01790                                                         array[s] = data2[i2 + j2 * nx + (size_t)k2 * nxy];
01791                                                         ++s;
01792                                                 }
01793                                         }
01794                                 }
01795 
01796                                 process_pixel(&data[i + jnx + knxy], array, matrix_size);
01797                         }
01798                 }
01799         }
01800 
01801         image->update();
01802 
01803         if( data2 )
01804         {
01805                 delete[]data2;
01806                 data2 = 0;
01807         }
01808 }
01809 
01810 void DiffBlockProcessor::process_inplace(EMData * image)
01811 {
01812         if (!image) {
01813                 LOGWARN("NULL Image");
01814                 return;
01815         }
01816 
01817         int nz = image->get_zsize();
01818 
01819         if (nz > 1) {
01820                 LOGERR("%s Processor doesn't support 3D", get_name().c_str());
01821                 throw ImageDimensionException("3D model not supported");
01822         }
01823 
01824         int nx = image->get_xsize();
01825         int ny = image->get_ysize();
01826 
01827         int v1 = params["cal_half_width"];
01828         int v2 = params["fill_half_width"];
01829 
01830         int v0 = v1 > v2 ? v1 : v2;
01831 
01832         if (v2 <= 0) {
01833                 v2 = v1;
01834         }
01835 
01836         float *data = image->get_data();
01837 
01838         for (int y = v0; y <= ny - v0 - 1; y += v2) {
01839                 for (int x = v0; x <= nx - v0 - 1; x += v2) {
01840 
01841                         float sum = 0;
01842                         for (int y1 = y - v1; y1 <= y + v1; y1++) {
01843                                 for (int x1 = x - v1; x1 <= x + v1; x1++) {
01844                                         sum += data[x1 + y1 * nx];
01845                                 }
01846                         }
01847                         float mean = sum / ((v1 * 2 + 1) * (v1 * 2 + 1));
01848 
01849                         for (int j = y - v2; j <= y + v2; j++) {
01850                                 for (int i = x - v2; i <= x + v2; i++) {
01851                                         data[i + j * nx] = mean;
01852                                 }
01853                         }
01854                 }
01855         }
01856 
01857         image->update();
01858 }
01859 
01860 
01861 void CutoffBlockProcessor::process_inplace(EMData * image)
01862 {
01863         if (!image) {
01864                 LOGWARN("NULL Image");
01865                 return;
01866         }
01867         int nz = image->get_zsize();
01868 
01869         if (nz > 1) {
01870                 LOGERR("%s Processor doesn't support 3D", get_name().c_str());
01871                 throw ImageDimensionException("3D model not supported");
01872         }
01873 
01874         int nx = image->get_xsize();
01875         int ny = image->get_ysize();
01876 
01877         float value1 = params["value1"];
01878         float value2 = params["value2"];
01879 
01880         int v1 = (int) value1;
01881         int v2 = (int) value2;
01882         if (v2 > v1 / 2) {
01883                 LOGERR("invalid value2 '%f' in CutoffBlockProcessor", value2);
01884                 return;
01885         }
01886 
01887         if (v2 <= 0) {
01888                 v2 = v1;
01889         }
01890 
01891         float *data = image->get_data();
01892         int y = 0, x = 0;
01893         for (y = 0; y <= ny - v1; y += v1) {
01894                 for (x = 0; x <= nx - v1; x += v1) {
01895 
01896                         EMData *clip = image->get_clip(Region(x, y, v1, v1));
01897                         EMData *fft = clip->do_fft();
01898 
01899                         float *fft_data = fft->get_data();
01900                         float sum = 0;
01901                         int nitems = 0;
01902 
01903                         for (int i = -v2; i < v2; i++) {
01904                                 for (int j = 0; j < v2; j++) {
01905                                         if (j == 0 && i == 0) {
01906                                                 continue;
01907                                         }
01908 
01909 #ifdef  _WIN32
01910                                         if (_hypot(j, i) < value2) {
01911 #else
01912                                         if (hypot(j, i) < value2) {
01913 #endif
01914                                                 int t = j * 2 + (i + v1 / 2) * (v1 + 2);
01915                                                 sum += (fft_data[t] * fft_data[t] + fft_data[t + 1] * fft_data[t + 1]);
01916                                                 nitems++;
01917                                         }
01918                                 }
01919                         }
01920 
01921                         if( clip )
01922                         {
01923                                 delete clip;
01924                                 clip = 0;
01925                         }
01926 
01927                         float mean = sum / nitems;
01928 
01929                         for (int i = y; i < y + v1; i++) {
01930                                 for (int j = x; j < x + v1; j++) {
01931                                         data[i * nx + j] = mean;
01932                                 }
01933                         }
01934                 }
01935         }
01936 
01937         memset(&data[y * nx], 0, (ny - y) * nx * sizeof(float));
01938 
01939         for (int i = 0; i < ny; i++) {
01940                 memset(&data[i * nx + x], 0, (nx - x) * sizeof(float));
01941         }
01942 
01943         image->update();
01944 }
01945 
01946 void MedianShrinkProcessor::process_inplace(EMData * image)
01947 {
01948         if (image->is_complex()) throw ImageFormatException("Error, the median shrink processor does not work on complex images");
01949 
01950         int shrink_factor =  params.set_default("n",0);
01951         if (shrink_factor <= 1) {
01952                 throw InvalidValueException(shrink_factor,
01953                                                                         "median shrink: shrink factor must > 1");
01954         }
01955 
01956         int nx = image->get_xsize();
01957         int ny = image->get_ysize();
01958         int nz = image->get_zsize();
01959 
01960 //      if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) || (nz > 1 && (nz % shrink_factor != 0))) {
01961 //              throw InvalidValueException(shrink_factor, "Image size not divisible by shrink factor");
01962 //      }
01963 
01964 
01965         int shrunken_nx = nx / shrink_factor;
01966         int shrunken_ny = ny / shrink_factor;
01967         int shrunken_nz = 1;
01968         if (nz > 1) shrunken_nz = nz / shrink_factor;
01969 
01970         EMData* copy = image->copy();
01971         image->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
01972         accrue_median(image,copy,shrink_factor);
01973         image->update();
01974         if( copy )
01975         {
01976                 delete copy;
01977                 copy = 0;
01978         }
01979 }
01980 
01981 //
01982 EMData* MedianShrinkProcessor::process(const EMData *const image)
01983 {
01984         if (image->is_complex()) throw ImageFormatException("Error, the median shrink processor does not work on complex images");
01985 
01986         int shrink_factor =  params.set_default("n",0);
01987         if (shrink_factor <= 1) {
01988                 throw InvalidValueException(shrink_factor,
01989                                                                         "median shrink: shrink factor must > 1");
01990         }
01991         int nx = image->get_xsize();
01992         int ny = image->get_ysize();
01993         int nz = image->get_zsize();
01994 
01995 
01996 //      if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) || (nz > 1 && (nz % shrink_factor != 0))) {
01997 //              throw InvalidValueException(shrink_factor, "Image size not divisible by shrink factor");
01998 //      }
01999 
02000 
02001         int shrunken_nx = nx / shrink_factor;
02002         int shrunken_ny = ny / shrink_factor;
02003         int shrunken_nz = 1;
02004         if (nz > 1) shrunken_nz = nz / shrink_factor;
02005 
02006 //      EMData* ret = new EMData(shrunken_nx, shrunken_ny, shrunken_nz);
02007         EMData *ret = image->copy_head();
02008         ret->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
02009 
02010         accrue_median(ret,image,shrink_factor);
02011         ret->update();
02012         return ret;
02013 }
02014 
02015 void MedianShrinkProcessor::accrue_median(EMData* to, const EMData* const from,const int shrink_factor)
02016 {
02017 
02018         int nx_old = from->get_xsize();
02019         int ny_old = from->get_ysize();
02020 
02021         int threed_shrink_factor = shrink_factor * shrink_factor;
02022         int z_shrink_factor = 1;
02023         if (from->get_zsize() > 1) {
02024                 threed_shrink_factor *= shrink_factor;
02025                 z_shrink_factor = shrink_factor;
02026         }
02027 
02028         float *mbuf = new float[threed_shrink_factor];
02029 
02030 
02031         int nxy_old = nx_old * ny_old;
02032 
02033         int nx = to->get_xsize();
02034         int ny = to->get_ysize();
02035         int nz = to->get_zsize();
02036         int nxy_new = nx * ny;
02037 
02038         float * rdata = to->get_data();
02039         const float *const data_copy = from->get_const_data();
02040 
02041         for (int l = 0; l < nz; l++) {
02042                 int l_min = l * shrink_factor;
02043                 int l_max = l * shrink_factor + z_shrink_factor;
02044                 size_t cur_l = (size_t)l * nxy_new;
02045 
02046                 for (int j = 0; j < ny; j++) {
02047                         int j_min = j * shrink_factor;
02048                         int j_max = (j + 1) * shrink_factor;
02049                         size_t cur_j = j * nx + cur_l;
02050 
02051                         for (int i = 0; i < nx; i++) {
02052                                 int i_min = i * shrink_factor;
02053                                 int i_max = (i + 1) * shrink_factor;
02054 
02055                                 size_t k = 0;
02056                                 for (int l2 = l_min; l2 < l_max; l2++) {
02057                                         size_t cur_l2 = l2 * nxy_old;
02058 
02059                                         for (int j2 = j_min; j2 < j_max; j2++) {
02060                                                 size_t cur_j2 = j2 * nx_old + cur_l2;
02061 
02062                                                 for (int i2 = i_min; i2 < i_max; i2++) {
02063                                                         mbuf[k] = data_copy[i2 + cur_j2];
02064                                                         ++k;
02065                                                 }
02066                                         }
02067                                 }
02068 
02069                                 for (k = 0; k < size_t(threed_shrink_factor / 2 + 1); k++) {
02070                                         for (int i2 = k + 1; i2 < threed_shrink_factor; i2++) {
02071                                                 if (mbuf[i2] < mbuf[k]) {
02072                                                         float f = mbuf[i2];
02073                                                         mbuf[i2] = mbuf[k];
02074                                                         mbuf[k] = f;
02075                                                 }
02076                                         }
02077                                 }
02078 
02079                                 rdata[i + cur_j] = mbuf[threed_shrink_factor / 2];
02080                         }
02081                 }
02082         }
02083 
02084         if( mbuf )
02085         {
02086                 delete[]mbuf;
02087                 mbuf = 0;
02088         }
02089 
02090         to->scale_pixel((float)shrink_factor);
02091 }
02092 
02093 EMData* FFTResampleProcessor::process(const EMData *const image)
02094 {
02095         float sample_rate = params.set_default("n",0.0f);
02096         if (sample_rate <= 0.0F  )  {
02097                 throw InvalidValueException(sample_rate,        "sample rate must be >0 ");
02098         }
02099 
02100         EMData* result;
02101         if (image->is_complex()) result = image->copy();
02102         else result = image->do_fft();
02103         fft_resample(result,image,sample_rate);
02104         // The image may have been padded - we should shift it so that the phase origin is where FFTW expects it
02105         result->update();
02106         result->scale_pixel(sample_rate);
02107         return result;
02108 }
02109 
02110 void FFTResampleProcessor::process_inplace(EMData * image)
02111 {
02112         if (image->is_complex()) throw ImageFormatException("Error, the fft resampling processor does not work on complex images");
02113 
02114 
02115         float sample_rate = params.set_default("n",0.0f);
02116         if (sample_rate <= 0.0F  )  {
02117                 throw InvalidValueException(sample_rate,        "sample rate (n) must be >0 ");
02118         }
02119 
02120         fft_resample(image,image,sample_rate);
02121 
02122         image->scale_pixel(sample_rate);
02123         image->update();
02124 
02125 
02126 }
02127 
02128 void FFTResampleProcessor::fft_resample(EMData* to, const EMData *const from, const float& sample_rate) {
02129         int nx = from->get_xsize();
02130         int ny = from->get_ysize();
02131         int nz = from->get_zsize();
02132 
02133         int new_nx = static_cast<int>( static_cast<float> (nx) / sample_rate);
02134         int new_ny = static_cast<int>( static_cast<float> (ny) / sample_rate);
02135         int new_nz = static_cast<int>( static_cast<float> (nz) / sample_rate);
02136 
02137         if (new_nx == 0) throw UnexpectedBehaviorException("The resample rate causes the pixel dimensions in the x direction to go to zero");
02138         if (new_ny == 0) new_ny = 1;
02139         if (new_nz == 0) new_nz = 1;
02140 
02141         int ndim = from->get_ndim();
02142         if ( ndim < 3 ) {
02143                 new_nz = 1;
02144         }
02145         if ( ndim < 2 ) {
02146                 new_ny = 1;
02147         }
02148 
02149         int fft_x_correction = 1;
02150         if (new_nx % 2 == 0) fft_x_correction = 2;
02151 
02152         int fft_y_correction = 0;
02153         if (ny != 1 && new_ny % 2 == 0 && ny % 2 == 1) fft_y_correction = 1;
02154         else if (ny != 1 && new_ny % 2 == 1 && ny % 2 == 0) fft_y_correction = -1;
02155 
02156         int fft_z_correction = 0;
02157         if (nz != 1 && new_nz % 2 == 0 && nz % 2 == 1) fft_z_correction = 1;
02158         else if (nz != 1 && new_nz % 2 == 1 && nz % 2 == 0) fft_z_correction = -1;
02159 
02160         if ( ! to->is_complex()) to->do_fft_inplace();
02161 
02162         if (ndim != 1) to->process_inplace("xform.fourierorigin.tocenter");
02163 
02164         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);
02165         to->clip_inplace(clip);
02166 
02167         if (fft_x_correction == 1) to->set_fftodd(true);
02168         else to->set_fftodd(false);
02169 
02170         if (ndim != 1) to->process_inplace("xform.fourierorigin.tocorner");
02171 
02172         to->do_ift_inplace();
02173         to->depad_corner();
02174 
02175 }
02176 
02177 
02178 EMData* MeanShrinkProcessor::process(const EMData *const image)
02179 {
02180         if (image->is_complex()) throw ImageFormatException("Error, the mean shrink processor does not work on complex images");
02181 
02182         if (image->get_ndim() == 1) { throw ImageDimensionException("Error, mean shrink works only for 2D & 3D images"); }
02183 
02184         float shrink_factor0 = params.set_default("n",0.0f);
02185         int shrink_factor = int(shrink_factor0);
02186         if (shrink_factor0 <= 1.0F || ((shrink_factor0 != shrink_factor) && (shrink_factor0 != 1.5F) ) ) {
02187                 throw InvalidValueException(shrink_factor0,
02188                                                                         "mean shrink: shrink factor must be >1 integer or 1.5");
02189         }
02190 
02191         int nx = image->get_xsize();
02192         int ny = image->get_ysize();
02193         int nz = image->get_zsize();
02194 
02195 
02196         // here handle the special averaging by 1.5 for 2D case
02197         if (shrink_factor0==1.5 ) {
02198                 if (nz > 1 ) throw InvalidValueException(shrink_factor0, "mean shrink: only support 2D images for shrink factor = 1.5");
02199 
02200                 int shrunken_nx = (int(nx / 1.5)+1)/2*2;        // make sure the output size is even
02201                 int shrunken_ny = (int(ny / 1.5)+1)/2*2;
02202                 EMData* result = new EMData(shrunken_nx,shrunken_ny,1);
02203 
02204                 accrue_mean_one_p_five(result,image);
02205                 result->update();
02206 
02207                 return result;
02208         }
02209 
02210         int shrunken_nx = nx / shrink_factor;
02211         int shrunken_ny = ny / shrink_factor;
02212         int shrunken_nz = 1;
02213 
02214         if (nz > 1) {
02215                 shrunken_nz = nz / shrink_factor;
02216         }
02217 
02218 //      EMData* result = new EMData(shrunken_nx,shrunken_ny,shrunken_nz);
02219         EMData* result = image->copy_head();
02220         result->set_size(shrunken_nx,shrunken_ny,shrunken_nz);
02221         accrue_mean(result,image,shrink_factor);
02222 
02223         result->update();
02224 
02225         return result;
02226 }
02227 
02228 void MeanShrinkProcessor::process_inplace(EMData * image)
02229 {
02230         if (image->is_complex()) throw ImageFormatException("Error, the mean shrink processor does not work on complex images");
02231 
02232         if (image->get_ndim() == 1) { throw ImageDimensionException("Error, mean shrink works only for 2D & 3D images"); }
02233 
02234         float shrink_factor0 = params.set_default("n",0.0f);
02235         int shrink_factor = int(shrink_factor0);
02236         if (shrink_factor0 <= 1.0F || ((shrink_factor0 != shrink_factor) && (shrink_factor0 != 1.5F) ) ) {
02237                 throw InvalidValueException(shrink_factor0,
02238                                                                         "mean shrink: shrink factor must be >1 integer or 1.5");
02239         }
02240 
02241 /*      if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) ||
02242         (nz > 1 && (nz % shrink_factor != 0))) {
02243         throw InvalidValueException(shrink_factor,
02244         "Image size not divisible by shrink factor");
02245 }*/
02246 
02247         int nx = image->get_xsize();
02248         int ny = image->get_ysize();
02249         int nz = image->get_zsize();
02250         // here handle the special averaging by 1.5 for 2D case
02251         if (shrink_factor0==1.5 ) {
02252                 if (nz > 1 ) throw InvalidValueException(shrink_factor0, "mean shrink: only support 2D images for shrink factor = 1.5");
02253 
02254                 int shrunken_nx = (int(nx / 1.5)+1)/2*2;        // make sure the output size is even
02255                 int shrunken_ny = (int(ny / 1.5)+1)/2*2;
02256 
02257                 EMData* orig = image->copy();
02258                 image->set_size(shrunken_nx, shrunken_ny, 1);   // now nx = shrunken_nx, ny = shrunken_ny
02259                 image->to_zero();
02260 
02261                 accrue_mean_one_p_five(image,orig);
02262 
02263                 if( orig ) {
02264                         delete orig;
02265                         orig = 0;
02266                 }
02267                 image->update();
02268 
02269                 return;
02270         }
02271 
02272         accrue_mean(image,image,shrink_factor);
02273 
02274         int shrunken_nx = nx / shrink_factor;
02275         int shrunken_ny = ny / shrink_factor;
02276         int shrunken_nz = 1;
02277         if (nz > 1) shrunken_nz = nz / shrink_factor;
02278 
02279         image->update();
02280         image->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
02281 }
02282 
02283 void MeanShrinkProcessor::accrue_mean(EMData* to, const EMData* const from,const int shrink_factor)
02284 {
02285         const float * const data = from->get_const_data();
02286         float* rdata = to->get_data();
02287 
02288         size_t nx = from->get_xsize();
02289         size_t ny = from->get_ysize();
02290         size_t nz = from->get_zsize();
02291         size_t nxy = nx*ny;
02292 
02293 
02294         size_t shrunken_nx = nx / shrink_factor;
02295         size_t shrunken_ny = ny / shrink_factor;
02296         size_t shrunken_nz = 1;
02297         size_t shrunken_nxy = shrunken_nx * shrunken_ny;
02298 
02299         int normalize_shrink_factor = shrink_factor * shrink_factor;
02300         int z_shrink_factor = 1;
02301 
02302         if (nz > 1) {
02303                 shrunken_nz = nz / shrink_factor;
02304                 normalize_shrink_factor *= shrink_factor;
02305                 z_shrink_factor = shrink_factor;
02306         }
02307 
02308         float invnormfactor = 1.0f/(float)normalize_shrink_factor;
02309 
02310         for (size_t k = 0; k < shrunken_nz; k++) {
02311                 size_t k_min = k * shrink_factor;
02312                 size_t k_max = k * shrink_factor + z_shrink_factor;
02313                 size_t cur_k = k * shrunken_nxy;
02314 
02315                 for (size_t j = 0; j < shrunken_ny; j++) {
02316                         size_t j_min = j * shrink_factor;
02317                         size_t j_max = j * shrink_factor + shrink_factor;
02318                         size_t cur_j = j * shrunken_nx + cur_k;
02319 
02320                         for (size_t i = 0; i < shrunken_nx; i++) {
02321                                 size_t i_min = i * shrink_factor;
02322                                 size_t i_max = i * shrink_factor + shrink_factor;
02323 
02324                                 float sum = 0;
02325                                 for (size_t kk = k_min; kk < k_max; kk++) {
02326                                         size_t cur_kk = kk * nxy;
02327 
02328                                         for (size_t jj = j_min; jj < j_max; jj++) {
02329                                                 size_t cur_jj = jj * nx + cur_kk;
02330                                                 for (size_t ii = i_min; ii < i_max; ii++) {
02331                                                         sum += data[ii + cur_jj];
02332                                                 }
02333                                         }
02334                                 }
02335                                 rdata[i + cur_j] = sum * invnormfactor;
02336                         }
02337                 }
02338         }
02339         to->scale_pixel((float)shrink_factor);
02340 }
02341 
02342 
02343 void MeanShrinkProcessor::accrue_mean_one_p_five(EMData* to, const EMData * const from)
02344 {
02345         int nx0 = from->get_xsize(), ny0 = from->get_ysize();   // the original size
02346 
02347         int nx = to->get_xsize(), ny = to->get_ysize();
02348 
02349         float *data = to->get_data();
02350         const float * const data0 = from->get_const_data();
02351 
02352         for (int j = 0; j < ny; j++) {
02353                 int jj = int(j * 1.5);
02354                 float jw0 = 1.0F, jw1 = 0.5F;   // 3x3 -> 2x2, so each new pixel should have 2.25 of the old pixels
02355                 if ( j%2 ) {
02356                         jw0 = 0.5F;
02357                         jw1 = 1.0F;
02358                 }
02359                 for (int i = 0; i < nx; i++) {
02360                         int ii = int(i * 1.5);
02361                         float iw0 = 1.0F, iw1 = 0.5F;
02362                         float w = 0.0F;
02363 
02364                         if ( i%2 ) {
02365                                 iw0 = 0.5F;
02366                                 iw1 = 1.0F;
02367                         }
02368                         if ( jj < ny0 ) {
02369                                 if ( ii < nx0 ) {
02370                                         data[j * nx + i] = data0[ jj * nx0 + ii ] * jw0 * iw0 ;
02371                                         w += jw0 * iw0 ;
02372                                         if ( ii+1 < nx0 ) {
02373                                                 data[j * nx + i] += data0[ jj * nx0 + ii + 1] * jw0 * iw1;
02374                                                 w += jw0 * iw1;
02375                                         }
02376                                 }
02377                                 if ( jj +1 < ny0 ) {
02378                                         if ( ii < nx0 ) {
02379                                                 data[j * nx + i] += data0[ (jj+1) * nx0 + ii ] * jw1 * iw0;
02380                                                 w += jw1 * iw0;
02381                                                 if ( ii+1 < nx0 ) {
02382                                                         data[j * nx + i] += data0[ (jj+1) * nx0 + ii + 1] * jw1 * iw1;
02383                                                         w += jw1 * iw1;
02384                                                 }
02385                                         }
02386                                 }
02387                         }
02388                         if ( w>0 ) data[j * nx + i] /= w;
02389                 }
02390         }
02391 
02392         to->update();
02393         to->scale_pixel((float)1.5);
02394 }
02395 
02396 // This would have to be moved into the header if it were required in other source files
02397 template<class LogicOp>
02398 EMData* BooleanShrinkProcessor::process(const EMData *const image, Dict& params)
02399 {
02400         // The basic idea of this code is to iterate through each pixel in the output image
02401         // determining its value by investigation a region of the input image
02402 
02403         if (!image) throw NullPointerException("Attempt to max shrink a null image");
02404 
02405         if (image->is_complex() ) throw ImageFormatException("Can not max shrink a complex image");
02406 
02407 
02408         int shrink = params.set_default("n",2);
02409         int search = params.set_default("search",2);
02410 
02411         if ( shrink < 0 ) throw InvalidValueException(shrink, "Can not shrink by a value less than 0");
02412 
02413 
02414         int nz = image->get_zsize();
02415         int ny = image->get_ysize();
02416         int nx = image->get_xsize();
02417 
02418         if (nx == 1 && ny == 1 && nz == 1 ) return image->copy();
02419 
02420         LogicOp op;
02421         EMData* return_image = new EMData();
02422 
02423         int shrinkx = shrink;
02424         int shrinky = shrink;
02425         int shrinkz = shrink;
02426 
02427         int searchx = search;
02428         int searchy = search;
02429         int searchz = search;
02430 
02431         // Clamping the shrink values to the dimension lengths
02432         // ensures that the return image has non zero dimensions
02433         if ( shrinkx > nx ) shrinkx = nx;
02434         if ( shrinky > ny ) shrinky = ny;
02435         if ( shrinkz > nz ) shrinkz = nz;
02436 
02437         if ( nz == 1 && ny == 1 )
02438         {
02439                 return_image->set_size(nx/shrinkx);
02440                 for(int i = 0; i < nx/shrinkx; ++i)
02441                 {
02442                         float tmp = op.get_start_val();
02443                         for(int s=0; s < searchx; ++s)
02444                         {
02445                                 int idx = shrinkx*i+s;
02446                                 // Don't ask for memory beyond limits
02447                                 if ( idx > nx ) break;
02448                                 else
02449                                 {
02450                                         float val = image->get_value_at(idx);
02451                                         if ( op( val,tmp) ) tmp = val;
02452                                 }
02453                         }
02454                         return_image->set_value_at(i,tmp);
02455                 }
02456         }
02457         else if ( nz == 1 )
02458         {
02459                 int ty = ny/shrinky;
02460                 int tx = nx/shrinkx;
02461                 return_image->set_size(tx,ty);
02462                 for(int y = 0; y < ty; ++y) {
02463                         for(int x = 0; x < tx; ++x) {
02464                                 float tmp = op.get_start_val();
02465                                 for(int sy=0; sy < searchy; ++sy) {
02466                                         int yidx = shrinky*y+sy;
02467                                         if ( yidx >= ny) break;
02468                                         for(int sx=0; sx < searchx; ++sx) {
02469                                                 int xidx = shrinkx*x+sx;
02470                                                 if ( xidx >= nx) break;
02471 
02472                                                 float val = image->get_value_at(xidx,yidx);
02473                                                 if ( op( val,tmp) ) tmp = val;
02474                                         }
02475                                 }
02476                                 return_image->set_value_at(x,y,tmp);
02477                         }
02478                 }
02479         }
02480         else
02481         {
02482                 int tz = nz/shrinkz;
02483                 int ty = ny/shrinky;
02484                 int tx = nx/shrinkx;
02485 
02486                 return_image->set_size(tx,ty,tz);
02487                 for(int z = 0; z < tz; ++z) {
02488                         for(int y = 0; y < ty; ++y) {
02489                                 for(int x = 0; x < tx; ++x) {
02490                                         float tmp = op.get_start_val();
02491 
02492                                         for(int sz=0; sz < searchz; ++sz) {
02493                                                 int zidx = shrinkz*z+sz;
02494                                                 if ( zidx >= nz) break;
02495 
02496                                                 for(int sy=0; sy < searchy; ++sy) {
02497                                                         int yidx = shrinky*y+sy;
02498                                                         if ( yidx >= ny) break;
02499 
02500                                                         for(int sx=0; sx < searchx; ++sx) {
02501                                                                 int xidx = shrinkx*x+sx;
02502                                                                 if ( xidx >= nx) break;
02503                                                                 float val = image->get_value_at(xidx,yidx,zidx);
02504                                                                 if ( op( val,tmp) ) tmp = val;
02505                                                         }
02506                                                 }
02507                                         }
02508                                         return_image->set_value_at(x,y,z,tmp);
02509                                 }
02510                         }
02511                 }
02512         }
02513         return_image->update();
02514 
02515         return return_image;
02516 }
02517 
02518 template<class LogicOp>
02519 void BooleanShrinkProcessor::process_inplace(EMData * image, Dict& params)
02520 {
02521         // The basic idea of this code is to iterate through each pixel in the output image
02522         // determining its value by investigation a region of the input image
02523         if (!image) throw NullPointerException("Attempt to max shrink a null image");
02524 
02525         if (image->is_complex() ) throw ImageFormatException("Can not max shrink a complex image");
02526 
02527 
02528         int shrink = params.set_default("shrink",2);
02529         int search = params.set_default("search",2);
02530 
02531         if ( shrink < 0 ) throw InvalidValueException(shrink, "Can not shrink by a value less than 0");
02532 
02533 
02534         int nz = image->get_zsize();
02535         int ny = image->get_ysize();
02536         int nx = image->get_xsize();
02537 
02538         LogicOp op;
02539 
02540         int shrinkx = shrink;
02541         int shrinky = shrink;
02542         int shrinkz = shrink;
02543 
02544         int searchx = search;
02545         int searchy = search;
02546         int searchz = search;
02547 
02548         // Clamping the shrink values to the dimension lengths
02549         // ensures that the return image has non zero dimensions
02550         if ( shrinkx > nx ) shrinkx = nx;
02551         if ( shrinky > ny ) shrinkx = ny;
02552         if ( shrinkz > nz ) shrinkx = nz;
02553 
02554         if (nx == 1 && ny == 1 && nz == 1 ) return;
02555 
02556         if ( nz == 1 && ny == 1 )
02557         {
02558                 for(int i = 0; i < nx/shrink; ++i)
02559                 {
02560                         float tmp = op.get_start_val();
02561                         for(int s=0; s < searchx; ++s)
02562                         {
02563                                 int idx = shrinkx*i+s;
02564                                 if ( idx > nx ) break;
02565                                 else
02566                                 {
02567                                         float val = image->get_value_at(idx);
02568                                         if ( op( val,tmp) ) tmp = val;
02569                                 }
02570                         }
02571                         image->set_value_at(i,tmp);
02572                 }
02573 
02574                 image->set_size(nx/shrinkx);
02575         }
02576         else if ( nz == 1 )
02577         {
02578                 int ty = ny/shrinky;
02579                 int tx = nx/shrinkx;
02580                 for(int y = 0; y < ty; ++y) {
02581                         for(int x = 0; x < tx; ++x) {
02582                                 float tmp = op.get_start_val();
02583                                 for(int sy=0; sy < searchy; ++sy) {
02584                                         int yidx = shrinky*y+sy;
02585                                         if ( yidx >= ny) break;
02586                                         for(int sx=0; sx < searchx; ++sx) {
02587                                                 int xidx = shrinkx*x+sx;
02588                                                 if ( xidx >= nx) break;
02589 
02590                                                 float val = image->get_value_at(xidx,yidx);
02591                                                 if ( op( val,tmp) ) tmp = val;
02592                                         }
02593                                 }
02594                                 (*image)(x+tx*y) = tmp;
02595                         }
02596                 }
02597                 image->set_size(tx,ty);
02598         }
02599         else
02600         {
02601                 int tnxy = nx/shrinkx*ny/shrinky;
02602                 int tz = nz/shrinkz;
02603                 int ty = ny/shrinky;
02604                 int tx = nx/shrinkx;
02605 
02606                 for(int z = 0; z < tz; ++z) {
02607                         for(int y = 0; y < ty; ++y) {
02608                                 for(int x = 0; x < tx; ++x) {
02609                                         float tmp = op.get_start_val();
02610                                         for(int sz=0; sz < searchz; ++sz) {
02611                                                 int zidx = shrinkz*z+sz;
02612                                                 if ( zidx >= nz) break;
02613                                                 for(int sy=0; sy < searchy; ++sy) {
02614                                                         int yidx = shrinky*y+sy;
02615                                                         if ( yidx >= ny) break;
02616                                                         for(int sx=0; sx < shrinkx; ++sx) {
02617                                                                 int xidx = shrinkx*x+sx;
02618                                                                 if ( xidx >= nx) break;
02619 
02620                                                                 float val = image->get_value_at(xidx,yidx,zidx);
02621                                                                 if ( op( val,tmp) ) tmp = val;
02622                                                         }
02623                                                 }
02624                                         }
02625                                         (*image)(x+tx*y+tnxy*z) = tmp;
02626                                 }
02627                         }
02628                 }
02629                 image->set_size(tx,ty,tz);
02630         }
02631         image->update();
02632 }
02633 
02634 
02635 
02636 void GradientRemoverProcessor::process_inplace(EMData * image)
02637 {
02638         if (!image) {
02639                 LOGWARN("NULL Image");
02640                 return;
02641         }
02642 
02643         int nz = image->get_zsize();
02644         if (nz > 1) {
02645                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
02646                 throw ImageDimensionException("3D model not supported");
02647         }
02648 
02649         int nx = image->get_xsize();
02650         int ny = image->get_ysize();
02651         float *dy = new float[ny];
02652         float m = 0;
02653         float b = 0;
02654         float sum_y = 0;
02655         float *data = image->get_data();
02656 
02657         for (int i = 0; i < ny; i++) {
02658                 Util::calc_least_square_fit(nx, 0, data + i * nx, &m, &b, false);
02659                 dy[i] = b;
02660                 sum_y += m;
02661         }
02662 
02663         float mean_y = sum_y / ny;
02664         float sum_x = 0;
02665         Util::calc_least_square_fit(ny, 0, dy, &sum_x, &b, false);
02666 
02667         for (int j = 0; j < ny; j++) {
02668                 for (int i = 0; i < nx; i++) {
02669                         data[i + j * nx] -= i * sum_x + j * mean_y + b;
02670                 }
02671         }
02672 
02673         image->update();
02674 }
02675 
02676 void FlattenBackgroundProcessor::process_inplace(EMData * image)
02677 {
02678 
02679         EMData* mask = params.set_default("mask",(EMData*)0);
02680         int radius = params.set_default("radius",0);
02681 
02682         if (radius != 0 && mask != 0) throw InvalidParameterException("Error - the mask and radius parameters are mutually exclusive.");
02683 
02684         if (mask == 0 && radius == 0) throw InvalidParameterException("Error - you must specify either the mask or the radius parameter.");
02685 
02686         // If the radius isn't 0, then turn the mask into the thing we want...
02687         bool deletemask = false;
02688         if (radius != 0) {
02689                 mask = new EMData;
02690                 int n = image->get_ndim();
02691                 if (n==1){
02692                         mask->set_size(2*radius+1);
02693                 } else if (n==2) {
02694                         mask->set_size(2*radius+1,2*radius+1);
02695                 }
02696                 else /*n==3*/ {
02697                         mask->set_size(2*radius+1,2*radius+1,2*radius+1);
02698                 }
02699                 // assuming default behavior is to make a circle/sphere with using the radius of the mask
02700                 mask->process_inplace("testimage.circlesphere");
02701         }
02702 
02703         // Double check that that mask isn't too big
02704         int mnx = mask->get_xsize(); int mny = mask->get_ysize(); int mnz = mask->get_zsize();
02705         int nx = image->get_xsize(); int ny = image->get_ysize(); int nz = image->get_zsize();
02706         int nxc = nx+mnx; int nyc = ny+mny; int nzc = nz+mnz;
02707         if (nz == 1) nzc = 1; // Sanity check
02708         if (ny == 1) nyc = 1; // Sanity check
02709 
02710         if ( mnx > nx || mny > ny || mnz > nz)
02711                 throw ImageDimensionException("Can not flatten using a mask that is larger than the image.");
02712 
02713         // Get the normalization factor
02714         float normfac = 0.0;
02715         for (int i=0; i<mask->get_xsize()*mask->get_ysize()*mask->get_zsize(); ++i){
02716                 normfac += mask->get_value_at(i);
02717         }
02718         // If the sum is zero the user probably doesn't understand that determining a measure of the mean requires
02719         // strictly positive numbers. The user has specified a mask that consists entirely of zeros, or the mask
02720         // has a mean of zero.
02721         if (normfac == 0) throw InvalidParameterException("Error - the pixels in the mask sum to zero. This breaks the flattening procedure");
02722         normfac = 1.0f/normfac;
02723 
02724         // The mask can now be automatically resized to the dimensions of the image
02725 //      bool undoclip = false;
02726 
02727         Region r;
02728         if (ny == 1) r = Region((mnx-nxc)/2,nxc);
02729         else if (nz == 1) r = Region((mnx-nxc)/2, (mny-nyc)/2,nxc,nyc);
02730         else r = Region((mnx-nxc)/2, (mny-nyc)/2,(mnz-nzc)/2,nxc,nyc,nzc);
02731         mask->clip_inplace(r,0);
02732 //      undoclip = true;
02733 //      if ( mnx < nx || mny < ny || mnz < nz) {
02734 //              Region r((mnx-nx)/2, (mny-ny)/2,(mnz-nz)/2,nx,ny,nz);
02735 //              mask->clip_inplace(r);
02736 //              undoclip = true;
02737 //      }
02738 
02739         Region r2;
02740         if (ny == 1) r2 = Region((nx-nxc)/2,nxc);
02741         else if (nz == 1) r2 = Region((nx-nxc)/2, (ny-nyc)/2,nxc,nyc);
02742         else r2 = Region((nx-nxc)/2, (ny-nyc)/2,(nz-nzc)/2,nxc,nyc,nzc);
02743         image->clip_inplace(r2,image->get_edge_mean());
02744         // Finally do the convolution
02745         EMData* m = image->convolute(mask);
02746         // Normalize so that m is truly the local mean
02747         m->mult(normfac);
02748         // Before we can subtract, the mean must be phase shifted
02749         m->process_inplace("xform.phaseorigin.tocenter");
02750         // Subtract the local mean
02751 //      image->write_image("a.mrc");
02752 //      m->write_image("b.mrc");
02753         image->sub(*m); // WE'RE DONE!
02754         delete m;
02755 
02756         if (deletemask) {
02757                 delete mask;
02758         } else { // I clipped it inplace, so undo this clipping so the user gets back what the put in
02759                 Region r;
02760                 if (ny == 1) r = Region((nxc-mnx)/2,mnx);
02761                 else if (nz == 1) r = Region((nxc-mnx)/2, (nyc-mny)/2,mnx,mny);
02762                 else r = Region((nxc-mnx)/2, (nyc-mny)/2,(nzc-mnz)/2,mnx,mny,mnz);
02763                 mask->clip_inplace(r);
02764         }
02765 
02766         Region r3;
02767         if (ny == 1) r3 = Region((nxc-nx)/2,nx);
02768         else if (nz == 1) r3 = Region((nxc-nx)/2, (nyc-ny)/2,nx,ny);
02769         else r3 = Region((nxc-nx)/2, (nyc-ny)/2,(nzc-nz)/2,nx,ny,nz);
02770         image->clip_inplace(r3);
02771 //      if ( undoclip ) {
02772 //              Region r((nx-mnx)/2, (ny-mny)/2, (nz-mnz)/2,mnx,mny,mnz);
02773 //              mask->clip_inplace(r);
02774 //      }
02775 
02776 }
02777 
02778 void NonConvexProcessor::process_inplace(EMData * image) {
02779         if (!image) { LOGWARN("NULL IMAGE"); return; }
02780         //int isinten=image->get_attr_default("is_intensity",0);
02781         
02782         // 1-D
02783         if (image->get_ysize()==1) {
02784                 
02785         }
02786         // 2-D
02787         else if (image->get_zsize()==1) {
02788 //              if (!isinten) throw ImageDimensionException("Only complex intensity images currently supported by NonConvexProcessor");
02789                 int nx2=image->get_xsize()/2;
02790                 int ny2=image->get_ysize()/2;
02791                 vector<float> rdist = image->calc_radial_dist(nx2*1.5,0,1,false);               // radial distribution to make sure nonconvex values decrease radially
02792                 // Make sure rdist is decreasing (or flat)
02793                 for (int i=1; i<nx2; i++) {
02794                         if (rdist[i]>rdist[i-1]) rdist[i]=rdist[i-1];
02795                 }
02796                 
02797                 image->process_inplace("xform.fourierorigin.tocenter");
02798                 EMData* binary=image->copy();
02799                 
02800                 // First we eliminate convex points from the input image (set to zero)
02801                 for (int x=0; x<image->get_xsize(); x+=2) {
02802                         for (int y=1; y<image->get_ysize()-1; y++) {
02803                                 int r=(int)hypot((float)(x/2),(float)(y-ny2));
02804                                 float cen=(*binary)(x,y);
02805                                 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
02806                                         image->set_value_at_fast(x/2+nx2,y,0.0);        // we are turning image into a full real-space intensity image for now
02807                                         image->set_value_at_fast(nx2-x/2,ny2*2-y-1,0.0);
02808                                 }
02809                                 else {
02810                                         image->set_value_at_fast(x/2+nx2,y,cen);        // we are turning image into a full real-space intensity image for now
02811                                         image->set_value_at_fast(nx2-x/2,ny2*2-y-1,cen);        // It will contain non-zero values only for nonconvex points
02812                                 }
02813                         }
02814                 }
02815                 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
02816                 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
02817                 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
02818                 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
02819                 for (int y=0; y<ny2*2; y++) image->set_value_at_fast(0,y,0.0f);
02820                 
02821                 // Now make a binary version of the convex points
02822                 float *idat=image->get_data();
02823                 float *bdat=binary->get_data();
02824                 int nxy=(nx2*ny2*4);
02825                 for (int i=0; i<nxy; i++) {
02826                         bdat[i]=idat[i]==0?0:1.0f;              // binary version of the convex points in image
02827                 }
02828                 binary->update();
02829                 
02830                 // We now use a Gaussian filter on both images, to use Gaussian interpolation to fill in zero values
02831                 image->set_complex(false);              // so we can use a Gaussian filter on it 
02832                 binary->set_complex(false);
02833 
02834 /*              image->write_image("con.hdf",0);*/
02835                 image->set_fftpad(false);
02836                 binary->set_fftpad(false);
02837                 
02838                 // Gaussian blur of both images
02839                 image->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs",0.04f));
02840                 binary->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs",0.04f));
02841 
02842 /*              image->write_image("con.hdf",1);
02843                 binary->write_image("con.hdf",2);*/
02844                 
02845                 for (int x=0; x<image->get_xsize(); x+=2) {
02846                         for (int y=0; y<image->get_ysize(); y++) {
02847                                 float bv=binary->get_value_at(x/2+nx2,y);
02848                                 image->set_value_at_fast(x,y,image->get_value_at(x/2+nx2,y)/(bv<=0?1.0f:bv));
02849                                 image->set_value_at_fast(x+1,y,0.0);
02850                         }
02851                 }
02852                 image->set_complex(true);
02853                 image->set_fftpad(true);
02854                 image->process_inplace("xform.fourierorigin.tocorner");
02855                 delete binary;
02856         }
02857         else throw ImageDimensionException("3D maps not yet supported by NonConvexProcessor");
02858         
02859 }
02860 
02861 
02862 #include <gsl/gsl_linalg.h>
02863 void GradientPlaneRemoverProcessor::process_inplace(EMData * image)
02864 {
02865         if (!image) {
02866                 LOGWARN("NULL Image");
02867                 return;
02868         }
02869 
02870         int nz = image->get_zsize();
02871         if (nz > 1) {
02872                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
02873                 throw ImageDimensionException("3D map not supported");
02874         }
02875 
02876         int nx = image->get_xsize();
02877         int ny = image->get_ysize();
02878         float *d = image->get_data();
02879         EMData *mask = 0;
02880         float *dm = 0;
02881         if (params.has_key("mask")) {
02882                 mask = params["mask"];
02883                 if (nx!=mask->get_xsize() || ny!=mask->get_ysize()) {
02884                         LOGERR("%s Processor requires same size mask image", get_name().c_str());
02885                         throw ImageDimensionException("wrong size mask image");
02886                 }
02887                 dm = mask->get_data();
02888         }
02889         int count = 0;
02890         if (dm) {
02891                 for(int i=0; i<nx*ny; i++) {
02892                         if(dm[i]) count++;
02893                 }
02894         }
02895         else {
02896                 count = nx * ny;
02897         }
02898         if(count<3) {
02899                 LOGERR("%s Processor requires at least 3 pixels to fit a plane", get_name().c_str());
02900                 throw ImageDimensionException("too few usable pixels to fit a plane");
02901         }
02902         // Allocate the working space
02903         gsl_vector *S=gsl_vector_calloc(3);
02904         gsl_matrix *A=gsl_matrix_calloc(count,3);
02905         gsl_matrix *V=gsl_matrix_calloc(3,3);
02906 
02907         double m[3] = {0, 0, 0};
02908         int index=0;
02909         if (dm) {
02910                 for(int j=0; j<ny; j++){
02911                         for(int i=0; i<nx; i++){
02912                                 int ij=j*nx+i;
02913                                 if(dm[ij]) {
02914                                         m[0]+=i;        // x
02915                                         m[1]+=j;        // y
02916                                         m[2]+=d[ij];    // z
02917                                         /*printf("index=%d/%d\ti,j=%d,%d\tval=%g\txm,ym,zm=%g,%g,%g\n", \
02918                                                 index,count,i,j,d[ij],m[0]/(index+1),m[1]/(index+1),m[2]/(index+1));*/
02919                                         index++;
02920                                 }
02921                         }
02922                 }
02923         }
02924         else {
02925                 for(int j=0; j<ny; j++){
02926                         for(int i=0; i<nx; i++){
02927                                 int ij=j*nx+i;
02928                                         m[0]+=i;        // x
02929                                         m[1]+=j;        // y
02930                                         m[2]+=d[ij];    // z
02931                                         /*printf("index=%d/%d\ti,j=%d,%d\tval=%g\txm,ym,zm=%g,%g,%g\n", \
02932                                                 index,count,i,j,d[ij],m[0]/(index+1),m[1]/(index+1),m[2]/(index+1));*/
02933                                         index++;
02934                         }
02935                 }
02936         }
02937 
02938         for(int i=0; i<3; i++) m[i]/=count;     // compute center of the plane
02939 
02940         index=0;
02941         if (dm) {
02942                 for(int j=0; j<ny; j++){
02943                         for(int i=0; i<nx; i++){
02944                                 int ij=j*nx+i;
02945                                 if(dm[ij]) {
02946                                         //printf("index=%d/%d\ti,j=%d,%d\tval=%g\n",index,count,i,j,d[index]);
02947                                         gsl_matrix_set(A,index,0,i-m[0]);
02948                                         gsl_matrix_set(A,index,1,j-m[1]);
02949                                         gsl_matrix_set(A,index,2,d[ij]-m[2]);
02950                                         index++;
02951                                 }
02952                         }
02953                 }
02954                 mask->update();
02955         }
02956         else {
02957                 for(int j=0; j<ny; j++){
02958                         for(int i=0; i<nx; i++){
02959                                 int ij=j*nx+i;
02960                                         //printf("index=%d/%d\ti,j=%d,%d\tval=%g\n",index,count,i,j,d[index]);
02961                                         gsl_matrix_set(A,index,0,i-m[0]);
02962                                         gsl_matrix_set(A,index,1,j-m[1]);
02963                                         gsl_matrix_set(A,index,2,d[ij]-m[2]);
02964                                         index++;
02965                         }
02966                 }
02967         }
02968 
02969         // SVD decomposition and use the V vector associated with smallest singular value as the plan normal
02970         gsl_linalg_SV_decomp_jacobi(A, V, S);
02971 
02972         double n[3];
02973         for(int i=0; i<3; i++) n[i] = gsl_matrix_get(V, i, 2);
02974 
02975         #ifdef DEBUG
02976         printf("S=%g,%g,%g\n",gsl_vector_get(S,0), gsl_vector_get(S,1), gsl_vector_get(S,2));
02977         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));
02978         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));
02979         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));
02980         printf("Fitted plane: p0=%g,%g,%g\tn=%g,%g,%g\n",m[0],m[1],m[2],n[0],n[1],n[2]);
02981         #endif
02982 
02983         int changeZero = 0;
02984         if (params.has_key("changeZero")) changeZero = params["changeZero"];
02985         if (changeZero) {
02986                 for(int j=0; j<nx; j++){
02987                         for(int i=0; i<ny; i++){
02988                                 int ij = j*nx+i;
02989                                 d[ij]-=static_cast<float>(-((i-m[0])*n[0]+(j-m[1])*n[1])/n[2]+m[2]);
02990                         }
02991                 }
02992         }
02993         else {
02994                 for(int j=0; j<nx; j++){
02995                         for(int i=0; i<ny; i++){
02996                                 int ij = j*nx+i;
02997                                 if(d[ij]) d[ij]-=static_cast<float>(-((i-m[0])*n[0]+(j-m[1])*n[1])/n[2]+m[2]);
02998                         }
02999                 }
03000         }
03001         image->update();
03002         // set return plane parameters
03003         vector< float > planeParam;
03004         planeParam.resize(6);
03005         for(int i=0; i<3; i++) planeParam[i] = static_cast<float>(n[i]);
03006         for(int i=0; i<3; i++) planeParam[i+3] = static_cast<float>(m[i]);
03007         params["planeParam"]=EMObject(planeParam);
03008 }
03009 
03010 void VerticalStripeProcessor::process_inplace(EMData * image)
03011 {
03012         if (!image) {
03013                 LOGWARN("NULL Image");
03014                 return;
03015         }
03016 
03017         int nx = image->get_xsize();
03018         int ny = image->get_ysize();
03019         int nz = image->get_zsize();
03020 
03021         float *data = image->get_data();
03022         float sigma = image->get_attr("sigma");
03023 
03024         for (int k = 0; k < nz; k++) {
03025                 for (int i = 0; i < nx; i++) {
03026                         double sum = 0;
03027                         for (int j = ny / 4; j < 3 * ny / 4; j++) {
03028                                 sum += data[i + j * nx];
03029                         }
03030 
03031                         float mean = (float)sum / (ny / 2);
03032                         for (int j = 0; j < ny; j++) {
03033                                 data[i + j * nx] = (data[i + j * nx] - mean) / sigma;
03034                         }
03035                 }
03036         }
03037 
03038         image->update();
03039 }
03040 
03041 void RealToFFTProcessor::process_inplace(EMData *image)
03042 {
03043         if (!image) {
03044                 LOGWARN("NULL Image");
03045                 return;
03046         }
03047 
03048         //Note : real image only!
03049         if(image->is_complex()) {
03050                 LOGERR("%s Processor only operates on real images", get_name().c_str());
03051                 throw ImageFormatException("apply to real image only");
03052         }
03053 
03054         // Note : 2D only!
03055         int nz = image->get_zsize();
03056         if (nz > 1) {
03057                 LOGERR("%s Processor doesn't support 3D models", get_name().c_str());
03058                 throw ImageDimensionException("3D model not supported");
03059         }
03060 
03061         EMData *ff=image->do_fft();
03062         ff->ri2ap();
03063 
03064         int nx=image->get_xsize();
03065         int ny=image->get_ysize();
03066 
03067         int x,y;
03068         float norm=static_cast<float>(nx*ny);
03069 
03070         for (y=0; y<ny; y++) image->set_value_at(0,y,0);
03071 
03072         for (x=1; x<nx/2; x++) {
03073                 for (y=0; y<ny; y++) {
03074                         int y2;
03075                         if (y<ny/2) y2=y+ny/2;
03076                         else if (y==ny/2) y2=ny;
03077                         else y2=y-ny/2;
03078                         image->set_value_at(x,y,ff->get_value_at(nx-x*2,ny-y2)/norm);
03079                 }
03080         }
03081 
03082         for (x=nx/2; x<nx; x++) {
03083                 for (y=0; y<ny; y++) {
03084                         int y2;
03085                         if (y<ny/2) y2=y+ny/2;
03086                         else y2=y-ny/2;
03087                         image->set_value_at(x,y,ff->get_value_at(x*2-nx,y2)/norm);
03088                 }
03089         }
03090 
03091         image->update();
03092         if( ff )
03093         {
03094                 delete ff;
03095                 ff = 0;
03096         }
03097 }
03098 
03099 void SigmaZeroEdgeProcessor::process_inplace(EMData * image)
03100 {
03101         if (!image) {
03102                 LOGWARN("NULL Image");
03103                 return;
03104         }
03105 
03106         if (image->get_zsize() > 1) {
03107                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
03108                 throw ImageDimensionException("3D model not supported");
03109         }
03110         float *d = image->get_data();
03111         int i = 0;
03112         int j = 0;
03113 
03114         int nx = image->get_xsize();
03115         int ny = image->get_ysize();
03116 
03117         for (j = 0; j < ny; j++) {
03118                 for (i = 0; i < nx - 1; i++) {
03119                         if (d[i + j * nx] != 0) {
03120                                 break;
03121                         }
03122                 }
03123 
03124                 float v = d[i + j * nx];
03125                 while (i >= 0) {
03126                         d[i + j * nx] = v;
03127                         i--;
03128                 }
03129 
03130                 for (i = nx - 1; i > 0; i--) {
03131                         if (d[i + j * nx] != 0)
03132                                 break;
03133                 }
03134                 v = d[i + j * nx];
03135                 while (i < nx) {
03136                         d[i + j * nx] = v;
03137                         i++;
03138                 }
03139         }
03140 
03141         for (i = 0; i < nx; i++) {
03142                 for (j = 0; j < ny; j++) {
03143                         if (d[i + j * nx] != 0)
03144                                 break;
03145                 }
03146 
03147                 float v = d[i + j * nx];
03148                 while (j >= 0) {
03149                         d[i + j * nx] = v;
03150                         j--;
03151                 }
03152 
03153                 for (j = ny - 1; j > 0; j--) {
03154                         if (d[i + j * nx] != 0)
03155                                 break;
03156                 }
03157                 v = d[i + j * nx];
03158                 while (j < ny) {
03159                         d[i + j * nx] = v;
03160                         j++;
03161                 }
03162         }
03163 
03164 
03165         image->update();
03166 }
03167 
03168 
03169 
03170 void BeamstopProcessor::process_inplace(EMData * image)
03171 {
03172         if (!image) {
03173                 LOGWARN("NULL Image");
03174                 return;
03175         }
03176         if (image->get_zsize() > 1) {
03177                 LOGERR("BeamstopProcessor doesn't support 3D model");
03178                 throw ImageDimensionException("3D model not supported");
03179         }
03180 
03181         float value1 = params["value1"];
03182         float value2 = params["value2"];
03183         float value3 = params["value3"];
03184 
03185         float thr = fabs(value1);
03186         float *data = image->get_data();
03187         int cenx = (int) value2;
03188         int ceny = (int) value3;
03189 
03190         int nx = image->get_xsize();
03191         int ny = image->get_ysize();
03192 
03193         if (cenx <= 0) {
03194                 cenx = nx / 2;
03195         }
03196 
03197         if (ceny <= 0) {
03198                 ceny = ny / 2;
03199         }
03200 
03201         int mxr = (int) floor(sqrt(2.0f) * nx / 2);
03202 
03203         float *mean_values = new float[mxr];
03204         float *sigma_values = new float[mxr];
03205         double sum = 0;
03206         int count = 0;
03207         double square_sum = 0;
03208 
03209         for (int i = 0; i < mxr; i++) {
03210                 sum = 0;
03211                 count = 0;
03212                 square_sum = 0;
03213                 int nitems = 6 * i + 2;
03214 
03215                 for (int j = 0; j < nitems; j++) {
03216                         float ang = j * 2 * M_PI / nitems;
03217                         int x0 = (int) floor(cos(ang) * i + cenx);
03218                         int y0 = (int) floor(sin(ang) * i + ceny);
03219 
03220                         if (x0 < 0 || y0 < 0 || x0 >= nx || y0 >= ny) {
03221                                 continue;
03222                         }
03223 
03224                         float f = data[x0 + y0 * nx];
03225                         sum += f;
03226                         square_sum += f * f;
03227                         count++;
03228                 }
03229 
03230                 mean_values[i] = (float)sum / count;
03231                 sigma_values[i] = (float) sqrt(square_sum / count - mean_values[i] * mean_values[i]);
03232         }
03233 
03234 
03235         for (int k = 0; k < 5; k++) {
03236                 for (int i = 0; i < mxr; i++) {
03237                         sum = 0;
03238                         count = 0;
03239                         square_sum = 0;
03240                         int nitems = 6 * i + 2;
03241                         double thr1 = mean_values[i] - sigma_values[i] * thr;
03242                         double thr2 = mean_values[i] + sigma_values[i];
03243 
03244                         for (int j = 0; j < nitems; j++) {
03245                                 float ang = j * 2 * M_PI / nitems;
03246                                 int x0 = (int) floor(cos(ang) * i + cenx);
03247                                 int y0 = (int) floor(sin(ang) * i + ceny);
03248 
03249                                 if (x0 < 0 || y0 < 0 || x0 >= nx || y0 >= ny ||
03250                                         data[x0 + y0 * nx] < thr1 || data[x0 + y0 * nx] > thr2) {
03251                                         continue;
03252                                 }
03253 
03254                                 sum += data[x0 + y0 * nx];
03255                                 square_sum += data[x0 + y0 * nx] * data[x0 + y0 * nx];
03256                                 count++;
03257                         }
03258 
03259                         mean_values[i] = (float) sum / count;
03260                         sigma_values[i] = (float) sqrt(square_sum / count - mean_values[i] * mean_values[i]);
03261                 }
03262         }
03263 
03264         for (int i = 0; i < nx; i++) {
03265                 for (int j = 0; j < ny; j++) {
03266 
03267 #ifdef  _WIN32
03268                         int r = Util::round(_hypot((float) i - cenx, (float) j - ceny));
03269 #else
03270                         int r = Util::round(hypot((float) i - cenx, (float) j - ceny));
03271 #endif  //_WIN32
03272 
03273                         if (value1 < 0) {
03274                                 if (data[i + j * nx] < (mean_values[r] - sigma_values[r] * thr)) {
03275                                         data[i + j * nx] = 0;
03276                                 }
03277                                 else {
03278                                         data[i + j * nx] -= mean_values[r];
03279                                 }
03280                                 continue;
03281                         }
03282                         if (data[i + j * nx] > (mean_values[r] - sigma_values[r] * thr)) {
03283                                 continue;
03284                         }
03285                         data[i + j * nx] = mean_values[r];
03286                 }
03287         }
03288 
03289         if( mean_values )
03290         {
03291                 delete[]mean_values;
03292                 mean_values = 0;
03293         }
03294 
03295         if( sigma_values )
03296         {
03297                 delete[]sigma_values;
03298                 sigma_values = 0;
03299         }
03300 
03301         image->update();
03302 }
03303 
03304 
03305 
03306 void MeanZeroEdgeProcessor::process_inplace(EMData * image)
03307 {
03308         if (!image) {
03309                 LOGWARN("NULL Image");
03310                 return;
03311         }
03312         if (image->get_zsize() > 1) {
03313                 LOGERR("MeanZeroEdgeProcessor doesn't support 3D model");
03314                 throw ImageDimensionException("3D model not supported");
03315         }
03316 
03317         int nx = image->get_xsize();
03318         int ny = image->get_ysize();
03319         Dict dict = image->get_attr_dict();
03320         float mean_nonzero = dict.get("mean_nonzero");
03321 
03322         float *d = image->get_data();
03323         int i = 0;
03324         int j = 0;
03325 
03326         for (j = 0; j < ny; j++) {
03327                 for (i = 0; i < nx - 1; i++) {
03328                         if (d[i + j * nx] != 0) {
03329                                 break;
03330                         }
03331                 }
03332 
03333                 if (i == nx - 1) {
03334                         i = -1;
03335                 }
03336 
03337                 float v = d[i + j * nx] - mean_nonzero;
03338 
03339                 while (i >= 0) {
03340                         v *= 0.9f;
03341                         d[i + j * nx] = v + mean_nonzero;
03342                         i--;
03343                 }
03344 
03345 
03346                 for (i = nx - 1; i > 0; i--) {
03347                         if (d[i + j * nx] != 0) {
03348                                 break;
03349                         }
03350                 }
03351 
03352                 if (i == 0) {
03353                         i = nx;
03354                 }
03355 
03356                 v = d[i + j * nx] - mean_nonzero;
03357 
03358                 while (i < nx) {
03359                         v *= .9f;
03360                         d[i + j * nx] = v + mean_nonzero;
03361                         i++;
03362                 }
03363         }
03364 
03365 
03366         for (i = 0; i < nx; i++) {
03367                 for (j = 0; j < ny; j++) {
03368                         if (d[i + j * nx] != 0)
03369                                 break;
03370                 }
03371 
03372                 float v = d[i + j * nx] - mean_nonzero;
03373 
03374                 while (j >= 0) {
03375                         v *= .9f;
03376                         d[i + j * nx] = v + mean_nonzero;
03377                         j--;
03378                 }
03379 
03380                 for (j = ny - 1; j > 0; j--) {
03381                         if (d[i + j * nx] != 0)
03382                                 break;
03383                 }
03384 
03385                 v = d[i + j * nx] - mean_nonzero;
03386 
03387                 while (j < ny) {
03388                         v *= .9f;
03389                         d[i + j * nx] = v + mean_nonzero;
03390                         j++;
03391                 }
03392         }
03393 
03394         image->update();
03395 }
03396 
03397 
03398 
03399 void AverageXProcessor::process_inplace(EMData * image)
03400 {
03401         if (!image) {
03402                 LOGWARN("NULL Image");
03403                 return;
03404         }
03405 
03406         float *data = image->get_data();
03407         int nx = image->get_xsize();
03408         int ny = image->get_ysize();
03409         int nz = image->get_zsize();
03410         size_t nxy = (size_t)nx * ny;
03411 
03412         size_t idx;
03413         for (int z = 0; z < nz; z++) {
03414                 for (int x = 0; x < nx; x++) {
03415                         double sum = 0;
03416                         for (int y = 0; y < ny; y++) {
03417                                 idx = x + y * nx + z * nxy;
03418                                 sum += data[idx];
03419                         }
03420                         float mean = (float) sum / ny;
03421 
03422                         for (int y = 0; y < ny; y++) {
03423                                 idx = x + y * nx + z * nxy;
03424                                 data[idx] = mean;
03425                         }
03426                 }
03427         }
03428 
03429         image->update();
03430 }
03431 
03432 void DecayEdgeProcessor::process_inplace(EMData * image)
03433 {
03434         if (!image) {
03435                 LOGWARN("NULL Image");
03436                 return;
03437         }
03438 
03439         if (image->get_zsize() > 1) throw ImageDimensionException("3D model not supported");
03440 
03441         int nx = image->get_xsize();
03442         int ny = image->get_ysize();
03443 
03444         float *d = image->get_data();
03445         int width = params["width"];
03446 
03447         for (int i=0; i<width; i++) {
03448                 float frac=i/(float)width;
03449                 for (int j=0; j<nx; j++) {
03450                         d[j+i*nx]*=frac;
03451                         d[nx*ny-j-i*nx-1]*=frac;
03452                 }
03453                 for (int j=0; j<ny; j++) {
03454                         d[j*nx+i]*=frac;
03455                         d[nx*ny-j*nx-i-1]*=frac;
03456                 }
03457         }
03458 
03459         image->update();
03460 }
03461 
03462 void ZeroEdgeRowProcessor::process_inplace(EMData * image)
03463 {
03464         if (!image) {
03465                 LOGWARN("NULL Image");
03466                 return;
03467         }
03468 
03469         if (image->get_zsize() > 1) {
03470                 LOGERR("ZeroEdgeRowProcessor is not supported in 3D models");
03471                 throw ImageDimensionException("3D model not supported");
03472         }
03473 
03474         int nx = image->get_xsize();
03475         int ny = image->get_ysize();
03476 
03477         float *d = image->get_data();
03478         int top_nrows = params["y0"];
03479         int bottom_nrows = params["y1"];
03480 
03481         int left_ncols = params["x0"];
03482         int right_ncols = params["x1"];
03483 
03484         size_t row_size = nx * sizeof(float);
03485 
03486         memset(d, 0, top_nrows * row_size);
03487         memset(d + (ny - bottom_nrows) * nx, 0, bottom_nrows * row_size);
03488 
03489         for (int i = top_nrows; i < ny - bottom_nrows; i++) {
03490                 memset(d + i * nx, 0, left_ncols * sizeof(float));
03491                 memset(d + i * nx + nx - right_ncols, 0, right_ncols * sizeof(float));
03492         }
03493         image->update();
03494 }
03495 
03496 void ZeroEdgePlaneProcessor::process_inplace(EMData * image)
03497 {
03498         if (!image) {
03499                 LOGWARN("NULL Image");
03500                 return;
03501         }
03502 
03503         if (image->get_zsize() <= 1) {
03504                 LOGERR("ZeroEdgePlaneProcessor only support 3D models");
03505                 throw ImageDimensionException("3D model only");
03506         }
03507 
03508         int nx = image->get_xsize();
03509         int ny = image->get_ysize();
03510         int nz = image->get_zsize();
03511 
03512         float *d = image->get_data();
03513 
03514         int x0=params["x0"];
03515         int x1=params["x1"];
03516         int y0=params["y0"];
03517         int y1=params["y1"];
03518         int z0=params["z0"];
03519         int z1=params["z1"];
03520 
03521         size_t row_size = nx * sizeof(float);
03522         size_t nxy = nx * ny;
03523         size_t sec_size = nxy * sizeof(float);
03524         size_t y0row = y0 * row_size;
03525         size_t y1row = y1 * row_size;
03526         int max_y = ny-y1;
03527         size_t x0size = x0*sizeof(float);
03528         size_t x1size = x1*sizeof(float);
03529 
03530         memset(d,0,z0*sec_size);                                        // zero -z
03531         memset(d+(nxy*(nz-z1)),0,sec_size*z1);      // zero +z
03532 
03533         for (int z=z0; z<nz-z1; z++) {
03534                 memset(d+z*nxy,0,y0row);                        // zero -y
03535                 memset(d+z*nxy+(ny-y1)*nx,0,y1row);     // zero +y
03536 
03537                 int znxy = z * nxy;
03538                 int znxy2 = znxy + nx - x1;
03539 
03540                 for (int y=y0; y<max_y; y++) {
03541                         memset(d+znxy+y*nx,0,x0size);   // zero -x
03542                         memset(d+znxy2+y*nx,0,x1size);  // zero +x
03543                 }
03544         }
03545 
03546         image->update();
03547 }
03548 
03549 
03550 float NormalizeProcessor::calc_sigma(EMData * image) const
03551 {
03552         return image->get_attr("sigma");
03553 }
03554 
03555 void NormalizeProcessor::process_inplace(EMData * image)
03556 {
03557         if (!image) {
03558                 LOGWARN("cannot do normalization on NULL image");
03559                 return;
03560         }
03561 
03562         if (image->is_complex()) {
03563                 LOGWARN("cannot do normalization on complex image");
03564                 return;
03565         }
03566 
03567         float sigma = calc_sigma(image);
03568         if (sigma == 0 || !Util::goodf(&sigma)) {
03569                 LOGWARN("cannot do normalization on image with sigma = 0");
03570                 return;
03571         }
03572 
03573         float mean = calc_mean(image);
03574 
03575         size_t size = (size_t)image->get_xsize() * image->get_ysize() * image->get_zsize();
03576         float *data = image->get_data();
03577 
03578         for (size_t i = 0; i < size; ++i) {
03579                 data[i] = (data[i] - mean) / sigma;
03580         }
03581 
03582         image->update();
03583 }
03584 
03585 float NormalizeUnitProcessor::calc_sigma(EMData * image) const
03586 {
03587         if (!image) {
03588                 LOGWARN("NULL Image");
03589                 return 0;
03590         }
03591         float ret=sqrt((float)image->get_attr("square_sum"));
03592         return ret==0.0f?1.0f:ret;
03593 }
03594 
03595 float NormalizeUnitSumProcessor::calc_sigma(EMData * image) const
03596 {
03597         if (!image) {
03598                 LOGWARN("NULL Image");
03599                 return 0;
03600         }
03601         float ret=(float)image->get_attr("mean")*image->get_xsize()*image->get_ysize()*image->get_zsize();
03602         return ret==0.0f?1.0f:ret;
03603 }
03604 
03605 float NormalizeMaskProcessor::calc_sigma(EMData * image) const
03606 {
03607         if (!image) {
03608                 LOGWARN("NULL Image");
03609                 return 0;
03610         }
03611         EMData *mask = params["mask"];
03612         int no_sigma = params["no_sigma"];
03613 
03614         if(no_sigma == 0) {
03615                 return 1;
03616         }
03617         else {
03618                 if (!EMUtil::is_same_size(mask, image)) {
03619                         LOGERR("normalize.maskProcessor: mask and image must be the same size");
03620                         throw ImageDimensionException("mask and image must be the same size");
03621                 }
03622 
03623                 float *data = image->get_data();
03624                 float *mask_data = mask->get_data();
03625                 size_t size = (size_t)image->get_xsize() * image->get_ysize() * image->get_zsize();
03626                 double sum = 0;
03627                 double sq2 = 0;
03628                 size_t n_norm = 0;
03629 
03630                 for (size_t i = 0; i < size; ++i) {
03631                         if (mask_data[i] > 0.5f) {
03632                                 sum += data[i];
03633                                 sq2 += data[i]*double (data[i]);
03634                                 n_norm++;
03635                         }
03636                 }
03637                 return sqrt(static_cast<float>((sq2 - sum * sum /n_norm)/(n_norm -1))) ;
03638         }
03639 }
03640 
03641 float NormalizeMaskProcessor::calc_mean(EMData * image) const
03642 {
03643         if (!image) {
03644                 LOGWARN("NULL Image");
03645                 return 0;
03646         }
03647         EMData *mask = params["mask"];
03648 
03649         if (!EMUtil::is_same_size(mask, image)) {
03650                 LOGERR("normalize.maskProcessor: mask and image must be the same size");
03651                 throw ImageDimensionException("mask and image must be the same size");
03652         }
03653 
03654         float *data = image->get_data();
03655         float *mask_data = mask->get_data();
03656         size_t size = (size_t)image->get_xsize() * image->get_ysize() * image->get_zsize();
03657         double sum = 0;
03658         size_t n_norm = 0;
03659 
03660         for (size_t i = 0; i < size; ++i) {
03661                 if (mask_data[i] > 0.5f) {
03662                         sum += data[i];
03663                         n_norm++;
03664                 }
03665         }
03666 
03667         float mean = 0;
03668         if (n_norm == 0) {
03669                 mean = image->get_edge_mean();
03670         }
03671         else {
03672                 mean = (float) sum / n_norm;
03673         }
03674 
03675         return mean;
03676 }
03677 
03678 void NormalizeRampNormVar::process_inplace(EMData * image)
03679 {
03680         if (!image) {
03681                 LOGWARN("cannot do normalization on NULL image");
03682                 return;
03683         }
03684 
03685         if (image->is_complex()) {
03686                 LOGWARN("cannot do normalization on complex image");
03687                 return;
03688         }
03689 
03690         image->process_inplace( "filter.ramp" );
03691         int nx = image->get_xsize();
03692         EMData mask(nx,nx);
03693         mask.process_inplace("testimage.circlesphere", Dict("radius",nx/2-2,"fill",1));
03694 
03695         vector<float> rstls = Util::infomask( image, &mask, false);
03696         image->add((float)-rstls[0]);
03697         image->mult((float)1.0/rstls[1]);
03698         image->update();
03699 }
03700 
03701 void NormalizeByMassProcessor::process_inplace(EMData * image)
03702 {
03703         float mass = params.set_default("mass",-1.0f);
03704 
03705         if (mass <= 0) throw InvalidParameterException("You must specify a positive non zero mass");
03706 
03707         float thr = params.set_default("thr",(float)image->get_attr("mean")+(float)image->get_attr("sigma"));
03708 
03709         float apix = image->get_attr_default("apix_x",1.0f);
03710         apix = params.set_default("apix",apix);
03711 
03712         if (apix <= 0) throw InvalidParameterException("You must specify a positive non zero apix");
03713 
03714         float step = ((float)image->get_attr("sigma"))/2.0f;
03715 
03716         int count=0;
03717         size_t n = image->get_size();
03718         float* d = image->get_data();
03719 
03720         for (size_t i=0; i<n; ++i) {
03721                 if (d[i]>=thr) ++count;
03722         }
03723 
03724         float max = image->get_attr("maximum");
03725         float min = image->get_attr("minimum");
03726         for (int j=0; j<4; j++) {
03727                 while (thr<max && count*apix*apix*apix*.81/1000.0>mass) {
03728                         thr+=step;
03729                         count=0;
03730                         for (size_t i=0; i<n; ++i) {
03731                                 if (d[i]>=thr) ++count;
03732                         }
03733                 }
03734 
03735                 step/=4.0;
03736 
03737                 while (thr>min && count*apix*apix*apix*.81/1000.0<mass) {
03738                         thr-=step;
03739                         count=0;
03740                         for (size_t i=0; i<n; ++i) {
03741                                 if (d[i]>=thr) ++count;
03742                         }
03743                 }
03744 
03745                 step/=4.0;
03746         }
03747 
03748         image->mult((float)1.0/thr);
03749         image->update();
03750 }
03751 
03752 float NormalizeEdgeMeanProcessor::calc_mean(EMData * image) const
03753 {
03754         if (!image) {
03755                 LOGWARN("NULL Image");
03756                 return 0;
03757         }
03758         return image->get_edge_mean();
03759 }
03760 
03761 float NormalizeCircleMeanProcessor::calc_mean(EMData * image) const
03762 {
03763         if (!image) {
03764                 LOGWARN("NULL Image");
03765                 return 0;
03766         }
03767         return image->get_circle_mean();
03768 }
03769 
03770 
03771 float NormalizeMaxMinProcessor::calc_sigma(EMData * image) const
03772 {
03773         if (!image) {
03774                 LOGWARN("NULL Image");
03775                 return 0;
03776         }
03777         float maxval = image->get_attr("maximum");
03778         float minval = image->get_attr("minimum");
03779         return (maxval + minval) / 2;
03780 }
03781 
03782 float NormalizeMaxMinProcessor::calc_mean(EMData * image) const
03783 {
03784         if (!image) {
03785                 LOGWARN("NULL Image");
03786                 return 0;
03787         }
03788         float maxval = image->get_attr("maximum");
03789         float minval = image->get_attr("minimum");
03790         return (maxval - minval) / 2;
03791 }
03792 
03793 float NormalizeLREdgeMeanProcessor::calc_mean(EMData * image) const
03794 {
03795         if (!image) {
03796                 LOGWARN("NULL Image");
03797                 return 0;
03798         }
03799         double sum = 0;
03800         int nx = image->get_xsize();
03801         int ny = image->get_ysize();
03802         int nz = image->get_zsize();
03803         float *d = image->get_data();
03804         size_t nyz = ny * nz;
03805 
03806         for (size_t i = 0; i < nyz; i++) {
03807                 size_t l = i * nx;
03808                 size_t r = l + nx - 2;
03809                 sum += d[l] + d[l + 1] + d[r] + d[r + 1];
03810         }
03811         float mean = (float) sum / (4 * nyz);
03812         return mean;
03813 }
03814 
03815 void NormalizeRowProcessor::process_inplace(EMData * image)
03816 {
03817         if (!image) {
03818                 LOGWARN("NULL Image");
03819                 return;
03820         }
03821 
03822         if (image->get_zsize() > 1) {
03823                 LOGERR("row normalize only works for 2D image");
03824                 return;
03825         }
03826 
03827         float *rdata = image->get_data();
03828         int nx = image->get_xsize();
03829         int ny = image->get_ysize();
03830 
03831         for (int y = 0; y < ny; y++) {
03832                 double row_sum = 0;
03833                 for (int x = 0; x < nx; x++) {
03834                         row_sum += rdata[x + y * nx];
03835                 }
03836 
03837                 double row_mean = row_sum / nx;
03838                 if (row_mean <= 0) {
03839                         row_mean = 1;
03840                 }
03841 
03842                 for (int x = 0; x < nx; x++) {
03843                         rdata[x + y * nx] /= (float)row_mean;
03844                 }
03845         }
03846 
03847         image->update();
03848 }
03849 
03850 float NormalizeStdProcessor::calc_mean(EMData * image) const
03851 {
03852         if (!image) {
03853                 LOGWARN("NULL Image");
03854                 return 0;
03855         }
03856         return image->get_attr("mean");
03857 }
03858 
03859 
03860 
03861 void NormalizeToLeastSquareProcessor::process_inplace(EMData * image)
03862 {
03863         if (!image) {
03864                 LOGWARN("NULL Image");
03865                 return;
03866         }
03867 
03868         EMData *to = params["to"];
03869 
03870         bool ignore_zero = params.set_default("ignore_zero",true);
03871 
03872         float low_threshold = FLT_MIN;
03873         string low_thr_name = "low_threshold";
03874         if (params.has_key(low_thr_name)) {
03875                 low_threshold = params[low_thr_name];
03876         }
03877 
03878         float high_threshold = FLT_MAX;
03879         string high_thr_name = "high_threshold";
03880         if (params.has_key(high_thr_name)) {
03881                 high_threshold = params[high_thr_name];
03882         }
03883 
03884         float *rawp = image->get_data();
03885         float *refp = to->get_data();
03886 
03887         int nx = image->get_xsize();
03888         int ny = image->get_ysize();
03889         int nz = image->get_zsize();
03890         size_t size = (size_t)nx * ny * nz;
03891 
03892         float sum_x = 0;
03893         float sum_y = 0;
03894         size_t count = 0;
03895 
03896         float sum_x_mean = 0;
03897         float sum_tt = 0;
03898         float b = 0;
03899 
03900         // This is really inefficient, who coded it ?   --steve
03901         if (ignore_zero) {
03902                 for (size_t i = 0; i < size; ++i) {
03903                         if (refp[i] >= low_threshold && refp[i] <= high_threshold && refp[i] != 0.0f && rawp[i] != 0.0f) {
03904                                 count++;
03905                                 sum_x += refp[i];
03906                                 sum_y += rawp[i];
03907                         }
03908                 }
03909 
03910                 sum_x_mean = sum_x / count;
03911                 sum_tt = 0;
03912                 b = 0;
03913 
03914                 float t;
03915                 for (size_t i = 0; i < size; ++i) {
03916                         if (refp[i] >= low_threshold && refp[i] <= high_threshold && refp[i] != 0.0f && rawp[i] != 0.0f) {
03917                                 t = refp[i] - sum_x_mean;
03918                                 sum_tt += t * t;
03919                                 b += t * rawp[i];
03920                         }
03921                 }
03922         }
03923         else {
03924                         for (size_t i = 0; i < size; ++i) {
03925                         if (refp[i] >= low_threshold && refp[i] <= high_threshold) {
03926                                 count++;
03927                                 sum_x += refp[i];
03928                                 sum_y += rawp[i];
03929                         }
03930                 }
03931 
03932                 sum_x_mean = sum_x / count;
03933                 sum_tt = 0;
03934                 b = 0;
03935 
03936                 float t;
03937                 for (size_t i = 0; i < size; ++i) {
03938                         if (refp[i] >= low_threshold && refp[i] <= high_threshold) {
03939                                 t = refp[i] - sum_x_mean;
03940                                 sum_tt += t * t;
03941                                 b += t * rawp[i];
03942                         }
03943                 }
03944         }
03945 
03946         b /= sum_tt;
03947 
03948         float a = (sum_y - sum_x * b) / count;
03949         float scale = 1 / b;
03950         float shift = -a / b;
03951 
03952         for (size_t i = 0; i < size; ++i) {
03953                 rawp[i] = (rawp[i] - a) / b;
03954         }
03955 
03956         image->update();
03957 
03958         params["scale"] = scale;
03959         params["shift"] = shift;
03960 
03961         image->set_attr("norm_mult",scale);
03962         image->set_attr("norm_add",shift);
03963 
03964 }
03965 
03966 void BinarizeFourierProcessor::process_inplace(EMData* image) {
03967         ENTERFUNC;
03968         if (!image->is_complex()) throw ImageFormatException("Fourier binary thresholding processor only works for complex images");
03969 
03970         float threshold = params.set_default("value",0.0f);
03971         image->ri2ap(); //  works for cuda
03972 
03973         float* d = image->get_data();
03974         for( size_t i = 0; i < image->get_size()/2; ++i, d+=2) {
03975                 if ( *d < threshold ) {
03976                         *d = 0;
03977                         *(d+1) = 0;
03978                 } 
03979         }
03980         image->ap2ri();
03981         image->set_ri(true); // So it can be used for fourier multiplaction, for example
03982         image->update();
03983         EXITFUNC;
03984 } 
03985   
03986 void BilateralProcessor::process_inplace(EMData * image)
03987 {
03988         if (!image) {
03989                 LOGWARN("NULL Image");
03990                 return;
03991         }
03992 
03993         float distance_sigma = params["distance_sigma"];
03994         float value_sigma = params["value_sigma"];
03995         int max_iter = params["niter"];
03996         int half_width = params["half_width"];
03997 
03998         if (half_width < distance_sigma) {
03999                 LOGWARN("localwidth(=%d) should be larger than distance_sigma=(%f)\n",
04000                                                         half_width, distance_sigma);
04001         }
04002 
04003         distance_sigma *= distance_sigma;
04004 
04005         float image_sigma = image->get_attr("sigma");
04006         if (image_sigma > value_sigma) {
04007                 LOGWARN("image sigma(=%f) should be smaller than value_sigma=(%f)\n",
04008                                                         image_sigma, value_sigma);
04009         }
04010         value_sigma *= value_sigma;
04011 
04012         int nx = image->get_xsize();
04013         int ny = image->get_ysize();
04014         int nz = image->get_zsize();
04015 
04016         if(nz==1) {     //for 2D image
04017                 int width=nx, height=ny;
04018 
04019                 int i,j,m,n;
04020 
04021                 float tempfloat1,tempfloat2,tempfloat3;
04022                 int   index1,index2,index;
04023                 int   Iter;
04024                 int   tempint1,tempint3;
04025 
04026                 tempint1=width;
04027                 tempint3=width+2*half_width;
04028 
04029                 float* mask=(float*)calloc((2*half_width+1)*(2*half_width+1),sizeof(float));
04030                 float* OrgImg=(float*)calloc((2*half_width+width)*(2*half_width+height),sizeof(float));
04031                 float* NewImg=image->get_data();
04032 
04033                 for(m=-(half_width);m<=half_width;m++)
04034                         for(n=-(half_width);n<=half_width;n++) {
04035                    index=(m+half_width)*(2*half_width+1)+(n+half_width);
04036                    mask[index]=exp((float)(-(m*m+n*n)/distance_sigma/2.0));
04037                 }
04038 
04039                 //printf("entering bilateral filtering process \n");
04040 
04041                 Iter=0;
04042                 while(Iter<max_iter) {
04043                         for(i=0;i<height;i++)
04044                         for(j=0;j<width;j++) {
04045                                 index1=(i+half_width)*tempint3+(j+half_width);
04046                                         index2=i*tempint1+j;
04047                                 OrgImg[index1]=NewImg[index2];
04048                         }
04049 
04050                         // Mirror Padding
04051                         for(i=0;i<height;i++){
04052                                 for(j=0;j<half_width;j++) OrgImg[(i+half_width)*tempint3+(j)]=OrgImg[(i+half_width)*tempint3+(2*half_width-j)];
04053                                 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)];
04054                         }
04055                         for(i=0;i<half_width;i++){
04056                                 for(j=0;j<(width+2*half_width);j++) OrgImg[i*tempint3+j]=OrgImg[(2*half_width-i)*tempint3+j];
04057                                 for(j=0;j<(width+2*half_width);j++) OrgImg[(i+height+half_width)*tempint3+j]=OrgImg[(height+half_width-2-i)*tempint3+j];
04058                         }
04059 
04060                         //printf("finish mirror padding process \n");
04061                         //now mirror padding have been done
04062 
04063                         for(i=0;i<height;i++){
04064                                 //printf("now processing the %d th row \n",i);
04065                                 for(j=0;j<width;j++){
04066                                         tempfloat1=0.0; tempfloat2=0.0;
04067                                         for(m=-(half_width);m<=half_width;m++)
04068                                                 for(n=-(half_width);n<=half_width;n++){
04069                                                         index =(m+half_width)*(2*half_width+1)+(n+half_width);
04070                                                         index1=(i+half_width)*tempint3+(j+half_width);
04071                                                         index2=(i+half_width+m)*tempint3+(j+half_width+n);
04072                                                         tempfloat3=(OrgImg[index1]-OrgImg[index2])*(OrgImg[index1]-OrgImg[index2]);
04073 
04074                                                         tempfloat3=mask[index]*(1.0f/(1+tempfloat3/value_sigma));       // Lorentz kernel
04075                                                         //tempfloat3=mask[index]*exp(tempfloat3/Sigma2/(-2.0)); // Guassian kernel
04076                                                         tempfloat1+=tempfloat3;
04077 
04078                                                         tempfloat2+=tempfloat3*OrgImg[(i+half_width+m)*tempint3+(j+half_width+n)];
04079                                         }
04080                                         NewImg[i*width+j]=tempfloat2/tempfloat1;
04081                                 }
04082                         }
04083                         Iter++;
04084             }
04085 
04086             //printf("have finished %d  th iteration\n ",Iter);
04087 //              doneData();
04088                 free(mask);
04089                 free(OrgImg);
04090                 // end of BilaFilter routine
04091 
04092         }
04093         else {  //3D case
04094                 int width = nx;
04095                 int height = ny;
04096                 int slicenum = nz;
04097 
04098                 int slice_size = width * height;
04099                 int new_width = width + 2 * half_width;
04100                 int new_slice_size = (width + 2 * half_width) * (height + 2 * half_width);
04101 
04102                 int width1 = 2 * half_width + 1;
04103                 int mask_size = width1 * width1;
04104                 int old_img_size = (2 * half_width + width) * (2 * half_width + height);
04105 
04106                 int zstart = -half_width;
04107                 int zend = -half_width;
04108                 int is_3d = 0;
04109                 if (nz > 1) {
04110                         mask_size *= width1;
04111                         old_img_size *= (2 * half_width + slicenum);
04112                         zend = half_width;
04113                         is_3d = 1;
04114                 }
04115 
04116                 float *mask = (float *) calloc(mask_size, sizeof(float));
04117                 float *old_img = (float *) calloc(old_img_size, sizeof(float));
04118 
04119                 float *new_img = image->get_data();
04120 
04121                 for (int p = zstart; p <= zend; p++) {
04122                         int cur_p = (p + half_width) * (2 * half_width + 1) * (2 * half_width + 1);
04123 
04124                         for (int m = -half_width; m <= half_width; m++) {
04125                                 int cur_m = (m + half_width) * (2 * half_width + 1) + half_width;
04126 
04127                                 for (int n = -half_width; n <= half_width; n++) {
04128                                         int l = cur_p + cur_m + n;
04129                                         mask[l] = exp((float) (-(m * m + n * n + p * p * is_3d) / distance_sigma / 2.0f));
04130                                 }
04131                         }
04132                 }
04133 
04134                 int iter = 0;
04135                 while (iter < max_iter) {
04136                         for (int k = 0; k < slicenum; k++) {
04137                                 size_t cur_k1 = (size_t)(k + half_width) * new_slice_size * is_3d;
04138                                 int cur_k2 = k * slice_size;
04139 
04140                                 for (int i = 0; i < height; i++) {
04141                                         int cur_i1 = (i + half_width) * new_width;
04142                                         int cur_i2 = i * width;
04143 
04144                                         for (int j = 0; j < width; j++) {
04145                                                 size_t k1 = cur_k1 + cur_i1 + (j + half_width);
04146                                                 int k2 = cur_k2 + cur_i2 + j;
04147                                                 old_img[k1] = new_img[k2];
04148                                         }
04149                                 }
04150                         }
04151 
04152                         for (int k = 0; k < slicenum; k++) {
04153                                 size_t cur_k = (k + half_width) * new_slice_size * is_3d;
04154 
04155                                 for (int i = 0; i < height; i++) {
04156                                         int cur_i = (i + half_width) * new_width;
04157 
04158                                         for (int j = 0; j < half_width; j++) {
04159                                                 size_t k1 = cur_k + cur_i + j;
04160                                                 size_t k2 = cur_k + cur_i + (2 * half_width - j);
04161                                                 old_img[k1] = old_img[k2];
04162                                         }
04163 
04164                                         for (int j = 0; j < half_width; j++) {
04165                                                 size_t k1 = cur_k + cur_i + (width + half_width + j);
04166                                                 size_t k2 = cur_k + cur_i + (width + half_width - j - 2);
04167                                                 old_img[k1] = old_img[k2];
04168                                         }
04169                                 }
04170 
04171 
04172                                 for (int i = 0; i < half_width; i++) {
04173                                         int i2 = i * new_width;
04174                                         int i3 = (2 * half_width - i) * new_width;
04175                                         for (int j = 0; j < (width + 2 * half_width); j++) {
04176                                                 size_t k1 = cur_k + i2 + j;
04177                                                 size_t k2 = cur_k + i3 + j;
04178                                                 old_img[k1] = old_img[k2];
04179                                         }
04180 
04181                                         i2 = (height + half_width + i) * new_width;
04182                                         i3 = (height + half_width - 2 - i) * new_width;
04183                                         for (int j = 0; j < (width + 2 * half_width); j++) {
04184                                                 size_t k1 = cur_k + i2 + j;
04185                                                 size_t k2 = cur_k + i3 + j;
04186                                                 old_img[k1] = old_img[k2];
04187                                         }
04188                                 }
04189                         }
04190 
04191                         size_t idx;
04192                         for (int k = 0; k < slicenum; k++) {
04193                                 size_t cur_k = (k + half_width) * new_slice_size;
04194 
04195                                 for (int i = 0; i < height; i++) {
04196                                         int cur_i = (i + half_width) * new_width;
04197 
04198                                         for (int j = 0; j < width; j++) {
04199                                                 float f1 = 0;
04200                                                 float f2 = 0;
04201                                                 size_t k1 = cur_k + cur_i + (j + half_width);
04202 
04203                                                 for (int p = zstart; p <= zend; p++) {
04204                                                         size_t cur_p1 = (p + half_width) * (2 * half_width + 1) * (2 * half_width + 1);
04205                                                         size_t cur_p2 = (k + half_width + p) * new_slice_size;
04206 
04207                                                         for (int m = -half_width; m <= half_width; m++) {
04208                                                                 size_t cur_m1 = (m + half_width) * (2 * half_width + 1);
04209                                                                 size_t cur_m2 = cur_p2 + cur_i + m * new_width + j + half_width;
04210 
04211                                                                 for (int n = -half_width; n <= half_width; n++) {
04212                                                                         size_t k = cur_p1 + cur_m1 + (n + half_width);
04213                                                                         size_t k2 = cur_m2 + n;
04214                                                                         float f3 = Util::square(old_img[k1] - old_img[k2]);
04215 
04216                                                                         f3 = mask[k] * (1.0f / (1 + f3 / value_sigma));
04217                                                                         f1 += f3;
04218                                                                         size_t l1 = cur_m2 + n;
04219                                                                         f2 += f3 * old_img[l1];
04220                                                                 }
04221 
04222                                                                 idx = (size_t)k * height * width + i * width + j;
04223                                                                 new_img[idx] = f2 / f1;
04224                                                         }
04225                                                 }
04226                                         }
04227                                 }
04228                         }
04229                         iter++;
04230                 }
04231                 if( mask ) {
04232                         free(mask);
04233                         mask = 0;
04234                 }
04235 
04236                 if( old_img ) {
04237                         free(old_img);
04238                         old_img = 0;
04239                 }
04240         }
04241 
04242         image->update();
04243 }
04244 
04245 void RotationalAverageProcessor::process_inplace(EMData * image)
04246 {
04247         if (!image || image->is_complex()) {
04248                 LOGWARN("only works on real image. do nothing.");
04249                 return;
04250         }
04251 
04252         if (image->get_ndim() <= 0 || image->get_ndim() > 3)    throw ImageDimensionException("radial average processor only works for 2D and 3D images");
04253 
04254         float *rdata = image->get_data();
04255         int nx = image->get_xsize();
04256         int ny = image->get_ysize();
04257 
04258         vector < float >dist = image->calc_radial_dist(nx / 2, 0, 1,0);
04259 
04260         float midx = (float)((int)nx/2);
04261         float midy = (float)((int)ny/2);
04262 
04263         size_t c = 0;
04264         if (image->get_ndim() == 2) {
04265                 for (int y = 0; y < ny; y++) {
04266                         for (int x = 0; x < nx; x++, c++) {
04267         #ifdef  _WIN32
04268                                 float r = (float) _hypot(x - midx, y - midy);
04269         #else
04270                                 float r = (float) hypot(x - midx, y - midy);
04271         #endif  //_WIN32
04272 
04273 
04274                                 int i = (int) floor(r);
04275                                 r -= i;
04276                                 if (i >= 0 && i < nx / 2 - 1) {
04277                                         rdata[c] = dist[i] * (1.0f - r) + dist[i + 1] * r;
04278                                 }
04279                                 else if (i < 0) {
04280                                         rdata[c] = dist[0];
04281                                 }
04282                                 else {
04283                                         rdata[c] = 0;
04284                                 }
04285                         }
04286                 }
04287         }
04288         else if (image->get_ndim() == 3) {
04289                 int nz = image->get_zsize();
04290                 float midz = (float)((int)nz/2);
04291                 float r;
04292                 int i;
04293                 for (int z = 0; z < nz; ++z) {
04294                         for (int y = 0; y < ny; ++y) {
04295                                 for (int x = 0; x < nx; ++x, ++c) {
04296 
04297                                         r = (float) Util::hypot3(x - midx, y - midy, z - midz);
04298 
04299                                         i = Util::fast_floor(r);
04300                                         r -= i;
04301                                         if (i >= 0 && i < nx / 2 - 1) {
04302                                                 rdata[c] = dist[i] * (1.0f - r) + dist[i + 1] * r;
04303                                         }
04304                                         else if (i < 0) {
04305                                                 rdata[c] = dist[0];
04306                                         }
04307                                         else {
04308                                                 rdata[c] = 0;
04309                                         }
04310                                 }
04311                         }
04312                 }
04313         }
04314 
04315         image->update();
04316 }
04317 
04318 
04319 
04320 void RotationalSubstractProcessor::process_inplace(EMData * image)
04321 {
04322         if (!image || image->is_complex()) {
04323                 LOGWARN("only works on real image. do nothing.");
04324                 return;
04325         }
04326 
04327         if (image->get_ndim() != 2) throw ImageDimensionException("This processor works only for 2D images");
04328 
04329         float *rdata = image->get_data();
04330         int nx = image->get_xsize();
04331         int ny = image->get_ysize();
04332 
04333         vector < float >dist = image->calc_radial_dist(nx / 2, 0, 1,0);
04334 
04335         int c = 0;
04336         for (int y = 0; y < ny; y++) {
04337                 for (int x = 0; x < nx; x++, c++) {
04338 #ifdef  _WIN32
04339                         float r = (float) _hypot(x - nx / 2, y - ny / 2);
04340 #else
04341                         float r = (float) hypot(x - nx / 2, y - ny / 2);
04342 #endif
04343                         int i = (int) floor(r);
04344                         r -= i;
04345                         if (i >= 0 && i < nx / 2 - 1) {
04346                                 rdata[c] -= dist[i] * (1.0f - r) + dist[i + 1] * r;
04347                         }
04348                         else {
04349                                 rdata[c] = 0;
04350                         }
04351                 }
04352         }
04353 
04354         image->update();
04355 }
04356 
04357 
04358 EMData* TransposeProcessor::process(const EMData* const image) {
04359         if (image->get_ndim() != 2) throw UnexpectedBehaviorException("Transpose processor only works with 2D images");
04360         if (image->is_complex()) throw UnexpectedBehaviorException("Transpose processor only works with real images");
04361 
04362         EMData* ret = new EMData(image->get_ysize(),image->get_xsize(),1); // transpose dimensions
04363 
04364         for(int j = 0; j< image->get_ysize();++j) {
04365                 for(int i = 0; i< image->get_xsize();++i) {
04366                         ret->set_value_at(j,i,image->get_value_at(i,j));
04367                 }
04368         }
04369 
04370         return ret;
04371 
04372 }
04373 
04374 void TransposeProcessor::process_inplace(EMData* image) {
04375         if (image->get_ndim() != 2) throw UnexpectedBehaviorException("Transpose processor only works with 2D images");
04376         if (image->is_complex()) throw UnexpectedBehaviorException("Transpose processor only works with real images");
04377 
04378         float* data = (float*)malloc(image->get_ysize()*image->get_xsize()*sizeof(float));
04379 
04380         int nx = image->get_ysize(); // note tranpose
04381         for(int j = 0; j< image->get_ysize();++j) {
04382                 for(int i = 0; i< image->get_xsize();++i) {
04383                         data[i*nx+j] = image->get_value_at(i,j);
04384                 }
04385         }
04386 
04387         image->set_data(data,image->get_ysize(),image->get_xsize(),1);
04388 
04389 }
04390 
04391 void FlipProcessor::process_inplace(EMData * image)
04392 {
04393         ENTERFUNC;
04394         if (!image) {
04395                 LOGWARN("NULL Image");
04396                 return;
04397         }
04398         string axis = (const char*)params["axis"];
04399         
04400 #ifdef EMAN2_USING_CUDA
04401         if (EMData::usecuda == 1 && image->getcudarwdata()) {
04402                 //cout << "flip processor" << endl;
04403                 float array[12] = {1.0, 0.0, 0.0, 0.0,
04404                                                    0.0, 1.0, 0.0, 0.0,
04405                                                    0.0, 0.0, 1.0, 0.0};
04406                 if (axis == "x" || axis == "X") {               // horizontal flip
04407                         array[0] = -1.0;
04408                 }else if (axis == "y" || axis == "Y") {         // vertical flip
04409                         array[5] = -1.0;
04410                 }
04411                 else if (axis == "z" || axis == "Z") {          // vertical flip
04412                         array[10] = -1.0;
04413                 }
04414                 Transform t(array);
04415                 Dict params("transform",(Transform*)&t);
04416                 image->process_inplace("xform",params);
04417 
04418                 EXITFUNC;
04419                 return;
04420         }
04421 #endif
04422 
04423 
04424         float *d = image->get_data();
04425         int nx = image->get_xsize();
04426         int ny = image->get_ysize();
04427         int nz = image->get_zsize();
04428 
04429         size_t nxy = nx * ny;
04430 
04431 
04432         // Note in all cases the origin is nx/2, ny/2 and nz/2
04433         // This means when flipping even sized dimensions that some pixels are redundant.
04434         // Here redundant pixels are set to zero, however, should this change to something
04435         // like the mean.
04436         if (axis == "x" || axis == "X") {               // Horizontal flip
04437                 int offset = (nx%2 == 0);
04438                 size_t idx1, idx2;
04439                 for(int z = 0; z < nz; ++z) {
04440                         for(int y = 0; y < ny; ++y) {
04441                                 if (offset != 0 ) {
04442                                         idx1 = z*nxy + y*nx;
04443                                         d[idx1] = 0; // Here's where you'd make it the mean
04444                                 }
04445                                 for(int x = offset; x < nx / 2; ++x) {
04446                                         idx1 = z*nxy + y*nx + x;
04447                                         idx2 = z*nxy + y*nx + (nx-x-1+offset);
04448                                         std::swap(d[idx1], d[idx2]);
04449                                 }
04450 
04451                         }
04452                 }
04453         }
04454 
04455         else if (axis == "y" || axis == "Y") {          // vertical flip
04456                 int offset = (ny%2 == 0);
04457                 for(int z=0; z<nz; ++z) {
04458                         if (offset != 0) {
04459                                 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)
04460                         }
04461                         for(int y=offset; y<ny/2; ++y) {
04462                                 for(int x=0; x<nx; ++x) {
04463                                         std::swap(d[(size_t)z*nxy + y*nx +x], d[(size_t)z*nxy + (ny -y -1+offset)*nx +x]);
04464                                 }
04465                         }
04466                 }
04467         }
04468         else if (axis == "z" || axis == "Z") {          //z axis flip
04469                 int offset = (nz%2 == 0);
04470                 if (offset != 0) {
04471                         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)
04472                 }
04473                 size_t idx1, idx2;
04474                 for(int z=offset; z<nz/2; ++z) {
04475                         for(int y=0; y<ny; ++y) {
04476                                 for(int x=0; x<nx; ++x) {
04477                                         idx1 = (size_t)z*nxy + y*nx + x;
04478                                         idx2 = (size_t)(nz-z-1+offset)*nxy + y*nx + x;
04479                                         std::swap(d[idx1], d[idx2]);
04480                                 }
04481                         }
04482                 }
04483         }
04484 
04485         image->update();
04486         EXITFUNC;
04487 }
04488 
04489 void AddNoiseProcessor::process_inplace(EMData * image)
04490 {
04491         if (!image) {
04492                 LOGWARN("NULL Image");
04493                 return;
04494         }
04495 
04496         Randnum * randnum = Randnum::Instance();
04497         if(params.has_key("seed")) {
04498                 randnum->set_seed((int)params["seed"]);
04499         }
04500 
04501         float addnoise = params["noise"];
04502         addnoise *= get_sigma(image);
04503         float *dat = image->get_data();
04504 
04505         for (size_t j = 0; j < image->get_size(); ++j) {
04506                 dat[j] += randnum->get_gauss_rand(addnoise, addnoise / 2);
04507         }
04508 
04509         image->update();
04510 }
04511 
04512 float AddSigmaNoiseProcessor::get_sigma(EMData * image)
04513 {
04514         if (!image) {
04515                 LOGWARN("NULL Image");
04516                 return 0;
04517         }
04518         return image->get_attr("sigma");
04519 }
04520 
04521 void FourierToCornerProcessor::process_inplace(EMData * image)
04522 {
04523         if ( !image->is_complex() ) throw ImageFormatException("Can not Fourier origin shift an image that is not complex");
04524 
04525         int nx=image->get_xsize();
04526         int ny=image->get_ysize();
04527         int nz=image->get_zsize();
04528 
04529         int nxy = nx*ny;
04530 
04531         if ( ny == 1 && nz == 1 ){
04532                 cout << "Warning- attempted     Fourier origin shift a 1D image - no action taken" << endl;
04533                 return;
04534         }
04535         int yodd = (ny%2==1);
04536         int zodd = (nz%2==1);
04537 
04538         float* rdata = image->get_data();
04539 
04540         float tmp[2];
04541         float* p1;
04542         float* p2;
04543 
04544         if (yodd){
04545                 // Swap the middle slice (with respect to the y direction) with the bottom slice
04546                 // shifting all slices above the middles slice upwards by one pixel, stopping
04547                 // at the middle slice, not if nz = 1 we are not talking about slices, we are
04548                 // talking about rows
04549                 float prev[2];
04550                 size_t idx;
04551                 for( int s = 0; s < nz; s++ ) {
04552                         for( int c =0; c < nx; c += 2 ) {
04553                                 idx = (size_t)s*nxy+ny/2*nx+c;
04554                                 prev[0] = rdata[idx];
04555                                 prev[1] = rdata[idx+1];
04556                                 for( int r = 0; r <= ny/2; ++r ) {
04557                                         idx = (size_t)s*nxy+r*nx+c;
04558                                         float* p1 = &rdata[idx];
04559                                         tmp[0] = p1[0];
04560                                         tmp[1] = p1[1];
04561 
04562                                         p1[0] = prev[0];
04563                                         p1[1] = prev[1];
04564 
04565                                         prev[0] = tmp[0];
04566                                         prev[1] = tmp[1];
04567                                 }
04568                         }
04569                 }
04570         }
04571 
04572         // Shift slices (3D) or rows (2D) correctly in the y direction
04573         size_t idx1, idx2;
04574         for( int s = 0; s < nz; ++s ) {
04575                 for( int r = 0 + yodd; r < ny/2+yodd; ++r ) {
04576                         for( int c =0; c < nx; c += 2 ) {
04577                                 idx1 = (size_t)s*nxy+r*nx+c;
04578                                 idx2 = (size_t)s*nxy+(r+ny/2)*nx+c;
04579                                 p1 = &rdata[idx1];
04580                                 p2 = &rdata[idx2];
04581 
04582                                 tmp[0] = p1[0];
04583                                 tmp[1] = p1[1];
04584 
04585                                 p1[0] = p2[0];
04586                                 p1[1] = p2[1];
04587 
04588                                 p2[0] = tmp[0];
04589                                 p2[1] = tmp[1];
04590                         }
04591                 }
04592         }
04593 
04594         if ( nz != 1 )
04595         {
04596 
04597                 if (zodd){
04598                         // Swap the middle slice (with respect to the z direction) and the front slice
04599                         // shifting all behind the front slice towards the middle a distance of 1 voxel,
04600                         // stopping at the middle slice.
04601                         float prev[2];
04602                         size_t idx;
04603                         for( int r = 0; r < ny; ++r ) {
04604                                 for( int c =0; c < nx; c += 2 ) {
04605                                         idx = (size_t)nz/2*nxy+r*nx+c;
04606                                         prev[0] = rdata[idx];
04607                                         prev[1] = rdata[idx+1];
04608                                         for( int s = 0; s <= nz/2; ++s ) {
04609                                                 idx = (size_t)s*nxy+r*nx+c;
04610                                                 float* p1 = &rdata[idx];
04611                                                 tmp[0] = p1[0];
04612                                                 tmp[1] = p1[1];
04613 
04614                                                 p1[0] = prev[0];
04615                                                 p1[1] = prev[1];
04616 
04617                                                 prev[0] = tmp[0];
04618                                                 prev[1] = tmp[1];
04619                                         }
04620                                 }
04621                         }
04622                 }
04623 
04624                 // Shift slices correctly in the z direction
04625                 size_t idx1, idx2;
04626                 for( int s = 0+zodd; s < nz/2 + zodd; ++s ) {
04627                         for( int r = 0; r < ny; ++r ) {
04628                                 for( int c =0; c < nx; c += 2 ) {
04629                                         idx1 = (size_t)s*nxy+r*nx+c;
04630                                         idx2 = (size_t)(s+nz/2)*nxy+r*nx+c;
04631                                         p1 = &rdata[idx1];
04632                                         p2 = &rdata[idx2];
04633 
04634                                         tmp[0] = p1[0];
04635                                         tmp[1] = p1[1];
04636 
04637                                         p1[0] = p2[0];
04638                                         p1[1] = p2[1];
04639 
04640                                         p2[0] = tmp[0];
04641                                         p2[1] = tmp[1];
04642                                 }
04643                         }
04644                 }
04645         }
04646         image->set_shuffled(false);
04647 }
04648 
04649 void FourierToCenterProcessor::process_inplace(EMData * image)
04650 {
04651 //      if ( !image->is_complex() ) throw ImageFormatException("Can not Fourier origin shift an image that is not complex");
04652 
04653         int nx=image->get_xsize();
04654         int ny=image->get_ysize();
04655         int nz=image->get_zsize();
04656 
04657         int nxy = nx*ny;
04658 
04659         if ( ny == 1 && nz == 1 ){
04660                 cout << "Warning- attempted     Fourier origin shift a 1D image - no action taken" << endl;
04661                 return;
04662         }
04663 
04664         int yodd = (ny%2==1);
04665         int zodd = (nz%2==1);
04666 
04667         float* rdata = image->get_data();
04668 
04669         float tmp[2];
04670         float* p1;
04671         float* p2;
04672 
04673         // This will tackle the 'normalization' images which come out of the Fourier reconstructor.
04674         // ie- real-space 1/2 FFt images centered on the corner
04675         if ( !image->is_complex() ) {
04676                 if (nz!=1 && !yodd && !zodd) {
04677                         for (int x=0; x<nx; x++) {
04678                                 for (int y=0; y<ny; y++) {
04679                                         for (int z=0; z<nz/2; z++) {
04680                                                 int y2=(y+ny/2)%ny;
04681                                                 int z2=(z+nz/2)%nz;             // %nz should be redundant here
04682                                                 size_t i=x+y*nx+(size_t)z*nxy;
04683                                                 size_t i2=x+y2*nx+(size_t)z2*nxy;
04684                                                 float swp=rdata[i];
04685                                                 rdata[i]=rdata[i2];
04686                                                 rdata[i2]=swp;
04687                                         }
04688                                 }
04689                         }
04690 
04691                         return;
04692                 }
04693                 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");
04694         }
04695 
04696         if (yodd){
04697                 // In 3D this is swapping the bottom slice (with respect to the y direction) and the middle slice,
04698                 // shifting all slices below the middle slice down one. In 2D it is equivalent, but in terms of rows.
04699                 float prev[2];
04700                 size_t idx;
04701                 for( int s = 0; s < nz; s++ ) {
04702                         for( int c =0; c < nx; c += 2 ) {
04703                                 idx = (size_t)s*nxy+c;
04704                                 prev[0] = rdata[idx];
04705                                 prev[1] = rdata[idx+1];
04706                                 for( int r = ny/2; r >= 0; --r ) {
04707                                         idx = (size_t)s*nxy+r*nx+c;
04708                                         float* p1 = &rdata[idx];
04709                                         tmp[0] = p1[0];
04710                                         tmp[1] = p1[1];
04711 
04712                                         p1[0] = prev[0];
04713                                         p1[1] = prev[1];
04714 
04715                                         prev[0] = tmp[0];
04716                                         prev[1] = tmp[1];
04717                                 }
04718                         }
04719                 }
04720         }
04721 
04722         // 3D - Shift slices correctly in the y direction, 2D - shift rows
04723         size_t idx1, idx2;
04724         for( int s = 0; s < nz; ++s ) {
04725                 for( int r = 0; r < ny/2; ++r ) {
04726                         for( int c =0; c < nx; c += 2 ) {
04727                                 idx1 = (size_t)s*nxy+r*nx+c;
04728                                 idx2 = (size_t)s*nxy+(r+ny/2+yodd)*nx+c;
04729                                 p1 = &rdata[idx1];
04730                                 p2 = &rdata[idx2];
04731 
04732                                 tmp[0] = p1[0];
04733                                 tmp[1] = p1[1];
04734 
04735                                 p1[0] = p2[0];
04736                                 p1[1] = p2[1];
04737 
04738                                 p2[0] = tmp[0];
04739                                 p2[1] = tmp[1];
04740                         }
04741                 }
04742         }
04743 
04744         if ( nz != 1 )  {
04745                 if (zodd){
04746                         // Swap the front slice (with respect to the z direction) and the middle slice
04747                         // shifting all slices behind the middles slice towards the front slice 1 voxel.
04748                         float prev[2];
04749                         size_t idx;
04750                         for( int r = 0; r < ny; ++r ) {
04751                                 for( int c =0; c < nx; c += 2 ) {
04752                                         prev[0] = rdata[r*nx+c];
04753                                         prev[1] = rdata[r*nx+c+1];
04754                                         for( int s = nz/2; s >= 0; --s ) {
04755                                                 idx = (size_t)s*nxy+r*nx+c;
04756                                                 float* p1 = &rdata[idx];
04757                                                 tmp[0] = p1[0];
04758                                                 tmp[1] = p1[1];
04759 
04760                                                 p1[0] = prev[0];
04761                                                 p1[1] = prev[1];
04762 
04763                                                 prev[0] = tmp[0];
04764                                                 prev[1] = tmp[1];
04765                                         }
04766                                 }
04767                         }
04768                 }
04769 
04770                 // Shift slices correctly in the y direction
04771                 size_t idx1, idx2;
04772                 for( int s = 0; s < nz/2; ++s ) {
04773                         for( int r = 0; r < ny; ++r ) {
04774                                 for( int c =0; c < nx; c += 2 ) {
04775                                         idx1 = (size_t)s*nxy+r*nx+c;
04776                                         idx2 = (size_t)(s+nz/2+zodd)*nxy+r*nx+c;
04777                                         p1 = &rdata[idx1];
04778                                         p2 = &rdata[idx2];
04779 
04780                                         tmp[0] = p1[0];
04781                                         tmp[1] = p1[1];
04782 
04783                                         p1[0] = p2[0];
04784                                         p1[1] = p2[1];
04785 
04786                                         p2[0] = tmp[0];
04787                                         p2[1] = tmp[1];
04788                                 }
04789                         }
04790                 }
04791         }
04792         image->set_shuffled(true);
04793 }
04794 
04795 void Phase180Processor::fourier_phaseshift180(EMData * image)
04796 {
04797         if ( !image->is_complex() ) throw ImageFormatException("Can not handle images that are not complex in fourier phase shift 180");
04798 
04799         int nx = image->get_xsize();
04800         int ny = image->get_ysize();
04801         int nz = image->get_zsize();
04802 
04803         int nxy = nx * ny;
04804 
04805         float *rdata = image->get_data();
04806 
04807         // Who uses this function? It doesn't work for odd images, and it will give incorrect results for some even images
04808         // d.woolford, March 15 2009
04809         int of=0;
04810         if (((ny/2)%2)+((nz/2)%2)==1) of=1;
04811 
04812         for (int k = 0; k < nz; k++) {
04813                 size_t k2 = (size_t)k * nxy;
04814 
04815                 for (int j = 0; j < ny; j++) {
04816                         int i = ((k+j)%2==of?2:0);
04817                         size_t j2 = j * nx + k2;
04818 
04819                         for (; i < nx; i += 4) {
04820                                 rdata[i + j2] *= -1.0f;
04821                                 rdata[i + j2 + 1] *= -1.0f;
04822                         }
04823                 }
04824         }
04825 }
04826 
04827 void Phase180Processor::swap_corners_180(EMData * image)
04828 {
04829         int nx = image->get_xsize();
04830         int ny = image->get_ysize();
04831         int nz = image->get_zsize();
04832 
04833         int xodd = (nx % 2) == 1;
04834         int yodd = (ny % 2) == 1;
04835         int zodd = (nz % 2) == 1;
04836 
04837         int nxy = nx * ny;
04838 
04839         float *rdata = image->get_data();
04840 
04841         if ( ny == 1 && nz == 1 ){
04842                 throw ImageDimensionException("Error, cannot handle 1D images. This function should not have been called");
04843         }
04844         else if ( nz == 1 ) {
04845 
04846                 // Swap the bottom left and top right corners
04847                 for ( int r = 0; r < ny/2; ++r ) {
04848                         for ( int c = 0; c < nx/2; ++c) {
04849                                 int idx1 = r*nx + c;
04850                                 int idx2 = (r+ny/2+yodd)*nx + c + nx/2+xodd;
04851                                 float tmp = rdata[idx1];
04852                                 rdata[idx1] = rdata[idx2];
04853                                 rdata[idx2] = tmp;
04854                         }
04855                 }
04856 
04857                 // Swap the top left and bottom right corners
04858                 for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
04859                         for ( int c = 0; c < nx/2; ++c) {
04860                                 int idx1 = r*nx + c;
04861                                 int idx2 = (r-ny/2-yodd)*nx + c + nx/2+xodd;
04862                                 float tmp = rdata[idx1];
04863                                 rdata[idx1] = rdata[idx2];
04864                                 rdata[idx2] = tmp;
04865                         }
04866                 }
04867         }
04868         else // nx && ny && nz are greater than 1
04869         {
04870                 float tmp;
04871                 // Swap the bottom left front and back right top quadrants
04872                 size_t idx1, idx2;
04873 
04874                 for ( int s = 0; s < nz/2; ++s ) {
04875                         for ( int r = 0; r < ny/2; ++r ) {
04876                                 for ( int c = 0; c < nx/2; ++ c) {
04877                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04878                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c+nx/2+xodd;
04879                                         tmp = rdata[idx1];
04880                                         rdata[idx1] = rdata[idx2];
04881                                         rdata[idx2] = tmp;
04882                                 }
04883                         }
04884                 }
04885                 // Swap the bottom right front and back left top quadrants
04886                 for ( int s = 0; s < nz/2; ++s ) {
04887                         for ( int r = 0; r < ny/2; ++r ) {
04888                                 for ( int c = nx-1; c >= (nx/2+xodd); --c) {
04889                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04890                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c-nx/2-xodd;
04891                                         tmp = rdata[idx1];
04892                                         rdata[idx1] = rdata[idx2];
04893                                         rdata[idx2] = tmp;
04894                                 }
04895                         }
04896                 }
04897                 // Swap the top right front and back left bottom quadrants
04898                 for ( int s = 0; s < nz/2; ++s ) {
04899                         for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
04900                                 for ( int c = nx-1; c >= (nx/2+xodd); --c) {
04901                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04902                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r-ny/2-yodd)*(size_t)nx+c-nx/2-xodd;
04903                                         tmp = rdata[idx1];
04904                                         rdata[idx1] = rdata[idx2];
04905                                         rdata[idx2] = tmp;
04906                                 }
04907                         }
04908                 }
04909                 // Swap the top left front and back right bottom quadrants
04910                 for ( int s = 0; s < nz/2; ++s ) {
04911                         for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
04912                                 for ( int c = 0; c < nx/2; ++c) {
04913                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04914                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r-ny/2-yodd)*(size_t)nx+c+nx/2+xodd;
04915                                         tmp = rdata[idx1];
04916                                         rdata[idx1] = rdata[idx2];
04917                                         rdata[idx2] = tmp;
04918                                 }
04919                         }
04920                 }
04921         }
04922 }
04923 
04924 void Phase180Processor::swap_central_slices_180(EMData * image)
04925 {
04926         int nx = image->get_xsize();
04927         int ny = image->get_ysize();
04928         int nz = image->get_zsize();
04929 
04930         int xodd = (nx % 2) == 1;
04931         int yodd = (ny % 2) == 1;
04932         int zodd = (nz % 2) == 1;
04933 
04934         int nxy = nx * ny;
04935 
04936         float *rdata = image->get_data();
04937 
04938         if ( ny == 1 && nz == 1 ){
04939                 throw ImageDimensionException("Error, cannot handle 1D images. This function should not have been called");
04940         }
04941         else if ( nz == 1 ) {
04942                 float tmp;
04943                 if ( yodd ) {
04944                         // Iterate along middle row, swapping values where appropriate
04945                         int r = ny/2;
04946                         for ( int c = 0; c < nx/2; ++c ) {
04947                                 int idx1 = r*nx + c;
04948                                 int idx2 = r*nx + c + nx/2+ xodd;
04949                                 tmp = rdata[idx1];
04950                                 rdata[idx1] = rdata[idx2];
04951                                 rdata[idx2] = tmp;
04952                         }
04953                 }
04954 
04955                 if ( xodd )     {
04956                         // Iterate along the central column, swapping values where appropriate
04957                         int c = nx/2;
04958                         for (  int r = 0; r < ny/2; ++r ) {
04959                                 int idx1 = r*nx + c;
04960                                 int idx2 = (r+ny/2+yodd)*nx + c;
04961                                 tmp = rdata[idx1];
04962                                 rdata[idx1] = rdata[idx2];
04963                                 rdata[idx2] = tmp;
04964                         }
04965                 }
04966         }
04967         else // nx && ny && nz are greater than 1
04968         {
04969                 float tmp;
04970                 if ( xodd ) {
04971                         // Iterate along the x = nx/2 slice, swapping values where appropriate
04972                         int c = nx/2;
04973                         size_t idx1, idx2;
04974                         for( int s = 0; s < nz/2; ++s ) {
04975                                 for ( int r = 0; r < ny/2; ++r ) {
04976                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04977                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c;
04978                                         tmp = rdata[idx1];
04979                                         rdata[idx1] = rdata[idx2];
04980                                         rdata[idx2] = tmp;
04981                                 }
04982                         }
04983 
04984                         for( int s = nz-1; s >= (nz/2+zodd); --s ) {
04985                                 for ( int r = 0; r < ny/2; ++r ) {
04986                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04987                                         idx2 = (s-nz/2-zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c;
04988                                         tmp = rdata[idx1];
04989                                         rdata[idx1] = rdata[idx2];
04990                                         rdata[idx2] = tmp;
04991                                 }
04992                         }
04993                 }
04994                 if ( yodd ) {
04995                         // Iterate along the y = ny/2 slice, swapping values where appropriate
04996                         int r = ny/2;
04997                         size_t idx1, idx2;
04998                         for( int s = 0; s < nz/2; ++s ) {
04999                                 for ( int c = 0; c < nx/2; ++c ) {
05000                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05001                                         idx2 =(s+nz/2+zodd)*(size_t)nxy+(size_t)r*nx+c+nx/2+xodd;
05002                                         tmp = rdata[idx1];
05003                                         rdata[idx1] = rdata[idx2];
05004                                         rdata[idx2] = tmp;
05005                                 }
05006                         }
05007 
05008                         for( int s = nz-1; s >= (nz/2+zodd); --s ) {
05009                                 for ( int c = 0; c < nx/2; ++c ) {
05010                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05011                                         idx2 = (s-nz/2-zodd)*(size_t)nxy+(size_t)r*nx+c+nx/2+xodd;
05012                                         tmp = rdata[idx1];
05013                                         rdata[idx1] = rdata[idx2];
05014                                         rdata[idx2] = tmp;
05015                                 }
05016                         }
05017                 }
05018                 if ( zodd ) {
05019                         // Iterate along the z = nz/2 slice, swapping values where appropriate
05020                         int s = nz/2;
05021                         size_t idx1, idx2;
05022                         for( int r = 0; r < ny/2; ++r ) {
05023                                 for ( int c = 0; c < nx/2; ++c ) {
05024                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05025                                         idx2 = (size_t)s*nxy+(r+ny/2+yodd)*(size_t)nx+c+nx/2+xodd;
05026                                         tmp = rdata[idx1];
05027                                         rdata[idx1] = rdata[idx2];
05028                                         rdata[idx2] = tmp;
05029                                 }
05030                         }
05031 
05032                         for( int r = ny-1; r >= (ny/2+yodd); --r ) {
05033                                 for ( int c = 0; c < nx/2; ++c ) {
05034                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05035                                         idx2 = (size_t)s*nxy+(r-ny/2-yodd)*(size_t)nx+c+nx/2+xodd;
05036                                         tmp = rdata[idx1];
05037                                         rdata[idx1] = rdata[idx2];
05038                                         rdata[idx2] = tmp;
05039                                 }
05040                         }
05041                 }
05042         }
05043 }
05044 
05045 void PhaseToCornerProcessor::process_inplace(EMData * image)
05046 {
05047         if (!image)     throw NullPointerException("Error: attempt to phase shift a null image");
05048 
05049 #ifdef EMAN2_USING_CUDA
05050         if (EMData::usecuda == 1 && image->getcudarwdata() && image->get_ndim() == 2) { // Because CUDA phase origin to center only works for 2D atm
05051                 //cout << "CUDA tocorner " << image->getcudarwdata() << endl;
05052                 emdata_phaseorigin_to_corner(image->getcudarwdata(), image->get_xsize(), image->get_ysize(), image->get_zsize());
05053                 return;
05054         }
05055 #endif // EMAN2_USING_CUDA
05056 
05057         if (image->is_complex()) {
05058                 fourier_phaseshift180(image);
05059                 return;
05060         }
05061 
05062         int nx = image->get_xsize();
05063         int ny = image->get_ysize();
05064         int nz = image->get_zsize();
05065 
05066         if ( ny == 1 && nz == 1 && nx == 1) return;
05067 
05068         int nxy = nx * ny;
05069 
05070         float *rdata = image->get_data();
05071 
05072         bool xodd = (nx % 2) == 1;
05073         bool yodd = (ny % 2) == 1;
05074         bool zodd = (nz % 2) == 1;
05075 
05076         if ( ny == 1 && nz == 1 ){
05077                 if (xodd){
05078                         // Put the last pixel in the center, shifting the contents
05079                         // to right of the center one step to the right
05080                         float in_x = rdata[nx-1];
05081                         float tmp;
05082                         for ( int i = nx/2; i < nx; ++i ) {
05083                                 tmp = rdata[i];
05084                                 rdata[i] = in_x;
05085                                 in_x = tmp;
05086                         }
05087                 }
05088                 // now the operation is straight forward
05089                 for ( int i = 0; i < nx/2; ++i ) {
05090                         int idx = i+nx/2+xodd;
05091                         float tmp = rdata[i];
05092                         rdata[i] = rdata[idx];
05093                         rdata[idx] = tmp;
05094                 }
05095 
05096         }
05097         else if ( nz == 1 ) {
05098                 if (yodd) {
05099                         // Tranfer the top row into the middle row,
05100                         // shifting all pixels above and including the current middle up one.
05101                         for ( int c = 0; c < nx; ++c ) {
05102                                 // Get the value in the top row
05103                                 float last_val = rdata[(ny-1)*nx + c];
05104                                 float tmp;
05105                                 for ( int r = ny/2; r < ny; ++r ){
05106                                         int idx =r*nx+c;
05107                                         tmp = rdata[idx];
05108                                         rdata[idx] = last_val;
05109                                         last_val = tmp;
05110                                 }
05111                         }
05112                 }
05113 
05114                 if (xodd) {
05115                         // Transfer the right most column into the center column
05116                         // Shift all columns right of and including center to the right one pixel
05117                         for ( int r  = 0; r < ny; ++r ) {
05118                                 float last_val = rdata[(r+1)*nx -1];
05119                                 float tmp;
05120                                 for ( int c = nx/2; c < nx; ++c ){
05121                                         int idx =r*nx+c;
05122                                         tmp = rdata[idx];
05123                                         rdata[idx] = last_val;
05124                                         last_val = tmp;
05125                                 }
05126                         }
05127                 }
05128                 // It is important central slice shifting come after the previous two operations
05129                 swap_central_slices_180(image);
05130                 // Now the corners of the image can be shifted...
05131                 swap_corners_180(image);
05132 
05133         }
05134         else
05135         {
05136                 float tmp;
05137                 if (zodd) {
05138                         // Tranfer the back slice into the middle slice,
05139                         // shifting all pixels beyond and including the middle slice back one.
05140                         size_t idx = 0;
05141                         for (int r = 0; r < ny; ++r){
05142                                 for (int c = 0; c < nx; ++c) {
05143                                         float last_val = rdata[(nz-1)*nxy+r*nx+c];
05144                                         for (int s = nz/2; s < nz; ++s) {
05145                                                 idx = (size_t)s*nxy+r*nx+c;
05146                                                 tmp = rdata[idx];
05147                                                 rdata[idx] = last_val;
05148                                                 last_val = tmp;
05149                                         }
05150                                 }
05151                         }
05152                 }
05153                 if (yodd) {
05154                         // Tranfer the top slice into the middle slice,
05155                         // shifting all pixels above and including the middle slice up one.
05156                         size_t idx = 0;
05157                         for (int s = 0; s < nz; ++s) {
05158                                 for (int c = 0; c < nx; ++c) {
05159                                 float last_val = rdata[s*nxy+(ny-1)*nx+c];
05160                                         for (int r = ny/2; r < ny; ++r){
05161                                                 idx = (size_t)s*nxy+r*nx+c;
05162                                                 tmp = rdata[idx];
05163                                                 rdata[idx] = last_val;
05164                                                 last_val = tmp;
05165                                         }
05166                                 }
05167                         }
05168                 }
05169                 if (xodd) {
05170                         // Transfer the right most slice into the central slice
05171                         // Shift all pixels to right of and including center slice to the right one pixel
05172                         size_t idx = 0;
05173                         for (int s = 0; s < nz; ++s) {
05174                                 for (int r = 0; r < ny; ++r) {
05175                                         float last_val = rdata[s*nxy+r*nx+nx-1];
05176                                         for (int c = nx/2; c < nx; ++c){
05177                                                 idx = (size_t)s*nxy+r*nx+c;
05178                                                 tmp = rdata[idx];
05179                                                 rdata[idx] = last_val;
05180                                                 last_val = tmp;
05181                                         }
05182                                 }
05183                         }
05184                 }
05185                 // Now swap the various parts in the central slices
05186                 swap_central_slices_180(image);
05187                 // Now shift the corners
05188                 swap_corners_180(image);
05189         }
05190 }
05191 
05192 
05193 void PhaseToCenterProcessor::process_inplace(EMData * image)
05194 {
05195         if (!image)     throw NullPointerException("Error: attempt to phase shift a null image");
05196 
05197 #ifdef EMAN2_USING_CUDA
05198         if (EMData::usecuda == 1 && image->getcudarwdata() && image->get_ndim() == 2) { // Because CUDA phase origin to center only works for 2D atm
05199                 //cout << "CUDA tocenter" << endl;
05200                 emdata_phaseorigin_to_center(image->getcudarwdata(), image->get_xsize(), image->get_ysize(), image->get_zsize());
05201                 return;
05202         }
05203 #endif // EMAN2_USING_CUDA
05204 
05205         if (image->is_complex()) {
05206                 fourier_phaseshift180(image);
05207                 return;
05208         }
05209 
05210         int nx = image->get_xsize();
05211         int ny = image->get_ysize();
05212         int nz = image->get_zsize();
05213 
05214         if ( ny == 1 && nz == 1 && nx == 1) return;
05215 
05216         int nxy = nx * ny;
05217 
05218         float *rdata = image->get_data();
05219 
05220         bool xodd = (nx % 2) == 1;
05221         bool yodd = (ny % 2) == 1;
05222         bool zodd = (nz % 2) == 1;
05223 
05224         if ( ny == 1 && nz == 1 ){
05225                 if (xodd) {
05226                         // Put the center pixel at the end, shifting the contents
05227                         // to right of the center one step to the left
05228                         float in_x = rdata[nx/2];
05229                         float tmp;
05230                         for ( int i = nx-1; i >= nx/2; --i ) {
05231                                 tmp = rdata[i];
05232                                 rdata[i] = in_x;
05233                                 in_x = tmp;
05234                         }
05235                 }
05236                 // now the operation is straight forward
05237                 for ( int i = 0; i < nx/2; ++i ) {
05238                         int idx = i + nx/2;
05239                         float tmp = rdata[i];
05240                         rdata[i] = rdata[idx];
05241                         rdata[idx] = tmp;
05242                 }
05243         }
05244         else if ( nz == 1 ){
05245                 // The order in which these operations occur literally undoes what the
05246                 // PhaseToCornerProcessor did to the image.
05247                 // First, the corners sections of the image are swapped appropriately
05248                 swap_corners_180(image);
05249                 // Second, central pixel lines are swapped
05250                 swap_central_slices_180(image);
05251 
05252                 float tmp;
05253                 // Third, appropriate sections of the image are cyclically shifted by one pixel
05254                 if (xodd) {
05255                         // Transfer the middle column to the far right
05256                         // Shift all from the far right to (but not including the) middle one to the left
05257                         for ( int r  = 0; r < ny; ++r ) {
05258                                 float last_val = rdata[r*nx+nx/2];
05259                                 for ( int c = nx-1; c >=  nx/2; --c ){
05260                                         int idx = r*nx+c;
05261                                         tmp = rdata[idx];
05262                                         rdata[idx] = last_val;
05263                                         last_val = tmp;
05264                                 }
05265                         }
05266                 }
05267                 if (yodd) {
05268                         // Tranfer the middle row to the top,
05269                         // shifting all pixels from the top row down one, until  but not including the) middle
05270                         for ( int c = 0; c < nx; ++c ) {
05271                                 // Get the value in the top row
05272                                 float last_val = rdata[ny/2*nx + c];
05273                                 for ( int r = ny-1; r >= ny/2; --r ){
05274                                         int idx = r*nx+c;
05275                                         tmp = rdata[idx];
05276                                         rdata[idx] = last_val;
05277                                         last_val = tmp;
05278                                 }
05279                         }
05280                 }
05281         }
05282         else
05283         {
05284                 // The order in which these operations occur literally undoes the
05285                 // PhaseToCornerProcessor operation - in 3D.
05286                 // First, the corner quadrants of the voxel volume are swapped
05287                 swap_corners_180(image);
05288                 // Second, appropriate parts of the central slices are swapped
05289                 swap_central_slices_180(image);
05290 
05291                 float tmp;
05292                 // Third, appropriate sections of the image are cyclically shifted by one voxel
05293                 if (xodd) {
05294                         // Transfer the central slice in the x direction to the far right
05295                         // moving all slices on the far right toward the center one pixel, until
05296                         // the center x slice is ecountered
05297                         size_t idx = 0;
05298                         for (int s = 0; s < nz; ++s) {
05299                                 for (int r = 0; r < ny; ++r) {
05300                                         float last_val = rdata[s*nxy+r*nx+nx/2];
05301                                         for (int c = nx-1; c >= nx/2; --c){
05302                                                 idx = (size_t)s*nxy+r*nx+c;
05303                                                 tmp = rdata[idx];
05304                                                 rdata[idx] = last_val;
05305                                                 last_val = tmp;
05306                                         }
05307                                 }
05308                         }
05309                 }
05310                 if (yodd) {
05311                         // Tranfer the central slice in the y direction to the top
05312                         // shifting all pixels below it down on, until the center y slice is encountered.
05313                         size_t idx = 0;
05314                         for (int s = 0; s < nz; ++s) {
05315                                 for (int c = 0; c < nx; ++c) {
05316                                         float last_val = rdata[s*nxy+ny/2*nx+c];
05317                                         for (int r = ny-1; r >= ny/2; --r){
05318                                                 idx = (size_t)s*nxy+r*nx+c;
05319                                                 tmp = rdata[idx];
05320                                                 rdata[idx] = last_val;
05321                                                 last_val = tmp;
05322                                         }
05323                                 }
05324                         }
05325                 }
05326                 if (zodd) {
05327                         // Tranfer the central slice in the z direction to the back
05328                         // shifting all pixels beyond and including the middle slice back one.
05329                         size_t idx = 0;
05330                         for (int r = 0; r < ny; ++r){
05331                                 for (int c = 0; c < nx; ++c) {
05332                                         float last_val = rdata[nz/2*nxy+r*nx+c];
05333                                         for (int s = nz-1; s >= nz/2; --s) {
05334                                                 idx = (size_t)s*nxy+r*nx+c;
05335                                                 tmp = rdata[idx];
05336                                                 rdata[idx] = last_val;
05337                                                 last_val = tmp;
05338                                         }
05339                                 }
05340                         }
05341                 }
05342 
05343 
05344         }
05345 }
05346 
05347 void AutoMaskAsymUnit::process_inplace(EMData* image) {
05348         if (!image) {
05349                 LOGWARN("NULL Image");
05350                 return;
05351         }
05352 
05353         int nx = image->get_xsize();
05354         int ny = image->get_ysize();
05355         int nz = image->get_zsize();
05356 
05357         int ox = nx/2;
05358         int oy = ny/2;
05359         int oz = nz/2;
05360 
05361         Symmetry3D* sym = Factory<Symmetry3D>::get((string)params["sym"]);
05362         int au = params.set_default("au",0);
05363 
05364         float *d = image->get_data();
05365         for(int k = 0; k < nz; ++k ) {
05366                 for(int j = 0; j < ny; ++j ) {
05367                         for (int i = 0; i< nx; ++i, ++d) {
05368                                 //cout << i << " " << j << " " << k << endl;
05369                                 Vec3f v(i-ox,j-oy,k-oz);
05370 //                              v.normalize();
05371                                 int a = sym->point_in_which_asym_unit(v);
05372                                 if (au == -1) {
05373                                         *d = (float)a;
05374                                 } else {
05375                                         if ( a == au ) *d = 1;
05376                                         else *d = 0;
05377                                 }
05378                         }
05379                 }
05380         }
05381 
05382         delete sym;
05383 
05384 }
05385 
05386 void AutoMask2DProcessor::process_inplace(EMData * image)
05387 {
05388         if (!image) {
05389                 LOGWARN("NULL Image");
05390                 return;
05391         }
05392 
05393         if (image->get_ndim() != 2) {
05394                 throw ImageDimensionException("This processor only supports 2D images.");
05395         }
05396 
05397         /*
05398          The mask writing functionality was removed to comply with an EMAN2 policy which dictates that file io is not allowed from within a processor
05399          To get around this just use the return_mask parameter.
05400         string mask_output = params.set_default("write_mask", "");
05401         if ( mask_output != "") {
05402                 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.");
05403                 if (!EMUtil::is_valid_filename(mask_output)) throw InvalidParameterException("The mask output file name type is invalid or unrecognized");
05404         }
05405         */
05406 
05407         int radius=0;
05408         if (params.has_key("radius")) {
05409                 radius = params["radius"];
05410         }
05411         int nmaxseed=0;
05412         if (params.has_key("nmaxseed")) {
05413                 nmaxseed = params["nmaxseed"];
05414         }
05415 
05416         float threshold=0.0;
05417         if (params.has_key("sigma")) threshold=(float)(image->get_attr("mean"))+(float)(image->get_attr("sigma"))*(float)params["sigma"];
05418         else threshold=params["threshold"];
05419 
05420 
05421         int nshells = params["nshells"];
05422         int nshellsgauss = params["nshellsgauss"];
05423         int verbose=params.set_default("verbose",0);
05424 
05425         int nx = image->get_xsize();
05426         int ny = image->get_ysize();
05427 
05428         EMData *amask = new EMData();
05429         amask->set_size(nx, ny);
05430 
05431         float *dat = image->get_data();
05432         float *dat2 = amask->get_data();
05433         int i,j;
05434         size_t l = 0;
05435 
05436         if (verbose) printf("%f\t%f\t%f\n",(float)image->get_attr("mean"),(float)image->get_attr("sigma"),threshold);
05437 
05438         // Seeds with the highest valued pixels
05439         if (nmaxseed>0) {
05440                 vector<Pixel> maxs=image->calc_n_highest_locations(nmaxseed);
05441 
05442                 for (vector<Pixel>::iterator i=maxs.begin(); i<maxs.end(); i++) {
05443                         amask->set_value_at((*i).x,(*i).y,0,1.0);
05444                         if (verbose) printf("Seed at %d,%d,%d (%1.3f)\n",(*i).x,(*i).y,(*i).z,(*i).value);
05445                 }
05446         }
05447 
05448         // Seeds with a circle
05449         if (radius>0) {
05450                 // start with an initial circle
05451                 l=0;
05452                 for (j = -ny / 2; j < ny / 2; ++j) {
05453                         for (i = -nx / 2; i < nx / 2; ++i,++l) {
05454                                 if ( abs(j) > radius || abs(i) > radius) continue;
05455 //                              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
05456                                 if ( (j * j + i * i) > (radius*radius) ) continue;
05457                                 dat2[l] = 1.0f;
05458                         }
05459                 }
05460         }
05461 
05462         // iteratively 'flood fills' the map... recursion would be better
05463         int done=0;
05464         int iter=0;
05465         while (!done) {
05466                 iter++;
05467                 done=1;
05468                 if (verbose && iter%10==0) printf("%d iterations\n",iter);
05469                 for (j=1; j<ny-1; ++j) {
05470                         for (i=1; i<nx-1; ++i) {
05471                                 l=i+j*nx;
05472                                 if (dat2[l]) continue;
05473                                 if (dat[l]>threshold && (dat2[l-1]||dat2[l+1]||dat2[l+nx]||dat2[l-nx])) {
05474                                         dat2[l]=1.0;
05475                                         done=0;
05476                                 }
05477                         }
05478                 }
05479         }
05480 
05481         amask->update();
05482 
05483         if (verbose) printf("extending mask\n");
05484         amask->process_inplace("mask.addshells.gauss", Dict("val1", nshells, "val2", nshellsgauss));
05485 
05486         bool return_mask = params.set_default("return_mask",false);
05487         if (return_mask) {
05488                 // 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.
05489                 memcpy(dat,dat2,image->get_size()*sizeof(float));
05490         } else {
05491                 image->mult(*amask);
05492         }
05493 
05494         // EMAN2 policy is not to allow file io from with a processor
05495         //if (mask_output != "") {
05496         //      amask->write_image(mask_output);
05497         //}
05498 
05499 
05500         delete amask;
05501 }
05502 
05503 void CtfSimProcessor::process_inplace(EMData *image) {
05504         EMData *tmp=process(image);
05505         memcpy(image->get_data(),tmp->get_data(),image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
05506         delete tmp;
05507         image->update();
05508         return;
05509 }
05510 
05511 EMData* CtfSimProcessor::process(const EMData * const image) {
05512         if (!image) {
05513                 LOGWARN("NULL Image");
05514                 return NULL;
05515         }
05516 
05517         EMData *fft;
05518         if (!image->is_complex()) fft=image->do_fft();
05519         else fft=image->copy();
05520 
05521         EMAN2Ctf ctf;
05522         ctf.defocus=params["defocus"];
05523         ctf.bfactor=params["bfactor"];
05524         ctf.ampcont=params.set_default("ampcont",10.0f);
05525         ctf.voltage=params.set_default("voltage",200.0f);
05526         ctf.cs=params.set_default("cs",2.0);
05527         ctf.apix=params.set_default("apix",image->get_attr_default("apix_x",1.0));
05528         ctf.dsbg=1.0/(ctf.apix*fft->get_ysize()*4.0);           //4x oversampling
05529         
05530         float noiseamp=params.set_default("noiseamp",0.0f);
05531         float noiseampwhite=params.set_default("noiseampwhite",0.0f);
05532         
05533         // compute and apply the CTF
05534         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
05535 
05536 //      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());
05537 //      FILE *out=fopen("x.txt","w");
05538 //      for (int i=0; i<ctfc.size(); i++) fprintf(out,"%f\t%1.3g\n",0.25*i/(float)fft->get_ysize(),ctfc[i]);
05539 //      fclose(out);
05540         
05541         fft->apply_radial_func(0,0.25f/fft->get_ysize(),ctfc,1);
05542         
05543         // Add noise
05544         if (noiseamp!=0 || noiseampwhite!=0) {
05545                 EMData *noise = new EMData(image->get_ysize(),image->get_ysize(),1);
05546                 noise->process_inplace("testimage.noise.gauss");
05547                 noise->do_fft_inplace();
05548         
05549                 // White noise
05550                 if (noiseampwhite!=0) {
05551                         noise->mult((float)noiseampwhite*15.0f);                // The 15.0 is to roughly compensate for the stronger pink noise curve
05552                         fft->add(*noise);
05553                         noise->mult((float)1.0/(noiseampwhite*15.0f));
05554                 }
05555                 
05556                 // Pink noise
05557                 if (noiseamp!=0) {
05558                         vector <float> pinkbg;
05559                         pinkbg.resize(500);
05560                         float nyimg=0.5f/ctf.apix;      // image nyquist
05561                         // This pink curve came from a typical image in the GroEL 4A data set
05562                         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
05563                         noise->apply_radial_func(0,.002f,pinkbg,1);             // Image nyquist is at 250 -> 0.5
05564                         fft->add(*noise);
05565                 }
05566                 
05567         }
05568         
05569         EMData *ret=fft->do_ift();
05570         delete fft;
05571         
05572         return ret;
05573 }
05574 
05575 void AddRandomNoiseProcessor::process_inplace(EMData * image)
05576 {
05577         if (!image) {
05578                 LOGWARN("NULL Image");
05579                 return;
05580         }
05581 
05582         if (!image->is_complex()) {
05583                 LOGERR("AddRandomNoise Processor only works for complex image");
05584                 throw ImageFormatException("only work for complex image");
05585         }
05586 
05587         int n = params["n"];
05588         float x0 = params["x0"];
05589         float dx = params["dx"];
05590         vector < float >y = params["y"];
05591 
05592         int interpolation = 1;
05593         if (params.has_key("interpolation")) {
05594                 interpolation = params["interpolation"];
05595         }
05596 
05597         Randnum * randnum = Randnum::Instance();
05598         if(params.has_key("seed")) {
05599                 randnum->set_seed((int)params["seed"]);
05600         }
05601 
05602         int nx = image->get_xsize();
05603         int ny = image->get_ysize();
05604         int nz = image->get_zsize();
05605 
05606         image->ap2ri();
05607         float *rdata = image->get_data();
05608 
05609         size_t k = 0;
05610         float half_nz = 0;
05611         if (nz > 1) {
05612                 half_nz = nz / 2.0f;
05613         }
05614 
05615         const float sqrt_2 = sqrt((float) 2);
05616 
05617         float r;
05618         for (int h = 0; h < nz; h++) {
05619                 for (int j = 0; j < ny; j++) {
05620                         for (int i = 0; i < nx; i += 2, k += 2) {
05621                                 r = (Util::hypot3(i / 2.0f, j - ny / 2.0f, h - half_nz));
05622 //                              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
05623                                 r = (r - x0) / dx;
05624                                 int l = 0;
05625                                 if (interpolation) {
05626                                         l = Util::fast_floor(r);
05627                                 }
05628                                 else {
05629                                         l = Util::fast_floor(r + 0.5f);
05630                                 }
05631                                 r -= l;
05632                                 float f = 0;
05633                                 if (l >= n - 2) {
05634                                         f = y[n - 1];
05635                                 }
05636                                 else if (l < 0) {
05637                                         l = 0;
05638                                 }
05639                                 else {
05640                                         if (interpolation) {
05641                                                 f = (y[l] * (1 - r) + y[l + 1] * r);
05642                                         }
05643                                         else {
05644                                                 f = y[l];
05645                                         }
05646                                 }
05647                                 f = randnum->get_gauss_rand(sqrt(f), sqrt(f) / 3);
05648                                 float a = randnum->get_frand(0.0f, (float)(2 * M_PI));
05649                                 if (i == 0) {
05650                                         f *= sqrt_2;
05651                                 }
05652                                 rdata[k] += f * cos(a);
05653                                 rdata[k + 1] += f * sin(a);
05654                         }
05655                 }
05656         }
05657 
05658         image->update();
05659 }
05660 
05661 void AddMaskShellProcessor::process_inplace(EMData * image)
05662 {
05663         if (!image) {
05664                 LOGWARN("NULL Image");
05665                 return;
05666         }
05667 
05668         int nx = image->get_xsize();
05669         int ny = image->get_ysize();
05670         int nz = image->get_zsize();
05671 
05672         if (ny == 1) {
05673                 LOGERR("Tried to add mask shell to 1d image");
05674                 return;
05675         }
05676 
05677         int num_shells = params["nshells"];
05678 
05679         float *d = image->get_data();
05680         float k = 0.99999f;
05681         int nxy = nx * ny;
05682 
05683         if (nz == 1) {
05684                 for (int i = 0; i < num_shells; i++) {
05685                         for (int y = 1; y < ny - 1; y++) {
05686                                 int cur_y = y * nx;
05687 
05688                                 for (int x = 1; x < nx - 1; x++) {
05689                                         int j = x + cur_y;
05690                                         if (!d[j] && (d[j - 1] > k || d[j + 1] > k || d[j + nx] > k || d[j - nx] > k)) {
05691                                                 d[j] = k;
05692                                         }
05693                                 }
05694                         }
05695                         k -= 0.00001f;
05696                 }
05697         }
05698         else {
05699                 for (int i = 0; i < num_shells; i++) {
05700                         for (int z = 1; z < nz - 1; z++) {
05701                                 size_t cur_z = (size_t)z * nx * ny;
05702 
05703                                 for (int y = 1; y < ny - 1; y++) {
05704                                         size_t cur_y = y * nx + cur_z;
05705 
05706                                         for (int x = 1; x < nx - 1; x++) {
05707                                                 size_t j = x + cur_y;
05708 
05709                                                 if (!d[j] && (d[j - 1] > k || d[j + 1] > k || d[j + nx] > k ||
05710                                                                           d[j - nx] > k || d[j - nxy] > k || d[j + nxy] > k)) {
05711                                                         d[j] = k;
05712                                                 }
05713                                         }
05714                                 }
05715                         }
05716 
05717                         k -= 0.00001f;
05718                 }
05719         }
05720 
05721         size_t size = (size_t)nx * ny * nz;
05722         for (size_t i = 0; i < size; ++i) {
05723                 if (d[i]) {
05724                         d[i] = 1;
05725                 }
05726                 else {
05727                         d[i] = 0;
05728                 }
05729         }
05730 
05731         image->update();
05732 }
05733 
05734 void ToMassCenterProcessor::process_inplace(EMData * image)
05735 {
05736         if (!image) {
05737                 LOGWARN("NULL Image");
05738                 return;
05739         }
05740 
05741         int int_shift_only = params.set_default("int_shift_only",1);
05742         float threshold = params.set_default("threshold",0.0f);
05743 //      int positive = params.set_default("positive",0);
05744 
05745         if ((float)image->get_attr("sigma")==0.0f) return;              // Can't center a constant valued image
05746         if (threshold>(float)image->get_attr("maximum")) {
05747                 printf("Warning, centering threshold %1.2f, but image max %1.2f. Adjusting.",threshold,(float)image->get_attr("maximum"));
05748                 threshold=(float)image->get_attr("mean")+(float)image->get_attr("sigma");
05749         }
05750 
05751         FloatPoint com = image->calc_center_of_mass(threshold);
05752 
05753         int nx = image->get_xsize();
05754         int ny = image->get_ysize();
05755         int nz = image->get_zsize();
05756 
05757         if (int_shift_only) {
05758                 int dx = -(int)(floor(com[0] + 0.5f) - nx / 2);
05759                 int dy = -(int)(floor(com[1] + 0.5f) - ny / 2);
05760                 int dz = 0;
05761                 if (nz > 1) {
05762                         dz = -(int)(floor(com[2] + 0.5f) - nz / 2);
05763                 }
05764                 image->translate(dx, dy, dz);
05765 
05766                 Transform t;
05767                 t.set_trans((float)dx,(float)dy,(float)dz);
05768 
05769                 if (nz > 1) {
05770                         image->set_attr("xform.align3d",&t);
05771                 } else {
05772                         image->set_attr("xform.align2d",&t);
05773                 }
05774         }
05775         else {
05776                 float dx = -(com[0] - nx / 2);
05777                 float dy = -(com[1] - ny / 2);
05778                 float dz = 0;
05779                 if (nz > 1) {
05780                         dz = -(com[2] - nz / 2);
05781                 }
05782                 image->translate(dx, dy, dz);
05783 
05784                 Transform t;
05785                 t.set_trans(dx,dy,dz);
05786 
05787                 if (nz > 1) {
05788                         image->set_attr("xform.align3d",&t);
05789                 } else {
05790                         image->set_attr("xform.align2d",&t);
05791                 }
05792         }
05793 }
05794 
05795 void PhaseToMassCenterProcessor::process_inplace(EMData * image)
05796 {
05797         if (!image) {
05798                 LOGWARN("NULL Image");
05799                 return;
05800         }
05801 
05802         int int_shift_only = params.set_default("int_shift_only",1);
05803 
05804         vector<float> pcog = image->phase_cog();
05805 
05806         int dims = image->get_ndim();
05807 
05808         if (int_shift_only) {
05809                 int dx=-int(pcog[0]+0.5f),dy=0,dz=0;
05810                 if ( dims >= 2 ) dy = -int(pcog[1]+0.5);
05811                 if ( dims == 3 ) dz = -int(pcog[2]+0.5);
05812 
05813                 Transform t;
05814                 t.set_trans((float)dx,(float)dy,(float)dz);
05815                 if (dims == 3) image->set_attr("xform.align3d",&t);
05816                 else if (dims == 2) image->set_attr("xform.align2d",&t);
05817 
05818                 image->translate(dx,dy,dz);
05819         } else  {
05820                 float dx=-pcog[0],dy=0.0,dz=0.0;
05821                 if ( dims >= 2 ) dy = -pcog[1];
05822                 if ( dims == 3 ) dz = -pcog[2];
05823                 image->translate(dx,dy,dz);
05824 
05825                 Transform t;
05826                 t.set_trans(dx,dy,dz);
05827                 if (dims == 3) image->set_attr("xform.align3d",&t);
05828                 else if (dims == 2) image->set_attr("xform.align2d",&t);
05829         }
05830 }
05831 
05832 void ACFCenterProcessor::process_inplace(EMData * image)
05833 {
05834         if (!image) {
05835                 LOGWARN("NULL Image");
05836                 return;
05837         }
05838 
05839         Dict params1;
05840         params1["intonly"] = 1;
05841         params1["maxshift"] = image->get_xsize() / 4;
05842         EMData* aligned = image->align("translational", 0, params1);
05843         if ( image->get_ndim() == 3 ) {
05844                 Transform* t = aligned->get_attr("xform.align3d");
05845                 image->translate(t->get_trans());
05846                 image->set_attr("xform.align3d",t);
05847                 delete t;
05848         }
05849         else {
05850                 // assumption is the image is 2D which may be  false
05851                 Transform* t = aligned->get_attr("xform.align2d");
05852                 image->translate(t->get_trans());
05853                 image->set_attr("xform.align2d",t);
05854                 delete t;
05855         }
05856 
05857         delete aligned;
05858 
05859 }
05860 
05861 void SNRProcessor::process_inplace(EMData * image)
05862 {
05863         if (!image) {
05864                 return;
05865         }
05866 
05867         int wiener = params["wiener"];
05868         const char *snrfile = params["snrfile"];
05869 
05870         XYData sf;
05871         int err = sf.read_file(snrfile);
05872         if (err) {
05873                 LOGERR("couldn't read structure factor file!");
05874                 return;
05875         }
05876 
05877 
05878         for (size_t i = 0; i < sf.get_size(); i++) {
05879                 if (sf.get_y(i) <= 0) {
05880                         sf.set_y(i, -4.0f);
05881                 }
05882                 else {
05883                         sf.set_y(i, log10(sf.get_y(i)));
05884                 }
05885         }
05886         sf.update();
05887 
05888         Ctf *image_ctf = image->get_ctf();
05889 
05890         vector < float >ctf;
05891         if (wiener) {
05892                 ctf = image_ctf->compute_1d(image->get_ysize(),1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_WIENER_FILTER, &sf);
05893         }
05894         else {
05895                 ctf = image_ctf->compute_1d(image->get_ysize(),1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_SNR, &sf);
05896         }
05897 
05898         if(image_ctf) {delete image_ctf; image_ctf=0;}
05899 
05900         image->process_inplace("normalize.circlemean");
05901 
05902         int nx = image->get_xsize();
05903         int ny = image->get_ysize();
05904 
05905         Region clip_r(-nx / 2, -ny / 2, nx * 2, ny * 2);
05906         EMData *d3 = image->get_clip(clip_r);
05907         EMData *d2 = d3->do_fft();
05908 
05909         d2->apply_radial_func(0, 2.0f / Ctf::CTFOS, ctf, 0);
05910 
05911         if( d3 )
05912         {
05913                 delete d3;
05914                 d3 = 0;
05915         }
05916 
05917         if( image )
05918         {
05919                 delete image;
05920                 image = 0;
05921         }
05922 
05923         EMData *d1 = d2->do_ift();
05924         int d1_nx = d1->get_xsize();
05925         int d1_ny = d1->get_ysize();
05926         Region d1_r(d1_nx / 4, d1_ny / 4, d1_nx / 2, d1_ny / 2);
05927 
05928         image = d1->get_clip(d1_r);
05929 
05930         if( d1 )
05931         {
05932                 delete d1;
05933                 d1 = 0;
05934         }
05935 
05936         if( d2 )
05937         {
05938                 delete d2;
05939                 d2 = 0;
05940         }
05941 }
05942 
05943 void FileFourierProcessor::process_inplace(EMData * image)
05944 {
05945         if (!image) {
05946                 LOGWARN("NULL Image");
05947                 return;
05948         }
05949         const char *filename = params["filename"];
05950         float apix = params["apix"];
05951 
05952         FILE *in = fopen(filename, "rb");
05953         if (!in) {
05954                 LOGERR("FileFourierProcessor: cannot open file '%s'", filename);
05955                 return;
05956         }
05957 
05958         float f = 0;
05959         int n = 0;
05960         while (fscanf(in, " %f %f", &f, &f) == 2) {
05961                 n++;
05962         }
05963         rewind(in);
05964 
05965         vector < float >xd(n);
05966         vector < float >yd(n);
05967 
05968         float sf = apix * image->get_xsize();
05969 
05970         for (int i = 0; fscanf(in, " %f %f", &xd[i], &yd[i]) == 2; i++) {
05971                 xd[i] *= sf;
05972         }
05973 
05974         if (xd[2] - xd[1] != xd[1] - xd[0]) {
05975                 LOGWARN("Warning, x spacing appears nonuniform %g!=%g\n",
05976                                 xd[2] - xd[1], xd[1] - xd[0]);
05977         }
05978 
05979         EMData *d2 = image->do_fft();
05980         if( image )
05981         {
05982                 delete image;
05983                 image = 0;
05984         }
05985 
05986         d2->apply_radial_func(xd[0], xd[1] - xd[0], yd, 1);
05987         image = d2->do_ift();
05988 }
05989 
05990 void LocalNormProcessor::process_inplace(EMData * image)
05991 {
05992         if (!image) {
05993                 LOGWARN("NULL Image");
05994                 return;
05995         }
05996         float apix = params["apix"];
05997         float threshold = params["threshold"];
05998         float radius = params["radius"];
05999 
06000         if (apix > 0) {
06001                 int ny = image->get_ysize();
06002                 radius = ny * apix / radius;
06003                 //printf("Norm filter radius=%1.1f\n", radius);
06004         }
06005 
06006         EMData *blur = image->copy();
06007         EMData *maskblur = image->copy();
06008 
06009         maskblur->process_inplace("threshold.binary", Dict("value", threshold));
06010         maskblur->process_inplace("filter.lowpass.gauss", Dict("cutoff_pixels", radius));
06011 //      maskblur->process_inplace("filter.highpass.tanh", Dict("highpass", -10.0f));
06012         maskblur->process_inplace("threshold.belowtozero", Dict("minval", 0.001f));
06013 //      maskblur->process_inplace("threshold.belowtozero", Dict("minval", 0.001f));
06014 
06015 
06016         blur->process_inplace("threshold.belowtozero", Dict("minval", threshold));
06017         blur->process_inplace("filter.lowpass.gauss", Dict("cutoff_pixels", radius));
06018 //      blur->process_inplace("filter.highpass.tanh", Dict("cutoff_abs", -10.0f));
06019 
06020         maskblur->div(*blur);
06021         image->mult(*maskblur);
06022 //      maskblur->write_image("norm.mrc", 0, EMUtil::IMAGE_MRC);
06023 
06024         if( maskblur )
06025         {
06026                 delete maskblur;
06027                 maskblur = 0;
06028         }
06029 
06030         if( blur )
06031         {
06032                 delete blur;
06033                 blur = 0;
06034         }
06035 }
06036 
06037 
06038 void SymSearchProcessor::process_inplace(EMData * image)
06039 {
06040         if (!image) {
06041                 LOGWARN("NULL Image");
06042                 return;
06043         }
06044         float thresh = params["thresh"];
06045         int output_symlabel = params["output_symlabel"];
06046 
06047         // set up all the symmetry transforms for all the searched symmetries
06048         const vector<string> sym_list = params["sym"];
06049         int sym_num = sym_list.size();
06050         vector< vector< Transform > > transforms(sym_num);
06051         vector< float* > symvals(sym_num);
06052         for (int i =0; i < sym_num; i++) {
06053                 vector<Transform> sym_transform =  Symmetry3D::get_symmetries(sym_list[i]);
06054                 transforms[i] = sym_transform;
06055                 symvals[i] = new float[sym_transform.size()]; // new float(nsym);
06056         }
06057 
06058         EMData *orig = image->copy();
06059 
06060         image->to_zero();
06061 
06062         int nx= image->get_xsize();
06063         int ny= image->get_ysize();
06064         int nz= image->get_zsize();
06065         int xy = nx * ny;
06066         float * data = image->get_data();
06067         float * sdata = orig->get_data();
06068 
06069         EMData *symlabel = 0;
06070         float * ldata = symlabel->get_data();
06071         if (output_symlabel) {
06072                 symlabel = image->copy();
06073                 symlabel->to_zero();
06074                 ldata = symlabel->get_data();
06075         }
06076 
06077         for (int k = 0; k < nz; k++) {
06078                 for (int j = 0; j < ny; j++) {
06079                         for(int i = 0; i < nx; i++) {
06080                                 size_t index = (size_t)k * nx * ny + j * nx + i;
06081                                 float val = sdata[ index ];
06082                                 float bestmean = val, bestsymlevel = FLT_MAX;
06083                                 int bestsym = 0;
06084                                 for( int sym = 0; sym< sym_num; sym++) {
06085                                         int cur_sym_num = transforms[sym].size();
06086                                         float *symval = symvals[sym];
06087                                         // first find out all the symmetry related location values
06088                                         for( int s = 0; s < cur_sym_num; s++){
06089                                                 Transform r = transforms[sym][s];
06090                                                 float x2 = (float)(r[0][0] * (i-nx/2) + r[0][1] * (j-ny/2) + r[0][2] * (k-nz/2) + nx / 2);
06091                                                 float y2 = (float)(r[1][0] * (i-nx/2) + r[1][1] * (j-ny/2) + r[1][2] * (k-nz/2) + ny / 2);
06092                                                 float z2 = (float)(r[2][0] * (i-nx/2) + r[2][1] * (j-ny/2) + r[2][2] * (k-nz/2) + nz / 2);
06093 
06094                                                 if (x2 >= 0 && y2 >= 0 && z2 >= 0 && x2 < (nx - 1) && y2 < (ny - 1)
06095                                                         && z2 < (nz - 1)) {
06096                                                         float x = (float)Util::fast_floor(x2);
06097                                                         float y = (float)Util::fast_floor(y2);
06098                                                         float z = (float)Util::fast_floor(z2);
06099 
06100                                                         float t = x2 - x;
06101                                                         float u = y2 - y;
06102                                                         float v = z2 - z;
06103 
06104                                                         size_t ii = x + y * nx + z * (size_t)xy;
06105 
06106                                                         symval[s]=
06107                                                                 Util::trilinear_interpolate(sdata[ii], sdata[ii + 1], sdata[ii + nx],
06108                                                                                                                         sdata[ii + nx + 1], sdata[ii + nx * ny],
06109                                                                                                                         sdata[ii + xy + 1], sdata[ii + xy + nx],
06110                                                                                                                         sdata[ii + xy + nx + 1], t, u, v);
06111                                                 }
06112                                                 else {
06113                                                         symval[s] = 0.0 ;
06114                                                 }
06115                                         }
06116                                         float tmean=0, tsigma=0;
06117                                         for( int s = 0; s < cur_sym_num; s++) {
06118                                                 tmean += symval[s];
06119                                                 tsigma += symval[s] * symval[s];
06120                                         }
06121                                         tmean /= cur_sym_num;
06122                                         tsigma = tsigma/cur_sym_num - tmean*tmean;
06123                                         if (tsigma < bestsymlevel ) {
06124                                                 bestsymlevel = tsigma;
06125                                                 bestmean = tmean;
06126                                                 bestsym = sym;
06127                                         }
06128                                 }
06129                                 if ( bestsymlevel > thresh) {
06130                                         if (output_symlabel) ldata[index] = (float)bestsym;
06131                                         data[index] = bestmean;
06132                                 }
06133                                 else {
06134                                         if (output_symlabel) ldata[index] = -1;
06135                                         data[index] = val;
06136                                 }
06137                         }
06138                 }
06139         }
06140         if( orig )
06141         {
06142                 delete orig;
06143                 orig = 0;
06144         }
06145         for (int i =0; i < sym_num; i++) {
06146                 if( symvals[i] )
06147                 {
06148                         delete symvals[i];
06149                         symvals[i] = 0;
06150                 }
06151         }
06152         if (symlabel) params.put("symlabel_map", EMObject(symlabel));
06153 }
06154 
06155 
06156 void IndexMaskFileProcessor::process_inplace(EMData * image)
06157 {
06158         if (!image) {
06159                 LOGWARN("NULL Image");
06160                 return;
06161         }
06162 
06163         const char *filename = params["filename"];
06164         EMData *msk = new EMData();
06165         msk->read_image(filename);
06166         if (!EMUtil::is_same_size(image, msk)) {
06167                 LOGERR("IndexMaskFileProcessor: Mask size different than image");
06168                 return;
06169         }
06170 
06171         if ((int) params["ismaskset"] != 0) {
06172                 msk->process_inplace("threshold.binaryrange", Dict("low", 0.5f, "high", 1.5f));
06173         }
06174 
06175         image->mult(*msk);
06176         if( msk )
06177         {
06178                 delete msk;
06179                 msk = 0;
06180         }
06181 }
06182 
06183 
06184 void CoordinateMaskFileProcessor::process_inplace(EMData * image)
06185 {
06186         if (!image) {
06187                 LOGWARN("NULL Image");
06188                 return;
06189         }
06190 
06191         const char *filename = params["filename"];
06192         EMData *msk = new EMData();
06193         msk->read_image(filename);
06194 
06195         int nx = image->get_xsize();
06196         int ny = image->get_ysize();
06197         int nz = image->get_zsize();
06198 
06199         int xm = msk->get_xsize();
06200         int ym = msk->get_ysize();
06201         int zm = msk->get_zsize();
06202 
06203         float apix = image->get_attr("apix_x");
06204         float apixm = msk->get_attr("apix_x");
06205 
06206         float xo = image->get_attr_default("origin_x",0.0);
06207         float yo = image->get_attr_default("origin_y",0.0);
06208         float zo = image->get_attr_default("origin_z",0.0);
06209 
06210         float xom = msk->get_attr_default("origin_x",0.0);
06211         float yom = msk->get_attr_default("origin_y",0.0);
06212         float zom = msk->get_attr_default("origin_z",0.0);
06213 
06214         float *dp = image->get_data();
06215         float *dpm = msk->get_data();
06216         int nxy = nx * ny;
06217 
06218         for (int k = 0; k < nz; k++) {
06219                 float zc = zo + k * apix;
06220                 if (zc <= zom || zc >= zom + zm * apixm) {
06221                         memset(&(dp[k * nxy]), 0, sizeof(float) * nxy);
06222                 }
06223                 else {
06224                         int km = (int) ((zc - zom) / apixm);
06225 
06226                         for (int j = 0; j < ny; j++) {
06227                                 float yc = yo + j * apix;
06228                                 if (yc <= yom || yc >= yom + ym * apixm) {
06229                                         memset(&(dp[k * nxy + j * nx]), 0, sizeof(float) * nx);
06230                                 }
06231                                 else {
06232                                         int jm = (int) ((yc - yom) / apixm);
06233                                         size_t idx = 0;
06234                                         float xc;
06235                                         int im;
06236                                         for (int i = 0; i < nx; i++) {
06237                                                 xc = xo + i * apix;
06238                                                 idx = (size_t)k * nxy + j * nx + i;
06239                                                 if (xc <= xom || xc >= xom + xm * apixm) {
06240                                                         dp[idx] = 0;
06241                                                 }
06242                                                 else {
06243                                                         im = (int) ((xc - xom) / apixm);
06244                                                         if (dpm[km * xm * ym + jm * xm + im] <= 0) {
06245                                                                 dp[idx] = 0;
06246                                                         }
06247                                                 }
06248                                         }
06249                                 }
06250                         }
06251                 }
06252         }
06253 
06254         image->update();
06255         msk->update();
06256         if( msk )
06257         {
06258                 delete msk;
06259                 msk = 0;
06260         }
06261 }
06262 
06263 void MatchSFProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const {
06264         // The radial mask comes in with the existing radial image profile
06265         // The radial mask runs from 0 to the 1-D Nyquist (it leaves out the corners in Fourier space)
06266 
06267         EMData *to = params["to"];
06268         XYData *sf = new XYData();
06269         float apixto = to->get_attr("apix_x");
06270 
06271 
06272         if (to->is_complex()) {
06273                 vector<float> rd=to->calc_radial_dist(to->get_ysize()/2.0f,0,1.0f,1);
06274                 for (size_t i=0; i<rd.size(); ++i) {
06275                         sf->set_x(i,i/(apixto*2.0f*rd.size()));
06276                         sf->set_y(i,rd[i]);
06277                 }
06278         }
06279         else {
06280                 EMData *tmp=to->do_fft();
06281                 vector<float> rd=tmp->calc_radial_dist(to->get_ysize()/2,0,1.0,1);
06282                 for (size_t i=0; i<rd.size(); ++i) {
06283                         sf->set_x(i,i/(apixto*2.0f*rd.size()));
06284                         sf->set_y(i,rd[i]);
06285                 }
06286                 delete tmp;
06287         }
06288 
06289         float apix=image->get_attr("apix_x");
06290 
06291 //      sf->write_file("a.txt");
06292 //      Util::save_data(0,sf->get_x(1),radial_mask,"b.txt");
06293 
06294         int n = radial_mask.size();
06295         for (int i=0; i<n; i++) {
06296                 if (radial_mask[i]>0) radial_mask[i]= sqrt(sf->get_yatx(i/(apix*2.0f*n),false)/radial_mask[i]);
06297                 else if (i>0) radial_mask[i]=radial_mask[i-1];
06298         }
06299 
06300 //      Util::save_data(0,sf->get_x(1),radial_mask,"c.txt");
06301 
06302         delete sf;
06303 }
06304 
06305 void SetSFProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const {
06306         // The radial mask comes in with the existing radial image profile
06307         // The radial mask runs from 0 to the 1-D Nyquist (it leaves out the corners in Fourier space)
06308 
06309         XYData *sf = params["strucfac"];
06310         if(params.has_key("apix")) {
06311                 image->set_attr("apix_x", (float)params["apix"]);
06312                 image->set_attr("apix_y", (float)params["apix"]);
06313                 image->set_attr("apix_z", (float)params["apix"]);
06314         }
06315 
06316         float apix=image->get_attr("apix_x");
06317         
06318         int n = radial_mask.size();
06319         for (int i=0; i<n; i++) {
06320 //              if (radial_mask[i]>0)
06321 //              {
06322 //                      radial_mask[i]= sqrt(n*sf->get_yatx(i/(apix*2.0f*n),false)/radial_mask[i]);
06323 //              }
06324                 if (radial_mask[i]>0) {
06325                         radial_mask[i]= sqrt((n*n*n)*sf->get_yatx(i/(apix*2.0f*n))/radial_mask[i]);
06326                 }
06327                 else if (i>0) radial_mask[i]=radial_mask[i-1];
06328         }
06329 
06330 }
06331 
06332 void SmartMaskProcessor::process_inplace(EMData * image)
06333 {
06334         if (!image) {
06335                 LOGWARN("NULL Image");
06336                 return;
06337         }
06338 
06339         float mask = params["mask"];
06340 
06341         int nx = image->get_xsize();
06342         int ny = image->get_ysize();
06343         int nz = image->get_zsize();
06344 
06345         float *dat = image->get_data();
06346         double sma = 0;
06347         size_t smn = 0;
06348         float r = 0.0f;
06349         for (int k = 0; k < nz; ++k) {
06350                 for (int j = 0; j < ny; ++j) {
06351                         for (int i = 0; i < nx; ++i, ++dat) {
06352                                 r =
06353                                         sqrt((float) Util::square(i - nx / 2) + Util::square(j - ny / 2) +
06354                                                  Util::square(k - nz / 2));
06355                                 if (r > mask - 1.5f && r < mask - 0.5f) {
06356                                         sma += *dat;
06357                                         smn++;
06358                                 }
06359                         }
06360                 }
06361         }
06362 
06363         float smask = (float) (sma / smn);
06364         image->update();
06365 
06366         dat = image->get_data();
06367         for (int k = 0; k < nz; ++k) {
06368                 for (int j = 0; j < ny; ++j) {
06369                         for (int i = 0; i < nx; ++i, ++dat) {
06370                                 r =
06371                                         sqrt((float) Util::square(i - nx / 2) + Util::square(j - ny / 2) +
06372                                                  Util::square(k - nz / 2));
06373                                 if (r > mask - .5) {
06374                                         *dat = 0;
06375                                 }
06376                                 else {
06377                                         *dat -= smask;
06378                                 }
06379                         }
06380                 }
06381         }
06382 
06383         image->update();
06384 }
06385 
06386 void AutoMask3DProcessor::search_nearby(float *dat, float *dat2, int nx, int ny, int nz, float threshold)
06387 {
06388         Assert(dat != 0);
06389         Assert(dat2 != 0);
06390         Assert(nx > 0);
06391         Assert(ny > 0);
06392 
06393         bool done = false;
06394         int nxy = nx * ny;
06395 
06396         while (!done) {
06397                 done = true;
06398                 for (int k = 1; k < nz - 1; k++) {
06399                         size_t k2 = (size_t)k * nxy;
06400                         for (int j = 1; j < ny - 1; j++) {
06401                                 size_t l = j * nx + k2 + 1;
06402 
06403                                 for (int i = 1; i < nx - 1; i++) {
06404                                         if (dat[l] >= threshold || dat2[l]) {
06405                                                 if (dat2[l - 1] || dat2[l + 1] ||
06406                                                         dat2[l - nx] || dat2[l + nx] || dat2[l - nxy] || dat2[l + nxy]) {
06407                                                         dat2[l] = 1.0f;
06408                                                         done = false;
06409                                                 }
06410                                         }
06411                                         ++l;
06412                                 }
06413                         }
06414                 }
06415         }
06416 }
06417 
06418 void AutoMask3DProcessor::fill_nearby(float *dat2, int nx, int ny, int nz)
06419 {
06420         Assert(dat2 != 0);
06421         Assert(nx > 0);
06422         Assert(ny > 0);
06423         Assert(nz >= 0);
06424 
06425         int nxy = nx * ny;
06426         size_t idx;
06427         for (int i = 0; i < nx; ++i) {
06428                 for (int j = 0; j < ny; ++j) {
06429                         int j2 = j * nx + i;
06430                         int k0 = 0;
06431                         for (int k = 0; k < nz; ++k) {
06432                                 idx = j2 + (size_t)k * nxy;
06433                                 if (dat2[idx]) {
06434                                         k0 = k;
06435                                         break;
06436                                 }
06437                         }
06438 
06439                         if (k0 != nz) {
06440                                 int k1 = nz - 1;
06441                                 for (int k = nz - 1; k >= 0; --k) {
06442                                         idx = j2 + (size_t)k * nxy;
06443                                         if (dat2[idx]) {
06444                                                 k1 = k;
06445                                                 break;
06446                                         }
06447                                 }
06448 
06449                                 for (int k = k0 + 1; k < k1; ++k) {
06450                                         idx = j2 + (size_t)k * nxy;
06451                                         dat2[idx] = 1.0f;
06452                                 }
06453                         }
06454                 }
06455         }
06456 
06457         for (int i = 0; i < nx; ++i) {
06458                 for (int j = 0; j < nz; ++j) {
06459                         size_t j2 = (size_t)j * nxy + i;
06460                         int k0 = 0;
06461                         for (int k = 0; k < ny; ++k) {
06462                                 idx = (size_t)k * nx + j2;
06463                                 if (dat2[idx]) {
06464                                         k0 = k;
06465                                         break;
06466                                 }
06467                         }
06468 
06469                         if (k0 != ny) {
06470                                 int k1 = ny - 1;
06471                                 for (int k = ny - 1; k >= 0; --k) {
06472                                         idx = (size_t)k * nx + j2;
06473                                         if (dat2[idx]) {
06474                                                 k1 = k;
06475                                                 break;
06476                                         }
06477                                 }
06478 
06479                                 for (int k = k0 + 1; k < k1; ++k) {
06480                                         idx = (size_t)k * nx + j2;
06481                                         dat2[idx] = 1.0f;
06482                                 }
06483                         }
06484                 }
06485         }
06486 
06487         for (int i = 0; i < ny; ++i) {
06488                 for (int j = 0; j < nz; ++j) {
06489                         size_t j2 = i * nx + (size_t)j * nxy;
06490                         int k0 = 0;
06491                         for (int k = 0; k < nx; ++k) {
06492                                 if (dat2[k + j2]) {
06493                                         k0 = k;
06494                                         break;
06495                                 }
06496                         }
06497                         if (k0 != nx) {
06498                                 int k1 = nx - 1;
06499                                 for (int k = nx - 1; k >= 0; --k) {
06500                                         if (dat2[k + j2]) {
06501                                                 k1 = k;
06502                                                 break;
06503                                         }
06504                                 }
06505 
06506                                 for (int k = k0 + 1; k < k1; ++k) {
06507                                         dat2[k + j2] = 1.0f;
06508                                 }
06509                         }
06510                 }
06511         }
06512 
06513 }
06514 
06515 void AutoMask3DProcessor::process_inplace(EMData * image)
06516 {
06517         if (!image) {
06518                 LOGWARN("NULL Image");
06519                 return;
06520         }
06521 
06522         int nx = image->get_xsize();
06523         int ny = image->get_ysize();
06524         int nz = image->get_zsize();
06525 
06526         EMData *amask = new EMData();
06527         amask->set_size(nx, ny, nz);
06528 
06529         float sig = 0;
06530         float mean = 0;
06531 
06532         if (params.has_key("threshold1") && params.has_key("threshold2")) {
06533                 sig = image->get_attr("sigma");
06534                 mean = image->get_attr("mean");
06535         }
06536 
06537         float *dat = image->get_data();
06538         float *dat2 = amask->get_data();
06539 
06540         float t = 0;
06541         if (params.has_key("threshold1")) {
06542                 t = params["threshold1"];
06543         }
06544         else {
06545                 t = mean + sig * 2.5f;
06546         }
06547 
06548         size_t l = 0;
06549         for (int k = 0; k < nz; ++k) {
06550                 for (int j = 0; j < ny; ++j) {
06551                         for (int i = 0; i < nx; ++i) {
06552                                 if (dat[l] > t) {
06553                                         dat2[l] = 1.0f;
06554                                 }
06555                                 ++l;
06556                         }
06557                 }
06558         }
06559 
06560 
06561         if (params.has_key("threshold2")) {
06562                 t = params["threshold2"];
06563         }
06564         else {
06565                 t = mean + sig * 0.5f;
06566         }
06567 
06568         search_nearby(dat, dat2, nx, ny, nz, t);
06569 
06570         int nxy = nx * ny;
06571 
06572         for (int k = 1; k < nz - 1; ++k) {
06573                 for (int j = 1; j < ny - 1; ++j) {
06574                         size_t l = j * nx + (size_t)k * nxy + 1;
06575                         for (int i = 1; i < nx - 1; ++i, ++l) {
06576                                 if (dat2[l - 1] == 1.0f || dat2[l + 1] == 1.0f ||
06577                                         dat2[l - nx] == 1.0f || dat2[l + nx] == 1.0f ||
06578                                         dat2[l - nxy] == 1.0f || dat2[l + nxy] == 1.0f) {
06579                                         dat2[l] = 2.0f;
06580                                 }
06581                         }
06582                 }
06583         }
06584 
06585         size_t size = (size_t)nx * ny * nz;
06586         for (size_t i = 0; i < size; ++i) {
06587                 if (dat2[i] == 2.0f) {
06588                         dat2[i] = 1.0f;
06589                 }
06590         }
06591 
06592         fill_nearby(dat2, nx, ny, nz);
06593 
06594         image->update();
06595         amask->update();
06596 
06597         image->mult(*amask);
06598         amask->write_image("mask.mrc", 0, EMUtil::IMAGE_MRC);
06599         if( amask )
06600         {
06601                 delete amask;
06602                 amask = 0;
06603         }
06604 }
06605 
06606 
06607 void AutoMask3D2Processor::process_inplace(EMData * image)
06608 {
06609         if (!image) {
06610                 LOGWARN("NULL Image");
06611                 return;
06612         }
06613 
06614         if (image->get_ndim() != 3) {
06615                 throw ImageDimensionException("This processor was only ever designed to work on 3D images.");
06616         }
06617 
06618         /*
06619          The mask writing functionality was removed to comply with an EMAN2 policy which dictates that file io is not allowed from within a processor
06620          To get around this just use the return_mask parameter.
06621         string mask_output = params.set_default("write_mask", "");
06622         if ( mask_output != "") {
06623                 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.");
06624                 if (!EMUtil::is_valid_filename(mask_output)) throw InvalidParameterException("The mask output file name type is invalid or unrecognized");
06625         }
06626         */
06627 
06628         int radius=0;
06629         if (params.has_key("radius")) {
06630                 radius = params["radius"];
06631         }
06632         int nmaxseed=0;
06633         if (params.has_key("nmaxseed")) {
06634                 nmaxseed = params["nmaxseed"];
06635         }
06636 
06637         float threshold=0.0;
06638         if (params.has_key("sigma")) threshold=(float)(image->get_attr("mean"))+(float)(image->get_attr("sigma"))*(float)params["sigma"];
06639         else threshold=params["threshold"];
06640 
06641         int nshells = params["nshells"];
06642         int nshellsgauss = params["nshellsgauss"];
06643         int verbose=params.set_default("verbose",0);
06644 
06645         int nx = image->get_xsize();
06646         int ny = image->get_ysize();
06647         int nz = image->get_zsize();
06648         int nxy=nx*ny;
06649 
06650         EMData *amask = new EMData();
06651         amask->set_size(nx, ny, nz);
06652 
06653         float *dat = image->get_data();
06654         float *dat2 = amask->get_data();
06655         int i,j,k;
06656         size_t l = 0;
06657 
06658         // Seeds with the highest valued pixels
06659         if (nmaxseed>0) {
06660                 vector<Pixel> maxs=image->calc_n_highest_locations(nmaxseed);
06661 
06662                 for (vector<Pixel>::iterator i=maxs.begin(); i<maxs.end(); i++) {
06663                         amask->set_value_at((*i).x,(*i).y,(*i).z,1.0);
06664                         if (verbose) printf("Seed at %d,%d,%d (%1.3f)\n",(*i).x,(*i).y,(*i).z,(*i).value);
06665                 }
06666         }
06667 
06668         // Seeds with a sphere
06669         if (radius>0) {
06670                 // start with an initial sphere
06671                 for (k = -nz / 2; k < nz / 2; ++k) {
06672                         for (j = -ny / 2; j < ny / 2; ++j) {
06673                                 for (i = -nx / 2; i < nx / 2; ++i,++l) {
06674                                         if (abs(k) > radius || abs(j) > radius || abs(i) > radius) continue;
06675                                         if ( (k * k + j * j + i * i) > (radius*radius) || dat[l] < threshold) continue;
06676                                         dat2[l] = 1.0f;
06677                                 }
06678                         }
06679                 }
06680         }
06681 
06682 
06683         // iteratively 'flood fills' the map... recursion would be better
06684         int done=0;
06685         int iter=0;
06686         while (!done) {
06687                 iter++;
06688                 done=1;
06689                 if (verbose && iter%10==0) printf("%d iterations\n",iter);
06690                 for (k=1; k<nz-1; ++k) {
06691                         for (j=1; j<ny-1; ++j) {
06692                                 for (i=1; i<nx-1; ++i) {
06693                                         l=i+j*nx+k*nx*ny;
06694                                         if (dat2[l]) continue;
06695                                         if (dat[l]>threshold && (dat2[l-1]||dat2[l+1]||dat2[l+nx]||dat2[l-nx]||dat2[l-nxy]||dat2[l+nxy])) {
06696                                                 dat2[l]=1.0;
06697                                                 done=0;
06698                                         }
06699                                 }
06700                         }
06701                 }
06702         }
06703 
06704         amask->update();
06705 
06706         if (verbose) printf("expanding mask\n");
06707         amask->process_inplace("mask.addshells.gauss", Dict("val1", (int)(nshells+nshellsgauss/2),"val2",0));
06708         if (verbose) printf("filtering mask\n");
06709         amask->process_inplace("filter.lowpass.gauss", Dict("cutoff_abs", (float)(1.0f/(float)nshellsgauss)));
06710         amask->process_inplace("threshold.belowtozero", Dict("minval",(float)0.002));   // this makes the value exactly 0 beyond ~2.5 sigma
06711 
06712         bool return_mask = params.set_default("return_mask",false);
06713         if (return_mask) {
06714                 // 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.
06715                 dat = image->get_data();
06716                 dat2 = amask->get_data();
06717                 memcpy(dat,dat2,image->get_size()*sizeof(float));
06718         } else {
06719                 image->mult(*amask);
06720         }
06721 
06722         // EMAN2 policy is not to allow file io from with a processor
06723         //if (mask_output != "") {
06724         //      amask->write_image(mask_output);
06725         //}
06726 
06727 
06728         delete amask;
06729 }
06730 
06731 void IterBinMaskProcessor::process_inplace(EMData * image)
06732 {
06733         if (!image) {
06734                 LOGWARN("NULL Image");
06735                 return;
06736         }
06737 
06738         float val1 = params["val1"];
06739         float val2 = params["val2"];
06740 
06741         int nx = image->get_xsize();
06742         int ny = image->get_ysize();
06743         int nz = image->get_zsize();
06744         EMData *image2 = new EMData(nx,ny,nz);
06745 
06746         // Got a compile warning complaining that these things were never used. Hope I didn't break anything - apologies if so (d.woolford)
06747 //      float *dat = image->get_data();
06748 //      float *dat2 = image2->get_data();
06749 
06750 
06751         float *d = image->get_data();
06752         float *d2 = image2->get_data();
06753 
06754         const int nxy = nx * ny;
06755         size_t size = (size_t)nx * ny * nz;
06756 
06757         // TODO: THIS IS EXTREMELY INEFFICIENT
06758         if (nz != 1) {
06759                 for (int l = 1; l <= (int) val1+val2; ++l) {
06760                         for (size_t i=0; i<size; i++) d2[i]=d[i];
06761                         for (int k = 1; k < nz - 1; ++k) {
06762                                 for (int j = 1; j < ny - 1; ++j) {
06763                                         for (int i = 1; i < nx - 1; ++i) {
06764                                                 size_t t = i + j*nx+(size_t)k*nx*ny;
06765                                                 if (d[t]) continue;
06766                                                 if (d2[t - 1] || d2[t + 1] || d2[t + nx] || d2[t - nx] || d2[t + nxy] || d2[t - nxy]) d[t] = (float) l + 1;
06767                                         }
06768                                 }
06769                         }
06770                 }
06771         }
06772         else {
06773                 for (int l = 1; l <= (int) val1+val2; ++l) {
06774                         for (size_t i=0; i<size; i++) d2[i]=d[i];
06775                         for (int j = 1; j < ny - 1; ++j) {
06776                                 for (int i = 1; i < nx - 1; ++i) {
06777                                         size_t t = i + j * nx;
06778                                         if (d[t]) continue;
06779                                         if (d2[t - 1] || d2[t + 1] || d2[t + nx] || d2[t - nx]) d[t] = (float) l + 1;
06780                                 }
06781                         }
06782                 }
06783         }
06784 
06785         vector<float> vec;
06786         for (int i=0; i<val1+2; i++) vec.push_back(1.0);
06787         for (int i=0; i<val2; i++) {
06788                 vec.push_back(exp(-pow(2.0f*i/(val2),2.0f)));
06789 //              printf("%f\n",exp(-pow(2.0*i/(val1-val2),2.0)));
06790         }
06791         for (size_t i = 0; i < size; ++i) if (d[i]) d[i]=vec[(int)d[i]];
06792 
06793         image->update();
06794         delete image2;
06795 }
06796 
06797 EMData* DirectionalSumProcessor::process(const EMData* const image ) {
06798         string dir = params.set_default("axis", "");
06799         if ( dir == "" || ( dir != "x" && dir != "y" && dir != "z" ) )
06800                 throw InvalidParameterException("The direction parameter must be either x, y, or z");
06801 
06802         int nx = image->get_xsize();
06803         int ny = image->get_ysize();
06804         int nz = image->get_zsize();
06805 
06806         int a0 = params.set_default("first", 0);
06807         int a1 = params.set_default("last", -1);
06808 
06809         EMData* ret = new EMData;
06810         // compress one of the dimensions
06811         if ( dir == "x" ) {
06812                 ret->set_size(nz,ny);
06813 
06814                 // bounds checks
06815                 if (a0<0) a0+=nx;
06816                 if (a1<0) a1+=nx;
06817                 if (a0<0) a0=0;
06818                 if (a1<0) a1=0;
06819                 if (a0>=nx) a0=nx-1;
06820                 if (a1>=nx) a1=nx-1;
06821 
06822                 for (int y=0; y<ny; y++) {
06823                         for (int z=0; z<nz; z++) {
06824                                 double sum=0.0;
06825                                 for (int x=a0; x<=a1; x++) sum+=image->get_value_at(x,y,z);
06826                                 ret->set_value_at(z,y,(float)sum);
06827                         }
06828                 }
06829         }
06830         else if ( dir == "y" ) {
06831                 ret->set_size(nx,nz);
06832 
06833                 // bounds checks
06834                 if (a0<0) a0+=ny;
06835                 if (a1<0) a1+=ny;
06836                 if (a0<0) a0=0;
06837                 if (a1<0) a1=0;
06838                 if (a0>=ny) a0=ny-1;
06839                 if (a1>=ny) a1=ny-1;
06840 
06841                 for (int x=0; x<nx; x++) {
06842                         for (int z=0; z<nz; z++) {
06843                                 double sum=0.0;
06844                                 for (int y=a0; y<=a1; y++) sum+=image->get_value_at(x,y,z);
06845                                 ret->set_value_at(x,z,(float)sum);
06846                         }
06847                 }
06848         }
06849         else if ( dir == "z" ) {
06850                 ret->set_size(nx,ny);
06851 
06852                 // bounds checks
06853                 if (a0<0) a0+=nz;
06854                 if (a1<0) a1+=nz;
06855                 if (a0<0) a0=0;
06856                 if (a1<0) a1=0;
06857                 if (a0>=nz) a0=nz-1;
06858                 if (a1>=nz) a1=nz-1;
06859 
06860                 for (int y=0; y<ny; y++) {
06861                         for (int x=0; x<nx; x++) {
06862                                 double sum=0.0;
06863                                 for (int z=a0; z<=a1; z++) sum+=image->get_value_at(x,y,z);
06864                                 ret->set_value_at(x,y,(float)sum);
06865                         }
06866                 }
06867         }
06868 
06869         ret->update();
06870         return ret;
06871 }
06872 
06873 void TestImageProcessor::preprocess(EMData * image)
06874 {
06875         if (!image) {
06876                 LOGWARN("NULL Image");
06877                 return;
06878         }
06879 
06880         nx = image->get_xsize();
06881         ny = image->get_ysize();
06882         nz = image->get_zsize();
06883 }
06884 
06885 
06886 void TestImageFourierNoiseGaussian::process_inplace(EMData* image)
06887 {
06888         if (!image->is_complex()) {
06889                 int nx = image->get_xsize();
06890                 int offset = 2 - nx%2;
06891 
06892                 image->set_size(nx+offset,image->get_ysize(),image->get_zsize());
06893                 image->set_complex(true);
06894                 if (1 == offset) image->set_fftodd(true);
06895                 else image->set_fftodd(false);
06896                 image->set_fftpad(true);
06897         }
06898         image->ri2ap();
06899 
06900         float sigma = params.set_default("sigma",.25f);
06901 
06902         float * d = image->get_data();
06903         int nx = image->get_xsize();
06904         int ny = image->get_ysize();
06905         int nxy = image->get_ysize()*nx;
06906         int nzon2 = image->get_zsize()/2;
06907         int nyon2 = image->get_ysize()/2;
06908         float rx, ry, rz, length, amp, phase;
06909         int twox;
06910         for (int z = 0; z< image->get_zsize(); ++z) {
06911                 for (int y = 0; y < image->get_ysize(); ++y) {
06912                         for (int x = 0; x < image->get_xsize()/2; ++x) {
06913                                 rx = (float)x;
06914                                 ry = (float)nyon2 - (float)y;
06915                                 rz = (float)nzon2 - (float)z;
06916                                 length = sqrt(rx*rx + ry*ry + rz*rz);
06917                                 amp = exp(-sigma*length);
06918                                 phase = Util::get_frand(0,1)*2*M_PI;
06919 
06920                                 twox = 2*x;
06921                                 size_t idx1 = twox + y*nx+(size_t)z*nxy;
06922                                 size_t idx2 = idx1 + 1;
06923                                 d[idx1] = amp;
06924                                 d[idx2] = phase;
06925 
06926                         }
06927                 }
06928         }
06929 
06930         image->ap2ri();
06931         if (image->get_ndim() == 2) {
06932                 bool yodd = image->get_ysize() % 2 == 1;
06933 
06934                 int yit = image->get_ysize()/2-1;
06935                 int offset = 1;
06936                 if (yodd) {
06937                         offset = 0;
06938                 }
06939                 for (int y = 0; y < yit; ++y) {
06940                         int bot_idx = (y+offset)*nx;
06941                         int top_idx = (ny-1-y)*nx;
06942                         float r1 = d[bot_idx];
06943                         float i1 = d[bot_idx+1];
06944                         float r2 = d[top_idx];
06945                         float i2 = d[top_idx+1];
06946                         float r = (r1 + r2)/2.0f;
06947                         float i = (i1 + i2)/2.0f;
06948                         d[bot_idx] = r;
06949                         d[top_idx] = r;
06950                         d[bot_idx+1] = i;
06951                         d[top_idx+1] = -i;
06952 
06953                         bot_idx = (y+offset)*nx+nx-2;
06954                         top_idx = (ny-1-y)*nx+nx-2;
06955                         r1 = d[bot_idx];
06956                         i1 = d[bot_idx+1];
06957                         r2 = d[top_idx];
06958                         i2 = d[top_idx+1];
06959                         r = (r1 + r2)/2.0f;
06960                         i = (i1 + i2)/2.0f;
06961                         d[bot_idx] = r;
06962                         d[top_idx] = r;
06963                         d[bot_idx+1] = i;
06964                         d[top_idx+1] = -i;
06965                 }
06966 
06967                 d[1] = 0; // 0 phase for this componenet
06968                 d[nx-1] = 0; // 0 phase for this component
06969                 d[ny/2*nx+nx-1] = 0;// 0 phase for this component
06970                 d[ny/2*nx+1] = 0;// 0 phase for this component
06971         }
06972 
06973         if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
06974         image->do_ift_inplace();
06975         image->depad();
06976 }
06977 
06978 #include <iostream>
06979 using std::ostream_iterator;
06980 
06981 void CTFSNRWeightProcessor::process_inplace(EMData* image) {
06982         if (params.has_key("noise")==false) throw InvalidParameterException("You must supply the noise argument");
06983         if (params.has_key("snr")==false) throw InvalidParameterException("You must supply the snr argument");
06984 
06985         float boost = params.set_default("boost",1.0f);
06986 
06987         if (!image->is_complex()) {
06988                 image->do_fft_inplace();
06989         }
06990         EMData* cpy = image->copy();
06991         cpy->ri2inten();
06992         vector<float> sf = cpy->calc_radial_dist(cpy->get_ysize()/2,0.0,1.0,1);
06993         transform(sf.begin(),sf.end(),sf.begin(),sqrtf);
06994         delete cpy;
06995 
06996         image->ri2ap();
06997 
06998         vector<float> noise = params["noise"];
06999         vector<float> snr = params["snr"];
07000 
07001 //      copy(snr.begin(), snr.end(), ostream_iterator<float>(cout, "\n"));
07002 //      copy(noise.begin(), noise.end(), ostream_iterator<float>(cout, "\n"));
07003 
07004         for(vector<float>::iterator it = noise.begin(); it != noise.end(); ++it){
07005                 if ((*it) == 0) *it = 1;
07006         }
07007         for(vector<float>::iterator it = snr.begin(); it != snr.end(); ++it){
07008                 if ((*it) < 0) *it = 0;
07009         }
07010         // Subtract the mean from the data and store it in data_mm
07011         transform(snr.begin(),snr.end(),noise.begin(),snr.begin(),std::multiplies<float>());
07012         transform(snr.begin(),snr.end(),snr.begin(),sqrtf);
07013 //      copy(snr.begin(), snr.end(), ostream_iterator<float>(cout, "\n"));
07014 //      copy(noise.begin(), noise.end(), ostream_iterator<float>(cout, "\n"));
07015 
07016         int i = static_cast<int>(snr.size());
07017 
07018         float * d = image->get_data();
07019         int nx = image->get_xsize();
07020 //      int ny = image->get_ysize();
07021         int nxy = image->get_ysize()*nx;
07022         int nzon2 = image->get_zsize()/2;
07023         int nyon2 = image->get_ysize()/2;
07024         float rx, ry, rz, amp;
07025         int length;
07026         int twox;
07027         image->process_inplace("xform.fourierorigin.tocenter");
07028         for (int z = 0; z< image->get_zsize(); ++z) {
07029                 for (int y = 0; y < image->get_ysize(); ++y) {
07030                         for (int x = 0; x < image->get_xsize()/2; ++x) {
07031                                 rx = (float)x;
07032                                 ry = (float)nyon2 - (float)y;
07033                                 rz = (float)nzon2 - (float)z;
07034                                 length = static_cast<int>(sqrt(rx*rx + ry*ry + rz*rz));
07035 
07036                                 twox = 2*x;
07037                                 size_t idx1 = twox + y*nx+(size_t)z*nxy;
07038                                 if (length >= i || length >= (int)sf.size()) {
07039                                         d[idx1] = 0;
07040                                         continue;
07041                                 } else {
07042                                         amp = boost*snr[length];
07043 //                                      if (amp > 0) amp =sqrtf(amp);
07044 //                                      else amp = 0;
07045                                 }
07046 
07047                                 if (sf[length] == 0) {
07048                                         d[idx1] = 0;
07049                                         continue;
07050                                 }
07051 
07052 //                              size_t idx2 = idx1 + 1;
07053 //                              cout << d[idx1] << " " << sf[length] << endl;
07054                                 d[idx1] /= sf[length];
07055                                 if (d[idx1] < 0) {
07056                                         d[idx1] *= amp;
07057                                 }else {
07058                                         d[idx1] *= -amp;
07059                                 }
07060 //                              d[idx2] = phase;
07061 
07062                         }
07063                 }
07064         }
07065 
07066         image->ap2ri();
07067         if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
07068         image->do_ift_inplace();
07069         image->depad();
07070 }
07071 
07072 void TestImageFourierNoiseProfile::process_inplace(EMData * image) {
07073 
07074         if (params.has_key("profile")==false) throw InvalidParameterException("You must supply the profile argument");
07075 
07076         if (!image->is_complex()) {
07077                 int nx = image->get_xsize();
07078                 int offset = 2 - nx%2;
07079 
07080                 image->set_size(nx+offset,image->get_ysize(),image->get_zsize());
07081                 image->set_complex(true);
07082                 if (1 == offset) image->set_fftodd(true);
07083                 else image->set_fftodd(false);
07084                 image->set_fftpad(true);
07085         }
07086         image->to_zero();
07087         image->ri2ap();
07088 
07089         vector<float> profile = params["profile"];
07090         transform(profile.begin(),profile.end(),profile.begin(),sqrtf);
07091 
07092         int i = static_cast<int>(profile.size());
07093 
07094         float * d = image->get_data();
07095         int nx = image->get_xsize();
07096         int ny = image->get_ysize();
07097         int nxy = image->get_ysize()*nx;
07098         int nzon2 = image->get_zsize()/2;
07099         int nyon2 = image->get_ysize()/2;
07100         float rx, ry, rz, amp, phase;
07101         int length;
07102         int twox;
07103         for (int z = 0; z< image->get_zsize(); ++z) {
07104                 for (int y = 0; y < image->get_ysize(); ++y) {
07105                         for (int x = 0; x < image->get_xsize()/2; ++x) {
07106                                 rx = (float)x;
07107                                 ry = (float)nyon2 - (float)y;
07108                                 rz = (float)nzon2 - (float)z;
07109                                 length = static_cast<int>(sqrt(rx*rx + ry*ry + rz*rz));
07110 
07111                                 twox = 2*x;
07112                                 size_t idx1 = twox + y*nx+(size_t)z*nxy;
07113                                 size_t idx2 = idx1 + 1;
07114 
07115 
07116                                 if (length >= i) {
07117                                         d[idx1] = 0;
07118                                         d[idx2] = 0;
07119                                         continue;
07120                                 }
07121                                 amp = profile[length];
07122                                 phase = Util::get_frand(0,1)*2*M_PI;
07123 
07124 
07125                                 d[idx1] = amp;
07126                                 d[idx2] = phase;
07127 
07128                         }
07129                 }
07130         }
07131 
07132         image->ap2ri();
07133         if (image->get_ndim() == 2) {
07134                 bool yodd = image->get_ysize() % 2 == 1;
07135 
07136                 int yit = image->get_ysize()/2-1;
07137                 int offset = 1;
07138                 if (yodd) {
07139                         offset = 0;
07140                 }
07141                 for (int y = 0; y < yit; ++y) {
07142                         int bot_idx = (y+offset)*nx;
07143                         int top_idx = (ny-1-y)*nx;
07144                         float r1 = d[bot_idx];
07145                         float i1 = d[bot_idx+1];
07146                         float r2 = d[top_idx];
07147                         float i2 = d[top_idx+1];
07148                         float r = (r1 + r2)/2.0f;
07149                         float i = (i1 + i2)/2.0f;
07150                         d[bot_idx] = r;
07151                         d[top_idx] = r;
07152                         d[bot_idx+1] = i;
07153                         d[top_idx+1] = -i;
07154 
07155                         bot_idx = (y+offset)*nx+nx-2;
07156                         top_idx = (ny-1-y)*nx+nx-2;
07157                         r1 = d[bot_idx];
07158                         i1 = d[bot_idx+1];
07159                         r2 = d[top_idx];
07160                         i2 = d[top_idx+1];
07161                         r = (r1 + r2)/2.0f;
07162                         i = (i1 + i2)/2.0f;
07163                         d[bot_idx] = r;
07164                         d[top_idx] = r;
07165                         d[bot_idx+1] = i;
07166                         d[top_idx+1] = -i;
07167                 }
07168 
07169                 d[1] = 0; // 0 phase for this componenet
07170                 d[nx-1] = 0; // 0 phase for this component
07171                 d[ny/2*nx+nx-1] = 0;// 0 phase for this component
07172                 d[ny/2*nx+1] = 0;// 0 phase for this component
07173         }
07174 
07175         if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
07176         image->do_ift_inplace();
07177         image->depad();
07178 }
07179 
07180 void TestImageLineWave::process_inplace(EMData * image)
07181 {
07182         preprocess(image);
07183 
07184         float period = params.set_default("period",10.0f);
07185         size_t n = (size_t)image->get_xsize()*image->get_ysize()*image->get_zsize();
07186 
07187         for(size_t i = 0; i < n; ++i) {
07188                 float x = fmod((float)i,period);
07189                 x /= period;
07190                 x = (float)sin(x*EMConsts::pi*2.0);
07191                 image->set_value_at_fast(i,x);
07192         }
07193 }
07194 
07195 void TestImageGaussian::process_inplace(EMData * image)
07196 {
07197         preprocess(image);
07198 
07199         float sigma = params["sigma"];
07200         string axis = (const char*)params["axis"];
07201         float c = params["c"];
07202 
07203         float *dat = image->get_data();
07204         float r; //this is the distance of pixel from the image center(nx/2, ny/2, nz/2)
07205         float x2, y2, z2; //this is the coordinates of this pixel from image center
07206         for (int k = 0; k < nz; ++k) {
07207                 for (int j = 0; j < ny; ++j) {
07208                         for (int i = 0; i < nx; ++i, ++dat) {
07209                                 x2 = (float)( i - nx/2 );
07210                                 y2 = (float)( j - ny/2 );
07211                                 z2 = (float)( k - nz/2 );
07212 
07213                                 if(axis==""){
07214                                         r = (float)sqrt(x2*x2+y2*y2+z2*z2);
07215                                 }
07216                                 else if(axis == "x"){
07217                                         float lc = -c;
07218                                         float rc = c;
07219                                         r = ( (float)sqrt((x2-lc)*(x2-lc)+y2*y2+z2*z2) +
07220                                                   (float)sqrt((x2-rc)*(x2-rc)+y2*y2+z2*z2) ) /2.0f - c;
07221                                 }
07222                                 else if(axis == "y"){
07223                                         float lc = -c;
07224                                         float rc = c;
07225                                         r = ( (float)sqrt(x2*x2+(y2-lc)*(y2-lc)+z2*z2) +
07226                                                   (float)sqrt(x2*x2+(y2-rc)*(y2-rc)+z2*z2) ) /2.0f - c;
07227                                 }
07228                                 else if(axis == "z"){
07229                                         if( nz == 1 ){
07230                                                 throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07231                                         }
07232                                         float lc = -c;
07233                                         float rc = c;
07234                                         r = ( (float)sqrt(x2*x2+y2*y2+(z2-lc)*(z2-lc)) +
07235                                                   (float)sqrt(x2*x2+y2*y2+(z2-rc)*(z2-rc)) ) /2.0f - c;
07236                                 }
07237                                 else{
07238                                         throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07239                                 }
07240                                 //the amplitude of the pixel is proportional to the distance of this pixel from the center
07241                                 *dat = (float)gsl_ran_gaussian_pdf((double)r,(double)sigma);
07242                         }
07243                 }
07244         }
07245 
07246         image->update();
07247 }
07248 
07249 void TestImageGradient::process_inplace(EMData * image)
07250 {
07251         string axis = params.set_default("axis", "x");
07252 
07253         float m = params.set_default("m", 1.0f);
07254         float b = params.set_default("b", 0.0f);
07255 
07256         if ( axis != "z" && axis != "y" && axis != "x") throw InvalidParameterException("Axis must be x,y or z");
07257 
07258         preprocess(image);
07259 
07260         if ( axis == "x")
07261         {
07262                 for(int k=0; k<nz;++k) {
07263                         for(int j=0; j<ny; ++j) {
07264                                 for(int i=0; i <nx; ++i) {
07265                                         image->set_value_at(i,j,k,m*i+b);
07266                                 }
07267                         }
07268                 }
07269         }
07270         else if ( axis == "y")
07271         {
07272                 for(int k=0; k<nz;++k) {
07273                         for(int j=0; j<ny; ++j) {
07274                                 for(int i=0; i <nx; ++i) {
07275                                         image->set_value_at(i,j,k,m*j+b);
07276                                 }
07277                         }
07278                 }
07279         }
07280         else if ( axis == "z")
07281         {
07282                 for(int k=0; k<nz;++k) {
07283                         for(int j=0; j<ny; ++j) {
07284                                 for(int i=0; i <nx; ++i) {
07285                                         image->set_value_at(i,j,k,m*k+b);
07286                                 }
07287                         }
07288                 }
07289         }
07290         image->update();
07291 }
07292 
07293 void TestImageAxes::process_inplace(EMData * image)
07294 {
07295         preprocess(image);
07296 
07297         float fill = params.set_default("fill", 1.0f);
07298         // get the central coordinates
07299         int cx = nx/2;
07300         int cy = ny/2;
07301         int cz = nz/2;
07302 
07303         // Offsets are used to detect when "the extra pixel" needs to be filled in
07304         // They are implemented on the assumption that for odd dimensions
07305         // the "center pixel" is the center pixel, but for even dimensions the "center
07306         // pixel" is displaced in the positive direction by 1
07307         int xoffset = (nx % 2 == 0? 1:0);
07308         int yoffset = (ny % 2 == 0? 1:0);
07309         int zoffset = (nz % 2 == 0? 1:0);
07310 
07311         // This should never occur - but if indeed it did occur, the code in this function
07312         // would break - the function would proceed into the final "else" and seg fault
07313         // It is commented out but left for clarity
07314 //      if ( nx < 1 || ny < 1 || nz < 1 ) throw ImageDimensionException("Error: one of the image dimensions was less than zero");
07315 
07316         if ( nx == 1 && ny == 1 && nz == 1 )
07317         {
07318                 (*image)(0) = fill;
07319         }
07320         else if ( ny == 1 && nz == 1 )
07321         {
07322                 int radius = params.set_default("radius", cx );
07323                 if ( radius > cx ) radius = cx;
07324 
07325                 (*image)(cx) = fill;
07326                 for ( int i = 1; i <= radius-xoffset; ++i ) (*image)(cx+i) = fill;
07327                 for ( int i = 1; i <= radius; ++i ) (*image)(cx-i) = fill;
07328         }
07329         else if ( nz == 1 )
07330         {
07331                 int min = ( nx < ny ? nx : ny );
07332                 min /= 2;
07333 
07334                 int radius = params.set_default("radius", min );
07335                 if ( radius > min ) radius = min;
07336 
07337                 (*image)(cx,cy) = fill;
07338 
07339                 for ( int i = 1; i <= radius-xoffset; ++i ) (*image)(cx+i,cy) = fill;
07340                 for ( int i = 1; i <= radius-yoffset; ++i )(*image)(cx,cy+i) = fill;
07341 
07342                 for ( int i = 1; i <= radius; ++i )
07343                 {
07344                         (*image)(cx-i,cy) = fill;
07345                         (*image)(cx,cy-i) = fill;
07346                 }
07347 
07348         }
07349         else
07350         {
07351                 // nx > 1 && ny > 1 && nz > 1
07352                 int min = ( nx < ny ? nx : ny );
07353                 if (nz < min ) min = nz;
07354                 min /= 2;
07355 
07356                 int radius = params.set_default("radius", min);
07357                 if ( radius > min ) radius = min;
07358 
07359 
07360                 (*image)(cx,cy,cz) = fill;
07361                 for ( int i = 1; i <=radius-xoffset; ++i ) (*image)(cx+i,cy,cz) = fill;
07362                 for ( int i = 1; i <=radius-yoffset; ++i ) (*image)(cx,cy+i,cz) = fill;
07363                 for ( int i = 1; i <=radius-zoffset; ++i ) (*image)(cx,cy,cz+i) = fill;
07364                 for ( int i = 1; i <= radius; ++i )
07365                 {
07366                         (*image)(cx-i,cy,cz) = fill;
07367                         (*image)(cx,cy-i,cz) = fill;
07368                         (*image)(cx,cy,cz-i) = fill;
07369                 }
07370         }
07371 
07372         image->update();
07373 }
07374 
07375 void TestImageScurve::process_inplace(EMData * image)
07376 {
07377         preprocess(image);
07378 
07379         int dim_size = image->get_ndim();
07380         if( 2 != dim_size ) {
07381                 throw ImageDimensionException("works for 2D images only");
07382         }
07383 
07384         int nx = image->get_xsize();
07385         int ny = image->get_ysize();
07386         image->to_zero();
07387 
07388         for (int i=0; i<100; i++) {
07389                 int x=static_cast<int>( nx/2+nx/6.0*sin(i*2.0*3.14159/100.0) );
07390                 int y=ny/4+i*ny/200;
07391                 for (int xx=x-nx/10; xx<x+nx/10; xx++) {
07392                         for (int yy=y-ny/10; yy<y+ny/10; yy++) {
07393 #ifdef  _WIN32
07394                                 (*image)(xx,yy)+=exp(-pow(static_cast<float>(_hypot(xx-x,yy-y))*30.0f/nx,2.0f))*(sin(static_cast<float>((xx-x)*(yy-y)))+.5f);
07395 #else
07396                                 (*image)(xx,yy)+=exp(-pow(static_cast<float>(hypot(xx-x,yy-y))*30.0f/nx,2.0f))*(sin(static_cast<float>((xx-x)*(yy-y)))+.5f);
07397 #endif
07398                         }
07399                 }
07400         }
07401 
07402         image->update();
07403 }
07404 
07405 void TestImagePureGaussian::process_inplace(EMData * image)
07406 {
07407         preprocess(image);
07408 
07409         float x_sigma = params["x_sigma"];
07410         float y_sigma = params["y_sigma"];
07411         float z_sigma = params["z_sigma"];
07412 
07413         float x_center = params["x_center"];
07414         float y_center = params["y_center"];
07415         float z_center = params["z_center"];
07416 
07417         int nx = image->get_xsize();
07418         int ny = image->get_ysize();
07419         int nz = image->get_zsize();
07420 
07421         float x_twosig2 = 2*x_sigma*x_sigma;
07422         float y_twosig2 = 2*y_sigma*y_sigma;
07423         float z_twosig2 = 2*z_sigma*z_sigma;
07424 
07425         float sr2pi = sqrt( 2.0f*(float)pi );
07426         float norm  = 1.0f/ ( x_sigma*sr2pi );
07427         if (ny > 1) {
07428                 norm *= 1.0f/ ( y_sigma*sr2pi );
07429                 if (nz > 1) norm  *= 1.0f/ ( z_sigma*sr2pi );
07430         }
07431 
07432         float z, y, x, sum, val;
07433         for (int iz=0; iz < nz; ++iz) {
07434                 z = static_cast<float>(iz) - z_center;
07435                 for (int iy=0; iy < ny; ++iy) {
07436                         y = static_cast<float>(iy) - y_center;
07437                         for (int ix=0; ix < nx; ++ix) {
07438                                 x = static_cast<float>(ix) - x_center;
07439                                 sum = x*x/x_twosig2 + y*y/y_twosig2 + z*z/z_twosig2;
07440                                 val = norm*exp(-sum);
07441                                 (*image)(ix,iy,iz) = val;
07442                         }
07443                 }
07444         }
07445         image->update();
07446 }
07447 
07448 void TestImageSphericalWave::process_inplace(EMData * image)
07449 {
07450         preprocess(image);
07451 
07452         if(!params.has_key("wavelength")) {
07453                 LOGERR("%s wavelength is required parameter", get_name().c_str());
07454                 throw InvalidParameterException("wavelength parameter is required.");
07455         }
07456         float wavelength = params["wavelength"];
07457 
07458         float phase = 0;
07459         if(params.has_key("phase")) {
07460                 phase = params["phase"];
07461         }
07462 
07463         float x = (float)(nx/2);
07464         if (params.has_key("x")) x=params["x"];
07465         float y = (float)(ny/2);
07466         if (params.has_key("y")) y=params["y"];
07467         float z = (float)(nz/2);
07468         if (params.has_key("z")) z=params["z"];
07469 
07470         int ndim = image->get_ndim();
07471 
07472         if(ndim==2) {   //2D
07473                 for(int j=0; j<ny; ++j) {
07474                         for(int i=0; i<nx; ++i) {
07475 #ifdef _WIN32
07476                                 float r=_hypotf(x-(float)i,y-(float)j);
07477 #else
07478                                 float r=hypot(x-(float)i,y-(float)j);
07479 #endif  //_WIN32
07480                                 if (r<.5) continue;
07481                                 image->set_value_at(i,j,cos(2*(float)pi*r/wavelength+phase)/r);
07482                         }
07483                 }
07484         }
07485         else {  //3D
07486                 for(int k=0; k<nz; ++k) {
07487                         for(int j=0; j<ny; ++j) {
07488                                 for(int i=0; i<nx; ++i) {
07489                                         float r=Util::hypot3(x-(float)i,y-(float)j,z-(float)k);
07490                                         if (r<.5) continue;
07491                                         image->set_value_at(i,j,k,cos(2*(float)pi*r/wavelength+phase)/(r*r));
07492                                 }
07493                         }
07494                 }
07495         }
07496 
07497         image->update();
07498 }
07499 
07500 
07501 void TestImageSinewave::process_inplace(EMData * image)
07502 {
07503         preprocess(image);
07504 
07505         if(!params.has_key("wavelength")) {
07506                 LOGERR("%s wavelength is required parameter", get_name().c_str());
07507                 throw InvalidParameterException("wavelength parameter is required.");
07508         }
07509         float wavelength = params["wavelength"];
07510 
07511         string axis = "";
07512         if(params.has_key("axis")) {
07513                 axis = (const char*)params["axis"];
07514         }
07515 
07516         float phase = 0;
07517         if(params.has_key("phase")) {
07518                 phase = params["phase"];
07519         }
07520 
07521         int ndim = image->get_ndim();
07522         float * dat = image->get_data();
07523 
07524         if(ndim==1) {   //1D
07525                 for(int i=0; i<nx; ++i, ++dat) {
07526                         *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
07527                 }
07528         }
07529         else if(ndim==2) {      //2D
07530                 float alpha = 0;
07531                 if(params.has_key("az")) {
07532                         alpha = params["az"];
07533                 }
07534                 for(int j=0; j<ny; ++j) {
07535                         for(int i=0; i<nx; ++i, ++dat) {
07536                                 if(alpha != 0) {
07537                                         *dat = sin((i*sin((180-alpha)*M_PI/180)+j*cos((180-alpha)*M_PI/180))*(2.0f*M_PI/wavelength) + phase);
07538                                 }
07539                                 else if(axis.compare("y")==0 || axis.compare("Y")==0) {
07540                                         *dat = sin(j*(2.0f*M_PI/wavelength) + phase);
07541                                 }
07542                                 else {
07543                                         *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
07544                                 }
07545                         }
07546                 }
07547         }
07548         else {  //3D
07549                 float az = 0;
07550                 if(params.has_key("az")) {
07551                         az = params["az"];
07552                 }
07553                 float alt = 0;
07554                 if(params.has_key("alt")) {
07555                         alt = params["alt"];
07556                 }
07557                 float phi = 0;
07558                 if(params.has_key("phi")) {
07559                         phi = params["phi"];
07560                 }
07561 
07562                 for(int k=0; k<nz; ++k) {
07563                         for(int j=0; j<ny; ++j) {
07564                                 for(int i=0; i<nx; ++i, ++dat) {
07565                                         if(axis.compare("z")==0 || axis.compare("Z")==0) {
07566                                                 *dat = sin(k*(2.0f*M_PI/wavelength) + phase);
07567                                         }
07568                                         else if(axis.compare("y")==0 || axis.compare("Y")==0) {
07569                                                 *dat = sin(j*(2.0f*M_PI/wavelength) + phase);
07570                                         }
07571                                         else {
07572                                                 *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
07573                                         }
07574                                 }
07575                         }
07576                 }
07577 
07578                 if(az != 0 || alt != 0 || phi != 0) {
07579                         Dict d("type","eman");
07580                         d["az"] = az; d["phi"] = phi; d["alt"] = alt;
07581                         image->transform(Transform(d));
07582                 }
07583         }
07584 
07585         image->update();
07586 }
07587 
07588 void TestImageSinewaveCircular::process_inplace(EMData * image)
07589 {
07590         preprocess(image);
07591 
07592         float wavelength = params["wavelength"];
07593         string axis = (const char*)params["axis"];
07594         float c = params["c"];
07595         float phase = params["phase"];
07596 
07597         float *dat = image->get_data();
07598         float r; //this is the distance of pixel from the image center(nx/2, ny/2, nz/2)
07599         float x2, y2, z2; //this is the coordinates of this pixel from image center
07600         for (int k = 0; k < nz; ++k) {
07601                 for (int j = 0; j < ny; ++j) {
07602                         for (int i = 0; i < nx; ++i, ++dat) {
07603                                 x2 = (float)( i - nx/2 );
07604                                 y2 = (float)( j - ny/2 );
07605                                 z2 = (float)( k - nz/2 );
07606                                 if(axis == ""){
07607                                         r = (float)sqrt(x2*x2+y2*y2+z2*z2);
07608                                 }
07609                                 else if(axis == "x"){
07610                                         float lc = -c;
07611                                         float rc = c;
07612                                         r = ( (float)sqrt((x2-lc)*(x2-lc)+y2*y2+z2*z2) +
07613                                                   (float)sqrt((x2-rc)*(x2-rc)+y2*y2+z2*z2) ) /2.0f - c;
07614                                 }
07615                                 else if(axis == "y"){
07616                                         float lc = -c;
07617                                         float rc = c;
07618                                         r = ( (float)sqrt(x2*x2+(y2-lc)*(y2-lc)+z2*z2) +
07619                                                   (float)sqrt(x2*x2+(y2-rc)*(y2-rc)+z2*z2) ) /2.0f - c;
07620                                 }
07621                                 else if(axis == "z"){
07622                                         if( nz == 1 ){
07623                                                 throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07624                                         }
07625                                         float lc = -c;
07626                                         float rc = c;
07627                                         r = ( (float)sqrt(x2*x2+y2*y2+(z2-lc)*(z2-lc)) +
07628                                                   (float)sqrt(x2*x2+y2*y2+(z2-rc)*(z2-rc)) ) /2.0f - c;
07629                                 }
07630                                 else{
07631                                         throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07632                                 }
07633                                 *dat = sin( r * (2.0f*M_PI/wavelength) - phase*180/M_PI);
07634                         }
07635                 }
07636         }
07637 
07638         image->update();
07639 }
07640 
07641 void TestImageSquarecube::process_inplace(EMData * image)
07642 {
07643         preprocess(image);
07644 
07645         float edge_length = params["edge_length"];
07646         string axis = (const char*)params["axis"];
07647         float odd_edge = params["odd_edge"];
07648         int fill = 1;
07649         if(params.has_key("fill")) {
07650                 fill = (int)params["fill"];
07651         }
07652 
07653         float *dat = image->get_data();
07654         float x2, y2, z2; //this coordinates of this pixel from center
07655         float xEdge, yEdge, zEdge; //half of edge length for this cube
07656         if(axis == ""){
07657                 xEdge = edge_length/2.0f;
07658                 yEdge = edge_length/2.0f;
07659                 zEdge = edge_length/2.0f;
07660         }
07661         else if(axis == "x"){
07662                 xEdge = odd_edge/2.0f;
07663                 yEdge = edge_length/2.0f;
07664                 zEdge = edge_length/2.0f;
07665         }
07666         else if(axis == "y"){
07667                 xEdge = edge_length/2.0f;
07668                 yEdge = odd_edge/2.0f;
07669                 zEdge = edge_length/2.0f;
07670         }
07671         else if(axis == "z"){
07672                 if( nz == 1 ){
07673                         throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07674                 }
07675                 xEdge = edge_length/2.0f;
07676                 yEdge = edge_length/2.0f;
07677                 zEdge = odd_edge/2.0f;
07678         }
07679         else{
07680                 throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07681         }
07682         for (int k = 0; k < nz; ++k) {
07683                 for (int j = 0; j < ny; ++j) {
07684                         for (int i = 0; i < nx; ++i, ++dat) {
07685                                 x2 = (float)fabs((float)i - nx/2);
07686                                 y2 = (float)fabs((float)j - ny/2);
07687                                 z2 = (float)fabs((float)k - nz/2);
07688                                 if( x2<=xEdge && y2<=yEdge && z2<=zEdge ) {
07689                                         if( !fill) {
07690                                                 *dat = 0;
07691                                         }
07692                                         else {
07693                                                 *dat = 1;
07694                                         }
07695                                 }
07696                                 else {
07697                                         if( !fill ) {
07698                                                 *dat = 1;
07699                                         }
07700                                         else {
07701                                                 *dat = 0;
07702                                         }
07703                                 }
07704                         }
07705                 }
07706         }
07707 
07708         image->update();
07709 }
07710 
07711 void TestImageCirclesphere::process_inplace(EMData * image)
07712 {
07713         preprocess(image);
07714 
07715         float radius = params.set_default("radius",nx/2.0f);
07716         string axis = (const char*)params["axis"];
07717         float c =  params.set_default("c",nx/2.0f);
07718         int fill = params.set_default("fill",1);
07719 
07720         float *dat = image->get_data();
07721         float x2, y2, z2; //this is coordinates of this pixel from center
07722         float r = 0.0f;
07723         float asy = 0.0f;
07724         if(axis == ""){
07725                 asy = radius;
07726         }
07727         else if(axis == "x" || axis == "y"){
07728                 asy = c;
07729         }
07730         else if(axis=="z"){
07731                 if( nz == 1 ){
07732                         throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07733                 }
07734                 asy = c;
07735         }
07736         else{
07737                 throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07738         }
07739 
07740         for (int k = 0; k < nz; ++k) {
07741                 for (int j = 0; j < ny; ++j) {
07742                         for (int i = 0; i < nx; ++i, ++dat) {
07743                                 x2 = fabs((float)i - nx/2);
07744                                 y2 = fabs((float)j - ny/2);
07745                                 z2 = fabs((float)k - nz/2);
07746                                 if( axis == "" ){
07747                                         r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius) + (z2*z2)/(radius*radius);
07748                                 }
07749                                 else if (axis == "x"){
07750                                         r = (x2*x2)/(asy*asy) + (y2*y2)/(radius*radius) + (z2*z2)/(radius*radius);
07751                                 }
07752                                 else if(axis == "y"){
07753                                         r = (x2*x2)/(radius*radius) + (y2*y2)/(asy*asy) + (z2*z2)/(radius*radius);
07754                                 }
07755                                 else if(axis=="z"){
07756                                         r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius) + (z2*z2)/(asy*asy);
07757                                 }
07758                                 if( r<=1 ) {
07759                                         if( !fill) {
07760                                                 *dat = 0;
07761                                         }
07762                                         else {
07763                                                 *dat = 1;
07764                                         }
07765                                 }
07766                                 else {
07767                                         if( !fill ) {
07768                                                 *dat = 1;
07769                                         }
07770                                         else {
07771                                                 *dat = 0;
07772                                         }
07773                                 }
07774                         }
07775                 }
07776         }
07777 
07778         image->update();
07779 }
07780 
07781 void TestImageHollowEllipse::process_inplace(EMData * image)
07782 {
07783         preprocess(image);
07784 
07785         float width = params.set_default("width",2.0f);
07786 
07787         float a2 = params.set_default("a",nx/2.0f-1.0f);
07788         float b2 = params.set_default("b",ny/2.0f-1.0f);
07789         float c2 = params.set_default("c",nz/2.0f-1.0f);
07790 
07791         float a1 = params.set_default("xwidth",a2-width);
07792         float b1 = params.set_default("ywidth",b2-width);
07793         float c1 = params.set_default("zwidth",c2-width);
07794 
07795         float fill = params.set_default("fill",1.0f);
07796         Transform* t;
07797         if (params.has_key("transform")) {
07798                 t = params["transform"];
07799         } else {
07800                 t = new Transform;
07801         }
07802 
07803 
07804         int mz = 2*(int)c2+1;
07805         if ( nz < mz ) mz = nz;
07806         int my = 2*(int)b2+1;
07807         if ( ny < my ) my = ny;
07808         int mx = 2*(int)a2+1;
07809         if ( nx < mx ) mx = nx;
07810 
07811         float ai1 = 1/(a1*a1);
07812         float bi1 = 1/(b1*b1);
07813         float ci1 = 1/(c1*c1);
07814 
07815         float ai2 = 1/(a2*a2);
07816         float bi2 = 1/(b2*b2);
07817         float ci2 = 1/(c2*c2);
07818 
07819         Vec3f origin(nx/2,ny/2,nz/2);
07820 
07821         float x2, y2, z2, r1,r2;
07822         int xl, yl, zl;
07823         for (int k = 0; k < mz; ++k) {
07824                 for (int j = 0; j < my; ++j) {
07825                         for (int i = 0; i < mx; ++i) {
07826                                 x2 = (float)(i - mx/2);
07827                                 y2 = (float)(j - my/2);
07828                                 z2 = (float)(k - mz/2);
07829                                 r1 = (x2*x2)*ai1 + (y2*y2)*bi1 + (z2*z2)*ci1;
07830                                 r2 = (x2*x2)*ai2 + (y2*y2)*bi2 + (z2*z2)*ci2;
07831                                 if (r2 <= 1 && r1 >= 1) {
07832 
07833                                         if (t != 0) {
07834                                                 Vec3f v(x2,y2,z2);
07835                                                 v = (*t)*v;
07836                                                 v += origin;
07837 
07838                                                 // THIS ISN'T THE BEST STRATEGY BUT IT'S A STOP GAP. A FLOOD FILL IS PROBABLY BETTER
07839                                                 // I fill in 3x3 cubes to make sure there are no gaps...
07840 
07841                                                 for( int kk = -1; kk <= 1; ++kk)
07842                                                         for( int jj = -1; jj <= 1; ++jj)
07843                                                                 for( int ii = -1; ii <= 1; ++ii) {
07844                                                                         xl = (int)v[0]+ii;
07845                                                                         yl = (int)v[1]+jj;
07846                                                                         zl = (int)v[2]+kk;
07847                                                                         if (xl >= 0 && xl < nx && yl >= 0 && yl < ny && zl >= 0 && zl < nz)
07848                                                                                 image->set_value_at(xl,yl,zl,1.0);
07849                                                                 }
07850                                         } else {
07851                                                 image->set_value_at((int)x2+nx/2,(int)y2+ny/2,(int)z2+nz/2,fill);
07852                                         }
07853                                 }
07854                         }
07855                 }
07856         }
07857 
07858         delete t;
07859 
07860         image->update();
07861 }
07862 
07863 void TestImageEllipse::process_inplace(EMData * image)
07864 {
07865         preprocess(image);
07866 
07867 
07868         float a = params.set_default("a",nx/2.0f-1.0f);
07869         float b = params.set_default("b",ny/2.0f-1.0f);
07870         float c = params.set_default("c",nz/2.0f-1.0f);
07871         float fill = params.set_default("fill",1.0f);
07872         //bool hollow = params.set_default("hollow",false);
07873         Transform* t;
07874         if (params.has_key("transform")) {
07875                 t = params["transform"];
07876         } else {
07877                 t = new Transform;
07878         }
07879 
07880 
07881         int mz = 2*(int)c+1;
07882         if ( nz < mz ) mz = nz;
07883         int my = 2*(int)b+1;
07884         if ( ny < my ) my = ny;
07885         int mx = 2*(int)a+1;
07886         if ( nx < mx ) mx = nx;
07887 
07888 
07889         float ai = 1/(a*a);
07890         float bi = 1/(b*b);
07891         float ci = 1/(c*c);
07892 
07893         Vec3f origin(nx/2,ny/2,nz/2);
07894 
07895         float x2, y2, z2, r;
07896         int xl, yl, zl;
07897         for (int k = 0; k < mz; ++k) {
07898                 for (int j = 0; j < my; ++j) {
07899                         for (int i = 0; i < mx; ++i) {
07900                                 x2 = (float)(i - mx/2);
07901                                 y2 = (float)(j - my/2);
07902                                 z2 = (float)(k - mz/2);
07903                                 r = (x2*x2)*ai + (y2*y2)*bi + (z2*z2)*ci;
07904                                 if (r <= 1) {
07905 
07906                                         if (t != 0) {
07907                                                 Vec3f v(x2,y2,z2);
07908                                                 v = (*t)*v;
07909                                                 v += origin;
07910 
07911                                                 // THIS ISN'T THE BEST STRATEGY BUT IT'S A STOP GAP. A FLOOD FILL IS PROBABLY BETTER
07912                                                 // I fill in 3x3 cubes to make sure there are no gaps...
07913 
07914                                                 for( int kk = -1; kk <= 1; ++kk)
07915                                                         for( int jj = -1; jj <= 1; ++jj)
07916                                                                 for( int ii = -1; ii <= 1; ++ii) {
07917                                                                         xl = (int)v[0]+ii;
07918                                                                         yl = (int)v[1]+jj;
07919                                                                         zl = (int)v[2]+kk;
07920                                                                         if (xl >= 0 && xl < nx && yl >= 0 && yl < ny && zl >= 0 && zl < nz)
07921                                                                                 image->set_value_at(xl,yl,zl,fill);
07922                                                                 }
07923                                         } else {
07924                                                 image->set_value_at((int)x2+nx/2,(int)y2+ny/2,(int)z2+nz/2,fill);
07925                                         }
07926                                 }
07927                         }
07928                 }
07929         }
07930 
07931         delete t;
07932 
07933         image->update();
07934 }
07935 
07936 void TestImageNoiseUniformRand::process_inplace(EMData * image)
07937 {
07938         preprocess(image);
07939 
07940         Randnum * r = Randnum::Instance();
07941         if(params.has_key("seed")) {
07942                 r->set_seed((int)params["seed"]);
07943         }
07944 
07945         float *dat = image->get_data();
07946         size_t size = (size_t)nx*ny*nz;
07947         for (size_t i=0; i<size; ++i) {
07948                 dat[i] = r->get_frand();
07949         }
07950 
07951         image->update();
07952 }
07953 
07954 void TestImageNoiseGauss::process_inplace(EMData * image)
07955 {
07956         preprocess(image);
07957 
07958         float sigma = params["sigma"];
07959         if (sigma<=0) { sigma = 1.0; }
07960         float mean = params["mean"];
07961 
07962         Randnum * r = Randnum::Instance();
07963         if (params.has_key("seed")) {
07964                 r->set_seed((int)params["seed"]);
07965         }
07966 
07967         float *dat = image->get_data();
07968         size_t size = (size_t)nx*ny*nz;
07969         for (size_t i=0; i<size; ++i) {
07970                 dat[i] = r->get_gauss_rand(mean, sigma);
07971         }
07972 
07973         image->update();
07974 }
07975 
07976 void TestImageCylinder::process_inplace(EMData * image)
07977 {
07978         preprocess(image);
07979 
07980         int nx = image->get_xsize();
07981         int ny = image->get_ysize();
07982         int nz = image->get_zsize();
07983 
07984         if(nz == 1) {
07985                 throw ImageDimensionException("This processor only apply to 3D image");
07986         }
07987 
07988         float radius = params["radius"];
07989 #ifdef _WIN32
07990         if(radius > _cpp_min(nx, ny)/2.0) {
07991 #else
07992         if(radius > std::min(nx, ny)/2.0) {
07993 #endif
07994                 throw InvalidValueException(radius, "radius must be <= min(nx, ny)/2");
07995         }
07996 
07997         float height;
07998         if(params.has_key("height")) {
07999                 height = params["height"];
08000                 if(height > nz) {
08001                         throw InvalidValueException(radius, "height must be <= nz");
08002                 }
08003         }
08004         else {
08005                 height = static_cast<float>(nz);
08006         }
08007 
08008         float *dat = image->get_data();
08009         float x2, y2; //this is coordinates of this pixel from center axle
08010         float r = 0.0f;
08011         for (int k = 0; k < nz; ++k) {
08012                 for (int j = 0; j < ny; ++j) {
08013                         for (int i = 0; i < nx; ++i, ++dat) {
08014                                 x2 = fabs((float)i - nx/2);
08015                                 y2 = fabs((float)j - ny/2);
08016                                 r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius);
08017 
08018                                 if(r<=1 && k>=(nz-height)/2 && k<=(nz+height)/2) {
08019                                         *dat = 1;
08020                                 }
08021                                 else {
08022                                         *dat = 0;
08023                                 }
08024                         }
08025                 }
08026         }
08027 
08028         image->update();
08029 }
08030 
08031 void RampProcessor::process_inplace(EMData * image)
08032 {
08033         if (!image) {
08034                 return;
08035         }
08036 
08037         int nz = image->get_zsize();
08038         if (nz > 1) {
08039                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
08040                 throw ImageDimensionException("3D model not supported");
08041         }
08042 
08043         int nsam = image->get_xsize();
08044         int nrow = image->get_ysize();
08045         int n1 = nsam / 2;
08046         double sx1 = double(n1)*double(nsam+1);
08047         if ( nsam % 2 == 1 )
08048                 sx1 += 1 + n1;
08049         sx1 *= nrow;
08050         int n2 = nrow / 2;
08051         double sx2 = double(n2)*double(nrow+1);
08052         if ( nrow % 2 == 1 )
08053                 sx2 += 1 + n2;
08054         sx2 *= nsam;
08055         float *data = image->get_data();
08056         float *row = NULL; // handy pointer for values in a specific row of the data
08057         // statistical sums
08058         double syx1 = 0, syx2 = 0, sy = 0, sx1q = 0, sx2q = 0, syq = 0;
08059         for (int j=1; j <= nrow; j++) {
08060                 row = data + (j-1)*nsam - 1; // "-1" so that we can start counting at 1
08061                 for (int i=1; i<=nsam; i++) {
08062                         syx1 += row[i]*i;
08063                         syx2 += row[i]*j;
08064                         sy += row[i];
08065                         sx1q += i*i;
08066                         sx2q += j*j;
08067                         syq += row[i]*double(row[i]);
08068                 }
08069         }
08070         // least-squares
08071         float dn = float(nsam)*float(nrow);
08072         double qyx1 = syx1 - sx1*sy / dn;
08073         double qyx2 = syx2 - sx2*sy / dn;
08074         double qx1x2 = 0.0;
08075         double qx1 = sx1q - sx1*sx1 / dn;
08076         double qx2 = sx2q - sx2*sx2 / dn;
08077         double qy = syq - sy*sy / dn;
08078         double c = qx1*qx2 - qx1x2*qx1x2;
08079         if ( c > FLT_EPSILON ) {
08080                 double b1 = (qyx1*qx2 - qyx2*qx1x2) / c;
08081                 double b2 = (qyx2*qx1 - qyx1*qx1x2) / c;
08082                 double a = (sy - b1*sx1 - b2*sx2) / dn;
08083                 double d = a + b1 + b2;
08084                 for (int i=1; i<=nrow; i++) {
08085                         qy = d;
08086                         row = data + (i-1)*nsam - 1;
08087                         for (int k=1; k<=nsam; k++) {
08088                                 row[k] -= static_cast<float>(qy);
08089                                 qy += b1;
08090                         }
08091                         d += b2;
08092                 }
08093         } // image not altered if c is zero
08094 
08095         image->update();
08096 }
08097 
08098 
08099 void CCDNormProcessor::process_inplace(EMData * image)
08100 {
08101         if (!image) {
08102           Log::logger()->set_level(Log::ERROR_LOG);
08103           Log::logger()->error("Null image during call to CCDNorm\n");
08104           return;
08105         }
08106         if (image->get_zsize() > 1) {
08107           Log::logger()->set_level(Log::ERROR_LOG);
08108           Log::logger()->error("CCDNorm does not support 3d images\n");
08109           return;
08110         }
08111 
08112         int xs = image->get_xsize();
08113         int ys = image->get_ysize();
08114 
08115         // width of sample area on either side of the seams
08116         int width = params["width"];
08117 
08118         width%=(xs > ys ? xs/2 : ys/2);  // make sure width is a valid value
08119         if (width==0) {
08120           width=1;
08121         }
08122 
08123         // get the 4 "seams" of the image
08124         float *left, *right, *top, *bottom;
08125 
08126         double *temp;
08127         temp= (double*)malloc((xs > ys ? xs*width : ys*width)*sizeof(double));
08128         if (temp==NULL) {
08129           Log::logger()->set_level(Log::ERROR_LOG);
08130           Log::logger()->error("Could not allocate enough memory during call to CCDNorm\n");
08131           return;
08132         }
08133 
08134         int x, y, z;
08135 
08136         // the mean values of each seam and the average
08137         double mL,mR,mT,mB;
08138 
08139         // how much to shift each seam
08140         double nl,nr,nt,nb;
08141 
08142         // quad. shifting amount
08143         double q1,q2,q3,q4;
08144 
08145         // calc. the mean for each quadrant
08146         for (z=0; z<width; z++) {
08147           left = image->get_col(xs/2 -1-z)->get_data();
08148           for (y=0; y<ys; y++)
08149             temp[z*ys+y]=left[y];
08150         }
08151         mL=gsl_stats_mean(temp,1,ys*width);
08152 
08153         for (z=0; z<width; z++) {
08154           right = image->get_col(xs/2 +z)->get_data();
08155           for (y=0; y<ys; y++)
08156             temp[z*ys+y]=right[y];
08157         }
08158         mR=gsl_stats_mean(temp,1,ys*width);
08159 
08160         for (z=0; z<width; z++) {
08161           top = image->get_row(ys/2 -1-z)->get_data();
08162           for (x=0; x<xs; x++)
08163             temp[z*xs+x]=top[x];
08164         }
08165         mT=gsl_stats_mean(temp,1,xs*width);
08166 
08167         for (z=0; z<width; z++) {
08168           bottom = image->get_row(ys/2 +z)->get_data();
08169           for (x=0; x<xs; x++)
08170             temp[z*xs+x]=bottom[x];
08171         }
08172         mB=gsl_stats_mean(temp,1,xs*width);
08173 
08174         free(temp);
08175 
08176         nl=(mL+mR)/2-mL;
08177         nr=(mL+mR)/2-mR;
08178         nt=(mT+mB)/2-mT;
08179         nb=(mT+mB)/2-mB;
08180 
08181         q1=nl+nt;
08182         q2=nr+nt;
08183         q3=nr+nb;
08184         q4=nl+nb;
08185 
08186         // change the pixel values
08187         for (x = 0; x < xs / 2; x++)
08188           for (y = 0; y < ys / 2; y++) {
08189             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q1));
08190           }
08191         for (x = xs / 2; x < xs; x++)
08192           for (y = 0; y < ys / 2; y++) {
08193             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q2));
08194           }
08195         for (x = xs / 2; x < xs; x++)
08196           for (y = ys / 2; y < ys; y++) {
08197             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q3));
08198           }
08199         for (x = 0; x < xs / 2; x++)
08200           for (y = ys / 2; y < ys; y++) {
08201             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q4));
08202           }
08203 
08204 }
08205 
08206 void WaveletProcessor::process_inplace(EMData *image)
08207 {
08208         if (image->get_zsize() != 1) {
08209                         LOGERR("%s Processor doesn't support 3D", get_name().c_str());
08210                         throw ImageDimensionException("3D model not supported");
08211         }
08212 
08213         int i,nx,ny;
08214         const gsl_wavelet_type * T;
08215         nx=image->get_xsize();
08216         ny=image->get_ysize();
08217 
08218         if (nx != ny && ny!=1) throw ImageDimensionException("Wavelet transform only supports square images");
08219 //      float l=log((float)nx)/log(2.0f);
08220 //      if (l!=floor(l)) throw ImageDimensionException("Wavelet transform size must be power of 2");
08221         if( !Util::IsPower2(nx) )  throw ImageDimensionException("Wavelet transform size must be power of 2");
08222 
08223         // Unfortunately GSL works only on double() arrays
08224         // eventually we should put our own wavelet code in here
08225         // but this will work for now
08226         double *cpy = (double *)malloc(nx*ny*sizeof(double));
08227 
08228         for (i=0; i<nx*ny; i++) cpy[i]=image->get_value_at(i,0,0);
08229 
08230         string tp = (const char*)params["type"];
08231         if (tp=="daub") T=gsl_wavelet_daubechies;
08232         else if (tp=="harr") T=gsl_wavelet_haar;
08233         else if (tp=="bspl") T=gsl_wavelet_bspline;
08234         else throw InvalidStringException(tp,"Invalid wavelet name, 'daub', 'harr' or 'bspl'");
08235 
08236         int K=(int)params["ord"];
08237         gsl_wavelet_direction dir;
08238         if ((int)params["dir"]==1) dir=forward;
08239         else dir=backward;
08240 
08241         gsl_wavelet *w = gsl_wavelet_alloc(T, K);
08242         gsl_wavelet_workspace *work = gsl_wavelet_workspace_alloc(nx);
08243 
08244         if (ny==1) gsl_wavelet_transform (w,cpy, 1, nx, dir, work);
08245         else gsl_wavelet2d_transform (w, cpy, nx,nx,ny, dir, work);
08246 
08247         gsl_wavelet_workspace_free (work);
08248         gsl_wavelet_free (w);
08249 
08250         for (i=0; i<nx*ny; i++) image->set_value_at_fast(i,0,0,static_cast<float>(cpy[i]));
08251 
08252         free(cpy);
08253 }
08254 
08255 void FFTProcessor::process_inplace(EMData* image)
08256 {
08257         if( params.has_key("dir") ) {
08258                 if ((int)params["dir"]==-1) {
08259                         image->do_ift_inplace();
08260                 }
08261                 else {
08262                         image->do_fft_inplace();
08263                 }
08264         }
08265 }
08266 
08267 void RadialProcessor::process_inplace(EMData * image)
08268 {
08269         if (!image) {
08270                 LOGWARN("NULL Image");
08271                 return;
08272         }
08273 
08274         //Note : real image only!
08275         if(image->is_complex()) {
08276                 LOGERR("%s Processor only operates on real images", get_name().c_str());
08277                 throw ImageFormatException("apply to real image only");
08278         }
08279 
08280         vector<float> table = params["table"];
08281         vector<float>::size_type tsize = table.size();
08282 
08283         int nx = image->get_xsize();
08284         int ny = image->get_ysize();
08285         int nz = image->get_zsize();
08286 
08287         int nx2 = nx / 2;
08288         int ny2 = ny / 2;
08289         int nz2 = nz / 2;
08290         float sz[3];
08291         sz[0] = static_cast<float>(nx2);
08292         sz[1] = static_cast<float>(ny2);
08293         sz[2] = static_cast<float>(nz2);
08294         float szmax = *std::max_element(&sz[0], &sz[3]);
08295         float maxsize;
08296         if(nz>1) {
08297                 maxsize = (float)(1.8f * szmax);
08298         }
08299         else{
08300                 maxsize = (float)(1.5f * szmax);
08301         }
08302         for(int i=tsize+1; i<maxsize; i++) {
08303                 table.push_back(0.0f);
08304         }
08305 
08306         float dx = 1.0f / (float)nx;
08307         float dy = 1.0f / (float)ny;
08308         float dz = 1.0f / (float)nz;
08309         float dx2 = dx * dx;
08310         float dy2 = dy * dy;
08311         float dz2 = dz * dz;
08312         int iz, iy, ix, jz, jy, jx;
08313         float argx, argy, argz;
08314         float rf, df, f;
08315         int ir;
08316         for(iz=1; iz<=nz; iz++) {
08317                 jz = iz - 1;
08318                 if(jz > nz2) {
08319                         jz -= nz;
08320                 }
08321                 argz = float(jz*jz) * dz2;
08322 
08323                 for(iy=1; iy<=ny; iy++) {
08324                         jy = iy - 1;
08325                         if(jy > ny2) {
08326                                 jy -= ny;
08327                         }
08328                         argy = argz + float(jy*jy) * dy2;
08329 
08330                         for(ix=1; ix<=nx; ix++) {
08331                                 jx = ix -1;
08332                                 argx = argy + float(jx*jx)*dx2;
08333 
08334                                 rf = sqrt(argx)*2.0f*nx2;
08335                                 ir = int(rf);
08336                                 df = rf - float(ir);
08337                                 f = table[ir] + df*(table[ir+1]-table[ir]);
08338 
08339                                 (*image)(ix-1,iy-1,iz-1) *= f;
08340                         }
08341                 }
08342         }
08343 
08344         image->update();
08345 }
08346 
08347 void MirrorProcessor::process_inplace(EMData *image)
08348 {
08349         if (!image) {
08350                 LOGWARN("NULL Image");
08351                 return;
08352         }
08353 
08354         string axis = (const char*)params["axis"];
08355 
08356         float* data = image->EMData::get_data();
08357 
08358         int nx = image->get_xsize();
08359         int ny = image->get_ysize();
08360         int nz = image->get_zsize();
08361         size_t nxy = nx*ny;
08362 
08363         int x_start = 1-nx%2;
08364         int y_start = 1-ny%2;
08365         int z_start = 1-nz%2;
08366 
08367         if (axis == "x" || axis == "X") {
08368                 for (int iz = 0; iz < nz; iz++)
08369                         for (int iy = 0; iy < ny; iy++) {
08370                                 int offset = nx*iy + nxy*iz;
08371                                 reverse(&data[offset+x_start],&data[offset+nx]);
08372                         }
08373         } else if (axis == "y" || axis == "Y") {
08374                 float *tmp = new float[nx];
08375                 int nhalf   = ny/2;
08376                 size_t beg     = 0;
08377                 for (int iz = 0; iz < nz; iz++) {
08378                         beg = iz*nxy;
08379                         for (int iy = y_start; iy < nhalf; iy++) {
08380                                 memcpy(tmp, &data[beg+iy*nx], nx*sizeof(float));
08381                                 memcpy(&data[beg+iy*nx], &data[beg+(ny-iy-1+y_start)*nx], nx*sizeof(float));
08382                                 memcpy(&data[beg+(ny-iy-1+y_start)*nx], tmp, nx*sizeof(float));
08383                         }
08384                 }
08385                 delete[] tmp;
08386         } else if (axis == "z" || axis == "Z") {
08387                 if(1-z_start) {
08388                         int nhalf = nz/2;
08389                         float *tmp = new float[nxy];
08390                         for(int iz = 0;iz<nhalf;iz++){
08391                                 memcpy(tmp,&data[iz*nxy],nxy*sizeof(float));
08392                                 memcpy(&data[iz*nxy],&data[(nz-iz-1)*nxy],nxy*sizeof(float));
08393                                 memcpy(&data[(nz-iz-1)*nxy],tmp,nxy*sizeof(float));
08394                         }
08395                         delete[] tmp;
08396                 } else {
08397                         float *tmp = new float[nx];
08398                         int nhalf   = nz/2;
08399                         size_t beg     = 0;
08400                         for (int iy = 0; iy < ny; iy++) {
08401                                 beg = iy*nx;
08402                                 for (int iz = z_start; iz < nhalf; iz++) {
08403                                         memcpy(tmp, &data[beg+ iz*nxy], nx*sizeof(float));
08404                                         memcpy(&data[beg+iz*nxy], &data[beg+(nz-iz-1+z_start)*nxy], nx*sizeof(float));
08405                                         memcpy(&data[beg+(nz-iz-1+z_start)*nxy], tmp, nx*sizeof(float));
08406                                 }
08407                         }
08408                         delete[] tmp;
08409                 }
08410         }
08411 
08412         image->update();
08413 }
08414 
08415 
08416 int EMAN::multi_processors(EMData * image, vector < string > processornames)
08417 {
08418         Assert(image != 0);
08419         Assert(processornames.size() > 0);
08420 
08421         for (size_t i = 0; i < processornames.size(); i++) {
08422                 image->process_inplace(processornames[i]);
08423         }
08424         return 0;
08425 }
08426 
08427 
08428 float* TransformProcessor::transform(const EMData* const image, const Transform& t) const {
08429 
08430         ENTERFUNC;
08431 
08432         Transform inv = t.inverse();
08433         int nx = image->get_xsize();
08434         int ny = image->get_ysize();
08435         int nz = image->get_zsize();
08436         int nxy = nx*ny;
08437 
08438         const float * const src_data = image->get_const_data();
08439         float *des_data = (float *) EMUtil::em_malloc(nx*ny*nz* sizeof(float));
08440 
08441         if (nz == 1) {
08442                 Vec2f offset(nx/2,ny/2);
08443                 for (int j = 0; j < ny; j++) {
08444                         for (int i = 0; i < nx; i++) {
08445                                 Vec2f coord(i-nx/2,j-ny/2);
08446                                 Vec2f soln = inv*coord;
08447                                 soln += offset;
08448 
08449                                 float x2 = soln[0];
08450                                 float y2 = soln[1];
08451 
08452                                 if (x2 < 0 || x2 >= nx || y2 < 0 || y2 >= ny ) {
08453                                         des_data[i + j * nx] = 0; // It may be tempting to set this value to the
08454                                         // mean but in fact this is not a good thing to do. Talk to S.Ludtke about it.
08455                                 }
08456                                 else {
08457                                         int ii = Util::fast_floor(x2);
08458                                         int jj = Util::fast_floor(y2);
08459                                         int k0 = ii + jj * nx;
08460                                         int k1 = k0 + 1;
08461                                         int k2 = k0 + nx;
08462                                         int k3 = k0 + nx + 1;
08463 
08464                                         if (ii == nx - 1) {
08465                                                 k1--;
08466                                                 k3--;
08467                                         }
08468                                         if (jj == ny - 1) {
08469                                                 k2 -= nx;
08470                                                 k3 -= nx;
08471                                         }
08472 
08473                                         float t = x2 - ii;
08474                                         float u = y2 - jj;
08475 
08476                                         des_data[i + j * nx] = Util::bilinear_interpolate(src_data[k0],src_data[k1], src_data[k2], src_data[k3],t,u);
08477                                 }
08478                         }
08479                 }
08480         }
08481         else {
08482                 size_t l=0, ii, k0, k1, k2, k3, k4, k5, k6, k7;
08483                 Vec3f offset(nx/2,ny/2,nz/2);
08484                 float x2, y2, z2, tuvx, tuvy, tuvz;
08485                 int ix, iy, iz;
08486                 for (int k = 0; k < nz; ++k) {
08487                         for (int j = 0; j < ny; ++j) {
08488                                 for (int i = 0; i < nx; ++i,++l) {
08489                                         Vec3f coord(i-nx/2,j-ny/2,k-nz/2);
08490                                         Vec3f soln = inv*coord;
08491                                         soln += offset;
08492 
08493                                         x2 = soln[0];
08494                                         y2 = soln[1];
08495                                         z2 = soln[2];
08496 
08497                                         if (x2 < 0 || y2 < 0 || z2 < 0 || x2 >= nx  || y2 >= ny  || z2>= nz ) {
08498                                                 des_data[l] = 0;
08499                                         }
08500                                         else {
08501                                                 ix = Util::fast_floor(x2);
08502                                                 iy = Util::fast_floor(y2);
08503                                                 iz = Util::fast_floor(z2);
08504                                                 tuvx = x2-ix;
08505                                                 tuvy = y2-iy;
08506                                                 tuvz = z2-iz;
08507                                                 ii = ix + iy * nx + iz * nxy;
08508 
08509                                                 k0 = ii;
08510                                                 k1 = k0 + 1;
08511                                                 k2 = k0 + nx;
08512                                                 k3 = k0 + nx+1;
08513                                                 k4 = k0 + nxy;
08514                                                 k5 = k1 + nxy;
08515                                                 k6 = k2 + nxy;
08516                                                 k7 = k3 + nxy;
08517 
08518                                                 if (ix == nx - 1) {
08519                                                         k1--;
08520                                                         k3--;
08521                                                         k5--;
08522                                                         k7--;
08523                                                 }
08524                                                 if (iy == ny - 1) {
08525                                                         k2 -= nx;
08526                                                         k3 -= nx;
08527                                                         k6 -= nx;
08528                                                         k7 -= nx;
08529                                                 }
08530                                                 if (iz == nz - 1) {
08531                                                         k4 -= nxy;
08532                                                         k5 -= nxy;
08533                                                         k6 -= nxy;
08534                                                         k7 -= nxy;
08535                                                 }
08536 
08537                                                 des_data[l] = Util::trilinear_interpolate(src_data[k0],
08538                                                                 src_data[k1], src_data[k2], src_data[k3], src_data[k4],
08539                                                                 src_data[k5], src_data[k6],     src_data[k7], tuvx, tuvy, tuvz);
08540                                         }
08541                                 }
08542                         }
08543                 }
08544         }
08545 
08546         EXITFUNC;
08547         return des_data;
08548 }
08549 
08550 void TransformProcessor::assert_valid_aspect(const EMData* const image) const {
08551         int ndim = image->get_ndim();
08552         if (ndim != 2 && ndim != 3) throw ImageDimensionException("Transforming an EMData only works if it's 2D or 3D");
08553 
08554         if (! params.has_key("transform") ) throw InvalidParameterException("You must specify a Transform in order to perform this operation");
08555 }
08556 
08557 //void TransformProcessor::update_emdata_attributes(EMData* const p, const Dict& attr_dict, const float& scale) const {
08558 //
08559 //      float inv_scale = 1.0f/scale;
08560 //
08561 //      p->scale_pixel(1.0f/scale);
08562 //
08563 //      // According to Baker the origin attributes remain unchanged
08574 //
08575 //      vector<string> scale_attrs;
08576 //      scale_attrs.push_back("apix_x");
08577 //      scale_attrs.push_back("apix_y");
08578 //      scale_attrs.push_back("apix_z");
08579 //
08580 //
08581 //      for(vector<string>::const_iterator it = scale_attrs.begin(); it != scale_attrs.end(); ++it) {
08582 //              if (attr_dict.has_key(*it)) {
08583 //                      p->set_attr(*it,(float) attr_dict[*it] * inv_scale);
08584 //              }
08585 //      }
08586 //
08587 //}
08588 
08589 EMData* TransformProcessor::process(const EMData* const image) {
08590         ENTERFUNC;
08591 
08592         assert_valid_aspect(image);
08593 
08594         Transform* t = params["transform"];
08595 
08596         EMData* p  = 0;
08597 #ifdef EMAN2_USING_CUDA
08598         if(EMData::usecuda == 1 && image->isrodataongpu()){     
08599                 //cout << "using CUDA xform" << endl;
08600                 p = new EMData(0,0,image->get_xsize(),image->get_ysize(),image->get_zsize(),image->get_attr_dict()); 
08601                 float * m = new float[12];
08602                 Transform inv = t->inverse();
08603                 inv.copy_matrix_into_array(m);
08604                 image->bindcudaarrayA(true);
08605                 p->runcuda(emdata_transform_cuda(m,image->get_xsize(),image->get_ysize(),image->get_zsize()));
08606                 image->unbindcudaarryA();
08607                 delete [] m;
08608                 p->update();
08609         }
08610 #endif
08611 
08612         if ( p == 0 ) {
08613                 float* des_data = transform(image,*t);
08614                 p = new EMData(des_data,image->get_xsize(),image->get_ysize(),image->get_zsize(),image->get_attr_dict());
08615         }
08616 
08617         //      all_translation += transform.get_trans();
08618 
08619         float scale = t->get_scale();
08620         if (scale != 1.0) {
08621                 p->scale_pixel(1.0f/scale);
08622 //              update_emdata_attributes(p,image->get_attr_dict(),scale);
08623         }
08624 
08625         if(t) {delete t; t=0;}
08626         EXITFUNC;
08627         return p;
08628 }
08629 
08630 void TransformProcessor::process_inplace(EMData* image) {
08631         ENTERFUNC;
08632 
08633         assert_valid_aspect(image);
08634 
08635         Transform* t = params["transform"];
08636 
08637         //      all_translation += transform.get_trans();
08638         bool use_cpu = true;
08639         
08640 #ifdef EMAN2_USING_CUDA
08641         if(EMData::usecuda == 1 && image->isrodataongpu()){
08642                 //cout << "CUDA xform inplace" << endl;
08643                 image->bindcudaarrayA(false);   
08644                 float * m = new float[12];
08645                 Transform inv = t->inverse();
08646                 inv.copy_matrix_into_array(m);  
08647                 image->runcuda(emdata_transform_cuda(m,image->get_xsize(),image->get_ysize(),image->get_zsize()));
08648                 image->unbindcudaarryA();
08649                 delete [] m;
08650                 use_cpu = false;
08651                 image->update();
08652         }
08653 #endif
08654         if ( use_cpu ) {
08655                 float* des_data = transform(image,*t);
08656                 image->set_data(des_data,image->get_xsize(),image->get_ysize(),image->get_zsize());
08657                 image->update();
08658         }
08659         float scale = t->get_scale();
08660         if (scale != 1.0f) {
08661                 image->scale_pixel(1.0f/scale);
08662 //              update_emdata_attributes(image,image->get_attr_dict(),scale);
08663         }
08664 
08665         if(t) {delete t; t=0;}
08666 
08667         EXITFUNC;
08668 }
08669 
08670 
08671 void IntTranslateProcessor::assert_valid_aspect(const vector<int>& translation, const EMData* const) const {
08672         if (translation.size() == 0 ) throw InvalidParameterException("You must specify the trans argument");
08673 }
08674 
08675 Region IntTranslateProcessor::get_clip_region(vector<int>& translation, const EMData* const image) const {
08676         unsigned int dim = static_cast<unsigned int> (image->get_ndim());
08677 
08678         if ( translation.size() != dim ) {
08679                 for(unsigned int i = translation.size(); i < dim; ++i ) translation.push_back(0);
08680         }
08681 
08682         Region clip_region;
08683         if (dim == 1) {
08684                 clip_region = Region(-translation[0],image->get_xsize());
08685         } else if ( dim == 2 ) {
08686                 clip_region = Region(-translation[0],-translation[1],image->get_xsize(),image->get_ysize());
08687         } else if ( dim == 3 ) {
08688                 clip_region = Region(-translation[0],-translation[1],-translation[2],image->get_xsize(),image->get_ysize(),image->get_zsize());
08689         } else throw ImageDimensionException("Only 1,2 and 3D images are supported");
08690 
08691         return clip_region;
08692 }
08693 
08694 void IntTranslateProcessor::process_inplace(EMData* image) {
08695 
08696         vector<int> translation = params.set_default("trans",vector<int>() );
08697 
08698 
08699         assert_valid_aspect(translation,image);
08700 
08701         Region clip_region = get_clip_region(translation,image);
08702 
08703         image->clip_inplace(clip_region,0);
08704         // clip_inplace does the update!
08705 }
08706 
08707 EMData* IntTranslateProcessor::process(const EMData* const image) {
08708 
08709         vector<int> translation = params.set_default("trans",vector<int>() );
08710 
08711         assert_valid_aspect(translation,image);
08712 
08713         Region clip_region = get_clip_region(translation,image);
08714 
08715         return image->get_clip(clip_region,0);
08716         // clip_inplace does the update!
08717 }
08718 
08719 
08720 void ScaleTransformProcessor::process_inplace(EMData* image) {
08721         int ndim = image->get_ndim();
08722         if (ndim != 2 && ndim != 3) throw UnexpectedBehaviorException("The Scale Transform processors only works for 2D and 3D images");
08723 
08724         if ( image->get_xsize() != image->get_ysize()) {
08725                 throw ImageDimensionException("x size and y size of image do not match. This processor only works for uniformly sized data");
08726         }
08727         if ( ndim == 3 ) {
08728                 if ( image->get_xsize() != image->get_zsize()) {
08729                 throw ImageDimensionException("x size and z size of image do not match. This processor only works for uniformly sized data");
08730                 }
08731         }
08732 
08733         float scale = params.set_default("scale",0.0f);
08734         if (scale <= 0.0f) throw InvalidParameterException("The scale parameter must be greater than 0");
08735 
08736         int clip = 0;
08737 
08738         if(params.has_key("clip"))
08739         {
08740                 clip = params["clip"];
08741                 if (clip < 0) throw InvalidParameterException("The clip parameter must be greater than 0"); // If it's zero it's not used
08742         }
08743         else
08744         {
08745                 clip = (int)(scale*image->get_xsize());
08746         }
08747 
08748         Region r;
08749         if (ndim == 3) {
08750                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2,clip, clip,clip);
08751         } else { // ndim == 2 guaranteed by check at beginning of function
08752                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, clip, clip);
08753         }
08754 
08755         if (scale > 1) {
08756                 if ( clip != 0) {
08757                         image->clip_inplace(r);
08758                 }
08759                 Transform t;
08760                 t.set_scale(scale);
08761                 image->process_inplace("xform",Dict("transform",&t));
08762         } else if (scale < 1) {
08763                 Transform t;
08764                 t.set_scale(scale);
08765                 image->process_inplace("xform",Dict("transform",&t));
08766                 if ( clip != 0) {
08767                         image->clip_inplace(r);
08768                 }
08769         } else {
08770                 if ( clip != 0) {
08771                         image->clip_inplace(r);
08772                 }
08773         }
08774 }
08775 
08776 EMData* ScaleTransformProcessor::process(const EMData* const image) {
08777         int ndim = image->get_ndim();
08778         if (ndim != 2 && ndim != 3) throw UnexpectedBehaviorException("The Scale Transform processors only works for 2D and 3D images");
08779 
08780         if ( image->get_xsize() != image->get_ysize()) {
08781                 throw ImageDimensionException("x size and y size of image do not match. This processor only works for uniformly sized data");
08782         }
08783         if ( ndim == 3 ) {
08784                 if ( image->get_xsize() != image->get_zsize()) {
08785                 throw ImageDimensionException("x size and z size of image do not match. This processor only works for uniformly sized data");
08786                 }
08787         }
08788 
08789         float scale = params.set_default("scale",0.0f);
08790         if (scale <= 0.0f) throw InvalidParameterException("The scale parameter must be greater than 0");
08791 
08792         int clip = 0;
08793 
08794         if(params.has_key("clip"))
08795         {
08796                 clip = params["clip"];
08797                 if (clip < 0) throw InvalidParameterException("The clip parameter must be greater than 0"); // If it's zero it's not used
08798         }
08799         else
08800         {
08801                 clip = (int)(scale*image->get_xsize());
08802         }
08803 
08804         Region r;
08805         if (ndim == 3) {
08806                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2,clip, clip,clip);
08807         } else { // ndim == 2 guaranteed by check at beginning of function
08808                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, clip, clip);
08809         }
08810 
08811         EMData* ret = 0;
08812         if (scale > 1) {
08813                 if ( clip != 0) {
08814                         ret = image->get_clip(r);
08815                 }
08816                 Transform t;
08817                 t.set_scale(scale);
08818                 if (ret != 0) {
08819                         ret->process_inplace("xform",Dict("transform",&t));
08820                 } else {
08821                         ret = image->process("xform",Dict("transform",&t));
08822                 }
08823         } else if (scale < 1) {
08824                 Transform t;
08825                 t.set_scale(scale);
08826                 ret = image->process("xform",Dict("transform",&t));
08827                 if ( clip != 0) {
08828                         ret->clip_inplace(r);
08829                 }
08830         } else {
08831                 if ( clip != 0) {
08832                         ret = image->get_clip(r);
08833                 } else {
08834                         ret = image->copy();
08835                 }
08836         }
08837         return ret;
08838 
08839 }
08840 
08841 void Rotate180Processor::process_inplace(EMData* image) {
08842         ENTERFUNC;
08843 
08844 
08845         if (image->get_ndim() != 2) {
08846                 throw ImageDimensionException("2D only");
08847         }
08848 
08849 #ifdef EMAN2_USING_CUDA
08850         if (EMData::usecuda == 1 && image->getcudarwdata()) {
08851                 //cout << "CUDA rotate 180" << endl;
08852                 emdata_rotate_180(image->getcudarwdata(), image->get_xsize(), image->get_ysize());
08853                 EXITFUNC;
08854                 return;
08855         }
08856 #endif
08857 
08858         float *d = image->get_data();
08859         int nx = image->get_xsize();
08860         int ny = image->get_ysize();
08861 
08862         // x and y offsets are used to handle even vs odd cases
08863         int x_offset = 0;
08864         if (nx % 2 == 1) x_offset=1;
08865         int y_offset = 0;
08866         if (ny % 2 == 1) y_offset=1;
08867 
08868         bool stop = false;
08869         for (int x = 1; x <= (nx/2+x_offset); x++) {
08870                 int y = 0;
08871                 for (y = 1; y < (ny+y_offset); y++) {
08872                         if (x == (nx / 2+x_offset) && y == (ny / 2+y_offset)) {
08873                                 stop = true;
08874                                 break;
08875                         }
08876                         int i = (x-x_offset) + (y-y_offset) * nx;
08877                         int k = nx - x + (ny - y) * nx;
08878 
08879                         float t = d[i];
08880                         d[i] = d[k];
08881                         d[k] = t;
08882                 }
08883                 if (stop) break;
08884         }
08885 
08886         /* Here we guard against irregularites that occur at the boundaries
08887          * of even dimensioned images. The basic policy is to replace the pixel
08888          * in row 0 and/or column 0 with those in row 1 and/or column 1, respectively.
08889          * The pixel at 0,0 is replaced with the pixel at 1,1 if both image dimensions
08890          * are even. FIXME - it may be better to use an average at the corner, in
08891          * this latter case, using pixels (1,1), (0,1) and (1,0). I am not sure. (dsawoolford)
08892         */
08893         if (x_offset == 0) {
08894                 for (int y = 0; y < ny; y++) {
08895                         image->set_value_at_fast(0,y,image->get_value_at(1,y));
08896                 }
08897         }
08898 
08899         if (y_offset == 0) {
08900                 for (int x = 0; x < nx; x++) {
08901                         image->set_value_at_fast(x,0,image->get_value_at(x,1));
08902                 }
08903         }
08904 
08905         if (y_offset == 0 && x_offset == 0) {
08906                 image->set_value_at_fast(0,0,image->get_value_at(1,1));
08907         }
08908 
08909         image->update();
08910         EXITFUNC;
08911 }
08912 
08913 
08914 void ClampingProcessor::process_inplace( EMData* image )
08915 {
08916 
08917         if ( image->is_complex() ) throw ImageFormatException("Error: clamping processor does not work on complex images");
08918 
08919         float min = params.set_default("minval",default_min);
08920         float max = params.set_default("maxval",default_max);
08921         bool tomean = params.set_default("tomean",false);
08922         float new_min_vals = min;
08923         float new_max_vals = max;
08924         if (tomean){
08925 
08926                 new_min_vals = image->get_attr("mean");
08927                 new_max_vals = image->get_attr("mean");
08928         }
08929 
08930         // Okay, throwing such an error is probably overkill - but atleast the user will get a loud message
08931         // saying what went wrong.
08932         if ( max < min ) throw InvalidParameterException("Error: minval was greater than maxval, aborting");
08933 
08934         size_t size = image->get_size();
08935         for(size_t i = 0; i < size; ++i )
08936         {
08937                 float * data = &image->get_data()[i];
08938                 if ( *data < min ) *data = new_min_vals;
08939                 else if ( *data > max ) *data = new_max_vals;
08940         }
08941         image->update();
08942 }
08943 
08944 void TestTomoImage::insert_rectangle( EMData* image, const Region& region, const float& value, const Transform& t3d )
08945 {
08946         int startx = (int)region.origin[0] - (int)region.size[0]/2;
08947         int starty = (int)region.origin[1] - (int)region.size[1]/2;
08948         int startz = (int)region.origin[2] - (int)region.size[2]/2;
08949 
08950         int endx  = (int)region.origin[0] + (int)region.size[0]/2;
08951         int endy  = (int)region.origin[1] + (int)region.size[1]/2;
08952         int endz  = (int)region.origin[2] + (int)region.size[2]/2;
08953 
08954         if ( ! t3d.is_identity() ) {
08955                 float xt, yt, zt;
08956                 for ( float z = (float)startz; z < (float)endz; z += 0.25f ) {
08957                         for ( float y = (float)starty; y < (float)endy; y += 0.25f ) {
08958                                 for ( float x = (float)startx; x < (float)endx; x += 0.25f ) {
08959                                         xt = (float) x - region.origin[0];
08960                                         yt = (float) y - region.origin[1];
08961                                         zt = (float) z - region.origin[2];
08962                                         Vec3f v((float)xt,(float)yt,(float)zt);
08963                                         v = t3d*v;
08964                                         image->set_value_at((int)(v[0]+region.origin[0]),(int)(v[1]+region.origin[1]),(int)(v[2]+region.origin[2]), value);
08965                                 }
08966                         }
08967                 }
08968         } else {
08969                 for ( int z = startz; z < endz; ++z ) {
08970                         for ( int y = starty; y < endy; ++y ) {
08971                                 for ( int x = startx; x < endx; ++x ) {
08972                                         image->set_value_at(x,y,z, value);
08973                                 }
08974                         }
08975                 }
08976         }
08977 }
08978 
08979 void TestTomoImage::process_inplace( EMData* image )
08980 {
08981         //float nx = 240;
08982         //float ny = 240;
08983         //float nz = 60;
08984 
08985         //image->set_size((int)nx,(int)ny,(int)nz);
08986         float nx = (float) image->get_xsize();
08987         float ny = (float) image->get_ysize();
08988         float nz = (float) image->get_zsize();
08989 
08990         // This increment is used to simplified positioning
08991         // It's an incremental factor that matches the grid size of the paper
08992         // that I drew this design on before implementing it in code
08993         float inc = 1.0f/22.0f;
08994         float xinc = inc;
08995         float yinc = inc;
08996         float zinc = inc;
08997 
08998         Dict d;
08999         d["a"] = (float) .4*nx+3;
09000         d["b"] = (float) .4*ny+3;
09001         d["c"] = (float) .4*nz+3;
09002         d["fill"] = 0.2;
09003         image->process_inplace("testimage.ellipsoid",d);
09004 
09005         d["a"] = (float) .4*nx;
09006         d["b"] = (float) .4*ny;
09007         d["c"] = (float) .4*nz;
09008         d["fill"] = 0.1;
09009         image->process_inplace("testimage.ellipsoid",d);
09010 
09011         // Center x, center z, bottom y ellipsoids that grow progessively smaller
09012         {
09013                 Transform t;
09014                 t.set_trans(0.,ny*4.0f*yinc-ny/2,0);
09015                 Dict d;
09016                 d["transform"] = &t;
09017                 d["a"] = (float) 2.*xinc*nx;
09018                 d["b"] = (float)0.5*yinc*ny;
09019                 d["c"] = (float) 1.*zinc*nz;
09020                 d["fill"] = 0.3;
09021                 image->process_inplace("testimage.ellipsoid",d);
09022         }
09023 
09024         {
09025                 Transform t;
09026                 t.set_trans(0.,ny*5.5f*yinc-ny/2,0);
09027                 Dict d;
09028                 d["transform"] = &t;
09029                 d["a"] = (float) 1.5*xinc*nx;
09030                 d["b"] = (float)0.5*yinc*ny;
09031                 d["c"] = (float) 1.*zinc*nz;
09032                 d["fill"] = 0.0;
09033                 image->process_inplace("testimage.ellipsoid",d);
09034         }
09035         {
09036                 Transform t;
09037                 t.set_trans(0.,ny*7*yinc-ny/2,0);
09038                 Dict d;
09039                 d["transform"] = &t;
09040                 d["a"] = (float) 1.*xinc*nx;
09041                 d["b"] = (float)0.5*yinc*ny;
09042                 d["c"] = (float) 1.*zinc*nz;
09043                 d["fill"] = 0.3;
09044                 image->process_inplace("testimage.ellipsoid",d);
09045         }
09046 
09047 
09048         {
09049                 Transform t;
09050                 t.set_trans(0.,ny*8.5f*yinc-ny/2,0);
09051                 Dict d;
09052                 d["transform"] = &t;
09053                 d["a"] = (float) .75*xinc*nx;
09054                 d["b"] = (float)0.5*yinc*ny;
09055                 d["c"] = (float) 1.*zinc*nz;
09056                 d["fill"] = 0.0;
09057                 image->process_inplace("testimage.ellipsoid",d);
09058         }
09059 
09060         // Center x, center z, bottom y ellipsoids that grow progessively smaller
09061         {
09062                 Transform t;
09063                 t.set_trans(0.,ny*18*yinc-ny/2,0);
09064                 Dict d;
09065                 d["transform"] = &t;
09066                 d["a"] = (float) 2*xinc*nx;
09067                 d["b"] = (float)0.5*yinc*ny;
09068                 d["c"] = (float) 1.*zinc*nz;
09069                 d["fill"] = 0.3;
09070                 image->process_inplace("testimage.ellipsoid",d);
09071         }
09072 
09073         {
09074                 Transform t;
09075                 t.set_trans(0.,ny*16.5f*yinc-ny/2,0);
09076                 Dict d;
09077                 d["transform"] = &t;
09078                 d["a"] = (float) 1.5*xinc*nx;
09079                 d["b"] = (float)0.5*yinc*ny;
09080                 d["c"] = (float) 1.*zinc*nz;
09081                 d["fill"] = 0.3;
09082                 image->process_inplace("testimage.ellipsoid",d);
09083         }
09084 
09085         {
09086                 Transform t;
09087                 t.set_trans(0.,ny*15*yinc-ny/2,0);
09088                 Dict d;
09089                 d["transform"] = &t;
09090                 d["a"] = (float) 1*xinc*nx;
09091                 d["b"] = (float)0.5*yinc*ny;
09092                 d["c"] = (float) 1.*zinc*nz;
09093                 d["fill"] = 0.3f;
09094                 image->process_inplace("testimage.ellipsoid",d);
09095         }
09096 
09097         {
09098                 Transform t;
09099                 t.set_trans(0.,ny*13.5f*yinc-ny/2,0);
09100                 Dict d;
09101                 d["transform"] = &t;
09102                 d["a"] = (float).75*xinc*nx;
09103                 d["b"] = (float)0.5*yinc*ny;
09104                 d["c"] = (float) 1.*zinc*nz;
09105                 d["fill"] = 0.3;
09106                 image->process_inplace("testimage.ellipsoid",d);
09107         }
09108 
09109         // Left ellipsoids from the bottom up
09110         {
09111 
09112                 Transform t;
09113                 t.set_trans(nx*6*xinc-nx/2,ny*5*yinc-ny/2,0);
09114                 Dict d;
09115                 d["transform"] = &t;
09116                 d["a"] = (float)1*xinc*nx;
09117                 d["b"] = (float).75*yinc*ny;
09118                 d["c"] = (float) .75*zinc*nz;
09119                 d["fill"] = 0.25;
09120                 image->process_inplace("testimage.ellipsoid",d);
09121         }
09122 
09123         {
09124                 Transform t;
09125                 t.set_trans(nx*6*xinc-nx/2,ny*7*yinc-ny/2,0);
09126                 Dict d;
09127                 d["transform"] = &t;
09128                 d["a"] = (float)1.5*xinc*nx;
09129                 d["b"] = (float).75*yinc*ny;
09130                 d["c"] = (float) .75*zinc*nz;
09131                 d["fill"] = 0.25;
09132                 image->process_inplace("testimage.ellipsoid",d);
09133         }
09134 
09135         {
09136                 Transform t;
09137                 t.set_trans(nx*6*xinc-nx/2,ny*9*yinc-ny/2,0);
09138                 Dict d;
09139                 d["transform"] = &t;
09140                 d["a"] = (float)2*xinc*nx;
09141                 d["b"] = (float).75*yinc*ny;
09142                 d["c"] = (float) .75*zinc*nz;
09143                 d["fill"] = 0.25;
09144                 image->process_inplace("testimage.ellipsoid",d);
09145         }
09146 
09147         {
09148                 Transform t;
09149                 t.set_trans(nx*6*xinc-nx/2,ny*11*yinc-ny/2,0);
09150                 Dict d;
09151                 d["transform"] = &t;
09152                 d["a"] = (float)2.5*xinc*nx;
09153                 d["b"] = (float).75*yinc*ny;
09154                 d["c"] = (float) 1*zinc*nz;
09155                 d["fill"] = 0.25;
09156                 image->process_inplace("testimage.ellipsoid",d);
09157         }
09158 
09159         {
09160                 Transform t;
09161                 t.set_trans(nx*6*xinc-nx/2,ny*13*yinc-ny/2,0);
09162                 Dict d;
09163                 d["transform"] = &t;
09164                 d["a"] = (float) 3*xinc*nx;
09165                 d["b"] = (float).75*yinc*ny;
09166                 d["c"] = (float) 1*zinc*nz;
09167                 d["fill"] = 0.25;
09168                 image->process_inplace("testimage.ellipsoid",d);
09169         }
09170 
09171         // Right rectangle from the top down
09172         {
09173                 Region region(nx*15.*inc,ny*17.*inc,nz/2.,1.*inc*nx,1.5*inc*ny,1.5*inc*nz);
09174                 insert_rectangle(image, region, 0.25);
09175         }
09176         {
09177                 Region region(nx*15.*inc,ny*15.*inc,nz/2.,1.5*inc*nx,1.5*inc*ny,1.5*inc*nz);
09178                 insert_rectangle(image, region, 0.25);
09179         }
09180         {
09181                 Region region(nx*15.*inc,ny*13.*inc,nz/2.,2.*inc*nx,1.5*inc*ny,1.5*inc*nz);
09182                 insert_rectangle(image, region, 0.25);
09183         }
09184         {
09185                 Region region(nx*15.*inc,ny*11.*inc,nz/2.,2.5*inc*nx,1.5*inc*ny,1.5*inc*nz);
09186                 insert_rectangle(image, region, 0.25);
09187         }
09188         {
09189                 Region region(nx*15.*inc,ny*9.*inc,nz/2.,3.*inc*nx,1.5*inc*ny,1.5*inc*nz);
09190                 insert_rectangle(image, region, 0.25);
09191         }
09192 
09193         // Center rotated rectangle
09194         {
09195                 Region region(nx/2.,ny/2.,nz/2.,2.*inc*nx,2.5*inc*ny,1.*inc*nz);
09196                 Transform t3d(Dict("type","eman","az",(float)-25.0));
09197                 insert_rectangle(image, region, 0.4f, t3d);
09198         }
09199 
09200         // Rotated ellipsoids
09201         {
09202                 Transform t;
09203                 t.set_trans(nx*6.8f*xinc-nx/2,ny*16*yinc-ny/2,0);
09204                 Dict rot;
09205                 rot["type"] = "eman";
09206                 rot["az"] = 43.0f;
09207                 t.set_rotation(rot);
09208                 Dict d;
09209                 d["transform"] = &t;
09210                 d["a"] = (float) 1.5*xinc*nx;
09211                 d["b"] = (float) .5*yinc*ny;
09212                 d["c"] = (float) .5*zinc*nz;
09213                 d["fill"] = 0.2;
09214                 image->process_inplace("testimage.ellipsoid",d);
09215         }
09216         {
09217                 Transform t;
09218                 t.set_trans(nx*7.2f*xinc-nx/2,ny*16*yinc-ny/2,0);
09219                 Dict rot;
09220                 rot["type"] = "eman";
09221                 rot["az"] = 135.0f;
09222                 t.set_rotation(rot);
09223                 Dict d;
09224                 d["transform"] = &t;
09225                 d["a"] = (float) 1.5*xinc*nx;
09226                 d["b"] = (float) .5*yinc*ny;
09227                 d["c"] = (float) .5*zinc*nz;
09228                 d["fill"] = 0.3;
09229                 image->process_inplace("testimage.ellipsoid",d);
09230         }
09231 
09232         // Dense small ellipsoids
09233         {
09234                 Transform t;
09235                 t.set_trans(nx*3.5f*xinc-nx/2,ny*8*yinc-ny/2,0);
09236                 Dict d;
09237                 d["transform"] = &t;
09238                 d["a"] = (float) .5*xinc*nx;
09239                 d["b"] = (float) .5*yinc*ny;
09240                 d["c"] = (float) .5*zinc*nz;
09241                 d["fill"] = 2.05;
09242                 image->process_inplace("testimage.ellipsoid",d);
09243 
09244                 t.set_trans(nx*8*xinc-nx/2,ny*18*yinc-ny/2,0);
09245                 image->process_inplace("testimage.ellipsoid",d);
09246 
09247                 t.set_trans(nx*14*xinc-nx/2,ny*18.2f*yinc-ny/2,0);
09248                 image->process_inplace("testimage.ellipsoid",d);
09249 
09250                 t.set_trans(nx*18*xinc-nx/2,ny*14*yinc-ny/2,0);
09251                 image->process_inplace("testimage.ellipsoid",d);
09252 
09253                 t.set_trans(nx*17*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
09254                 image->process_inplace("testimage.ellipsoid",d);
09255         }
09256 
09257 
09258         // Dense small rectangles
09259         {
09260                 Region region(nx*18.*inc,ny*11.5*inc,nz/2.,1.*inc*nx,1.*inc*ny,1.*inc*nz);
09261                 Transform t3d(Dict("type","eman","az",(float)45.0));
09262                 insert_rectangle(image, region, 1.45f, t3d);
09263         }
09264         {
09265                 Region region(nx*3.*inc,ny*10.5*inc,nz/2.,1.*inc*nx,1.*inc*ny,1.*inc*nz);
09266                 Transform t3d(Dict("type","eman","az",(float)45.0));
09267                 insert_rectangle(image, region, 1.45f, t3d);
09268         }
09269 
09270         // Insert small cluster of spheres
09271         {
09272                 Transform t;
09273                 t.set_trans(nx*14*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
09274                 Dict d;
09275                 d["transform"] = &t;
09276                 d["a"] = (float) .5*xinc*nx;
09277                 d["b"] = (float) .5*yinc*ny;
09278                 d["c"] = (float) .5*zinc*nz;
09279                 d["fill"] = .35;
09280                 image->process_inplace("testimage.ellipsoid",d);
09281         }
09282         {
09283                 Transform t;
09284                 t.set_trans(nx*15*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
09285                 Dict d;
09286                 d["transform"] = &t;
09287                 d["a"] = (float) .25*xinc*nx;
09288                 d["b"] = (float) .25*yinc*ny;
09289                 d["c"] = (float) .25*zinc*nz;
09290                 d["fill"] = .35;
09291                 image->process_inplace("testimage.ellipsoid",d);
09292 
09293                 t.set_trans(nx*13.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
09294                 image->process_inplace("testimage.ellipsoid",d);
09295 
09296                 t.set_trans(nx*14.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
09297                 image->process_inplace("testimage.ellipsoid",d);
09298 
09299                 t.set_trans(nx*15.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
09300                 image->process_inplace("testimage.ellipsoid",d);
09301 
09302                 t.set_trans(nx*14*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09303                 image->process_inplace("testimage.ellipsoid",d);
09304 
09305                 t.set_trans(nx*14*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09306                 image->process_inplace("testimage.ellipsoid",d);
09307 
09308                 t.set_trans(nx*15*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09309                 image->process_inplace("testimage.ellipsoid",d);
09310 
09311                 t.set_trans(nx*16*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09312                 image->process_inplace("testimage.ellipsoid",d);
09313 
09314                 t.set_trans(nx*14.5f*xinc-nx/2,ny*4.5f*yinc-ny/2,0);
09315                 image->process_inplace("testimage.ellipsoid",d);
09316 
09317                 t.set_trans(nx*15.5f*xinc-nx/2,ny*4.5f*yinc-ny/2,0);
09318                 image->process_inplace("testimage.ellipsoid",d);
09319         }
09320         // Insert feducials around the outside of the "cell"
09321 //      for ( float i = 0.; i < 3.; i += 1. ) {
09322 //              for ( float j = 0.; j < 3.; j += 1. ) {
09323 //                      Region region(nx*2.+i*inc,ny*2.+j*inc,nz/2.,0.05*inc*nx,0.05*inc*ny,0.05*inc*nz);
09324 //                      insert_solid_ellipse(image, region, 2.0);
09325 //              }
09326 //      }
09327 
09328 }
09329 
09330 void NSigmaClampingProcessor::process_inplace(EMData *image)
09331 {
09332         float nsigma = params.set_default("nsigma",default_sigma);
09333         float sigma = image->get_attr("sigma");
09334         float mean = image->get_attr("mean");
09335         params.set_default("minval",mean - nsigma*sigma);
09336         params.set_default("maxval",mean + nsigma*sigma);
09337 
09338         ClampingProcessor::process_inplace(image);
09339 }
09340 
09341 void HistogramBin::process_inplace(EMData *image)
09342 {
09343         float min = image->get_attr("minimum");
09344         float max = image->get_attr("maximum");
09345         float nbins = (float)params.set_default("nbins",default_bins);
09346         bool debug = params.set_default("debug",false);
09347 
09348         vector<int> debugscores;
09349         if ( debug ) {
09350                 debugscores = vector<int>((int)nbins, 0);
09351         }
09352 
09353         if ( nbins < 0 ) throw InvalidParameterException("nbins must be greater than 0");
09354 
09355         float bin_width = (max-min)/nbins;
09356         float bin_val_offset = bin_width/2.0f;
09357 
09358         size_t size = image->get_size();
09359         float* dat = image->get_data();
09360 
09361         for(size_t i = 0; i < size; ++i ) {
09362                 float val = dat[i];
09363                 val -= min;
09364                 int bin = (int) (val/bin_width);
09365 
09366                 // This makes the last interval [] and not [)
09367                 if (bin == nbins) bin -= 1;
09368 
09369                 dat[i] = min + bin*bin_width + bin_val_offset;
09370                 if ( debug ) {
09371                         debugscores[bin]++;
09372                 }
09373         }
09374 
09375         if ( debug ) {
09376                 int i = 0;
09377                 for( vector<int>::const_iterator it = debugscores.begin(); it != debugscores.end(); ++it, ++i)
09378                         cout << "Bin " << i << " has " << *it << " pixels in it" << endl;
09379         }
09380 
09381 }
09382 void ConvolutionProcessor::process_inplace(EMData* image)
09383 {
09384         //bool complexflag = false;
09385         EMData* null = 0;
09386         EMData* with = params.set_default("with", null);
09387         if ( with == NULL ) throw InvalidParameterException("Error - the image required for the convolution is null");
09388 
09389         EMData* newimage = fourierproduct(image, with, CIRCULANT, CONVOLUTION, false);
09390 
09391         float* orig = image->get_data();
09392         float* work = newimage->get_data();
09393         int nx  = image->get_xsize();
09394         int ny  = image->get_ysize();
09395         int nz  = image->get_zsize();
09396         memcpy(orig,work,nx*ny*nz*sizeof(float));
09397         image->update();
09398 
09399         delete newimage;
09400 }
09401 
09402 void XGradientProcessor::process_inplace( EMData* image )
09403 {
09404         if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
09405 
09406         EMData* e = new EMData();
09407         int nx = image->get_xsize();
09408         int ny = image->get_ysize();
09409         int nz = image->get_zsize();
09410 
09411         if ( nz == 1 && ny == 1 ) {
09412                 if ( nx < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09413 
09414                 e->set_size(3,1,1);
09415                 e->set_value_at(0,-1);
09416                 e->set_value_at(2, 1);
09417 
09418                 Region r = Region(-nx/2+1,nx);
09419                 e->clip_inplace(r);
09420         } else if ( nz == 1 ) {
09421                 if ( nx < 3 || ny < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09422                 e->set_size(3,3,1);
09423                 e->set_value_at(0,0,-1);
09424                 e->set_value_at(0,1,-2);
09425                 e->set_value_at(0,2,-1);
09426 
09427                 e->set_value_at(2,0,1);
09428                 e->set_value_at(2,1,2);
09429                 e->set_value_at(2,2,1);
09430                 Region r = Region(-nx/2+1,-ny/2+1,nx,ny);
09431                 e->clip_inplace(r);
09432         } else {
09433                 if ( nx < 3 || ny < 3 || nz < 3) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09434                 e->set_size(3,3,3);
09435                 e->set_value_at(0,0,0,-1);
09436                 e->set_value_at(0,1,0,-1);
09437                 e->set_value_at(0,2,0,-1);
09438                 e->set_value_at(0,0,1,-1);
09439                 e->set_value_at(0,1,1,-8);
09440                 e->set_value_at(0,2,1,-1);
09441                 e->set_value_at(0,0,2,-1);
09442                 e->set_value_at(0,1,2,-1);
09443                 e->set_value_at(0,2,2,-1);
09444 
09445                 e->set_value_at(2,0,0,1);
09446                 e->set_value_at(2,1,0,1);
09447                 e->set_value_at(2,2,0,1);
09448                 e->set_value_at(2,0,1,1);
09449                 e->set_value_at(2,1,1,8);
09450                 e->set_value_at(2,2,1,1);
09451                 e->set_value_at(2,0,2,1);
09452                 e->set_value_at(2,1,2,1);
09453                 e->set_value_at(2,2,2,1);
09454 
09455                 Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
09456                 e->clip_inplace(r);
09457         }
09458 
09459         Dict conv_parms;
09460         conv_parms["with"] = e;
09461         image->process_inplace("math.convolution", conv_parms);
09462         image->process_inplace("xform.phaseorigin.tocenter");
09463 
09464         delete e;
09465 }
09466 
09467 
09468 void TomoTiltAngleWeightProcessor::process_inplace( EMData* image )
09469 {
09470         bool fim = params.set_default("angle_fim", false);
09471         float alt;
09472         if ( fim ) {
09473                 alt = image->get_attr("euler_alt");
09474         }
09475         else alt = params.set_default("angle", 0.0f);
09476 
09477         float cosine = cos(alt*M_PI/180.0f);
09478         float mult_fac =  1.0f/(cosine);
09479         image->mult( mult_fac );
09480 }
09481 
09482 void TomoTiltEdgeMaskProcessor::process_inplace( EMData* image )
09483 {
09484         bool biedgemean = params.set_default("biedgemean", false);
09485         bool edgemean = params.set_default("edgemean", false);
09486         // You can only do one of these - so if someone specifies them both the code complains loudly
09487         if (biedgemean && edgemean) throw InvalidParameterException("The edgemean and biedgemean options are mutually exclusive");
09488 
09489         bool fim = params.set_default("angle_fim", false);
09490         float alt;
09491         if ( fim ) {
09492                 Transform* t = (Transform*)image->get_attr("xform.projection");
09493                 Dict d = t->get_params("eman");
09494                 alt = (float) d["alt"];
09495                 if(t) {delete t; t=0;}
09496         }
09497         else alt = params.set_default("angle", 0.0f);
09498 
09499 
09500         float cosine = cos(alt*M_PI/180.0f);
09501 
09502         // Zero the edges
09503         int nx = image->get_xsize();
09504         int ny = image->get_ysize();
09505         int x_clip = static_cast<int>( (float) nx * ( 1.0 - cosine ) / 2.0);
09506 
09507         float x1_edge_mean = 0.0;
09508         float x2_edge_mean = 0.0;
09509 
09510         if ( biedgemean )
09511         {
09512                 float edge_mean = 0.0;
09513 
09514                 // Accrue the pixel densities on the side strips
09515                 for ( int i = 0; i < ny; ++i ) {
09516                         edge_mean += image->get_value_at(x_clip, i );
09517                         edge_mean += image->get_value_at(nx - x_clip-1, i );
09518                 }
09519                 // Now make it so the mean is stored
09520                 edge_mean /= 2*ny;
09521 
09522                 // Now shift pixel values accordingly
09523                 for ( int i = 0; i < ny; ++i ) {
09524                         for ( int j = nx-1; j >= nx - x_clip; --j) {
09525                                 image->set_value_at(j,i,edge_mean);
09526                         }
09527                         for ( int j = 0; j < x_clip; ++j) {
09528                                 image->set_value_at(j,i,edge_mean);
09529                         }
09530                 }
09531                 x1_edge_mean = edge_mean;
09532                 x2_edge_mean = edge_mean;
09533         }
09534         else if (edgemean)
09535         {
09536                 for ( int i = 0; i < ny; ++i ) {
09537                         x1_edge_mean += image->get_value_at(x_clip, i );
09538                         x2_edge_mean += image->get_value_at(nx - x_clip-1, i );
09539                 }
09540                 x1_edge_mean /= ny;
09541                 x2_edge_mean /= ny;
09542 
09543                 for ( int i = 0; i < ny; ++i ) {
09544                         for ( int j = 0; j < x_clip; ++j) {
09545                                 image->set_value_at(j,i,x1_edge_mean);
09546                         }
09547                         for ( int j = nx-1; j >= nx - x_clip; --j) {
09548                                 image->set_value_at(j,i,x2_edge_mean);
09549                         }
09550                 }
09551         }
09552         else
09553         {
09554                 // The edges are just zeroed -
09555                 Dict zero_dict;
09556                 zero_dict["x0"] = x_clip;
09557                 zero_dict["x1"] = x_clip;
09558                 zero_dict["y0"] = 0;
09559                 zero_dict["y1"] = 0;
09560                 image->process_inplace( "mask.zeroedge2d", zero_dict );
09561         }
09562 
09563         int gauss_rad = params.set_default("gauss_falloff", 0);
09564         if ( gauss_rad != 0)
09565         {
09566                 // If the gaussian falloff distance is greater than x_clip, it will technically
09567                 // go beyond the image boundaries. Thus we clamp gauss_rad so this cannot happen.
09568                 // Therefore, there is potential here for (benevolent) unexpected behavior.
09569                 if ( gauss_rad > x_clip ) gauss_rad = x_clip;
09570 
09571                 float gauss_sigma = params.set_default("gauss_sigma", 3.0f);
09572                 if ( gauss_sigma < 0 ) throw InvalidParameterException("Error - you must specify a positive, non-zero gauss_sigma");
09573                 float sigma = (float) gauss_rad/gauss_sigma;
09574 
09575                 GaussianFunctoid gf(sigma);
09576 
09577                 for ( int i = 0; i < ny; ++i ) {
09578 
09579                         float left_value = image->get_value_at(x_clip, i );
09580                         float scale1 = left_value-x1_edge_mean;
09581 
09582                         float right_value = image->get_value_at(nx - x_clip - 1, i );
09583                         float scale2 = right_value-x2_edge_mean;
09584 
09585                         for ( int j = 1; j < gauss_rad; ++j )
09586                         {
09587                                 image->set_value_at(x_clip-j, i, scale1*gf((float)j)+x1_edge_mean );
09588                                 image->set_value_at(nx - x_clip + j-1, i, scale2*gf((float)j)+x2_edge_mean);
09589                         }
09590                 }
09591         }
09592 
09593         image->update();
09594 }
09595 
09596 void YGradientProcessor::process_inplace( EMData* image )
09597 {
09598         if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
09599 
09600         EMData* e = new EMData();
09601         int nx = image->get_xsize();
09602         int ny = image->get_ysize();
09603         int nz = image->get_zsize();
09604 
09605         if ( nz == 1 && ny == 1 ) {
09606                 throw ImageDimensionException("Error - cannot detect Y edges for an image that that is 1D!");
09607         } else if ( nz == 1 ) {
09608                 if ( nx < 3 || ny < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09609                 e->set_size(3,3,1);
09610                 e->set_value_at(0,0,-1);
09611                 e->set_value_at(1,0,-2);
09612                 e->set_value_at(2,0,-1);
09613 
09614                 e->set_value_at(0,2,1);
09615                 e->set_value_at(1,2,2);
09616                 e->set_value_at(2,2,1);
09617                 Region r = Region(-nx/2+1,-ny/2+1,nx,ny);
09618                 e->clip_inplace(r);
09619         } else {
09620                 if ( nx < 3 || ny < 3 || nz < 3) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09621                 e->set_size(3,3,3);
09622                 e->set_value_at(0,0,0,-1);
09623                 e->set_value_at(1,0,0,-1);
09624                 e->set_value_at(2,0,0,-1);
09625                 e->set_value_at(0,0,1,-1);
09626                 e->set_value_at(1,0,1,-8);
09627                 e->set_value_at(2,0,1,-1);
09628                 e->set_value_at(0,0,2,-1);
09629                 e->set_value_at(1,0,2,-1);
09630                 e->set_value_at(2,0,2,-1);
09631 
09632                 e->set_value_at(0,2,0,1);
09633                 e->set_value_at(1,2,0,1);
09634                 e->set_value_at(2,2,0,1);
09635                 e->set_value_at(0,2,1,1);
09636                 e->set_value_at(1,2,1,8);
09637                 e->set_value_at(2,2,1,1);
09638                 e->set_value_at(0,2,2,1);
09639                 e->set_value_at(1,2,2,1);
09640                 e->set_value_at(2,2,2,1);
09641 
09642                 Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
09643                 e->clip_inplace(r);
09644         }
09645 
09646         Dict conv_parms;
09647         conv_parms["with"] = e;
09648         image->process_inplace("math.convolution", conv_parms);
09649 
09650         delete e;
09651 }
09652 
09653 
09654 void ZGradientProcessor::process_inplace( EMData* image )
09655 {
09656         if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
09657 
09658         EMData* e = new EMData();
09659         int nx = image->get_xsize();
09660         int ny = image->get_ysize();
09661         int nz = image->get_zsize();
09662 
09663         if ( nx < 3 || ny < 3 || nz < 3) throw ImageDimensionException("Error - cannot edge detect in the z direction with any dimension being less than three pixels");
09664 
09665         e->set_size(3,3,3);
09666         e->set_value_at(0,0,0,-1);
09667         e->set_value_at(1,0,0,-1);
09668         e->set_value_at(2,0,0,-1);
09669         e->set_value_at(0,1,0,-1);
09670         e->set_value_at(1,1,0,-8);
09671         e->set_value_at(2,1,0,-1);
09672         e->set_value_at(0,2,0,-1);
09673         e->set_value_at(1,2,0,-1);
09674         e->set_value_at(2,2,0,-1);
09675 
09676         e->set_value_at(0,0,2,1);
09677         e->set_value_at(1,0,2,1);
09678         e->set_value_at(2,0,2,1);
09679         e->set_value_at(0,1,2,1);
09680         e->set_value_at(1,1,2,8);
09681         e->set_value_at(2,1,2,1);
09682         e->set_value_at(0,2,2,1);
09683         e->set_value_at(1,2,2,1);
09684         e->set_value_at(2,2,2,1);
09685 
09686         Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
09687         e->clip_inplace(r);
09688 
09689         Dict conv_parms;
09690         conv_parms["with"] = e;
09691         image->process_inplace("math.convolution", conv_parms);
09692 
09693         delete e;
09694 }
09695 
09696 void EMAN::dump_processors()
09697 {
09698         dump_factory < Processor > ();
09699 }
09700 
09701 map<string, vector<string> > EMAN::dump_processors_list()
09702 {
09703         return dump_factory_list < Processor > ();
09704 }
09705 
09706 map<string, vector<string> > EMAN::group_processors()
09707 {
09708         map<string, vector<string> > processor_groups;
09709 
09710         vector <string> processornames = Factory<Processor>::get_list();
09711 
09712         for (size_t i = 0; i < processornames.size(); i++) {
09713                 Processor * f = Factory<Processor>::get(processornames[i]);
09714                 if (dynamic_cast<RealPixelProcessor*>(f) != 0) {
09715                         processor_groups["RealPixelProcessor"].push_back(f->get_name());
09716                 }
09717                 else if (dynamic_cast<BoxStatProcessor*>(f)  != 0) {
09718                         processor_groups["BoxStatProcessor"].push_back(f->get_name());
09719                 }
09720                 else if (dynamic_cast<ComplexPixelProcessor*>(f)  != 0) {
09721                         processor_groups["ComplexPixelProcessor"].push_back(f->get_name());
09722                 }
09723                 else if (dynamic_cast<CoordinateProcessor*>(f)  != 0) {
09724                         processor_groups["CoordinateProcessor"].push_back(f->get_name());
09725                 }
09726                 else if (dynamic_cast<FourierProcessor*>(f)  != 0) {
09727                         processor_groups["FourierProcessor"].push_back(f->get_name());
09728                 }
09729                 else if (dynamic_cast<NewFourierProcessor*>(f)  != 0) {
09730                         processor_groups["FourierProcessor"].push_back(f->get_name());
09731                 }
09732                 else if (dynamic_cast<NormalizeProcessor*>(f)  != 0) {
09733                         processor_groups["NormalizeProcessor"].push_back(f->get_name());
09734                 }
09735                 else {
09736                         processor_groups["Others"].push_back(f->get_name());
09737                 }
09738         }
09739 
09740         return processor_groups;
09741 }
09742 
09743 
09744 
09745 /* vim: set ts=4 noet: */
09746 
09747 float ModelHelixProcessor::radprofile(float r, int type)
09748 //Ross Coleman: modified from EMAN1 Cylinder.C by Wen Jiang
09749 {
09750         // r in angstrom
09751         double ret = 0;//iterations ==> rounding is problematic with float types if 15 < r < 20 and really bad if 20 < r < 30
09752         if (type == 0) { // pure Gaussian falloff
09753                 r /= 2;
09754                 ret = exp(-r * r);
09755         } else if (type == 1) { // pure Gaussian falloff + negative dip, so mean is 0
09756                 r /= 2;
09757                 ret = (1 - r * r / 4) * exp(-r * r / 4);
09758         } else if (type == 2) {
09759                 // polynomial fitting to the radial profile of real helix density
09760                 // f=a0*x^n+a1+x^(n-1)+ ... +a[n-1]*x+an
09761                 //float an[11]={2.847024584977009e-10,-3.063997224364090e-08,1.418801040660860e-06,-3.678676414383996e-05,5.804871622801710e-04,-5.640340018430164e-03,3.208802421493864e-02,-9.068475313823952e-02,7.097329559749284e-02,-9.993347339658298e-02,1.000000000000000e+00};
09762 
09763                 // now the fitting to the original profile
09764                 if (r >= 12.2)
09765                         return 0; //We don't want that part of the polynomial --> goes way below zero
09766                 static float an[15] = { -3.9185246832229140e-16f,
09767                                 3.3957205298900993e-14f, 2.0343351971222658e-12f,
09768                                 -4.4935965816879751e-10f, 3.0668169835080933e-08f,
09769                                 -1.1904544689091790e-06f, 2.9753088549414953e-05f,
09770                                 -4.9802112876220150e-04f, 5.5900917825309360e-03f,
09771                                 -4.0823714462925299e-02f, 1.8021733669148599e-01f,
09772                                 -4.0992557296268717e-01f, 3.3980328566901458e-01f,
09773                                 -3.6062024812411908e-01f, 1.0000000000000000e+00f };
09774 
09775                 ret = an[0];
09776                 for (int i = 1; i < 15; i++) {
09777                         ret = ret * r + an[i];
09778                 }
09779         }
09780         return (float)ret;
09781 }
09782 
09783 void ModelEMCylinderProcessor::process_inplace(EMData * in)
09784 //Ross Coleman: modified from EMAN1 Cylinder.C by Wen Jiang
09785 {
09786         // synthesize model alpha helix, len is Angstrom, default to 2 turns
09787         //The helical axis is parallel to the z axis.
09788         EMData * cyl = in;
09789         int nx = cyl->get_xsize();
09790         int ny = cyl->get_ysize();
09791         int nz = cyl->get_zsize();
09792 
09793         int type = params.set_default("type", 2);
09794         float len = params.set_default("length", 16.2f); //in angstroms
09795         int x0 = params.set_default("x0", -1); //in voxels -- default value changed a few lines down
09796         int y0 = params.set_default("y0", -1); //in voxels
09797         int z0 = params.set_default("z0", -1); //in voxels
09798         //TODO: check with Matt about default values
09799 
09800         if (x0 < 0 || x0 >= nx)
09801                 x0 = nx / 2;
09802         if (y0 < 0 || y0 >= ny)
09803                 y0 = ny / 2;
09804         if (z0 < 0 || z0 >= nz)
09805                 z0 = nz / 2;
09806 
09807         float apix_x = cyl->get_attr("apix_x"); //TODO: Ask Matt if I correctly handled cases where apix_x != apix_y or apix_x != apix_z are not equal
09808         float apix_y = cyl->get_attr("apix_y");
09809         float apix_z = cyl->get_attr("apix_z");
09810 
09811         float * dat = cyl->get_data();
09812         int cyl_voxel_len = (int) (len / apix_z);
09813         int cyl_k_min = z0 - cyl_voxel_len / 2;
09814         int cyl_k_max = z0 + cyl_voxel_len / 2;
09815 
09816         int x, y;
09817         for (int k = 0; k < nz; ++k) {
09818                 for (int j = 0; j < ny; ++j) {
09819                         for (int i = 0; i < nx; ++i, ++dat) {
09820                                 x = i - x0;//coordinate sys centered on cylinder
09821                                 y = j - y0;//coordinate sys centered on cylinder
09822                                 float radius = (float)hypot(x * apix_x, y * apix_y);
09823                                 if ((k > cyl_k_min) && (k < cyl_k_max))
09824                                         *dat += radprofile(radius, type); //pointer arithmetic for array done in loop
09825                                 //else
09826                                         //continue;
09827 
09828                         }
09829                 }
09830         }
09831 }
09832 
09833 void ApplyPolynomialProfileToHelix::process_inplace(EMData * in)
09834 {
09835         EMData * cyl = in;
09836         int nx = cyl->get_xsize();
09837         int ny = cyl->get_ysize();
09838         int nz = cyl->get_zsize();
09839         float apix_x = cyl->get_attr("apix_x"); //TODO: Ask Matt if I correctly handled cases where apix_x != apix_y or apix_x != apix_z are not equal
09840         float apix_y = cyl->get_attr("apix_y");
09841         float apix_z = cyl->get_attr("apix_z");
09842         float lengthAngstroms = params["length"];
09843         int z0 = params.set_default("z0", -1); //in voxels
09844 
09845         if (z0 < 0 || z0 >= nz)
09846                 z0 = nz / 2;
09847 
09848         int z_start = Util::round( z0 - 0.5*lengthAngstroms/apix_z );
09849         int z_stop = Util::round( z0 + 0.5*lengthAngstroms/apix_z );
09850 
09851         float * dat = cyl->get_data();
09852         double rho_x_sum, rho_y_sum, rho_sum, x_cm, y_cm, radius;
09853 
09854         for (int k = 0; k < nz; ++k) //taking slices along z axis
09855         {
09856                 rho_x_sum = rho_y_sum = rho_sum = 0; //Set to zero for a new slice
09857 
09858                 if (k >= z_start && k <= z_stop)
09859                 //Apply the radial profile only between z_start and z_stop on the z axis
09860                 {
09861                         //Calculating CM for the slice...
09862                         for (int j = 0; j < ny; ++j)
09863                         {
09864                                 for (int i = 0; i < nx; ++i, ++dat)
09865                                 {
09866                                         rho_x_sum += (*dat)*i;
09867                                         rho_y_sum += (*dat)*j;
09868                                         rho_sum += *dat;
09869                                 }
09870                         }
09871                         if (rho_sum != 0)
09872                         {
09873                                 dat -= nx*ny;//going back to the beginning of the dat array
09874                                 x_cm = rho_x_sum/rho_sum;
09875                                 y_cm = rho_y_sum/rho_sum;
09876 
09877                                 //Applying radial profile...
09878                                 for (int j=0; j<ny;++j)
09879                                 {
09880                                         for (int i=0;i<nx;++i,++dat)
09881                                         {
09882                                                 radius = hypot( (i-x_cm)*apix_x, (j-y_cm)*apix_y );
09883                                                 *dat = radprofile((float)radius, 2);//Type 2 is the polynomial radial profile.
09884                                         }
09885                                 }
09886                         }
09887                 }
09888                 else
09889                 //Clear the map, setting the density to zero everywhere else.
09890                 {
09891                         for (int j=0; j<ny; j++)
09892                                 for(int i=0; i<nx; i++)
09893                                 {
09894                                         *dat = 0;
09895                                         dat++;
09896                                 }
09897                 }
09898 
09899         }
09900 }
09901 
09902 //Do NOT use this code as an example, (const EMData* const image) needs to be used otherwise process_inplace is called and the params are throw out!
09903 EMData* BinarySkeletonizerProcessor::process(EMData * image)
09904 {
09905         using namespace wustl_mm::GraySkeletonCPP;
09906         using namespace wustl_mm::SkeletonMaker;
09907 
09908         Volume * vimage = new Volume(image);
09909         float threshold = params["threshold"];
09910         int min_curvew = params.set_default("min_curve_width", 4);
09911         int min_srfcw = params.set_default("min_surface_width", 4);
09912         bool mark_surfaces = params.set_default("mark_surfaces", true);
09913         Volume* vskel = VolumeSkeletonizer::PerformPureJuSkeletonization(vimage, "unused", static_cast<double>(threshold), min_curvew, min_srfcw);
09914         //VolumeSkeletonizer::CleanUpSkeleton(vskel, 4, 0.01f);
09915         if (mark_surfaces) {
09916                 VolumeSkeletonizer::MarkSurfaces(vskel);
09917         }
09918 
09919         vskel->getVolumeData()->owns_emdata = false; //ensure the EMData object will remain when the Volume and its VolumeData object are freed
09920         EMData* skel = vskel->get_emdata();
09921         skel->update();
09922         return skel;
09923 }
09924 
09925 void BinarySkeletonizerProcessor::process_inplace(EMData * image)
09926 {
09927         EMData* em_skel = this->process(image);
09928         //TODO: use memcpy and copy metadata explicitly
09929         *image = *em_skel; //Deep copy performed by EMData::operator=
09930         image->update();
09931         delete em_skel;
09932         em_skel = NULL;
09933         return;
09934 }
09935 
09936 EMData* ConvolutionKernelProcessor::process(const EMData* const image) 
09937 {
09938         if (image->get_zsize()!=1) throw ImageDimensionException("Only 2-D images supported");
09939         
09940         EMData* conv = new EMData(image->get_xsize(),image->get_ysize(),1);
09941         vector<float>kernel = params["kernel"];
09942 
09943         if (fmod(sqrt((float)kernel.size()), 1.0f) != 0) throw InvalidParameterException("Convolution kernel must be square!!");
09944         
09945         float* data = image->get_data();
09946         float* cdata = conv->get_data();        // Yes I could use set_value_at_fast, but is still slower than this....
09947         
09948         //I could do the edges by wrapping around, but this is not necessary(such functionality can be iplemented later)
09949         int ks = int(sqrt(float(kernel.size())));
09950         int n = (ks - 1)/2;
09951         int nx = image->get_xsize();
09952         int ny = image->get_ysize();
09953         for (int i = n; i < (nx - n); i++) {
09954                 for (int j = n; j < (ny - n); j++) {
09955                         //now do the convolution
09956                         float cpixel = 0;
09957                         int idx = 0;
09958                         // Perahps I could use some ofrm of Caching to speed things up?
09959                         for (int cx = -n; cx <= n; cx++) {
09960                                 for (int cy = -n; cy <= n; cy++) {
09961                                         cpixel += data[(i+cx) + (j+cy) * nx]*kernel[idx];
09962                                         idx++;
09963                                 }
09964                         }
09965                         cdata[i + j * nx] = cpixel;
09966                 }
09967         }
09968           
09969         return conv;
09970 }
09971 
09972 void ConvolutionKernelProcessor::process_inplace(EMData * image )
09973 {
09974         throw UnexpectedBehaviorException("Not implemented yet");
09975         
09976         return;
09977 }
09978 
09979 
09980 EMData* RotateInFSProcessor::process(const EMData* const image) // 
09981 {
09982 
09983     EMData* imageCp        = image -> copy(); // This is the rotated image
09984     process_inplace(imageCp);
09985     
09986     return imageCp;
09987 }
09988 
09989 
09990 void RotateInFSProcessor::process_inplace(EMData * image) // right now for 2d images
09991 {
09992 //      float angle = params["angle"];
09993         
09994 
09995 //      Transform *rotNow  = params.set_default("transform",&Transform());
09996         Transform *rotNow  = params["transform"];
09997         float interpCutoff = params.set_default("interpCutoff",0.8f);   // JFF, can you move this to input parameter? 
09998 //      float interpCutoff = params["interpCutoff"];   // JFF, can you move this to input parameter? 
09999 //      float interpCutoff =.8;   // JFF, can you move this to input parameter? 
10000         
10001         
10002         int debug=0;
10003         
10004 //      error: conversion from ‘EMAN::EMObject’ to non-scalar type ‘EMAN::Transform’ requested
10005         
10006         
10007         // if 2N is size of image, then sizes of FFT are (2N+2,2N,2N) or  (2N+2,2N,1)
10008         // if 2N+1 is size of image, then sizes of FFT are (2N+2,2N+1,2N+1) or  (2N+2,2N+1,1)
10009         
10010         int x_size = image->get_xsize();  //16
10011         int y_size = image->get_ysize();  int y_odd=  (y_size%2);
10012         int z_size = image->get_zsize();
10013         
10014 //      float size_check = abs(y_size-z_size)+abs(x_size-y_size-2+y_odd);
10015 //      if (size_check!=0) throw ImageDimensionException("Only cubic images");
10016         int size_check = abs(x_size-y_size-2+y_odd)+ abs(z_size-1)*abs(z_size-y_size);
10017         int N = x_size/2-1;
10018         int Mid = N+1;
10019         if (size_check!=0) throw ImageDimensionException("Only square or cubic  images for now");
10020         if (image->is_real()) throw ImageDimensionException("Only for Fourier images");
10021 //      if (y_odd==0) throw ImageDimensionException("Only use odd images for now");
10022         
10023         if (debug) printf("Mid=%d, x_size=%d, y_size=%d, N=%d, z_size=%d \n", Mid,x_size,y_size, N, z_size );
10024         
10025         EMData* RotIm        = image -> copy(); // This is the rotated image
10026         EMData* WeightIm     = image -> copy(); WeightIm     ->to_zero();// This is the Weight image for rotated image
10027         EMData* PhaseOrigIm  = new EMData(N+1,2*N+1,z_size) ; PhaseOrigIm  ->to_zero();// This is the Weight image for rotated image
10028         EMData* PhaseFinalIm = PhaseOrigIm -> copy(); PhaseFinalIm ->to_zero();// This is the Weight image for rotated image
10029         EMData* MagFinalIm   = PhaseOrigIm -> copy(); MagFinalIm   ->to_zero();// This is the Weight image for rotated image
10030         
10031 //      float*   data      = image    -> get_data();
10032 //      float* Rotdata     = RotIm    -> get_data();  // This is the data of the rotated image
10033 //      float* WeightData  = WeightIm -> get_data();  //
10034         
10035         float  WeightNowX, WeightNowY, WeightNowZ ;
10036         int    kxMin,kxMax, kyMin, kyMax,  kzMin, kzMax, kxBefore, kyBefore, kzBefore ;
10037         float  kxRT, kyRT, kzRT ;
10038         
10039         Vec3f PosAfter;
10040         Vec3f PosBefore;
10041         Transform invRotNow;
10042         // Fill out real and imaginary full images
10043 
10044         //int kz=0;
10045 
10046         if (debug) {image -> write_image("OrigImageFFT.hdf");   
10047                     printf("Just wrote OrigImageFFT.hdf \n"); }
10048         
10049 
10050         for (kxBefore = 0; kxBefore <=  N      ; ++kxBefore) {  // These are the  kx, ky coordinates of the original image
10051            for (kyBefore = 0; kyBefore < y_size ; ++kyBefore)  {         //  We need to rephase
10052               for (kzBefore = 0; kzBefore < z_size ; ++kzBefore)  {         //  We need to rephase
10053 
10054             // Now we need a 
10055               float CurrentReal = RotIm -> get_value_at(2*kxBefore  ,kyBefore, kzBefore);
10056               float CurrentImag = RotIm -> get_value_at(2*kxBefore+1,kyBefore, kzBefore);
10057               
10058 //         fftOfxPRB3(1+mod(ik-Mid,N))=Grand*exp(-2*pi*1i*Mid*(ik-Mid)/x_size); % Phase to apply to centered version
10059               
10060 //            float Phase    = -2*pi*(kxBefore+kyBefore + kzBefore)*(Mid)/y_size;
10061               float Phase    = -pi*(kxBefore+kyBefore + kzBefore)*x_size/y_size;
10062               // Phase    = 0;
10063               float CosPhase = cos( Phase);
10064               float SinPhase = sin( Phase);
10065              
10066               float NewRealValue = CosPhase*CurrentReal -SinPhase*CurrentImag;
10067               float NewImagValue = SinPhase*CurrentReal +CosPhase*CurrentImag;
10068               
10069               RotIm ->set_value_at(2*kxBefore  ,kyBefore, kzBefore, NewRealValue);
10070               RotIm ->set_value_at(2*kxBefore+1,kyBefore, kzBefore, NewImagValue);
10071         }}}
10072         
10073         if (debug) {RotIm  -> write_image("OrigImageFFTAfterPhaseCorrection.hdf"); 
10074                     printf("  Just wrote OrigImageFFTAfterPhaseCorrection.hdf \n");}
10075         
10076         // RotIm ->set_value_at(2*Mid-1,0, 0, 0);
10077         if (debug) printf("  Just about to start second loop  \n");
10078         
10079         image ->to_zero();
10080         invRotNow = rotNow ->inverse(); //  no match for ‘operator=’ in ‘PosBefore = EMAN::operator*(const EMAN::Transform&, const EMAN::Transform&)((
10081          
10082         
10083         for (int kxAfter = 0; kxAfter <= N  ; ++kxAfter) {  // These are the  kx, ky, kz coordinates of the rotated image
10084           for (int kyAfter = -N; kyAfter < y_size-N     ; ++kyAfter)  {     // referring to a properly centered version
10085              for (int kzAfter = -z_size/2; kzAfter <= z_size/2  ; ++kzAfter)  {   
10086 
10087             // Now we need a 
10088 
10089               PosAfter = Vec3f(kxAfter, kyAfter, kzAfter);
10090               PosBefore = invRotNow*PosAfter;
10091               kxRT = PosBefore[0]; // This will be the off-lattice site, where the point was rotated from
10092               kyRT = PosBefore[1]; //  
10093               kzRT = PosBefore[2]; //  
10094               
10095               
10096               kxMin = ceil( kxRT-interpCutoff); kxMax = floor(kxRT+interpCutoff);
10097               kyMin = ceil( kyRT-interpCutoff); kyMax = floor(kyRT+interpCutoff);
10098               kzMin = ceil( kzRT-interpCutoff); kzMax = floor(kzRT+interpCutoff);
10099 
10100     
10101 //              printf("Block 0,kx=%d, ky=%d,kxMin=%d, kyMin=%d, kxMax=%d, kyMax=%d, kyAfter=%d  \n",kxAfter,kyAfter,kxMin,kyMin, kxMax, kyMax, kyAfter); 
10102               //continue; 
10103               for (int kxI= kxMin; kxI <= kxMax; ++kxI){  // go through this
10104                 for (int kyI= kyMin; kyI <= kyMax; ++kyI){  // and get values to interp
10105                    for (int kzI= kzMin; kzI <= kzMax; ++kzI){ //  
10106 
10107 // 
10108                      if (abs(kxI) >N) continue; // don't go off the lattice
10109                      if (abs(kyI) >N) continue;
10110                      if (abs(kzI) >z_size/2) continue;
10111                      
10112                      float distx= abs(kxI-kxRT);
10113                      float disty= abs(kyI-kyRT);
10114                      float distz= abs(kzI-kzRT);
10115 
10116                      // fold kxI, kyI back into lattice if possible
10117                      int IsComplexConj= 1;
10118                      
10119                      if (kxI<0) IsComplexConj=-1;
10120                      kxBefore= IsComplexConj*kxI; // The Proper coordinates will be
10121                      kyBefore= IsComplexConj*kyI; // where the original data is stored 
10122                      kzBefore= IsComplexConj*kzI; // At this point kxBefore >=0, but not necessarily kyBefore
10123                      
10124                      if ( kyBefore<0 ) kyBefore += y_size; // makes sure kyBefore is also >0
10125                      if ( kzBefore<0 ) kzBefore += y_size; // makes sure kzBefore is also >0
10126                      
10127                      WeightNowX  = (distx ==0)? 1: (sin(pi*distx) /(pi*distx)) ;
10128                      WeightNowY  = (disty ==0)? 1: (sin(pi*disty) /(pi*disty)) ;
10129                      WeightNowZ  = (distz ==0)? 1: (sin(pi*distz) /(pi*distz)) ;
10130                      
10131                      
10132                      float CurrentValue;
10133                      float ToAdd;
10134                      int kyAfterInd = (kyAfter+y_size)%(y_size);
10135                      int kzAfterInd = (kzAfter+z_size)%(z_size);
10136                      
10137                     // if (kxAfter==0) IsComplexConj*=-1;
10138                      
10139 //                   if ((kxI+kyI)%1 ==0)
10140 //                       printf("Block5,kx=%d, ky=%d,kxI=%d, kyI=%d, kxBefore=%d, kyBefore=%d  \n",kxAfter,kyAfter,kxI,kyI, kxBefore,kyBefore);
10141 //                       printf("  %d,     %d,  %d,  %d,        %d,  %d,       %d, %d \n",IsComplexConj,kxAfter,kyAfter, kyAfterInd,kxI,kyI, kxBefore,kyBefore);
10142                      
10143                      CurrentValue =   image -> get_value_at(2*kxAfter,kyAfterInd, kzAfterInd);  // Update real part of Image
10144                      ToAdd =   WeightNowX*WeightNowY*WeightNowZ*(RotIm -> get_value_at(2*kxBefore,kyBefore, kzBefore));
10145                      image -> set_value_at(2*kxAfter  ,kyAfterInd  , kzAfterInd,  ToAdd   + CurrentValue );
10146                      
10147                      
10148                      CurrentValue =   WeightIm -> get_value_at(kxAfter,kyAfterInd, kzAfterInd);    // Update real  part of Weight image
10149                      ToAdd =   WeightNowX*WeightNowY;
10150                      WeightIm -> set_value_at(kxAfter  , kyAfterInd , kzAfterInd,  abs(ToAdd)   + CurrentValue );
10151                      
10152                      CurrentValue = image -> get_value_at(2*kxAfter+1,kyAfterInd);    // Update imaginary   part of image
10153                      ToAdd =   IsComplexConj*WeightNowX*WeightNowY*RotIm -> get_value_at(2*kxBefore+1,kyBefore, kzBefore );
10154                      image -> set_value_at(2*kxAfter+1  , kyAfterInd , kzAfterInd,  ToAdd   + CurrentValue );
10155                      
10156                       
10157                 }}}
10158 
10159             
10160           }}}
10161 
10162 //        Set the image values to the rotated image, because we do it in place
10163 
10164 
10165         if (debug) { image        -> write_image("RotImageBeforeFinalPhaseCorrection.hdf"); 
10166                      printf("  Just wrote RotImageBeforeFinalPhaseCorrection.hdf \n");   }
10167 
10168 
10169         for (kxBefore = 0; kxBefore <= N     ; ++kxBefore) {      // This is  the normalization step
10170           for (kyBefore = 0; kyBefore < y_size   ; ++kyBefore)  {  // These are the  kx, ky, kz coordinates of the original image       
10171               for (kzBefore = 0; kzBefore < z_size   ; ++kzBefore)  {       
10172 
10173               float CurrentReal = image -> get_value_at(2*kxBefore   , kyBefore, kzBefore);
10174               float CurrentImag = image -> get_value_at(2*kxBefore+1 , kyBefore, kzBefore);
10175               
10176               PhaseFinalIm -> set_value_at(kxBefore,kyBefore, kzBefore, atan2(CurrentImag,CurrentReal));
10177               MagFinalIm   -> set_value_at(kxBefore,kyBefore, kzBefore, sqrt(CurrentImag*CurrentImag+CurrentReal*CurrentReal) );
10178               float WeightNow    = WeightIm -> get_value_at(kxBefore,kyBefore, kzBefore);
10179               if (WeightNow>0) {
10180                  float val =  (image->get_value_at(2*kxBefore   , kyBefore, kzBefore))/WeightNow;
10181                  image -> set_value_at(2*kxBefore   , kyBefore, kzBefore, val);
10182                  val      =  (image->get_value_at(2*kxBefore +1  , kyBefore, kzBefore))/WeightNow;
10183                  image -> set_value_at(2*kxBefore +1  , kyBefore, kzBefore,  val);
10184               }
10185         
10186         }}}
10187         
10188         if (debug) { printf("  Just did normalization step \n");}
10189         
10190 
10191         for ( kxBefore = 0; kxBefore < Mid     ; ++kxBefore) {     //  This is the rephase step
10192           for ( kyBefore = 0; kyBefore < y_size   ; ++kyBefore)  {     
10193             for ( kzBefore = 0; kzBefore < z_size   ; ++kzBefore)  {     
10194 
10195               float CurrentReal = image -> get_value_at(2*kxBefore  ,kyBefore, kzBefore);
10196               float CurrentImag = image -> get_value_at(2*kxBefore+1,kyBefore, kzBefore);
10197               
10198 //            float Phase    = +2*pi*(kxBefore+kyBefore+kzBefore)*(Mid)/y_size;
10199               float Phase    =  pi*(kxBefore + kyBefore + kzBefore)*x_size/y_size;
10200               // Phase    = 0; // Offset should be Mid-1
10201               float CosPhase = cos( Phase);
10202               float SinPhase = sin( Phase);
10203              
10204               float NewRealValue = CosPhase*CurrentReal -SinPhase*CurrentImag;
10205               float NewImagValue = SinPhase*CurrentReal +CosPhase*CurrentImag;
10206               
10207               image ->set_value_at(2*kxBefore,  kyBefore,  kzBefore, NewRealValue);
10208               image ->set_value_at(2*kxBefore+1,kyBefore,  kzBefore, NewImagValue);
10209         }}}
10210         
10211         if (debug) {
10212            image        -> write_image("RotatedImageFFT.hdf");
10213            PhaseFinalIm -> write_image("PhaseImInFS.hdf");   // These are the phases,mags of the image when properly centered
10214            MagFinalIm   -> write_image("MagFinalImInFS.hdf"); 
10215            WeightIm     -> write_image("WeightIm.hdf");
10216            printf("  Just wrote RotatedImageFFT.hdf \n");
10217         }
10218 
10219         image -> update();
10220         
10221 }
10222 
10223 
10224 #ifdef SPARX_USING_CUDA
10225 
10226 /* CLASS MPICUDA_kmeans processor
10227  *
10228  */
10229 #include "sparx/cuda/cuda_mpi_kmeans.h"
10230 MPICUDA_kmeans::MPICUDA_kmeans() {
10231     h_IM = NULL;
10232     h_AVE = NULL;
10233     h_ASG = NULL;
10234     h_dist = NULL;
10235     h_AVE2 = NULL;
10236     h_im2 = NULL;
10237     h_NC = NULL;
10238     params = NULL;
10239     d_im = NULL;
10240     d_AVE = NULL;
10241     d_dist = NULL;
10242 }
10243 
10244 MPICUDA_kmeans::~MPICUDA_kmeans() {
10245     if (h_IM) delete h_IM;
10246     if (h_ASG) delete h_ASG;
10247     if (h_AVE) delete h_AVE;
10248     if (h_dist) delete h_dist;
10249     if (h_AVE2) delete h_AVE2;
10250     if (h_im2) delete h_im2;
10251     if (h_NC) delete h_NC;
10252     if (params) delete params;
10253 }
10254 
10255 #include "sparx/cuda/cuda_mpi_kmeans.h"
10256 int MPICUDA_kmeans::setup(int extm, int extN, int extn, int extK, int extn_start) {
10257     m = extm;                           // number of pixels per image
10258     N = extN;                           // Total number of images
10259     n = extn;                           // Number of images used locally
10260     K = extK;                           // number of classes
10261     n_start = extn_start;               // Starting point to local images
10262     size_IM = m * N;                    // nb elements in IM
10263     size_im = m * n;                    // nb elements in im
10264     size_AVE = m * K;                   // nb elements in ave
10265     size_dist = n * K;                  // nb elements in dist
10266     ite = 0;                            // init nb of iterations
10267     BLOCK_SIZE = 512;
10268     NB = size_dist / BLOCK_SIZE;
10269     ins_BLOCK = NB * BLOCK_SIZE;
10270     // Host memory allocation for images
10271     h_IM = (float*)malloc(size_IM * sizeof(float));
10272     if (h_IM == 0) return 1;
10273     h_im = &h_IM[n_start * m]; // for local images
10274     // Host memory allocation for the averages
10275     h_AVE = (float*)malloc(size_AVE * sizeof(float));
10276     if (h_AVE == 0) return 1;
10277     // Host memory allocation for all assignment
10278     h_ASG = (unsigned short int*)malloc(N * sizeof(unsigned short int));
10279     if (h_ASG == 0) return 1;
10280     h_asg = &h_ASG[n_start]; // for local assignment
10281     // allocate the memory for the sum squared of averages
10282     h_AVE2 = (float*)malloc(K * sizeof(float));
10283     if (h_AVE2 == 0) return 1;
10284     // allocate the memory for the sum squared of images
10285     h_im2 = (float*)malloc(n * sizeof(float));
10286     if (h_im2 == 0) return 1;
10287     // allocate the memory for the distances
10288     h_dist = (float*)malloc(size_dist * sizeof(float));
10289     if (h_dist == 0) return 1;
10290     // allocate the memory for the number of images per class
10291     h_NC = (unsigned int*)malloc(K * sizeof(unsigned int));
10292     if (h_NC == 0) return 1;
10293     // allocate the memory to parameters
10294     params = (int*)malloc(8 * sizeof(int));
10295     if (params == 0) return 1;
10296     params[0] = n;
10297     params[1] = m;
10298     params[2] = K;
10299     params[3] = 0;          // Reserve for flag_stop_iteration
10300     params[4] = 0;          // Reserve for ct_im_mv (debug)
10301     params[5] = BLOCK_SIZE; // Size of threads block (512)
10302     params[6] = NB;         // Number of blocks which fit with BLOCK_SIZE
10303     params[7] = ins_BLOCK;  // Number of blocks remaining
10304     
10305 
10306     return 0;
10307 }
10308 
10309 // add image pre-process by Util.compress_image_mask
10310 void MPICUDA_kmeans::append_flat_image(EMData* im, int pos) {
10311    
10312     for (int i = 0; i < m ; ++i) h_IM[pos * m + i] = (*im)(i);
10313     
10314 }
10315 
10316 // cuda init mem device, cublas (get device ptr)
10317 int MPICUDA_kmeans::init_mem(int numdev) {
10318     int stat = 1;
10319     float** hd_AVE = NULL;
10320     float** hd_im = NULL;
10321     float** hd_dist = NULL;
10322     hd_AVE = &d_AVE;
10323     hd_im = &d_im;
10324     hd_dist = &d_dist;
10325     stat = cuda_mpi_init(h_im, hd_im, hd_AVE, hd_dist, size_im, size_AVE, size_dist, numdev);
10326     //printf("C++ get this pointer for d_AVE: %p\n", d_AVE);
10327     //printf("C++ get this pointer for d_im: %p\n", d_im);
10328     //printf("C++ get this pointer for d_dist: %p\n", d_dist);
10329     return stat;
10330 }
10331 
10332 // precalculate im2
10333 void MPICUDA_kmeans::compute_im2() {
10334     for (int i = 0; i < n; i++) {
10335         h_im2[i] = 0.0f;
10336         for (int j = 0; j < m; j++) h_im2[i] += (h_im[i * m + j] * h_im[i * m + j]);
10337     }
10338 }
10339 
10340 // init randomly the first assignment
10341 int MPICUDA_kmeans::random_ASG(long int rnd) {
10342     srand(rnd);
10343     int ret = 20;
10344     int flag = 0;
10345     int i, k;
10346     std::cout<<"111111111  number of image==="<<N<<"number cluster=="<<K<<"img size"<<m<<std::endl;
10347     for (k = 0; k < K; k++) h_NC[k] = 0;
10348     while (ret > 0) {
10349         ret--;
10350         for (i = 0; i < N; i++) {
10351             h_ASG[i] = rand() % K;
10352             h_NC[h_ASG[i]]++;
10353         }
10354         flag = 1;
10355         k = K;
10356         while (k > 0 && flag) {
10357             k--;
10358             if (h_NC[k] <= 1) {
10359                 flag = 0;
10360                 if (ret == 0) {
10361                     //printf("Erreur randomize assignment\n");
10362                     return -1;
10363                 }
10364                 for (k = 0; k < K; k++) h_NC[k] = 0;
10365             }
10366         if (flag == 1) ret = 0;
10367         }
10368     }
10369    
10370     return 0;
10371 }
10372 
10373 // get back the assignment
10374 vector <int> MPICUDA_kmeans::get_ASG() {
10375     vector <int> ASG(h_ASG, &h_ASG[N]);
10376     return ASG;
10377 }
10378 
10379 // get back the global assignment
10380 vector <int> MPICUDA_kmeans::get_asg() {
10381     vector <int> asg(h_asg, &h_asg[n]);
10382     return asg;
10383 }
10384 
10385 // compute NC from ASG
10386 void MPICUDA_kmeans::compute_NC() {
10387     for (int i = 0; i < K; ++i) h_NC[i] = 0;
10388     for (int i = 0; i < N; ++i) h_NC[h_ASG[i]]++;
10389 }
10390 
10391 // get NC
10392 vector <int> MPICUDA_kmeans::get_NC() {
10393     vector <int> NC(h_NC, &h_NC[K]);
10394     return NC;
10395 }
10396 
10397 // set a new global assignment
10398 void MPICUDA_kmeans::set_ASG(const vector <int>& ASG) {
10399     for (int i = 0; i < N ; ++i) h_ASG[i] = ASG[i];
10400 }
10401 
10402 // set number of objects per group
10403 void MPICUDA_kmeans::set_NC(const vector <int>& NC) {
10404     for (int i = 0; i < K; ++i) h_NC[i] = NC[i];
10405 }
10406 
10407 // get back some information (ite and T0)
10408 int MPICUDA_kmeans::get_ct_im_mv() {
10409     return params[4]; // ct_im_mov
10410 }
10411 
10412 // set the value of T
10413 void MPICUDA_kmeans::set_T(float extT) {
10414     T = extT;
10415 }
10416 
10417 // get the T value
10418 float MPICUDA_kmeans::get_T() {
10419     return T;
10420 }
10421 
10422 // compute ave and ave2
10423 void MPICUDA_kmeans::compute_AVE() {
10424     float buf = 0.0f;
10425     int i, j, c, d, ind;
10426     // compute the averages according ASG
10427     for (i = 0; i < size_AVE; ++i) h_AVE[i] = 0.0f;                          // set averages to zero
10428     for (i = 0; i < N; ++i) {
10429         c = h_ASG[i] * m;
10430         d = i * m;
10431         for (j = 0; j < m; ++j) h_AVE[c + j] += h_IM[d + j];                 // accumulate images
10432     }
10433     for (i = 0; i < K; i++) {
10434         buf = 0.0f;
10435         for (j = 0 ; j < m; j++) {
10436             ind = i * m + j;
10437             h_AVE[ind] /= (float)h_NC[i];                                    // compute average
10438             buf += (h_AVE[ind] * h_AVE[ind]);                                // do sum squared AVE
10439         }
10440         h_AVE2[i] = buf;
10441     }
10442     
10443     /*for (i = 0; i < K; i++) {
10444         std::cout<<"average image"<<std::endl;
10445         std::cout<<h_AVE[i*m+0]<<"  "<<h_AVE[i*m+1]<<"  "<<h_AVE[i*m+2]<<"  "<<h_AVE[i*m+3]<<"  "<<h_AVE[i*m+4]<<std::endl;
10446     }*/
10447   
10448 }
10449 
10450 // set averages
10451 void MPICUDA_kmeans::set_AVE(EMData* im, int pos) {
10452     for (int i = 0; i < m ; ++i) h_AVE[pos * m + i] = (*im)(i);
10453 }
10454 
10455 // get back the averages
10456 vector<EMData*> MPICUDA_kmeans::get_AVE() {
10457     vector<EMData*> ave(K);
10458     for (int k = 0; k < K; ++k) {
10459         EMData* im = new EMData();
10460         im->set_size(m, 1, 1);
10461         float *ptr = im->get_data();
10462         for (int i = 0; i < m; ++i) {ptr[i] =  h_AVE[k * m + i];}
10463         ave[k] = im->copy();
10464         delete im;
10465     }
10466     return ave;
10467 }
10468 
10469 // k-means one iteration
10470 int MPICUDA_kmeans::one_iter() {
10471     int status = cuda_mpi_kmeans(h_AVE, d_AVE, h_dist, d_dist, d_im, h_im2, h_AVE2, h_asg, h_NC, params);
10472     ite++;
10473     return status;
10474 }
10475 // k-means SSE one iteration help function
10476 /*int MPICUDA_kmeans::init_dist() {
10477    
10478     int status = cuda_mpi_kmeans_dist_SSE(h_AVE, d_AVE, h_dist, d_dist, d_im, h_im2, h_AVE2, h_asg, h_NC, params);
10479    
10480     return status;
10481 }*/
10482 
10483 /*int MPICUDA_kmeans::AVE_to_host() {
10484    
10485     int status = cuda_mpi_kmeans_copy_ave_from_device(h_AVE, d_AVE, params);
10486    
10487     return status;
10488 }*/
10489 
10490 
10491 int one_iter_SA();
10492 // k-means SSE one iteration
10493 /*int MPICUDA_kmeans::one_iter_SSE() {
10494     //if ( ite == 0)
10495     
10496     if( ite ==0) {
10497          int status_init=init_dist();
10498          ttt = compute_tt();//int status = 0;
10499          printf("intial energy ===%f\n",ttt);
10500     }
10501     //std::cout<<bb<<BB<<std::endl;
10502     int status = cuda_mpi_kmeans_SSE(h_AVE, d_AVE, h_dist, d_dist, d_im, h_im2, h_AVE2, h_asg, h_NC, params, ite, ttt);
10503     
10504     //float t = compute_tt();//int status = 0;
10505     //std::cout<<"engery at iteration"<<ite<<"==="<<t<<std::endl;
10506  
10507     ite++;
10508     return status;
10509 }*/
10510 // k-means SA one iteration
10511 int MPICUDA_kmeans::one_iter_SA() {
10512     int status = cuda_mpi_kmeans_SA(h_AVE, d_AVE, h_dist, d_dist, d_im, h_im2, h_AVE2, h_asg, h_NC, T, params);
10513     ite++;
10514     return status;
10515 }
10516 
10517 // compute ji
10518 vector <float> MPICUDA_kmeans::compute_ji() {
10519     int status = cuda_mpi_dist(h_AVE, d_AVE, h_dist, d_dist, d_im, n, K, m);
10520     vector <float> ji(K);
10521     int i;
10522     if (status != 0) {
10523         for (i = 0; i < K; ++i) ji[i] = -1.0;
10524         return ji;
10525     }
10526     for (i = 0; i < n; ++i) ji[h_asg[i]] += (h_im2[i] + h_AVE2[h_asg[i]] - 2 * h_dist[i * K + h_asg[i]]);
10527     return ji;
10528 }
10529 
10530 
10531 float MPICUDA_kmeans::compute_tt() {
10532     /*int status = cuda_mpi_dist(h_AVE, d_AVE, h_dist, d_dist, d_im, n, K, m);
10533     vector <float> ji(K);
10534     int i;
10535     if (status != 0) {
10536         for (i = 0; i < K; ++i) ji[i] = -1.0;
10537         return -11111111;
10538     }
10539     for (i = 0; i < n; ++i) ji[h_asg[i]] += (h_im2[i] + h_AVE2[h_asg[i]] - 2 * h_dist[i * K + h_asg[i]]);
10540    float t =0.0; 
10541    for (i =0; i<K;i++)
10542        t +=ji[i];
10543     return t;*/
10544     
10545            
10546     vector <float> ji(K);
10547     int i,j;
10548     float dist, temp;
10549     for (i = 0; i < n; ++i) 
10550     {
10551         dist =0;
10552         for ( j=0; j<m; j++)     {
10553             temp = (h_im[i*m+j] -h_AVE[ h_asg[i]*m+j]);
10554             dist = dist + temp*temp;
10555          }
10556         ji[h_asg[i]] = ji[h_asg[i]]+ dist;
10557    }
10558         
10559    float t =0.0; 
10560    for (i =0; i<K;i++)
10561        t +=ji[i];
10562     return t;
10563 }
10564 
10565 
10566 //
10567 vector <float> MPICUDA_kmeans::compute_criterion(const vector <float>& Ji) {
10568     float buf = 0.0f;
10569     float Je = 0.0f;
10570     float Tr_AVE = 0.0f;
10571     float v_max = 0.0f;
10572     float* S_AVE2 = (float*)calloc(m, sizeof(float));
10573     float* S_AVE = (float*)calloc(m, sizeof(float));
10574     vector <float> crit(4);
10575     int i, j, k;
10576     // Je
10577     for (i = 0; i < K; ++i) Je += (Ji[i] / float(m));
10578     crit[0] = Je;
10579     // trace ave
10580     for (i = 0; i < K; ++i) {
10581         for (j = 0; j < m; ++j) {
10582             S_AVE[j] += h_AVE[i * m + j];
10583             S_AVE2[j] += (h_AVE[i * m + j] * h_AVE[i * m +j]);
10584         }
10585     }
10586     buf = 1 / (float)K;
10587     for (i = 0; i < m; ++i) Tr_AVE += (buf * (S_AVE2[i] - buf * S_AVE[i] * S_AVE[i]));
10588     // Coleman
10589     crit[1] = Tr_AVE * Je;
10590     // Harabasz
10591     crit[2] = (Tr_AVE * (float)(N - K)) / (Je * (float)(K - 1));
10592     // Davies-Bouldin
10593     for (i = 0; i < K; ++i) {
10594         v_max = 0.0f;
10595         for (j = 0; j < K; ++j) {
10596             if (j != i) {
10597                 buf = 0.0f;
10598                 for (k = 0; k < m; ++k) buf += ((h_AVE[j * m + k] - h_AVE[i * m + k]) * (h_AVE[j * m + k] - h_AVE[i * m + k]));
10599                 buf = (Ji[i] / (float)h_NC[i] + Ji[j] / (float)h_NC[j]) * ((float)m / buf);
10600             }
10601             if (buf > v_max) v_max = buf;
10602         }
10603         crit[3] += v_max;
10604     }
10605     crit[3] /= (float)K;
10606     free(S_AVE);
10607     free(S_AVE2);
10608     return crit;
10609 }
10610 
10611 // shutdown cublas and release device mem
10612 int MPICUDA_kmeans::shutdown() {
10613     return cuda_mpi_shutdown(d_im, d_AVE, d_dist);
10614 }
10616 
10617 #endif //SPARX_USING_CUDA
10618 
10619 

Generated on Mon Aug 13 13:40:23 2012 for EMAN2 by  doxygen 1.3.9.1