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         for (int z = 0; z < nz; ++z) {
01562                 for (int y = 0; y < ny; ++y) {
01563                         for (int x = 0; x < nx; ++x) {
01564                                 float x1 = sqrt((x - xc) * (x - xc) + (y - yc) * (y - yc) + (z - zc) * (z - zc));
01565                                 if (x1 <= outer_radius + ring_width && x1 >= outer_radius - ring_width) {
01566                                         sum += data[i];
01567                                         ++nitems;
01568                                 }
01569                                 ++i;
01570                         }
01571                 }
01572         }
01573 
01574         ring_avg = sum / nitems;
01575 }
01576 
01577 void ToMinvalProcessor::process_inplace(EMData * image)
01578 {
01579         if (!image) {
01580                 LOGWARN("NULL Image");
01581                 return;
01582         }
01583 
01584         float minval = params.set_default("minval",0.0f);
01585         float newval = params.set_default("newval",minval);
01586 
01587         size_t size = (size_t)image->get_xsize() *
01588                           (size_t)image->get_ysize() *
01589                           (size_t)image->get_zsize();
01590         float *data = image->get_data();
01591 
01592 
01593 
01594         for (size_t i = 0; i < size; ++i) {
01595                 if (data[i]<minval) data[i]=newval;
01596         }
01597         image->update();
01598 }
01599 
01600 
01601 void ComplexPixelProcessor::process_inplace(EMData * image)
01602 {
01603         if (!image) {
01604                 LOGWARN("NULL image");
01605                 return;
01606         }
01607         if (!image->is_complex()) {
01608                 LOGWARN("cannot apply complex processor on a real image. Nothing is done.");
01609                 return;
01610         }
01611 
01612         size_t size = (size_t)image->get_xsize() *
01613                           (size_t)image->get_ysize() *
01614                           (size_t)image->get_zsize();
01615         float *data = image->get_data();
01616 
01617         image->ri2ap();
01618 
01619         for (size_t i = 0; i < size; i += 2) {
01620                 process_pixel(data);
01621                 data += 2;
01622         }
01623 
01624         image->update();
01625         image->ap2ri();
01626 }
01627 
01628 
01629 
01630 void AreaProcessor::process_inplace(EMData * image)
01631 {
01632         if (!image) {
01633                 LOGWARN("NULL Image");
01634                 return;
01635         }
01636 
01637         float *data = image->get_data();
01638 
01639         nx = image->get_xsize();
01640         ny = image->get_ysize();
01641         nz = image->get_zsize();
01642 
01643         int n = (areasize - 1) / 2;
01644         matrix_size = areasize * areasize;
01645 
01646         if (nz > 1) {
01647                 matrix_size *= areasize;
01648         }
01649 
01650         float *matrix = new float[matrix_size];
01651         kernel = new float[matrix_size];
01652 
01653         size_t cpysize = areasize * sizeof(float);
01654         size_t start = (nx * ny + nx + 1) * n;
01655 
01656         int xend = nx - n;
01657         int yend = ny - n;
01658 
01659         int zstart = n;
01660         int zend = nz - n;
01661 
01662         int zbox_start = 0;
01663         int zbox_end = areasize;
01664 
01665         if (nz == 1) {
01666                 zstart = 0;
01667                 zend = 1;
01668                 zbox_end = 1;
01669         }
01670 
01671         size_t nsec = (size_t)nx * (size_t)ny;
01672         int box_nsec = areasize * areasize;
01673 
01674         create_kernel();
01675 
01676         size_t total_size = (size_t)nx * (size_t)ny * (size_t)nz;
01677         float *data2 = new float[total_size];
01678         memcpy(data2, data, total_size * sizeof(float));
01679 
01680         size_t k;
01681         for (int z = zstart; z < zend; z++) {
01682                 for (int y = n; y < yend; y++) {
01683                         for (int x = n; x < xend; x++) {
01684 
01685                                 k = (size_t)z * nsec + y * nx + x;
01686 
01687                                 for (int bz = zbox_start; bz < zbox_end; bz++) {
01688                                         for (int by = 0; by < areasize; by++) {
01689                                                 memcpy(&matrix[(size_t)bz * box_nsec + by * areasize],
01690                                                            &data2[k - start + bz * nsec + by * nx], cpysize);
01691                                         }
01692                                 }
01693 
01694                                 process_pixel(&data[k], (float) x, (float) y, (float) z, matrix);
01695                         }
01696                 }
01697         }
01698 
01699         if( matrix )
01700         {
01701                 delete[]matrix;
01702                 matrix = 0;
01703         }
01704 
01705         if( kernel )
01706         {
01707                 delete[]kernel;
01708                 kernel = 0;
01709         }
01710         image->update();
01711 }
01712 
01713 
01714 void LaplacianProcessor::create_kernel() const
01715 {
01716         if (nz == 1) {
01717                 memset(kernel, 0, areasize * areasize);
01718                 kernel[1] = -0.25f;
01719                 kernel[3] = -0.25f;
01720                 kernel[5] = -0.25f;
01721                 kernel[7] = -0.25f;
01722                 kernel[4] = 1;
01723         }
01724         else {
01725                 memset(kernel, 0, (size_t)areasize * areasize * areasize);
01726                 kernel[4] = -1.0f / 6.0f;
01727                 kernel[10] = -1.0f / 6.0f;
01728                 kernel[12] = -1.0f / 6.0f;
01729                 kernel[14] = -1.0f / 6.0f;
01730                 kernel[16] = -1.0f / 6.0f;
01731                 kernel[22] = -1.0f / 6.0f;
01732                 kernel[13] = 1;
01733         }
01734 }
01735 
01736 void BoxStatProcessor::process_inplace(EMData * image)
01737 {
01738         if (!image) {
01739                 LOGWARN("NULL Image");
01740                 return;
01741         }
01742 
01743         int nx = image->get_xsize();
01744         int ny = image->get_ysize();
01745         int nz = image->get_zsize();
01746 
01747         int n = params.set_default("radius",1);
01748         int areasize = 2 * n + 1;
01749 
01750         int matrix_size = areasize * areasize;
01751         if (nz > 1) {
01752                 matrix_size *= areasize;
01753         }
01754 
01755         float *array = new float[matrix_size];
01756 //      image->process_inplace("normalize");
01757 
01758         float *data = image->get_data();
01759         size_t total_size = (size_t)nx * (size_t)ny * (size_t)nz;
01760         float *data2 = new float[total_size];
01761         memcpy(data2, data, total_size * sizeof(float));
01762 
01763         int z_begin = 0;
01764         int z_end = 1;
01765         int nzz=0;
01766         if (nz > 1) {
01767                 z_begin = n;
01768                 z_end = nz - n;
01769                 nzz=n;
01770         }
01771 
01772         int nxy = nx * ny;
01773 
01774         for (int k = z_begin; k < z_end; k++) {
01775                 size_t knxy = (size_t)k * nxy;
01776 
01777                 for (int j = n; j < ny - n; j++) {
01778                         int jnx = j * nx;
01779 
01780                         for (int i = n; i < nx - n; i++) {
01781                                 size_t s = 0;
01782 
01783                                 for (int i2 = i - n; i2 <= i + n; i2++) {
01784                                         for (int j2 = j - n; j2 <= j + n; j2++) {
01785                                                 for (int k2 = k - nzz; k2 <= k + nzz; k2++) {
01786                                                         array[s] = data2[i2 + j2 * nx + (size_t)k2 * nxy];
01787                                                         ++s;
01788                                                 }
01789                                         }
01790                                 }
01791 
01792                                 process_pixel(&data[i + jnx + knxy], array, matrix_size);
01793                         }
01794                 }
01795         }
01796 
01797         image->update();
01798 
01799         if( data2 )
01800         {
01801                 delete[]data2;
01802                 data2 = 0;
01803         }
01804 }
01805 
01806 void DiffBlockProcessor::process_inplace(EMData * image)
01807 {
01808         if (!image) {
01809                 LOGWARN("NULL Image");
01810                 return;
01811         }
01812 
01813         int nz = image->get_zsize();
01814 
01815         if (nz > 1) {
01816                 LOGERR("%s Processor doesn't support 3D", get_name().c_str());
01817                 throw ImageDimensionException("3D model not supported");
01818         }
01819 
01820         int nx = image->get_xsize();
01821         int ny = image->get_ysize();
01822 
01823         int v1 = params["cal_half_width"];
01824         int v2 = params["fill_half_width"];
01825 
01826         int v0 = v1 > v2 ? v1 : v2;
01827 
01828         if (v2 <= 0) {
01829                 v2 = v1;
01830         }
01831 
01832         float *data = image->get_data();
01833 
01834         for (int y = v0; y <= ny - v0 - 1; y += v2) {
01835                 for (int x = v0; x <= nx - v0 - 1; x += v2) {
01836 
01837                         float sum = 0;
01838                         for (int y1 = y - v1; y1 <= y + v1; y1++) {
01839                                 for (int x1 = x - v1; x1 <= x + v1; x1++) {
01840                                         sum += data[x1 + y1 * nx];
01841                                 }
01842                         }
01843                         float mean = sum / ((v1 * 2 + 1) * (v1 * 2 + 1));
01844 
01845                         for (int j = y - v2; j <= y + v2; j++) {
01846                                 for (int i = x - v2; i <= x + v2; i++) {
01847                                         data[i + j * nx] = mean;
01848                                 }
01849                         }
01850                 }
01851         }
01852 
01853         image->update();
01854 }
01855 
01856 
01857 void CutoffBlockProcessor::process_inplace(EMData * image)
01858 {
01859         if (!image) {
01860                 LOGWARN("NULL Image");
01861                 return;
01862         }
01863         int nz = image->get_zsize();
01864 
01865         if (nz > 1) {
01866                 LOGERR("%s Processor doesn't support 3D", get_name().c_str());
01867                 throw ImageDimensionException("3D model not supported");
01868         }
01869 
01870         int nx = image->get_xsize();
01871         int ny = image->get_ysize();
01872 
01873         float value1 = params["value1"];
01874         float value2 = params["value2"];
01875 
01876         int v1 = (int) value1;
01877         int v2 = (int) value2;
01878         if (v2 > v1 / 2) {
01879                 LOGERR("invalid value2 '%f' in CutoffBlockProcessor", value2);
01880                 return;
01881         }
01882 
01883         if (v2 <= 0) {
01884                 v2 = v1;
01885         }
01886 
01887         float *data = image->get_data();
01888         int y = 0, x = 0;
01889         for (y = 0; y <= ny - v1; y += v1) {
01890                 for (x = 0; x <= nx - v1; x += v1) {
01891 
01892                         EMData *clip = image->get_clip(Region(x, y, v1, v1));
01893                         EMData *fft = clip->do_fft();
01894 
01895                         float *fft_data = fft->get_data();
01896                         float sum = 0;
01897                         int nitems = 0;
01898 
01899                         for (int i = -v2; i < v2; i++) {
01900                                 for (int j = 0; j < v2; j++) {
01901                                         if (j == 0 && i == 0) {
01902                                                 continue;
01903                                         }
01904 
01905 #ifdef  _WIN32
01906                                         if (_hypot(j, i) < value2) {
01907 #else
01908                                         if (hypot(j, i) < value2) {
01909 #endif
01910                                                 int t = j * 2 + (i + v1 / 2) * (v1 + 2);
01911                                                 sum += (fft_data[t] * fft_data[t] + fft_data[t + 1] * fft_data[t + 1]);
01912                                                 nitems++;
01913                                         }
01914                                 }
01915                         }
01916 
01917                         if( clip )
01918                         {
01919                                 delete clip;
01920                                 clip = 0;
01921                         }
01922 
01923                         float mean = sum / nitems;
01924 
01925                         for (int i = y; i < y + v1; i++) {
01926                                 for (int j = x; j < x + v1; j++) {
01927                                         data[i * nx + j] = mean;
01928                                 }
01929                         }
01930                 }
01931         }
01932 
01933         memset(&data[y * nx], 0, (ny - y) * nx * sizeof(float));
01934 
01935         for (int i = 0; i < ny; i++) {
01936                 memset(&data[i * nx + x], 0, (nx - x) * sizeof(float));
01937         }
01938 
01939         image->update();
01940 }
01941 
01942 void MedianShrinkProcessor::process_inplace(EMData * image)
01943 {
01944         if (image->is_complex()) throw ImageFormatException("Error, the median shrink processor does not work on complex images");
01945 
01946         int shrink_factor =  params.set_default("n",0);
01947         if (shrink_factor <= 1) {
01948                 throw InvalidValueException(shrink_factor,
01949                                                                         "median shrink: shrink factor must > 1");
01950         }
01951 
01952         int nx = image->get_xsize();
01953         int ny = image->get_ysize();
01954         int nz = image->get_zsize();
01955 
01956 //      if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) || (nz > 1 && (nz % shrink_factor != 0))) {
01957 //              throw InvalidValueException(shrink_factor, "Image size not divisible by shrink factor");
01958 //      }
01959 
01960 
01961         int shrunken_nx = nx / shrink_factor;
01962         int shrunken_ny = ny / shrink_factor;
01963         int shrunken_nz = 1;
01964         if (nz > 1) shrunken_nz = nz / shrink_factor;
01965 
01966         EMData* copy = image->copy();
01967         image->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
01968         accrue_median(image,copy,shrink_factor);
01969         image->update();
01970         if( copy )
01971         {
01972                 delete copy;
01973                 copy = 0;
01974         }
01975 }
01976 
01977 //
01978 EMData* MedianShrinkProcessor::process(const EMData *const image)
01979 {
01980         if (image->is_complex()) throw ImageFormatException("Error, the median shrink processor does not work on complex images");
01981 
01982         int shrink_factor =  params.set_default("n",0);
01983         if (shrink_factor <= 1) {
01984                 throw InvalidValueException(shrink_factor,
01985                                                                         "median shrink: shrink factor must > 1");
01986         }
01987         int nx = image->get_xsize();
01988         int ny = image->get_ysize();
01989         int nz = image->get_zsize();
01990 
01991 
01992 //      if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) || (nz > 1 && (nz % shrink_factor != 0))) {
01993 //              throw InvalidValueException(shrink_factor, "Image size not divisible by shrink factor");
01994 //      }
01995 
01996 
01997         int shrunken_nx = nx / shrink_factor;
01998         int shrunken_ny = ny / shrink_factor;
01999         int shrunken_nz = 1;
02000         if (nz > 1) shrunken_nz = nz / shrink_factor;
02001 
02002 //      EMData* ret = new EMData(shrunken_nx, shrunken_ny, shrunken_nz);
02003         EMData *ret = image->copy_head();
02004         ret->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
02005 
02006         accrue_median(ret,image,shrink_factor);
02007         ret->update();
02008         return ret;
02009 }
02010 
02011 void MedianShrinkProcessor::accrue_median(EMData* to, const EMData* const from,const int shrink_factor)
02012 {
02013 
02014         int nx_old = from->get_xsize();
02015         int ny_old = from->get_ysize();
02016 
02017         int threed_shrink_factor = shrink_factor * shrink_factor;
02018         int z_shrink_factor = 1;
02019         if (from->get_zsize() > 1) {
02020                 threed_shrink_factor *= shrink_factor;
02021                 z_shrink_factor = shrink_factor;
02022         }
02023 
02024         float *mbuf = new float[threed_shrink_factor];
02025 
02026 
02027         int nxy_old = nx_old * ny_old;
02028 
02029         int nx = to->get_xsize();
02030         int ny = to->get_ysize();
02031         int nz = to->get_zsize();
02032         int nxy_new = nx * ny;
02033 
02034         float * rdata = to->get_data();
02035         const float *const data_copy = from->get_const_data();
02036 
02037         for (int l = 0; l < nz; l++) {
02038                 int l_min = l * shrink_factor;
02039                 int l_max = l * shrink_factor + z_shrink_factor;
02040                 size_t cur_l = (size_t)l * nxy_new;
02041 
02042                 for (int j = 0; j < ny; j++) {
02043                         int j_min = j * shrink_factor;
02044                         int j_max = (j + 1) * shrink_factor;
02045                         size_t cur_j = j * nx + cur_l;
02046 
02047                         for (int i = 0; i < nx; i++) {
02048                                 int i_min = i * shrink_factor;
02049                                 int i_max = (i + 1) * shrink_factor;
02050 
02051                                 size_t k = 0;
02052                                 for (int l2 = l_min; l2 < l_max; l2++) {
02053                                         size_t cur_l2 = l2 * nxy_old;
02054 
02055                                         for (int j2 = j_min; j2 < j_max; j2++) {
02056                                                 size_t cur_j2 = j2 * nx_old + cur_l2;
02057 
02058                                                 for (int i2 = i_min; i2 < i_max; i2++) {
02059                                                         mbuf[k] = data_copy[i2 + cur_j2];
02060                                                         ++k;
02061                                                 }
02062                                         }
02063                                 }
02064 
02065                                 for (k = 0; k < size_t(threed_shrink_factor / 2 + 1); k++) {
02066                                         for (int i2 = k + 1; i2 < threed_shrink_factor; i2++) {
02067                                                 if (mbuf[i2] < mbuf[k]) {
02068                                                         float f = mbuf[i2];
02069                                                         mbuf[i2] = mbuf[k];
02070                                                         mbuf[k] = f;
02071                                                 }
02072                                         }
02073                                 }
02074 
02075                                 rdata[i + cur_j] = mbuf[threed_shrink_factor / 2];
02076                         }
02077                 }
02078         }
02079 
02080         if( mbuf )
02081         {
02082                 delete[]mbuf;
02083                 mbuf = 0;
02084         }
02085 
02086         to->scale_pixel((float)shrink_factor);
02087 }
02088 
02089 EMData* FFTResampleProcessor::process(const EMData *const image)
02090 {
02091         float sample_rate = params.set_default("n",0.0f);
02092         if (sample_rate <= 0.0F  )  {
02093                 throw InvalidValueException(sample_rate,        "sample rate must be >0 ");
02094         }
02095 
02096         EMData* result;
02097         if (image->is_complex()) result = image->copy();
02098         else result = image->do_fft();
02099         fft_resample(result,image,sample_rate);
02100         // The image may have been padded - we should shift it so that the phase origin is where FFTW expects it
02101         result->update();
02102         result->scale_pixel(sample_rate);
02103         return result;
02104 }
02105 
02106 void FFTResampleProcessor::process_inplace(EMData * image)
02107 {
02108         if (image->is_complex()) throw ImageFormatException("Error, the fft resampling processor does not work on complex images");
02109 
02110 
02111         float sample_rate = params.set_default("n",0.0f);
02112         if (sample_rate <= 0.0F  )  {
02113                 throw InvalidValueException(sample_rate,        "sample rate (n) must be >0 ");
02114         }
02115 
02116         fft_resample(image,image,sample_rate);
02117 
02118         image->scale_pixel(sample_rate);
02119         image->update();
02120 
02121 
02122 }
02123 
02124 void FFTResampleProcessor::fft_resample(EMData* to, const EMData *const from, const float& sample_rate) {
02125         int nx = from->get_xsize();
02126         int ny = from->get_ysize();
02127         int nz = from->get_zsize();
02128 
02129         int new_nx = static_cast<int>( static_cast<float> (nx) / sample_rate);
02130         int new_ny = static_cast<int>( static_cast<float> (ny) / sample_rate);
02131         int new_nz = static_cast<int>( static_cast<float> (nz) / sample_rate);
02132 
02133         if (new_nx == 0) throw UnexpectedBehaviorException("The resample rate causes the pixel dimensions in the x direction to go to zero");
02134         if (new_ny == 0) new_ny = 1;
02135         if (new_nz == 0) new_nz = 1;
02136 
02137         int ndim = from->get_ndim();
02138         if ( ndim < 3 ) {
02139                 new_nz = 1;
02140         }
02141         if ( ndim < 2 ) {
02142                 new_ny = 1;
02143         }
02144 
02145         int fft_x_correction = 1;
02146         if (new_nx % 2 == 0) fft_x_correction = 2;
02147 
02148         int fft_y_correction = 0;
02149         if (ny != 1 && new_ny % 2 == 0 && ny % 2 == 1) fft_y_correction = 1;
02150         else if (ny != 1 && new_ny % 2 == 1 && ny % 2 == 0) fft_y_correction = -1;
02151 
02152         int fft_z_correction = 0;
02153         if (nz != 1 && new_nz % 2 == 0 && nz % 2 == 1) fft_z_correction = 1;
02154         else if (nz != 1 && new_nz % 2 == 1 && nz % 2 == 0) fft_z_correction = -1;
02155 
02156         if ( ! to->is_complex()) to->do_fft_inplace();
02157 
02158         if (ndim != 1) to->process_inplace("xform.fourierorigin.tocenter");
02159 
02160         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);
02161         to->clip_inplace(clip);
02162 
02163         if (fft_x_correction == 1) to->set_fftodd(true);
02164         else to->set_fftodd(false);
02165 
02166         if (ndim != 1) to->process_inplace("xform.fourierorigin.tocorner");
02167 
02168         to->do_ift_inplace();
02169         to->depad_corner();
02170 
02171 }
02172 
02173 
02174 EMData* MeanShrinkProcessor::process(const EMData *const image)
02175 {
02176         if (image->is_complex()) throw ImageFormatException("Error, the mean shrink processor does not work on complex images");
02177 
02178         if (image->get_ndim() == 1) { throw ImageDimensionException("Error, mean shrink works only for 2D & 3D images"); }
02179 
02180         float shrink_factor0 = params.set_default("n",0.0f);
02181         int shrink_factor = int(shrink_factor0);
02182         if (shrink_factor0 <= 1.0F || ((shrink_factor0 != shrink_factor) && (shrink_factor0 != 1.5F) ) ) {
02183                 throw InvalidValueException(shrink_factor0,
02184                                                                         "mean shrink: shrink factor must be >1 integer or 1.5");
02185         }
02186 
02187         int nx = image->get_xsize();
02188         int ny = image->get_ysize();
02189         int nz = image->get_zsize();
02190 
02191 
02192         // here handle the special averaging by 1.5 for 2D case
02193         if (shrink_factor0==1.5 ) {
02194                 if (nz > 1 ) throw InvalidValueException(shrink_factor0, "mean shrink: only support 2D images for shrink factor = 1.5");
02195 
02196                 int shrunken_nx = (int(nx / 1.5)+1)/2*2;        // make sure the output size is even
02197                 int shrunken_ny = (int(ny / 1.5)+1)/2*2;
02198                 EMData* result = new EMData(shrunken_nx,shrunken_ny,1);
02199 
02200                 accrue_mean_one_p_five(result,image);
02201                 result->update();
02202 
02203                 return result;
02204         }
02205 
02206         int shrunken_nx = nx / shrink_factor;
02207         int shrunken_ny = ny / shrink_factor;
02208         int shrunken_nz = 1;
02209 
02210         if (nz > 1) {
02211                 shrunken_nz = nz / shrink_factor;
02212         }
02213 
02214 //      EMData* result = new EMData(shrunken_nx,shrunken_ny,shrunken_nz);
02215         EMData* result = image->copy_head();
02216         result->set_size(shrunken_nx,shrunken_ny,shrunken_nz);
02217         accrue_mean(result,image,shrink_factor);
02218 
02219         result->update();
02220 
02221         return result;
02222 }
02223 
02224 void MeanShrinkProcessor::process_inplace(EMData * image)
02225 {
02226         if (image->is_complex()) throw ImageFormatException("Error, the mean shrink processor does not work on complex images");
02227 
02228         if (image->get_ndim() == 1) { throw ImageDimensionException("Error, mean shrink works only for 2D & 3D images"); }
02229 
02230         float shrink_factor0 = params.set_default("n",0.0f);
02231         int shrink_factor = int(shrink_factor0);
02232         if (shrink_factor0 <= 1.0F || ((shrink_factor0 != shrink_factor) && (shrink_factor0 != 1.5F) ) ) {
02233                 throw InvalidValueException(shrink_factor0,
02234                                                                         "mean shrink: shrink factor must be >1 integer or 1.5");
02235         }
02236 
02237 /*      if ((nx % shrink_factor != 0) || (ny % shrink_factor != 0) ||
02238         (nz > 1 && (nz % shrink_factor != 0))) {
02239         throw InvalidValueException(shrink_factor,
02240         "Image size not divisible by shrink factor");
02241 }*/
02242 
02243         int nx = image->get_xsize();
02244         int ny = image->get_ysize();
02245         int nz = image->get_zsize();
02246         // here handle the special averaging by 1.5 for 2D case
02247         if (shrink_factor0==1.5 ) {
02248                 if (nz > 1 ) throw InvalidValueException(shrink_factor0, "mean shrink: only support 2D images for shrink factor = 1.5");
02249 
02250                 int shrunken_nx = (int(nx / 1.5)+1)/2*2;        // make sure the output size is even
02251                 int shrunken_ny = (int(ny / 1.5)+1)/2*2;
02252 
02253                 EMData* orig = image->copy();
02254                 image->set_size(shrunken_nx, shrunken_ny, 1);   // now nx = shrunken_nx, ny = shrunken_ny
02255                 image->to_zero();
02256 
02257                 accrue_mean_one_p_five(image,orig);
02258 
02259                 if( orig ) {
02260                         delete orig;
02261                         orig = 0;
02262                 }
02263                 image->update();
02264 
02265                 return;
02266         }
02267 
02268         accrue_mean(image,image,shrink_factor);
02269 
02270         int shrunken_nx = nx / shrink_factor;
02271         int shrunken_ny = ny / shrink_factor;
02272         int shrunken_nz = 1;
02273         if (nz > 1) shrunken_nz = nz / shrink_factor;
02274 
02275         image->update();
02276         image->set_size(shrunken_nx, shrunken_ny, shrunken_nz);
02277 }
02278 
02279 void MeanShrinkProcessor::accrue_mean(EMData* to, const EMData* const from,const int shrink_factor)
02280 {
02281         const float * const data = from->get_const_data();
02282         float* rdata = to->get_data();
02283 
02284         size_t nx = from->get_xsize();
02285         size_t ny = from->get_ysize();
02286         size_t nz = from->get_zsize();
02287         size_t nxy = nx*ny;
02288 
02289 
02290         size_t shrunken_nx = nx / shrink_factor;
02291         size_t shrunken_ny = ny / shrink_factor;
02292         size_t shrunken_nz = 1;
02293         size_t shrunken_nxy = shrunken_nx * shrunken_ny;
02294 
02295         int normalize_shrink_factor = shrink_factor * shrink_factor;
02296         int z_shrink_factor = 1;
02297 
02298         if (nz > 1) {
02299                 shrunken_nz = nz / shrink_factor;
02300                 normalize_shrink_factor *= shrink_factor;
02301                 z_shrink_factor = shrink_factor;
02302         }
02303 
02304         float invnormfactor = 1.0f/(float)normalize_shrink_factor;
02305 
02306         for (size_t k = 0; k < shrunken_nz; k++) {
02307                 size_t k_min = k * shrink_factor;
02308                 size_t k_max = k * shrink_factor + z_shrink_factor;
02309                 size_t cur_k = k * shrunken_nxy;
02310 
02311                 for (size_t j = 0; j < shrunken_ny; j++) {
02312                         size_t j_min = j * shrink_factor;
02313                         size_t j_max = j * shrink_factor + shrink_factor;
02314                         size_t cur_j = j * shrunken_nx + cur_k;
02315 
02316                         for (size_t i = 0; i < shrunken_nx; i++) {
02317                                 size_t i_min = i * shrink_factor;
02318                                 size_t i_max = i * shrink_factor + shrink_factor;
02319 
02320                                 float sum = 0;
02321                                 for (size_t kk = k_min; kk < k_max; kk++) {
02322                                         size_t cur_kk = kk * nxy;
02323 
02324                                         for (size_t jj = j_min; jj < j_max; jj++) {
02325                                                 size_t cur_jj = jj * nx + cur_kk;
02326                                                 for (size_t ii = i_min; ii < i_max; ii++) {
02327                                                         sum += data[ii + cur_jj];
02328                                                 }
02329                                         }
02330                                 }
02331                                 rdata[i + cur_j] = sum * invnormfactor;
02332                         }
02333                 }
02334         }
02335         to->scale_pixel((float)shrink_factor);
02336 }
02337 
02338 
02339 void MeanShrinkProcessor::accrue_mean_one_p_five(EMData* to, const EMData * const from)
02340 {
02341         int nx0 = from->get_xsize(), ny0 = from->get_ysize();   // the original size
02342 
02343         int nx = to->get_xsize(), ny = to->get_ysize();
02344 
02345         float *data = to->get_data();
02346         const float * const data0 = from->get_const_data();
02347 
02348         for (int j = 0; j < ny; j++) {
02349                 int jj = int(j * 1.5);
02350                 float jw0 = 1.0F, jw1 = 0.5F;   // 3x3 -> 2x2, so each new pixel should have 2.25 of the old pixels
02351                 if ( j%2 ) {
02352                         jw0 = 0.5F;
02353                         jw1 = 1.0F;
02354                 }
02355                 for (int i = 0; i < nx; i++) {
02356                         int ii = int(i * 1.5);
02357                         float iw0 = 1.0F, iw1 = 0.5F;
02358                         float w = 0.0F;
02359 
02360                         if ( i%2 ) {
02361                                 iw0 = 0.5F;
02362                                 iw1 = 1.0F;
02363                         }
02364                         if ( jj < ny0 ) {
02365                                 if ( ii < nx0 ) {
02366                                         data[j * nx + i] = data0[ jj * nx0 + ii ] * jw0 * iw0 ;
02367                                         w += jw0 * iw0 ;
02368                                         if ( ii+1 < nx0 ) {
02369                                                 data[j * nx + i] += data0[ jj * nx0 + ii + 1] * jw0 * iw1;
02370                                                 w += jw0 * iw1;
02371                                         }
02372                                 }
02373                                 if ( jj +1 < ny0 ) {
02374                                         if ( ii < nx0 ) {
02375                                                 data[j * nx + i] += data0[ (jj+1) * nx0 + ii ] * jw1 * iw0;
02376                                                 w += jw1 * iw0;
02377                                                 if ( ii+1 < nx0 ) {
02378                                                         data[j * nx + i] += data0[ (jj+1) * nx0 + ii + 1] * jw1 * iw1;
02379                                                         w += jw1 * iw1;
02380                                                 }
02381                                         }
02382                                 }
02383                         }
02384                         if ( w>0 ) data[j * nx + i] /= w;
02385                 }
02386         }
02387 
02388         to->update();
02389         to->scale_pixel((float)1.5);
02390 }
02391 
02392 // This would have to be moved into the header if it were required in other source files
02393 template<class LogicOp>
02394 EMData* BooleanShrinkProcessor::process(const EMData *const image, Dict& params)
02395 {
02396         // The basic idea of this code is to iterate through each pixel in the output image
02397         // determining its value by investigation a region of the input image
02398 
02399         if (!image) throw NullPointerException("Attempt to max shrink a null image");
02400 
02401         if (image->is_complex() ) throw ImageFormatException("Can not max shrink a complex image");
02402 
02403 
02404         int shrink = params.set_default("n",2);
02405         int search = params.set_default("search",2);
02406 
02407         if ( shrink < 0 ) throw InvalidValueException(shrink, "Can not shrink by a value less than 0");
02408 
02409 
02410         int nz = image->get_zsize();
02411         int ny = image->get_ysize();
02412         int nx = image->get_xsize();
02413 
02414         if (nx == 1 && ny == 1 && nz == 1 ) return image->copy();
02415 
02416         LogicOp op;
02417         EMData* return_image = new EMData();
02418 
02419         int shrinkx = shrink;
02420         int shrinky = shrink;
02421         int shrinkz = shrink;
02422 
02423         int searchx = search;
02424         int searchy = search;
02425         int searchz = search;
02426 
02427         // Clamping the shrink values to the dimension lengths
02428         // ensures that the return image has non zero dimensions
02429         if ( shrinkx > nx ) shrinkx = nx;
02430         if ( shrinky > ny ) shrinky = ny;
02431         if ( shrinkz > nz ) shrinkz = nz;
02432 
02433         if ( nz == 1 && ny == 1 )
02434         {
02435                 return_image->set_size(nx/shrinkx);
02436                 for(int i = 0; i < nx/shrinkx; ++i)
02437                 {
02438                         float tmp = op.get_start_val();
02439                         for(int s=0; s < searchx; ++s)
02440                         {
02441                                 int idx = shrinkx*i+s;
02442                                 // Don't ask for memory beyond limits
02443                                 if ( idx > nx ) break;
02444                                 else
02445                                 {
02446                                         float val = image->get_value_at(idx);
02447                                         if ( op( val,tmp) ) tmp = val;
02448                                 }
02449                         }
02450                         return_image->set_value_at(i,tmp);
02451                 }
02452         }
02453         else if ( nz == 1 )
02454         {
02455                 int ty = ny/shrinky;
02456                 int tx = nx/shrinkx;
02457                 return_image->set_size(tx,ty);
02458                 for(int y = 0; y < ty; ++y) {
02459                         for(int x = 0; x < tx; ++x) {
02460                                 float tmp = op.get_start_val();
02461                                 for(int sy=0; sy < searchy; ++sy) {
02462                                         int yidx = shrinky*y+sy;
02463                                         if ( yidx >= ny) break;
02464                                         for(int sx=0; sx < searchx; ++sx) {
02465                                                 int xidx = shrinkx*x+sx;
02466                                                 if ( xidx >= nx) break;
02467 
02468                                                 float val = image->get_value_at(xidx,yidx);
02469                                                 if ( op( val,tmp) ) tmp = val;
02470                                         }
02471                                 }
02472                                 return_image->set_value_at(x,y,tmp);
02473                         }
02474                 }
02475         }
02476         else
02477         {
02478                 int tz = nz/shrinkz;
02479                 int ty = ny/shrinky;
02480                 int tx = nx/shrinkx;
02481 
02482                 return_image->set_size(tx,ty,tz);
02483                 for(int z = 0; z < tz; ++z) {
02484                         for(int y = 0; y < ty; ++y) {
02485                                 for(int x = 0; x < tx; ++x) {
02486                                         float tmp = op.get_start_val();
02487 
02488                                         for(int sz=0; sz < searchz; ++sz) {
02489                                                 int zidx = shrinkz*z+sz;
02490                                                 if ( zidx >= nz) break;
02491 
02492                                                 for(int sy=0; sy < searchy; ++sy) {
02493                                                         int yidx = shrinky*y+sy;
02494                                                         if ( yidx >= ny) break;
02495 
02496                                                         for(int sx=0; sx < searchx; ++sx) {
02497                                                                 int xidx = shrinkx*x+sx;
02498                                                                 if ( xidx >= nx) break;
02499                                                                 float val = image->get_value_at(xidx,yidx,zidx);
02500                                                                 if ( op( val,tmp) ) tmp = val;
02501                                                         }
02502                                                 }
02503                                         }
02504                                         return_image->set_value_at(x,y,z,tmp);
02505                                 }
02506                         }
02507                 }
02508         }
02509         return_image->update();
02510 
02511         return return_image;
02512 }
02513 
02514 template<class LogicOp>
02515 void BooleanShrinkProcessor::process_inplace(EMData * image, Dict& params)
02516 {
02517         // The basic idea of this code is to iterate through each pixel in the output image
02518         // determining its value by investigation a region of the input image
02519         if (!image) throw NullPointerException("Attempt to max shrink a null image");
02520 
02521         if (image->is_complex() ) throw ImageFormatException("Can not max shrink a complex image");
02522 
02523 
02524         int shrink = params.set_default("shrink",2);
02525         int search = params.set_default("search",2);
02526 
02527         if ( shrink < 0 ) throw InvalidValueException(shrink, "Can not shrink by a value less than 0");
02528 
02529 
02530         int nz = image->get_zsize();
02531         int ny = image->get_ysize();
02532         int nx = image->get_xsize();
02533 
02534         LogicOp op;
02535 
02536         int shrinkx = shrink;
02537         int shrinky = shrink;
02538         int shrinkz = shrink;
02539 
02540         int searchx = search;
02541         int searchy = search;
02542         int searchz = search;
02543 
02544         // Clamping the shrink values to the dimension lengths
02545         // ensures that the return image has non zero dimensions
02546         if ( shrinkx > nx ) shrinkx = nx;
02547         if ( shrinky > ny ) shrinkx = ny;
02548         if ( shrinkz > nz ) shrinkx = nz;
02549 
02550         if (nx == 1 && ny == 1 && nz == 1 ) return;
02551 
02552         if ( nz == 1 && ny == 1 )
02553         {
02554                 for(int i = 0; i < nx/shrink; ++i)
02555                 {
02556                         float tmp = op.get_start_val();
02557                         for(int s=0; s < searchx; ++s)
02558                         {
02559                                 int idx = shrinkx*i+s;
02560                                 if ( idx > nx ) break;
02561                                 else
02562                                 {
02563                                         float val = image->get_value_at(idx);
02564                                         if ( op( val,tmp) ) tmp = val;
02565                                 }
02566                         }
02567                         image->set_value_at(i,tmp);
02568                 }
02569 
02570                 image->set_size(nx/shrinkx);
02571         }
02572         else if ( nz == 1 )
02573         {
02574                 int ty = ny/shrinky;
02575                 int tx = nx/shrinkx;
02576                 for(int y = 0; y < ty; ++y) {
02577                         for(int x = 0; x < tx; ++x) {
02578                                 float tmp = op.get_start_val();
02579                                 for(int sy=0; sy < searchy; ++sy) {
02580                                         int yidx = shrinky*y+sy;
02581                                         if ( yidx >= ny) break;
02582                                         for(int sx=0; sx < searchx; ++sx) {
02583                                                 int xidx = shrinkx*x+sx;
02584                                                 if ( xidx >= nx) break;
02585 
02586                                                 float val = image->get_value_at(xidx,yidx);
02587                                                 if ( op( val,tmp) ) tmp = val;
02588                                         }
02589                                 }
02590                                 (*image)(x+tx*y) = tmp;
02591                         }
02592                 }
02593                 image->set_size(tx,ty);
02594         }
02595         else
02596         {
02597                 int tnxy = nx/shrinkx*ny/shrinky;
02598                 int tz = nz/shrinkz;
02599                 int ty = ny/shrinky;
02600                 int tx = nx/shrinkx;
02601 
02602                 for(int z = 0; z < tz; ++z) {
02603                         for(int y = 0; y < ty; ++y) {
02604                                 for(int x = 0; x < tx; ++x) {
02605                                         float tmp = op.get_start_val();
02606                                         for(int sz=0; sz < searchz; ++sz) {
02607                                                 int zidx = shrinkz*z+sz;
02608                                                 if ( zidx >= nz) break;
02609                                                 for(int sy=0; sy < searchy; ++sy) {
02610                                                         int yidx = shrinky*y+sy;
02611                                                         if ( yidx >= ny) break;
02612                                                         for(int sx=0; sx < shrinkx; ++sx) {
02613                                                                 int xidx = shrinkx*x+sx;
02614                                                                 if ( xidx >= nx) break;
02615 
02616                                                                 float val = image->get_value_at(xidx,yidx,zidx);
02617                                                                 if ( op( val,tmp) ) tmp = val;
02618                                                         }
02619                                                 }
02620                                         }
02621                                         (*image)(x+tx*y+tnxy*z) = tmp;
02622                                 }
02623                         }
02624                 }
02625                 image->set_size(tx,ty,tz);
02626         }
02627         image->update();
02628 }
02629 
02630 
02631 
02632 void GradientRemoverProcessor::process_inplace(EMData * image)
02633 {
02634         if (!image) {
02635                 LOGWARN("NULL Image");
02636                 return;
02637         }
02638 
02639         int nz = image->get_zsize();
02640         if (nz > 1) {
02641                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
02642                 throw ImageDimensionException("3D model not supported");
02643         }
02644 
02645         int nx = image->get_xsize();
02646         int ny = image->get_ysize();
02647         float *dy = new float[ny];
02648         float m = 0;
02649         float b = 0;
02650         float sum_y = 0;
02651         float *data = image->get_data();
02652 
02653         for (int i = 0; i < ny; i++) {
02654                 Util::calc_least_square_fit(nx, 0, data + i * nx, &m, &b, false);
02655                 dy[i] = b;
02656                 sum_y += m;
02657         }
02658 
02659         float mean_y = sum_y / ny;
02660         float sum_x = 0;
02661         Util::calc_least_square_fit(ny, 0, dy, &sum_x, &b, false);
02662 
02663         for (int j = 0; j < ny; j++) {
02664                 for (int i = 0; i < nx; i++) {
02665                         data[i + j * nx] -= i * sum_x + j * mean_y + b;
02666                 }
02667         }
02668 
02669         image->update();
02670 }
02671 
02672 void FlattenBackgroundProcessor::process_inplace(EMData * image)
02673 {
02674 
02675         EMData* mask = params.set_default("mask",(EMData*)0);
02676         int radius = params.set_default("radius",0);
02677 
02678         if (radius != 0 && mask != 0) throw InvalidParameterException("Error - the mask and radius parameters are mutually exclusive.");
02679 
02680         if (mask == 0 && radius == 0) throw InvalidParameterException("Error - you must specify either the mask or the radius parameter.");
02681 
02682         // If the radius isn't 0, then turn the mask into the thing we want...
02683         bool deletemask = false;
02684         if (radius != 0) {
02685                 mask = new EMData;
02686                 int n = image->get_ndim();
02687                 if (n==1){
02688                         mask->set_size(2*radius+1);
02689                 } else if (n==2) {
02690                         mask->set_size(2*radius+1,2*radius+1);
02691                 }
02692                 else /*n==3*/ {
02693                         mask->set_size(2*radius+1,2*radius+1,2*radius+1);
02694                 }
02695                 // assuming default behavior is to make a circle/sphere with using the radius of the mask
02696                 mask->process_inplace("testimage.circlesphere");
02697         }
02698 
02699         // Double check that that mask isn't too big
02700         int mnx = mask->get_xsize(); int mny = mask->get_ysize(); int mnz = mask->get_zsize();
02701         int nx = image->get_xsize(); int ny = image->get_ysize(); int nz = image->get_zsize();
02702         int nxc = nx+mnx; int nyc = ny+mny; int nzc = nz+mnz;
02703         if (nz == 1) nzc = 1; // Sanity check
02704         if (ny == 1) nyc = 1; // Sanity check
02705 
02706         if ( mnx > nx || mny > ny || mnz > nz)
02707                 throw ImageDimensionException("Can not flatten using a mask that is larger than the image.");
02708 
02709         // Get the normalization factor
02710         float normfac = 0.0;
02711         for (int i=0; i<mask->get_xsize()*mask->get_ysize()*mask->get_zsize(); ++i){
02712                 normfac += mask->get_value_at(i);
02713         }
02714         // If the sum is zero the user probably doesn't understand that determining a measure of the mean requires
02715         // strictly positive numbers. The user has specified a mask that consists entirely of zeros, or the mask
02716         // has a mean of zero.
02717         if (normfac == 0) throw InvalidParameterException("Error - the pixels in the mask sum to zero. This breaks the flattening procedure");
02718         normfac = 1.0f/normfac;
02719 
02720         // The mask can now be automatically resized to the dimensions of the image
02721 //      bool undoclip = false;
02722 
02723         Region r;
02724         if (ny == 1) r = Region((mnx-nxc)/2,nxc);
02725         else if (nz == 1) r = Region((mnx-nxc)/2, (mny-nyc)/2,nxc,nyc);
02726         else r = Region((mnx-nxc)/2, (mny-nyc)/2,(mnz-nzc)/2,nxc,nyc,nzc);
02727         mask->clip_inplace(r,0);
02728 //      undoclip = true;
02729 //      if ( mnx < nx || mny < ny || mnz < nz) {
02730 //              Region r((mnx-nx)/2, (mny-ny)/2,(mnz-nz)/2,nx,ny,nz);
02731 //              mask->clip_inplace(r);
02732 //              undoclip = true;
02733 //      }
02734 
02735         Region r2;
02736         if (ny == 1) r2 = Region((nx-nxc)/2,nxc);
02737         else if (nz == 1) r2 = Region((nx-nxc)/2, (ny-nyc)/2,nxc,nyc);
02738         else r2 = Region((nx-nxc)/2, (ny-nyc)/2,(nz-nzc)/2,nxc,nyc,nzc);
02739         image->clip_inplace(r2,image->get_edge_mean());
02740         // Finally do the convolution
02741         EMData* m = image->convolute(mask);
02742         // Normalize so that m is truly the local mean
02743         m->mult(normfac);
02744         // Before we can subtract, the mean must be phase shifted
02745         m->process_inplace("xform.phaseorigin.tocenter");
02746         // Subtract the local mean
02747 //      image->write_image("a.mrc");
02748 //      m->write_image("b.mrc");
02749         image->sub(*m); // WE'RE DONE!
02750         delete m;
02751 
02752         if (deletemask) {
02753                 delete mask;
02754         } else { // I clipped it inplace, so undo this clipping so the user gets back what the put in
02755                 Region r;
02756                 if (ny == 1) r = Region((nxc-mnx)/2,mnx);
02757                 else if (nz == 1) r = Region((nxc-mnx)/2, (nyc-mny)/2,mnx,mny);
02758                 else r = Region((nxc-mnx)/2, (nyc-mny)/2,(nzc-mnz)/2,mnx,mny,mnz);
02759                 mask->clip_inplace(r);
02760         }
02761 
02762         Region r3;
02763         if (ny == 1) r3 = Region((nxc-nx)/2,nx);
02764         else if (nz == 1) r3 = Region((nxc-nx)/2, (nyc-ny)/2,nx,ny);
02765         else r3 = Region((nxc-nx)/2, (nyc-ny)/2,(nzc-nz)/2,nx,ny,nz);
02766         image->clip_inplace(r3);
02767 //      if ( undoclip ) {
02768 //              Region r((nx-mnx)/2, (ny-mny)/2, (nz-mnz)/2,mnx,mny,mnz);
02769 //              mask->clip_inplace(r);
02770 //      }
02771 
02772 }
02773 
02774 void NonConvexProcessor::process_inplace(EMData * image) {
02775         if (!image) { LOGWARN("NULL IMAGE"); return; }
02776         //int isinten=image->get_attr_default("is_intensity",0);
02777         
02778         // 1-D
02779         if (image->get_ysize()==1) {
02780                 
02781         }
02782         // 2-D
02783         else if (image->get_zsize()==1) {
02784 //              if (!isinten) throw ImageDimensionException("Only complex intensity images currently supported by NonConvexProcessor");
02785                 int nx2=image->get_xsize()/2;
02786                 int ny2=image->get_ysize()/2;
02787                 vector<float> rdist = image->calc_radial_dist(nx2*1.5,0,1,false);               // radial distribution to make sure nonconvex values decrease radially
02788                 // Make sure rdist is decreasing (or flat)
02789                 for (int i=1; i<nx2; i++) {
02790                         if (rdist[i]>rdist[i-1]) rdist[i]=rdist[i-1];
02791                 }
02792                 
02793                 image->process_inplace("xform.fourierorigin.tocenter");
02794                 EMData* binary=image->copy();
02795                 
02796                 // First we eliminate convex points from the input image (set to zero)
02797                 for (int x=0; x<image->get_xsize(); x+=2) {
02798                         for (int y=1; y<image->get_ysize()-1; y++) {
02799                                 int r=(int)hypot((float)(x/2),(float)(y-ny2));
02800                                 float cen=(*binary)(x,y);
02801                                 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
02802                                         image->set_value_at_fast(x/2+nx2,y,0.0);        // we are turning image into a full real-space intensity image for now
02803                                         image->set_value_at_fast(nx2-x/2,ny2*2-y-1,0.0);
02804                                 }
02805                                 else {
02806                                         image->set_value_at_fast(x/2+nx2,y,cen);        // 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,cen);        // It will contain non-zero values only for nonconvex points
02808                                 }
02809                         }
02810                 }
02811                 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
02812                 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
02813                 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
02814                 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
02815                 for (int y=0; y<ny2*2; y++) image->set_value_at_fast(0,y,0.0f);
02816                 
02817                 // Now make a binary version of the convex points
02818                 float *idat=image->get_data();
02819                 float *bdat=binary->get_data();
02820                 int nxy=(nx2*ny2*4);
02821                 for (int i=0; i<nxy; i++) {
02822                         bdat[i]=idat[i]==0?0:1.0f;              // binary version of the convex points in image
02823                 }
02824                 binary->update();
02825                 
02826                 // We now use a Gaussian filter on both images, to use Gaussian interpolation to fill in zero values
02827                 image->set_complex(false);              // so we can use a Gaussian filter on it 
02828                 binary->set_complex(false);
02829 
02830 /*              image->write_image("con.hdf",0);*/
02831                 image->set_fftpad(false);
02832                 binary->set_fftpad(false);
02833                 
02834                 // Gaussian blur of both images
02835                 image->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs",0.04f));
02836                 binary->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs",0.04f));
02837 
02838 /*              image->write_image("con.hdf",1);
02839                 binary->write_image("con.hdf",2);*/
02840                 
02841                 for (int x=0; x<image->get_xsize(); x+=2) {
02842                         for (int y=0; y<image->get_ysize(); y++) {
02843                                 float bv=binary->get_value_at(x/2+nx2,y);
02844                                 image->set_value_at_fast(x,y,image->get_value_at(x/2+nx2,y)/(bv<=0?1.0f:bv));
02845                                 image->set_value_at_fast(x+1,y,0.0);
02846                         }
02847                 }
02848                 image->set_complex(true);
02849                 image->set_fftpad(true);
02850                 image->process_inplace("xform.fourierorigin.tocorner");
02851                 delete binary;
02852         }
02853         else throw ImageDimensionException("3D maps not yet supported by NonConvexProcessor");
02854         
02855 }
02856 
02857 
02858 #include <gsl/gsl_linalg.h>
02859 void GradientPlaneRemoverProcessor::process_inplace(EMData * image)
02860 {
02861         if (!image) {
02862                 LOGWARN("NULL Image");
02863                 return;
02864         }
02865 
02866         int nz = image->get_zsize();
02867         if (nz > 1) {
02868                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
02869                 throw ImageDimensionException("3D map not supported");
02870         }
02871 
02872         int nx = image->get_xsize();
02873         int ny = image->get_ysize();
02874         float *d = image->get_data();
02875         EMData *mask = 0;
02876         float *dm = 0;
02877         if (params.has_key("mask")) {
02878                 mask = params["mask"];
02879                 if (nx!=mask->get_xsize() || ny!=mask->get_ysize()) {
02880                         LOGERR("%s Processor requires same size mask image", get_name().c_str());
02881                         throw ImageDimensionException("wrong size mask image");
02882                 }
02883                 dm = mask->get_data();
02884         }
02885         int count = 0;
02886         if (dm) {
02887                 for(int i=0; i<nx*ny; i++) {
02888                         if(dm[i]) count++;
02889                 }
02890         }
02891         else {
02892                 count = nx * ny;
02893         }
02894         if(count<3) {
02895                 LOGERR("%s Processor requires at least 3 pixels to fit a plane", get_name().c_str());
02896                 throw ImageDimensionException("too few usable pixels to fit a plane");
02897         }
02898         // Allocate the working space
02899         gsl_vector *S=gsl_vector_calloc(3);
02900         gsl_matrix *A=gsl_matrix_calloc(count,3);
02901         gsl_matrix *V=gsl_matrix_calloc(3,3);
02902 
02903         double m[3] = {0, 0, 0};
02904         int index=0;
02905         if (dm) {
02906                 for(int j=0; j<ny; j++){
02907                         for(int i=0; i<nx; i++){
02908                                 int ij=j*nx+i;
02909                                 if(dm[ij]) {
02910                                         m[0]+=i;        // x
02911                                         m[1]+=j;        // y
02912                                         m[2]+=d[ij];    // z
02913                                         /*printf("index=%d/%d\ti,j=%d,%d\tval=%g\txm,ym,zm=%g,%g,%g\n", \
02914                                                 index,count,i,j,d[ij],m[0]/(index+1),m[1]/(index+1),m[2]/(index+1));*/
02915                                         index++;
02916                                 }
02917                         }
02918                 }
02919         }
02920         else {
02921                 for(int j=0; j<ny; j++){
02922                         for(int i=0; i<nx; i++){
02923                                 int ij=j*nx+i;
02924                                         m[0]+=i;        // x
02925                                         m[1]+=j;        // y
02926                                         m[2]+=d[ij];    // z
02927                                         /*printf("index=%d/%d\ti,j=%d,%d\tval=%g\txm,ym,zm=%g,%g,%g\n", \
02928                                                 index,count,i,j,d[ij],m[0]/(index+1),m[1]/(index+1),m[2]/(index+1));*/
02929                                         index++;
02930                         }
02931                 }
02932         }
02933 
02934         for(int i=0; i<3; i++) m[i]/=count;     // compute center of the plane
02935 
02936         index=0;
02937         if (dm) {
02938                 for(int j=0; j<ny; j++){
02939                         for(int i=0; i<nx; i++){
02940                                 int ij=j*nx+i;
02941                                 if(dm[ij]) {
02942                                         //printf("index=%d/%d\ti,j=%d,%d\tval=%g\n",index,count,i,j,d[index]);
02943                                         gsl_matrix_set(A,index,0,i-m[0]);
02944                                         gsl_matrix_set(A,index,1,j-m[1]);
02945                                         gsl_matrix_set(A,index,2,d[ij]-m[2]);
02946                                         index++;
02947                                 }
02948                         }
02949                 }
02950                 mask->update();
02951         }
02952         else {
02953                 for(int j=0; j<ny; j++){
02954                         for(int i=0; i<nx; i++){
02955                                 int ij=j*nx+i;
02956                                         //printf("index=%d/%d\ti,j=%d,%d\tval=%g\n",index,count,i,j,d[index]);
02957                                         gsl_matrix_set(A,index,0,i-m[0]);
02958                                         gsl_matrix_set(A,index,1,j-m[1]);
02959                                         gsl_matrix_set(A,index,2,d[ij]-m[2]);
02960                                         index++;
02961                         }
02962                 }
02963         }
02964 
02965         // SVD decomposition and use the V vector associated with smallest singular value as the plan normal
02966         gsl_linalg_SV_decomp_jacobi(A, V, S);
02967 
02968         double n[3];
02969         for(int i=0; i<3; i++) n[i] = gsl_matrix_get(V, i, 2);
02970 
02971         #ifdef DEBUG
02972         printf("S=%g,%g,%g\n",gsl_vector_get(S,0), gsl_vector_get(S,1), gsl_vector_get(S,2));
02973         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));
02974         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));
02975         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));
02976         printf("Fitted plane: p0=%g,%g,%g\tn=%g,%g,%g\n",m[0],m[1],m[2],n[0],n[1],n[2]);
02977         #endif
02978 
02979         int changeZero = 0;
02980         if (params.has_key("changeZero")) changeZero = params["changeZero"];
02981         if (changeZero) {
02982                 for(int j=0; j<nx; j++){
02983                         for(int i=0; i<ny; i++){
02984                                 int ij = j*nx+i;
02985                                 d[ij]-=static_cast<float>(-((i-m[0])*n[0]+(j-m[1])*n[1])/n[2]+m[2]);
02986                         }
02987                 }
02988         }
02989         else {
02990                 for(int j=0; j<nx; j++){
02991                         for(int i=0; i<ny; i++){
02992                                 int ij = j*nx+i;
02993                                 if(d[ij]) d[ij]-=static_cast<float>(-((i-m[0])*n[0]+(j-m[1])*n[1])/n[2]+m[2]);
02994                         }
02995                 }
02996         }
02997         image->update();
02998         // set return plane parameters
02999         vector< float > planeParam;
03000         planeParam.resize(6);
03001         for(int i=0; i<3; i++) planeParam[i] = static_cast<float>(n[i]);
03002         for(int i=0; i<3; i++) planeParam[i+3] = static_cast<float>(m[i]);
03003         params["planeParam"]=EMObject(planeParam);
03004 }
03005 
03006 void VerticalStripeProcessor::process_inplace(EMData * image)
03007 {
03008         if (!image) {
03009                 LOGWARN("NULL Image");
03010                 return;
03011         }
03012 
03013         int nx = image->get_xsize();
03014         int ny = image->get_ysize();
03015         int nz = image->get_zsize();
03016 
03017         float *data = image->get_data();
03018         float sigma = image->get_attr("sigma");
03019 
03020         for (int k = 0; k < nz; k++) {
03021                 for (int i = 0; i < nx; i++) {
03022                         double sum = 0;
03023                         for (int j = ny / 4; j < 3 * ny / 4; j++) {
03024                                 sum += data[i + j * nx];
03025                         }
03026 
03027                         float mean = (float)sum / (ny / 2);
03028                         for (int j = 0; j < ny; j++) {
03029                                 data[i + j * nx] = (data[i + j * nx] - mean) / sigma;
03030                         }
03031                 }
03032         }
03033 
03034         image->update();
03035 }
03036 
03037 void RealToFFTProcessor::process_inplace(EMData *image)
03038 {
03039         if (!image) {
03040                 LOGWARN("NULL Image");
03041                 return;
03042         }
03043 
03044         //Note : real image only!
03045         if(image->is_complex()) {
03046                 LOGERR("%s Processor only operates on real images", get_name().c_str());
03047                 throw ImageFormatException("apply to real image only");
03048         }
03049 
03050         // Note : 2D only!
03051         int nz = image->get_zsize();
03052         if (nz > 1) {
03053                 LOGERR("%s Processor doesn't support 3D models", get_name().c_str());
03054                 throw ImageDimensionException("3D model not supported");
03055         }
03056 
03057         EMData *ff=image->do_fft();
03058         ff->ri2ap();
03059 
03060         int nx=image->get_xsize();
03061         int ny=image->get_ysize();
03062 
03063         int x,y;
03064         float norm=static_cast<float>(nx*ny);
03065 
03066         for (y=0; y<ny; y++) image->set_value_at(0,y,0);
03067 
03068         for (x=1; x<nx/2; x++) {
03069                 for (y=0; y<ny; y++) {
03070                         int y2;
03071                         if (y<ny/2) y2=y+ny/2;
03072                         else if (y==ny/2) y2=ny;
03073                         else y2=y-ny/2;
03074                         image->set_value_at(x,y,ff->get_value_at(nx-x*2,ny-y2)/norm);
03075                 }
03076         }
03077 
03078         for (x=nx/2; x<nx; x++) {
03079                 for (y=0; y<ny; y++) {
03080                         int y2;
03081                         if (y<ny/2) y2=y+ny/2;
03082                         else y2=y-ny/2;
03083                         image->set_value_at(x,y,ff->get_value_at(x*2-nx,y2)/norm);
03084                 }
03085         }
03086 
03087         image->update();
03088         if( ff )
03089         {
03090                 delete ff;
03091                 ff = 0;
03092         }
03093 }
03094 
03095 void SigmaZeroEdgeProcessor::process_inplace(EMData * image)
03096 {
03097         if (!image) {
03098                 LOGWARN("NULL Image");
03099                 return;
03100         }
03101 
03102         if (image->get_zsize() > 1) {
03103                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
03104                 throw ImageDimensionException("3D model not supported");
03105         }
03106         float *d = image->get_data();
03107         int i = 0;
03108         int j = 0;
03109 
03110         int nx = image->get_xsize();
03111         int ny = image->get_ysize();
03112 
03113         for (j = 0; j < ny; j++) {
03114                 for (i = 0; i < nx - 1; i++) {
03115                         if (d[i + j * nx] != 0) {
03116                                 break;
03117                         }
03118                 }
03119 
03120                 float v = d[i + j * nx];
03121                 while (i >= 0) {
03122                         d[i + j * nx] = v;
03123                         i--;
03124                 }
03125 
03126                 for (i = nx - 1; i > 0; i--) {
03127                         if (d[i + j * nx] != 0)
03128                                 break;
03129                 }
03130                 v = d[i + j * nx];
03131                 while (i < nx) {
03132                         d[i + j * nx] = v;
03133                         i++;
03134                 }
03135         }
03136 
03137         for (i = 0; i < nx; i++) {
03138                 for (j = 0; j < ny; j++) {
03139                         if (d[i + j * nx] != 0)
03140                                 break;
03141                 }
03142 
03143                 float v = d[i + j * nx];
03144                 while (j >= 0) {
03145                         d[i + j * nx] = v;
03146                         j--;
03147                 }
03148 
03149                 for (j = ny - 1; j > 0; j--) {
03150                         if (d[i + j * nx] != 0)
03151                                 break;
03152                 }
03153                 v = d[i + j * nx];
03154                 while (j < ny) {
03155                         d[i + j * nx] = v;
03156                         j++;
03157                 }
03158         }
03159 
03160 
03161         image->update();
03162 }
03163 
03164 
03165 
03166 void BeamstopProcessor::process_inplace(EMData * image)
03167 {
03168         if (!image) {
03169                 LOGWARN("NULL Image");
03170                 return;
03171         }
03172         if (image->get_zsize() > 1) {
03173                 LOGERR("BeamstopProcessor doesn't support 3D model");
03174                 throw ImageDimensionException("3D model not supported");
03175         }
03176 
03177         float value1 = params["value1"];
03178         float value2 = params["value2"];
03179         float value3 = params["value3"];
03180 
03181         float thr = fabs(value1);
03182         float *data = image->get_data();
03183         int cenx = (int) value2;
03184         int ceny = (int) value3;
03185 
03186         int nx = image->get_xsize();
03187         int ny = image->get_ysize();
03188 
03189         if (cenx <= 0) {
03190                 cenx = nx / 2;
03191         }
03192 
03193         if (ceny <= 0) {
03194                 ceny = ny / 2;
03195         }
03196 
03197         int mxr = (int) floor(sqrt(2.0f) * nx / 2);
03198 
03199         float *mean_values = new float[mxr];
03200         float *sigma_values = new float[mxr];
03201         double sum = 0;
03202         int count = 0;
03203         double square_sum = 0;
03204 
03205         for (int i = 0; i < mxr; i++) {
03206                 sum = 0;
03207                 count = 0;
03208                 square_sum = 0;
03209                 int nitems = 6 * i + 2;
03210 
03211                 for (int j = 0; j < nitems; j++) {
03212                         float ang = j * 2 * M_PI / nitems;
03213                         int x0 = (int) floor(cos(ang) * i + cenx);
03214                         int y0 = (int) floor(sin(ang) * i + ceny);
03215 
03216                         if (x0 < 0 || y0 < 0 || x0 >= nx || y0 >= ny) {
03217                                 continue;
03218                         }
03219 
03220                         float f = data[x0 + y0 * nx];
03221                         sum += f;
03222                         square_sum += f * f;
03223                         count++;
03224                 }
03225 
03226                 mean_values[i] = (float)sum / count;
03227                 sigma_values[i] = (float) sqrt(square_sum / count - mean_values[i] * mean_values[i]);
03228         }
03229 
03230 
03231         for (int k = 0; k < 5; k++) {
03232                 for (int i = 0; i < mxr; i++) {
03233                         sum = 0;
03234                         count = 0;
03235                         square_sum = 0;
03236                         int nitems = 6 * i + 2;
03237                         double thr1 = mean_values[i] - sigma_values[i] * thr;
03238                         double thr2 = mean_values[i] + sigma_values[i];
03239 
03240                         for (int j = 0; j < nitems; j++) {
03241                                 float ang = j * 2 * M_PI / nitems;
03242                                 int x0 = (int) floor(cos(ang) * i + cenx);
03243                                 int y0 = (int) floor(sin(ang) * i + ceny);
03244 
03245                                 if (x0 < 0 || y0 < 0 || x0 >= nx || y0 >= ny ||
03246                                         data[x0 + y0 * nx] < thr1 || data[x0 + y0 * nx] > thr2) {
03247                                         continue;
03248                                 }
03249 
03250                                 sum += data[x0 + y0 * nx];
03251                                 square_sum += data[x0 + y0 * nx] * data[x0 + y0 * nx];
03252                                 count++;
03253                         }
03254 
03255                         mean_values[i] = (float) sum / count;
03256                         sigma_values[i] = (float) sqrt(square_sum / count - mean_values[i] * mean_values[i]);
03257                 }
03258         }
03259 
03260         for (int i = 0; i < nx; i++) {
03261                 for (int j = 0; j < ny; j++) {
03262 
03263 #ifdef  _WIN32
03264                         int r = Util::round(_hypot((float) i - cenx, (float) j - ceny));
03265 #else
03266                         int r = Util::round(hypot((float) i - cenx, (float) j - ceny));
03267 #endif  //_WIN32
03268 
03269                         if (value1 < 0) {
03270                                 if (data[i + j * nx] < (mean_values[r] - sigma_values[r] * thr)) {
03271                                         data[i + j * nx] = 0;
03272                                 }
03273                                 else {
03274                                         data[i + j * nx] -= mean_values[r];
03275                                 }
03276                                 continue;
03277                         }
03278                         if (data[i + j * nx] > (mean_values[r] - sigma_values[r] * thr)) {
03279                                 continue;
03280                         }
03281                         data[i + j * nx] = mean_values[r];
03282                 }
03283         }
03284 
03285         if( mean_values )
03286         {
03287                 delete[]mean_values;
03288                 mean_values = 0;
03289         }
03290 
03291         if( sigma_values )
03292         {
03293                 delete[]sigma_values;
03294                 sigma_values = 0;
03295         }
03296 
03297         image->update();
03298 }
03299 
03300 
03301 
03302 void MeanZeroEdgeProcessor::process_inplace(EMData * image)
03303 {
03304         if (!image) {
03305                 LOGWARN("NULL Image");
03306                 return;
03307         }
03308         if (image->get_zsize() > 1) {
03309                 LOGERR("MeanZeroEdgeProcessor doesn't support 3D model");
03310                 throw ImageDimensionException("3D model not supported");
03311         }
03312 
03313         int nx = image->get_xsize();
03314         int ny = image->get_ysize();
03315         Dict dict = image->get_attr_dict();
03316         float mean_nonzero = dict.get("mean_nonzero");
03317 
03318         float *d = image->get_data();
03319         int i = 0;
03320         int j = 0;
03321 
03322         for (j = 0; j < ny; j++) {
03323                 for (i = 0; i < nx - 1; i++) {
03324                         if (d[i + j * nx] != 0) {
03325                                 break;
03326                         }
03327                 }
03328 
03329                 if (i == nx - 1) {
03330                         i = -1;
03331                 }
03332 
03333                 float v = d[i + j * nx] - mean_nonzero;
03334 
03335                 while (i >= 0) {
03336                         v *= 0.9f;
03337                         d[i + j * nx] = v + mean_nonzero;
03338                         i--;
03339                 }
03340 
03341 
03342                 for (i = nx - 1; i > 0; i--) {
03343                         if (d[i + j * nx] != 0) {
03344                                 break;
03345                         }
03346                 }
03347 
03348                 if (i == 0) {
03349                         i = nx;
03350                 }
03351 
03352                 v = d[i + j * nx] - mean_nonzero;
03353 
03354                 while (i < nx) {
03355                         v *= .9f;
03356                         d[i + j * nx] = v + mean_nonzero;
03357                         i++;
03358                 }
03359         }
03360 
03361 
03362         for (i = 0; i < nx; i++) {
03363                 for (j = 0; j < ny; j++) {
03364                         if (d[i + j * nx] != 0)
03365                                 break;
03366                 }
03367 
03368                 float v = d[i + j * nx] - mean_nonzero;
03369 
03370                 while (j >= 0) {
03371                         v *= .9f;
03372                         d[i + j * nx] = v + mean_nonzero;
03373                         j--;
03374                 }
03375 
03376                 for (j = ny - 1; j > 0; j--) {
03377                         if (d[i + j * nx] != 0)
03378                                 break;
03379                 }
03380 
03381                 v = d[i + j * nx] - mean_nonzero;
03382 
03383                 while (j < ny) {
03384                         v *= .9f;
03385                         d[i + j * nx] = v + mean_nonzero;
03386                         j++;
03387                 }
03388         }
03389 
03390         image->update();
03391 }
03392 
03393 
03394 
03395 void AverageXProcessor::process_inplace(EMData * image)
03396 {
03397         if (!image) {
03398                 LOGWARN("NULL Image");
03399                 return;
03400         }
03401 
03402         float *data = image->get_data();
03403         int nx = image->get_xsize();
03404         int ny = image->get_ysize();
03405         int nz = image->get_zsize();
03406         size_t nxy = (size_t)nx * ny;
03407 
03408         size_t idx;
03409         for (int z = 0; z < nz; z++) {
03410                 for (int x = 0; x < nx; x++) {
03411                         double sum = 0;
03412                         for (int y = 0; y < ny; y++) {
03413                                 idx = x + y * nx + z * nxy;
03414                                 sum += data[idx];
03415                         }
03416                         float mean = (float) sum / ny;
03417 
03418                         for (int y = 0; y < ny; y++) {
03419                                 idx = x + y * nx + z * nxy;
03420                                 data[idx] = mean;
03421                         }
03422                 }
03423         }
03424 
03425         image->update();
03426 }
03427 
03428 void DecayEdgeProcessor::process_inplace(EMData * image)
03429 {
03430         if (!image) {
03431                 LOGWARN("NULL Image");
03432                 return;
03433         }
03434 
03435         if (image->get_zsize() > 1) throw ImageDimensionException("3D model not supported");
03436 
03437         int nx = image->get_xsize();
03438         int ny = image->get_ysize();
03439 
03440         float *d = image->get_data();
03441         int width = params["width"];
03442 
03443         for (int i=0; i<width; i++) {
03444                 float frac=i/(float)width;
03445                 for (int j=0; j<nx; j++) {
03446                         d[j+i*nx]*=frac;
03447                         d[nx*ny-j-i*nx-1]*=frac;
03448                 }
03449                 for (int j=0; j<ny; j++) {
03450                         d[j*nx+i]*=frac;
03451                         d[nx*ny-j*nx-i-1]*=frac;
03452                 }
03453         }
03454 
03455         image->update();
03456 }
03457 
03458 void ZeroEdgeRowProcessor::process_inplace(EMData * image)
03459 {
03460         if (!image) {
03461                 LOGWARN("NULL Image");
03462                 return;
03463         }
03464 
03465         if (image->get_zsize() > 1) {
03466                 LOGERR("ZeroEdgeRowProcessor is not supported in 3D models");
03467                 throw ImageDimensionException("3D model not supported");
03468         }
03469 
03470         int nx = image->get_xsize();
03471         int ny = image->get_ysize();
03472 
03473         float *d = image->get_data();
03474         int top_nrows = params["y0"];
03475         int bottom_nrows = params["y1"];
03476 
03477         int left_ncols = params["x0"];
03478         int right_ncols = params["x1"];
03479 
03480         size_t row_size = nx * sizeof(float);
03481 
03482         memset(d, 0, top_nrows * row_size);
03483         memset(d + (ny - bottom_nrows) * nx, 0, bottom_nrows * row_size);
03484 
03485         for (int i = top_nrows; i < ny - bottom_nrows; i++) {
03486                 memset(d + i * nx, 0, left_ncols * sizeof(float));
03487                 memset(d + i * nx + nx - right_ncols, 0, right_ncols * sizeof(float));
03488         }
03489         image->update();
03490 }
03491 
03492 void ZeroEdgePlaneProcessor::process_inplace(EMData * image)
03493 {
03494         if (!image) {
03495                 LOGWARN("NULL Image");
03496                 return;
03497         }
03498 
03499         if (image->get_zsize() <= 1) {
03500                 LOGERR("ZeroEdgePlaneProcessor only support 3D models");
03501                 throw ImageDimensionException("3D model only");
03502         }
03503 
03504         int nx = image->get_xsize();
03505         int ny = image->get_ysize();
03506         int nz = image->get_zsize();
03507 
03508         float *d = image->get_data();
03509 
03510         int x0=params["x0"];
03511         int x1=params["x1"];
03512         int y0=params["y0"];
03513         int y1=params["y1"];
03514         int z0=params["z0"];
03515         int z1=params["z1"];
03516 
03517         size_t row_size = nx * sizeof(float);
03518         size_t nxy = nx * ny;
03519         size_t sec_size = nxy * sizeof(float);
03520         size_t y0row = y0 * row_size;
03521         size_t y1row = y1 * row_size;
03522         int max_y = ny-y1;
03523         size_t x0size = x0*sizeof(float);
03524         size_t x1size = x1*sizeof(float);
03525 
03526         memset(d,0,z0*sec_size);                                        // zero -z
03527         memset(d+(nxy*(nz-z1)),0,sec_size*z1);      // zero +z
03528 
03529         for (int z=z0; z<nz-z1; z++) {
03530                 memset(d+z*nxy,0,y0row);                        // zero -y
03531                 memset(d+z*nxy+(ny-y1)*nx,0,y1row);     // zero +y
03532 
03533                 int znxy = z * nxy;
03534                 int znxy2 = znxy + nx - x1;
03535 
03536                 for (int y=y0; y<max_y; y++) {
03537                         memset(d+znxy+y*nx,0,x0size);   // zero -x
03538                         memset(d+znxy2+y*nx,0,x1size);  // zero +x
03539                 }
03540         }
03541 
03542         image->update();
03543 }
03544 
03545 
03546 float NormalizeProcessor::calc_sigma(EMData * image) const
03547 {
03548         return image->get_attr("sigma");
03549 }
03550 
03551 void NormalizeProcessor::process_inplace(EMData * image)
03552 {
03553         if (!image) {
03554                 LOGWARN("cannot do normalization on NULL image");
03555                 return;
03556         }
03557 
03558         if (image->is_complex()) {
03559                 LOGWARN("cannot do normalization on complex image");
03560                 return;
03561         }
03562 
03563         float sigma = calc_sigma(image);
03564         if (sigma == 0 || !Util::goodf(&sigma)) {
03565                 LOGWARN("cannot do normalization on image with sigma = 0");
03566                 return;
03567         }
03568 
03569         float mean = calc_mean(image);
03570 
03571         size_t size = (size_t)image->get_xsize() * image->get_ysize() * image->get_zsize();
03572         float *data = image->get_data();
03573 
03574         for (size_t i = 0; i < size; ++i) {
03575                 data[i] = (data[i] - mean) / sigma;
03576         }
03577 
03578         image->update();
03579 }
03580 
03581 float NormalizeUnitProcessor::calc_sigma(EMData * image) const
03582 {
03583         if (!image) {
03584                 LOGWARN("NULL Image");
03585                 return 0;
03586         }
03587         float ret=sqrt((float)image->get_attr("square_sum"));
03588         return ret==0.0f?1.0f:ret;
03589 }
03590 
03591 float NormalizeUnitSumProcessor::calc_sigma(EMData * image) const
03592 {
03593         if (!image) {
03594                 LOGWARN("NULL Image");
03595                 return 0;
03596         }
03597         float ret=(float)image->get_attr("mean")*image->get_xsize()*image->get_ysize()*image->get_zsize();
03598         return ret==0.0f?1.0f:ret;
03599 }
03600 
03601 float NormalizeMaskProcessor::calc_sigma(EMData * image) const
03602 {
03603         if (!image) {
03604                 LOGWARN("NULL Image");
03605                 return 0;
03606         }
03607         EMData *mask = params["mask"];
03608         int no_sigma = params["no_sigma"];
03609 
03610         if(no_sigma == 0) {
03611                 return 1;
03612         }
03613         else {
03614                 if (!EMUtil::is_same_size(mask, image)) {
03615                         LOGERR("normalize.maskProcessor: mask and image must be the same size");
03616                         throw ImageDimensionException("mask and image must be the same size");
03617                 }
03618 
03619                 float *data = image->get_data();
03620                 float *mask_data = mask->get_data();
03621                 size_t size = (size_t)image->get_xsize() * image->get_ysize() * image->get_zsize();
03622                 double sum = 0;
03623                 double sq2 = 0;
03624                 size_t n_norm = 0;
03625 
03626                 for (size_t i = 0; i < size; ++i) {
03627                         if (mask_data[i] > 0.5f) {
03628                                 sum += data[i];
03629                                 sq2 += data[i]*double (data[i]);
03630                                 n_norm++;
03631                         }
03632                 }
03633                 return sqrt(static_cast<float>((sq2 - sum * sum /n_norm)/(n_norm -1))) ;
03634         }
03635 }
03636 
03637 float NormalizeMaskProcessor::calc_mean(EMData * image) const
03638 {
03639         if (!image) {
03640                 LOGWARN("NULL Image");
03641                 return 0;
03642         }
03643         EMData *mask = params["mask"];
03644 
03645         if (!EMUtil::is_same_size(mask, image)) {
03646                 LOGERR("normalize.maskProcessor: mask and image must be the same size");
03647                 throw ImageDimensionException("mask and image must be the same size");
03648         }
03649 
03650         float *data = image->get_data();
03651         float *mask_data = mask->get_data();
03652         size_t size = (size_t)image->get_xsize() * image->get_ysize() * image->get_zsize();
03653         double sum = 0;
03654         size_t n_norm = 0;
03655 
03656         for (size_t i = 0; i < size; ++i) {
03657                 if (mask_data[i] > 0.5f) {
03658                         sum += data[i];
03659                         n_norm++;
03660                 }
03661         }
03662 
03663         float mean = 0;
03664         if (n_norm == 0) {
03665                 mean = image->get_edge_mean();
03666         }
03667         else {
03668                 mean = (float) sum / n_norm;
03669         }
03670 
03671         return mean;
03672 }
03673 
03674 void NormalizeRampNormVar::process_inplace(EMData * image)
03675 {
03676         if (!image) {
03677                 LOGWARN("cannot do normalization on NULL image");
03678                 return;
03679         }
03680 
03681         if (image->is_complex()) {
03682                 LOGWARN("cannot do normalization on complex image");
03683                 return;
03684         }
03685 
03686         image->process_inplace( "filter.ramp" );
03687         int nx = image->get_xsize();
03688         EMData mask(nx,nx);
03689         mask.process_inplace("testimage.circlesphere", Dict("radius",nx/2-2,"fill",1));
03690 
03691         vector<float> rstls = Util::infomask( image, &mask, false);
03692         image->add((float)-rstls[0]);
03693         image->mult((float)1.0/rstls[1]);
03694         image->update();
03695 }
03696 
03697 void NormalizeByMassProcessor::process_inplace(EMData * image)
03698 {
03699         float mass = params.set_default("mass",-1.0f);
03700 
03701         if (mass <= 0) throw InvalidParameterException("You must specify a positive non zero mass");
03702 
03703         float thr = params.set_default("thr",(float)image->get_attr("mean")+(float)image->get_attr("sigma"));
03704 
03705         float apix = image->get_attr_default("apix_x",1.0f);
03706         apix = params.set_default("apix",apix);
03707 
03708         if (apix <= 0) throw InvalidParameterException("You must specify a positive non zero apix");
03709 
03710         float step = ((float)image->get_attr("sigma"))/2.0f;
03711 
03712         int count=0;
03713         size_t n = image->get_size();
03714         float* d = image->get_data();
03715 
03716         for (size_t i=0; i<n; ++i) {
03717                 if (d[i]>=thr) ++count;
03718         }
03719 
03720         float max = image->get_attr("maximum");
03721         float min = image->get_attr("minimum");
03722         for (int j=0; j<4; j++) {
03723                 while (thr<max && count*apix*apix*apix*.81/1000.0>mass) {
03724                         thr+=step;
03725                         count=0;
03726                         for (size_t i=0; i<n; ++i) {
03727                                 if (d[i]>=thr) ++count;
03728                         }
03729                 }
03730 
03731                 step/=4.0;
03732 
03733                 while (thr>min && count*apix*apix*apix*.81/1000.0<mass) {
03734                         thr-=step;
03735                         count=0;
03736                         for (size_t i=0; i<n; ++i) {
03737                                 if (d[i]>=thr) ++count;
03738                         }
03739                 }
03740 
03741                 step/=4.0;
03742         }
03743 
03744         image->mult((float)1.0/thr);
03745         image->update();
03746 }
03747 
03748 float NormalizeEdgeMeanProcessor::calc_mean(EMData * image) const
03749 {
03750         if (!image) {
03751                 LOGWARN("NULL Image");
03752                 return 0;
03753         }
03754         return image->get_edge_mean();
03755 }
03756 
03757 float NormalizeCircleMeanProcessor::calc_mean(EMData * image) const
03758 {
03759         if (!image) {
03760                 LOGWARN("NULL Image");
03761                 return 0;
03762         }
03763         return image->get_circle_mean();
03764 }
03765 
03766 
03767 float NormalizeMaxMinProcessor::calc_sigma(EMData * image) const
03768 {
03769         if (!image) {
03770                 LOGWARN("NULL Image");
03771                 return 0;
03772         }
03773         float maxval = image->get_attr("maximum");
03774         float minval = image->get_attr("minimum");
03775         return (maxval + minval) / 2;
03776 }
03777 
03778 float NormalizeMaxMinProcessor::calc_mean(EMData * image) const
03779 {
03780         if (!image) {
03781                 LOGWARN("NULL Image");
03782                 return 0;
03783         }
03784         float maxval = image->get_attr("maximum");
03785         float minval = image->get_attr("minimum");
03786         return (maxval - minval) / 2;
03787 }
03788 
03789 float NormalizeLREdgeMeanProcessor::calc_mean(EMData * image) const
03790 {
03791         if (!image) {
03792                 LOGWARN("NULL Image");
03793                 return 0;
03794         }
03795         double sum = 0;
03796         int nx = image->get_xsize();
03797         int ny = image->get_ysize();
03798         int nz = image->get_zsize();
03799         float *d = image->get_data();
03800         size_t nyz = ny * nz;
03801 
03802         for (size_t i = 0; i < nyz; i++) {
03803                 size_t l = i * nx;
03804                 size_t r = l + nx - 2;
03805                 sum += d[l] + d[l + 1] + d[r] + d[r + 1];
03806         }
03807         float mean = (float) sum / (4 * nyz);
03808         return mean;
03809 }
03810 
03811 void NormalizeRowProcessor::process_inplace(EMData * image)
03812 {
03813         if (!image) {
03814                 LOGWARN("NULL Image");
03815                 return;
03816         }
03817 
03818         if (image->get_zsize() > 1) {
03819                 LOGERR("row normalize only works for 2D image");
03820                 return;
03821         }
03822 
03823         float *rdata = image->get_data();
03824         int nx = image->get_xsize();
03825         int ny = image->get_ysize();
03826 
03827         for (int y = 0; y < ny; y++) {
03828                 double row_sum = 0;
03829                 for (int x = 0; x < nx; x++) {
03830                         row_sum += rdata[x + y * nx];
03831                 }
03832 
03833                 double row_mean = row_sum / nx;
03834                 if (row_mean <= 0) {
03835                         row_mean = 1;
03836                 }
03837 
03838                 for (int x = 0; x < nx; x++) {
03839                         rdata[x + y * nx] /= (float)row_mean;
03840                 }
03841         }
03842 
03843         image->update();
03844 }
03845 
03846 float NormalizeStdProcessor::calc_mean(EMData * image) const
03847 {
03848         if (!image) {
03849                 LOGWARN("NULL Image");
03850                 return 0;
03851         }
03852         return image->get_attr("mean");
03853 }
03854 
03855 
03856 
03857 void NormalizeToLeastSquareProcessor::process_inplace(EMData * image)
03858 {
03859         if (!image) {
03860                 LOGWARN("NULL Image");
03861                 return;
03862         }
03863 
03864         EMData *to = params["to"];
03865 
03866         bool ignore_zero = params.set_default("ignore_zero",true);
03867 
03868         float low_threshold = FLT_MIN;
03869         string low_thr_name = "low_threshold";
03870         if (params.has_key(low_thr_name)) {
03871                 low_threshold = params[low_thr_name];
03872         }
03873 
03874         float high_threshold = FLT_MAX;
03875         string high_thr_name = "high_threshold";
03876         if (params.has_key(high_thr_name)) {
03877                 high_threshold = params[high_thr_name];
03878         }
03879 
03880         float *rawp = image->get_data();
03881         float *refp = to->get_data();
03882 
03883         int nx = image->get_xsize();
03884         int ny = image->get_ysize();
03885         int nz = image->get_zsize();
03886         size_t size = (size_t)nx * ny * nz;
03887 
03888         float sum_x = 0;
03889         float sum_y = 0;
03890         size_t count = 0;
03891 
03892         float sum_x_mean = 0;
03893         float sum_tt = 0;
03894         float b = 0;
03895 
03896         // This is really inefficient, who coded it ?   --steve
03897         if (ignore_zero) {
03898                 for (size_t i = 0; i < size; ++i) {
03899                         if (refp[i] >= low_threshold && refp[i] <= high_threshold && refp[i] != 0.0f && rawp[i] != 0.0f) {
03900                                 count++;
03901                                 sum_x += refp[i];
03902                                 sum_y += rawp[i];
03903                         }
03904                 }
03905 
03906                 sum_x_mean = sum_x / count;
03907                 sum_tt = 0;
03908                 b = 0;
03909 
03910                 float t;
03911                 for (size_t i = 0; i < size; ++i) {
03912                         if (refp[i] >= low_threshold && refp[i] <= high_threshold && refp[i] != 0.0f && rawp[i] != 0.0f) {
03913                                 t = refp[i] - sum_x_mean;
03914                                 sum_tt += t * t;
03915                                 b += t * rawp[i];
03916                         }
03917                 }
03918         }
03919         else {
03920                         for (size_t i = 0; i < size; ++i) {
03921                         if (refp[i] >= low_threshold && refp[i] <= high_threshold) {
03922                                 count++;
03923                                 sum_x += refp[i];
03924                                 sum_y += rawp[i];
03925                         }
03926                 }
03927 
03928                 sum_x_mean = sum_x / count;
03929                 sum_tt = 0;
03930                 b = 0;
03931 
03932                 float t;
03933                 for (size_t i = 0; i < size; ++i) {
03934                         if (refp[i] >= low_threshold && refp[i] <= high_threshold) {
03935                                 t = refp[i] - sum_x_mean;
03936                                 sum_tt += t * t;
03937                                 b += t * rawp[i];
03938                         }
03939                 }
03940         }
03941 
03942         b /= sum_tt;
03943 
03944         float a = (sum_y - sum_x * b) / count;
03945         float scale = 1 / b;
03946         float shift = -a / b;
03947 
03948         for (size_t i = 0; i < size; ++i) {
03949                 rawp[i] = (rawp[i] - a) / b;
03950         }
03951 
03952         image->update();
03953 
03954         params["scale"] = scale;
03955         params["shift"] = shift;
03956 
03957         image->set_attr("norm_mult",scale);
03958         image->set_attr("norm_add",shift);
03959 
03960 }
03961 
03962 void BinarizeFourierProcessor::process_inplace(EMData* image) {
03963         ENTERFUNC;
03964         if (!image->is_complex()) throw ImageFormatException("Fourier binary thresholding processor only works for complex images");
03965 
03966         float threshold = params.set_default("value",0.0f);
03967         image->ri2ap(); //  works for cuda
03968 
03969         float* d = image->get_data();
03970         for( size_t i = 0; i < image->get_size()/2; ++i, d+=2) {
03971                 if ( *d < threshold ) {
03972                         *d = 0;
03973                         *(d+1) = 0;
03974                 } 
03975         }
03976         image->ap2ri();
03977         image->set_ri(true); // So it can be used for fourier multiplaction, for example
03978         image->update();
03979         EXITFUNC;
03980 } 
03981   
03982 void BilateralProcessor::process_inplace(EMData * image)
03983 {
03984         if (!image) {
03985                 LOGWARN("NULL Image");
03986                 return;
03987         }
03988 
03989         float distance_sigma = params["distance_sigma"];
03990         float value_sigma = params["value_sigma"];
03991         int max_iter = params["niter"];
03992         int half_width = params["half_width"];
03993 
03994         if (half_width < distance_sigma) {
03995                 LOGWARN("localwidth(=%d) should be larger than distance_sigma=(%f)\n",
03996                                                         half_width, distance_sigma);
03997         }
03998 
03999         distance_sigma *= distance_sigma;
04000 
04001         float image_sigma = image->get_attr("sigma");
04002         if (image_sigma > value_sigma) {
04003                 LOGWARN("image sigma(=%f) should be smaller than value_sigma=(%f)\n",
04004                                                         image_sigma, value_sigma);
04005         }
04006         value_sigma *= value_sigma;
04007 
04008         int nx = image->get_xsize();
04009         int ny = image->get_ysize();
04010         int nz = image->get_zsize();
04011 
04012         if(nz==1) {     //for 2D image
04013                 int width=nx, height=ny;
04014 
04015                 int i,j,m,n;
04016 
04017                 float tempfloat1,tempfloat2,tempfloat3;
04018                 int   index1,index2,index;
04019                 int   Iter;
04020                 int   tempint1,tempint3;
04021 
04022                 tempint1=width;
04023                 tempint3=width+2*half_width;
04024 
04025                 float* mask=(float*)calloc((2*half_width+1)*(2*half_width+1),sizeof(float));
04026                 float* OrgImg=(float*)calloc((2*half_width+width)*(2*half_width+height),sizeof(float));
04027                 float* NewImg=image->get_data();
04028 
04029                 for(m=-(half_width);m<=half_width;m++)
04030                         for(n=-(half_width);n<=half_width;n++) {
04031                    index=(m+half_width)*(2*half_width+1)+(n+half_width);
04032                    mask[index]=exp((float)(-(m*m+n*n)/distance_sigma/2.0));
04033                 }
04034 
04035                 //printf("entering bilateral filtering process \n");
04036 
04037                 Iter=0;
04038                 while(Iter<max_iter) {
04039                         for(i=0;i<height;i++)
04040                         for(j=0;j<width;j++) {
04041                                 index1=(i+half_width)*tempint3+(j+half_width);
04042                                         index2=i*tempint1+j;
04043                                 OrgImg[index1]=NewImg[index2];
04044                         }
04045 
04046                         // Mirror Padding
04047                         for(i=0;i<height;i++){
04048                                 for(j=0;j<half_width;j++) OrgImg[(i+half_width)*tempint3+(j)]=OrgImg[(i+half_width)*tempint3+(2*half_width-j)];
04049                                 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)];
04050                         }
04051                         for(i=0;i<half_width;i++){
04052                                 for(j=0;j<(width+2*half_width);j++) OrgImg[i*tempint3+j]=OrgImg[(2*half_width-i)*tempint3+j];
04053                                 for(j=0;j<(width+2*half_width);j++) OrgImg[(i+height+half_width)*tempint3+j]=OrgImg[(height+half_width-2-i)*tempint3+j];
04054                         }
04055 
04056                         //printf("finish mirror padding process \n");
04057                         //now mirror padding have been done
04058 
04059                         for(i=0;i<height;i++){
04060                                 //printf("now processing the %d th row \n",i);
04061                                 for(j=0;j<width;j++){
04062                                         tempfloat1=0.0; tempfloat2=0.0;
04063                                         for(m=-(half_width);m<=half_width;m++)
04064                                                 for(n=-(half_width);n<=half_width;n++){
04065                                                         index =(m+half_width)*(2*half_width+1)+(n+half_width);
04066                                                         index1=(i+half_width)*tempint3+(j+half_width);
04067                                                         index2=(i+half_width+m)*tempint3+(j+half_width+n);
04068                                                         tempfloat3=(OrgImg[index1]-OrgImg[index2])*(OrgImg[index1]-OrgImg[index2]);
04069 
04070                                                         tempfloat3=mask[index]*(1.0f/(1+tempfloat3/value_sigma));       // Lorentz kernel
04071                                                         //tempfloat3=mask[index]*exp(tempfloat3/Sigma2/(-2.0)); // Guassian kernel
04072                                                         tempfloat1+=tempfloat3;
04073 
04074                                                         tempfloat2+=tempfloat3*OrgImg[(i+half_width+m)*tempint3+(j+half_width+n)];
04075                                         }
04076                                         NewImg[i*width+j]=tempfloat2/tempfloat1;
04077                                 }
04078                         }
04079                         Iter++;
04080             }
04081 
04082             //printf("have finished %d  th iteration\n ",Iter);
04083 //              doneData();
04084                 free(mask);
04085                 free(OrgImg);
04086                 // end of BilaFilter routine
04087 
04088         }
04089         else {  //3D case
04090                 int width = nx;
04091                 int height = ny;
04092                 int slicenum = nz;
04093 
04094                 int slice_size = width * height;
04095                 int new_width = width + 2 * half_width;
04096                 int new_slice_size = (width + 2 * half_width) * (height + 2 * half_width);
04097 
04098                 int width1 = 2 * half_width + 1;
04099                 int mask_size = width1 * width1;
04100                 int old_img_size = (2 * half_width + width) * (2 * half_width + height);
04101 
04102                 int zstart = -half_width;
04103                 int zend = -half_width;
04104                 int is_3d = 0;
04105                 if (nz > 1) {
04106                         mask_size *= width1;
04107                         old_img_size *= (2 * half_width + slicenum);
04108                         zend = half_width;
04109                         is_3d = 1;
04110                 }
04111 
04112                 float *mask = (float *) calloc(mask_size, sizeof(float));
04113                 float *old_img = (float *) calloc(old_img_size, sizeof(float));
04114 
04115                 float *new_img = image->get_data();
04116 
04117                 for (int p = zstart; p <= zend; p++) {
04118                         int cur_p = (p + half_width) * (2 * half_width + 1) * (2 * half_width + 1);
04119 
04120                         for (int m = -half_width; m <= half_width; m++) {
04121                                 int cur_m = (m + half_width) * (2 * half_width + 1) + half_width;
04122 
04123                                 for (int n = -half_width; n <= half_width; n++) {
04124                                         int l = cur_p + cur_m + n;
04125                                         mask[l] = exp((float) (-(m * m + n * n + p * p * is_3d) / distance_sigma / 2.0f));
04126                                 }
04127                         }
04128                 }
04129 
04130                 int iter = 0;
04131                 while (iter < max_iter) {
04132                         for (int k = 0; k < slicenum; k++) {
04133                                 size_t cur_k1 = (size_t)(k + half_width) * new_slice_size * is_3d;
04134                                 int cur_k2 = k * slice_size;
04135 
04136                                 for (int i = 0; i < height; i++) {
04137                                         int cur_i1 = (i + half_width) * new_width;
04138                                         int cur_i2 = i * width;
04139 
04140                                         for (int j = 0; j < width; j++) {
04141                                                 size_t k1 = cur_k1 + cur_i1 + (j + half_width);
04142                                                 int k2 = cur_k2 + cur_i2 + j;
04143                                                 old_img[k1] = new_img[k2];
04144                                         }
04145                                 }
04146                         }
04147 
04148                         for (int k = 0; k < slicenum; k++) {
04149                                 size_t cur_k = (k + half_width) * new_slice_size * is_3d;
04150 
04151                                 for (int i = 0; i < height; i++) {
04152                                         int cur_i = (i + half_width) * new_width;
04153 
04154                                         for (int j = 0; j < half_width; j++) {
04155                                                 size_t k1 = cur_k + cur_i + j;
04156                                                 size_t k2 = cur_k + cur_i + (2 * half_width - j);
04157                                                 old_img[k1] = old_img[k2];
04158                                         }
04159 
04160                                         for (int j = 0; j < half_width; j++) {
04161                                                 size_t k1 = cur_k + cur_i + (width + half_width + j);
04162                                                 size_t k2 = cur_k + cur_i + (width + half_width - j - 2);
04163                                                 old_img[k1] = old_img[k2];
04164                                         }
04165                                 }
04166 
04167 
04168                                 for (int i = 0; i < half_width; i++) {
04169                                         int i2 = i * new_width;
04170                                         int i3 = (2 * half_width - i) * new_width;
04171                                         for (int j = 0; j < (width + 2 * half_width); j++) {
04172                                                 size_t k1 = cur_k + i2 + j;
04173                                                 size_t k2 = cur_k + i3 + j;
04174                                                 old_img[k1] = old_img[k2];
04175                                         }
04176 
04177                                         i2 = (height + half_width + i) * new_width;
04178                                         i3 = (height + half_width - 2 - i) * new_width;
04179                                         for (int j = 0; j < (width + 2 * half_width); j++) {
04180                                                 size_t k1 = cur_k + i2 + j;
04181                                                 size_t k2 = cur_k + i3 + j;
04182                                                 old_img[k1] = old_img[k2];
04183                                         }
04184                                 }
04185                         }
04186 
04187                         size_t idx;
04188                         for (int k = 0; k < slicenum; k++) {
04189                                 size_t cur_k = (k + half_width) * new_slice_size;
04190 
04191                                 for (int i = 0; i < height; i++) {
04192                                         int cur_i = (i + half_width) * new_width;
04193 
04194                                         for (int j = 0; j < width; j++) {
04195                                                 float f1 = 0;
04196                                                 float f2 = 0;
04197                                                 size_t k1 = cur_k + cur_i + (j + half_width);
04198 
04199                                                 for (int p = zstart; p <= zend; p++) {
04200                                                         size_t cur_p1 = (p + half_width) * (2 * half_width + 1) * (2 * half_width + 1);
04201                                                         size_t cur_p2 = (k + half_width + p) * new_slice_size;
04202 
04203                                                         for (int m = -half_width; m <= half_width; m++) {
04204                                                                 size_t cur_m1 = (m + half_width) * (2 * half_width + 1);
04205                                                                 size_t cur_m2 = cur_p2 + cur_i + m * new_width + j + half_width;
04206 
04207                                                                 for (int n = -half_width; n <= half_width; n++) {
04208                                                                         size_t k = cur_p1 + cur_m1 + (n + half_width);
04209                                                                         size_t k2 = cur_m2 + n;
04210                                                                         float f3 = Util::square(old_img[k1] - old_img[k2]);
04211 
04212                                                                         f3 = mask[k] * (1.0f / (1 + f3 / value_sigma));
04213                                                                         f1 += f3;
04214                                                                         size_t l1 = cur_m2 + n;
04215                                                                         f2 += f3 * old_img[l1];
04216                                                                 }
04217 
04218                                                                 idx = (size_t)k * height * width + i * width + j;
04219                                                                 new_img[idx] = f2 / f1;
04220                                                         }
04221                                                 }
04222                                         }
04223                                 }
04224                         }
04225                         iter++;
04226                 }
04227                 if( mask ) {
04228                         free(mask);
04229                         mask = 0;
04230                 }
04231 
04232                 if( old_img ) {
04233                         free(old_img);
04234                         old_img = 0;
04235                 }
04236         }
04237 
04238         image->update();
04239 }
04240 
04241 void RotationalAverageProcessor::process_inplace(EMData * image)
04242 {
04243         if (!image || image->is_complex()) {
04244                 LOGWARN("only works on real image. do nothing.");
04245                 return;
04246         }
04247 
04248         if (image->get_ndim() <= 0 || image->get_ndim() > 3)    throw ImageDimensionException("radial average processor only works for 2D and 3D images");
04249 
04250         float *rdata = image->get_data();
04251         int nx = image->get_xsize();
04252         int ny = image->get_ysize();
04253 
04254         vector < float >dist = image->calc_radial_dist(nx / 2, 0, 1,0);
04255 
04256         float midx = (float)((int)nx/2);
04257         float midy = (float)((int)ny/2);
04258 
04259         size_t c = 0;
04260         if (image->get_ndim() == 2) {
04261                 for (int y = 0; y < ny; y++) {
04262                         for (int x = 0; x < nx; x++, c++) {
04263         #ifdef  _WIN32
04264                                 float r = (float) _hypot(x - midx, y - midy);
04265         #else
04266                                 float r = (float) hypot(x - midx, y - midy);
04267         #endif  //_WIN32
04268 
04269 
04270                                 int i = (int) floor(r);
04271                                 r -= i;
04272                                 if (i >= 0 && i < nx / 2 - 1) {
04273                                         rdata[c] = dist[i] * (1.0f - r) + dist[i + 1] * r;
04274                                 }
04275                                 else if (i < 0) {
04276                                         rdata[c] = dist[0];
04277                                 }
04278                                 else {
04279                                         rdata[c] = 0;
04280                                 }
04281                         }
04282                 }
04283         }
04284         else if (image->get_ndim() == 3) {
04285                 int nz = image->get_zsize();
04286                 float midz = (float)((int)nz/2);
04287                 float r;
04288                 int i;
04289                 for (int z = 0; z < nz; ++z) {
04290                         for (int y = 0; y < ny; ++y) {
04291                                 for (int x = 0; x < nx; ++x, ++c) {
04292 
04293                                         r = (float) Util::hypot3(x - midx, y - midy, z - midz);
04294 
04295                                         i = Util::fast_floor(r);
04296                                         r -= i;
04297                                         if (i >= 0 && i < nx / 2 - 1) {
04298                                                 rdata[c] = dist[i] * (1.0f - r) + dist[i + 1] * r;
04299                                         }
04300                                         else if (i < 0) {
04301                                                 rdata[c] = dist[0];
04302                                         }
04303                                         else {
04304                                                 rdata[c] = 0;
04305                                         }
04306                                 }
04307                         }
04308                 }
04309         }
04310 
04311         image->update();
04312 }
04313 
04314 
04315 
04316 void RotationalSubstractProcessor::process_inplace(EMData * image)
04317 {
04318         if (!image || image->is_complex()) {
04319                 LOGWARN("only works on real image. do nothing.");
04320                 return;
04321         }
04322 
04323         if (image->get_ndim() != 2) throw ImageDimensionException("This processor works only for 2D images");
04324 
04325         float *rdata = image->get_data();
04326         int nx = image->get_xsize();
04327         int ny = image->get_ysize();
04328 
04329         vector < float >dist = image->calc_radial_dist(nx / 2, 0, 1,0);
04330 
04331         int c = 0;
04332         for (int y = 0; y < ny; y++) {
04333                 for (int x = 0; x < nx; x++, c++) {
04334 #ifdef  _WIN32
04335                         float r = (float) _hypot(x - nx / 2, y - ny / 2);
04336 #else
04337                         float r = (float) hypot(x - nx / 2, y - ny / 2);
04338 #endif
04339                         int i = (int) floor(r);
04340                         r -= i;
04341                         if (i >= 0 && i < nx / 2 - 1) {
04342                                 rdata[c] -= dist[i] * (1.0f - r) + dist[i + 1] * r;
04343                         }
04344                         else {
04345                                 rdata[c] = 0;
04346                         }
04347                 }
04348         }
04349 
04350         image->update();
04351 }
04352 
04353 
04354 EMData* TransposeProcessor::process(const EMData* const image) {
04355         if (image->get_ndim() != 2) throw UnexpectedBehaviorException("Transpose processor only works with 2D images");
04356         if (image->is_complex()) throw UnexpectedBehaviorException("Transpose processor only works with real images");
04357 
04358         EMData* ret = new EMData(image->get_ysize(),image->get_xsize(),1); // transpose dimensions
04359 
04360         for(int j = 0; j< image->get_ysize();++j) {
04361                 for(int i = 0; i< image->get_xsize();++i) {
04362                         ret->set_value_at(j,i,image->get_value_at(i,j));
04363                 }
04364         }
04365 
04366         return ret;
04367 
04368 }
04369 
04370 void TransposeProcessor::process_inplace(EMData* image) {
04371         if (image->get_ndim() != 2) throw UnexpectedBehaviorException("Transpose processor only works with 2D images");
04372         if (image->is_complex()) throw UnexpectedBehaviorException("Transpose processor only works with real images");
04373 
04374         float* data = (float*)malloc(image->get_ysize()*image->get_xsize()*sizeof(float));
04375 
04376         int nx = image->get_ysize(); // note tranpose
04377         for(int j = 0; j< image->get_ysize();++j) {
04378                 for(int i = 0; i< image->get_xsize();++i) {
04379                         data[i*nx+j] = image->get_value_at(i,j);
04380                 }
04381         }
04382 
04383         image->set_data(data,image->get_ysize(),image->get_xsize(),1);
04384 
04385 }
04386 
04387 void FlipProcessor::process_inplace(EMData * image)
04388 {
04389         ENTERFUNC;
04390         if (!image) {
04391                 LOGWARN("NULL Image");
04392                 return;
04393         }
04394         string axis = (const char*)params["axis"];
04395         
04396 #ifdef EMAN2_USING_CUDA
04397         if (EMData::usecuda == 1 && image->getcudarwdata()) {
04398                 //cout << "flip processor" << endl;
04399                 float array[12] = {1.0, 0.0, 0.0, 0.0,
04400                                                    0.0, 1.0, 0.0, 0.0,
04401                                                    0.0, 0.0, 1.0, 0.0};
04402                 if (axis == "x" || axis == "X") {               // horizontal flip
04403                         array[0] = -1.0;
04404                 }else if (axis == "y" || axis == "Y") {         // vertical flip
04405                         array[5] = -1.0;
04406                 }
04407                 else if (axis == "z" || axis == "Z") {          // vertical flip
04408                         array[10] = -1.0;
04409                 }
04410                 Transform t(array);
04411                 Dict params("transform",(Transform*)&t);
04412                 image->process_inplace("xform",params);
04413 
04414                 EXITFUNC;
04415                 return;
04416         }
04417 #endif
04418 
04419 
04420         float *d = image->get_data();
04421         int nx = image->get_xsize();
04422         int ny = image->get_ysize();
04423         int nz = image->get_zsize();
04424 
04425         size_t nxy = nx * ny;
04426 
04427 
04428         // Note in all cases the origin is nx/2, ny/2 and nz/2
04429         // This means when flipping even sized dimensions that some pixels are redundant.
04430         // Here redundant pixels are set to zero, however, should this change to something
04431         // like the mean.
04432         if (axis == "x" || axis == "X") {               // Horizontal flip
04433                 int offset = (nx%2 == 0);
04434                 size_t idx1, idx2;
04435                 for(int z = 0; z < nz; ++z) {
04436                         for(int y = 0; y < ny; ++y) {
04437                                 if (offset != 0 ) {
04438                                         idx1 = z*nxy + y*nx;
04439                                         d[idx1] = 0; // Here's where you'd make it the mean
04440                                 }
04441                                 for(int x = offset; x < nx / 2; ++x) {
04442                                         idx1 = z*nxy + y*nx + x;
04443                                         idx2 = z*nxy + y*nx + (nx-x-1+offset);
04444                                         std::swap(d[idx1], d[idx2]);
04445                                 }
04446 
04447                         }
04448                 }
04449         }
04450 
04451         else if (axis == "y" || axis == "Y") {          // vertical flip
04452                 int offset = (ny%2 == 0);
04453                 for(int z=0; z<nz; ++z) {
04454                         if (offset != 0) {
04455                                 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)
04456                         }
04457                         for(int y=offset; y<ny/2; ++y) {
04458                                 for(int x=0; x<nx; ++x) {
04459                                         std::swap(d[(size_t)z*nxy + y*nx +x], d[(size_t)z*nxy + (ny -y -1+offset)*nx +x]);
04460                                 }
04461                         }
04462                 }
04463         }
04464         else if (axis == "z" || axis == "Z") {          //z axis flip
04465                 int offset = (nz%2 == 0);
04466                 if (offset != 0) {
04467                         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)
04468                 }
04469                 size_t idx1, idx2;
04470                 for(int z=offset; z<nz/2; ++z) {
04471                         for(int y=0; y<ny; ++y) {
04472                                 for(int x=0; x<nx; ++x) {
04473                                         idx1 = (size_t)z*nxy + y*nx + x;
04474                                         idx2 = (size_t)(nz-z-1+offset)*nxy + y*nx + x;
04475                                         std::swap(d[idx1], d[idx2]);
04476                                 }
04477                         }
04478                 }
04479         }
04480 
04481         image->update();
04482         EXITFUNC;
04483 }
04484 
04485 void AddNoiseProcessor::process_inplace(EMData * image)
04486 {
04487         if (!image) {
04488                 LOGWARN("NULL Image");
04489                 return;
04490         }
04491 
04492         Randnum * randnum = Randnum::Instance();
04493         if(params.has_key("seed")) {
04494                 randnum->set_seed((int)params["seed"]);
04495         }
04496 
04497         float addnoise = params["noise"];
04498         addnoise *= get_sigma(image);
04499         float *dat = image->get_data();
04500 
04501         for (size_t j = 0; j < image->get_size(); ++j) {
04502                 dat[j] += randnum->get_gauss_rand(addnoise, addnoise / 2);
04503         }
04504 
04505         image->update();
04506 }
04507 
04508 float AddSigmaNoiseProcessor::get_sigma(EMData * image)
04509 {
04510         if (!image) {
04511                 LOGWARN("NULL Image");
04512                 return 0;
04513         }
04514         return image->get_attr("sigma");
04515 }
04516 
04517 void FourierToCornerProcessor::process_inplace(EMData * image)
04518 {
04519         if ( !image->is_complex() ) throw ImageFormatException("Can not Fourier origin shift an image that is not complex");
04520 
04521         int nx=image->get_xsize();
04522         int ny=image->get_ysize();
04523         int nz=image->get_zsize();
04524 
04525         int nxy = nx*ny;
04526 
04527         if ( ny == 1 && nz == 1 ){
04528                 cout << "Warning- attempted     Fourier origin shift a 1D image - no action taken" << endl;
04529                 return;
04530         }
04531         int yodd = (ny%2==1);
04532         int zodd = (nz%2==1);
04533 
04534         float* rdata = image->get_data();
04535 
04536         float tmp[2];
04537         float* p1;
04538         float* p2;
04539 
04540         if (yodd){
04541                 // Swap the middle slice (with respect to the y direction) with the bottom slice
04542                 // shifting all slices above the middles slice upwards by one pixel, stopping
04543                 // at the middle slice, not if nz = 1 we are not talking about slices, we are
04544                 // talking about rows
04545                 float prev[2];
04546                 size_t idx;
04547                 for( int s = 0; s < nz; s++ ) {
04548                         for( int c =0; c < nx; c += 2 ) {
04549                                 idx = (size_t)s*nxy+ny/2*nx+c;
04550                                 prev[0] = rdata[idx];
04551                                 prev[1] = rdata[idx+1];
04552                                 for( int r = 0; r <= ny/2; ++r ) {
04553                                         idx = (size_t)s*nxy+r*nx+c;
04554                                         float* p1 = &rdata[idx];
04555                                         tmp[0] = p1[0];
04556                                         tmp[1] = p1[1];
04557 
04558                                         p1[0] = prev[0];
04559                                         p1[1] = prev[1];
04560 
04561                                         prev[0] = tmp[0];
04562                                         prev[1] = tmp[1];
04563                                 }
04564                         }
04565                 }
04566         }
04567 
04568         // Shift slices (3D) or rows (2D) correctly in the y direction
04569         size_t idx1, idx2;
04570         for( int s = 0; s < nz; ++s ) {
04571                 for( int r = 0 + yodd; r < ny/2+yodd; ++r ) {
04572                         for( int c =0; c < nx; c += 2 ) {
04573                                 idx1 = (size_t)s*nxy+r*nx+c;
04574                                 idx2 = (size_t)s*nxy+(r+ny/2)*nx+c;
04575                                 p1 = &rdata[idx1];
04576                                 p2 = &rdata[idx2];
04577 
04578                                 tmp[0] = p1[0];
04579                                 tmp[1] = p1[1];
04580 
04581                                 p1[0] = p2[0];
04582                                 p1[1] = p2[1];
04583 
04584                                 p2[0] = tmp[0];
04585                                 p2[1] = tmp[1];
04586                         }
04587                 }
04588         }
04589 
04590         if ( nz != 1 )
04591         {
04592 
04593                 if (zodd){
04594                         // Swap the middle slice (with respect to the z direction) and the front slice
04595                         // shifting all behind the front slice towards the middle a distance of 1 voxel,
04596                         // stopping at the middle slice.
04597                         float prev[2];
04598                         size_t idx;
04599                         for( int r = 0; r < ny; ++r ) {
04600                                 for( int c =0; c < nx; c += 2 ) {
04601                                         idx = (size_t)nz/2*nxy+r*nx+c;
04602                                         prev[0] = rdata[idx];
04603                                         prev[1] = rdata[idx+1];
04604                                         for( int s = 0; s <= nz/2; ++s ) {
04605                                                 idx = (size_t)s*nxy+r*nx+c;
04606                                                 float* p1 = &rdata[idx];
04607                                                 tmp[0] = p1[0];
04608                                                 tmp[1] = p1[1];
04609 
04610                                                 p1[0] = prev[0];
04611                                                 p1[1] = prev[1];
04612 
04613                                                 prev[0] = tmp[0];
04614                                                 prev[1] = tmp[1];
04615                                         }
04616                                 }
04617                         }
04618                 }
04619 
04620                 // Shift slices correctly in the z direction
04621                 size_t idx1, idx2;
04622                 for( int s = 0+zodd; s < nz/2 + zodd; ++s ) {
04623                         for( int r = 0; r < ny; ++r ) {
04624                                 for( int c =0; c < nx; c += 2 ) {
04625                                         idx1 = (size_t)s*nxy+r*nx+c;
04626                                         idx2 = (size_t)(s+nz/2)*nxy+r*nx+c;
04627                                         p1 = &rdata[idx1];
04628                                         p2 = &rdata[idx2];
04629 
04630                                         tmp[0] = p1[0];
04631                                         tmp[1] = p1[1];
04632 
04633                                         p1[0] = p2[0];
04634                                         p1[1] = p2[1];
04635 
04636                                         p2[0] = tmp[0];
04637                                         p2[1] = tmp[1];
04638                                 }
04639                         }
04640                 }
04641         }
04642         image->set_shuffled(false);
04643 }
04644 
04645 void FourierToCenterProcessor::process_inplace(EMData * image)
04646 {
04647 //      if ( !image->is_complex() ) throw ImageFormatException("Can not Fourier origin shift an image that is not complex");
04648 
04649         int nx=image->get_xsize();
04650         int ny=image->get_ysize();
04651         int nz=image->get_zsize();
04652 
04653         int nxy = nx*ny;
04654 
04655         if ( ny == 1 && nz == 1 ){
04656                 cout << "Warning- attempted     Fourier origin shift a 1D image - no action taken" << endl;
04657                 return;
04658         }
04659 
04660         int yodd = (ny%2==1);
04661         int zodd = (nz%2==1);
04662 
04663         float* rdata = image->get_data();
04664 
04665         float tmp[2];
04666         float* p1;
04667         float* p2;
04668 
04669         // This will tackle the 'normalization' images which come out of the Fourier reconstructor.
04670         // ie- real-space 1/2 FFt images centered on the corner
04671         if ( !image->is_complex() ) {
04672                 if (nz!=1 && !yodd && !zodd) {
04673                         for (int x=0; x<nx; x++) {
04674                                 for (int y=0; y<ny; y++) {
04675                                         for (int z=0; z<nz/2; z++) {
04676                                                 int y2=(y+ny/2)%ny;
04677                                                 int z2=(z+nz/2)%nz;             // %nz should be redundant here
04678                                                 size_t i=x+y*nx+(size_t)z*nxy;
04679                                                 size_t i2=x+y2*nx+(size_t)z2*nxy;
04680                                                 float swp=rdata[i];
04681                                                 rdata[i]=rdata[i2];
04682                                                 rdata[i2]=swp;
04683                                         }
04684                                 }
04685                         }
04686 
04687                         return;
04688                 }
04689                 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");
04690         }
04691 
04692         if (yodd){
04693                 // In 3D this is swapping the bottom slice (with respect to the y direction) and the middle slice,
04694                 // shifting all slices below the middle slice down one. In 2D it is equivalent, but in terms of rows.
04695                 float prev[2];
04696                 size_t idx;
04697                 for( int s = 0; s < nz; s++ ) {
04698                         for( int c =0; c < nx; c += 2 ) {
04699                                 idx = (size_t)s*nxy+c;
04700                                 prev[0] = rdata[idx];
04701                                 prev[1] = rdata[idx+1];
04702                                 for( int r = ny/2; r >= 0; --r ) {
04703                                         idx = (size_t)s*nxy+r*nx+c;
04704                                         float* p1 = &rdata[idx];
04705                                         tmp[0] = p1[0];
04706                                         tmp[1] = p1[1];
04707 
04708                                         p1[0] = prev[0];
04709                                         p1[1] = prev[1];
04710 
04711                                         prev[0] = tmp[0];
04712                                         prev[1] = tmp[1];
04713                                 }
04714                         }
04715                 }
04716         }
04717 
04718         // 3D - Shift slices correctly in the y direction, 2D - shift rows
04719         size_t idx1, idx2;
04720         for( int s = 0; s < nz; ++s ) {
04721                 for( int r = 0; r < ny/2; ++r ) {
04722                         for( int c =0; c < nx; c += 2 ) {
04723                                 idx1 = (size_t)s*nxy+r*nx+c;
04724                                 idx2 = (size_t)s*nxy+(r+ny/2+yodd)*nx+c;
04725                                 p1 = &rdata[idx1];
04726                                 p2 = &rdata[idx2];
04727 
04728                                 tmp[0] = p1[0];
04729                                 tmp[1] = p1[1];
04730 
04731                                 p1[0] = p2[0];
04732                                 p1[1] = p2[1];
04733 
04734                                 p2[0] = tmp[0];
04735                                 p2[1] = tmp[1];
04736                         }
04737                 }
04738         }
04739 
04740         if ( nz != 1 )  {
04741                 if (zodd){
04742                         // Swap the front slice (with respect to the z direction) and the middle slice
04743                         // shifting all slices behind the middles slice towards the front slice 1 voxel.
04744                         float prev[2];
04745                         size_t idx;
04746                         for( int r = 0; r < ny; ++r ) {
04747                                 for( int c =0; c < nx; c += 2 ) {
04748                                         prev[0] = rdata[r*nx+c];
04749                                         prev[1] = rdata[r*nx+c+1];
04750                                         for( int s = nz/2; s >= 0; --s ) {
04751                                                 idx = (size_t)s*nxy+r*nx+c;
04752                                                 float* p1 = &rdata[idx];
04753                                                 tmp[0] = p1[0];
04754                                                 tmp[1] = p1[1];
04755 
04756                                                 p1[0] = prev[0];
04757                                                 p1[1] = prev[1];
04758 
04759                                                 prev[0] = tmp[0];
04760                                                 prev[1] = tmp[1];
04761                                         }
04762                                 }
04763                         }
04764                 }
04765 
04766                 // Shift slices correctly in the y direction
04767                 size_t idx1, idx2;
04768                 for( int s = 0; s < nz/2; ++s ) {
04769                         for( int r = 0; r < ny; ++r ) {
04770                                 for( int c =0; c < nx; c += 2 ) {
04771                                         idx1 = (size_t)s*nxy+r*nx+c;
04772                                         idx2 = (size_t)(s+nz/2+zodd)*nxy+r*nx+c;
04773                                         p1 = &rdata[idx1];
04774                                         p2 = &rdata[idx2];
04775 
04776                                         tmp[0] = p1[0];
04777                                         tmp[1] = p1[1];
04778 
04779                                         p1[0] = p2[0];
04780                                         p1[1] = p2[1];
04781 
04782                                         p2[0] = tmp[0];
04783                                         p2[1] = tmp[1];
04784                                 }
04785                         }
04786                 }
04787         }
04788         image->set_shuffled(true);
04789 }
04790 
04791 void Phase180Processor::fourier_phaseshift180(EMData * image)
04792 {
04793         if ( !image->is_complex() ) throw ImageFormatException("Can not handle images that are not complex in fourier phase shift 180");
04794 
04795         int nx = image->get_xsize();
04796         int ny = image->get_ysize();
04797         int nz = image->get_zsize();
04798 
04799         int nxy = nx * ny;
04800 
04801         float *rdata = image->get_data();
04802 
04803         // Who uses this function? It doesn't work for odd images, and it will give incorrect results for some even images
04804         // d.woolford, March 15 2009
04805         int of=0;
04806         if (((ny/2)%2)+((nz/2)%2)==1) of=1;
04807 
04808         for (int k = 0; k < nz; k++) {
04809                 size_t k2 = (size_t)k * nxy;
04810 
04811                 for (int j = 0; j < ny; j++) {
04812                         int i = ((k+j)%2==of?2:0);
04813                         size_t j2 = j * nx + k2;
04814 
04815                         for (; i < nx; i += 4) {
04816                                 rdata[i + j2] *= -1.0f;
04817                                 rdata[i + j2 + 1] *= -1.0f;
04818                         }
04819                 }
04820         }
04821 }
04822 
04823 void Phase180Processor::swap_corners_180(EMData * image)
04824 {
04825         int nx = image->get_xsize();
04826         int ny = image->get_ysize();
04827         int nz = image->get_zsize();
04828 
04829         int xodd = (nx % 2) == 1;
04830         int yodd = (ny % 2) == 1;
04831         int zodd = (nz % 2) == 1;
04832 
04833         int nxy = nx * ny;
04834 
04835         float *rdata = image->get_data();
04836 
04837         if ( ny == 1 && nz == 1 ){
04838                 throw ImageDimensionException("Error, cannot handle 1D images. This function should not have been called");
04839         }
04840         else if ( nz == 1 ) {
04841 
04842                 // Swap the bottom left and top right corners
04843                 for ( int r = 0; r < ny/2; ++r ) {
04844                         for ( int c = 0; c < nx/2; ++c) {
04845                                 int idx1 = r*nx + c;
04846                                 int idx2 = (r+ny/2+yodd)*nx + c + nx/2+xodd;
04847                                 float tmp = rdata[idx1];
04848                                 rdata[idx1] = rdata[idx2];
04849                                 rdata[idx2] = tmp;
04850                         }
04851                 }
04852 
04853                 // Swap the top left and bottom right corners
04854                 for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
04855                         for ( int c = 0; c < nx/2; ++c) {
04856                                 int idx1 = r*nx + c;
04857                                 int idx2 = (r-ny/2-yodd)*nx + c + nx/2+xodd;
04858                                 float tmp = rdata[idx1];
04859                                 rdata[idx1] = rdata[idx2];
04860                                 rdata[idx2] = tmp;
04861                         }
04862                 }
04863         }
04864         else // nx && ny && nz are greater than 1
04865         {
04866                 float tmp;
04867                 // Swap the bottom left front and back right top quadrants
04868                 size_t idx1, idx2;
04869 
04870                 for ( int s = 0; s < nz/2; ++s ) {
04871                         for ( int r = 0; r < ny/2; ++r ) {
04872                                 for ( int c = 0; c < nx/2; ++ c) {
04873                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04874                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c+nx/2+xodd;
04875                                         tmp = rdata[idx1];
04876                                         rdata[idx1] = rdata[idx2];
04877                                         rdata[idx2] = tmp;
04878                                 }
04879                         }
04880                 }
04881                 // Swap the bottom right front and back left top quadrants
04882                 for ( int s = 0; s < nz/2; ++s ) {
04883                         for ( int r = 0; r < ny/2; ++r ) {
04884                                 for ( int c = nx-1; c >= (nx/2+xodd); --c) {
04885                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04886                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c-nx/2-xodd;
04887                                         tmp = rdata[idx1];
04888                                         rdata[idx1] = rdata[idx2];
04889                                         rdata[idx2] = tmp;
04890                                 }
04891                         }
04892                 }
04893                 // Swap the top right front and back left bottom quadrants
04894                 for ( int s = 0; s < nz/2; ++s ) {
04895                         for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
04896                                 for ( int c = nx-1; c >= (nx/2+xodd); --c) {
04897                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04898                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r-ny/2-yodd)*(size_t)nx+c-nx/2-xodd;
04899                                         tmp = rdata[idx1];
04900                                         rdata[idx1] = rdata[idx2];
04901                                         rdata[idx2] = tmp;
04902                                 }
04903                         }
04904                 }
04905                 // Swap the top left front and back right bottom quadrants
04906                 for ( int s = 0; s < nz/2; ++s ) {
04907                         for ( int r = ny-1; r >= (ny/2+yodd); --r ) {
04908                                 for ( int c = 0; c < nx/2; ++c) {
04909                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04910                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r-ny/2-yodd)*(size_t)nx+c+nx/2+xodd;
04911                                         tmp = rdata[idx1];
04912                                         rdata[idx1] = rdata[idx2];
04913                                         rdata[idx2] = tmp;
04914                                 }
04915                         }
04916                 }
04917         }
04918 }
04919 
04920 void Phase180Processor::swap_central_slices_180(EMData * image)
04921 {
04922         int nx = image->get_xsize();
04923         int ny = image->get_ysize();
04924         int nz = image->get_zsize();
04925 
04926         int xodd = (nx % 2) == 1;
04927         int yodd = (ny % 2) == 1;
04928         int zodd = (nz % 2) == 1;
04929 
04930         int nxy = nx * ny;
04931 
04932         float *rdata = image->get_data();
04933 
04934         if ( ny == 1 && nz == 1 ){
04935                 throw ImageDimensionException("Error, cannot handle 1D images. This function should not have been called");
04936         }
04937         else if ( nz == 1 ) {
04938                 float tmp;
04939                 if ( yodd ) {
04940                         // Iterate along middle row, swapping values where appropriate
04941                         int r = ny/2;
04942                         for ( int c = 0; c < nx/2; ++c ) {
04943                                 int idx1 = r*nx + c;
04944                                 int idx2 = r*nx + c + nx/2+ xodd;
04945                                 tmp = rdata[idx1];
04946                                 rdata[idx1] = rdata[idx2];
04947                                 rdata[idx2] = tmp;
04948                         }
04949                 }
04950 
04951                 if ( xodd )     {
04952                         // Iterate along the central column, swapping values where appropriate
04953                         int c = nx/2;
04954                         for (  int r = 0; r < ny/2; ++r ) {
04955                                 int idx1 = r*nx + c;
04956                                 int idx2 = (r+ny/2+yodd)*nx + c;
04957                                 tmp = rdata[idx1];
04958                                 rdata[idx1] = rdata[idx2];
04959                                 rdata[idx2] = tmp;
04960                         }
04961                 }
04962         }
04963         else // nx && ny && nz are greater than 1
04964         {
04965                 float tmp;
04966                 if ( xodd ) {
04967                         // Iterate along the x = nx/2 slice, swapping values where appropriate
04968                         int c = nx/2;
04969                         size_t idx1, idx2;
04970                         for( int s = 0; s < nz/2; ++s ) {
04971                                 for ( int r = 0; r < ny/2; ++r ) {
04972                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04973                                         idx2 = (s+nz/2+zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c;
04974                                         tmp = rdata[idx1];
04975                                         rdata[idx1] = rdata[idx2];
04976                                         rdata[idx2] = tmp;
04977                                 }
04978                         }
04979 
04980                         for( int s = nz-1; s >= (nz/2+zodd); --s ) {
04981                                 for ( int r = 0; r < ny/2; ++r ) {
04982                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04983                                         idx2 = (s-nz/2-zodd)*(size_t)nxy+(r+ny/2+yodd)*(size_t)nx+c;
04984                                         tmp = rdata[idx1];
04985                                         rdata[idx1] = rdata[idx2];
04986                                         rdata[idx2] = tmp;
04987                                 }
04988                         }
04989                 }
04990                 if ( yodd ) {
04991                         // Iterate along the y = ny/2 slice, swapping values where appropriate
04992                         int r = ny/2;
04993                         size_t idx1, idx2;
04994                         for( int s = 0; s < nz/2; ++s ) {
04995                                 for ( int c = 0; c < nx/2; ++c ) {
04996                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
04997                                         idx2 =(s+nz/2+zodd)*(size_t)nxy+(size_t)r*nx+c+nx/2+xodd;
04998                                         tmp = rdata[idx1];
04999                                         rdata[idx1] = rdata[idx2];
05000                                         rdata[idx2] = tmp;
05001                                 }
05002                         }
05003 
05004                         for( int s = nz-1; s >= (nz/2+zodd); --s ) {
05005                                 for ( int c = 0; c < nx/2; ++c ) {
05006                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05007                                         idx2 = (s-nz/2-zodd)*(size_t)nxy+(size_t)r*nx+c+nx/2+xodd;
05008                                         tmp = rdata[idx1];
05009                                         rdata[idx1] = rdata[idx2];
05010                                         rdata[idx2] = tmp;
05011                                 }
05012                         }
05013                 }
05014                 if ( zodd ) {
05015                         // Iterate along the z = nz/2 slice, swapping values where appropriate
05016                         int s = nz/2;
05017                         size_t idx1, idx2;
05018                         for( int r = 0; r < ny/2; ++r ) {
05019                                 for ( int c = 0; c < nx/2; ++c ) {
05020                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05021                                         idx2 = (size_t)s*nxy+(r+ny/2+yodd)*(size_t)nx+c+nx/2+xodd;
05022                                         tmp = rdata[idx1];
05023                                         rdata[idx1] = rdata[idx2];
05024                                         rdata[idx2] = tmp;
05025                                 }
05026                         }
05027 
05028                         for( int r = ny-1; r >= (ny/2+yodd); --r ) {
05029                                 for ( int c = 0; c < nx/2; ++c ) {
05030                                         idx1 = (size_t)s*nxy+(size_t)r*nx+c;
05031                                         idx2 = (size_t)s*nxy+(r-ny/2-yodd)*(size_t)nx+c+nx/2+xodd;
05032                                         tmp = rdata[idx1];
05033                                         rdata[idx1] = rdata[idx2];
05034                                         rdata[idx2] = tmp;
05035                                 }
05036                         }
05037                 }
05038         }
05039 }
05040 
05041 void PhaseToCornerProcessor::process_inplace(EMData * image)
05042 {
05043         if (!image)     throw NullPointerException("Error: attempt to phase shift a null image");
05044 
05045 #ifdef EMAN2_USING_CUDA
05046         if (EMData::usecuda == 1 && image->getcudarwdata() && image->get_ndim() == 2) { // Because CUDA phase origin to center only works for 2D atm
05047                 //cout << "CUDA tocorner " << image->getcudarwdata() << endl;
05048                 emdata_phaseorigin_to_corner(image->getcudarwdata(), image->get_xsize(), image->get_ysize(), image->get_zsize());
05049                 return;
05050         }
05051 #endif // EMAN2_USING_CUDA
05052 
05053         if (image->is_complex()) {
05054                 fourier_phaseshift180(image);
05055                 return;
05056         }
05057 
05058         int nx = image->get_xsize();
05059         int ny = image->get_ysize();
05060         int nz = image->get_zsize();
05061 
05062         if ( ny == 1 && nz == 1 && nx == 1) return;
05063 
05064         int nxy = nx * ny;
05065 
05066         float *rdata = image->get_data();
05067 
05068         bool xodd = (nx % 2) == 1;
05069         bool yodd = (ny % 2) == 1;
05070         bool zodd = (nz % 2) == 1;
05071 
05072         if ( ny == 1 && nz == 1 ){
05073                 if (xodd){
05074                         // Put the last pixel in the center, shifting the contents
05075                         // to right of the center one step to the right
05076                         float in_x = rdata[nx-1];
05077                         float tmp;
05078                         for ( int i = nx/2; i < nx; ++i ) {
05079                                 tmp = rdata[i];
05080                                 rdata[i] = in_x;
05081                                 in_x = tmp;
05082                         }
05083                 }
05084                 // now the operation is straight forward
05085                 for ( int i = 0; i < nx/2; ++i ) {
05086                         int idx = i+nx/2+xodd;
05087                         float tmp = rdata[i];
05088                         rdata[i] = rdata[idx];
05089                         rdata[idx] = tmp;
05090                 }
05091 
05092         }
05093         else if ( nz == 1 ) {
05094                 if (yodd) {
05095                         // Tranfer the top row into the middle row,
05096                         // shifting all pixels above and including the current middle up one.
05097                         for ( int c = 0; c < nx; ++c ) {
05098                                 // Get the value in the top row
05099                                 float last_val = rdata[(ny-1)*nx + c];
05100                                 float tmp;
05101                                 for ( int r = ny/2; r < ny; ++r ){
05102                                         int idx =r*nx+c;
05103                                         tmp = rdata[idx];
05104                                         rdata[idx] = last_val;
05105                                         last_val = tmp;
05106                                 }
05107                         }
05108                 }
05109 
05110                 if (xodd) {
05111                         // Transfer the right most column into the center column
05112                         // Shift all columns right of and including center to the right one pixel
05113                         for ( int r  = 0; r < ny; ++r ) {
05114                                 float last_val = rdata[(r+1)*nx -1];
05115                                 float tmp;
05116                                 for ( int c = nx/2; c < nx; ++c ){
05117                                         int idx =r*nx+c;
05118                                         tmp = rdata[idx];
05119                                         rdata[idx] = last_val;
05120                                         last_val = tmp;
05121                                 }
05122                         }
05123                 }
05124                 // It is important central slice shifting come after the previous two operations
05125                 swap_central_slices_180(image);
05126                 // Now the corners of the image can be shifted...
05127                 swap_corners_180(image);
05128 
05129         }
05130         else
05131         {
05132                 float tmp;
05133                 if (zodd) {
05134                         // Tranfer the back slice into the middle slice,
05135                         // shifting all pixels beyond and including the middle slice back one.
05136                         size_t idx = 0;
05137                         for (int r = 0; r < ny; ++r){
05138                                 for (int c = 0; c < nx; ++c) {
05139                                         float last_val = rdata[(nz-1)*nxy+r*nx+c];
05140                                         for (int s = nz/2; s < nz; ++s) {
05141                                                 idx = (size_t)s*nxy+r*nx+c;
05142                                                 tmp = rdata[idx];
05143                                                 rdata[idx] = last_val;
05144                                                 last_val = tmp;
05145                                         }
05146                                 }
05147                         }
05148                 }
05149                 if (yodd) {
05150                         // Tranfer the top slice into the middle slice,
05151                         // shifting all pixels above and including the middle slice up one.
05152                         size_t idx = 0;
05153                         for (int s = 0; s < nz; ++s) {
05154                                 for (int c = 0; c < nx; ++c) {
05155                                 float last_val = rdata[s*nxy+(ny-1)*nx+c];
05156                                         for (int r = ny/2; r < ny; ++r){
05157                                                 idx = (size_t)s*nxy+r*nx+c;
05158                                                 tmp = rdata[idx];
05159                                                 rdata[idx] = last_val;
05160                                                 last_val = tmp;
05161                                         }
05162                                 }
05163                         }
05164                 }
05165                 if (xodd) {
05166                         // Transfer the right most slice into the central slice
05167                         // Shift all pixels to right of and including center slice to the right one pixel
05168                         size_t idx = 0;
05169                         for (int s = 0; s < nz; ++s) {
05170                                 for (int r = 0; r < ny; ++r) {
05171                                         float last_val = rdata[s*nxy+r*nx+nx-1];
05172                                         for (int c = nx/2; c < nx; ++c){
05173                                                 idx = (size_t)s*nxy+r*nx+c;
05174                                                 tmp = rdata[idx];
05175                                                 rdata[idx] = last_val;
05176                                                 last_val = tmp;
05177                                         }
05178                                 }
05179                         }
05180                 }
05181                 // Now swap the various parts in the central slices
05182                 swap_central_slices_180(image);
05183                 // Now shift the corners
05184                 swap_corners_180(image);
05185         }
05186 }
05187 
05188 
05189 void PhaseToCenterProcessor::process_inplace(EMData * image)
05190 {
05191         if (!image)     throw NullPointerException("Error: attempt to phase shift a null image");
05192 
05193 #ifdef EMAN2_USING_CUDA
05194         if (EMData::usecuda == 1 && image->getcudarwdata() && image->get_ndim() == 2) { // Because CUDA phase origin to center only works for 2D atm
05195                 //cout << "CUDA tocenter" << endl;
05196                 emdata_phaseorigin_to_center(image->getcudarwdata(), image->get_xsize(), image->get_ysize(), image->get_zsize());
05197                 return;
05198         }
05199 #endif // EMAN2_USING_CUDA
05200 
05201         if (image->is_complex()) {
05202                 fourier_phaseshift180(image);
05203                 return;
05204         }
05205 
05206         int nx = image->get_xsize();
05207         int ny = image->get_ysize();
05208         int nz = image->get_zsize();
05209 
05210         if ( ny == 1 && nz == 1 && nx == 1) return;
05211 
05212         int nxy = nx * ny;
05213 
05214         float *rdata = image->get_data();
05215 
05216         bool xodd = (nx % 2) == 1;
05217         bool yodd = (ny % 2) == 1;
05218         bool zodd = (nz % 2) == 1;
05219 
05220         if ( ny == 1 && nz == 1 ){
05221                 if (xodd) {
05222                         // Put the center pixel at the end, shifting the contents
05223                         // to right of the center one step to the left
05224                         float in_x = rdata[nx/2];
05225                         float tmp;
05226                         for ( int i = nx-1; i >= nx/2; --i ) {
05227                                 tmp = rdata[i];
05228                                 rdata[i] = in_x;
05229                                 in_x = tmp;
05230                         }
05231                 }
05232                 // now the operation is straight forward
05233                 for ( int i = 0; i < nx/2; ++i ) {
05234                         int idx = i + nx/2;
05235                         float tmp = rdata[i];
05236                         rdata[i] = rdata[idx];
05237                         rdata[idx] = tmp;
05238                 }
05239         }
05240         else if ( nz == 1 ){
05241                 // The order in which these operations occur literally undoes what the
05242                 // PhaseToCornerProcessor did to the image.
05243                 // First, the corners sections of the image are swapped appropriately
05244                 swap_corners_180(image);
05245                 // Second, central pixel lines are swapped
05246                 swap_central_slices_180(image);
05247 
05248                 float tmp;
05249                 // Third, appropriate sections of the image are cyclically shifted by one pixel
05250                 if (xodd) {
05251                         // Transfer the middle column to the far right
05252                         // Shift all from the far right to (but not including the) middle one to the left
05253                         for ( int r  = 0; r < ny; ++r ) {
05254                                 float last_val = rdata[r*nx+nx/2];
05255                                 for ( int c = nx-1; c >=  nx/2; --c ){
05256                                         int idx = r*nx+c;
05257                                         tmp = rdata[idx];
05258                                         rdata[idx] = last_val;
05259                                         last_val = tmp;
05260                                 }
05261                         }
05262                 }
05263                 if (yodd) {
05264                         // Tranfer the middle row to the top,
05265                         // shifting all pixels from the top row down one, until  but not including the) middle
05266                         for ( int c = 0; c < nx; ++c ) {
05267                                 // Get the value in the top row
05268                                 float last_val = rdata[ny/2*nx + c];
05269                                 for ( int r = ny-1; r >= ny/2; --r ){
05270                                         int idx = r*nx+c;
05271                                         tmp = rdata[idx];
05272                                         rdata[idx] = last_val;
05273                                         last_val = tmp;
05274                                 }
05275                         }
05276                 }
05277         }
05278         else
05279         {
05280                 // The order in which these operations occur literally undoes the
05281                 // PhaseToCornerProcessor operation - in 3D.
05282                 // First, the corner quadrants of the voxel volume are swapped
05283                 swap_corners_180(image);
05284                 // Second, appropriate parts of the central slices are swapped
05285                 swap_central_slices_180(image);
05286 
05287                 float tmp;
05288                 // Third, appropriate sections of the image are cyclically shifted by one voxel
05289                 if (xodd) {
05290                         // Transfer the central slice in the x direction to the far right
05291                         // moving all slices on the far right toward the center one pixel, until
05292                         // the center x slice is ecountered
05293                         size_t idx = 0;
05294                         for (int s = 0; s < nz; ++s) {
05295                                 for (int r = 0; r < ny; ++r) {
05296                                         float last_val = rdata[s*nxy+r*nx+nx/2];
05297                                         for (int c = nx-1; c >= nx/2; --c){
05298                                                 idx = (size_t)s*nxy+r*nx+c;
05299                                                 tmp = rdata[idx];
05300                                                 rdata[idx] = last_val;
05301                                                 last_val = tmp;
05302                                         }
05303                                 }
05304                         }
05305                 }
05306                 if (yodd) {
05307                         // Tranfer the central slice in the y direction to the top
05308                         // shifting all pixels below it down on, until the center y slice is encountered.
05309                         size_t idx = 0;
05310                         for (int s = 0; s < nz; ++s) {
05311                                 for (int c = 0; c < nx; ++c) {
05312                                         float last_val = rdata[s*nxy+ny/2*nx+c];
05313                                         for (int r = ny-1; r >= ny/2; --r){
05314                                                 idx = (size_t)s*nxy+r*nx+c;
05315                                                 tmp = rdata[idx];
05316                                                 rdata[idx] = last_val;
05317                                                 last_val = tmp;
05318                                         }
05319                                 }
05320                         }
05321                 }
05322                 if (zodd) {
05323                         // Tranfer the central slice in the z direction to the back
05324                         // shifting all pixels beyond and including the middle slice back one.
05325                         size_t idx = 0;
05326                         for (int r = 0; r < ny; ++r){
05327                                 for (int c = 0; c < nx; ++c) {
05328                                         float last_val = rdata[nz/2*nxy+r*nx+c];
05329                                         for (int s = nz-1; s >= nz/2; --s) {
05330                                                 idx = (size_t)s*nxy+r*nx+c;
05331                                                 tmp = rdata[idx];
05332                                                 rdata[idx] = last_val;
05333                                                 last_val = tmp;
05334                                         }
05335                                 }
05336                         }
05337                 }
05338 
05339 
05340         }
05341 }
05342 
05343 void AutoMaskAsymUnit::process_inplace(EMData* image) {
05344         if (!image) {
05345                 LOGWARN("NULL Image");
05346                 return;
05347         }
05348 
05349         int nx = image->get_xsize();
05350         int ny = image->get_ysize();
05351         int nz = image->get_zsize();
05352 
05353         int ox = nx/2;
05354         int oy = ny/2;
05355         int oz = nz/2;
05356 
05357         Symmetry3D* sym = Factory<Symmetry3D>::get((string)params["sym"]);
05358         int au = params.set_default("au",0);
05359 
05360         float *d = image->get_data();
05361         for(int k = 0; k < nz; ++k ) {
05362                 for(int j = 0; j < ny; ++j ) {
05363                         for (int i = 0; i< nx; ++i, ++d) {
05364                                 //cout << i << " " << j << " " << k << endl;
05365                                 Vec3f v(i-ox,j-oy,k-oz);
05366 //                              v.normalize();
05367                                 int a = sym->point_in_which_asym_unit(v);
05368                                 if (au == -1) {
05369                                         *d = (float)a;
05370                                 } else {
05371                                         if ( a == au ) *d = 1;
05372                                         else *d = 0;
05373                                 }
05374                         }
05375                 }
05376         }
05377 
05378         delete sym;
05379 
05380 }
05381 
05382 void AutoMask2DProcessor::process_inplace(EMData * image)
05383 {
05384         if (!image) {
05385                 LOGWARN("NULL Image");
05386                 return;
05387         }
05388 
05389         if (image->get_ndim() != 2) {
05390                 throw ImageDimensionException("This processor only supports 2D images.");
05391         }
05392 
05393         /*
05394          The mask writing functionality was removed to comply with an EMAN2 policy which dictates that file io is not allowed from within a processor
05395          To get around this just use the return_mask parameter.
05396         string mask_output = params.set_default("write_mask", "");
05397         if ( mask_output != "") {
05398                 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.");
05399                 if (!EMUtil::is_valid_filename(mask_output)) throw InvalidParameterException("The mask output file name type is invalid or unrecognized");
05400         }
05401         */
05402 
05403         int radius=0;
05404         if (params.has_key("radius")) {
05405                 radius = params["radius"];
05406         }
05407         int nmaxseed=0;
05408         if (params.has_key("nmaxseed")) {
05409                 nmaxseed = params["nmaxseed"];
05410         }
05411 
05412         float threshold=0.0;
05413         if (params.has_key("sigma")) threshold=(float)(image->get_attr("mean"))+(float)(image->get_attr("sigma"))*(float)params["sigma"];
05414         else threshold=params["threshold"];
05415 
05416 
05417         int nshells = params["nshells"];
05418         int nshellsgauss = params["nshellsgauss"];
05419         int verbose=params.set_default("verbose",0);
05420 
05421         int nx = image->get_xsize();
05422         int ny = image->get_ysize();
05423 
05424         EMData *amask = new EMData();
05425         amask->set_size(nx, ny);
05426 
05427         float *dat = image->get_data();
05428         float *dat2 = amask->get_data();
05429         int i,j;
05430         size_t l = 0;
05431 
05432         if (verbose) printf("%f\t%f\t%f\n",(float)image->get_attr("mean"),(float)image->get_attr("sigma"),threshold);
05433 
05434         // Seeds with the highest valued pixels
05435         if (nmaxseed>0) {
05436                 vector<Pixel> maxs=image->calc_n_highest_locations(nmaxseed);
05437 
05438                 for (vector<Pixel>::iterator i=maxs.begin(); i<maxs.end(); i++) {
05439                         amask->set_value_at((*i).x,(*i).y,0,1.0);
05440                         if (verbose) printf("Seed at %d,%d,%d (%1.3f)\n",(*i).x,(*i).y,(*i).z,(*i).value);
05441                 }
05442         }
05443 
05444         // Seeds with a circle
05445         if (radius>0) {
05446                 // start with an initial circle
05447                 l=0;
05448                 for (j = -ny / 2; j < ny / 2; ++j) {
05449                         for (i = -nx / 2; i < nx / 2; ++i,++l) {
05450                                 if ( abs(j) > radius || abs(i) > radius) continue;
05451 //                              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
05452                                 if ( (j * j + i * i) > (radius*radius) ) continue;
05453                                 dat2[l] = 1.0f;
05454                         }
05455                 }
05456         }
05457 
05458         // iteratively 'flood fills' the map... recursion would be better
05459         int done=0;
05460         int iter=0;
05461         while (!done) {
05462                 iter++;
05463                 done=1;
05464                 if (verbose && iter%10==0) printf("%d iterations\n",iter);
05465                 for (j=1; j<ny-1; ++j) {
05466                         for (i=1; i<nx-1; ++i) {
05467                                 l=i+j*nx;
05468                                 if (dat2[l]) continue;
05469                                 if (dat[l]>threshold && (dat2[l-1]||dat2[l+1]||dat2[l+nx]||dat2[l-nx])) {
05470                                         dat2[l]=1.0;
05471                                         done=0;
05472                                 }
05473                         }
05474                 }
05475         }
05476 
05477         amask->update();
05478 
05479         if (verbose) printf("extending mask\n");
05480         amask->process_inplace("mask.addshells.gauss", Dict("val1", nshells, "val2", nshellsgauss));
05481 
05482         bool return_mask = params.set_default("return_mask",false);
05483         if (return_mask) {
05484                 // 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.
05485                 memcpy(dat,dat2,image->get_size()*sizeof(float));
05486         } else {
05487                 image->mult(*amask);
05488         }
05489 
05490         // EMAN2 policy is not to allow file io from with a processor
05491         //if (mask_output != "") {
05492         //      amask->write_image(mask_output);
05493         //}
05494 
05495 
05496         delete amask;
05497 }
05498 
05499 void CtfSimProcessor::process_inplace(EMData *image) {
05500         EMData *tmp=process(image);
05501         memcpy(image->get_data(),tmp->get_data(),image->get_xsize()*image->get_ysize()*image->get_zsize()*sizeof(float));
05502         delete tmp;
05503         image->update();
05504         return;
05505 }
05506 
05507 EMData* CtfSimProcessor::process(const EMData * const image) {
05508         if (!image) {
05509                 LOGWARN("NULL Image");
05510                 return NULL;
05511         }
05512 
05513         EMData *fft;
05514         if (!image->is_complex()) fft=image->do_fft();
05515         else fft=image->copy();
05516 
05517         EMAN2Ctf ctf;
05518         ctf.defocus=params["defocus"];
05519         ctf.bfactor=params["bfactor"];
05520         ctf.ampcont=params.set_default("ampcont",10.0f);
05521         ctf.voltage=params.set_default("voltage",200.0f);
05522         ctf.cs=params.set_default("cs",2.0);
05523         ctf.apix=params.set_default("apix",image->get_attr_default("apix_x",1.0));
05524         ctf.dsbg=1.0/(ctf.apix*fft->get_ysize()*4.0);           //4x oversampling
05525         
05526         float noiseamp=params.set_default("noiseamp",0.0f);
05527         float noiseampwhite=params.set_default("noiseampwhite",0.0f);
05528         
05529         // compute and apply the CTF
05530         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
05531 
05532 //      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());
05533 //      FILE *out=fopen("x.txt","w");
05534 //      for (int i=0; i<ctfc.size(); i++) fprintf(out,"%f\t%1.3g\n",0.25*i/(float)fft->get_ysize(),ctfc[i]);
05535 //      fclose(out);
05536         
05537         fft->apply_radial_func(0,0.25f/fft->get_ysize(),ctfc,1);
05538         
05539         // Add noise
05540         if (noiseamp!=0 || noiseampwhite!=0) {
05541                 EMData *noise = new EMData(image->get_ysize(),image->get_ysize(),1);
05542                 noise->process_inplace("testimage.noise.gauss");
05543                 noise->do_fft_inplace();
05544         
05545                 // White noise
05546                 if (noiseampwhite!=0) {
05547                         noise->mult((float)noiseampwhite*15.0f);                // The 15.0 is to roughly compensate for the stronger pink noise curve
05548                         fft->add(*noise);
05549                         noise->mult((float)1.0/(noiseampwhite*15.0f));
05550                 }
05551                 
05552                 // Pink noise
05553                 if (noiseamp!=0) {
05554                         vector <float> pinkbg;
05555                         pinkbg.resize(500);
05556                         float nyimg=0.5f/ctf.apix;      // image nyquist
05557                         // This pink curve came from a typical image in the GroEL 4A data set
05558                         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
05559                         noise->apply_radial_func(0,.002f,pinkbg,1);             // Image nyquist is at 250 -> 0.5
05560                         fft->add(*noise);
05561                 }
05562                 
05563         }
05564         
05565         EMData *ret=fft->do_ift();
05566         delete fft;
05567         
05568         return ret;
05569 }
05570 
05571 void AddRandomNoiseProcessor::process_inplace(EMData * image)
05572 {
05573         if (!image) {
05574                 LOGWARN("NULL Image");
05575                 return;
05576         }
05577 
05578         if (!image->is_complex()) {
05579                 LOGERR("AddRandomNoise Processor only works for complex image");
05580                 throw ImageFormatException("only work for complex image");
05581         }
05582 
05583         int n = params["n"];
05584         float x0 = params["x0"];
05585         float dx = params["dx"];
05586         vector < float >y = params["y"];
05587 
05588         int interpolation = 1;
05589         if (params.has_key("interpolation")) {
05590                 interpolation = params["interpolation"];
05591         }
05592 
05593         Randnum * randnum = Randnum::Instance();
05594         if(params.has_key("seed")) {
05595                 randnum->set_seed((int)params["seed"]);
05596         }
05597 
05598         int nx = image->get_xsize();
05599         int ny = image->get_ysize();
05600         int nz = image->get_zsize();
05601 
05602         image->ap2ri();
05603         float *rdata = image->get_data();
05604 
05605         size_t k = 0;
05606         float half_nz = 0;
05607         if (nz > 1) {
05608                 half_nz = nz / 2.0f;
05609         }
05610 
05611         const float sqrt_2 = sqrt((float) 2);
05612 
05613         float r;
05614         for (int h = 0; h < nz; h++) {
05615                 for (int j = 0; j < ny; j++) {
05616                         for (int i = 0; i < nx; i += 2, k += 2) {
05617                                 r = (Util::hypot3(i / 2.0f, j - ny / 2.0f, h - half_nz));
05618 //                              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
05619                                 r = (r - x0) / dx;
05620                                 int l = 0;
05621                                 if (interpolation) {
05622                                         l = Util::fast_floor(r);
05623                                 }
05624                                 else {
05625                                         l = Util::fast_floor(r + 0.5f);
05626                                 }
05627                                 r -= l;
05628                                 float f = 0;
05629                                 if (l >= n - 2) {
05630                                         f = y[n - 1];
05631                                 }
05632                                 else if (l < 0) {
05633                                         l = 0;
05634                                 }
05635                                 else {
05636                                         if (interpolation) {
05637                                                 f = (y[l] * (1 - r) + y[l + 1] * r);
05638                                         }
05639                                         else {
05640                                                 f = y[l];
05641                                         }
05642                                 }
05643                                 f = randnum->get_gauss_rand(sqrt(f), sqrt(f) / 3);
05644                                 float a = randnum->get_frand(0.0f, (float)(2 * M_PI));
05645                                 if (i == 0) {
05646                                         f *= sqrt_2;
05647                                 }
05648                                 rdata[k] += f * cos(a);
05649                                 rdata[k + 1] += f * sin(a);
05650                         }
05651                 }
05652         }
05653 
05654         image->update();
05655 }
05656 
05657 void AddMaskShellProcessor::process_inplace(EMData * image)
05658 {
05659         if (!image) {
05660                 LOGWARN("NULL Image");
05661                 return;
05662         }
05663 
05664         int nx = image->get_xsize();
05665         int ny = image->get_ysize();
05666         int nz = image->get_zsize();
05667 
05668         if (ny == 1) {
05669                 LOGERR("Tried to add mask shell to 1d image");
05670                 return;
05671         }
05672 
05673         int num_shells = params["nshells"];
05674 
05675         float *d = image->get_data();
05676         float k = 0.99999f;
05677         int nxy = nx * ny;
05678 
05679         if (nz == 1) {
05680                 for (int i = 0; i < num_shells; i++) {
05681                         for (int y = 1; y < ny - 1; y++) {
05682                                 int cur_y = y * nx;
05683 
05684                                 for (int x = 1; x < nx - 1; x++) {
05685                                         int j = x + cur_y;
05686                                         if (!d[j] && (d[j - 1] > k || d[j + 1] > k || d[j + nx] > k || d[j - nx] > k)) {
05687                                                 d[j] = k;
05688                                         }
05689                                 }
05690                         }
05691                         k -= 0.00001f;
05692                 }
05693         }
05694         else {
05695                 for (int i = 0; i < num_shells; i++) {
05696                         for (int z = 1; z < nz - 1; z++) {
05697                                 size_t cur_z = (size_t)z * nx * ny;
05698 
05699                                 for (int y = 1; y < ny - 1; y++) {
05700                                         size_t cur_y = y * nx + cur_z;
05701 
05702                                         for (int x = 1; x < nx - 1; x++) {
05703                                                 size_t j = x + cur_y;
05704 
05705                                                 if (!d[j] && (d[j - 1] > k || d[j + 1] > k || d[j + nx] > k ||
05706                                                                           d[j - nx] > k || d[j - nxy] > k || d[j + nxy] > k)) {
05707                                                         d[j] = k;
05708                                                 }
05709                                         }
05710                                 }
05711                         }
05712 
05713                         k -= 0.00001f;
05714                 }
05715         }
05716 
05717         size_t size = (size_t)nx * ny * nz;
05718         for (size_t i = 0; i < size; ++i) {
05719                 if (d[i]) {
05720                         d[i] = 1;
05721                 }
05722                 else {
05723                         d[i] = 0;
05724                 }
05725         }
05726 
05727         image->update();
05728 }
05729 
05730 void ToMassCenterProcessor::process_inplace(EMData * image)
05731 {
05732         if (!image) {
05733                 LOGWARN("NULL Image");
05734                 return;
05735         }
05736 
05737         int int_shift_only = params.set_default("int_shift_only",1);
05738         float threshold = params.set_default("threshold",0.0f);
05739 //      int positive = params.set_default("positive",0);
05740 
05741         if ((float)image->get_attr("sigma")==0.0f) return;              // Can't center a constant valued image
05742         if (threshold>(float)image->get_attr("maximum")) {
05743                 printf("Warning, centering threshold %1.2f, but image max %1.2f. Adjusting.",threshold,(float)image->get_attr("maximum"));
05744                 threshold=(float)image->get_attr("mean")+(float)image->get_attr("sigma");
05745         }
05746 
05747         FloatPoint com = image->calc_center_of_mass(threshold);
05748 
05749         int nx = image->get_xsize();
05750         int ny = image->get_ysize();
05751         int nz = image->get_zsize();
05752 
05753         if (int_shift_only) {
05754                 int dx = -(int)(floor(com[0] + 0.5f) - nx / 2);
05755                 int dy = -(int)(floor(com[1] + 0.5f) - ny / 2);
05756                 int dz = 0;
05757                 if (nz > 1) {
05758                         dz = -(int)(floor(com[2] + 0.5f) - nz / 2);
05759                 }
05760                 image->translate(dx, dy, dz);
05761 
05762                 Transform t;
05763                 t.set_trans((float)dx,(float)dy,(float)dz);
05764 
05765                 if (nz > 1) {
05766                         image->set_attr("xform.align3d",&t);
05767                 } else {
05768                         image->set_attr("xform.align2d",&t);
05769                 }
05770         }
05771         else {
05772                 float dx = -(com[0] - nx / 2);
05773                 float dy = -(com[1] - ny / 2);
05774                 float dz = 0;
05775                 if (nz > 1) {
05776                         dz = -(com[2] - nz / 2);
05777                 }
05778                 image->translate(dx, dy, dz);
05779 
05780                 Transform t;
05781                 t.set_trans(dx,dy,dz);
05782 
05783                 if (nz > 1) {
05784                         image->set_attr("xform.align3d",&t);
05785                 } else {
05786                         image->set_attr("xform.align2d",&t);
05787                 }
05788         }
05789 }
05790 
05791 void PhaseToMassCenterProcessor::process_inplace(EMData * image)
05792 {
05793         if (!image) {
05794                 LOGWARN("NULL Image");
05795                 return;
05796         }
05797 
05798         int int_shift_only = params.set_default("int_shift_only",1);
05799 
05800         vector<float> pcog = image->phase_cog();
05801 
05802         int dims = image->get_ndim();
05803 
05804         if (int_shift_only) {
05805                 int dx=-int(pcog[0]+0.5f),dy=0,dz=0;
05806                 if ( dims >= 2 ) dy = -int(pcog[1]+0.5);
05807                 if ( dims == 3 ) dz = -int(pcog[2]+0.5);
05808 
05809                 Transform t;
05810                 t.set_trans((float)dx,(float)dy,(float)dz);
05811                 if (dims == 3) image->set_attr("xform.align3d",&t);
05812                 else if (dims == 2) image->set_attr("xform.align2d",&t);
05813 
05814                 image->translate(dx,dy,dz);
05815         } else  {
05816                 float dx=-pcog[0],dy=0.0,dz=0.0;
05817                 if ( dims >= 2 ) dy = -pcog[1];
05818                 if ( dims == 3 ) dz = -pcog[2];
05819                 image->translate(dx,dy,dz);
05820 
05821                 Transform t;
05822                 t.set_trans(dx,dy,dz);
05823                 if (dims == 3) image->set_attr("xform.align3d",&t);
05824                 else if (dims == 2) image->set_attr("xform.align2d",&t);
05825         }
05826 }
05827 
05828 void ACFCenterProcessor::process_inplace(EMData * image)
05829 {
05830         if (!image) {
05831                 LOGWARN("NULL Image");
05832                 return;
05833         }
05834 
05835         Dict params1;
05836         params1["intonly"] = 1;
05837         params1["maxshift"] = image->get_xsize() / 4;
05838         EMData* aligned = image->align("translational", 0, params1);
05839         if ( image->get_ndim() == 3 ) {
05840                 Transform* t = aligned->get_attr("xform.align3d");
05841                 image->translate(t->get_trans());
05842                 image->set_attr("xform.align3d",t);
05843                 delete t;
05844         }
05845         else {
05846                 // assumption is the image is 2D which may be  false
05847                 Transform* t = aligned->get_attr("xform.align2d");
05848                 image->translate(t->get_trans());
05849                 image->set_attr("xform.align2d",t);
05850                 delete t;
05851         }
05852 
05853         delete aligned;
05854 
05855 }
05856 
05857 void SNRProcessor::process_inplace(EMData * image)
05858 {
05859         if (!image) {
05860                 return;
05861         }
05862 
05863         int wiener = params["wiener"];
05864         const char *snrfile = params["snrfile"];
05865 
05866         XYData sf;
05867         int err = sf.read_file(snrfile);
05868         if (err) {
05869                 LOGERR("couldn't read structure factor file!");
05870                 return;
05871         }
05872 
05873 
05874         for (size_t i = 0; i < sf.get_size(); i++) {
05875                 if (sf.get_y(i) <= 0) {
05876                         sf.set_y(i, -4.0f);
05877                 }
05878                 else {
05879                         sf.set_y(i, log10(sf.get_y(i)));
05880                 }
05881         }
05882         sf.update();
05883 
05884         Ctf *image_ctf = image->get_ctf();
05885 
05886         vector < float >ctf;
05887         if (wiener) {
05888                 ctf = image_ctf->compute_1d(image->get_ysize(),1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_WIENER_FILTER, &sf);
05889         }
05890         else {
05891                 ctf = image_ctf->compute_1d(image->get_ysize(),1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_SNR, &sf);
05892         }
05893 
05894         if(image_ctf) {delete image_ctf; image_ctf=0;}
05895 
05896         image->process_inplace("normalize.circlemean");
05897 
05898         int nx = image->get_xsize();
05899         int ny = image->get_ysize();
05900 
05901         Region clip_r(-nx / 2, -ny / 2, nx * 2, ny * 2);
05902         EMData *d3 = image->get_clip(clip_r);
05903         EMData *d2 = d3->do_fft();
05904 
05905         d2->apply_radial_func(0, 2.0f / Ctf::CTFOS, ctf, 0);
05906 
05907         if( d3 )
05908         {
05909                 delete d3;
05910                 d3 = 0;
05911         }
05912 
05913         if( image )
05914         {
05915                 delete image;
05916                 image = 0;
05917         }
05918 
05919         EMData *d1 = d2->do_ift();
05920         int d1_nx = d1->get_xsize();
05921         int d1_ny = d1->get_ysize();
05922         Region d1_r(d1_nx / 4, d1_ny / 4, d1_nx / 2, d1_ny / 2);
05923 
05924         image = d1->get_clip(d1_r);
05925 
05926         if( d1 )
05927         {
05928                 delete d1;
05929                 d1 = 0;
05930         }
05931 
05932         if( d2 )
05933         {
05934                 delete d2;
05935                 d2 = 0;
05936         }
05937 }
05938 
05939 void FileFourierProcessor::process_inplace(EMData * image)
05940 {
05941         if (!image) {
05942                 LOGWARN("NULL Image");
05943                 return;
05944         }
05945         const char *filename = params["filename"];
05946         float apix = params["apix"];
05947 
05948         FILE *in = fopen(filename, "rb");
05949         if (!in) {
05950                 LOGERR("FileFourierProcessor: cannot open file '%s'", filename);
05951                 return;
05952         }
05953 
05954         float f = 0;
05955         int n = 0;
05956         while (fscanf(in, " %f %f", &f, &f) == 2) {
05957                 n++;
05958         }
05959         rewind(in);
05960 
05961         vector < float >xd(n);
05962         vector < float >yd(n);
05963 
05964         float sf = apix * image->get_xsize();
05965 
05966         for (int i = 0; fscanf(in, " %f %f", &xd[i], &yd[i]) == 2; i++) {
05967                 xd[i] *= sf;
05968         }
05969 
05970         if (xd[2] - xd[1] != xd[1] - xd[0]) {
05971                 LOGWARN("Warning, x spacing appears nonuniform %g!=%g\n",
05972                                 xd[2] - xd[1], xd[1] - xd[0]);
05973         }
05974 
05975         EMData *d2 = image->do_fft();
05976         if( image )
05977         {
05978                 delete image;
05979                 image = 0;
05980         }
05981 
05982         d2->apply_radial_func(xd[0], xd[1] - xd[0], yd, 1);
05983         image = d2->do_ift();
05984 }
05985 
05986 void LocalNormProcessor::process_inplace(EMData * image)
05987 {
05988         if (!image) {
05989                 LOGWARN("NULL Image");
05990                 return;
05991         }
05992         float apix = params["apix"];
05993         float threshold = params["threshold"];
05994         float radius = params["radius"];
05995 
05996         if (apix > 0) {
05997                 int ny = image->get_ysize();
05998                 radius = ny * apix / radius;
05999                 //printf("Norm filter radius=%1.1f\n", radius);
06000         }
06001 
06002         EMData *blur = image->copy();
06003         EMData *maskblur = image->copy();
06004 
06005         maskblur->process_inplace("threshold.binary", Dict("value", threshold));
06006         maskblur->process_inplace("filter.lowpass.gauss", Dict("cutoff_pixels", radius));
06007 //      maskblur->process_inplace("filter.highpass.tanh", Dict("highpass", -10.0f));
06008         maskblur->process_inplace("threshold.belowtozero", Dict("minval", 0.001f));
06009 //      maskblur->process_inplace("threshold.belowtozero", Dict("minval", 0.001f));
06010 
06011 
06012         blur->process_inplace("threshold.belowtozero", Dict("minval", threshold));
06013         blur->process_inplace("filter.lowpass.gauss", Dict("cutoff_pixels", radius));
06014 //      blur->process_inplace("filter.highpass.tanh", Dict("cutoff_abs", -10.0f));
06015 
06016         maskblur->div(*blur);
06017         image->mult(*maskblur);
06018 //      maskblur->write_image("norm.mrc", 0, EMUtil::IMAGE_MRC);
06019 
06020         if( maskblur )
06021         {
06022                 delete maskblur;
06023                 maskblur = 0;
06024         }
06025 
06026         if( blur )
06027         {
06028                 delete blur;
06029                 blur = 0;
06030         }
06031 }
06032 
06033 
06034 void SymSearchProcessor::process_inplace(EMData * image)
06035 {
06036         if (!image) {
06037                 LOGWARN("NULL Image");
06038                 return;
06039         }
06040         float thresh = params["thresh"];
06041         int output_symlabel = params["output_symlabel"];
06042 
06043         // set up all the symmetry transforms for all the searched symmetries
06044         const vector<string> sym_list = params["sym"];
06045         int sym_num = sym_list.size();
06046         vector< vector< Transform > > transforms(sym_num);
06047         vector< float* > symvals(sym_num);
06048         for (int i =0; i < sym_num; i++) {
06049                 vector<Transform> sym_transform =  Symmetry3D::get_symmetries(sym_list[i]);
06050                 transforms[i] = sym_transform;
06051                 symvals[i] = new float[sym_transform.size()]; // new float(nsym);
06052         }
06053 
06054         EMData *orig = image->copy();
06055 
06056         image->to_zero();
06057 
06058         int nx= image->get_xsize();
06059         int ny= image->get_ysize();
06060         int nz= image->get_zsize();
06061         int xy = nx * ny;
06062         float * data = image->get_data();
06063         float * sdata = orig->get_data();
06064 
06065         EMData *symlabel = 0;
06066         float * ldata = symlabel->get_data();
06067         if (output_symlabel) {
06068                 symlabel = image->copy();
06069                 symlabel->to_zero();
06070                 ldata = symlabel->get_data();
06071         }
06072 
06073         for (int k = 0; k < nz; k++) {
06074                 for (int j = 0; j < ny; j++) {
06075                         for(int i = 0; i < nx; i++) {
06076                                 size_t index = (size_t)k * nx * ny + j * nx + i;
06077                                 float val = sdata[ index ];
06078                                 float bestmean = val, bestsymlevel = FLT_MAX;
06079                                 int bestsym = 0;
06080                                 for( int sym = 0; sym< sym_num; sym++) {
06081                                         int cur_sym_num = transforms[sym].size();
06082                                         float *symval = symvals[sym];
06083                                         // first find out all the symmetry related location values
06084                                         for( int s = 0; s < cur_sym_num; s++){
06085                                                 Transform r = transforms[sym][s];
06086                                                 float x2 = (float)(r[0][0] * (i-nx/2) + r[0][1] * (j-ny/2) + r[0][2] * (k-nz/2) + nx / 2);
06087                                                 float y2 = (float)(r[1][0] * (i-nx/2) + r[1][1] * (j-ny/2) + r[1][2] * (k-nz/2) + ny / 2);
06088                                                 float z2 = (float)(r[2][0] * (i-nx/2) + r[2][1] * (j-ny/2) + r[2][2] * (k-nz/2) + nz / 2);
06089 
06090                                                 if (x2 >= 0 && y2 >= 0 && z2 >= 0 && x2 < (nx - 1) && y2 < (ny - 1)
06091                                                         && z2 < (nz - 1)) {
06092                                                         float x = (float)Util::fast_floor(x2);
06093                                                         float y = (float)Util::fast_floor(y2);
06094                                                         float z = (float)Util::fast_floor(z2);
06095 
06096                                                         float t = x2 - x;
06097                                                         float u = y2 - y;
06098                                                         float v = z2 - z;
06099 
06100                                                         size_t ii = x + y * nx + z * (size_t)xy;
06101 
06102                                                         symval[s]=
06103                                                                 Util::trilinear_interpolate(sdata[ii], sdata[ii + 1], sdata[ii + nx],
06104                                                                                                                         sdata[ii + nx + 1], sdata[ii + nx * ny],
06105                                                                                                                         sdata[ii + xy + 1], sdata[ii + xy + nx],
06106                                                                                                                         sdata[ii + xy + nx + 1], t, u, v);
06107                                                 }
06108                                                 else {
06109                                                         symval[s] = 0.0 ;
06110                                                 }
06111                                         }
06112                                         float tmean=0, tsigma=0;
06113                                         for( int s = 0; s < cur_sym_num; s++) {
06114                                                 tmean += symval[s];
06115                                                 tsigma += symval[s] * symval[s];
06116                                         }
06117                                         tmean /= cur_sym_num;
06118                                         tsigma = tsigma/cur_sym_num - tmean*tmean;
06119                                         if (tsigma < bestsymlevel ) {
06120                                                 bestsymlevel = tsigma;
06121                                                 bestmean = tmean;
06122                                                 bestsym = sym;
06123                                         }
06124                                 }
06125                                 if ( bestsymlevel > thresh) {
06126                                         if (output_symlabel) ldata[index] = (float)bestsym;
06127                                         data[index] = bestmean;
06128                                 }
06129                                 else {
06130                                         if (output_symlabel) ldata[index] = -1;
06131                                         data[index] = val;
06132                                 }
06133                         }
06134                 }
06135         }
06136         if( orig )
06137         {
06138                 delete orig;
06139                 orig = 0;
06140         }
06141         for (int i =0; i < sym_num; i++) {
06142                 if( symvals[i] )
06143                 {
06144                         delete symvals[i];
06145                         symvals[i] = 0;
06146                 }
06147         }
06148         if (symlabel) params.put("symlabel_map", EMObject(symlabel));
06149 }
06150 
06151 
06152 void IndexMaskFileProcessor::process_inplace(EMData * image)
06153 {
06154         if (!image) {
06155                 LOGWARN("NULL Image");
06156                 return;
06157         }
06158 
06159         const char *filename = params["filename"];
06160         EMData *msk = new EMData();
06161         msk->read_image(filename);
06162         if (!EMUtil::is_same_size(image, msk)) {
06163                 LOGERR("IndexMaskFileProcessor: Mask size different than image");
06164                 return;
06165         }
06166 
06167         if ((int) params["ismaskset"] != 0) {
06168                 msk->process_inplace("threshold.binaryrange", Dict("low", 0.5f, "high", 1.5f));
06169         }
06170 
06171         image->mult(*msk);
06172         if( msk )
06173         {
06174                 delete msk;
06175                 msk = 0;
06176         }
06177 }
06178 
06179 
06180 void CoordinateMaskFileProcessor::process_inplace(EMData * image)
06181 {
06182         if (!image) {
06183                 LOGWARN("NULL Image");
06184                 return;
06185         }
06186 
06187         const char *filename = params["filename"];
06188         EMData *msk = new EMData();
06189         msk->read_image(filename);
06190 
06191         int nx = image->get_xsize();
06192         int ny = image->get_ysize();
06193         int nz = image->get_zsize();
06194 
06195         int xm = msk->get_xsize();
06196         int ym = msk->get_ysize();
06197         int zm = msk->get_zsize();
06198 
06199         float apix = image->get_attr("apix_x");
06200         float apixm = msk->get_attr("apix_x");
06201 
06202         float xo = image->get_attr("origin_x");
06203         float yo = image->get_attr("origin_y");
06204         float zo = image->get_attr("origin_z");
06205 
06206         float xom = msk->get_attr("origin_x");
06207         float yom = msk->get_attr("origin_y");
06208         float zom = msk->get_attr("origin_z");
06209 
06210         float *dp = image->get_data();
06211         float *dpm = msk->get_data();
06212         int nxy = nx * ny;
06213 
06214         for (int k = 0; k < nz; k++) {
06215                 float zc = zo + k * apix;
06216                 if (zc <= zom || zc >= zom + zm * apixm) {
06217                         memset(&(dp[k * nxy]), 0, sizeof(float) * nxy);
06218                 }
06219                 else {
06220                         int km = (int) ((zc - zom) / apixm);
06221 
06222                         for (int j = 0; j < ny; j++) {
06223                                 float yc = yo + j * apix;
06224                                 if (yc <= yom || yc >= yom + ym * apixm) {
06225                                         memset(&(dp[k * nxy + j * nx]), 0, sizeof(float) * nx);
06226                                 }
06227                                 else {
06228                                         int jm = (int) ((yc - yom) / apixm);
06229                                         size_t idx = 0;
06230                                         float xc;
06231                                         int im;
06232                                         for (int i = 0; i < nx; i++) {
06233                                                 xc = xo + i * apix;
06234                                                 idx = (size_t)k * nxy + j * nx + i;
06235                                                 if (xc <= xom || xc >= xom + xm * apixm) {
06236                                                         dp[idx] = 0;
06237                                                 }
06238                                                 else {
06239                                                         im = (int) ((xc - xom) / apixm);
06240                                                         if (dpm[km * xm * ym + jm * xm + im] <= 0) {
06241                                                                 dp[idx] = 0;
06242                                                         }
06243                                                 }
06244                                         }
06245                                 }
06246                         }
06247                 }
06248         }
06249 
06250         image->update();
06251         msk->update();
06252         if( msk )
06253         {
06254                 delete msk;
06255                 msk = 0;
06256         }
06257 }
06258 
06259 void MatchSFProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const {
06260         // The radial mask comes in with the existing radial image profile
06261         // The radial mask runs from 0 to the 1-D Nyquist (it leaves out the corners in Fourier space)
06262 
06263         EMData *to = params["to"];
06264         XYData *sf = new XYData();
06265         float apixto = to->get_attr("apix_x");
06266 
06267 
06268         if (to->is_complex()) {
06269                 vector<float> rd=to->calc_radial_dist(to->get_ysize()/2.0f,0,1.0f,1);
06270                 for (size_t i=0; i<rd.size(); ++i) {
06271                         sf->set_x(i,i/(apixto*2.0f*rd.size()));
06272                         sf->set_y(i,rd[i]);
06273                 }
06274         }
06275         else {
06276                 EMData *tmp=to->do_fft();
06277                 vector<float> rd=tmp->calc_radial_dist(to->get_ysize()/2,0,1.0,1);
06278                 for (size_t i=0; i<rd.size(); ++i) {
06279                         sf->set_x(i,i/(apixto*2.0f*rd.size()));
06280                         sf->set_y(i,rd[i]);
06281                 }
06282                 delete tmp;
06283         }
06284 
06285         float apix=image->get_attr("apix_x");
06286 
06287 //      sf->write_file("a.txt");
06288 //      Util::save_data(0,sf->get_x(1),radial_mask,"b.txt");
06289 
06290         int n = radial_mask.size();
06291         for (int i=0; i<n; i++) {
06292                 if (radial_mask[i]>0) radial_mask[i]= sqrt(sf->get_yatx(i/(apix*2.0f*n),false)/radial_mask[i]);
06293                 else if (i>0) radial_mask[i]=radial_mask[i-1];
06294         }
06295 
06296 //      Util::save_data(0,sf->get_x(1),radial_mask,"c.txt");
06297 
06298         delete sf;
06299 }
06300 
06301 void SetSFProcessor::create_radial_func(vector < float >&radial_mask,EMData *image) const {
06302         // The radial mask comes in with the existing radial image profile
06303         // The radial mask runs from 0 to the 1-D Nyquist (it leaves out the corners in Fourier space)
06304 
06305         XYData *sf = params["strucfac"];
06306         if(params.has_key("apix")) {
06307                 image->set_attr("apix_x", (float)params["apix"]);
06308                 image->set_attr("apix_y", (float)params["apix"]);
06309                 image->set_attr("apix_z", (float)params["apix"]);
06310         }
06311 
06312         float apix=image->get_attr("apix_x");
06313 
06314         int n = radial_mask.size();
06315         for (int i=0; i<n; i++) {
06316                 if (radial_mask[i]>0) radial_mask[i]= n*n*n*sqrt(sf->get_yatx(i/(apix*2.0f*n),false)/radial_mask[i]);
06317                 else if (i>0) radial_mask[i]=radial_mask[i-1];
06318         }
06319 
06320 }
06321 
06322 void SmartMaskProcessor::process_inplace(EMData * image)
06323 {
06324         if (!image) {
06325                 LOGWARN("NULL Image");
06326                 return;
06327         }
06328 
06329         float mask = params["mask"];
06330 
06331         int nx = image->get_xsize();
06332         int ny = image->get_ysize();
06333         int nz = image->get_zsize();
06334 
06335         float *dat = image->get_data();
06336         double sma = 0;
06337         size_t smn = 0;
06338         float r = 0.0f;
06339         for (int k = 0; k < nz; ++k) {
06340                 for (int j = 0; j < ny; ++j) {
06341                         for (int i = 0; i < nx; ++i, ++dat) {
06342                                 r =
06343                                         sqrt((float) Util::square(i - nx / 2) + Util::square(j - ny / 2) +
06344                                                  Util::square(k - nz / 2));
06345                                 if (r > mask - 1.5f && r < mask - 0.5f) {
06346                                         sma += *dat;
06347                                         smn++;
06348                                 }
06349                         }
06350                 }
06351         }
06352 
06353         float smask = (float) (sma / smn);
06354         image->update();
06355 
06356         dat = image->get_data();
06357         for (int k = 0; k < nz; ++k) {
06358                 for (int j = 0; j < ny; ++j) {
06359                         for (int i = 0; i < nx; ++i, ++dat) {
06360                                 r =
06361                                         sqrt((float) Util::square(i - nx / 2) + Util::square(j - ny / 2) +
06362                                                  Util::square(k - nz / 2));
06363                                 if (r > mask - .5) {
06364                                         *dat = 0;
06365                                 }
06366                                 else {
06367                                         *dat -= smask;
06368                                 }
06369                         }
06370                 }
06371         }
06372 
06373         image->update();
06374 }
06375 
06376 void AutoMask3DProcessor::search_nearby(float *dat, float *dat2, int nx, int ny, int nz, float threshold)
06377 {
06378         Assert(dat != 0);
06379         Assert(dat2 != 0);
06380         Assert(nx > 0);
06381         Assert(ny > 0);
06382 
06383         bool done = false;
06384         int nxy = nx * ny;
06385 
06386         while (!done) {
06387                 done = true;
06388                 for (int k = 1; k < nz - 1; k++) {
06389                         size_t k2 = (size_t)k * nxy;
06390                         for (int j = 1; j < ny - 1; j++) {
06391                                 size_t l = j * nx + k2 + 1;
06392 
06393                                 for (int i = 1; i < nx - 1; i++) {
06394                                         if (dat[l] >= threshold || dat2[l]) {
06395                                                 if (dat2[l - 1] || dat2[l + 1] ||
06396                                                         dat2[l - nx] || dat2[l + nx] || dat2[l - nxy] || dat2[l + nxy]) {
06397                                                         dat2[l] = 1.0f;
06398                                                         done = false;
06399                                                 }
06400                                         }
06401                                         ++l;
06402                                 }
06403                         }
06404                 }
06405         }
06406 }
06407 
06408 void AutoMask3DProcessor::fill_nearby(float *dat2, int nx, int ny, int nz)
06409 {
06410         Assert(dat2 != 0);
06411         Assert(nx > 0);
06412         Assert(ny > 0);
06413         Assert(nz >= 0);
06414 
06415         int nxy = nx * ny;
06416         size_t idx;
06417         for (int i = 0; i < nx; ++i) {
06418                 for (int j = 0; j < ny; ++j) {
06419                         int j2 = j * nx + i;
06420                         int k0 = 0;
06421                         for (int k = 0; k < nz; ++k) {
06422                                 idx = j2 + (size_t)k * nxy;
06423                                 if (dat2[idx]) {
06424                                         k0 = k;
06425                                         break;
06426                                 }
06427                         }
06428 
06429                         if (k0 != nz) {
06430                                 int k1 = nz - 1;
06431                                 for (int k = nz - 1; k >= 0; --k) {
06432                                         idx = j2 + (size_t)k * nxy;
06433                                         if (dat2[idx]) {
06434                                                 k1 = k;
06435                                                 break;
06436                                         }
06437                                 }
06438 
06439                                 for (int k = k0 + 1; k < k1; ++k) {
06440                                         idx = j2 + (size_t)k * nxy;
06441                                         dat2[idx] = 1.0f;
06442                                 }
06443                         }
06444                 }
06445         }
06446 
06447         for (int i = 0; i < nx; ++i) {
06448                 for (int j = 0; j < nz; ++j) {
06449                         size_t j2 = (size_t)j * nxy + i;
06450                         int k0 = 0;
06451                         for (int k = 0; k < ny; ++k) {
06452                                 idx = (size_t)k * nx + j2;
06453                                 if (dat2[idx]) {
06454                                         k0 = k;
06455                                         break;
06456                                 }
06457                         }
06458 
06459                         if (k0 != ny) {
06460                                 int k1 = ny - 1;
06461                                 for (int k = ny - 1; k >= 0; --k) {
06462                                         idx = (size_t)k * nx + j2;
06463                                         if (dat2[idx]) {
06464                                                 k1 = k;
06465                                                 break;
06466                                         }
06467                                 }
06468 
06469                                 for (int k = k0 + 1; k < k1; ++k) {
06470                                         idx = (size_t)k * nx + j2;
06471                                         dat2[idx] = 1.0f;
06472                                 }
06473                         }
06474                 }
06475         }
06476 
06477         for (int i = 0; i < ny; ++i) {
06478                 for (int j = 0; j < nz; ++j) {
06479                         size_t j2 = i * nx + (size_t)j * nxy;
06480                         int k0 = 0;
06481                         for (int k = 0; k < nx; ++k) {
06482                                 if (dat2[k + j2]) {
06483                                         k0 = k;
06484                                         break;
06485                                 }
06486                         }
06487                         if (k0 != nx) {
06488                                 int k1 = nx - 1;
06489                                 for (int k = nx - 1; k >= 0; --k) {
06490                                         if (dat2[k + j2]) {
06491                                                 k1 = k;
06492                                                 break;
06493                                         }
06494                                 }
06495 
06496                                 for (int k = k0 + 1; k < k1; ++k) {
06497                                         dat2[k + j2] = 1.0f;
06498                                 }
06499                         }
06500                 }
06501         }
06502 
06503 }
06504 
06505 void AutoMask3DProcessor::process_inplace(EMData * image)
06506 {
06507         if (!image) {
06508                 LOGWARN("NULL Image");
06509                 return;
06510         }
06511 
06512         int nx = image->get_xsize();
06513         int ny = image->get_ysize();
06514         int nz = image->get_zsize();
06515 
06516         EMData *amask = new EMData();
06517         amask->set_size(nx, ny, nz);
06518 
06519         float sig = 0;
06520         float mean = 0;
06521 
06522         if (params.has_key("threshold1") && params.has_key("threshold2")) {
06523                 sig = image->get_attr("sigma");
06524                 mean = image->get_attr("mean");
06525         }
06526 
06527         float *dat = image->get_data();
06528         float *dat2 = amask->get_data();
06529 
06530         float t = 0;
06531         if (params.has_key("threshold1")) {
06532                 t = params["threshold1"];
06533         }
06534         else {
06535                 t = mean + sig * 2.5f;
06536         }
06537 
06538         size_t l = 0;
06539         for (int k = 0; k < nz; ++k) {
06540                 for (int j = 0; j < ny; ++j) {
06541                         for (int i = 0; i < nx; ++i) {
06542                                 if (dat[l] > t) {
06543                                         dat2[l] = 1.0f;
06544                                 }
06545                                 ++l;
06546                         }
06547                 }
06548         }
06549 
06550 
06551         if (params.has_key("threshold2")) {
06552                 t = params["threshold2"];
06553         }
06554         else {
06555                 t = mean + sig * 0.5f;
06556         }
06557 
06558         search_nearby(dat, dat2, nx, ny, nz, t);
06559 
06560         int nxy = nx * ny;
06561 
06562         for (int k = 1; k < nz - 1; ++k) {
06563                 for (int j = 1; j < ny - 1; ++j) {
06564                         size_t l = j * nx + (size_t)k * nxy + 1;
06565                         for (int i = 1; i < nx - 1; ++i, ++l) {
06566                                 if (dat2[l - 1] == 1.0f || dat2[l + 1] == 1.0f ||
06567                                         dat2[l - nx] == 1.0f || dat2[l + nx] == 1.0f ||
06568                                         dat2[l - nxy] == 1.0f || dat2[l + nxy] == 1.0f) {
06569                                         dat2[l] = 2.0f;
06570                                 }
06571                         }
06572                 }
06573         }
06574 
06575         size_t size = (size_t)nx * ny * nz;
06576         for (size_t i = 0; i < size; ++i) {
06577                 if (dat2[i] == 2.0f) {
06578                         dat2[i] = 1.0f;
06579                 }
06580         }
06581 
06582         fill_nearby(dat2, nx, ny, nz);
06583 
06584         image->update();
06585         amask->update();
06586 
06587         image->mult(*amask);
06588         amask->write_image("mask.mrc", 0, EMUtil::IMAGE_MRC);
06589         if( amask )
06590         {
06591                 delete amask;
06592                 amask = 0;
06593         }
06594 }
06595 
06596 
06597 void AutoMask3D2Processor::process_inplace(EMData * image)
06598 {
06599         if (!image) {
06600                 LOGWARN("NULL Image");
06601                 return;
06602         }
06603 
06604         if (image->get_ndim() != 3) {
06605                 throw ImageDimensionException("This processor was only ever designed to work on 3D images.");
06606         }
06607 
06608         /*
06609          The mask writing functionality was removed to comply with an EMAN2 policy which dictates that file io is not allowed from within a processor
06610          To get around this just use the return_mask parameter.
06611         string mask_output = params.set_default("write_mask", "");
06612         if ( mask_output != "") {
06613                 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.");
06614                 if (!EMUtil::is_valid_filename(mask_output)) throw InvalidParameterException("The mask output file name type is invalid or unrecognized");
06615         }
06616         */
06617 
06618         int radius=0;
06619         if (params.has_key("radius")) {
06620                 radius = params["radius"];
06621         }
06622         int nmaxseed=0;
06623         if (params.has_key("nmaxseed")) {
06624                 nmaxseed = params["nmaxseed"];
06625         }
06626 
06627         float threshold=0.0;
06628         if (params.has_key("sigma")) threshold=(float)(image->get_attr("mean"))+(float)(image->get_attr("sigma"))*(float)params["sigma"];
06629         else threshold=params["threshold"];
06630 
06631         int nshells = params["nshells"];
06632         int nshellsgauss = params["nshellsgauss"];
06633         int verbose=params.set_default("verbose",0);
06634 
06635         int nx = image->get_xsize();
06636         int ny = image->get_ysize();
06637         int nz = image->get_zsize();
06638         int nxy=nx*ny;
06639 
06640         EMData *amask = new EMData();
06641         amask->set_size(nx, ny, nz);
06642 
06643         float *dat = image->get_data();
06644         float *dat2 = amask->get_data();
06645         int i,j,k;
06646         size_t l = 0;
06647 
06648         // Seeds with the highest valued pixels
06649         if (nmaxseed>0) {
06650                 vector<Pixel> maxs=image->calc_n_highest_locations(nmaxseed);
06651 
06652                 for (vector<Pixel>::iterator i=maxs.begin(); i<maxs.end(); i++) {
06653                         amask->set_value_at((*i).x,(*i).y,(*i).z,1.0);
06654                         if (verbose) printf("Seed at %d,%d,%d (%1.3f)\n",(*i).x,(*i).y,(*i).z,(*i).value);
06655                 }
06656         }
06657 
06658         // Seeds with a sphere
06659         if (radius>0) {
06660                 // start with an initial sphere
06661                 for (k = -nz / 2; k < nz / 2; ++k) {
06662                         for (j = -ny / 2; j < ny / 2; ++j) {
06663                                 for (i = -nx / 2; i < nx / 2; ++i,++l) {
06664                                         if (abs(k) > radius || abs(j) > radius || abs(i) > radius) continue;
06665                                         if ( (k * k + j * j + i * i) > (radius*radius) || dat[l] < threshold) continue;
06666                                         dat2[l] = 1.0f;
06667                                 }
06668                         }
06669                 }
06670         }
06671 
06672 
06673         // iteratively 'flood fills' the map... recursion would be better
06674         int done=0;
06675         int iter=0;
06676         while (!done) {
06677                 iter++;
06678                 done=1;
06679                 if (verbose && iter%10==0) printf("%d iterations\n",iter);
06680                 for (k=1; k<nz-1; ++k) {
06681                         for (j=1; j<ny-1; ++j) {
06682                                 for (i=1; i<nx-1; ++i) {
06683                                         l=i+j*nx+k*nx*ny;
06684                                         if (dat2[l]) continue;
06685                                         if (dat[l]>threshold && (dat2[l-1]||dat2[l+1]||dat2[l+nx]||dat2[l-nx]||dat2[l-nxy]||dat2[l+nxy])) {
06686                                                 dat2[l]=1.0;
06687                                                 done=0;
06688                                         }
06689                                 }
06690                         }
06691                 }
06692         }
06693 
06694         amask->update();
06695 
06696         if (verbose) printf("extending mask\n");
06697         amask->process_inplace("mask.addshells.gauss", Dict("val1", nshells, "val2", nshellsgauss));
06698 
06699         bool return_mask = params.set_default("return_mask",false);
06700         if (return_mask) {
06701                 // 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.
06702                 memcpy(dat,dat2,image->get_size()*sizeof(float));
06703         } else {
06704                 image->mult(*amask);
06705         }
06706 
06707         // EMAN2 policy is not to allow file io from with a processor
06708         //if (mask_output != "") {
06709         //      amask->write_image(mask_output);
06710         //}
06711 
06712 
06713         delete amask;
06714 }
06715 
06716 void IterBinMaskProcessor::process_inplace(EMData * image)
06717 {
06718         if (!image) {
06719                 LOGWARN("NULL Image");
06720                 return;
06721         }
06722 
06723         float val1 = params["val1"];
06724         float val2 = params["val2"];
06725 
06726         int nx = image->get_xsize();
06727         int ny = image->get_ysize();
06728         int nz = image->get_zsize();
06729         EMData *image2 = new EMData(nx,ny,nz);
06730 
06731         // Got a compile warning complaining that these things were never used. Hope I didn't break anything - apologies if so (d.woolford)
06732 //      float *dat = image->get_data();
06733 //      float *dat2 = image2->get_data();
06734 
06735 
06736         float *d = image->get_data();
06737         float *d2 = image2->get_data();
06738 
06739         const int nxy = nx * ny;
06740         size_t size = (size_t)nx * ny * nz;
06741 
06742         // TODO: THIS IS EXTREMELY INEFFICIENT
06743         if (nz != 1) {
06744                 for (int l = 1; l <= (int) val1+val2; ++l) {
06745                         for (size_t i=0; i<size; i++) d2[i]=d[i];
06746                         for (int k = 1; k < nz - 1; ++k) {
06747                                 for (int j = 1; j < ny - 1; ++j) {
06748                                         for (int i = 1; i < nx - 1; ++i) {
06749                                                 size_t t = i + j*nx+(size_t)k*nx*ny;
06750                                                 if (d[t]) continue;
06751                                                 if (d2[t - 1] || d2[t + 1] || d2[t + nx] || d2[t - nx] || d2[t + nxy] || d2[t - nxy]) d[t] = (float) l + 1;
06752                                         }
06753                                 }
06754                         }
06755                 }
06756         }
06757         else {
06758                 for (int l = 1; l <= (int) val1+val2; ++l) {
06759                         for (size_t i=0; i<size; i++) d2[i]=d[i];
06760                         for (int j = 1; j < ny - 1; ++j) {
06761                                 for (int i = 1; i < nx - 1; ++i) {
06762                                         size_t t = i + j * nx;
06763                                         if (d[t]) continue;
06764                                         if (d2[t - 1] || d2[t + 1] || d2[t + nx] || d2[t - nx]) d[t] = (float) l + 1;
06765                                 }
06766                         }
06767                 }
06768         }
06769 
06770         vector<float> vec;
06771         for (int i=0; i<val1+2; i++) vec.push_back(1.0);
06772         for (int i=0; i<val2; i++) {
06773                 vec.push_back(exp(-pow(2.0f*i/(val2),2.0f)));
06774 //              printf("%f\n",exp(-pow(2.0*i/(val1-val2),2.0)));
06775         }
06776         for (size_t i = 0; i < size; ++i) if (d[i]) d[i]=vec[(int)d[i]];
06777 
06778         image->update();
06779         delete image2;
06780 }
06781 
06782 EMData* DirectionalSumProcessor::process(const EMData* const image ) {
06783         string dir = params.set_default("axis", "");
06784         if ( dir == "" || ( dir != "x" && dir != "y" && dir != "z" ) )
06785                 throw InvalidParameterException("The direction parameter must be either x, y, or z");
06786 
06787         int nx = image->get_xsize();
06788         int ny = image->get_ysize();
06789         int nz = image->get_zsize();
06790 
06791         int a0 = params.set_default("first", 0);
06792         int a1 = params.set_default("last", -1);
06793 
06794         EMData* ret = new EMData;
06795         // compress one of the dimensions
06796         if ( dir == "x" ) {
06797                 ret->set_size(nz,ny);
06798 
06799                 // bounds checks
06800                 if (a0<0) a0+=nx;
06801                 if (a1<0) a1+=nx;
06802                 if (a0<0) a0=0;
06803                 if (a1<0) a1=0;
06804                 if (a0>=nx) a0=nx-1;
06805                 if (a1>=nx) a1=nx-1;
06806 
06807                 for (int y=0; y<ny; y++) {
06808                         for (int z=0; z<nz; z++) {
06809                                 double sum=0.0;
06810                                 for (int x=a0; x<=a1; x++) sum+=image->get_value_at(x,y,z);
06811                                 ret->set_value_at(z,y,(float)sum);
06812                         }
06813                 }
06814         }
06815         else if ( dir == "y" ) {
06816                 ret->set_size(nx,nz);
06817 
06818                 // bounds checks
06819                 if (a0<0) a0+=ny;
06820                 if (a1<0) a1+=ny;
06821                 if (a0<0) a0=0;
06822                 if (a1<0) a1=0;
06823                 if (a0>=ny) a0=ny-1;
06824                 if (a1>=ny) a1=ny-1;
06825 
06826                 for (int x=0; x<nx; x++) {
06827                         for (int z=0; z<nz; z++) {
06828                                 double sum=0.0;
06829                                 for (int y=a0; y<=a1; y++) sum+=image->get_value_at(x,y,z);
06830                                 ret->set_value_at(x,z,(float)sum);
06831                         }
06832                 }
06833         }
06834         else if ( dir == "z" ) {
06835                 ret->set_size(nx,ny);
06836 
06837                 // bounds checks
06838                 if (a0<0) a0+=nz;
06839                 if (a1<0) a1+=nz;
06840                 if (a0<0) a0=0;
06841                 if (a1<0) a1=0;
06842                 if (a0>=nz) a0=nz-1;
06843                 if (a1>=nz) a1=nz-1;
06844 
06845                 for (int y=0; y<ny; y++) {
06846                         for (int x=0; x<nx; x++) {
06847                                 double sum=0.0;
06848                                 for (int z=a0; z<=a1; z++) sum+=image->get_value_at(x,y,z);
06849                                 ret->set_value_at(x,y,(float)sum);
06850                         }
06851                 }
06852         }
06853 
06854         ret->update();
06855         return ret;
06856 }
06857 
06858 void TestImageProcessor::preprocess(EMData * image)
06859 {
06860         if (!image) {
06861                 LOGWARN("NULL Image");
06862                 return;
06863         }
06864 
06865         nx = image->get_xsize();
06866         ny = image->get_ysize();
06867         nz = image->get_zsize();
06868 }
06869 
06870 
06871 void TestImageFourierNoiseGaussian::process_inplace(EMData* image)
06872 {
06873         if (!image->is_complex()) {
06874                 int nx = image->get_xsize();
06875                 int offset = 2 - nx%2;
06876 
06877                 image->set_size(nx+offset,image->get_ysize(),image->get_zsize());
06878                 image->set_complex(true);
06879                 if (1 == offset) image->set_fftodd(true);
06880                 else image->set_fftodd(false);
06881                 image->set_fftpad(true);
06882         }
06883         image->ri2ap();
06884 
06885         float sigma = params.set_default("sigma",.25f);
06886 
06887         float * d = image->get_data();
06888         int nx = image->get_xsize();
06889         int ny = image->get_ysize();
06890         int nxy = image->get_ysize()*nx;
06891         int nzon2 = image->get_zsize()/2;
06892         int nyon2 = image->get_ysize()/2;
06893         float rx, ry, rz, length, amp, phase;
06894         int twox;
06895         for (int z = 0; z< image->get_zsize(); ++z) {
06896                 for (int y = 0; y < image->get_ysize(); ++y) {
06897                         for (int x = 0; x < image->get_xsize()/2; ++x) {
06898                                 rx = (float)x;
06899                                 ry = (float)nyon2 - (float)y;
06900                                 rz = (float)nzon2 - (float)z;
06901                                 length = sqrt(rx*rx + ry*ry + rz*rz);
06902                                 amp = exp(-sigma*length);
06903                                 phase = Util::get_frand(0,1)*2*M_PI;
06904 
06905                                 twox = 2*x;
06906                                 size_t idx1 = twox + y*nx+(size_t)z*nxy;
06907                                 size_t idx2 = idx1 + 1;
06908                                 d[idx1] = amp;
06909                                 d[idx2] = phase;
06910 
06911                         }
06912                 }
06913         }
06914 
06915         image->ap2ri();
06916         if (image->get_ndim() == 2) {
06917                 bool yodd = image->get_ysize() % 2 == 1;
06918 
06919                 int yit = image->get_ysize()/2-1;
06920                 int offset = 1;
06921                 if (yodd) {
06922                         offset = 0;
06923                 }
06924                 for (int y = 0; y < yit; ++y) {
06925                         int bot_idx = (y+offset)*nx;
06926                         int top_idx = (ny-1-y)*nx;
06927                         float r1 = d[bot_idx];
06928                         float i1 = d[bot_idx+1];
06929                         float r2 = d[top_idx];
06930                         float i2 = d[top_idx+1];
06931                         float r = (r1 + r2)/2.0f;
06932                         float i = (i1 + i2)/2.0f;
06933                         d[bot_idx] = r;
06934                         d[top_idx] = r;
06935                         d[bot_idx+1] = i;
06936                         d[top_idx+1] = -i;
06937 
06938                         bot_idx = (y+offset)*nx+nx-2;
06939                         top_idx = (ny-1-y)*nx+nx-2;
06940                         r1 = d[bot_idx];
06941                         i1 = d[bot_idx+1];
06942                         r2 = d[top_idx];
06943                         i2 = d[top_idx+1];
06944                         r = (r1 + r2)/2.0f;
06945                         i = (i1 + i2)/2.0f;
06946                         d[bot_idx] = r;
06947                         d[top_idx] = r;
06948                         d[bot_idx+1] = i;
06949                         d[top_idx+1] = -i;
06950                 }
06951 
06952                 d[1] = 0; // 0 phase for this componenet
06953                 d[nx-1] = 0; // 0 phase for this component
06954                 d[ny/2*nx+nx-1] = 0;// 0 phase for this component
06955                 d[ny/2*nx+1] = 0;// 0 phase for this component
06956         }
06957 
06958         if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
06959         image->do_ift_inplace();
06960         image->depad();
06961 }
06962 
06963 #include <iostream>
06964 using std::ostream_iterator;
06965 
06966 void CTFSNRWeightProcessor::process_inplace(EMData* image) {
06967         if (params.has_key("noise")==false) throw InvalidParameterException("You must supply the noise argument");
06968         if (params.has_key("snr")==false) throw InvalidParameterException("You must supply the snr argument");
06969 
06970         float boost = params.set_default("boost",1.0f);
06971 
06972         if (!image->is_complex()) {
06973                 image->do_fft_inplace();
06974         }
06975         EMData* cpy = image->copy();
06976         cpy->ri2inten();
06977         vector<float> sf = cpy->calc_radial_dist(cpy->get_ysize()/2,0.0,1.0,1);
06978         transform(sf.begin(),sf.end(),sf.begin(),sqrtf);
06979         delete cpy;
06980 
06981         image->ri2ap();
06982 
06983         vector<float> noise = params["noise"];
06984         vector<float> snr = params["snr"];
06985 
06986 //      copy(snr.begin(), snr.end(), ostream_iterator<float>(cout, "\n"));
06987 //      copy(noise.begin(), noise.end(), ostream_iterator<float>(cout, "\n"));
06988 
06989         for(vector<float>::iterator it = noise.begin(); it != noise.end(); ++it){
06990                 if ((*it) == 0) *it = 1;
06991         }
06992         for(vector<float>::iterator it = snr.begin(); it != snr.end(); ++it){
06993                 if ((*it) < 0) *it = 0;
06994         }
06995         // Subtract the mean from the data and store it in data_mm
06996         transform(snr.begin(),snr.end(),noise.begin(),snr.begin(),std::multiplies<float>());
06997         transform(snr.begin(),snr.end(),snr.begin(),sqrtf);
06998 //      copy(snr.begin(), snr.end(), ostream_iterator<float>(cout, "\n"));
06999 //      copy(noise.begin(), noise.end(), ostream_iterator<float>(cout, "\n"));
07000 
07001         int i = static_cast<int>(snr.size());
07002 
07003         float * d = image->get_data();
07004         int nx = image->get_xsize();
07005 //      int ny = image->get_ysize();
07006         int nxy = image->get_ysize()*nx;
07007         int nzon2 = image->get_zsize()/2;
07008         int nyon2 = image->get_ysize()/2;
07009         float rx, ry, rz, amp;
07010         int length;
07011         int twox;
07012         image->process_inplace("xform.fourierorigin.tocenter");
07013         for (int z = 0; z< image->get_zsize(); ++z) {
07014                 for (int y = 0; y < image->get_ysize(); ++y) {
07015                         for (int x = 0; x < image->get_xsize()/2; ++x) {
07016                                 rx = (float)x;
07017                                 ry = (float)nyon2 - (float)y;
07018                                 rz = (float)nzon2 - (float)z;
07019                                 length = static_cast<int>(sqrt(rx*rx + ry*ry + rz*rz));
07020 
07021                                 twox = 2*x;
07022                                 size_t idx1 = twox + y*nx+(size_t)z*nxy;
07023                                 if (length >= i || length >= (int)sf.size()) {
07024                                         d[idx1] = 0;
07025                                         continue;
07026                                 } else {
07027                                         amp = boost*snr[length];
07028 //                                      if (amp > 0) amp =sqrtf(amp);
07029 //                                      else amp = 0;
07030                                 }
07031 
07032                                 if (sf[length] == 0) {
07033                                         d[idx1] = 0;
07034                                         continue;
07035                                 }
07036 
07037 //                              size_t idx2 = idx1 + 1;
07038 //                              cout << d[idx1] << " " << sf[length] << endl;
07039                                 d[idx1] /= sf[length];
07040                                 if (d[idx1] < 0) {
07041                                         d[idx1] *= amp;
07042                                 }else {
07043                                         d[idx1] *= -amp;
07044                                 }
07045 //                              d[idx2] = phase;
07046 
07047                         }
07048                 }
07049         }
07050 
07051         image->ap2ri();
07052         if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
07053         image->do_ift_inplace();
07054         image->depad();
07055 }
07056 
07057 void TestImageFourierNoiseProfile::process_inplace(EMData * image) {
07058 
07059         if (params.has_key("profile")==false) throw InvalidParameterException("You must supply the profile argument");
07060 
07061         if (!image->is_complex()) {
07062                 int nx = image->get_xsize();
07063                 int offset = 2 - nx%2;
07064 
07065                 image->set_size(nx+offset,image->get_ysize(),image->get_zsize());
07066                 image->set_complex(true);
07067                 if (1 == offset) image->set_fftodd(true);
07068                 else image->set_fftodd(false);
07069                 image->set_fftpad(true);
07070         }
07071         image->to_zero();
07072         image->ri2ap();
07073 
07074         vector<float> profile = params["profile"];
07075         transform(profile.begin(),profile.end(),profile.begin(),sqrtf);
07076 
07077         int i = static_cast<int>(profile.size());
07078 
07079         float * d = image->get_data();
07080         int nx = image->get_xsize();
07081         int ny = image->get_ysize();
07082         int nxy = image->get_ysize()*nx;
07083         int nzon2 = image->get_zsize()/2;
07084         int nyon2 = image->get_ysize()/2;
07085         float rx, ry, rz, amp, phase;
07086         int length;
07087         int twox;
07088         for (int z = 0; z< image->get_zsize(); ++z) {
07089                 for (int y = 0; y < image->get_ysize(); ++y) {
07090                         for (int x = 0; x < image->get_xsize()/2; ++x) {
07091                                 rx = (float)x;
07092                                 ry = (float)nyon2 - (float)y;
07093                                 rz = (float)nzon2 - (float)z;
07094                                 length = static_cast<int>(sqrt(rx*rx + ry*ry + rz*rz));
07095 
07096                                 twox = 2*x;
07097                                 size_t idx1 = twox + y*nx+(size_t)z*nxy;
07098                                 size_t idx2 = idx1 + 1;
07099 
07100 
07101                                 if (length >= i) {
07102                                         d[idx1] = 0;
07103                                         d[idx2] = 0;
07104                                         continue;
07105                                 }
07106                                 amp = profile[length];
07107                                 phase = Util::get_frand(0,1)*2*M_PI;
07108 
07109 
07110                                 d[idx1] = amp;
07111                                 d[idx2] = phase;
07112 
07113                         }
07114                 }
07115         }
07116 
07117         image->ap2ri();
07118         if (image->get_ndim() == 2) {
07119                 bool yodd = image->get_ysize() % 2 == 1;
07120 
07121                 int yit = image->get_ysize()/2-1;
07122                 int offset = 1;
07123                 if (yodd) {
07124                         offset = 0;
07125                 }
07126                 for (int y = 0; y < yit; ++y) {
07127                         int bot_idx = (y+offset)*nx;
07128                         int top_idx = (ny-1-y)*nx;
07129                         float r1 = d[bot_idx];
07130                         float i1 = d[bot_idx+1];
07131                         float r2 = d[top_idx];
07132                         float i2 = d[top_idx+1];
07133                         float r = (r1 + r2)/2.0f;
07134                         float i = (i1 + i2)/2.0f;
07135                         d[bot_idx] = r;
07136                         d[top_idx] = r;
07137                         d[bot_idx+1] = i;
07138                         d[top_idx+1] = -i;
07139 
07140                         bot_idx = (y+offset)*nx+nx-2;
07141                         top_idx = (ny-1-y)*nx+nx-2;
07142                         r1 = d[bot_idx];
07143                         i1 = d[bot_idx+1];
07144                         r2 = d[top_idx];
07145                         i2 = d[top_idx+1];
07146                         r = (r1 + r2)/2.0f;
07147                         i = (i1 + i2)/2.0f;
07148                         d[bot_idx] = r;
07149                         d[top_idx] = r;
07150                         d[bot_idx+1] = i;
07151                         d[top_idx+1] = -i;
07152                 }
07153 
07154                 d[1] = 0; // 0 phase for this componenet
07155                 d[nx-1] = 0; // 0 phase for this component
07156                 d[ny/2*nx+nx-1] = 0;// 0 phase for this component
07157                 d[ny/2*nx+1] = 0;// 0 phase for this component
07158         }
07159 
07160         if (image->get_ndim() != 1) image->process_inplace("xform.fourierorigin.tocorner");
07161         image->do_ift_inplace();
07162         image->depad();
07163 }
07164 
07165 void TestImageLineWave::process_inplace(EMData * image)
07166 {
07167         preprocess(image);
07168 
07169         float period = params.set_default("period",10.0f);
07170         size_t n = (size_t)image->get_xsize()*image->get_ysize()*image->get_zsize();
07171 
07172         for(size_t i = 0; i < n; ++i) {
07173                 float x = fmod((float)i,period);
07174                 x /= period;
07175                 x = (float)sin(x*EMConsts::pi*2.0);
07176                 image->set_value_at_fast(i,x);
07177         }
07178 }
07179 
07180 void TestImageGaussian::process_inplace(EMData * image)
07181 {
07182         preprocess(image);
07183 
07184         float sigma = params["sigma"];
07185         string axis = (const char*)params["axis"];
07186         float c = params["c"];
07187 
07188         float *dat = image->get_data();
07189         float r; //this is the distance of pixel from the image center(nx/2, ny/2, nz/2)
07190         float x2, y2, z2; //this is the coordinates of this pixel from image center
07191         for (int k = 0; k < nz; ++k) {
07192                 for (int j = 0; j < ny; ++j) {
07193                         for (int i = 0; i < nx; ++i, ++dat) {
07194                                 x2 = (float)( i - nx/2 );
07195                                 y2 = (float)( j - ny/2 );
07196                                 z2 = (float)( k - nz/2 );
07197 
07198                                 if(axis==""){
07199                                         r = (float)sqrt(x2*x2+y2*y2+z2*z2);
07200                                 }
07201                                 else if(axis == "x"){
07202                                         float lc = -c;
07203                                         float rc = c;
07204                                         r = ( (float)sqrt((x2-lc)*(x2-lc)+y2*y2+z2*z2) +
07205                                                   (float)sqrt((x2-rc)*(x2-rc)+y2*y2+z2*z2) ) /2.0f - c;
07206                                 }
07207                                 else if(axis == "y"){
07208                                         float lc = -c;
07209                                         float rc = c;
07210                                         r = ( (float)sqrt(x2*x2+(y2-lc)*(y2-lc)+z2*z2) +
07211                                                   (float)sqrt(x2*x2+(y2-rc)*(y2-rc)+z2*z2) ) /2.0f - c;
07212                                 }
07213                                 else if(axis == "z"){
07214                                         if( nz == 1 ){
07215                                                 throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07216                                         }
07217                                         float lc = -c;
07218                                         float rc = c;
07219                                         r = ( (float)sqrt(x2*x2+y2*y2+(z2-lc)*(z2-lc)) +
07220                                                   (float)sqrt(x2*x2+y2*y2+(z2-rc)*(z2-rc)) ) /2.0f - c;
07221                                 }
07222                                 else{
07223                                         throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07224                                 }
07225                                 //the amplitude of the pixel is proportional to the distance of this pixel from the center
07226                                 *dat = (float)gsl_ran_gaussian_pdf((double)r,(double)sigma);
07227                         }
07228                 }
07229         }
07230 
07231         image->update();
07232 }
07233 
07234 void TestImageGradient::process_inplace(EMData * image)
07235 {
07236         string axis = params.set_default("axis", "x");
07237 
07238         float m = params.set_default("m", 1.0f);
07239         float b = params.set_default("b", 0.0f);
07240 
07241         if ( axis != "z" && axis != "y" && axis != "x") throw InvalidParameterException("Axis must be x,y or z");
07242 
07243         preprocess(image);
07244 
07245         if ( axis == "x")
07246         {
07247                 for(int k=0; k<nz;++k) {
07248                         for(int j=0; j<ny; ++j) {
07249                                 for(int i=0; i <nx; ++i) {
07250                                         image->set_value_at(i,j,k,m*i+b);
07251                                 }
07252                         }
07253                 }
07254         }
07255         else if ( axis == "y")
07256         {
07257                 for(int k=0; k<nz;++k) {
07258                         for(int j=0; j<ny; ++j) {
07259                                 for(int i=0; i <nx; ++i) {
07260                                         image->set_value_at(i,j,k,m*j+b);
07261                                 }
07262                         }
07263                 }
07264         }
07265         else if ( axis == "z")
07266         {
07267                 for(int k=0; k<nz;++k) {
07268                         for(int j=0; j<ny; ++j) {
07269                                 for(int i=0; i <nx; ++i) {
07270                                         image->set_value_at(i,j,k,m*k+b);
07271                                 }
07272                         }
07273                 }
07274         }
07275         image->update();
07276 }
07277 
07278 void TestImageAxes::process_inplace(EMData * image)
07279 {
07280         preprocess(image);
07281 
07282         float fill = params.set_default("fill", 1.0f);
07283         // get the central coordinates
07284         int cx = nx/2;
07285         int cy = ny/2;
07286         int cz = nz/2;
07287 
07288         // Offsets are used to detect when "the extra pixel" needs to be filled in
07289         // They are implemented on the assumption that for odd dimensions
07290         // the "center pixel" is the center pixel, but for even dimensions the "center
07291         // pixel" is displaced in the positive direction by 1
07292         int xoffset = (nx % 2 == 0? 1:0);
07293         int yoffset = (ny % 2 == 0? 1:0);
07294         int zoffset = (nz % 2 == 0? 1:0);
07295 
07296         // This should never occur - but if indeed it did occur, the code in this function
07297         // would break - the function would proceed into the final "else" and seg fault
07298         // It is commented out but left for clarity
07299 //      if ( nx < 1 || ny < 1 || nz < 1 ) throw ImageDimensionException("Error: one of the image dimensions was less than zero");
07300 
07301         if ( nx == 1 && ny == 1 && nz == 1 )
07302         {
07303                 (*image)(0) = fill;
07304         }
07305         else if ( ny == 1 && nz == 1 )
07306         {
07307                 int radius = params.set_default("radius", cx );
07308                 if ( radius > cx ) radius = cx;
07309 
07310                 (*image)(cx) = fill;
07311                 for ( int i = 1; i <= radius-xoffset; ++i ) (*image)(cx+i) = fill;
07312                 for ( int i = 1; i <= radius; ++i ) (*image)(cx-i) = fill;
07313         }
07314         else if ( nz == 1 )
07315         {
07316                 int min = ( nx < ny ? nx : ny );
07317                 min /= 2;
07318 
07319                 int radius = params.set_default("radius", min );
07320                 if ( radius > min ) radius = min;
07321 
07322                 (*image)(cx,cy) = fill;
07323 
07324                 for ( int i = 1; i <= radius-xoffset; ++i ) (*image)(cx+i,cy) = fill;
07325                 for ( int i = 1; i <= radius-yoffset; ++i )(*image)(cx,cy+i) = fill;
07326 
07327                 for ( int i = 1; i <= radius; ++i )
07328                 {
07329                         (*image)(cx-i,cy) = fill;
07330                         (*image)(cx,cy-i) = fill;
07331                 }
07332 
07333         }
07334         else
07335         {
07336                 // nx > 1 && ny > 1 && nz > 1
07337                 int min = ( nx < ny ? nx : ny );
07338                 if (nz < min ) min = nz;
07339                 min /= 2;
07340 
07341                 int radius = params.set_default("radius", min);
07342                 if ( radius > min ) radius = min;
07343 
07344 
07345                 (*image)(cx,cy,cz) = fill;
07346                 for ( int i = 1; i <=radius-xoffset; ++i ) (*image)(cx+i,cy,cz) = fill;
07347                 for ( int i = 1; i <=radius-yoffset; ++i ) (*image)(cx,cy+i,cz) = fill;
07348                 for ( int i = 1; i <=radius-zoffset; ++i ) (*image)(cx,cy,cz+i) = fill;
07349                 for ( int i = 1; i <= radius; ++i )
07350                 {
07351                         (*image)(cx-i,cy,cz) = fill;
07352                         (*image)(cx,cy-i,cz) = fill;
07353                         (*image)(cx,cy,cz-i) = fill;
07354                 }
07355         }
07356 
07357         image->update();
07358 }
07359 
07360 void TestImageScurve::process_inplace(EMData * image)
07361 {
07362         preprocess(image);
07363 
07364         int dim_size = image->get_ndim();
07365         if( 2 != dim_size ) {
07366                 throw ImageDimensionException("works for 2D images only");
07367         }
07368 
07369         int nx = image->get_xsize();
07370         int ny = image->get_ysize();
07371         image->to_zero();
07372 
07373         for (int i=0; i<100; i++) {
07374                 int x=static_cast<int>( nx/2+nx/6.0*sin(i*2.0*3.14159/100.0) );
07375                 int y=ny/4+i*ny/200;
07376                 for (int xx=x-nx/10; xx<x+nx/10; xx++) {
07377                         for (int yy=y-ny/10; yy<y+ny/10; yy++) {
07378 #ifdef  _WIN32
07379                                 (*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);
07380 #else
07381                                 (*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);
07382 #endif
07383                         }
07384                 }
07385         }
07386 
07387         image->update();
07388 }
07389 
07390 void TestImagePureGaussian::process_inplace(EMData * image)
07391 {
07392         preprocess(image);
07393 
07394         float x_sigma = params["x_sigma"];
07395         float y_sigma = params["y_sigma"];
07396         float z_sigma = params["z_sigma"];
07397 
07398         float x_center = params["x_center"];
07399         float y_center = params["y_center"];
07400         float z_center = params["z_center"];
07401 
07402         int nx = image->get_xsize();
07403         int ny = image->get_ysize();
07404         int nz = image->get_zsize();
07405 
07406         float x_twosig2 = 2*x_sigma*x_sigma;
07407         float y_twosig2 = 2*y_sigma*y_sigma;
07408         float z_twosig2 = 2*z_sigma*z_sigma;
07409 
07410         float sr2pi = sqrt( 2.0f*(float)pi );
07411         float norm  = 1.0f/ ( x_sigma*sr2pi );
07412         if (ny > 1) {
07413                 norm *= 1.0f/ ( y_sigma*sr2pi );
07414                 if (nz > 1) norm  *= 1.0f/ ( z_sigma*sr2pi );
07415         }
07416 
07417         float z, y, x, sum, val;
07418         for (int iz=0; iz < nz; ++iz) {
07419                 z = static_cast<float>(iz) - z_center;
07420                 for (int iy=0; iy < ny; ++iy) {
07421                         y = static_cast<float>(iy) - y_center;
07422                         for (int ix=0; ix < nx; ++ix) {
07423                                 x = static_cast<float>(ix) - x_center;
07424                                 sum = x*x/x_twosig2 + y*y/y_twosig2 + z*z/z_twosig2;
07425                                 val = norm*exp(-sum);
07426                                 (*image)(ix,iy,iz) = val;
07427                         }
07428                 }
07429         }
07430         image->update();
07431 }
07432 
07433 void TestImageSphericalWave::process_inplace(EMData * image)
07434 {
07435         preprocess(image);
07436 
07437         if(!params.has_key("wavelength")) {
07438                 LOGERR("%s wavelength is required parameter", get_name().c_str());
07439                 throw InvalidParameterException("wavelength parameter is required.");
07440         }
07441         float wavelength = params["wavelength"];
07442 
07443         float phase = 0;
07444         if(params.has_key("phase")) {
07445                 phase = params["phase"];
07446         }
07447 
07448         float x = (float)(nx/2);
07449         if (params.has_key("x")) x=params["x"];
07450         float y = (float)(ny/2);
07451         if (params.has_key("y")) y=params["y"];
07452         float z = (float)(nz/2);
07453         if (params.has_key("z")) z=params["z"];
07454 
07455         int ndim = image->get_ndim();
07456 
07457         if(ndim==2) {   //2D
07458                 for(int j=0; j<ny; ++j) {
07459                         for(int i=0; i<nx; ++i) {
07460 #ifdef _WIN32
07461                                 float r=_hypotf(x-(float)i,y-(float)j);
07462 #else
07463                                 float r=hypot(x-(float)i,y-(float)j);
07464 #endif  //_WIN32
07465                                 if (r<.5) continue;
07466                                 image->set_value_at(i,j,cos(2*(float)pi*r/wavelength+phase)/r);
07467                         }
07468                 }
07469         }
07470         else {  //3D
07471                 for(int k=0; k<nz; ++k) {
07472                         for(int j=0; j<ny; ++j) {
07473                                 for(int i=0; i<nx; ++i) {
07474                                         float r=Util::hypot3(x-(float)i,y-(float)j,z-(float)k);
07475                                         if (r<.5) continue;
07476                                         image->set_value_at(i,j,k,cos(2*(float)pi*r/wavelength+phase)/(r*r));
07477                                 }
07478                         }
07479                 }
07480         }
07481 
07482         image->update();
07483 }
07484 
07485 
07486 void TestImageSinewave::process_inplace(EMData * image)
07487 {
07488         preprocess(image);
07489 
07490         if(!params.has_key("wavelength")) {
07491                 LOGERR("%s wavelength is required parameter", get_name().c_str());
07492                 throw InvalidParameterException("wavelength parameter is required.");
07493         }
07494         float wavelength = params["wavelength"];
07495 
07496         string axis = "";
07497         if(params.has_key("axis")) {
07498                 axis = (const char*)params["axis"];
07499         }
07500 
07501         float phase = 0;
07502         if(params.has_key("phase")) {
07503                 phase = params["phase"];
07504         }
07505 
07506         int ndim = image->get_ndim();
07507         float * dat = image->get_data();
07508 
07509         if(ndim==1) {   //1D
07510                 for(int i=0; i<nx; ++i, ++dat) {
07511                         *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
07512                 }
07513         }
07514         else if(ndim==2) {      //2D
07515                 float alpha = 0;
07516                 if(params.has_key("az")) {
07517                         alpha = params["az"];
07518                 }
07519                 for(int j=0; j<ny; ++j) {
07520                         for(int i=0; i<nx; ++i, ++dat) {
07521                                 if(alpha != 0) {
07522                                         *dat = sin((i*sin((180-alpha)*M_PI/180)+j*cos((180-alpha)*M_PI/180))*(2.0f*M_PI/wavelength) + phase);
07523                                 }
07524                                 else if(axis.compare("y")==0 || axis.compare("Y")==0) {
07525                                         *dat = sin(j*(2.0f*M_PI/wavelength) + phase);
07526                                 }
07527                                 else {
07528                                         *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
07529                                 }
07530                         }
07531                 }
07532         }
07533         else {  //3D
07534                 float az = 0;
07535                 if(params.has_key("az")) {
07536                         az = params["az"];
07537                 }
07538                 float alt = 0;
07539                 if(params.has_key("alt")) {
07540                         alt = params["alt"];
07541                 }
07542                 float phi = 0;
07543                 if(params.has_key("phi")) {
07544                         phi = params["phi"];
07545                 }
07546 
07547                 for(int k=0; k<nz; ++k) {
07548                         for(int j=0; j<ny; ++j) {
07549                                 for(int i=0; i<nx; ++i, ++dat) {
07550                                         if(axis.compare("z")==0 || axis.compare("Z")==0) {
07551                                                 *dat = sin(k*(2.0f*M_PI/wavelength) + phase);
07552                                         }
07553                                         else if(axis.compare("y")==0 || axis.compare("Y")==0) {
07554                                                 *dat = sin(j*(2.0f*M_PI/wavelength) + phase);
07555                                         }
07556                                         else {
07557                                                 *dat = sin(i*(2.0f*M_PI/wavelength) + phase);
07558                                         }
07559                                 }
07560                         }
07561                 }
07562 
07563                 if(az != 0 || alt != 0 || phi != 0) {
07564                         Dict d("type","eman");
07565                         d["az"] = az; d["phi"] = phi; d["alt"] = alt;
07566                         image->transform(Transform(d));
07567                 }
07568         }
07569 
07570         image->update();
07571 }
07572 
07573 void TestImageSinewaveCircular::process_inplace(EMData * image)
07574 {
07575         preprocess(image);
07576 
07577         float wavelength = params["wavelength"];
07578         string axis = (const char*)params["axis"];
07579         float c = params["c"];
07580         float phase = params["phase"];
07581 
07582         float *dat = image->get_data();
07583         float r; //this is the distance of pixel from the image center(nx/2, ny/2, nz/2)
07584         float x2, y2, z2; //this is the coordinates of this pixel from image center
07585         for (int k = 0; k < nz; ++k) {
07586                 for (int j = 0; j < ny; ++j) {
07587                         for (int i = 0; i < nx; ++i, ++dat) {
07588                                 x2 = (float)( i - nx/2 );
07589                                 y2 = (float)( j - ny/2 );
07590                                 z2 = (float)( k - nz/2 );
07591                                 if(axis == ""){
07592                                         r = (float)sqrt(x2*x2+y2*y2+z2*z2);
07593                                 }
07594                                 else if(axis == "x"){
07595                                         float lc = -c;
07596                                         float rc = c;
07597                                         r = ( (float)sqrt((x2-lc)*(x2-lc)+y2*y2+z2*z2) +
07598                                                   (float)sqrt((x2-rc)*(x2-rc)+y2*y2+z2*z2) ) /2.0f - c;
07599                                 }
07600                                 else if(axis == "y"){
07601                                         float lc = -c;
07602                                         float rc = c;
07603                                         r = ( (float)sqrt(x2*x2+(y2-lc)*(y2-lc)+z2*z2) +
07604                                                   (float)sqrt(x2*x2+(y2-rc)*(y2-rc)+z2*z2) ) /2.0f - c;
07605                                 }
07606                                 else if(axis == "z"){
07607                                         if( nz == 1 ){
07608                                                 throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07609                                         }
07610                                         float lc = -c;
07611                                         float rc = c;
07612                                         r = ( (float)sqrt(x2*x2+y2*y2+(z2-lc)*(z2-lc)) +
07613                                                   (float)sqrt(x2*x2+y2*y2+(z2-rc)*(z2-rc)) ) /2.0f - c;
07614                                 }
07615                                 else{
07616                                         throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07617                                 }
07618                                 *dat = sin( r * (2.0f*M_PI/wavelength) - phase*180/M_PI);
07619                         }
07620                 }
07621         }
07622 
07623         image->update();
07624 }
07625 
07626 void TestImageSquarecube::process_inplace(EMData * image)
07627 {
07628         preprocess(image);
07629 
07630         float edge_length = params["edge_length"];
07631         string axis = (const char*)params["axis"];
07632         float odd_edge = params["odd_edge"];
07633         int fill = 1;
07634         if(params.has_key("fill")) {
07635                 fill = (int)params["fill"];
07636         }
07637 
07638         float *dat = image->get_data();
07639         float x2, y2, z2; //this coordinates of this pixel from center
07640         float xEdge, yEdge, zEdge; //half of edge length for this cube
07641         if(axis == ""){
07642                 xEdge = edge_length/2.0f;
07643                 yEdge = edge_length/2.0f;
07644                 zEdge = edge_length/2.0f;
07645         }
07646         else if(axis == "x"){
07647                 xEdge = odd_edge/2.0f;
07648                 yEdge = edge_length/2.0f;
07649                 zEdge = edge_length/2.0f;
07650         }
07651         else if(axis == "y"){
07652                 xEdge = edge_length/2.0f;
07653                 yEdge = odd_edge/2.0f;
07654                 zEdge = edge_length/2.0f;
07655         }
07656         else if(axis == "z"){
07657                 if( nz == 1 ){
07658                         throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07659                 }
07660                 xEdge = edge_length/2.0f;
07661                 yEdge = edge_length/2.0f;
07662                 zEdge = odd_edge/2.0f;
07663         }
07664         else{
07665                 throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07666         }
07667         for (int k = 0; k < nz; ++k) {
07668                 for (int j = 0; j < ny; ++j) {
07669                         for (int i = 0; i < nx; ++i, ++dat) {
07670                                 x2 = (float)fabs((float)i - nx/2);
07671                                 y2 = (float)fabs((float)j - ny/2);
07672                                 z2 = (float)fabs((float)k - nz/2);
07673                                 if( x2<=xEdge && y2<=yEdge && z2<=zEdge ) {
07674                                         if( !fill) {
07675                                                 *dat = 0;
07676                                         }
07677                                         else {
07678                                                 *dat = 1;
07679                                         }
07680                                 }
07681                                 else {
07682                                         if( !fill ) {
07683                                                 *dat = 1;
07684                                         }
07685                                         else {
07686                                                 *dat = 0;
07687                                         }
07688                                 }
07689                         }
07690                 }
07691         }
07692 
07693         image->update();
07694 }
07695 
07696 void TestImageCirclesphere::process_inplace(EMData * image)
07697 {
07698         preprocess(image);
07699 
07700         float radius = params.set_default("radius",nx/2.0f);
07701         string axis = (const char*)params["axis"];
07702         float c =  params.set_default("c",nx/2.0f);
07703         int fill = params.set_default("fill",1);
07704 
07705         float *dat = image->get_data();
07706         float x2, y2, z2; //this is coordinates of this pixel from center
07707         float r = 0.0f;
07708         float asy = 0.0f;
07709         if(axis == ""){
07710                 asy = radius;
07711         }
07712         else if(axis == "x" || axis == "y"){
07713                 asy = c;
07714         }
07715         else if(axis=="z"){
07716                 if( nz == 1 ){
07717                         throw InvalidValueException(0, "This is a 2D image, no asymmetric feature for z axis");
07718                 }
07719                 asy = c;
07720         }
07721         else{
07722                 throw InvalidValueException(0, "please specify a valid axis for asymmetric features");
07723         }
07724 
07725         for (int k = 0; k < nz; ++k) {
07726                 for (int j = 0; j < ny; ++j) {
07727                         for (int i = 0; i < nx; ++i, ++dat) {
07728                                 x2 = fabs((float)i - nx/2);
07729                                 y2 = fabs((float)j - ny/2);
07730                                 z2 = fabs((float)k - nz/2);
07731                                 if( axis == "" ){
07732                                         r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius) + (z2*z2)/(radius*radius);
07733                                 }
07734                                 else if (axis == "x"){
07735                                         r = (x2*x2)/(asy*asy) + (y2*y2)/(radius*radius) + (z2*z2)/(radius*radius);
07736                                 }
07737                                 else if(axis == "y"){
07738                                         r = (x2*x2)/(radius*radius) + (y2*y2)/(asy*asy) + (z2*z2)/(radius*radius);
07739                                 }
07740                                 else if(axis=="z"){
07741                                         r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius) + (z2*z2)/(asy*asy);
07742                                 }
07743                                 if( r<=1 ) {
07744                                         if( !fill) {
07745                                                 *dat = 0;
07746                                         }
07747                                         else {
07748                                                 *dat = 1;
07749                                         }
07750                                 }
07751                                 else {
07752                                         if( !fill ) {
07753                                                 *dat = 1;
07754                                         }
07755                                         else {
07756                                                 *dat = 0;
07757                                         }
07758                                 }
07759                         }
07760                 }
07761         }
07762 
07763         image->update();
07764 }
07765 
07766 void TestImageHollowEllipse::process_inplace(EMData * image)
07767 {
07768         preprocess(image);
07769 
07770         float width = params.set_default("width",2.0f);
07771 
07772         float a2 = params.set_default("a",nx/2.0f-1.0f);
07773         float b2 = params.set_default("b",ny/2.0f-1.0f);
07774         float c2 = params.set_default("c",nz/2.0f-1.0f);
07775 
07776         float a1 = params.set_default("xwidth",a2-width);
07777         float b1 = params.set_default("ywidth",b2-width);
07778         float c1 = params.set_default("zwidth",c2-width);
07779 
07780         float fill = params.set_default("fill",1.0f);
07781         Transform* t;
07782         if (params.has_key("transform")) {
07783                 t = params["transform"];
07784         } else {
07785                 t = new Transform;
07786         }
07787 
07788 
07789         int mz = 2*(int)c2+1;
07790         if ( nz < mz ) mz = nz;
07791         int my = 2*(int)b2+1;
07792         if ( ny < my ) my = ny;
07793         int mx = 2*(int)a2+1;
07794         if ( nx < mx ) mx = nx;
07795 
07796         float ai1 = 1/(a1*a1);
07797         float bi1 = 1/(b1*b1);
07798         float ci1 = 1/(c1*c1);
07799 
07800         float ai2 = 1/(a2*a2);
07801         float bi2 = 1/(b2*b2);
07802         float ci2 = 1/(c2*c2);
07803 
07804         Vec3f origin(nx/2,ny/2,nz/2);
07805 
07806         float x2, y2, z2, r1,r2;
07807         int xl, yl, zl;
07808         for (int k = 0; k < mz; ++k) {
07809                 for (int j = 0; j < my; ++j) {
07810                         for (int i = 0; i < mx; ++i) {
07811                                 x2 = (float)(i - mx/2);
07812                                 y2 = (float)(j - my/2);
07813                                 z2 = (float)(k - mz/2);
07814                                 r1 = (x2*x2)*ai1 + (y2*y2)*bi1 + (z2*z2)*ci1;
07815                                 r2 = (x2*x2)*ai2 + (y2*y2)*bi2 + (z2*z2)*ci2;
07816                                 if (r2 <= 1 && r1 >= 1) {
07817 
07818                                         if (t != 0) {
07819                                                 Vec3f v(x2,y2,z2);
07820                                                 v = (*t)*v;
07821                                                 v += origin;
07822 
07823                                                 // THIS ISN'T THE BEST STRATEGY BUT IT'S A STOP GAP. A FLOOD FILL IS PROBABLY BETTER
07824                                                 // I fill in 3x3 cubes to make sure there are no gaps...
07825 
07826                                                 for( int kk = -1; kk <= 1; ++kk)
07827                                                         for( int jj = -1; jj <= 1; ++jj)
07828                                                                 for( int ii = -1; ii <= 1; ++ii) {
07829                                                                         xl = (int)v[0]+ii;
07830                                                                         yl = (int)v[1]+jj;
07831                                                                         zl = (int)v[2]+kk;
07832                                                                         if (xl >= 0 && xl < nx && yl >= 0 && yl < ny && zl >= 0 && zl < nz)
07833                                                                                 image->set_value_at(xl,yl,zl,1.0);
07834                                                                 }
07835                                         } else {
07836                                                 image->set_value_at((int)x2+nx/2,(int)y2+ny/2,(int)z2+nz/2,fill);
07837                                         }
07838                                 }
07839                         }
07840                 }
07841         }
07842 
07843         delete t;
07844 
07845         image->update();
07846 }
07847 
07848 void TestImageEllipse::process_inplace(EMData * image)
07849 {
07850         preprocess(image);
07851 
07852 
07853         float a = params.set_default("a",nx/2.0f-1.0f);
07854         float b = params.set_default("b",ny/2.0f-1.0f);
07855         float c = params.set_default("c",nz/2.0f-1.0f);
07856         float fill = params.set_default("fill",1.0f);
07857         //bool hollow = params.set_default("hollow",false);
07858         Transform* t;
07859         if (params.has_key("transform")) {
07860                 t = params["transform"];
07861         } else {
07862                 t = new Transform;
07863         }
07864 
07865 
07866         int mz = 2*(int)c+1;
07867         if ( nz < mz ) mz = nz;
07868         int my = 2*(int)b+1;
07869         if ( ny < my ) my = ny;
07870         int mx = 2*(int)a+1;
07871         if ( nx < mx ) mx = nx;
07872 
07873 
07874         float ai = 1/(a*a);
07875         float bi = 1/(b*b);
07876         float ci = 1/(c*c);
07877 
07878         Vec3f origin(nx/2,ny/2,nz/2);
07879 
07880         float x2, y2, z2, r;
07881         int xl, yl, zl;
07882         for (int k = 0; k < mz; ++k) {
07883                 for (int j = 0; j < my; ++j) {
07884                         for (int i = 0; i < mx; ++i) {
07885                                 x2 = (float)(i - mx/2);
07886                                 y2 = (float)(j - my/2);
07887                                 z2 = (float)(k - mz/2);
07888                                 r = (x2*x2)*ai + (y2*y2)*bi + (z2*z2)*ci;
07889                                 if (r <= 1) {
07890 
07891                                         if (t != 0) {
07892                                                 Vec3f v(x2,y2,z2);
07893                                                 v = (*t)*v;
07894                                                 v += origin;
07895 
07896                                                 // THIS ISN'T THE BEST STRATEGY BUT IT'S A STOP GAP. A FLOOD FILL IS PROBABLY BETTER
07897                                                 // I fill in 3x3 cubes to make sure there are no gaps...
07898 
07899                                                 for( int kk = -1; kk <= 1; ++kk)
07900                                                         for( int jj = -1; jj <= 1; ++jj)
07901                                                                 for( int ii = -1; ii <= 1; ++ii) {
07902                                                                         xl = (int)v[0]+ii;
07903                                                                         yl = (int)v[1]+jj;
07904                                                                         zl = (int)v[2]+kk;
07905                                                                         if (xl >= 0 && xl < nx && yl >= 0 && yl < ny && zl >= 0 && zl < nz)
07906                                                                                 image->set_value_at(xl,yl,zl,fill);
07907                                                                 }
07908                                         } else {
07909                                                 image->set_value_at((int)x2+nx/2,(int)y2+ny/2,(int)z2+nz/2,fill);
07910                                         }
07911                                 }
07912                         }
07913                 }
07914         }
07915 
07916         delete t;
07917 
07918         image->update();
07919 }
07920 
07921 void TestImageNoiseUniformRand::process_inplace(EMData * image)
07922 {
07923         preprocess(image);
07924 
07925         Randnum * r = Randnum::Instance();
07926         if(params.has_key("seed")) {
07927                 r->set_seed((int)params["seed"]);
07928         }
07929 
07930         float *dat = image->get_data();
07931         size_t size = (size_t)nx*ny*nz;
07932         for (size_t i=0; i<size; ++i) {
07933                 dat[i] = r->get_frand();
07934         }
07935 
07936         image->update();
07937 }
07938 
07939 void TestImageNoiseGauss::process_inplace(EMData * image)
07940 {
07941         preprocess(image);
07942 
07943         float sigma = params["sigma"];
07944         if (sigma<=0) { sigma = 1.0; }
07945         float mean = params["mean"];
07946 
07947         Randnum * r = Randnum::Instance();
07948         if (params.has_key("seed")) {
07949                 r->set_seed((int)params["seed"]);
07950         }
07951 
07952         float *dat = image->get_data();
07953         size_t size = (size_t)nx*ny*nz;
07954         for (size_t i=0; i<size; ++i) {
07955                 dat[i] = r->get_gauss_rand(mean, sigma);
07956         }
07957 
07958         image->update();
07959 }
07960 
07961 void TestImageCylinder::process_inplace(EMData * image)
07962 {
07963         preprocess(image);
07964 
07965         int nx = image->get_xsize();
07966         int ny = image->get_ysize();
07967         int nz = image->get_zsize();
07968 
07969         if(nz == 1) {
07970                 throw ImageDimensionException("This processor only apply to 3D image");
07971         }
07972 
07973         float radius = params["radius"];
07974 #ifdef _WIN32
07975         if(radius > _cpp_min(nx, ny)/2.0) {
07976 #else
07977         if(radius > std::min(nx, ny)/2.0) {
07978 #endif
07979                 throw InvalidValueException(radius, "radius must be <= min(nx, ny)/2");
07980         }
07981 
07982         float height;
07983         if(params.has_key("height")) {
07984                 height = params["height"];
07985                 if(height > nz) {
07986                         throw InvalidValueException(radius, "height must be <= nz");
07987                 }
07988         }
07989         else {
07990                 height = static_cast<float>(nz);
07991         }
07992 
07993         float *dat = image->get_data();
07994         float x2, y2; //this is coordinates of this pixel from center axle
07995         float r = 0.0f;
07996         for (int k = 0; k < nz; ++k) {
07997                 for (int j = 0; j < ny; ++j) {
07998                         for (int i = 0; i < nx; ++i, ++dat) {
07999                                 x2 = fabs((float)i - nx/2);
08000                                 y2 = fabs((float)j - ny/2);
08001                                 r = (x2*x2)/(radius*radius) + (y2*y2)/(radius*radius);
08002 
08003                                 if(r<=1 && k>=(nz-height)/2 && k<=(nz+height)/2) {
08004                                         *dat = 1;
08005                                 }
08006                                 else {
08007                                         *dat = 0;
08008                                 }
08009                         }
08010                 }
08011         }
08012 
08013         image->update();
08014 }
08015 
08016 void RampProcessor::process_inplace(EMData * image)
08017 {
08018         if (!image) {
08019                 return;
08020         }
08021 
08022         int nz = image->get_zsize();
08023         if (nz > 1) {
08024                 LOGERR("%s Processor doesn't support 3D model", get_name().c_str());
08025                 throw ImageDimensionException("3D model not supported");
08026         }
08027 
08028         int nsam = image->get_xsize();
08029         int nrow = image->get_ysize();
08030         int n1 = nsam / 2;
08031         double sx1 = double(n1)*double(nsam+1);
08032         if ( nsam % 2 == 1 )
08033                 sx1 += 1 + n1;
08034         sx1 *= nrow;
08035         int n2 = nrow / 2;
08036         double sx2 = double(n2)*double(nrow+1);
08037         if ( nrow % 2 == 1 )
08038                 sx2 += 1 + n2;
08039         sx2 *= nsam;
08040         float *data = image->get_data();
08041         float *row = NULL; // handy pointer for values in a specific row of the data
08042         // statistical sums
08043         double syx1 = 0, syx2 = 0, sy = 0, sx1q = 0, sx2q = 0, syq = 0;
08044         for (int j=1; j <= nrow; j++) {
08045                 row = data + (j-1)*nsam - 1; // "-1" so that we can start counting at 1
08046                 for (int i=1; i<=nsam; i++) {
08047                         syx1 += row[i]*i;
08048                         syx2 += row[i]*j;
08049                         sy += row[i];
08050                         sx1q += i*i;
08051                         sx2q += j*j;
08052                         syq += row[i]*double(row[i]);
08053                 }
08054         }
08055         // least-squares
08056         float dn = float(nsam)*float(nrow);
08057         double qyx1 = syx1 - sx1*sy / dn;
08058         double qyx2 = syx2 - sx2*sy / dn;
08059         double qx1x2 = 0.0;
08060         double qx1 = sx1q - sx1*sx1 / dn;
08061         double qx2 = sx2q - sx2*sx2 / dn;
08062         double qy = syq - sy*sy / dn;
08063         double c = qx1*qx2 - qx1x2*qx1x2;
08064         if ( c > FLT_EPSILON ) {
08065                 double b1 = (qyx1*qx2 - qyx2*qx1x2) / c;
08066                 double b2 = (qyx2*qx1 - qyx1*qx1x2) / c;
08067                 double a = (sy - b1*sx1 - b2*sx2) / dn;
08068                 double d = a + b1 + b2;
08069                 for (int i=1; i<=nrow; i++) {
08070                         qy = d;
08071                         row = data + (i-1)*nsam - 1;
08072                         for (int k=1; k<=nsam; k++) {
08073                                 row[k] -= static_cast<float>(qy);
08074                                 qy += b1;
08075                         }
08076                         d += b2;
08077                 }
08078         } // image not altered if c is zero
08079 
08080         image->update();
08081 }
08082 
08083 
08084 void CCDNormProcessor::process_inplace(EMData * image)
08085 {
08086         if (!image) {
08087           Log::logger()->set_level(Log::ERROR_LOG);
08088           Log::logger()->error("Null image during call to CCDNorm\n");
08089           return;
08090         }
08091         if (image->get_zsize() > 1) {
08092           Log::logger()->set_level(Log::ERROR_LOG);
08093           Log::logger()->error("CCDNorm does not support 3d images\n");
08094           return;
08095         }
08096 
08097         int xs = image->get_xsize();
08098         int ys = image->get_ysize();
08099 
08100         // width of sample area on either side of the seams
08101         int width = params["width"];
08102 
08103         width%=(xs > ys ? xs/2 : ys/2);  // make sure width is a valid value
08104         if (width==0) {
08105           width=1;
08106         }
08107 
08108         // get the 4 "seams" of the image
08109         float *left, *right, *top, *bottom;
08110 
08111         double *temp;
08112         temp= (double*)malloc((xs > ys ? xs*width : ys*width)*sizeof(double));
08113         if (temp==NULL) {
08114           Log::logger()->set_level(Log::ERROR_LOG);
08115           Log::logger()->error("Could not allocate enough memory during call to CCDNorm\n");
08116           return;
08117         }
08118 
08119         int x, y, z;
08120 
08121         // the mean values of each seam and the average
08122         double mL,mR,mT,mB;
08123 
08124         // how much to shift each seam
08125         double nl,nr,nt,nb;
08126 
08127         // quad. shifting amount
08128         double q1,q2,q3,q4;
08129 
08130         // calc. the mean for each quadrant
08131         for (z=0; z<width; z++) {
08132           left = image->get_col(xs/2 -1-z)->get_data();
08133           for (y=0; y<ys; y++)
08134             temp[z*ys+y]=left[y];
08135         }
08136         mL=gsl_stats_mean(temp,1,ys*width);
08137 
08138         for (z=0; z<width; z++) {
08139           right = image->get_col(xs/2 +z)->get_data();
08140           for (y=0; y<ys; y++)
08141             temp[z*ys+y]=right[y];
08142         }
08143         mR=gsl_stats_mean(temp,1,ys*width);
08144 
08145         for (z=0; z<width; z++) {
08146           top = image->get_row(ys/2 -1-z)->get_data();
08147           for (x=0; x<xs; x++)
08148             temp[z*xs+x]=top[x];
08149         }
08150         mT=gsl_stats_mean(temp,1,xs*width);
08151 
08152         for (z=0; z<width; z++) {
08153           bottom = image->get_row(ys/2 +z)->get_data();
08154           for (x=0; x<xs; x++)
08155             temp[z*xs+x]=bottom[x];
08156         }
08157         mB=gsl_stats_mean(temp,1,xs*width);
08158 
08159         free(temp);
08160 
08161         nl=(mL+mR)/2-mL;
08162         nr=(mL+mR)/2-mR;
08163         nt=(mT+mB)/2-mT;
08164         nb=(mT+mB)/2-mB;
08165 
08166         q1=nl+nt;
08167         q2=nr+nt;
08168         q3=nr+nb;
08169         q4=nl+nb;
08170 
08171         // change the pixel values
08172         for (x = 0; x < xs / 2; x++)
08173           for (y = 0; y < ys / 2; y++) {
08174             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q1));
08175           }
08176         for (x = xs / 2; x < xs; x++)
08177           for (y = 0; y < ys / 2; y++) {
08178             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q2));
08179           }
08180         for (x = xs / 2; x < xs; x++)
08181           for (y = ys / 2; y < ys; y++) {
08182             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q3));
08183           }
08184         for (x = 0; x < xs / 2; x++)
08185           for (y = ys / 2; y < ys; y++) {
08186             image->set_value_at_fast(x, y, image->get_value_at(x, y) + static_cast<float>(q4));
08187           }
08188 
08189 }
08190 
08191 void WaveletProcessor::process_inplace(EMData *image)
08192 {
08193         if (image->get_zsize() != 1) {
08194                         LOGERR("%s Processor doesn't support 3D", get_name().c_str());
08195                         throw ImageDimensionException("3D model not supported");
08196         }
08197 
08198         int i,nx,ny;
08199         const gsl_wavelet_type * T;
08200         nx=image->get_xsize();
08201         ny=image->get_ysize();
08202 
08203         if (nx != ny && ny!=1) throw ImageDimensionException("Wavelet transform only supports square images");
08204 //      float l=log((float)nx)/log(2.0f);
08205 //      if (l!=floor(l)) throw ImageDimensionException("Wavelet transform size must be power of 2");
08206         if( !Util::IsPower2(nx) )  throw ImageDimensionException("Wavelet transform size must be power of 2");
08207 
08208         // Unfortunately GSL works only on double() arrays
08209         // eventually we should put our own wavelet code in here
08210         // but this will work for now
08211         double *cpy = (double *)malloc(nx*ny*sizeof(double));
08212 
08213         for (i=0; i<nx*ny; i++) cpy[i]=image->get_value_at(i,0,0);
08214 
08215         string tp = (const char*)params["type"];
08216         if (tp=="daub") T=gsl_wavelet_daubechies;
08217         else if (tp=="harr") T=gsl_wavelet_haar;
08218         else if (tp=="bspl") T=gsl_wavelet_bspline;
08219         else throw InvalidStringException(tp,"Invalid wavelet name, 'daub', 'harr' or 'bspl'");
08220 
08221         int K=(int)params["ord"];
08222         gsl_wavelet_direction dir;
08223         if ((int)params["dir"]==1) dir=forward;
08224         else dir=backward;
08225 
08226         gsl_wavelet *w = gsl_wavelet_alloc(T, K);
08227         gsl_wavelet_workspace *work = gsl_wavelet_workspace_alloc(nx);
08228 
08229         if (ny==1) gsl_wavelet_transform (w,cpy, 1, nx, dir, work);
08230         else gsl_wavelet2d_transform (w, cpy, nx,nx,ny, dir, work);
08231 
08232         gsl_wavelet_workspace_free (work);
08233         gsl_wavelet_free (w);
08234 
08235         for (i=0; i<nx*ny; i++) image->set_value_at_fast(i,0,0,static_cast<float>(cpy[i]));
08236 
08237         free(cpy);
08238 }
08239 
08240 void FFTProcessor::process_inplace(EMData* image)
08241 {
08242         if( params.has_key("dir") ) {
08243                 if ((int)params["dir"]==-1) {
08244                         image->do_ift_inplace();
08245                 }
08246                 else {
08247                         image->do_fft_inplace();
08248                 }
08249         }
08250 }
08251 
08252 void RadialProcessor::process_inplace(EMData * image)
08253 {
08254         if (!image) {
08255                 LOGWARN("NULL Image");
08256                 return;
08257         }
08258 
08259         //Note : real image only!
08260         if(image->is_complex()) {
08261                 LOGERR("%s Processor only operates on real images", get_name().c_str());
08262                 throw ImageFormatException("apply to real image only");
08263         }
08264 
08265         vector<float> table = params["table"];
08266         vector<float>::size_type tsize = table.size();
08267 
08268         int nx = image->get_xsize();
08269         int ny = image->get_ysize();
08270         int nz = image->get_zsize();
08271 
08272         int nx2 = nx / 2;
08273         int ny2 = ny / 2;
08274         int nz2 = nz / 2;
08275         float sz[3];
08276         sz[0] = static_cast<float>(nx2);
08277         sz[1] = static_cast<float>(ny2);
08278         sz[2] = static_cast<float>(nz2);
08279         float szmax = *std::max_element(&sz[0], &sz[3]);
08280         float maxsize;
08281         if(nz>1) {
08282                 maxsize = (float)(1.8f * szmax);
08283         }
08284         else{
08285                 maxsize = (float)(1.5f * szmax);
08286         }
08287         for(int i=tsize+1; i<maxsize; i++) {
08288                 table.push_back(0.0f);
08289         }
08290 
08291         float dx = 1.0f / (float)nx;
08292         float dy = 1.0f / (float)ny;
08293         float dz = 1.0f / (float)nz;
08294         float dx2 = dx * dx;
08295         float dy2 = dy * dy;
08296         float dz2 = dz * dz;
08297         int iz, iy, ix, jz, jy, jx;
08298         float argx, argy, argz;
08299         float rf, df, f;
08300         int ir;
08301         for(iz=1; iz<=nz; iz++) {
08302                 jz = iz - 1;
08303                 if(jz > nz2) {
08304                         jz -= nz;
08305                 }
08306                 argz = float(jz*jz) * dz2;
08307 
08308                 for(iy=1; iy<=ny; iy++) {
08309                         jy = iy - 1;
08310                         if(jy > ny2) {
08311                                 jy -= ny;
08312                         }
08313                         argy = argz + float(jy*jy) * dy2;
08314 
08315                         for(ix=1; ix<=nx; ix++) {
08316                                 jx = ix -1;
08317                                 argx = argy + float(jx*jx)*dx2;
08318 
08319                                 rf = sqrt(argx)*2.0f*nx2;
08320                                 ir = int(rf);
08321                                 df = rf - float(ir);
08322                                 f = table[ir] + df*(table[ir+1]-table[ir]);
08323 
08324                                 (*image)(ix-1,iy-1,iz-1) *= f;
08325                         }
08326                 }
08327         }
08328 
08329         image->update();
08330 }
08331 
08332 void MirrorProcessor::process_inplace(EMData *image)
08333 {
08334         if (!image) {
08335                 LOGWARN("NULL Image");
08336                 return;
08337         }
08338 
08339         string axis = (const char*)params["axis"];
08340 
08341         float* data = image->EMData::get_data();
08342 
08343         int nx = image->get_xsize();
08344         int ny = image->get_ysize();
08345         int nz = image->get_zsize();
08346         size_t nxy = nx*ny;
08347 
08348         int x_start = 1-nx%2;
08349         int y_start = 1-ny%2;
08350         int z_start = 1-nz%2;
08351 
08352         if (axis == "x" || axis == "X") {
08353                 for (int iz = 0; iz < nz; iz++)
08354                         for (int iy = 0; iy < ny; iy++) {
08355                                 int offset = nx*iy + nxy*iz;
08356                                 reverse(&data[offset+x_start],&data[offset+nx]);
08357                         }
08358         } else if (axis == "y" || axis == "Y") {
08359                 float *tmp = new float[nx];
08360                 int nhalf   = ny/2;
08361                 size_t beg     = 0;
08362                 for (int iz = 0; iz < nz; iz++) {
08363                         beg = iz*nxy;
08364                         for (int iy = y_start; iy < nhalf; iy++) {
08365                                 memcpy(tmp, &data[beg+iy*nx], nx*sizeof(float));
08366                                 memcpy(&data[beg+iy*nx], &data[beg+(ny-iy-1+y_start)*nx], nx*sizeof(float));
08367                                 memcpy(&data[beg+(ny-iy-1+y_start)*nx], tmp, nx*sizeof(float));
08368                         }
08369                 }
08370                 delete[] tmp;
08371         } else if (axis == "z" || axis == "Z") {
08372                 if(1-z_start) {
08373                         int nhalf = nz/2;
08374                         float *tmp = new float[nxy];
08375                         for(int iz = 0;iz<nhalf;iz++){
08376                                 memcpy(tmp,&data[iz*nxy],nxy*sizeof(float));
08377                                 memcpy(&data[iz*nxy],&data[(nz-iz-1)*nxy],nxy*sizeof(float));
08378                                 memcpy(&data[(nz-iz-1)*nxy],tmp,nxy*sizeof(float));
08379                         }
08380                         delete[] tmp;
08381                 } else {
08382                         float *tmp = new float[nx];
08383                         int nhalf   = nz/2;
08384                         size_t beg     = 0;
08385                         for (int iy = 0; iy < ny; iy++) {
08386                                 beg = iy*nx;
08387                                 for (int iz = z_start; iz < nhalf; iz++) {
08388                                         memcpy(tmp, &data[beg+ iz*nxy], nx*sizeof(float));
08389                                         memcpy(&data[beg+iz*nxy], &data[beg+(nz-iz-1+z_start)*nxy], nx*sizeof(float));
08390                                         memcpy(&data[beg+(nz-iz-1+z_start)*nxy], tmp, nx*sizeof(float));
08391                                 }
08392                         }
08393                         delete[] tmp;
08394                 }
08395         }
08396 
08397         image->update();
08398 }
08399 
08400 
08401 int EMAN::multi_processors(EMData * image, vector < string > processornames)
08402 {
08403         Assert(image != 0);
08404         Assert(processornames.size() > 0);
08405 
08406         for (size_t i = 0; i < processornames.size(); i++) {
08407                 image->process_inplace(processornames[i]);
08408         }
08409         return 0;
08410 }
08411 
08412 
08413 float* TransformProcessor::transform(const EMData* const image, const Transform& t) const {
08414 
08415         ENTERFUNC;
08416 
08417         Transform inv = t.inverse();
08418         int nx = image->get_xsize();
08419         int ny = image->get_ysize();
08420         int nz = image->get_zsize();
08421         int nxy = nx*ny;
08422 
08423         const float * const src_data = image->get_const_data();
08424         float *des_data = (float *) EMUtil::em_malloc(nx*ny*nz* sizeof(float));
08425 
08426         if (nz == 1) {
08427                 Vec2f offset(nx/2,ny/2);
08428                 for (int j = 0; j < ny; j++) {
08429                         for (int i = 0; i < nx; i++) {
08430                                 Vec2f coord(i-nx/2,j-ny/2);
08431                                 Vec2f soln = inv*coord;
08432                                 soln += offset;
08433 
08434                                 float x2 = soln[0];
08435                                 float y2 = soln[1];
08436 
08437                                 if (x2 < 0 || x2 >= nx || y2 < 0 || y2 >= ny ) {
08438                                         des_data[i + j * nx] = 0; // It may be tempting to set this value to the
08439                                         // mean but in fact this is not a good thing to do. Talk to S.Ludtke about it.
08440                                 }
08441                                 else {
08442                                         int ii = Util::fast_floor(x2);
08443                                         int jj = Util::fast_floor(y2);
08444                                         int k0 = ii + jj * nx;
08445                                         int k1 = k0 + 1;
08446                                         int k2 = k0 + nx;
08447                                         int k3 = k0 + nx + 1;
08448 
08449                                         if (ii == nx - 1) {
08450                                                 k1--;
08451                                                 k3--;
08452                                         }
08453                                         if (jj == ny - 1) {
08454                                                 k2 -= nx;
08455                                                 k3 -= nx;
08456                                         }
08457 
08458                                         float t = x2 - ii;
08459                                         float u = y2 - jj;
08460 
08461                                         des_data[i + j * nx] = Util::bilinear_interpolate(src_data[k0],src_data[k1], src_data[k2], src_data[k3],t,u);
08462                                 }
08463                         }
08464                 }
08465         }
08466         else {
08467                 size_t l=0, ii, k0, k1, k2, k3, k4, k5, k6, k7;
08468                 Vec3f offset(nx/2,ny/2,nz/2);
08469                 float x2, y2, z2, tuvx, tuvy, tuvz;
08470                 int ix, iy, iz;
08471                 for (int k = 0; k < nz; ++k) {
08472                         for (int j = 0; j < ny; ++j) {
08473                                 for (int i = 0; i < nx; ++i,++l) {
08474                                         Vec3f coord(i-nx/2,j-ny/2,k-nz/2);
08475                                         Vec3f soln = inv*coord;
08476                                         soln += offset;
08477 
08478                                         x2 = soln[0];
08479                                         y2 = soln[1];
08480                                         z2 = soln[2];
08481 
08482                                         if (x2 < 0 || y2 < 0 || z2 < 0 || x2 >= nx  || y2 >= ny  || z2>= nz ) {
08483                                                 des_data[l] = 0;
08484                                         }
08485                                         else {
08486                                                 ix = Util::fast_floor(x2);
08487                                                 iy = Util::fast_floor(y2);
08488                                                 iz = Util::fast_floor(z2);
08489                                                 tuvx = x2-ix;
08490                                                 tuvy = y2-iy;
08491                                                 tuvz = z2-iz;
08492                                                 ii = ix + iy * nx + iz * nxy;
08493 
08494                                                 k0 = ii;
08495                                                 k1 = k0 + 1;
08496                                                 k2 = k0 + nx;
08497                                                 k3 = k0 + nx+1;
08498                                                 k4 = k0 + nxy;
08499                                                 k5 = k1 + nxy;
08500                                                 k6 = k2 + nxy;
08501                                                 k7 = k3 + nxy;
08502 
08503                                                 if (ix == nx - 1) {
08504                                                         k1--;
08505                                                         k3--;
08506                                                         k5--;
08507                                                         k7--;
08508                                                 }
08509                                                 if (iy == ny - 1) {
08510                                                         k2 -= nx;
08511                                                         k3 -= nx;
08512                                                         k6 -= nx;
08513                                                         k7 -= nx;
08514                                                 }
08515                                                 if (iz == nz - 1) {
08516                                                         k4 -= nxy;
08517                                                         k5 -= nxy;
08518                                                         k6 -= nxy;
08519                                                         k7 -= nxy;
08520                                                 }
08521 
08522                                                 des_data[l] = Util::trilinear_interpolate(src_data[k0],
08523                                                                 src_data[k1], src_data[k2], src_data[k3], src_data[k4],
08524                                                                 src_data[k5], src_data[k6],     src_data[k7], tuvx, tuvy, tuvz);
08525                                         }
08526                                 }
08527                         }
08528                 }
08529         }
08530 
08531         EXITFUNC;
08532         return des_data;
08533 }
08534 
08535 void TransformProcessor::assert_valid_aspect(const EMData* const image) const {
08536         int ndim = image->get_ndim();
08537         if (ndim != 2 && ndim != 3) throw ImageDimensionException("Transforming an EMData only works if it's 2D or 3D");
08538 
08539         if (! params.has_key("transform") ) throw InvalidParameterException("You must specify a Transform in order to perform this operation");
08540 }
08541 
08542 //void TransformProcessor::update_emdata_attributes(EMData* const p, const Dict& attr_dict, const float& scale) const {
08543 //
08544 //      float inv_scale = 1.0f/scale;
08545 //
08546 //      p->scale_pixel(1.0f/scale);
08547 //
08548 //      // According to Baker the origin attributes remain unchanged
08559 //
08560 //      vector<string> scale_attrs;
08561 //      scale_attrs.push_back("apix_x");
08562 //      scale_attrs.push_back("apix_y");
08563 //      scale_attrs.push_back("apix_z");
08564 //
08565 //
08566 //      for(vector<string>::const_iterator it = scale_attrs.begin(); it != scale_attrs.end(); ++it) {
08567 //              if (attr_dict.has_key(*it)) {
08568 //                      p->set_attr(*it,(float) attr_dict[*it] * inv_scale);
08569 //              }
08570 //      }
08571 //
08572 //}
08573 
08574 EMData* TransformProcessor::process(const EMData* const image) {
08575         ENTERFUNC;
08576 
08577         assert_valid_aspect(image);
08578 
08579         Transform* t = params["transform"];
08580 
08581         EMData* p  = 0;
08582 #ifdef EMAN2_USING_CUDA
08583         if(EMData::usecuda == 1 && image->isrodataongpu()){     
08584                 //cout << "using CUDA xform" << endl;
08585                 p = new EMData(0,0,image->get_xsize(),image->get_ysize(),image->get_zsize(),image->get_attr_dict()); 
08586                 float * m = new float[12];
08587                 Transform inv = t->inverse();
08588                 inv.copy_matrix_into_array(m);
08589                 image->bindcudaarrayA(true);
08590                 p->runcuda(emdata_transform_cuda(m,image->get_xsize(),image->get_ysize(),image->get_zsize()));
08591                 image->unbindcudaarryA();
08592                 delete [] m;
08593                 p->update();
08594         }
08595 #endif
08596 
08597         if ( p == 0 ) {
08598                 float* des_data = transform(image,*t);
08599                 p = new EMData(des_data,image->get_xsize(),image->get_ysize(),image->get_zsize(),image->get_attr_dict());
08600         }
08601 
08602         //      all_translation += transform.get_trans();
08603 
08604         float scale = t->get_scale();
08605         if (scale != 1.0) {
08606                 p->scale_pixel(1.0f/scale);
08607 //              update_emdata_attributes(p,image->get_attr_dict(),scale);
08608         }
08609 
08610         if(t) {delete t; t=0;}
08611         EXITFUNC;
08612         return p;
08613 }
08614 
08615 void TransformProcessor::process_inplace(EMData* image) {
08616         ENTERFUNC;
08617 
08618         assert_valid_aspect(image);
08619 
08620         Transform* t = params["transform"];
08621 
08622         //      all_translation += transform.get_trans();
08623         bool use_cpu = true;
08624         
08625 #ifdef EMAN2_USING_CUDA
08626         if(EMData::usecuda == 1 && image->isrodataongpu()){
08627                 //cout << "CUDA xform inplace" << endl;
08628                 image->bindcudaarrayA(false);   
08629                 float * m = new float[12];
08630                 Transform inv = t->inverse();
08631                 inv.copy_matrix_into_array(m);  
08632                 image->runcuda(emdata_transform_cuda(m,image->get_xsize(),image->get_ysize(),image->get_zsize()));
08633                 image->unbindcudaarryA();
08634                 delete [] m;
08635                 use_cpu = false;
08636                 image->update();
08637         }
08638 #endif
08639         if ( use_cpu ) {
08640                 float* des_data = transform(image,*t);
08641                 image->set_data(des_data,image->get_xsize(),image->get_ysize(),image->get_zsize());
08642                 image->update();
08643         }
08644         float scale = t->get_scale();
08645         if (scale != 1.0f) {
08646                 image->scale_pixel(1.0f/scale);
08647 //              update_emdata_attributes(image,image->get_attr_dict(),scale);
08648         }
08649 
08650         if(t) {delete t; t=0;}
08651 
08652         EXITFUNC;
08653 }
08654 
08655 
08656 void IntTranslateProcessor::assert_valid_aspect(const vector<int>& translation, const EMData* const) const {
08657         if (translation.size() == 0 ) throw InvalidParameterException("You must specify the trans argument");
08658 }
08659 
08660 Region IntTranslateProcessor::get_clip_region(vector<int>& translation, const EMData* const image) const {
08661         unsigned int dim = static_cast<unsigned int> (image->get_ndim());
08662 
08663         if ( translation.size() != dim ) {
08664                 for(unsigned int i = translation.size(); i < dim; ++i ) translation.push_back(0);
08665         }
08666 
08667         Region clip_region;
08668         if (dim == 1) {
08669                 clip_region = Region(-translation[0],image->get_xsize());
08670         } else if ( dim == 2 ) {
08671                 clip_region = Region(-translation[0],-translation[1],image->get_xsize(),image->get_ysize());
08672         } else if ( dim == 3 ) {
08673                 clip_region = Region(-translation[0],-translation[1],-translation[2],image->get_xsize(),image->get_ysize(),image->get_zsize());
08674         } else throw ImageDimensionException("Only 1,2 and 3D images are supported");
08675 
08676         return clip_region;
08677 }
08678 
08679 void IntTranslateProcessor::process_inplace(EMData* image) {
08680 
08681         vector<int> translation = params.set_default("trans",vector<int>() );
08682 
08683 
08684         assert_valid_aspect(translation,image);
08685 
08686         Region clip_region = get_clip_region(translation,image);
08687 
08688         image->clip_inplace(clip_region,0);
08689         // clip_inplace does the update!
08690 }
08691 
08692 EMData* IntTranslateProcessor::process(const EMData* const image) {
08693 
08694         vector<int> translation = params.set_default("trans",vector<int>() );
08695 
08696         assert_valid_aspect(translation,image);
08697 
08698         Region clip_region = get_clip_region(translation,image);
08699 
08700         return image->get_clip(clip_region,0);
08701         // clip_inplace does the update!
08702 }
08703 
08704 
08705 void ScaleTransformProcessor::process_inplace(EMData* image) {
08706         int ndim = image->get_ndim();
08707         if (ndim != 2 && ndim != 3) throw UnexpectedBehaviorException("The Scale Transform processors only works for 2D and 3D images");
08708 
08709         if ( image->get_xsize() != image->get_ysize()) {
08710                 throw ImageDimensionException("x size and y size of image do not match. This processor only works for uniformly sized data");
08711         }
08712         if ( ndim == 3 ) {
08713                 if ( image->get_xsize() != image->get_zsize()) {
08714                 throw ImageDimensionException("x size and z size of image do not match. This processor only works for uniformly sized data");
08715                 }
08716         }
08717 
08718         float scale = params.set_default("scale",0.0f);
08719         if (scale <= 0.0f) throw InvalidParameterException("The scale parameter must be greater than 0");
08720 
08721         int clip = 0;
08722 
08723         if(params.has_key("clip"))
08724         {
08725                 clip = params["clip"];
08726                 if (clip < 0) throw InvalidParameterException("The clip parameter must be greater than 0"); // If it's zero it's not used
08727         }
08728         else
08729         {
08730                 clip = (int)(scale*image->get_xsize());
08731         }
08732 
08733         Region r;
08734         if (ndim == 3) {
08735                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2,clip, clip,clip);
08736         } else { // ndim == 2 guaranteed by check at beginning of function
08737                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, clip, clip);
08738         }
08739 
08740         if (scale > 1) {
08741                 if ( clip != 0) {
08742                         image->clip_inplace(r);
08743                 }
08744                 Transform t;
08745                 t.set_scale(scale);
08746                 image->process_inplace("xform",Dict("transform",&t));
08747         } else if (scale < 1) {
08748                 Transform t;
08749                 t.set_scale(scale);
08750                 image->process_inplace("xform",Dict("transform",&t));
08751                 if ( clip != 0) {
08752                         image->clip_inplace(r);
08753                 }
08754         } else {
08755                 if ( clip != 0) {
08756                         image->clip_inplace(r);
08757                 }
08758         }
08759 }
08760 
08761 EMData* ScaleTransformProcessor::process(const EMData* const image) {
08762         int ndim = image->get_ndim();
08763         if (ndim != 2 && ndim != 3) throw UnexpectedBehaviorException("The Scale Transform processors only works for 2D and 3D images");
08764 
08765         if ( image->get_xsize() != image->get_ysize()) {
08766                 throw ImageDimensionException("x size and y size of image do not match. This processor only works for uniformly sized data");
08767         }
08768         if ( ndim == 3 ) {
08769                 if ( image->get_xsize() != image->get_zsize()) {
08770                 throw ImageDimensionException("x size and z size of image do not match. This processor only works for uniformly sized data");
08771                 }
08772         }
08773 
08774         float scale = params.set_default("scale",0.0f);
08775         if (scale <= 0.0f) throw InvalidParameterException("The scale parameter must be greater than 0");
08776 
08777         int clip = 0;
08778 
08779         if(params.has_key("clip"))
08780         {
08781                 clip = params["clip"];
08782                 if (clip < 0) throw InvalidParameterException("The clip parameter must be greater than 0"); // If it's zero it's not used
08783         }
08784         else
08785         {
08786                 clip = (int)(scale*image->get_xsize());
08787         }
08788 
08789         Region r;
08790         if (ndim == 3) {
08791                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2,clip, clip,clip);
08792         } else { // ndim == 2 guaranteed by check at beginning of function
08793                  r = Region( (image->get_xsize()-clip)/2, (image->get_xsize()-clip)/2, clip, clip);
08794         }
08795 
08796         EMData* ret = 0;
08797         if (scale > 1) {
08798                 if ( clip != 0) {
08799                         ret = image->get_clip(r);
08800                 }
08801                 Transform t;
08802                 t.set_scale(scale);
08803                 if (ret != 0) {
08804                         ret->process_inplace("xform",Dict("transform",&t));
08805                 } else {
08806                         ret = image->process("xform",Dict("transform",&t));
08807                 }
08808         } else if (scale < 1) {
08809                 Transform t;
08810                 t.set_scale(scale);
08811                 ret = image->process("xform",Dict("transform",&t));
08812                 if ( clip != 0) {
08813                         ret->clip_inplace(r);
08814                 }
08815         } else {
08816                 if ( clip != 0) {
08817                         ret = image->get_clip(r);
08818                 } else {
08819                         ret = image->copy();
08820                 }
08821         }
08822         return ret;
08823 
08824 }
08825 
08826 void Rotate180Processor::process_inplace(EMData* image) {
08827         ENTERFUNC;
08828 
08829 
08830         if (image->get_ndim() != 2) {
08831                 throw ImageDimensionException("2D only");
08832         }
08833 
08834 #ifdef EMAN2_USING_CUDA
08835         if (EMData::usecuda == 1 && image->getcudarwdata()) {
08836                 //cout << "CUDA rotate 180" << endl;
08837                 emdata_rotate_180(image->getcudarwdata(), image->get_xsize(), image->get_ysize());
08838                 EXITFUNC;
08839                 return;
08840         }
08841 #endif
08842 
08843         float *d = image->get_data();
08844         int nx = image->get_xsize();
08845         int ny = image->get_ysize();
08846 
08847         // x and y offsets are used to handle even vs odd cases
08848         int x_offset = 0;
08849         if (nx % 2 == 1) x_offset=1;
08850         int y_offset = 0;
08851         if (ny % 2 == 1) y_offset=1;
08852 
08853         bool stop = false;
08854         for (int x = 1; x <= (nx/2+x_offset); x++) {
08855                 int y = 0;
08856                 for (y = 1; y < (ny+y_offset); y++) {
08857                         if (x == (nx / 2+x_offset) && y == (ny / 2+y_offset)) {
08858                                 stop = true;
08859                                 break;
08860                         }
08861                         int i = (x-x_offset) + (y-y_offset) * nx;
08862                         int k = nx - x + (ny - y) * nx;
08863 
08864                         float t = d[i];
08865                         d[i] = d[k];
08866                         d[k] = t;
08867                 }
08868                 if (stop) break;
08869         }
08870 
08871         /* Here we guard against irregularites that occur at the boundaries
08872          * of even dimensioned images. The basic policy is to replace the pixel
08873          * in row 0 and/or column 0 with those in row 1 and/or column 1, respectively.
08874          * The pixel at 0,0 is replaced with the pixel at 1,1 if both image dimensions
08875          * are even. FIXME - it may be better to use an average at the corner, in
08876          * this latter case, using pixels (1,1), (0,1) and (1,0). I am not sure. (dsawoolford)
08877         */
08878         if (x_offset == 0) {
08879                 for (int y = 0; y < ny; y++) {
08880                         image->set_value_at_fast(0,y,image->get_value_at(1,y));
08881                 }
08882         }
08883 
08884         if (y_offset == 0) {
08885                 for (int x = 0; x < nx; x++) {
08886                         image->set_value_at_fast(x,0,image->get_value_at(x,1));
08887                 }
08888         }
08889 
08890         if (y_offset == 0 && x_offset == 0) {
08891                 image->set_value_at_fast(0,0,image->get_value_at(1,1));
08892         }
08893 
08894         image->update();
08895         EXITFUNC;
08896 }
08897 
08898 
08899 void ClampingProcessor::process_inplace( EMData* image )
08900 {
08901 
08902         if ( image->is_complex() ) throw ImageFormatException("Error: clamping processor does not work on complex images");
08903 
08904         float min = params.set_default("minval",default_min);
08905         float max = params.set_default("maxval",default_max);
08906         bool tomean = params.set_default("tomean",false);
08907         float new_min_vals = min;
08908         float new_max_vals = max;
08909         if (tomean){
08910 
08911                 new_min_vals = image->get_attr("mean");
08912                 new_max_vals = image->get_attr("mean");
08913         }
08914 
08915         // Okay, throwing such an error is probably overkill - but atleast the user will get a loud message
08916         // saying what went wrong.
08917         if ( max < min ) throw InvalidParameterException("Error: minval was greater than maxval, aborting");
08918 
08919         size_t size = image->get_size();
08920         for(size_t i = 0; i < size; ++i )
08921         {
08922                 float * data = &image->get_data()[i];
08923                 if ( *data < min ) *data = new_min_vals;
08924                 else if ( *data > max ) *data = new_max_vals;
08925         }
08926         image->update();
08927 }
08928 
08929 void TestTomoImage::insert_rectangle( EMData* image, const Region& region, const float& value, const Transform& t3d )
08930 {
08931         int startx = (int)region.origin[0] - (int)region.size[0]/2;
08932         int starty = (int)region.origin[1] - (int)region.size[1]/2;
08933         int startz = (int)region.origin[2] - (int)region.size[2]/2;
08934 
08935         int endx  = (int)region.origin[0] + (int)region.size[0]/2;
08936         int endy  = (int)region.origin[1] + (int)region.size[1]/2;
08937         int endz  = (int)region.origin[2] + (int)region.size[2]/2;
08938 
08939         if ( ! t3d.is_identity() ) {
08940                 float xt, yt, zt;
08941                 for ( float z = (float)startz; z < (float)endz; z += 0.25f ) {
08942                         for ( float y = (float)starty; y < (float)endy; y += 0.25f ) {
08943                                 for ( float x = (float)startx; x < (float)endx; x += 0.25f ) {
08944                                         xt = (float) x - region.origin[0];
08945                                         yt = (float) y - region.origin[1];
08946                                         zt = (float) z - region.origin[2];
08947                                         Vec3f v((float)xt,(float)yt,(float)zt);
08948                                         v = t3d*v;
08949                                         image->set_value_at((int)(v[0]+region.origin[0]),(int)(v[1]+region.origin[1]),(int)(v[2]+region.origin[2]), value);
08950                                 }
08951                         }
08952                 }
08953         } else {
08954                 for ( int z = startz; z < endz; ++z ) {
08955                         for ( int y = starty; y < endy; ++y ) {
08956                                 for ( int x = startx; x < endx; ++x ) {
08957                                         image->set_value_at(x,y,z, value);
08958                                 }
08959                         }
08960                 }
08961         }
08962 }
08963 
08964 void TestTomoImage::process_inplace( EMData* image )
08965 {
08966         //float nx = 240;
08967         //float ny = 240;
08968         //float nz = 60;
08969 
08970         //image->set_size((int)nx,(int)ny,(int)nz);
08971         float nx = (float) image->get_xsize();
08972         float ny = (float) image->get_ysize();
08973         float nz = (float) image->get_zsize();
08974 
08975         // This increment is used to simplified positioning
08976         // It's an incremental factor that matches the grid size of the paper
08977         // that I drew this design on before implementing it in code
08978         float inc = 1.0f/22.0f;
08979         float xinc = inc;
08980         float yinc = inc;
08981         float zinc = inc;
08982 
08983         Dict d;
08984         d["a"] = (float) .4*nx+3;
08985         d["b"] = (float) .4*ny+3;
08986         d["c"] = (float) .4*nz+3;
08987         d["fill"] = 0.2;
08988         image->process_inplace("testimage.ellipsoid",d);
08989 
08990         d["a"] = (float) .4*nx;
08991         d["b"] = (float) .4*ny;
08992         d["c"] = (float) .4*nz;
08993         d["fill"] = 0.1;
08994         image->process_inplace("testimage.ellipsoid",d);
08995 
08996         // Center x, center z, bottom y ellipsoids that grow progessively smaller
08997         {
08998                 Transform t;
08999                 t.set_trans(0.,ny*4.0f*yinc-ny/2,0);
09000                 Dict d;
09001                 d["transform"] = &t;
09002                 d["a"] = (float) 2.*xinc*nx;
09003                 d["b"] = (float)0.5*yinc*ny;
09004                 d["c"] = (float) 1.*zinc*nz;
09005                 d["fill"] = 0.3;
09006                 image->process_inplace("testimage.ellipsoid",d);
09007         }
09008 
09009         {
09010                 Transform t;
09011                 t.set_trans(0.,ny*5.5f*yinc-ny/2,0);
09012                 Dict d;
09013                 d["transform"] = &t;
09014                 d["a"] = (float) 1.5*xinc*nx;
09015                 d["b"] = (float)0.5*yinc*ny;
09016                 d["c"] = (float) 1.*zinc*nz;
09017                 d["fill"] = 0.0;
09018                 image->process_inplace("testimage.ellipsoid",d);
09019         }
09020         {
09021                 Transform t;
09022                 t.set_trans(0.,ny*7*yinc-ny/2,0);
09023                 Dict d;
09024                 d["transform"] = &t;
09025                 d["a"] = (float) 1.*xinc*nx;
09026                 d["b"] = (float)0.5*yinc*ny;
09027                 d["c"] = (float) 1.*zinc*nz;
09028                 d["fill"] = 0.3;
09029                 image->process_inplace("testimage.ellipsoid",d);
09030         }
09031 
09032 
09033         {
09034                 Transform t;
09035                 t.set_trans(0.,ny*8.5f*yinc-ny/2,0);
09036                 Dict d;
09037                 d["transform"] = &t;
09038                 d["a"] = (float) .75*xinc*nx;
09039                 d["b"] = (float)0.5*yinc*ny;
09040                 d["c"] = (float) 1.*zinc*nz;
09041                 d["fill"] = 0.0;
09042                 image->process_inplace("testimage.ellipsoid",d);
09043         }
09044 
09045         // Center x, center z, bottom y ellipsoids that grow progessively smaller
09046         {
09047                 Transform t;
09048                 t.set_trans(0.,ny*18*yinc-ny/2,0);
09049                 Dict d;
09050                 d["transform"] = &t;
09051                 d["a"] = (float) 2*xinc*nx;
09052                 d["b"] = (float)0.5*yinc*ny;
09053                 d["c"] = (float) 1.*zinc*nz;
09054                 d["fill"] = 0.3;
09055                 image->process_inplace("testimage.ellipsoid",d);
09056         }
09057 
09058         {
09059                 Transform t;
09060                 t.set_trans(0.,ny*16.5f*yinc-ny/2,0);
09061                 Dict d;
09062                 d["transform"] = &t;
09063                 d["a"] = (float) 1.5*xinc*nx;
09064                 d["b"] = (float)0.5*yinc*ny;
09065                 d["c"] = (float) 1.*zinc*nz;
09066                 d["fill"] = 0.3;
09067                 image->process_inplace("testimage.ellipsoid",d);
09068         }
09069 
09070         {
09071                 Transform t;
09072                 t.set_trans(0.,ny*15*yinc-ny/2,0);
09073                 Dict d;
09074                 d["transform"] = &t;
09075                 d["a"] = (float) 1*xinc*nx;
09076                 d["b"] = (float)0.5*yinc*ny;
09077                 d["c"] = (float) 1.*zinc*nz;
09078                 d["fill"] = 0.3f;
09079                 image->process_inplace("testimage.ellipsoid",d);
09080         }
09081 
09082         {
09083                 Transform t;
09084                 t.set_trans(0.,ny*13.5f*yinc-ny/2,0);
09085                 Dict d;
09086                 d["transform"] = &t;
09087                 d["a"] = (float).75*xinc*nx;
09088                 d["b"] = (float)0.5*yinc*ny;
09089                 d["c"] = (float) 1.*zinc*nz;
09090                 d["fill"] = 0.3;
09091                 image->process_inplace("testimage.ellipsoid",d);
09092         }
09093 
09094         // Left ellipsoids from the bottom up
09095         {
09096 
09097                 Transform t;
09098                 t.set_trans(nx*6*xinc-nx/2,ny*5*yinc-ny/2,0);
09099                 Dict d;
09100                 d["transform"] = &t;
09101                 d["a"] = (float)1*xinc*nx;
09102                 d["b"] = (float).75*yinc*ny;
09103                 d["c"] = (float) .75*zinc*nz;
09104                 d["fill"] = 0.25;
09105                 image->process_inplace("testimage.ellipsoid",d);
09106         }
09107 
09108         {
09109                 Transform t;
09110                 t.set_trans(nx*6*xinc-nx/2,ny*7*yinc-ny/2,0);
09111                 Dict d;
09112                 d["transform"] = &t;
09113                 d["a"] = (float)1.5*xinc*nx;
09114                 d["b"] = (float).75*yinc*ny;
09115                 d["c"] = (float) .75*zinc*nz;
09116                 d["fill"] = 0.25;
09117                 image->process_inplace("testimage.ellipsoid",d);
09118         }
09119 
09120         {
09121                 Transform t;
09122                 t.set_trans(nx*6*xinc-nx/2,ny*9*yinc-ny/2,0);
09123                 Dict d;
09124                 d["transform"] = &t;
09125                 d["a"] = (float)2*xinc*nx;
09126                 d["b"] = (float).75*yinc*ny;
09127                 d["c"] = (float) .75*zinc*nz;
09128                 d["fill"] = 0.25;
09129                 image->process_inplace("testimage.ellipsoid",d);
09130         }
09131 
09132         {
09133                 Transform t;
09134                 t.set_trans(nx*6*xinc-nx/2,ny*11*yinc-ny/2,0);
09135                 Dict d;
09136                 d["transform"] = &t;
09137                 d["a"] = (float)2.5*xinc*nx;
09138                 d["b"] = (float).75*yinc*ny;
09139                 d["c"] = (float) 1*zinc*nz;
09140                 d["fill"] = 0.25;
09141                 image->process_inplace("testimage.ellipsoid",d);
09142         }
09143 
09144         {
09145                 Transform t;
09146                 t.set_trans(nx*6*xinc-nx/2,ny*13*yinc-ny/2,0);
09147                 Dict d;
09148                 d["transform"] = &t;
09149                 d["a"] = (float) 3*xinc*nx;
09150                 d["b"] = (float).75*yinc*ny;
09151                 d["c"] = (float) 1*zinc*nz;
09152                 d["fill"] = 0.25;
09153                 image->process_inplace("testimage.ellipsoid",d);
09154         }
09155 
09156         // Right rectangle from the top down
09157         {
09158                 Region region(nx*15.*inc,ny*17.*inc,nz/2.,1.*inc*nx,1.5*inc*ny,1.5*inc*nz);
09159                 insert_rectangle(image, region, 0.25);
09160         }
09161         {
09162                 Region region(nx*15.*inc,ny*15.*inc,nz/2.,1.5*inc*nx,1.5*inc*ny,1.5*inc*nz);
09163                 insert_rectangle(image, region, 0.25);
09164         }
09165         {
09166                 Region region(nx*15.*inc,ny*13.*inc,nz/2.,2.*inc*nx,1.5*inc*ny,1.5*inc*nz);
09167                 insert_rectangle(image, region, 0.25);
09168         }
09169         {
09170                 Region region(nx*15.*inc,ny*11.*inc,nz/2.,2.5*inc*nx,1.5*inc*ny,1.5*inc*nz);
09171                 insert_rectangle(image, region, 0.25);
09172         }
09173         {
09174                 Region region(nx*15.*inc,ny*9.*inc,nz/2.,3.*inc*nx,1.5*inc*ny,1.5*inc*nz);
09175                 insert_rectangle(image, region, 0.25);
09176         }
09177 
09178         // Center rotated rectangle
09179         {
09180                 Region region(nx/2.,ny/2.,nz/2.,2.*inc*nx,2.5*inc*ny,1.*inc*nz);
09181                 Transform t3d(Dict("type","eman","az",(float)-25.0));
09182                 insert_rectangle(image, region, 0.4f, t3d);
09183         }
09184 
09185         // Rotated ellipsoids
09186         {
09187                 Transform t;
09188                 t.set_trans(nx*6.8f*xinc-nx/2,ny*16*yinc-ny/2,0);
09189                 Dict rot;
09190                 rot["type"] = "eman";
09191                 rot["az"] = 43.0f;
09192                 t.set_rotation(rot);
09193                 Dict d;
09194                 d["transform"] = &t;
09195                 d["a"] = (float) 1.5*xinc*nx;
09196                 d["b"] = (float) .5*yinc*ny;
09197                 d["c"] = (float) .5*zinc*nz;
09198                 d["fill"] = 0.2;
09199                 image->process_inplace("testimage.ellipsoid",d);
09200         }
09201         {
09202                 Transform t;
09203                 t.set_trans(nx*7.2f*xinc-nx/2,ny*16*yinc-ny/2,0);
09204                 Dict rot;
09205                 rot["type"] = "eman";
09206                 rot["az"] = 135.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.3;
09214                 image->process_inplace("testimage.ellipsoid",d);
09215         }
09216 
09217         // Dense small ellipsoids
09218         {
09219                 Transform t;
09220                 t.set_trans(nx*3.5f*xinc-nx/2,ny*8*yinc-ny/2,0);
09221                 Dict d;
09222                 d["transform"] = &t;
09223                 d["a"] = (float) .5*xinc*nx;
09224                 d["b"] = (float) .5*yinc*ny;
09225                 d["c"] = (float) .5*zinc*nz;
09226                 d["fill"] = 2.05;
09227                 image->process_inplace("testimage.ellipsoid",d);
09228 
09229                 t.set_trans(nx*8*xinc-nx/2,ny*18*yinc-ny/2,0);
09230                 image->process_inplace("testimage.ellipsoid",d);
09231 
09232                 t.set_trans(nx*14*xinc-nx/2,ny*18.2f*yinc-ny/2,0);
09233                 image->process_inplace("testimage.ellipsoid",d);
09234 
09235                 t.set_trans(nx*18*xinc-nx/2,ny*14*yinc-ny/2,0);
09236                 image->process_inplace("testimage.ellipsoid",d);
09237 
09238                 t.set_trans(nx*17*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
09239                 image->process_inplace("testimage.ellipsoid",d);
09240         }
09241 
09242 
09243         // Dense small rectangles
09244         {
09245                 Region region(nx*18.*inc,ny*11.5*inc,nz/2.,1.*inc*nx,1.*inc*ny,1.*inc*nz);
09246                 Transform t3d(Dict("type","eman","az",(float)45.0));
09247                 insert_rectangle(image, region, 1.45f, t3d);
09248         }
09249         {
09250                 Region region(nx*3.*inc,ny*10.5*inc,nz/2.,1.*inc*nx,1.*inc*ny,1.*inc*nz);
09251                 Transform t3d(Dict("type","eman","az",(float)45.0));
09252                 insert_rectangle(image, region, 1.45f, t3d);
09253         }
09254 
09255         // Insert small cluster of spheres
09256         {
09257                 Transform t;
09258                 t.set_trans(nx*14*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
09259                 Dict d;
09260                 d["transform"] = &t;
09261                 d["a"] = (float) .5*xinc*nx;
09262                 d["b"] = (float) .5*yinc*ny;
09263                 d["c"] = (float) .5*zinc*nz;
09264                 d["fill"] = .35;
09265                 image->process_inplace("testimage.ellipsoid",d);
09266         }
09267         {
09268                 Transform t;
09269                 t.set_trans(nx*15*xinc-nx/2,ny*7.5f*yinc-ny/2,0);
09270                 Dict d;
09271                 d["transform"] = &t;
09272                 d["a"] = (float) .25*xinc*nx;
09273                 d["b"] = (float) .25*yinc*ny;
09274                 d["c"] = (float) .25*zinc*nz;
09275                 d["fill"] = .35;
09276                 image->process_inplace("testimage.ellipsoid",d);
09277 
09278                 t.set_trans(nx*13.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
09279                 image->process_inplace("testimage.ellipsoid",d);
09280 
09281                 t.set_trans(nx*14.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
09282                 image->process_inplace("testimage.ellipsoid",d);
09283 
09284                 t.set_trans(nx*15.5f*xinc-nx/2,ny*6.5f*yinc-ny/2,0);
09285                 image->process_inplace("testimage.ellipsoid",d);
09286 
09287                 t.set_trans(nx*14*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09288                 image->process_inplace("testimage.ellipsoid",d);
09289 
09290                 t.set_trans(nx*14*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09291                 image->process_inplace("testimage.ellipsoid",d);
09292 
09293                 t.set_trans(nx*15*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09294                 image->process_inplace("testimage.ellipsoid",d);
09295 
09296                 t.set_trans(nx*16*xinc-nx/2,ny*5.5f*yinc-ny/2,0);
09297                 image->process_inplace("testimage.ellipsoid",d);
09298 
09299                 t.set_trans(nx*14.5f*xinc-nx/2,ny*4.5f*yinc-ny/2,0);
09300                 image->process_inplace("testimage.ellipsoid",d);
09301 
09302                 t.set_trans(nx*15.5f*xinc-nx/2,ny*4.5f*yinc-ny/2,0);
09303                 image->process_inplace("testimage.ellipsoid",d);
09304         }
09305         // Insert feducials around the outside of the "cell"
09306 //      for ( float i = 0.; i < 3.; i += 1. ) {
09307 //              for ( float j = 0.; j < 3.; j += 1. ) {
09308 //                      Region region(nx*2.+i*inc,ny*2.+j*inc,nz/2.,0.05*inc*nx,0.05*inc*ny,0.05*inc*nz);
09309 //                      insert_solid_ellipse(image, region, 2.0);
09310 //              }
09311 //      }
09312 
09313 }
09314 
09315 void NSigmaClampingProcessor::process_inplace(EMData *image)
09316 {
09317         float nsigma = params.set_default("nsigma",default_sigma);
09318         float sigma = image->get_attr("sigma");
09319         float mean = image->get_attr("mean");
09320         params.set_default("minval",mean - nsigma*sigma);
09321         params.set_default("maxval",mean + nsigma*sigma);
09322 
09323         ClampingProcessor::process_inplace(image);
09324 }
09325 
09326 void HistogramBin::process_inplace(EMData *image)
09327 {
09328         float min = image->get_attr("minimum");
09329         float max = image->get_attr("maximum");
09330         float nbins = (float)params.set_default("nbins",default_bins);
09331         bool debug = params.set_default("debug",false);
09332 
09333         vector<int> debugscores;
09334         if ( debug ) {
09335                 debugscores = vector<int>((int)nbins, 0);
09336         }
09337 
09338         if ( nbins < 0 ) throw InvalidParameterException("nbins must be greater than 0");
09339 
09340         float bin_width = (max-min)/nbins;
09341         float bin_val_offset = bin_width/2.0f;
09342 
09343         size_t size = image->get_size();
09344         float* dat = image->get_data();
09345 
09346         for(size_t i = 0; i < size; ++i ) {
09347                 float val = dat[i];
09348                 val -= min;
09349                 int bin = (int) (val/bin_width);
09350 
09351                 // This makes the last interval [] and not [)
09352                 if (bin == nbins) bin -= 1;
09353 
09354                 dat[i] = min + bin*bin_width + bin_val_offset;
09355                 if ( debug ) {
09356                         debugscores[bin]++;
09357                 }
09358         }
09359 
09360         if ( debug ) {
09361                 int i = 0;
09362                 for( vector<int>::const_iterator it = debugscores.begin(); it != debugscores.end(); ++it, ++i)
09363                         cout << "Bin " << i << " has " << *it << " pixels in it" << endl;
09364         }
09365 
09366 }
09367 void ConvolutionProcessor::process_inplace(EMData* image)
09368 {
09369         //bool complexflag = false;
09370         EMData* null = 0;
09371         EMData* with = params.set_default("with", null);
09372         if ( with == NULL ) throw InvalidParameterException("Error - the image required for the convolution is null");
09373 
09374         EMData* newimage = fourierproduct(image, with, CIRCULANT, CONVOLUTION, false);
09375 
09376         float* orig = image->get_data();
09377         float* work = newimage->get_data();
09378         int nx  = image->get_xsize();
09379         int ny  = image->get_ysize();
09380         int nz  = image->get_zsize();
09381         memcpy(orig,work,nx*ny*nz*sizeof(float));
09382         image->update();
09383 
09384         delete newimage;
09385 }
09386 
09387 void XGradientProcessor::process_inplace( EMData* image )
09388 {
09389         if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
09390 
09391         EMData* e = new EMData();
09392         int nx = image->get_xsize();
09393         int ny = image->get_ysize();
09394         int nz = image->get_zsize();
09395 
09396         if ( nz == 1 && ny == 1 ) {
09397                 if ( nx < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09398 
09399                 e->set_size(3,1,1);
09400                 e->set_value_at(0,-1);
09401                 e->set_value_at(2, 1);
09402 
09403                 Region r = Region(-nx/2+1,nx);
09404                 e->clip_inplace(r);
09405         } else if ( nz == 1 ) {
09406                 if ( nx < 3 || ny < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09407                 e->set_size(3,3,1);
09408                 e->set_value_at(0,0,-1);
09409                 e->set_value_at(0,1,-2);
09410                 e->set_value_at(0,2,-1);
09411 
09412                 e->set_value_at(2,0,1);
09413                 e->set_value_at(2,1,2);
09414                 e->set_value_at(2,2,1);
09415                 Region r = Region(-nx/2+1,-ny/2+1,nx,ny);
09416                 e->clip_inplace(r);
09417         } else {
09418                 if ( nx < 3 || ny < 3 || nz < 3) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09419                 e->set_size(3,3,3);
09420                 e->set_value_at(0,0,0,-1);
09421                 e->set_value_at(0,1,0,-1);
09422                 e->set_value_at(0,2,0,-1);
09423                 e->set_value_at(0,0,1,-1);
09424                 e->set_value_at(0,1,1,-8);
09425                 e->set_value_at(0,2,1,-1);
09426                 e->set_value_at(0,0,2,-1);
09427                 e->set_value_at(0,1,2,-1);
09428                 e->set_value_at(0,2,2,-1);
09429 
09430                 e->set_value_at(2,0,0,1);
09431                 e->set_value_at(2,1,0,1);
09432                 e->set_value_at(2,2,0,1);
09433                 e->set_value_at(2,0,1,1);
09434                 e->set_value_at(2,1,1,8);
09435                 e->set_value_at(2,2,1,1);
09436                 e->set_value_at(2,0,2,1);
09437                 e->set_value_at(2,1,2,1);
09438                 e->set_value_at(2,2,2,1);
09439 
09440                 Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
09441                 e->clip_inplace(r);
09442         }
09443 
09444         Dict conv_parms;
09445         conv_parms["with"] = e;
09446         image->process_inplace("math.convolution", conv_parms);
09447         image->process_inplace("xform.phaseorigin.tocenter");
09448 
09449         delete e;
09450 }
09451 
09452 
09453 void TomoTiltAngleWeightProcessor::process_inplace( EMData* image )
09454 {
09455         bool fim = params.set_default("angle_fim", false);
09456         float alt;
09457         if ( fim ) {
09458                 alt = image->get_attr("euler_alt");
09459         }
09460         else alt = params.set_default("angle", 0.0f);
09461 
09462         float cosine = cos(alt*M_PI/180.0f);
09463         float mult_fac =  1.0f/(cosine);
09464         image->mult( mult_fac );
09465 }
09466 
09467 void TomoTiltEdgeMaskProcessor::process_inplace( EMData* image )
09468 {
09469         bool biedgemean = params.set_default("biedgemean", false);
09470         bool edgemean = params.set_default("edgemean", false);
09471         // You can only do one of these - so if someone specifies them both the code complains loudly
09472         if (biedgemean && edgemean) throw InvalidParameterException("The edgemean and biedgemean options are mutually exclusive");
09473 
09474         bool fim = params.set_default("angle_fim", false);
09475         float alt;
09476         if ( fim ) {
09477                 Transform* t = (Transform*)image->get_attr("xform.projection");
09478                 Dict d = t->get_params("eman");
09479                 alt = (float) d["alt"];
09480                 if(t) {delete t; t=0;}
09481         }
09482         else alt = params.set_default("angle", 0.0f);
09483 
09484 
09485         float cosine = cos(alt*M_PI/180.0f);
09486 
09487         // Zero the edges
09488         int nx = image->get_xsize();
09489         int ny = image->get_ysize();
09490         int x_clip = static_cast<int>( (float) nx * ( 1.0 - cosine ) / 2.0);
09491 
09492         float x1_edge_mean = 0.0;
09493         float x2_edge_mean = 0.0;
09494 
09495         if ( biedgemean )
09496         {
09497                 float edge_mean = 0.0;
09498 
09499                 // Accrue the pixel densities on the side strips
09500                 for ( int i = 0; i < ny; ++i ) {
09501                         edge_mean += image->get_value_at(x_clip, i );
09502                         edge_mean += image->get_value_at(nx - x_clip-1, i );
09503                 }
09504                 // Now make it so the mean is stored
09505                 edge_mean /= 2*ny;
09506 
09507                 // Now shift pixel values accordingly
09508                 for ( int i = 0; i < ny; ++i ) {
09509                         for ( int j = nx-1; j >= nx - x_clip; --j) {
09510                                 image->set_value_at(j,i,edge_mean);
09511                         }
09512                         for ( int j = 0; j < x_clip; ++j) {
09513                                 image->set_value_at(j,i,edge_mean);
09514                         }
09515                 }
09516                 x1_edge_mean = edge_mean;
09517                 x2_edge_mean = edge_mean;
09518         }
09519         else if (edgemean)
09520         {
09521                 for ( int i = 0; i < ny; ++i ) {
09522                         x1_edge_mean += image->get_value_at(x_clip, i );
09523                         x2_edge_mean += image->get_value_at(nx - x_clip-1, i );
09524                 }
09525                 x1_edge_mean /= ny;
09526                 x2_edge_mean /= ny;
09527 
09528                 for ( int i = 0; i < ny; ++i ) {
09529                         for ( int j = 0; j < x_clip; ++j) {
09530                                 image->set_value_at(j,i,x1_edge_mean);
09531                         }
09532                         for ( int j = nx-1; j >= nx - x_clip; --j) {
09533                                 image->set_value_at(j,i,x2_edge_mean);
09534                         }
09535                 }
09536         }
09537         else
09538         {
09539                 // The edges are just zeroed -
09540                 Dict zero_dict;
09541                 zero_dict["x0"] = x_clip;
09542                 zero_dict["x1"] = x_clip;
09543                 zero_dict["y0"] = 0;
09544                 zero_dict["y1"] = 0;
09545                 image->process_inplace( "mask.zeroedge2d", zero_dict );
09546         }
09547 
09548         int gauss_rad = params.set_default("gauss_falloff", 0);
09549         if ( gauss_rad != 0)
09550         {
09551                 // If the gaussian falloff distance is greater than x_clip, it will technically
09552                 // go beyond the image boundaries. Thus we clamp gauss_rad so this cannot happen.
09553                 // Therefore, there is potential here for (benevolent) unexpected behavior.
09554                 if ( gauss_rad > x_clip ) gauss_rad = x_clip;
09555 
09556                 float gauss_sigma = params.set_default("gauss_sigma", 3.0f);
09557                 if ( gauss_sigma < 0 ) throw InvalidParameterException("Error - you must specify a positive, non-zero gauss_sigma");
09558                 float sigma = (float) gauss_rad/gauss_sigma;
09559 
09560                 GaussianFunctoid gf(sigma);
09561 
09562                 for ( int i = 0; i < ny; ++i ) {
09563 
09564                         float left_value = image->get_value_at(x_clip, i );
09565                         float scale1 = left_value-x1_edge_mean;
09566 
09567                         float right_value = image->get_value_at(nx - x_clip - 1, i );
09568                         float scale2 = right_value-x2_edge_mean;
09569 
09570                         for ( int j = 1; j < gauss_rad; ++j )
09571                         {
09572                                 image->set_value_at(x_clip-j, i, scale1*gf((float)j)+x1_edge_mean );
09573                                 image->set_value_at(nx - x_clip + j-1, i, scale2*gf((float)j)+x2_edge_mean);
09574                         }
09575                 }
09576         }
09577 
09578         image->update();
09579 }
09580 
09581 void YGradientProcessor::process_inplace( EMData* image )
09582 {
09583         if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
09584 
09585         EMData* e = new EMData();
09586         int nx = image->get_xsize();
09587         int ny = image->get_ysize();
09588         int nz = image->get_zsize();
09589 
09590         if ( nz == 1 && ny == 1 ) {
09591                 throw ImageDimensionException("Error - cannot detect Y edges for an image that that is 1D!");
09592         } else if ( nz == 1 ) {
09593                 if ( nx < 3 || ny < 3 ) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09594                 e->set_size(3,3,1);
09595                 e->set_value_at(0,0,-1);
09596                 e->set_value_at(1,0,-2);
09597                 e->set_value_at(2,0,-1);
09598 
09599                 e->set_value_at(0,2,1);
09600                 e->set_value_at(1,2,2);
09601                 e->set_value_at(2,2,1);
09602                 Region r = Region(-nx/2+1,-ny/2+1,nx,ny);
09603                 e->clip_inplace(r);
09604         } else {
09605                 if ( nx < 3 || ny < 3 || nz < 3) throw ImageDimensionException("Error - cannot edge detect an image with less than three pixels");
09606                 e->set_size(3,3,3);
09607                 e->set_value_at(0,0,0,-1);
09608                 e->set_value_at(1,0,0,-1);
09609                 e->set_value_at(2,0,0,-1);
09610                 e->set_value_at(0,0,1,-1);
09611                 e->set_value_at(1,0,1,-8);
09612                 e->set_value_at(2,0,1,-1);
09613                 e->set_value_at(0,0,2,-1);
09614                 e->set_value_at(1,0,2,-1);
09615                 e->set_value_at(2,0,2,-1);
09616 
09617                 e->set_value_at(0,2,0,1);
09618                 e->set_value_at(1,2,0,1);
09619                 e->set_value_at(2,2,0,1);
09620                 e->set_value_at(0,2,1,1);
09621                 e->set_value_at(1,2,1,8);
09622                 e->set_value_at(2,2,1,1);
09623                 e->set_value_at(0,2,2,1);
09624                 e->set_value_at(1,2,2,1);
09625                 e->set_value_at(2,2,2,1);
09626 
09627                 Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
09628                 e->clip_inplace(r);
09629         }
09630 
09631         Dict conv_parms;
09632         conv_parms["with"] = e;
09633         image->process_inplace("math.convolution", conv_parms);
09634 
09635         delete e;
09636 }
09637 
09638 
09639 void ZGradientProcessor::process_inplace( EMData* image )
09640 {
09641         if (image->is_complex()) throw ImageFormatException("Cannot edge detect a complex image");
09642 
09643         EMData* e = new EMData();
09644         int nx = image->get_xsize();
09645         int ny = image->get_ysize();
09646         int nz = image->get_zsize();
09647 
09648         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");
09649 
09650         e->set_size(3,3,3);
09651         e->set_value_at(0,0,0,-1);
09652         e->set_value_at(1,0,0,-1);
09653         e->set_value_at(2,0,0,-1);
09654         e->set_value_at(0,1,0,-1);
09655         e->set_value_at(1,1,0,-8);
09656         e->set_value_at(2,1,0,-1);
09657         e->set_value_at(0,2,0,-1);
09658         e->set_value_at(1,2,0,-1);
09659         e->set_value_at(2,2,0,-1);
09660 
09661         e->set_value_at(0,0,2,1);
09662         e->set_value_at(1,0,2,1);
09663         e->set_value_at(2,0,2,1);
09664         e->set_value_at(0,1,2,1);
09665         e->set_value_at(1,1,2,8);
09666         e->set_value_at(2,1,2,1);
09667         e->set_value_at(0,2,2,1);
09668         e->set_value_at(1,2,2,1);
09669         e->set_value_at(2,2,2,1);
09670 
09671         Region r = Region(-nx/2+1,-ny/2+1,-nz/2+1,nx,ny,nz);
09672         e->clip_inplace(r);
09673 
09674         Dict conv_parms;
09675         conv_parms["with"] = e;
09676         image->process_inplace("math.convolution", conv_parms);
09677 
09678         delete e;
09679 }
09680 
09681 void EMAN::dump_processors()
09682 {
09683         dump_factory < Processor > ();
09684 }
09685 
09686 map<string, vector<string> > EMAN::dump_processors_list()
09687 {
09688         return dump_factory_list < Processor > ();
09689 }
09690 
09691 map<string, vector<string> > EMAN::group_processors()
09692 {
09693         map<string, vector<string> > processor_groups;
09694 
09695         vector <string> processornames = Factory<Processor>::get_list();
09696 
09697         for (size_t i = 0; i < processornames.size(); i++) {
09698                 Processor * f = Factory<Processor>::get(processornames[i]);
09699                 if (dynamic_cast<RealPixelProcessor*>(f) != 0) {
09700                         processor_groups["RealPixelProcessor"].push_back(f->get_name());
09701                 }
09702                 else if (dynamic_cast<BoxStatProcessor*>(f)  != 0) {
09703                         processor_groups["BoxStatProcessor"].push_back(f->get_name());
09704                 }
09705                 else if (dynamic_cast<ComplexPixelProcessor*>(f)  != 0) {
09706                         processor_groups["ComplexPixelProcessor"].push_back(f->get_name());
09707                 }
09708                 else if (dynamic_cast<CoordinateProcessor*>(f)  != 0) {
09709                         processor_groups["CoordinateProcessor"].push_back(f->get_name());
09710                 }
09711                 else if (dynamic_cast<FourierProcessor*>(f)  != 0) {
09712                         processor_groups["FourierProcessor"].push_back(f->get_name());
09713                 }
09714                 else if (dynamic_cast<NewFourierProcessor*>(f)  != 0) {
09715                         processor_groups["FourierProcessor"].push_back(f->get_name());
09716                 }
09717                 else if (dynamic_cast<NormalizeProcessor*>(f)  != 0) {
09718                         processor_groups["NormalizeProcessor"].push_back(f->get_name());
09719                 }
09720                 else {
09721                         processor_groups["Others"].push_back(f->get_name());
09722                 }
09723         }
09724 
09725         return processor_groups;
09726 }
09727 
09728 
09729 
09730 /* vim: set ts=4 noet: */
09731 
09732 float ModelHelixProcessor::radprofile(float r, int type)
09733 //Ross Coleman: modified from EMAN1 Cylinder.C by Wen Jiang
09734 {
09735         // r in angstrom
09736         double ret = 0;//iterations ==> rounding is problematic with float types if 15 < r < 20 and really bad if 20 < r < 30
09737         if (type == 0) { // pure Gaussian falloff
09738                 r /= 2;
09739                 ret = exp(-r * r);
09740         } else if (type == 1) { // pure Gaussian falloff + negative dip, so mean is 0
09741                 r /= 2;
09742                 ret = (1 - r * r / 4) * exp(-r * r / 4);
09743         } else if (type == 2) {
09744                 // polynomial fitting to the radial profile of real helix density
09745                 // f=a0*x^n+a1+x^(n-1)+ ... +a[n-1]*x+an
09746                 //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};
09747 
09748                 // now the fitting to the original profile
09749                 if (r >= 12.2)
09750                         return 0; //We don't want that part of the polynomial --> goes way below zero
09751                 static float an[15] = { -3.9185246832229140e-16f,
09752                                 3.3957205298900993e-14f, 2.0343351971222658e-12f,
09753                                 -4.4935965816879751e-10f, 3.0668169835080933e-08f,
09754                                 -1.1904544689091790e-06f, 2.9753088549414953e-05f,
09755                                 -4.9802112876220150e-04f, 5.5900917825309360e-03f,
09756                                 -4.0823714462925299e-02f, 1.8021733669148599e-01f,
09757                                 -4.0992557296268717e-01f, 3.3980328566901458e-01f,
09758                                 -3.6062024812411908e-01f, 1.0000000000000000e+00f };
09759 
09760                 ret = an[0];
09761                 for (int i = 1; i < 15; i++) {
09762                         ret = ret * r + an[i];
09763                 }
09764         }
09765         return (float)ret;
09766 }
09767 
09768 void ModelEMCylinderProcessor::process_inplace(EMData * in)
09769 //Ross Coleman: modified from EMAN1 Cylinder.C by Wen Jiang
09770 {
09771         // synthesize model alpha helix, len is Angstrom, default to 2 turns
09772         //The helical axis is parallel to the z axis.
09773         EMData * cyl = in;
09774         int nx = cyl->get_xsize();
09775         int ny = cyl->get_ysize();
09776         int nz = cyl->get_zsize();
09777 
09778         int type = params.set_default("type", 2);
09779         float len = params.set_default("length", 16.2f); //in angstroms
09780         int x0 = params.set_default("x0", -1); //in voxels -- default value changed a few lines down
09781         int y0 = params.set_default("y0", -1); //in voxels
09782         int z0 = params.set_default("z0", -1); //in voxels
09783         //TODO: check with Matt about default values
09784 
09785         if (x0 < 0 || x0 >= nx)
09786                 x0 = nx / 2;
09787         if (y0 < 0 || y0 >= ny)
09788                 y0 = ny / 2;
09789         if (z0 < 0 || z0 >= nz)
09790                 z0 = nz / 2;
09791 
09792         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
09793         float apix_y = cyl->get_attr("apix_y");
09794         float apix_z = cyl->get_attr("apix_z");
09795 
09796         float * dat = cyl->get_data();
09797         int cyl_voxel_len = (int) (len / apix_z);
09798         int cyl_k_min = z0 - cyl_voxel_len / 2;
09799         int cyl_k_max = z0 + cyl_voxel_len / 2;
09800 
09801         int x, y;
09802         for (int k = 0; k < nz; ++k) {
09803                 for (int j = 0; j < ny; ++j) {
09804                         for (int i = 0; i < nx; ++i, ++dat) {
09805                                 x = i - x0;//coordinate sys centered on cylinder
09806                                 y = j - y0;//coordinate sys centered on cylinder
09807                                 float radius = (float)hypot(x * apix_x, y * apix_y);
09808                                 if ((k > cyl_k_min) && (k < cyl_k_max))
09809                                         *dat += radprofile(radius, type); //pointer arithmetic for array done in loop
09810                                 //else
09811                                         //continue;
09812 
09813                         }
09814                 }
09815         }
09816 }
09817 
09818 void ApplyPolynomialProfileToHelix::process_inplace(EMData * in)
09819 {
09820         EMData * cyl = in;
09821         int nx = cyl->get_xsize();
09822         int ny = cyl->get_ysize();
09823         int nz = cyl->get_zsize();
09824         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
09825         float apix_y = cyl->get_attr("apix_y");
09826         float apix_z = cyl->get_attr("apix_z");
09827         float lengthAngstroms = params["length"];
09828         int z0 = params.set_default("z0", -1); //in voxels
09829 
09830         if (z0 < 0 || z0 >= nz)
09831                 z0 = nz / 2;
09832 
09833         int z_start = Util::round( z0 - 0.5*lengthAngstroms/apix_z );
09834         int z_stop = Util::round( z0 + 0.5*lengthAngstroms/apix_z );
09835 
09836         float * dat = cyl->get_data();
09837         double rho_x_sum, rho_y_sum, rho_sum, x_cm, y_cm, radius;
09838 
09839         for (int k = 0; k < nz; ++k) //taking slices along z axis
09840         {
09841                 rho_x_sum = rho_y_sum = rho_sum = 0; //Set to zero for a new slice
09842 
09843                 if (k >= z_start && k <= z_stop)
09844                 //Apply the radial profile only between z_start and z_stop on the z axis
09845                 {
09846                         //Calculating CM for the slice...
09847                         for (int j = 0; j < ny; ++j)
09848                         {
09849                                 for (int i = 0; i < nx; ++i, ++dat)
09850                                 {
09851                                         rho_x_sum += (*dat)*i;
09852                                         rho_y_sum += (*dat)*j;
09853                                         rho_sum += *dat;
09854                                 }
09855                         }
09856                         if (rho_sum != 0)
09857                         {
09858                                 dat -= nx*ny;//going back to the beginning of the dat array
09859                                 x_cm = rho_x_sum/rho_sum;
09860                                 y_cm = rho_y_sum/rho_sum;
09861 
09862                                 //Applying radial profile...
09863                                 for (int j=0; j<ny;++j)
09864                                 {
09865                                         for (int i=0;i<nx;++i,++dat)
09866                                         {
09867                                                 radius = hypot( (i-x_cm)*apix_x, (j-y_cm)*apix_y );
09868                                                 *dat = radprofile((float)radius, 2);//Type 2 is the polynomial radial profile.
09869                                         }
09870                                 }
09871                         }
09872                 }
09873                 else
09874                 //Clear the map, setting the density to zero everywhere else.
09875                 {
09876                         for (int j=0; j<ny; j++)
09877                                 for(int i=0; i<nx; i++)
09878                                 {
09879                                         *dat = 0;
09880                                         dat++;
09881                                 }
09882                 }
09883 
09884         }
09885 }
09886 
09887 //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!
09888 EMData* BinarySkeletonizerProcessor::process(EMData * image)
09889 {
09890         using namespace wustl_mm::GraySkeletonCPP;
09891         using namespace wustl_mm::SkeletonMaker;
09892 
09893         Volume * vimage = new Volume(image);
09894         float threshold = params["threshold"];
09895         int min_curvew = params.set_default("min_curve_width", 4);
09896         int min_srfcw = params.set_default("min_surface_width", 4);
09897         bool mark_surfaces = params.set_default("mark_surfaces", true);
09898         Volume* vskel = VolumeSkeletonizer::PerformPureJuSkeletonization(vimage, "unused", static_cast<double>(threshold), min_curvew, min_srfcw);
09899         //VolumeSkeletonizer::CleanUpSkeleton(vskel, 4, 0.01f);
09900         if (mark_surfaces) {
09901                 VolumeSkeletonizer::MarkSurfaces(vskel);
09902         }
09903 
09904         vskel->getVolumeData()->owns_emdata = false; //ensure the EMData object will remain when the Volume and its VolumeData object are freed
09905         EMData* skel = vskel->get_emdata();
09906         skel->update();
09907         return skel;
09908 }
09909 
09910 void BinarySkeletonizerProcessor::process_inplace(EMData * image)
09911 {
09912         EMData* em_skel = this->process(image);
09913         //TODO: use memcpy and copy metadata explicitly
09914         *image = *em_skel; //Deep copy performed by EMData::operator=
09915         image->update();
09916         delete em_skel;
09917         em_skel = NULL;
09918         return;
09919 }
09920 
09921 EMData* ConvolutionKernelProcessor::process(const EMData* const image) 
09922 {
09923         if (image->get_zsize()!=1) throw ImageDimensionException("Only 2-D images supported");
09924         
09925         EMData* conv = new EMData(image->get_xsize(),image->get_ysize(),1);
09926         vector<float>kernel = params["kernel"];
09927 
09928         if (fmod(sqrt((float)kernel.size()), 1.0f) != 0) throw InvalidParameterException("Convolution kernel must be square!!");
09929         
09930         float* data = image->get_data();
09931         float* cdata = conv->get_data();        // Yes I could use set_value_at_fast, but is still slower than this....
09932         
09933         //I could do the edges by wrapping around, but this is not necessary(such functionality can be iplemented later)
09934         int ks = int(sqrt(float(kernel.size())));
09935         int n = (ks - 1)/2;
09936         int nx = image->get_xsize();
09937         int ny = image->get_ysize();
09938         for (int i = n; i < (nx - n); i++) {
09939                 for (int j = n; j < (ny - n); j++) {
09940                         //now do the convolution
09941                         float cpixel = 0;
09942                         int idx = 0;
09943                         // Perahps I could use some ofrm of Caching to speed things up?
09944                         for (int cx = -n; cx <= n; cx++) {
09945                                 for (int cy = -n; cy <= n; cy++) {
09946                                         cpixel += data[(i+cx) + (j+cy) * nx]*kernel[idx];
09947                                         idx++;
09948                                 }
09949                         }
09950                         cdata[i + j * nx] = cpixel;
09951                 }
09952         }
09953           
09954         return conv;
09955 }
09956 
09957 void ConvolutionKernelProcessor::process_inplace(EMData * image )
09958 {
09959         throw UnexpectedBehaviorException("Not implemented yet");
09960         
09961         return;
09962 }
09963 
09964 
09965 EMData* RotateInFSProcessor::process(const EMData* const image) // 
09966 {
09967 
09968     EMData* imageCp        = image -> copy(); // This is the rotated image
09969     process_inplace(imageCp);
09970     
09971     return imageCp;
09972 }
09973 
09974 
09975 void RotateInFSProcessor::process_inplace(EMData * image) // right now for 2d images
09976 {
09977 //      float angle = params["angle"];
09978         
09979 
09980 //      Transform *rotNow  = params.set_default("transform",&Transform());
09981         Transform *rotNow  = params["transform"];
09982         float interpCutoff = params.set_default("interpCutoff",0.8f);   // JFF, can you move this to input parameter? 
09983 //      float interpCutoff = params["interpCutoff"];   // JFF, can you move this to input parameter? 
09984 //      float interpCutoff =.8;   // JFF, can you move this to input parameter? 
09985         
09986         
09987         int debug=0;
09988         
09989 //      error: conversion from ‘EMAN::EMObject’ to non-scalar type ‘EMAN::Transform’ requested
09990         
09991         
09992         // if 2N is size of image, then sizes of FFT are (2N+2,2N,2N) or  (2N+2,2N,1)
09993         // if 2N+1 is size of image, then sizes of FFT are (2N+2,2N+1,2N+1) or  (2N+2,2N+1,1)
09994         
09995         int x_size = image->get_xsize();  //16
09996         int y_size = image->get_ysize();  int y_odd=  (y_size%2);
09997         int z_size = image->get_zsize();
09998         
09999 //      float size_check = abs(y_size-z_size)+abs(x_size-y_size-2+y_odd);
10000 //      if (size_check!=0) throw ImageDimensionException("Only cubic images");
10001         int size_check = abs(x_size-y_size-2+y_odd)+ abs(z_size-1)*abs(z_size-y_size);
10002         int N = x_size/2-1;
10003         int Mid = N+1;
10004         if (size_check!=0) throw ImageDimensionException("Only square or cubic  images for now");
10005         if (image->is_real()) throw ImageDimensionException("Only for Fourier images");
10006 //      if (y_odd==0) throw ImageDimensionException("Only use odd images for now");
10007         
10008         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 );
10009         
10010         EMData* RotIm        = image -> copy(); // This is the rotated image
10011         EMData* WeightIm     = image -> copy(); WeightIm     ->to_zero();// This is the Weight image for rotated image
10012         EMData* PhaseOrigIm  = new EMData(N+1,2*N+1,z_size) ; PhaseOrigIm  ->to_zero();// This is the Weight image for rotated image
10013         EMData* PhaseFinalIm = PhaseOrigIm -> copy(); PhaseFinalIm ->to_zero();// This is the Weight image for rotated image
10014         EMData* MagFinalIm   = PhaseOrigIm -> copy(); MagFinalIm   ->to_zero();// This is the Weight image for rotated image
10015         
10016 //      float*   data      = image    -> get_data();
10017 //      float* Rotdata     = RotIm    -> get_data();  // This is the data of the rotated image
10018 //      float* WeightData  = WeightIm -> get_data();  //
10019         
10020         float  WeightNowX, WeightNowY, WeightNowZ ;
10021         int    kxMin,kxMax, kyMin, kyMax,  kzMin, kzMax, kxBefore, kyBefore, kzBefore ;
10022         float  kxRT, kyRT, kzRT ;
10023         
10024         Vec3f PosAfter;
10025         Vec3f PosBefore;
10026         Transform invRotNow;
10027         // Fill out real and imaginary full images
10028 
10029         //int kz=0;
10030 
10031         if (debug) {image -> write_image("OrigImageFFT.hdf");   
10032                     printf("Just wrote OrigImageFFT.hdf \n"); }
10033         
10034 
10035         for (kxBefore = 0; kxBefore <=  N      ; ++kxBefore) {  // These are the  kx, ky coordinates of the original image
10036            for (kyBefore = 0; kyBefore < y_size ; ++kyBefore)  {         //  We need to rephase
10037               for (kzBefore = 0; kzBefore < z_size ; ++kzBefore)  {         //  We need to rephase
10038 
10039             // Now we need a 
10040               float CurrentReal = RotIm -> get_value_at(2*kxBefore  ,kyBefore, kzBefore);
10041               float CurrentImag = RotIm -> get_value_at(2*kxBefore+1,kyBefore, kzBefore);
10042               
10043 //         fftOfxPRB3(1+mod(ik-Mid,N))=Grand*exp(-2*pi*1i*Mid*(ik-Mid)/x_size); % Phase to apply to centered version
10044               
10045 //            float Phase    = -2*pi*(kxBefore+kyBefore + kzBefore)*(Mid)/y_size;
10046               float Phase    = -pi*(kxBefore+kyBefore + kzBefore)*x_size/y_size;
10047               // Phase    = 0;
10048               float CosPhase = cos( Phase);
10049               float SinPhase = sin( Phase);
10050              
10051               float NewRealValue = CosPhase*CurrentReal -SinPhase*CurrentImag;
10052               float NewImagValue = SinPhase*CurrentReal +CosPhase*CurrentImag;
10053               
10054               RotIm ->set_value_at(2*kxBefore  ,kyBefore, kzBefore, NewRealValue);
10055               RotIm ->set_value_at(2*kxBefore+1,kyBefore, kzBefore, NewImagValue);
10056         }}}
10057         
10058         if (debug) {RotIm  -> write_image("OrigImageFFTAfterPhaseCorrection.hdf"); 
10059                     printf("  Just wrote OrigImageFFTAfterPhaseCorrection.hdf \n");}
10060         
10061         // RotIm ->set_value_at(2*Mid-1,0, 0, 0);
10062         if (debug) printf("  Just about to start second loop  \n");
10063         
10064         image ->to_zero();
10065         invRotNow = rotNow ->inverse(); //  no match for ‘operator=’ in ‘PosBefore = EMAN::operator*(const EMAN::Transform&, const EMAN::Transform&)((
10066          
10067         
10068         for (int kxAfter = 0; kxAfter <= N  ; ++kxAfter) {  // These are the  kx, ky, kz coordinates of the rotated image
10069           for (int kyAfter = -N; kyAfter < y_size-N     ; ++kyAfter)  {     // referring to a properly centered version
10070              for (int kzAfter = -z_size/2; kzAfter <= z_size/2  ; ++kzAfter)  {   
10071 
10072             // Now we need a 
10073 
10074               PosAfter = Vec3f(kxAfter, kyAfter, kzAfter);
10075               PosBefore = invRotNow*PosAfter;
10076               kxRT = PosBefore[0]; // This will be the off-lattice site, where the point was rotated from
10077               kyRT = PosBefore[1]; //  
10078               kzRT = PosBefore[2]; //  
10079               
10080               
10081               kxMin = ceil( kxRT-interpCutoff); kxMax = floor(kxRT+interpCutoff);
10082               kyMin = ceil( kyRT-interpCutoff); kyMax = floor(kyRT+interpCutoff);
10083               kzMin = ceil( kzRT-interpCutoff); kzMax = floor(kzRT+interpCutoff);
10084 
10085     
10086 //              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); 
10087               //continue; 
10088               for (int kxI= kxMin; kxI <= kxMax; ++kxI){  // go through this
10089                 for (int kyI= kyMin; kyI <= kyMax; ++kyI){  // and get values to interp
10090                    for (int kzI= kzMin; kzI <= kzMax; ++kzI){ //  
10091 
10092 // 
10093                      if (abs(kxI) >N) continue; // don't go off the lattice
10094                      if (abs(kyI) >N) continue;
10095                      if (abs(kzI) >z_size/2) continue;
10096                      
10097                      float distx= abs(kxI-kxRT);
10098                      float disty= abs(kyI-kyRT);
10099                      float distz= abs(kzI-kzRT);
10100 
10101                      // fold kxI, kyI back into lattice if possible
10102                      int IsComplexConj= 1;
10103                      
10104                      if (kxI<0) IsComplexConj=-1;
10105                      kxBefore= IsComplexConj*kxI; // The Proper coordinates will be
10106                      kyBefore= IsComplexConj*kyI; // where the original data is stored 
10107                      kzBefore= IsComplexConj*kzI; // At this point kxBefore >=0, but not necessarily kyBefore
10108                      
10109                      if ( kyBefore<0 ) kyBefore += y_size; // makes sure kyBefore is also >0
10110                      if ( kzBefore<0 ) kzBefore += y_size; // makes sure kzBefore is also >0
10111                      
10112                      WeightNowX  = (distx ==0)? 1: (sin(pi*distx) /(pi*distx)) ;
10113                      WeightNowY  = (disty ==0)? 1: (sin(pi*disty) /(pi*disty)) ;
10114                      WeightNowZ  = (distz ==0)? 1: (sin(pi*distz) /(pi*distz)) ;
10115                      
10116                      
10117                      float CurrentValue;
10118                      float ToAdd;
10119                      int kyAfterInd = (kyAfter+y_size)%(y_size);
10120                      int kzAfterInd = (kzAfter+z_size)%(z_size);
10121                      
10122                     // if (kxAfter==0) IsComplexConj*=-1;
10123                      
10124 //                   if ((kxI+kyI)%1 ==0)
10125 //                       printf("Block5,kx=%d, ky=%d,kxI=%d, kyI=%d, kxBefore=%d, kyBefore=%d  \n",kxAfter,kyAfter,kxI,kyI, kxBefore,kyBefore);
10126 //                       printf("  %d,     %d,  %d,  %d,        %d,  %d,       %d, %d \n",IsComplexConj,kxAfter,kyAfter, kyAfterInd,kxI,kyI, kxBefore,kyBefore);
10127                      
10128                      CurrentValue =   image -> get_value_at(2*kxAfter,kyAfterInd, kzAfterInd);  // Update real part of Image
10129                      ToAdd =   WeightNowX*WeightNowY*WeightNowZ*(RotIm -> get_value_at(2*kxBefore,kyBefore, kzBefore));
10130                      image -> set_value_at(2*kxAfter  ,kyAfterInd  , kzAfterInd,  ToAdd   + CurrentValue );
10131                      
10132                      
10133                      CurrentValue =   WeightIm -> get_value_at(kxAfter,kyAfterInd, kzAfterInd);    // Update real  part of Weight image
10134                      ToAdd =   WeightNowX*WeightNowY;
10135                      WeightIm -> set_value_at(kxAfter  , kyAfterInd , kzAfterInd,  abs(ToAdd)   + CurrentValue );
10136                      
10137                      CurrentValue = image -> get_value_at(2*kxAfter+1,kyAfterInd);    // Update imaginary   part of image
10138                      ToAdd =   IsComplexConj*WeightNowX*WeightNowY*RotIm -> get_value_at(2*kxBefore+1,kyBefore, kzBefore );
10139                      image -> set_value_at(2*kxAfter+1  , kyAfterInd , kzAfterInd,  ToAdd   + CurrentValue );
10140                      
10141                       
10142                 }}}
10143 
10144             
10145           }}}
10146 
10147 //        Set the image values to the rotated image, because we do it in place
10148 
10149 
10150         if (debug) { image        -> write_image("RotImageBeforeFinalPhaseCorrection.hdf"); 
10151                      printf("  Just wrote RotImageBeforeFinalPhaseCorrection.hdf \n");   }
10152 
10153 
10154         for (kxBefore = 0; kxBefore <= N     ; ++kxBefore) {      // This is  the normalization step
10155           for (kyBefore = 0; kyBefore < y_size   ; ++kyBefore)  {  // These are the  kx, ky, kz coordinates of the original image       
10156               for (kzBefore = 0; kzBefore < z_size   ; ++kzBefore)  {       
10157 
10158               float CurrentReal = image -> get_value_at(2*kxBefore   , kyBefore, kzBefore);
10159               float CurrentImag = image -> get_value_at(2*kxBefore+1 , kyBefore, kzBefore);
10160               
10161               PhaseFinalIm -> set_value_at(kxBefore,kyBefore, kzBefore, atan2(CurrentImag,CurrentReal));
10162               MagFinalIm   -> set_value_at(kxBefore,kyBefore, kzBefore, sqrt(CurrentImag*CurrentImag+CurrentReal*CurrentReal) );
10163               float WeightNow    = WeightIm -> get_value_at(kxBefore,kyBefore, kzBefore);
10164               if (WeightNow>0) {
10165                  float val =  (image->get_value_at(2*kxBefore   , kyBefore, kzBefore))/WeightNow;
10166                  image -> set_value_at(2*kxBefore   , kyBefore, kzBefore, val);
10167                  val      =  (image->get_value_at(2*kxBefore +1  , kyBefore, kzBefore))/WeightNow;
10168                  image -> set_value_at(2*kxBefore +1  , kyBefore, kzBefore,  val);
10169               }
10170         
10171         }}}
10172         
10173         if (debug) { printf("  Just did normalization step \n");}
10174         
10175 
10176         for ( kxBefore = 0; kxBefore < Mid     ; ++kxBefore) {     //  This is the rephase step
10177           for ( kyBefore = 0; kyBefore < y_size   ; ++kyBefore)  {     
10178             for ( kzBefore = 0; kzBefore < z_size   ; ++kzBefore)  {     
10179 
10180               float CurrentReal = image -> get_value_at(2*kxBefore  ,kyBefore, kzBefore);
10181               float CurrentImag = image -> get_value_at(2*kxBefore+1,kyBefore, kzBefore);
10182               
10183 //            float Phase    = +2*pi*(kxBefore+kyBefore+kzBefore)*(Mid)/y_size;
10184               float Phase    =  pi*(kxBefore + kyBefore + kzBefore)*x_size/y_size;
10185               // Phase    = 0; // Offset should be Mid-1
10186               float CosPhase = cos( Phase);
10187               float SinPhase = sin( Phase);
10188              
10189               float NewRealValue = CosPhase*CurrentReal -SinPhase*CurrentImag;
10190               float NewImagValue = SinPhase*CurrentReal +CosPhase*CurrentImag;
10191               
10192               image ->set_value_at(2*kxBefore,  kyBefore,  kzBefore, NewRealValue);
10193               image ->set_value_at(2*kxBefore+1,kyBefore,  kzBefore, NewImagValue);
10194         }}}
10195         
10196         if (debug) {
10197            image        -> write_image("RotatedImageFFT.hdf");
10198            PhaseFinalIm -> write_image("PhaseImInFS.hdf");   // These are the phases,mags of the image when properly centered
10199            MagFinalIm   -> write_image("MagFinalImInFS.hdf"); 
10200            WeightIm     -> write_image("WeightIm.hdf");
10201            printf("  Just wrote RotatedImageFFT.hdf \n");
10202         }
10203 
10204         image -> update();
10205         
10206 }
10207 
10208 
10209 #ifdef SPARX_USING_CUDA
10210 
10211 /* CLASS MPICUDA_kmeans processor
10212  *
10213  */
10214 #include "sparx/cuda/cuda_mpi_kmeans.h"
10215 MPICUDA_kmeans::MPICUDA_kmeans() {
10216     h_IM = NULL;
10217     h_AVE = NULL;
10218     h_ASG = NULL;
10219     h_dist = NULL;
10220     h_AVE2 = NULL;
10221     h_im2 = NULL;
10222     h_NC = NULL;
10223     params = NULL;
10224     d_im = NULL;
10225     d_AVE = NULL;
10226     d_dist = NULL;
10227 }
10228 
10229 MPICUDA_kmeans::~MPICUDA_kmeans() {
10230     if (h_IM) delete h_IM;
10231     if (h_ASG) delete h_ASG;
10232     if (h_AVE) delete h_AVE;
10233     if (h_dist) delete h_dist;
10234     if (h_AVE2) delete h_AVE2;
10235     if (h_im2) delete h_im2;
10236     if (h_NC) delete h_NC;
10237     if (params) delete params;
10238 }
10239 
10240 #include "sparx/cuda/cuda_mpi_kmeans.h"
10241 int MPICUDA_kmeans::setup(int extm, int extN, int extn, int extK, int extn_start) {
10242     m = extm;                           // number of pixels per image
10243     N = extN;                           // Total number of images
10244     n = extn;                           // Number of images used locally
10245     K = extK;                           // number of classes
10246     n_start = extn_start;               // Starting point to local images
10247     size_IM = m * N;                    // nb elements in IM
10248     size_im = m * n;                    // nb elements in im
10249     size_AVE = m * K;                   // nb elements in ave
10250     size_dist = n * K;                  // nb elements in dist
10251     ite = 0;                            // init nb of iterations
10252     BLOCK_SIZE = 512;
10253     NB = size_dist / BLOCK_SIZE;
10254     ins_BLOCK = NB * BLOCK_SIZE;
10255     // Host memory allocation for images
10256     h_IM = (float*)malloc(size_IM * sizeof(float));
10257     if (h_IM == 0) return 1;
10258     h_im = &h_IM[n_start * m]; // for local images
10259     // Host memory allocation for the averages
10260     h_AVE = (float*)malloc(size_AVE * sizeof(float));
10261     if (h_AVE == 0) return 1;
10262     // Host memory allocation for all assignment
10263     h_ASG = (unsigned short int*)malloc(N * sizeof(unsigned short int));
10264     if (h_ASG == 0) return 1;
10265     h_asg = &h_ASG[n_start]; // for local assignment
10266     // allocate the memory for the sum squared of averages
10267     h_AVE2 = (float*)malloc(K * sizeof(float));
10268     if (h_AVE2 == 0) return 1;
10269     // allocate the memory for the sum squared of images
10270     h_im2 = (float*)malloc(n * sizeof(float));
10271     if (h_im2 == 0) return 1;
10272     // allocate the memory for the distances
10273     h_dist = (float*)malloc(size_dist * sizeof(float));
10274     if (h_dist == 0) return 1;
10275     // allocate the memory for the number of images per class
10276     h_NC = (unsigned int*)malloc(K * sizeof(unsigned int));
10277     if (h_NC == 0) return 1;
10278     // allocate the memory to parameters
10279     params = (int*)malloc(8 * sizeof(int));
10280     if (params == 0) return 1;
10281     params[0] = n;
10282     params[1] = m;
10283     params[2] = K;
10284     params[3] = 0;          // Reserve for flag_stop_iteration
10285     params[4] = 0;          // Reserve for ct_im_mv (debug)
10286     params[5] = BLOCK_SIZE; // Size of threads block (512)
10287     params[6] = NB;         // Number of blocks which fit with BLOCK_SIZE
10288     params[7] = ins_BLOCK;  // Number of blocks remaining
10289     
10290 
10291     return 0;
10292 }
10293 
10294 // add image pre-process by Util.compress_image_mask
10295 void MPICUDA_kmeans::append_flat_image(EMData* im, int pos) {
10296    
10297     for (int i = 0; i < m ; ++i) h_IM[pos * m + i] = (*im)(i);
10298     
10299 }
10300 
10301 // cuda init mem device, cublas (get device ptr)
10302 int MPICUDA_kmeans::init_mem(int numdev) {
10303     int stat = 1;
10304     float** hd_AVE = NULL;
10305     float** hd_im = NULL;
10306     float** hd_dist = NULL;
10307     hd_AVE = &d_AVE;
10308     hd_im = &d_im;
10309     hd_dist = &d_dist;
10310     stat = cuda_mpi_init(h_im, hd_im, hd_AVE, hd_dist, size_im, size_AVE, size_dist, numdev);
10311     //printf("C++ get this pointer for d_AVE: %p\n", d_AVE);
10312     //printf("C++ get this pointer for d_im: %p\n", d_im);
10313     //printf("C++ get this pointer for d_dist: %p\n", d_dist);
10314     return stat;
10315 }
10316 
10317 // precalculate im2
10318 void MPICUDA_kmeans::compute_im2() {
10319     for (int i = 0; i < n; i++) {
10320         h_im2[i] = 0.0f;
10321         for (int j = 0; j < m; j++) h_im2[i] += (h_im[i * m + j] * h_im[i * m + j]);
10322     }
10323 }
10324 
10325 // init randomly the first assignment
10326 int MPICUDA_kmeans::random_ASG(long int rnd) {
10327     srand(rnd);
10328     int ret = 20;
10329     int flag = 0;
10330     int i, k;
10331     std::cout<<"111111111  number of image==="<<N<<"number cluster=="<<K<<"img size"<<m<<std::endl;
10332     for (k = 0; k < K; k++) h_NC[k] = 0;
10333     while (ret > 0) {
10334         ret--;
10335         for (i = 0; i < N; i++) {
10336             h_ASG[i] = rand() % K;
10337             h_NC[h_ASG[i]]++;
10338         }
10339         flag = 1;
10340         k = K;
10341         while (k > 0 && flag) {
10342             k--;
10343             if (h_NC[k] <= 1) {
10344                 flag = 0;
10345                 if (ret == 0) {
10346                     //printf("Erreur randomize assignment\n");
10347                     return -1;
10348                 }
10349                 for (k = 0; k < K; k++) h_NC[k] = 0;
10350             }
10351         if (flag == 1) ret = 0;
10352         }
10353     }
10354    
10355     return 0;
10356 }
10357 
10358 // get back the assignment
10359 vector <int> MPICUDA_kmeans::get_ASG() {
10360     vector <int> ASG(h_ASG, &h_ASG[N]);
10361     return ASG;
10362 }
10363 
10364 // get back the global assignment
10365 vector <int> MPICUDA_kmeans::get_asg() {
10366     vector <int> asg(h_asg, &h_asg[n]);
10367     return asg;
10368 }
10369 
10370 // compute NC from ASG
10371 void MPICUDA_kmeans::compute_NC() {
10372     for (int i = 0; i < K; ++i) h_NC[i] = 0;
10373     for (int i = 0; i < N; ++i) h_NC[h_ASG[i]]++;
10374 }
10375 
10376 // get NC
10377 vector <int> MPICUDA_kmeans::get_NC() {
10378     vector <int> NC(h_NC, &h_NC[K]);
10379     return NC;
10380 }
10381 
10382 // set a new global assignment
10383 void MPICUDA_kmeans::set_ASG(const vector <int>& ASG) {
10384     for (int i = 0; i < N ; ++i) h_ASG[i] = ASG[i];
10385 }
10386 
10387 // set number of objects per group
10388 void MPICUDA_kmeans::set_NC(const vector <int>& NC) {
10389     for (int i = 0; i < K; ++i) h_NC[i] = NC[i];
10390 }
10391 
10392 // get back some information (ite and T0)
10393 int MPICUDA_kmeans::get_ct_im_mv() {
10394     return params[4]; // ct_im_mov
10395 }
10396 
10397 // set the value of T
10398 void MPICUDA_kmeans::set_T(float extT) {
10399     T = extT;
10400 }
10401 
10402 // get the T value
10403 float MPICUDA_kmeans::get_T() {
10404     return T;
10405 }
10406 
10407 // compute ave and ave2
10408 void MPICUDA_kmeans::compute_AVE() {
10409     float buf = 0.0f;
10410     int i, j, c, d, ind;
10411     // compute the averages according ASG
10412     for (i = 0; i < size_AVE; ++i) h_AVE[i] = 0.0f;                          // set averages to zero
10413     for (i = 0; i < N; ++i) {
10414         c = h_ASG[i] * m;
10415         d = i * m;
10416         for (j = 0; j < m; ++j) h_AVE[c + j] += h_IM[d + j];                 // accumulate images
10417     }
10418     for (i = 0; i < K; i++) {
10419         buf = 0.0f;
10420         for (j = 0 ; j < m; j++) {
10421             ind = i * m + j;
10422             h_AVE[ind] /= (float)h_NC[i];                                    // compute average
10423             buf += (h_AVE[ind] * h_AVE[ind]);                                // do sum squared AVE
10424         }
10425         h_AVE2[i] = buf;
10426     }
10427     
10428     /*for (i = 0; i < K; i++) {
10429         std::cout<<"average image"<<std::endl;
10430         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;
10431     }*/
10432   
10433 }
10434 
10435 // set averages
10436 void MPICUDA_kmeans::set_AVE(EMData* im, int pos) {
10437     for (int i = 0; i < m ; ++i) h_AVE[pos * m + i] = (*im)(i);
10438 }
10439 
10440 // get back the averages
10441 vector<EMData*> MPICUDA_kmeans::get_AVE() {
10442     vector<EMData*> ave(K);
10443     for (int k = 0; k < K; ++k) {
10444         EMData* im = new EMData();
10445         im->set_size(m, 1, 1);
10446         float *ptr = im->get_data();
10447         for (int i = 0; i < m; ++i) {ptr[i] =  h_AVE[k * m + i];}
10448         ave[k] = im->copy();
10449         delete im;
10450     }
10451     return ave;
10452 }
10453 
10454 // k-means one iteration
10455 int MPICUDA_kmeans::one_iter() {
10456     int status = cuda_mpi_kmeans(h_AVE, d_AVE, h_dist, d_dist, d_im, h_im2, h_AVE2, h_asg, h_NC, params);
10457     ite++;
10458     return status;
10459 }
10460 // k-means SSE one iteration help function
10461 /*int MPICUDA_kmeans::init_dist() {
10462    
10463     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);
10464    
10465     return status;
10466 }*/
10467 
10468 /*int MPICUDA_kmeans::AVE_to_host() {
10469    
10470     int status = cuda_mpi_kmeans_copy_ave_from_device(h_AVE, d_AVE, params);
10471    
10472     return status;
10473 }*/
10474 
10475 
10476 int one_iter_SA();
10477 // k-means SSE one iteration
10478 /*int MPICUDA_kmeans::one_iter_SSE() {
10479     //if ( ite == 0)
10480     
10481     if( ite ==0) {
10482          int status_init=init_dist();
10483          ttt = compute_tt();//int status = 0;
10484          printf("intial energy ===%f\n",ttt);
10485     }
10486     //std::cout<<bb<<BB<<std::endl;
10487     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);
10488     
10489     //float t = compute_tt();//int status = 0;
10490     //std::cout<<"engery at iteration"<<ite<<"==="<<t<<std::endl;
10491  
10492     ite++;
10493     return status;
10494 }*/
10495 // k-means SA one iteration
10496 int MPICUDA_kmeans::one_iter_SA() {
10497     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);
10498     ite++;
10499     return status;
10500 }
10501 
10502 // compute ji
10503 vector <float> MPICUDA_kmeans::compute_ji() {
10504     int status = cuda_mpi_dist(h_AVE, d_AVE, h_dist, d_dist, d_im, n, K, m);
10505     vector <float> ji(K);
10506     int i;
10507     if (status != 0) {
10508         for (i = 0; i < K; ++i) ji[i] = -1.0;
10509         return ji;
10510     }
10511     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]]);
10512     return ji;
10513 }
10514 
10515 
10516 float MPICUDA_kmeans::compute_tt() {
10517     /*int status = cuda_mpi_dist(h_AVE, d_AVE, h_dist, d_dist, d_im, n, K, m);
10518     vector <float> ji(K);
10519     int i;
10520     if (status != 0) {
10521         for (i = 0; i < K; ++i) ji[i] = -1.0;
10522         return -11111111;
10523     }
10524     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]]);
10525    float t =0.0; 
10526    for (i =0; i<K;i++)
10527        t +=ji[i];
10528     return t;*/
10529     
10530            
10531     vector <float> ji(K);
10532     int i,j;
10533     float dist, temp;
10534     for (i = 0; i < n; ++i) 
10535     {
10536         dist =0;
10537         for ( j=0; j<m; j++)     {
10538             temp = (h_im[i*m+j] -h_AVE[ h_asg[i]*m+j]);
10539             dist = dist + temp*temp;
10540          }
10541         ji[h_asg[i]] = ji[h_asg[i]]+ dist;
10542    }
10543         
10544    float t =0.0; 
10545    for (i =0; i<K;i++)
10546        t +=ji[i];
10547     return t;
10548 }
10549 
10550 
10551 //
10552 vector <float> MPICUDA_kmeans::compute_criterion(const vector <float>& Ji) {
10553     float buf = 0.0f;
10554     float Je = 0.0f;
10555     float Tr_AVE = 0.0f;
10556     float v_max = 0.0f;
10557     float* S_AVE2 = (float*)calloc(m, sizeof(float));
10558     float* S_AVE = (float*)calloc(m, sizeof(float));
10559     vector <float> crit(4);
10560     int i, j, k;
10561     // Je
10562     for (i = 0; i < K; ++i) Je += (Ji[i] / float(m));
10563     crit[0] = Je;
10564     // trace ave
10565     for (i = 0; i < K; ++i) {
10566         for (j = 0; j < m; ++j) {
10567             S_AVE[j] += h_AVE[i * m + j];
10568             S_AVE2[j] += (h_AVE[i * m + j] * h_AVE[i * m +j]);
10569         }
10570     }
10571     buf = 1 / (float)K;
10572     for (i = 0; i < m; ++i) Tr_AVE += (buf * (S_AVE2[i] - buf * S_AVE[i] * S_AVE[i]));
10573     // Coleman
10574     crit[1] = Tr_AVE * Je;
10575     // Harabasz
10576     crit[2] = (Tr_AVE * (float)(N - K)) / (Je * (float)(K - 1));
10577     // Davies-Bouldin
10578     for (i = 0; i < K; ++i) {
10579         v_max = 0.0f;
10580         for (j = 0; j < K; ++j) {
10581             if (j != i) {
10582                 buf = 0.0f;
10583                 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]));
10584                 buf = (Ji[i] / (float)h_NC[i] + Ji[j] / (float)h_NC[j]) * ((float)m / buf);
10585             }
10586             if (buf > v_max) v_max = buf;
10587         }
10588         crit[3] += v_max;
10589     }
10590     crit[3] /= (float)K;
10591     free(S_AVE);
10592     free(S_AVE2);
10593     return crit;
10594 }
10595 
10596 // shutdown cublas and release device mem
10597 int MPICUDA_kmeans::shutdown() {
10598     return cuda_mpi_shutdown(d_im, d_AVE, d_dist);
10599 }
10601 
10602 #endif //SPARX_USING_CUDA
10603 
10604 

Generated on Thu May 3 10:06:27 2012 for EMAN2 by  doxygen 1.4.7